From f800c0a37d45e51883f60e2751eb930251a7a903 Mon Sep 17 00:00:00 2001 From: divverent Date: Sun, 17 May 2009 18:59:45 +0000 Subject: [PATCH] experimental new persistent console history (uses same buffer as console output), file name = dp_history.txt, similar to .bash_history git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@8971 d7cf8633-e32d-0410-b094-e92efae38249 --- console.c | 152 ++++++++++++++++++++++++--------- console.h | 13 +++ host.c | 1 + keys.c | 246 ++++++++++++++++++++++++++++++++++++++---------------- keys.h | 6 +- 5 files changed, 304 insertions(+), 114 deletions(-) diff --git a/console.c b/console.c index c3b274c8..28b0bef7 100644 --- a/console.c +++ b/console.c @@ -28,8 +28,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. float con_cursorspeed = 4; -#define CON_TEXTSIZE 131072 -#define CON_MAXLINES 4096 +#define CON_TEXTSIZE 1048576 +#define CON_MAXLINES 16384 // lines up from bottom to display int con_backscroll; @@ -37,13 +37,10 @@ int con_backscroll; // console buffer char con_text[CON_TEXTSIZE]; -#define CON_MASK_HIDENOTIFY 128 -#define CON_MASK_CHAT 1 - typedef struct { char *start; - int len; + size_t len; double addtime; int mask; @@ -56,6 +53,7 @@ con_lineinfo con_lines[CON_MAXLINES]; int con_lines_first; // cyclic buffer int con_lines_count; #define CON_LINES_IDX(i) ((con_lines_first + (i)) % CON_MAXLINES) +#define CON_LINES_UNIDX(i) (((i) - con_lines_first + CON_MAXLINES) % CON_MAXLINES) #define CON_LINES_LAST CON_LINES_IDX(con_lines_count - 1) #define CON_LINES(i) con_lines[CON_LINES_IDX(i)] #define CON_LINES_PRED(i) (((i) + CON_MAXLINES - 1) % CON_MAXLINES) @@ -946,7 +944,7 @@ Prints to all appropriate console targets, and adds timestamps extern cvar_t timestamps; extern cvar_t timeformat; extern qboolean sys_nostdout; -void Con_Print(const char *msg) +static void Con_Print_Internal(const char *msg, qboolean history) { static int mask = 0; static int index = 0; @@ -1007,7 +1005,7 @@ void Con_Print(const char *msg) // send to log file Log_ConPrint(line); // send to scrollable buffer - if (con_initialized && cls.state != ca_dedicated) + if (history && con_initialized && cls.state != ca_dedicated) { Con_PrintToHistory(line, mask); mask = 0; @@ -1200,6 +1198,14 @@ void Con_Print(const char *msg) } } } +void Con_Print(const char *msg) +{ + Con_Print_Internal(msg, true); +} +void Con_PrintNotToHistory(const char *msg) +{ + Con_Print_Internal(msg, false); +} /* @@ -1285,7 +1291,7 @@ void Con_DrawInput (void) if (!key_consoleactive) return; // don't draw anything - strlcpy(editlinecopy, key_lines[edit_line], sizeof(editlinecopy)); + strlcpy(editlinecopy, key_line, sizeof(editlinecopy)); text = editlinecopy; // Advanced Console Editing by Radix radix@planetquake.com @@ -1313,7 +1319,7 @@ void Con_DrawInput (void) DrawQ_String_Font(x, con_vislines - con_textsize.value*2, text, 0, con_textsize.value, con_textsize.value, 1.0, 1.0, 1.0, 1.0, 0, NULL, false, FONT_CONSOLE ); // remove cursor -// key_lines[edit_line][key_linepos] = 0; +// key_line[key_linepos] = 0; } typedef struct @@ -1383,6 +1389,65 @@ int Con_DisplayLineFunc(void *passthrough, const char *line, size_t length, floa return 1; } +int Con_FindPrevLine(int mask_must, int mask_mustnot, int start) +{ + int i; + if(start == -1) + start = con_lines_count; + for(i = start - 1; i >= 0; --i) + { + con_lineinfo *l = &CON_LINES(i); + + if((l->mask & mask_must) != mask_must) + continue; + if(l->mask & mask_mustnot) + continue; + + return i; + } + + return -1; +} + +int Con_FindNextLine(int mask_must, int mask_mustnot, int start) +{ + int i; + for(i = start + 1; i < con_lines_count; ++i) + { + con_lineinfo *l = &CON_LINES(i); + + if((l->mask & mask_must) != mask_must) + continue; + if(l->mask & mask_mustnot) + continue; + + return i; + } + + return -1; +} + +const char *Con_GetLine(int i) +{ + static char buf[MAX_INPUTLINE]; + con_lineinfo *l = &CON_LINES(i); + size_t sz = l->len+1 > sizeof(buf) ? sizeof(buf) : l->len+1; + strlcpy(buf, l->start, sz); + return buf; +} + +int Con_GetLineID(int i) +{ + return CON_LINES_IDX(i); +} + +int Con_GetLineByID(int i) +{ + i = CON_LINES_UNIDX(i); + if(i >= con_lines_count) + return -1; + return i; +} int Con_DrawNotifyRect(int mask_must, int mask_mustnot, float maxage, float x, float y, float width, float height, float fontsize, float alignment_x, float alignment_y, const char *continuationString) { @@ -1523,13 +1588,13 @@ void Con_DrawNotify (void) chatstart = 0; // shut off gcc warning } - v = notifystart + con_notifysize.value * Con_DrawNotifyRect(0, CON_MASK_HIDENOTIFY | (numChatlines ? CON_MASK_CHAT : 0), con_notifytime.value, 0, notifystart, vid_conwidth.value, con_notify.value * con_notifysize.value, con_notifysize.value, align, 0.0, ""); + v = notifystart + con_notifysize.value * Con_DrawNotifyRect(0, CON_MASK_LOADEDHISTORY | CON_MASK_INPUT | CON_MASK_HIDENOTIFY | (numChatlines ? CON_MASK_CHAT : 0), con_notifytime.value, 0, notifystart, vid_conwidth.value, con_notify.value * con_notifysize.value, con_notifysize.value, align, 0.0, ""); // chat? if(numChatlines) { v = chatstart + numChatlines * con_chatsize.value; - Con_DrawNotifyRect(CON_MASK_CHAT, 0, con_chattime.value, 0, chatstart, vid_conwidth.value * con_chatwidth.value, v - chatstart, con_chatsize.value, 0.0, 1.0, "^3\014\014\014 "); // 015 is ·> character in conchars.tga + Con_DrawNotifyRect(CON_MASK_CHAT, CON_MASK_LOADEDHISTORY | CON_MASK_INPUT, con_chattime.value, 0, chatstart, vid_conwidth.value * con_chatwidth.value, v - chatstart, con_chatsize.value, 0.0, 1.0, "^3\014\014\014 "); // 015 is ·> character in conchars.tga } if (key_dest == key_message) @@ -1564,6 +1629,10 @@ int Con_MeasureConsoleLine(int lineno) { float width = vid_conwidth.value; con_text_info_t ti; + + if(con_lines[lineno].mask & CON_MASK_LOADEDHISTORY) + return 0; + ti.fontsize = con_textsize.value; ti.font = FONT_CONSOLE; @@ -1597,8 +1666,11 @@ returned. int Con_DrawConsoleLine(float y, int lineno, float ymin, float ymax) { float width = vid_conwidth.value; - con_text_info_t ti; + + if(con_lines[lineno].mask & CON_MASK_LOADEDHISTORY) + return 0; + ti.continuationString = ""; ti.alignment = 0; ti.fontsize = con_textsize.value; @@ -2418,20 +2490,20 @@ void Con_CompleteCommandLine (void) pos = key_linepos; while(--pos) { - k = key_lines[edit_line][pos]; + k = key_line[pos]; if(k == '\"' || k == ';' || k == ' ' || k == '\'') break; } pos++; - s = key_lines[edit_line] + pos; - strlcpy(s2, key_lines[edit_line] + key_linepos, sizeof(s2)); //save chars after cursor - key_lines[edit_line][key_linepos] = 0; //hide them + s = key_line + pos; + strlcpy(s2, key_line + key_linepos, sizeof(s2)); //save chars after cursor + key_line[key_linepos] = 0; //hide them - space = strchr(key_lines[edit_line] + 1, ' '); - if(space && pos == (space - key_lines[edit_line]) + 1) + space = strchr(key_line + 1, ' '); + if(space && pos == (space - key_line) + 1) { - strlcpy(command, key_lines[edit_line] + 1, min(sizeof(command), (unsigned int)(space - key_lines[edit_line]))); + strlcpy(command, key_line + 1, min(sizeof(command), (unsigned int)(space - key_line))); patterns = Cvar_VariableString(va("con_completion_%s", command)); // TODO maybe use a better place for this? if(patterns && !*patterns) @@ -2448,12 +2520,12 @@ void Con_CompleteCommandLine (void) // and now do the actual work *s = 0; - strlcat(key_lines[edit_line], t, MAX_INPUTLINE); - strlcat(key_lines[edit_line], s2, MAX_INPUTLINE); //add back chars after cursor + strlcat(key_line, t, MAX_INPUTLINE); + strlcat(key_line, s2, MAX_INPUTLINE); //add back chars after cursor // and fix the cursor - if(key_linepos > (int) strlen(key_lines[edit_line])) - key_linepos = (int) strlen(key_lines[edit_line]); + if(key_linepos > (int) strlen(key_line)) + key_linepos = (int) strlen(key_line); } return; } @@ -2588,12 +2660,12 @@ void Con_CompleteCommandLine (void) // and now do the actual work *s = 0; - strlcat(key_lines[edit_line], t, MAX_INPUTLINE); - strlcat(key_lines[edit_line], s2, MAX_INPUTLINE); //add back chars after cursor + strlcat(key_line, t, MAX_INPUTLINE); + strlcat(key_line, s2, MAX_INPUTLINE); //add back chars after cursor // and fix the cursor - if(key_linepos > (int) strlen(key_lines[edit_line])) - key_linepos = (int) strlen(key_lines[edit_line]); + if(key_linepos > (int) strlen(key_line)) + key_linepos = (int) strlen(key_line); } stringlistfreecontents(&resultbuf); stringlistfreecontents(&dirbuf); @@ -2622,7 +2694,7 @@ void Con_CompleteCommandLine (void) Con_Printf("\n%i possible aliases%s\n", a, (a > 1) ? "s: " : ":"); Cmd_CompleteAliasPrint(s); } - n = Nicks_CompleteCountPossible(key_lines[edit_line], key_linepos, s, true); + n = Nicks_CompleteCountPossible(key_line, key_linepos, s, true); if (n) { Con_Printf("\n%i possible nick%s\n", n, (n > 1) ? "s: " : ":"); @@ -2632,7 +2704,7 @@ void Con_CompleteCommandLine (void) if (!(c + v + a + n)) // No possible matches { if(s2[0]) - strlcpy(&key_lines[edit_line][key_linepos], s2, sizeof(key_lines[edit_line]) - key_linepos); + strlcpy(&key_line[key_linepos], s2, sizeof(key_line) - key_linepos); return; } @@ -2664,33 +2736,33 @@ void Con_CompleteCommandLine (void) done: // prevent a buffer overrun by limiting cmd_len according to remaining space - cmd_len = min(cmd_len, (int)sizeof(key_lines[edit_line]) - 1 - pos); + cmd_len = min(cmd_len, (int)sizeof(key_line) - 1 - pos); if (cmd) { key_linepos = pos; - memcpy(&key_lines[edit_line][key_linepos], cmd, cmd_len); + memcpy(&key_line[key_linepos], cmd, cmd_len); key_linepos += cmd_len; // if there is only one match, add a space after it - if (c + v + a + n == 1 && key_linepos < (int)sizeof(key_lines[edit_line]) - 1) + if (c + v + a + n == 1 && key_linepos < (int)sizeof(key_line) - 1) { if(n) { // was a nick, might have an offset, and needs colors ;) --blub key_linepos = pos - Nicks_offset[0]; cmd_len = strlen(Nicks_list[0]); - cmd_len = min(cmd_len, (int)sizeof(key_lines[edit_line]) - 3 - pos); + cmd_len = min(cmd_len, (int)sizeof(key_line) - 3 - pos); - memcpy(&key_lines[edit_line][key_linepos] , Nicks_list[0], cmd_len); + memcpy(&key_line[key_linepos] , Nicks_list[0], cmd_len); key_linepos += cmd_len; - if(key_linepos < (int)(sizeof(key_lines[edit_line])-4)) // space for ^, X and space and \0 - key_linepos = Nicks_AddLastColor(key_lines[edit_line], key_linepos); + if(key_linepos < (int)(sizeof(key_line)-4)) // space for ^, X and space and \0 + key_linepos = Nicks_AddLastColor(key_line, key_linepos); } - key_lines[edit_line][key_linepos++] = ' '; + key_line[key_linepos++] = ' '; } } // use strlcat to avoid a buffer overrun - key_lines[edit_line][key_linepos] = 0; - strlcat(key_lines[edit_line], s2, sizeof(key_lines[edit_line])); + key_line[key_linepos] = 0; + strlcat(key_line, s2, sizeof(key_line)); // free the command, cvar, and alias lists for (i = 0; i < 4; i++) diff --git a/console.h b/console.h index 009b05bd..be1010de 100644 --- a/console.h +++ b/console.h @@ -37,6 +37,7 @@ void Con_Init (void); void Con_Init_Commands (void); void Con_DrawConsole (int lines); void Con_Print(const char *txt); +void Con_PrintNotToHistory(const char *txt); void Con_Printf(const char *fmt, ...) DP_FUNC_PRINTF(1); void Con_DPrint(const char *msg); void Con_DPrintf(const char *fmt, ...) DP_FUNC_PRINTF(1); @@ -68,5 +69,17 @@ void Log_DestBuffer_Flush (void); // call this once per frame to send out replie void Log_Printf(const char *logfilename, const char *fmt, ...) DP_FUNC_PRINTF(2); +#define CON_MASK_HIDENOTIFY 128 +#define CON_MASK_CHAT 1 +#define CON_MASK_INPUT 2 +#define CON_MASK_LOADEDHISTORY 4 + +void Con_AddLine(const char *line, int len, int mask); +int Con_FindPrevLine(int mask_must, int mask_mustnot, int start); +int Con_FindNextLine(int mask_must, int mask_mustnot, int start); +const char *Con_GetLine(int i); +int Con_GetLineID(int i); +int Con_GetLineByID(int i); + #endif diff --git a/host.c b/host.c index de067d6b..afce873d 100644 --- a/host.c +++ b/host.c @@ -1215,6 +1215,7 @@ void Host_Shutdown(void) } Cmd_Shutdown(); + Key_Shutdown(); CL_Shutdown(); Sys_Shutdown(); Log_Close(); diff --git a/keys.c b/keys.c index bad2cfc2..a024ca04 100644 --- a/keys.c +++ b/keys.c @@ -29,14 +29,144 @@ cvar_t con_closeontoggleconsole = {CVAR_SAVE, "con_closeontoggleconsole","1", "a key up events are sent even if in console mode */ -int edit_line = MAX_INPUTLINES-1; -int history_line = MAX_INPUTLINES-1; -char key_lines[MAX_INPUTLINES][MAX_INPUTLINE]; +char key_line[MAX_INPUTLINE]; int key_linepos; qboolean key_insert = true; // insert key toggle (for editing) keydest_t key_dest; int key_consoleactive; char *keybindings[MAX_BINDMAPS][MAX_KEYS]; +int history_line; +int history_line_idx; +char history_savedline[MAX_INPUTLINE]; + +static void Key_History_Init() +{ + qfile_t *historyfile = FS_OpenRealFile("dp_history.txt", "r", false); + if(historyfile) + { + char buf[MAX_INPUTLINE]; + int bufpos; + int c; + + *buf = ']'; + bufpos = 1; + for(;;) + { + c = FS_Getc(historyfile); + if(c < 0 || c == 0 || c == '\r' || c == '\n') + { + if(bufpos > 1) + { + buf[bufpos] = 0; + Con_AddLine(buf, bufpos, CON_MASK_INPUT); + bufpos = 1; + } + if(c < 0) + break; + } + else + { + if(bufpos < MAX_INPUTLINE - 1) + buf[bufpos++] = c; + } + } + + FS_Close(historyfile); + } + + history_line = -1; +} + +static void Key_History_Shutdown() +{ + // TODO write history to a file + + qfile_t *historyfile = FS_OpenRealFile("dp_history.txt", "w", false); + if(historyfile) + { + int l = -1; + while((l = Con_FindNextLine(CON_MASK_INPUT, 0, l)) != -1) + FS_Printf(historyfile, "%s\n", Con_GetLine(l) + 1); // +1: skip the ] + FS_Close(historyfile); + } +} + +static void Key_History_Push() +{ + int mask; + + mask = CON_MASK_INPUT; + if(!key_line[1]) // empty? + mask = 0; + if(!strcmp(key_line, "]quit")) // putting these into the history just sucks + mask = 0; + Con_AddLine(key_line, strlen(key_line), mask); + Con_PrintNotToHistory(key_line); // don't mark empty lines as history + Con_PrintNotToHistory("\n"); + history_line = -1; +} + +static void Key_History_Up() +{ + int l; + + if(history_line >= 0) + { + history_line = Con_GetLineByID(history_line_idx); + if(history_line == -1) + history_line = -2; // -2 means before first + } + + // invalid history line? bad + if(history_line == -2) + return; + + if(history_line == -1) // editing the "new" line + strlcpy(history_savedline, key_line, sizeof(history_savedline)); + l = Con_FindPrevLine(CON_MASK_INPUT, 0, history_line); + if(l != -1) + { + history_line = l; + history_line_idx = Con_GetLineID(l); + strlcpy(key_line, Con_GetLine(history_line), sizeof(key_line)); + } + + key_linepos = strlen(key_line); +} + +static void Key_History_Down() +{ + int l; + + if(history_line >= 0) + { + history_line = Con_GetLineByID(history_line_idx); + if(history_line == -1) + history_line = -2; // -2 means before first + } + + if(history_line == -1) // editing the "new" line + return; + + // invalid history line? take the first line then + if(history_line == -2) + history_line = -1; // next Con_FindNextLine will fix it + + l = Con_FindNextLine(CON_MASK_INPUT, 0, history_line); + if(l != -1) + { + history_line = l; + history_line_idx = Con_GetLineID(l); + strlcpy(key_line, Con_GetLine(history_line), sizeof(key_line)); + } + else + { + history_line = -1; + strlcpy(key_line, history_savedline, sizeof(key_line)); + } + + key_linepos = strlen(key_line); +} static int key_bmap, key_bmap2; static unsigned char keydown[MAX_KEYS]; // 0 = up, 1 = down, 2 = repeating @@ -222,8 +352,8 @@ static const keyname_t keynames[] = { void Key_ClearEditLine (int edit_line) { - memset (key_lines[edit_line], '\0', sizeof(key_lines[edit_line])); - key_lines[edit_line][0] = ']'; + memset (key_line, '\0', sizeof(key_line)); + key_line[0] = ']'; key_linepos = 1; } @@ -311,12 +441,12 @@ Key_Console (int key, int ascii) char *temp = Z_Malloc(MAX_INPUTLINE); cbd[i]=0; temp[0]=0; - if ( key_linepos < (int)strlen(key_lines[edit_line]) ) - strlcpy(temp, key_lines[edit_line] + key_linepos, (int)strlen(key_lines[edit_line]) - key_linepos +1); - key_lines[edit_line][key_linepos] = 0; - strlcat(key_lines[edit_line], cbd, sizeof(key_lines[edit_line])); + if ( key_linepos < (int)strlen(key_line) ) + strlcpy(temp, key_line + key_linepos, (int)strlen(key_line) - key_linepos +1); + key_line[key_linepos] = 0; + strlcat(key_line, cbd, sizeof(key_line)); if (temp[0]) - strlcat(key_lines[edit_line], temp, sizeof(key_lines[edit_line])); + strlcat(key_line, temp, sizeof(key_line)); Z_Free(temp); key_linepos += i; } @@ -336,17 +466,11 @@ Key_Console (int key, int ascii) if (key == K_ENTER || key == K_KP_ENTER) { - Cbuf_AddText (key_lines[edit_line]+1); // skip the ] + Cbuf_AddText (key_line+1); // skip the ] Cbuf_AddText ("\n"); - Con_Printf("%s\n",key_lines[edit_line]); - if(key_lines[edit_line][1] == 0) // empty line (just a ])? - return; // no, no, you can't submit empty lines to the history... - // LordHavoc: redesigned edit_line/history_line - edit_line = 31; - history_line = edit_line; - memmove(key_lines[0], key_lines[1], sizeof(key_lines[0]) * edit_line); - key_lines[edit_line][0] = ']'; - key_lines[edit_line][1] = 0; // EvilTypeGuy: null terminate + Key_History_Push(); + key_line[0] = ']'; + key_line[1] = 0; // EvilTypeGuy: null terminate key_linepos = 1; // force an update, because the command may take some time if (cls.state == ca_disconnected) @@ -381,7 +505,7 @@ Key_Console (int key, int ascii) if(pos) while(--pos) { - k = key_lines[edit_line][pos]; + k = key_line[pos]; if(k == '\"' || k == ';' || k == ' ' || k == '\'') break; } @@ -392,10 +516,10 @@ Key_Console (int key, int ascii) int pos; pos = key_linepos-1; while (pos) - if(pos-1 > 0 && key_lines[edit_line][pos-1] == STRING_COLOR_TAG && isdigit(key_lines[edit_line][pos])) + if(pos-1 > 0 && key_line[pos-1] == STRING_COLOR_TAG && isdigit(key_line[pos])) pos-=2; - else if(pos-4 > 0 && key_lines[edit_line][pos-4] == STRING_COLOR_TAG && key_lines[edit_line][pos-3] == STRING_COLOR_RGB_TAG_CHAR - && isxdigit(key_lines[edit_line][pos-2]) && isxdigit(key_lines[edit_line][pos-1]) && isxdigit(key_lines[edit_line][pos])) + else if(pos-4 > 0 && key_line[pos-4] == STRING_COLOR_TAG && key_line[pos-3] == STRING_COLOR_RGB_TAG_CHAR + && isxdigit(key_line[pos-2]) && isxdigit(key_line[pos-1]) && isxdigit(key_line[pos])) pos-=5; else { @@ -414,7 +538,7 @@ Key_Console (int key, int ascii) { if (key_linepos > 1) { - strlcpy(key_lines[edit_line] + key_linepos - 1, key_lines[edit_line] + key_linepos, sizeof(key_lines[edit_line]) + 1 - key_linepos); + strlcpy(key_line + key_linepos - 1, key_line + key_linepos, sizeof(key_line) + 1 - key_linepos); key_linepos--; } return; @@ -424,9 +548,9 @@ Key_Console (int key, int ascii) if (key == K_DEL || key == K_KP_DEL) { size_t linelen; - linelen = strlen(key_lines[edit_line]); + linelen = strlen(key_line); if (key_linepos < (int)linelen) - memmove(key_lines[edit_line] + key_linepos, key_lines[edit_line] + key_linepos + 1, linelen - key_linepos); + memmove(key_line + key_linepos, key_line + key_linepos + 1, linelen - key_linepos); return; } @@ -434,17 +558,17 @@ Key_Console (int key, int ascii) // move cursor to the next character if (key == K_RIGHTARROW || key == K_KP_RIGHTARROW) { - if (key_linepos >= (int)strlen(key_lines[edit_line])) + if (key_linepos >= (int)strlen(key_line)) return; if(keydown[K_CTRL]) // move cursor to the next word { int pos, len; char k; - len = (int)strlen(key_lines[edit_line]); + len = (int)strlen(key_line); pos = key_linepos; while(++pos < len) { - k = key_lines[edit_line][pos]; + k = key_line[pos]; if(k == '\"' || k == ';' || k == ' ' || k == '\'') break; } @@ -453,25 +577,25 @@ Key_Console (int key, int ascii) else if(keydown[K_SHIFT]) // move cursor to the next character ignoring colors { int pos, len; - len = (int)strlen(key_lines[edit_line]); + len = (int)strlen(key_line); pos = key_linepos; // check if there is a color tag right after the cursor - if (key_lines[edit_line][pos] == STRING_COLOR_TAG) + if (key_line[pos] == STRING_COLOR_TAG) { - if(isdigit(key_lines[edit_line][pos+1])) + if(isdigit(key_line[pos+1])) pos+=1; - else if(key_lines[edit_line][pos+1] == STRING_COLOR_RGB_TAG_CHAR && isxdigit(key_lines[edit_line][pos+2]) && isxdigit(key_lines[edit_line][pos+3]) && isxdigit(key_lines[edit_line][pos+4])) + else if(key_line[pos+1] == STRING_COLOR_RGB_TAG_CHAR && isxdigit(key_line[pos+2]) && isxdigit(key_line[pos+3]) && isxdigit(key_line[pos+4])) pos+=4; } pos++; // now go beyond all next consecutive color tags, if any if(pos < len) - while (key_lines[edit_line][pos] == STRING_COLOR_TAG) + while (key_line[pos] == STRING_COLOR_TAG) { - if(isdigit(key_lines[edit_line][pos+1])) + if(isdigit(key_line[pos+1])) pos+=2; - else if(key_lines[edit_line][pos+1] == STRING_COLOR_RGB_TAG_CHAR && isxdigit(key_lines[edit_line][pos+2]) && isxdigit(key_lines[edit_line][pos+3]) && isxdigit(key_lines[edit_line][pos+4])) + else if(key_line[pos+1] == STRING_COLOR_RGB_TAG_CHAR && isxdigit(key_line[pos+2]) && isxdigit(key_line[pos+3]) && isxdigit(key_line[pos+4])) pos+=5; else break; @@ -493,34 +617,13 @@ Key_Console (int key, int ascii) if (key == K_UPARROW || key == K_KP_UPARROW || (key == 'p' && keydown[K_CTRL])) { - if (history_line > 0 && key_lines[history_line-1][1]) - { - size_t linelen; - history_line--; - linelen = strlen(key_lines[history_line]); - memcpy(key_lines[edit_line], key_lines[history_line], linelen + 1); - key_linepos = (int)linelen; - } + Key_History_Up(); return; } if (key == K_DOWNARROW || key == K_KP_DOWNARROW || (key == 'n' && keydown[K_CTRL])) { - history_line++; - if (history_line >= edit_line) - { - history_line = edit_line; - key_lines[edit_line][0] = ']'; - key_lines[edit_line][1] = 0; - key_linepos = 1; - } - else - { - size_t linelen; - linelen = strlen(key_lines[history_line]); - memcpy(key_lines[edit_line], key_lines[history_line], linelen + 1); - key_linepos = (int)linelen; - } + Key_History_Down(); return; } @@ -560,7 +663,7 @@ Key_Console (int key, int ascii) if (keydown[K_CTRL]) con_backscroll = 0; else - key_linepos = (int)strlen(key_lines[edit_line]); + key_linepos = (int)strlen(key_line); return; } @@ -571,15 +674,15 @@ Key_Console (int key, int ascii) if (key_linepos < MAX_INPUTLINE-1) { int len; - len = (int)strlen(&key_lines[edit_line][key_linepos]); + len = (int)strlen(&key_line[key_linepos]); // check insert mode, or always insert if at end of line if (key_insert || len == 0) { // can't use strcpy to move string to right len++; - memmove(&key_lines[edit_line][key_linepos + 1], &key_lines[edit_line][key_linepos], len); + memmove(&key_line[key_linepos + 1], &key_line[key_linepos], len); } - key_lines[edit_line][key_linepos] = ascii; + key_line[key_linepos] = ascii; key_linepos++; } } @@ -974,12 +1077,9 @@ Key_WriteBindings (qfile_t *f) void Key_Init (void) { - int i; - - for (i = 0; i < 32; i++) { - key_lines[i][0] = ']'; - key_lines[i][1] = 0; - } + Key_History_Init(); + key_line[0] = ']'; + key_line[1] = 0; key_linepos = 1; // @@ -998,6 +1098,12 @@ Key_Init (void) Cvar_RegisterVariable (&con_closeontoggleconsole); } +void +Key_Shutdown (void) +{ + Key_History_Shutdown(); +} + const char *Key_GetBind (int key) { const char *bind; diff --git a/keys.h b/keys.h index 5b42933a..beb5df69 100644 --- a/keys.h +++ b/keys.h @@ -190,12 +190,9 @@ keynum_t; typedef enum keydest_e { key_game, key_message, key_menu, key_menu_grabbed, key_console, key_void } keydest_t; -#define MAX_INPUTLINES 32 #define MAX_BINDMAPS 8 #define MAX_KEYS 1024 -extern int edit_line; -extern int history_line; -extern char key_lines[MAX_INPUTLINES][MAX_INPUTLINE]; +extern char key_line[MAX_INPUTLINE]; extern int key_linepos; extern qboolean key_insert; // insert key toggle (for editing) extern keydest_t key_dest; @@ -214,6 +211,7 @@ extern unsigned int chat_bufferlen; void Key_WriteBindings(qfile_t *f); void Key_Init(void); +void Key_Shutdown(void); void Key_Init_Cvars(void); void Key_Event(int key, int ascii, qboolean down); void Key_ClearStates (void); -- 2.39.2