int key_consoleactive;
char *keybindings[MAX_BINDMAPS][MAX_KEYS];
int history_line;
-int history_line_idx;
char history_savedline[MAX_INPUTLINE];
+conbuffer_t history;
+#define HIST_TEXTSIZE 262144
+#define HIST_MAXLINES 4096
-static void Key_History_Init()
+extern cvar_t con_textsize;
+
+
+static void Key_History_Init(void)
{
- qfile_t *historyfile = FS_OpenRealFile("darkplaces_history.txt", "r", false);
+ qfile_t *historyfile;
+ ConBuffer_Init(&history, HIST_TEXTSIZE, HIST_MAXLINES, zonemempool);
+
+ historyfile = FS_OpenRealFile("darkplaces_history.txt", "rb", false); // rb to handle unix line endings on windows too
if(historyfile)
{
char buf[MAX_INPUTLINE];
int bufpos;
int c;
- *buf = ']';
- bufpos = 1;
+ bufpos = 0;
for(;;)
{
c = FS_Getc(historyfile);
if(c < 0 || c == 0 || c == '\r' || c == '\n')
{
- if(bufpos > 1)
+ if(bufpos > 0)
{
buf[bufpos] = 0;
- Con_AddLine(buf, bufpos, CON_MASK_INPUT);
- bufpos = 1;
+ ConBuffer_AddLine(&history, buf, bufpos, 0);
+ bufpos = 0;
}
if(c < 0)
break;
history_line = -1;
}
-static void Key_History_Shutdown()
+static void Key_History_Shutdown(void)
{
// TODO write history to a file
qfile_t *historyfile = FS_OpenRealFile("darkplaces_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 ]
+ int i;
+ for(i = 0; i < CONBUFFER_LINES_COUNT(&history); ++i)
+ FS_Printf(historyfile, "%s\n", ConBuffer_GetLine(&history, i));
FS_Close(historyfile);
}
+
+ ConBuffer_Shutdown(&history);
}
-static void Key_History_Push()
+static void Key_History_Push(void)
{
- 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;
- if(!strncmp(key_line, "]quit ", 6)) // 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");
+ if(key_line[1]) // empty?
+ if(strcmp(key_line, "]quit")) // putting these into the history just sucks
+ if(strncmp(key_line, "]quit ", 6)) // putting these into the history just sucks
+ ConBuffer_AddLine(&history, key_line + 1, strlen(key_line) - 1, 0);
+ Con_Printf("%s\n", key_line); // don't mark empty lines as history
history_line = -1;
}
-static void Key_History_Up()
+static void Key_History_Up(void)
{
- int l;
+ if(history_line == -1) // editing the "new" line
+ strlcpy(history_savedline, key_line + 1, sizeof(history_savedline));
- if(history_line >= 0)
+ if(history_line == -1)
{
- history_line = Con_GetLineByID(history_line_idx);
- if(history_line == -1)
- history_line = -2; // -2 means before first
+ history_line = CONBUFFER_LINES_COUNT(&history) - 1;
+ if(history_line != -1)
+ {
+ strlcpy(key_line + 1, ConBuffer_GetLine(&history, history_line), sizeof(key_line) - 1);
+ key_linepos = strlen(key_line);
+ }
}
-
- // 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)
+ else if(history_line > 0)
{
- history_line = l;
- history_line_idx = Con_GetLineID(l);
- strlcpy(key_line, Con_GetLine(history_line), sizeof(key_line));
+ --history_line; // this also does -1 -> 0, so it is good
+ strlcpy(key_line + 1, ConBuffer_GetLine(&history, history_line), sizeof(key_line) - 1);
+ key_linepos = strlen(key_line);
}
-
- key_linepos = strlen(key_line);
}
-static void Key_History_Down()
+static void Key_History_Down(void)
{
- 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)
+ if(history_line < CONBUFFER_LINES_COUNT(&history) - 1)
{
- history_line = l;
- history_line_idx = Con_GetLineID(l);
- strlcpy(key_line, Con_GetLine(history_line), sizeof(key_line));
+ ++history_line;
+ strlcpy(key_line + 1, ConBuffer_GetLine(&history, history_line), sizeof(key_line) - 1);
}
else
{
history_line = -1;
- strlcpy(key_line, history_savedline, sizeof(key_line));
+ strlcpy(key_line + 1, history_savedline, sizeof(key_line) - 1);
}
key_linepos = strlen(key_line);
break;
}
- if ((toupper(key) == 'V' && keydown[K_CTRL]) || ((key == K_INS || key == K_KP_INS) && keydown[K_SHIFT]))
+ if ((key == 'v' && keydown[K_CTRL]) || ((key == K_INS || key == K_KP_INS) && keydown[K_SHIFT]))
{
char *cbd, *p;
if ((cbd = Sys_GetClipboardData()) != 0)
p = cbd;
while (*p)
{
- if (*p == '\n' || *p == '\r' || *p == '\b')
+ if (*p == '\r' && *(p+1) == '\n')
{
- *p++ = 0;
- break;
+ *p++ = ';';
+ *p++ = ' ';
}
+ else if (*p == '\n' || *p == '\r' || *p == '\b')
+ *p++ = ';';
p++;
}
#else
if (i > 0)
{
// terencehill: insert the clipboard text between the characters of the line
- char *temp = Z_Malloc(MAX_INPUTLINE);
+ char *temp = (char *) Z_Malloc(MAX_INPUTLINE);
cbd[i]=0;
temp[0]=0;
if ( key_linepos < (int)strlen(key_line) )
return;
}
- if (key == 'l')
+ if (key == 'l' && keydown[K_CTRL])
{
- if (keydown[K_CTRL])
- {
- Cbuf_AddText ("clear\n");
- return;
- }
+ Cbuf_AddText ("clear\n");
+ return;
+ }
+
+ if (key == 'u' && keydown[K_CTRL]) // like vi/readline ^u: delete currently edited line
+ {
+ // clear line
+ key_line[0] = ']';
+ key_line[1] = 0;
+ key_linepos = 1;
+ return;
+ }
+
+ if (key == 'q' && keydown[K_CTRL]) // like zsh ^q: push line to history, don't execute, and clear
+ {
+ // clear line
+ Key_History_Push();
+ key_line[0] = ']';
+ key_line[1] = 0;
+ key_linepos = 1;
+ return;
}
if (key == K_ENTER || key == K_KP_ENTER)
if (key == K_TAB)
{
+ if(keydown[K_CTRL]) // append to the cvar its value
+ {
+ int cvar_len, cvar_str_len, chars_to_move;
+ char k;
+ char cvar[MAX_INPUTLINE];
+ const char *cvar_str;
+
+ // go to the start of the variable
+ while(--key_linepos)
+ {
+ k = key_line[key_linepos];
+ if(k == '\"' || k == ';' || k == ' ' || k == '\'')
+ break;
+ }
+ key_linepos++;
+
+ // save the variable name in cvar
+ for(cvar_len=0; (k = key_line[key_linepos + cvar_len]) != 0; cvar_len++)
+ {
+ if(k == '\"' || k == ';' || k == ' ' || k == '\'')
+ break;
+ cvar[cvar_len] = k;
+ }
+ if (cvar_len==0)
+ return;
+ cvar[cvar_len] = 0;
+
+ // go to the end of the cvar
+ key_linepos += cvar_len;
+
+ // save the content of the variable in cvar_str
+ cvar_str = Cvar_VariableString(cvar);
+ cvar_str_len = strlen(cvar_str);
+ if (cvar_str_len==0)
+ return;
+
+ // insert space and cvar_str in key_line
+ chars_to_move = strlen(&key_line[key_linepos]);
+ if (key_linepos + 1 + cvar_str_len + chars_to_move < MAX_INPUTLINE)
+ {
+ if (chars_to_move)
+ memmove(&key_line[key_linepos + 1 + cvar_str_len], &key_line[key_linepos], chars_to_move);
+ key_line[key_linepos++] = ' ';
+ memcpy(&key_line[key_linepos], cvar_str, cvar_str_len);
+ key_linepos += cvar_str_len;
+ key_line[key_linepos + chars_to_move] = 0;
+ }
+ else
+ Con_Printf("Couldn't append cvar value, edit line too long.\n");
+ return;
+ }
// Enhanced command completion
// by EvilTypeGuy eviltypeguy@qeradiant.com
// Thanks to Fett, Taniwha
int pos;
char k;
pos = key_linepos-1;
+
+ if(pos) // skip all "; ' after the word
+ while(--pos)
+ {
+ k = key_line[pos];
+ if (!(k == '\"' || k == ';' || k == ' ' || k == '\''))
+ break;
+ }
+
if(pos)
while(--pos)
{
pos-=5;
else
{
+ if(pos-1 > 0 && key_line[pos-1] == STRING_COLOR_TAG && key_line[pos] == STRING_COLOR_TAG) // consider ^^ as a character
+ pos--;
pos--;
break;
}
char k;
len = (int)strlen(key_line);
pos = key_linepos;
+
while(++pos < len)
{
k = key_line[pos];
if(k == '\"' || k == ';' || k == ' ' || k == '\'')
break;
}
+
+ if (pos < len) // skip all "; ' after the word
+ while(++pos < len)
+ {
+ k = key_line[pos];
+ if (!(k == '\"' || k == ';' || k == ' ' || k == '\''))
+ break;
+ }
key_linepos = pos;
}
else if(keydown[K_SHIFT]) // move cursor to the next character ignoring colors
int pos, len;
len = (int)strlen(key_line);
pos = key_linepos;
- // check if there is a color tag right after the cursor
- if (key_line[pos] == STRING_COLOR_TAG)
- {
- if(isdigit(key_line[pos+1]))
- pos+=1;
- 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;
- }
+
+ // go beyond all initial consecutive color tags, if any
+ if(pos < len)
+ while (key_line[pos] == STRING_COLOR_TAG)
+ {
+ if(isdigit(key_line[pos+1]))
+ pos+=2;
+ 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;
+ }
+
+ // skip the char
+ if (key_line[pos] == STRING_COLOR_TAG && key_line[pos+1] == STRING_COLOR_TAG) // consider ^^ as a character
+ pos++;
pos++;
// now go beyond all next consecutive color tags, if any
Key_History_Down();
return;
}
-
- if (key == K_PGUP || key == K_KP_PGUP || key == K_MWHEELUP)
+ // ~1.0795 = 82/76 using con_textsize 64 76 is height of the char, 6 is the distance between 2 lines
+ if (key == K_PGUP || key == K_KP_PGUP)
{
if(keydown[K_CTRL])
{
- con_backscroll += 3;
+ con_backscroll += (int)floor((vid_conheight.integer >> 2) / con_textsize.integer)-1;
}
else
- con_backscroll += ((int) vid_conheight.integer >> 5);
+ con_backscroll += (int)floor((vid_conheight.integer >> 1) / con_textsize.integer)-3;
return;
}
- if (key == K_PGDN || key == K_KP_PGDN || key == K_MWHEELDOWN)
+ if (key == K_PGDN || key == K_KP_PGDN)
{
if(keydown[K_CTRL])
{
- con_backscroll -= 3;
+ con_backscroll -= (int)floor((vid_conheight.integer >> 2) / con_textsize.integer)-1;
}
else
- con_backscroll -= ((int) vid_conheight.integer >> 5);
+ con_backscroll -= (int)floor((vid_conheight.integer >> 1) / con_textsize.integer)-3;
+ return;
+ }
+
+ if (key == K_MWHEELUP)
+ {
+ if(keydown[K_CTRL])
+ con_backscroll += 1;
+ else if(keydown[K_SHIFT])
+ con_backscroll += (int)floor((vid_conheight.integer >> 2) / con_textsize.integer)-1;
+ else
+ con_backscroll += 5;
return;
}
+ if (key == K_MWHEELDOWN)
+ {
+ if(keydown[K_CTRL])
+ con_backscroll -= 1;
+ else if(keydown[K_SHIFT])
+ con_backscroll -= (int)floor((vid_conheight.integer >> 2) / con_textsize.integer)-1;
+ else
+ con_backscroll -= 5;
+ return;
+ }
+
+ if (keydown[K_CTRL])
+ {
+ // text zoom in
+ if (key == '+' || key == K_KP_PLUS)
+ {
+ if (con_textsize.integer < 128)
+ Cvar_SetValueQuick(&con_textsize, con_textsize.integer + 1);
+ return;
+ }
+ // text zoom out
+ if (key == '-' || key == K_KP_MINUS)
+ {
+ if (con_textsize.integer > 1)
+ Cvar_SetValueQuick(&con_textsize, con_textsize.integer - 1);
+ return;
+ }
+ // text zoom reset
+ if (key == '0' || key == K_KP_INS)
+ {
+ Cvar_SetValueQuick(&con_textsize, atoi(Cvar_VariableDefString("con_textsize")));
+ return;
+ }
+ }
+
if (key == K_HOME || key == K_KP_HOME)
{
if (keydown[K_CTRL])