mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2024-11-10 06:31:48 +00:00
unified the command history logic
when a command is the same as the previous one, it doesn't get saved Linux tty keys support: left, right, home, end, delete
This commit is contained in:
parent
b8b064fc53
commit
8b5728559b
7 changed files with 253 additions and 188 deletions
|
@ -280,8 +280,6 @@ static void Con_ResizeFont()
|
|||
|
||||
void CL_ConInit()
|
||||
{
|
||||
int i;
|
||||
|
||||
con_noprint = Cvar_Get( "con_noprint", "0", 0 );
|
||||
con_notifytime = Cvar_Get( "con_notifytime", "3", CVAR_ARCHIVE );
|
||||
con_scale = Cvar_Get( "con_scale", "1", CVAR_ARCHIVE );
|
||||
|
@ -290,10 +288,7 @@ void CL_ConInit()
|
|||
|
||||
Field_Clear( &g_consoleField );
|
||||
g_consoleField.widthInChars = g_console_field_width;
|
||||
for ( i = 0 ; i < COMMAND_HISTORY ; i++ ) {
|
||||
Field_Clear( &historyEditLines[i] );
|
||||
historyEditLines[i].widthInChars = g_console_field_width;
|
||||
}
|
||||
History_Clear( &g_history, g_console_field_width );
|
||||
Con_ClearNotify();
|
||||
|
||||
CL_LoadCommandHistory();
|
||||
|
|
|
@ -27,23 +27,16 @@ key up events are sent even if in console mode
|
|||
|
||||
*/
|
||||
|
||||
field_t historyEditLines[COMMAND_HISTORY];
|
||||
|
||||
int nextHistoryLine; // the last line in the history buffer, not masked
|
||||
int historyLine; // the line being displayed from history buffer
|
||||
// will be <= nextHistoryLine
|
||||
|
||||
history_t g_history;
|
||||
field_t g_consoleField;
|
||||
field_t chatField;
|
||||
qbool chat_team;
|
||||
|
||||
qbool chat_team;
|
||||
int chat_playerNum;
|
||||
int anykeydown;
|
||||
|
||||
|
||||
static qbool key_overstrikeMode;
|
||||
|
||||
int anykeydown;
|
||||
|
||||
|
||||
typedef struct {
|
||||
qbool down;
|
||||
|
@ -476,10 +469,7 @@ static void Console_Key( int key )
|
|||
}
|
||||
}
|
||||
|
||||
// copy line to history buffer
|
||||
historyEditLines[nextHistoryLine % COMMAND_HISTORY] = g_consoleField;
|
||||
nextHistoryLine++;
|
||||
historyLine = nextHistoryLine;
|
||||
History_SaveCommand( &g_history, &g_consoleField );
|
||||
|
||||
Field_Clear( &g_consoleField );
|
||||
g_consoleField.widthInChars = g_console_field_width;
|
||||
|
@ -502,24 +492,13 @@ static void Console_Key( int key )
|
|||
|
||||
if ( ( key == K_UPARROW ) ||
|
||||
( ( tolower(key) == 'p' ) && keys[K_CTRL].down ) ) {
|
||||
if ( nextHistoryLine - historyLine < COMMAND_HISTORY
|
||||
&& historyLine > 0 ) {
|
||||
historyLine--;
|
||||
}
|
||||
g_consoleField = historyEditLines[ historyLine % COMMAND_HISTORY ];
|
||||
History_GetPreviousCommand( &g_consoleField, &g_history );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ( key == K_DOWNARROW ) ||
|
||||
( ( tolower(key) == 'n' ) && keys[K_CTRL].down ) ) {
|
||||
historyLine++;
|
||||
if (historyLine >= nextHistoryLine) {
|
||||
historyLine = nextHistoryLine;
|
||||
Field_Clear( &g_consoleField );
|
||||
g_consoleField.widthInChars = g_console_field_width;
|
||||
return;
|
||||
}
|
||||
g_consoleField = historyEditLines[ historyLine % COMMAND_HISTORY ];
|
||||
History_GetNextCommand( &g_consoleField, &g_history, g_console_field_width );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1177,19 +1156,19 @@ void CL_LoadCommandHistory()
|
|||
for ( int i = 0; i < count; ++i ) {
|
||||
const int l = lengths[i];
|
||||
if ( l <= 0 ||
|
||||
FS_Read( historyEditLines[i].buffer, l, f ) != l ) {
|
||||
FS_Read( g_history.commands[i].buffer, l, f ) != l ) {
|
||||
FS_FCloseFile( f );
|
||||
return;
|
||||
}
|
||||
historyEditLines[i].buffer[l] = '\0';
|
||||
historyEditLines[i].cursor = l;
|
||||
g_history.commands[i].buffer[l] = '\0';
|
||||
g_history.commands[i].cursor = l;
|
||||
}
|
||||
|
||||
nextHistoryLine = count;
|
||||
historyLine = count;
|
||||
const int totalCount = ARRAY_LEN( historyEditLines );
|
||||
g_history.next = count;
|
||||
g_history.display = count;
|
||||
const int totalCount = ARRAY_LEN( g_history.commands );
|
||||
for ( int i = count; i < totalCount; ++i ) {
|
||||
historyEditLines[i].buffer[0] = '\0';
|
||||
g_history.commands[i].buffer[0] = '\0';
|
||||
}
|
||||
|
||||
FS_FCloseFile(f);
|
||||
|
@ -1207,9 +1186,9 @@ void CL_SaveCommandHistory()
|
|||
|
||||
int count = 0;
|
||||
int lengths[COMMAND_HISTORY];
|
||||
const int totalCount = ARRAY_LEN( historyEditLines );
|
||||
const int totalCount = ARRAY_LEN( g_history.commands );
|
||||
for ( int i = 0; i < totalCount; ++i ) {
|
||||
const char* const s = historyEditLines[(historyLine + i) % COMMAND_HISTORY].buffer;
|
||||
const char* const s = g_history.commands[(g_history.display + i) % COMMAND_HISTORY].buffer;
|
||||
if ( *s == '\0' )
|
||||
continue;
|
||||
|
||||
|
@ -1219,7 +1198,7 @@ void CL_SaveCommandHistory()
|
|||
FS_Write( &count, sizeof(count), f );
|
||||
FS_Write( lengths, sizeof(int) * count, f );
|
||||
for ( int i = 0, j = 0; i < totalCount; ++i ) {
|
||||
const char* const s = historyEditLines[(historyLine + i) % COMMAND_HISTORY].buffer;
|
||||
const char* const s = g_history.commands[(g_history.display + i) % COMMAND_HISTORY].buffer;
|
||||
if ( *s == '\0' )
|
||||
continue;
|
||||
|
||||
|
|
|
@ -24,13 +24,11 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
|
||||
void Field_Draw( field_t* edit, int x, int y, int cw, int ch );
|
||||
|
||||
#define COMMAND_HISTORY 32
|
||||
extern field_t historyEditLines[COMMAND_HISTORY];
|
||||
|
||||
extern field_t g_consoleField;
|
||||
extern field_t chatField;
|
||||
extern int anykeydown;
|
||||
extern qbool chat_team;
|
||||
extern history_t g_history;
|
||||
extern field_t g_consoleField;
|
||||
extern field_t chatField;
|
||||
extern int anykeydown;
|
||||
extern qbool chat_team;
|
||||
extern int chat_playerNum;
|
||||
|
||||
void Key_WriteBindings( fileHandle_t f );
|
||||
|
|
|
@ -2929,6 +2929,75 @@ void Field_AutoCompleteKeyName( int startArg, int compArg )
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
void History_Clear( history_t* history, int width )
|
||||
{
|
||||
for ( int i = 0; i < COMMAND_HISTORY; ++i ) {
|
||||
Field_Clear( &history->commands[i] );
|
||||
history->commands[i].widthInChars = width;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int LengthWithoutTrailingWhitespace( const char* s )
|
||||
{
|
||||
int i = (int)strlen(s);
|
||||
while ( i-- ) {
|
||||
if ( s[i] != ' ' && s[i] != '\t' )
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void History_SaveCommand( history_t* history, const field_t* edit )
|
||||
{
|
||||
// Avoid having the same command twice in a row.
|
||||
// Unfortunately, this has to be case sensitive since case might matter for some commands.
|
||||
if ( history->next > 0 ) {
|
||||
// The real proper way to ignore whitespace is to tokenize both strings and compare the
|
||||
// argument count and then each argument with a case sensitive comparison,
|
||||
// but there's only one tokenizer data instance...
|
||||
// Instead, we only ignore the trailing whitespace.
|
||||
const int prevLine = (history->next - 1) % COMMAND_HISTORY;
|
||||
const int length1 = LengthWithoutTrailingWhitespace( edit->buffer );
|
||||
const int length2 = LengthWithoutTrailingWhitespace( history->commands[prevLine].buffer );
|
||||
const int maxLength = min( length1, length2 );
|
||||
if ( maxLength <= 0 || strncmp(edit->buffer, history->commands[prevLine].buffer, maxLength) == 0 ) {
|
||||
history->display = history->next;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// copy the line
|
||||
history->commands[history->next % COMMAND_HISTORY] = *edit;
|
||||
++history->next;
|
||||
history->display = history->next;
|
||||
}
|
||||
|
||||
|
||||
void History_GetPreviousCommand( field_t* edit, history_t* history )
|
||||
{
|
||||
if ( history->next - history->display < COMMAND_HISTORY && history->display > 0 )
|
||||
--history->display;
|
||||
*edit = history->commands[history->display % COMMAND_HISTORY];
|
||||
}
|
||||
|
||||
|
||||
void History_GetNextCommand( field_t* edit, history_t* history, int width )
|
||||
{
|
||||
++history->display;
|
||||
if ( history->display < history->next ) {
|
||||
*edit = history->commands[history->display % COMMAND_HISTORY];
|
||||
return;
|
||||
}
|
||||
|
||||
history->display = history->next;
|
||||
Field_Clear( edit );
|
||||
edit->widthInChars = width;
|
||||
}
|
||||
|
||||
|
||||
const char* Q_itohex( uint64_t number, qbool uppercase, qbool prefix )
|
||||
{
|
||||
|
|
|
@ -666,6 +666,19 @@ void Field_AutoCompleteDemoNameRead( int startArg, int compArg );
|
|||
void Field_AutoCompleteDemoNameWrite( int startArg, int compArg );
|
||||
void Field_AutoCompleteKeyName( int startArg, int compArg );
|
||||
|
||||
#define COMMAND_HISTORY 32
|
||||
typedef struct {
|
||||
field_t commands[COMMAND_HISTORY];
|
||||
int next; // the last line in the history buffer, not masked
|
||||
int display; // the line being displayed from history buffer
|
||||
// will be <= nextHistoryLine
|
||||
} history_t;
|
||||
|
||||
void History_Clear( history_t* history, int width );
|
||||
void History_SaveCommand( history_t* history, const field_t* edit );
|
||||
void History_GetPreviousCommand( field_t* edit, history_t* history );
|
||||
void History_GetNextCommand( field_t* edit, history_t* history, int width );
|
||||
|
||||
/*
|
||||
==============================================================
|
||||
|
||||
|
|
|
@ -79,12 +79,7 @@ static field_t tty_con;
|
|||
static cvar_t *ttycon_ansicolor = NULL;
|
||||
static qboolean ttycon_color_on = qfalse;
|
||||
|
||||
// history
|
||||
// NOTE TTimo this is a bit duplicate of the graphical console history
|
||||
// but it's safer and faster to write our own here
|
||||
#define TTY_HISTORY 32
|
||||
static field_t ttyEditLines[TTY_HISTORY];
|
||||
static int hist_current = -1, hist_count = 0;
|
||||
static history_t tty_history;
|
||||
|
||||
|
||||
|
||||
|
@ -110,27 +105,33 @@ static void tty_Back()
|
|||
{
|
||||
char key;
|
||||
key = '\b';
|
||||
write(1, &key, 1);
|
||||
write(STDOUT_FILENO, &key, 1);
|
||||
key = ' ';
|
||||
write(1, &key, 1);
|
||||
write(STDOUT_FILENO, &key, 1);
|
||||
key = '\b';
|
||||
write(1, &key, 1);
|
||||
write(STDOUT_FILENO, &key, 1);
|
||||
}
|
||||
|
||||
// clear the display of the line currently edited
|
||||
// bring cursor back to beginning of line
|
||||
static void tty_Hide()
|
||||
{
|
||||
int i;
|
||||
assert(ttycon_on);
|
||||
if (ttycon_hide)
|
||||
{
|
||||
ttycon_hide++;
|
||||
return;
|
||||
}
|
||||
if (tty_con.cursor>0)
|
||||
const int length = strlen(tty_con.buffer);
|
||||
if (length > 0)
|
||||
{
|
||||
for (i=0; i<tty_con.cursor; i++)
|
||||
const int stepsForward = length - tty_con.cursor;
|
||||
// a single write call for this didn't work on my terminal
|
||||
for (int i = 0; i < stepsForward; ++i)
|
||||
{
|
||||
write(STDOUT_FILENO, "\033[1C", 4);
|
||||
}
|
||||
for (int i = 0; i < length; ++i)
|
||||
{
|
||||
tty_Back();
|
||||
}
|
||||
|
@ -143,76 +144,26 @@ static void tty_Hide()
|
|||
// FIXME TTimo need to position the cursor if needed??
|
||||
static void tty_Show()
|
||||
{
|
||||
int i;
|
||||
assert(ttycon_on);
|
||||
assert(ttycon_hide>0);
|
||||
ttycon_hide--;
|
||||
if (ttycon_hide == 0)
|
||||
{
|
||||
write(STDOUT_FILENO, "]", 1);
|
||||
if (tty_con.cursor)
|
||||
const int length = strlen(tty_con.buffer);
|
||||
if (length > 0)
|
||||
{
|
||||
for (i=0; i<tty_con.cursor; i++)
|
||||
const int stepsBack = length - tty_con.cursor;
|
||||
write(STDOUT_FILENO, tty_con.buffer, length);
|
||||
// a single write call for this didn't work on my terminal
|
||||
for (int i = 0; i < stepsBack; ++i)
|
||||
{
|
||||
write(1, tty_con.buffer+i, 1);
|
||||
}
|
||||
write(STDOUT_FILENO, "\033[1D", 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void tty_Hist_Add(field_t *field)
|
||||
{
|
||||
int i;
|
||||
assert(hist_count <= TTY_HISTORY);
|
||||
assert(hist_count >= 0);
|
||||
assert(hist_current >= -1);
|
||||
assert(hist_current <= hist_count);
|
||||
// make some room
|
||||
for (i=TTY_HISTORY-1; i>0; i--)
|
||||
{
|
||||
ttyEditLines[i] = ttyEditLines[i-1];
|
||||
}
|
||||
ttyEditLines[0] = *field;
|
||||
if (hist_count<TTY_HISTORY)
|
||||
{
|
||||
hist_count++;
|
||||
}
|
||||
hist_current = -1; // re-init
|
||||
}
|
||||
|
||||
static field_t* tty_Hist_Prev()
|
||||
{
|
||||
int hist_prev;
|
||||
assert(hist_count <= TTY_HISTORY);
|
||||
assert(hist_count >= 0);
|
||||
assert(hist_current >= -1);
|
||||
assert(hist_current <= hist_count);
|
||||
hist_prev = hist_current + 1;
|
||||
if (hist_prev >= hist_count)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
hist_current++;
|
||||
return &(ttyEditLines[hist_current]);
|
||||
}
|
||||
|
||||
static field_t* tty_Hist_Next()
|
||||
{
|
||||
assert(hist_count <= TTY_HISTORY);
|
||||
assert(hist_count >= 0);
|
||||
assert(hist_current >= -1);
|
||||
assert(hist_current <= hist_count);
|
||||
if (hist_current >= 0)
|
||||
{
|
||||
hist_current--;
|
||||
}
|
||||
if (hist_current == -1)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return &(ttyEditLines[hist_current]);
|
||||
}
|
||||
|
||||
|
||||
// initialize the console input (tty mode if wanted and possible)
|
||||
static void Sys_ConsoleInputInit()
|
||||
|
@ -281,7 +232,7 @@ const char* Sys_ConsoleInput()
|
|||
static char text[256];
|
||||
int avail;
|
||||
char key;
|
||||
field_t *history;
|
||||
field_t field;
|
||||
|
||||
if (ttycon && ttycon->value)
|
||||
{
|
||||
|
@ -289,50 +240,68 @@ const char* Sys_ConsoleInput()
|
|||
if (avail != -1)
|
||||
{
|
||||
// we have something
|
||||
// backspace?
|
||||
// NOTE TTimo testing a lot of values .. seems it's the only way to get it to work everywhere
|
||||
if ((key == tty_erase) || (key == 127) || (key == 8))
|
||||
if (key == tty_erase || key == 127 || key == 8) // backspace
|
||||
{
|
||||
if (tty_con.cursor > 0)
|
||||
const int length = strlen(tty_con.buffer);
|
||||
if (length > 0)
|
||||
{
|
||||
tty_con.cursor--;
|
||||
tty_con.buffer[tty_con.cursor] = '\0';
|
||||
tty_Back();
|
||||
if (tty_con.cursor == length)
|
||||
{
|
||||
tty_con.buffer[length - 1] = '\0';
|
||||
tty_con.cursor--;
|
||||
tty_Back();
|
||||
}
|
||||
else if (tty_con.cursor > 0)
|
||||
{
|
||||
tty_Hide();
|
||||
const int toMove = length + 1 - tty_con.cursor; // with the null terminator
|
||||
memmove(tty_con.buffer + tty_con.cursor - 1, tty_con.buffer + tty_con.cursor, toMove);
|
||||
tty_con.cursor--;
|
||||
tty_Show();
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check if this is a control char
|
||||
if ((key) && (key) < ' ')
|
||||
{
|
||||
if (key == '\n')
|
||||
{
|
||||
#ifdef DEDICATED
|
||||
// push it in history
|
||||
tty_Hist_Add(&tty_con);
|
||||
History_SaveCommand(&tty_history, &tty_con);
|
||||
Q_strncpyz(text, tty_con.buffer, sizeof(text));
|
||||
Field_Clear(&tty_con);
|
||||
write(STDOUT_FILENO, "\n]", 2);
|
||||
#else
|
||||
// not in a game yet and no leading slash?
|
||||
if (cls.state != CA_ACTIVE && tty_con.cursor > 0 &&
|
||||
if (cls.state != CA_ACTIVE &&
|
||||
tty_con.buffer[0] != '/' && tty_con.buffer[0] != '\\')
|
||||
{
|
||||
// there's no one to chat with, so we consider this a command
|
||||
memmove(tty_con.buffer + 1, tty_con.buffer, strlen(tty_con.buffer) + 1);
|
||||
tty_con.buffer[0] = '\\';
|
||||
const int length = strlen(tty_con.buffer);
|
||||
if (length > 0)
|
||||
{
|
||||
memmove(tty_con.buffer + 1, tty_con.buffer, length + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
tty_con.buffer[1] = '\0';
|
||||
}
|
||||
tty_con.buffer[0] = '\\';
|
||||
tty_con.cursor++;
|
||||
}
|
||||
|
||||
// decide what the final command will be
|
||||
const int length = strlen(tty_con.buffer);
|
||||
if (tty_con.buffer[0] == '/' || tty_con.buffer[0] == '\\')
|
||||
Q_strncpyz(text, tty_con.buffer + 1, sizeof(text));
|
||||
else if (tty_con.cursor)
|
||||
else if (length > 0)
|
||||
Com_sprintf(text, sizeof(text), "say %s", tty_con.buffer);
|
||||
else
|
||||
*text = '\0';
|
||||
|
||||
// push it in history
|
||||
tty_Hist_Add(&tty_con);
|
||||
History_SaveCommand(&tty_history, &tty_con);
|
||||
tty_Hide();
|
||||
Com_Printf("tty]%s\n", tty_con.buffer);
|
||||
Field_Clear(&tty_con);
|
||||
|
@ -359,27 +328,28 @@ const char* Sys_ConsoleInput()
|
|||
{
|
||||
avail = read(0, &key, 1);
|
||||
if (avail != -1)
|
||||
{
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case 'A':
|
||||
history = tty_Hist_Prev();
|
||||
if (history)
|
||||
case 'A': // up arrow (move cursor up)
|
||||
History_GetPreviousCommand(&field, &tty_history);
|
||||
if (field.buffer[0] != '\0')
|
||||
{
|
||||
tty_Hide();
|
||||
tty_con = *history;
|
||||
tty_con = field;
|
||||
tty_Show();
|
||||
}
|
||||
tty_FlushIn();
|
||||
return NULL;
|
||||
break;
|
||||
case 'B':
|
||||
history = tty_Hist_Next();
|
||||
case 'B': // down arrow (move cursor down)
|
||||
History_GetNextCommand(&field, &tty_history, 0);
|
||||
tty_Hide();
|
||||
if (history)
|
||||
if (tty_con.buffer[0] != '\0')
|
||||
{
|
||||
tty_con = *history;
|
||||
} else
|
||||
tty_con = field;
|
||||
}
|
||||
else
|
||||
{
|
||||
Field_Clear(&tty_con);
|
||||
}
|
||||
|
@ -387,10 +357,52 @@ const char* Sys_ConsoleInput()
|
|||
tty_FlushIn();
|
||||
return NULL;
|
||||
break;
|
||||
case 'C':
|
||||
case 'C': // right arrow (move cursor right)
|
||||
if (tty_con.cursor < strlen(tty_con.buffer))
|
||||
{
|
||||
write(STDOUT_FILENO, "\033[1C", 4);
|
||||
tty_con.cursor++;
|
||||
}
|
||||
return NULL;
|
||||
case 'D':
|
||||
case 'D': // left arrow (move cursor left)
|
||||
if (tty_con.cursor > 0)
|
||||
{
|
||||
write(STDOUT_FILENO, "\033[1D", 4);
|
||||
tty_con.cursor--;
|
||||
}
|
||||
return NULL;
|
||||
case '3': // delete (might not work on all terminals)
|
||||
{
|
||||
const int length = strlen(tty_con.buffer);
|
||||
if (tty_con.cursor < length)
|
||||
{
|
||||
tty_Hide();
|
||||
const int toMove = length - tty_con.cursor; // with terminating NULL
|
||||
memmove(tty_con.buffer + tty_con.cursor, tty_con.buffer + tty_con.cursor + 1, toMove);
|
||||
tty_Show();
|
||||
}
|
||||
}
|
||||
tty_FlushIn();
|
||||
return NULL;
|
||||
case 'H': // home (move cursor to upper left corner)
|
||||
if (tty_con.cursor > 0)
|
||||
{
|
||||
tty_Hide();
|
||||
tty_con.cursor = 0;
|
||||
tty_Show();
|
||||
}
|
||||
return NULL;
|
||||
case 'F': // end (might not work on all terminals)
|
||||
{
|
||||
const int length = strlen(tty_con.buffer);
|
||||
if (tty_con.cursor < length)
|
||||
{
|
||||
tty_Hide();
|
||||
tty_con.cursor = length;
|
||||
tty_Show();
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -399,11 +411,25 @@ const char* Sys_ConsoleInput()
|
|||
tty_FlushIn();
|
||||
return NULL;
|
||||
}
|
||||
// push regular character
|
||||
tty_con.buffer[tty_con.cursor] = key;
|
||||
tty_con.cursor++;
|
||||
// print the current line (this is differential)
|
||||
write(1, &key, 1);
|
||||
|
||||
// if we get here, key is a regular character
|
||||
const int length = strlen(tty_con.buffer);
|
||||
if (tty_con.cursor == length)
|
||||
{
|
||||
write(STDOUT_FILENO, &key, 1);
|
||||
tty_con.buffer[tty_con.cursor + 0] = key;
|
||||
tty_con.buffer[tty_con.cursor + 1] = '\0';
|
||||
tty_con.cursor++;
|
||||
}
|
||||
else
|
||||
{
|
||||
tty_Hide();
|
||||
const int toMove = length + 1 - tty_con.cursor; // need to move the null terminator too
|
||||
memmove(tty_con.buffer + tty_con.cursor + 1, tty_con.buffer + tty_con.cursor, toMove);
|
||||
tty_con.buffer[tty_con.cursor] = key;
|
||||
tty_con.cursor++;
|
||||
tty_Show();
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
} else
|
||||
|
|
|
@ -75,31 +75,18 @@ typedef struct
|
|||
|
||||
field_t inputField;
|
||||
|
||||
field_t historyEditLines[COMMAND_HISTORY];
|
||||
int nextHistoryLine; // the last line in the history buffer, not masked
|
||||
int historyLine; // the line being displayed from history buffer
|
||||
history_t history;
|
||||
} WinConData;
|
||||
|
||||
static WinConData s_wcd;
|
||||
|
||||
void Con_StoreCommand( const char* inputBuffer ) {
|
||||
field_t& field = s_wcd.historyEditLines[ s_wcd.nextHistoryLine % COMMAND_HISTORY ];
|
||||
field_t field;
|
||||
Q_strncpyz( field.buffer, inputBuffer, sizeof(field.buffer) );
|
||||
field.cursor = strlen( inputBuffer );
|
||||
field.scroll = 0;
|
||||
field.widthInChars = field.cursor;
|
||||
|
||||
// avoid having the same command twice in a row
|
||||
if ( s_wcd.nextHistoryLine > 0 ) {
|
||||
const int prevLine = (s_wcd.nextHistoryLine - 1) % COMMAND_HISTORY;
|
||||
if ( !memcmp(&field, &s_wcd.historyEditLines[prevLine], sizeof(field)) ) {
|
||||
s_wcd.historyLine = s_wcd.nextHistoryLine;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
s_wcd.nextHistoryLine++;
|
||||
s_wcd.historyLine = s_wcd.nextHistoryLine;
|
||||
History_SaveCommand( &s_wcd.history, &field );
|
||||
}
|
||||
|
||||
static LONG WINAPI ConWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
|
@ -298,27 +285,28 @@ LONG WINAPI InputLineWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
|
|||
break;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
if ( wParam == VK_UP ) {
|
||||
if ( s_wcd.nextHistoryLine - s_wcd.historyLine < COMMAND_HISTORY && s_wcd.historyLine > 0 )
|
||||
s_wcd.historyLine--;
|
||||
const field_t& field = s_wcd.historyEditLines[ s_wcd.historyLine % COMMAND_HISTORY ];
|
||||
if ( wParam == VK_UP )
|
||||
{
|
||||
field_t field;
|
||||
History_GetPreviousCommand( &field, &s_wcd.history );
|
||||
SetWindowText( hWnd, field.buffer );
|
||||
SendMessage( hWnd, EM_SETSEL, (WPARAM)field.cursor, (LPARAM)field.cursor );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( wParam == VK_DOWN ) {
|
||||
s_wcd.historyLine++;
|
||||
|
||||
if ( s_wcd.historyLine >= s_wcd.nextHistoryLine ) {
|
||||
s_wcd.historyLine = s_wcd.nextHistoryLine;
|
||||
SetWindowText( s_wcd.hwndInputLine, "" );
|
||||
return 0;
|
||||
if ( wParam == VK_DOWN )
|
||||
{
|
||||
field_t field;
|
||||
History_GetNextCommand( &field, &s_wcd.history, 0 );
|
||||
if ( field.buffer[0] != '\0' )
|
||||
{
|
||||
SetWindowText( hWnd, field.buffer );
|
||||
SendMessage( hWnd, EM_SETSEL, (WPARAM)field.cursor, (LPARAM)field.cursor );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowText( s_wcd.hwndInputLine, "" );
|
||||
}
|
||||
|
||||
const field_t& field = s_wcd.historyEditLines[ s_wcd.historyLine % COMMAND_HISTORY ];
|
||||
SetWindowText( hWnd, field.buffer );
|
||||
SendMessage( hWnd, EM_SETSEL, (WPARAM)field.cursor, (LPARAM)field.cursor );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -499,10 +487,7 @@ void Sys_CreateConsole( void )
|
|||
SetForegroundWindow( s_wcd.hWnd );
|
||||
SetFocus( s_wcd.hwndInputLine );
|
||||
|
||||
for ( int i = 0; i < COMMAND_HISTORY; ++i )
|
||||
Field_Clear( &s_wcd.historyEditLines[i] );
|
||||
s_wcd.historyLine = 0;
|
||||
s_wcd.nextHistoryLine = 0;
|
||||
History_Clear( &s_wcd.history, 0 );
|
||||
|
||||
s_wcd.visLevel = 1;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue