X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=keys.c;h=a3a6d9268601045bd102472293893308021bc966;hb=4223c283a73c5f2774a6e01515246dfc511889b7;hp=1392be6360c0e8d382977192a2c8f23d3a8d1530;hpb=7d917e0a7817da5998432cf9b7e779a623ef1bb3;p=xonotic%2Fdarkplaces.git diff --git a/keys.c b/keys.c index 1392be63..a3a6d926 100644 --- a/keys.c +++ b/keys.c @@ -25,7 +25,7 @@ #include "utf8lib.h" #include "csprogs.h" -cvar_t con_closeontoggleconsole = {CVAR_CLIENT | CVAR_SAVE, "con_closeontoggleconsole","1", "allows toggleconsole binds to close the console as well; when set to 2, this even works when not at the start of the line in console input; when set to 3, this works even if the toggleconsole key is the color tag"}; +cvar_t con_closeontoggleconsole = {CF_CLIENT | CF_ARCHIVE, "con_closeontoggleconsole","1", "allows toggleconsole binds to close the console as well; when set to 2, this even works when not at the start of the line in console input; when set to 3, this works even if the toggleconsole key is the color tag"}; /* key up events are sent even if in console mode @@ -33,7 +33,7 @@ key up events are sent even if in console mode char key_line[MAX_INPUTLINE]; int key_linepos; -qboolean key_insert = true; // insert key toggle (for editing) +qbool key_insert = true; // insert key toggle (for editing) keydest_t key_dest; int key_consoleactive; char *keybindings[MAX_BINDMAPS][MAX_KEYS]; @@ -41,7 +41,7 @@ char *keybindings[MAX_BINDMAPS][MAX_KEYS]; int history_line; char history_savedline[MAX_INPUTLINE]; char history_searchstring[MAX_INPUTLINE]; -qboolean history_matchfound = false; +qbool history_matchfound = false; conbuffer_t history; extern cvar_t con_textsize; @@ -92,18 +92,20 @@ static void Key_History_Init(void) static void Key_History_Shutdown(void) { - // TODO write history to a file - // not necessary for mobile #ifndef DP_MOBILETOUCH qfile_t *historyfile = FS_OpenRealFile("darkplaces_history.txt", "w", false); if(historyfile) { int i; + + Con_Print("Saving command history to darkplaces_history.txt ...\n"); for(i = 0; i < CONBUFFER_LINES_COUNT(&history); ++i) FS_Printf(historyfile, "%s\n", ConBuffer_GetLine(&history, i)); FS_Close(historyfile); } + else + Con_Print(CON_ERROR "Couldn't write darkplaces_history.txt\n"); #endif ConBuffer_Shutdown(&history); @@ -123,11 +125,11 @@ static void Key_History_Push(void) history_matchfound = false; } -static qboolean Key_History_Get_foundCommand(void) +static qbool Key_History_Get_foundCommand(void) { if (!history_matchfound) return false; - strlcpy(key_line + 1, ConBuffer_GetLine(&history, history_line), sizeof(key_line) - 1); + dp_strlcpy(key_line + 1, ConBuffer_GetLine(&history, history_line), sizeof(key_line) - 1); key_linepos = (int)strlen(key_line); history_matchfound = false; return true; @@ -136,7 +138,7 @@ static qboolean Key_History_Get_foundCommand(void) static void Key_History_Up(void) { if(history_line == -1) // editing the "new" line - strlcpy(history_savedline, key_line + 1, sizeof(history_savedline)); + dp_strlcpy(history_savedline, key_line + 1, sizeof(history_savedline)); if (Key_History_Get_foundCommand()) return; @@ -146,14 +148,14 @@ static void Key_History_Up(void) history_line = CONBUFFER_LINES_COUNT(&history) - 1; if(history_line != -1) { - strlcpy(key_line + 1, ConBuffer_GetLine(&history, history_line), sizeof(key_line) - 1); + dp_strlcpy(key_line + 1, ConBuffer_GetLine(&history, history_line), sizeof(key_line) - 1); key_linepos = (int)strlen(key_line); } } else if(history_line > 0) { --history_line; // this also does -1 -> 0, so it is good - strlcpy(key_line + 1, ConBuffer_GetLine(&history, history_line), sizeof(key_line) - 1); + dp_strlcpy(key_line + 1, ConBuffer_GetLine(&history, history_line), sizeof(key_line) - 1); key_linepos = (int)strlen(key_line); } } @@ -169,12 +171,12 @@ static void Key_History_Down(void) if(history_line < CONBUFFER_LINES_COUNT(&history) - 1) { ++history_line; - strlcpy(key_line + 1, ConBuffer_GetLine(&history, history_line), sizeof(key_line) - 1); + dp_strlcpy(key_line + 1, ConBuffer_GetLine(&history, history_line), sizeof(key_line) - 1); } else { history_line = -1; - strlcpy(key_line + 1, history_savedline, sizeof(key_line) - 1); + dp_strlcpy(key_line + 1, history_savedline, sizeof(key_line) - 1); } key_linepos = (int)strlen(key_line); @@ -183,12 +185,12 @@ static void Key_History_Down(void) static void Key_History_First(void) { if(history_line == -1) // editing the "new" line - strlcpy(history_savedline, key_line + 1, sizeof(history_savedline)); + dp_strlcpy(history_savedline, key_line + 1, sizeof(history_savedline)); if (CONBUFFER_LINES_COUNT(&history) > 0) { history_line = 0; - strlcpy(key_line + 1, ConBuffer_GetLine(&history, history_line), sizeof(key_line) - 1); + dp_strlcpy(key_line + 1, ConBuffer_GetLine(&history, history_line), sizeof(key_line) - 1); key_linepos = (int)strlen(key_line); } } @@ -196,12 +198,12 @@ static void Key_History_First(void) static void Key_History_Last(void) { if(history_line == -1) // editing the "new" line - strlcpy(history_savedline, key_line + 1, sizeof(history_savedline)); + dp_strlcpy(history_savedline, key_line + 1, sizeof(history_savedline)); if (CONBUFFER_LINES_COUNT(&history) > 0) { history_line = CONBUFFER_LINES_COUNT(&history) - 1; - strlcpy(key_line + 1, ConBuffer_GetLine(&history, history_line), sizeof(key_line) - 1); + dp_strlcpy(key_line + 1, ConBuffer_GetLine(&history, history_line), sizeof(key_line) - 1); key_linepos = (int)strlen(key_line); } } @@ -214,11 +216,11 @@ static void Key_History_Find_Backwards(void) size_t digits = strlen(va(vabuf, sizeof(vabuf), "%i", HIST_MAXLINES)); if (history_line == -1) // editing the "new" line - strlcpy(history_savedline, key_line + 1, sizeof(history_savedline)); + dp_strlcpy(history_savedline, key_line + 1, sizeof(history_savedline)); if (strcmp(key_line + 1, history_searchstring)) // different string? Start a new search { - strlcpy(history_searchstring, key_line + 1, sizeof(history_searchstring)); + dp_strlcpy(history_searchstring, key_line + 1, sizeof(history_searchstring)); i = CONBUFFER_LINES_COUNT(&history) - 1; } else if (history_line == -1) @@ -253,7 +255,7 @@ static void Key_History_Find_Forwards(void) if (strcmp(key_line + 1, history_searchstring)) // different string? Start a new search { - strlcpy(history_searchstring, key_line + 1, sizeof(history_searchstring)); + dp_strlcpy(history_searchstring, key_line + 1, sizeof(history_searchstring)); i = 0; } else i = history_line + 1; @@ -663,7 +665,7 @@ static const keyname_t keynames[] = { ============================================================================== */ -int Key_ClearEditLine(qboolean is_console) +int Key_ClearEditLine(qbool is_console) { if (is_console) { @@ -694,11 +696,11 @@ Interactive line editing and console scrollback ==================== */ -int chat_mode; // 0 for say, 1 for say_team, -1 for command +signed char chat_mode; // 0 for say, 1 for say_team, -1 for command char chat_buffer[MAX_INPUTLINE]; int chat_bufferpos = 0; -int Key_AddChar(int unicode, qboolean is_console) +int Key_AddChar(int unicode, qbool is_console) { char *line; char buf[16]; @@ -745,7 +747,7 @@ int Key_AddChar(int unicode, qboolean is_console) // returns -1 if no key has been recognized // returns linepos (>= 0) otherwise // if is_console is true can modify key_line (doesn't change key_linepos) -int Key_Parse_CommonKeys(cmd_state_t *cmd, qboolean is_console, int key, int unicode) +int Key_Parse_CommonKeys(cmd_state_t *cmd, qbool is_console, int key, int unicode) { char *line; int linepos, linestart; @@ -768,7 +770,7 @@ int Key_Parse_CommonKeys(cmd_state_t *cmd, qboolean is_console, int key, int uni if ((key == 'v' && KM_CTRL) || ((key == K_INS || key == K_KP_INS) && KM_SHIFT)) { char *cbd, *p; - if ((cbd = Sys_GetClipboardData()) != 0) + if ((cbd = Sys_SDL_GetClipboardData()) != 0) { int i; #if 1 @@ -782,7 +784,8 @@ int Key_Parse_CommonKeys(cmd_state_t *cmd, qboolean is_console, int key, int uni } else if (*p == '\n' || *p == '\r' || *p == '\b') *p++ = ';'; - p++; + else + p++; } #else strtok(cbd, "\n\r\b"); @@ -840,7 +843,7 @@ int Key_Parse_CommonKeys(cmd_state_t *cmd, qboolean is_console, int key, int uni linepos += cvar_len; // save the content of the variable in cvar_str - cvar_str = Cvar_VariableString(&cvars_all, cvar, CVAR_CLIENT | CVAR_SERVER); + cvar_str = Cvar_VariableString(&cvars_all, cvar, CF_CLIENT | CF_SERVER); cvar_str_len = (int)strlen(cvar_str); if (cvar_str_len==0) return linepos; @@ -948,7 +951,7 @@ int Key_Parse_CommonKeys(cmd_state_t *cmd, qboolean is_console, int key, int uni { // hide ']' from u8_prevbyte otherwise it could go out of bounds int newpos = (int)u8_prevbyte(line + linestart, linepos - linestart) + linestart; - strlcpy(line + newpos, line + linepos, linesize + 1 - linepos); + dp_strlcpy(line + newpos, line + linepos, linesize + 1 - linepos); linepos = newpos; } return linepos; @@ -1097,8 +1100,7 @@ static int Key_Convert_NumPadKey(int key) return key; } -static void -Key_Console(cmd_state_t *cmd, int key, int unicode) +static void Key_Console(cmd_state_t *cmd, int key, int unicode) { int linepos; @@ -1120,8 +1122,9 @@ Key_Console(cmd_state_t *cmd, int key, int unicode) if ((key == K_ENTER || key == K_KP_ENTER) && KM_NONE) { - Cbuf_AddText (cmd, key_line+1); // skip the ] - Cbuf_AddText (cmd, "\n"); + // bones_was_here: prepending allows a loop such as `alias foo "bar; wait; foo"; foo` + // to be broken with an alias or unalias command + Cbuf_InsertText(cmd, key_line+1); // skip the ] Key_History_Push(); key_linepos = Key_ClearEditLine(true); // force an update, because the command may take some time @@ -1278,7 +1281,7 @@ Key_Console(cmd_state_t *cmd, int key, int unicode) // text zoom reset if ((key == '0' || key == K_KP_INS) && KM_CTRL) { - Cvar_SetValueQuick(&con_textsize, atoi(Cvar_VariableDefString(&cvars_all, "con_textsize", CVAR_CLIENT | CVAR_SERVER))); + Cvar_SetValueQuick(&con_textsize, atoi(Cvar_VariableDefString(&cvars_all, "con_textsize", CF_CLIENT | CF_SERVER))); return; } } @@ -1305,9 +1308,9 @@ Key_Message (cmd_state_t *cmd, int key, int ascii) if (key == K_ENTER || key == K_KP_ENTER || ascii == 10 || ascii == 13) { if(chat_mode < 0) - Cmd_ExecuteString(cmd, chat_buffer, src_command, true); // not Cbuf_AddText to allow semiclons in args; however, this allows no variables then. Use aliases! + Cmd_ExecuteString(cmd, chat_buffer, strlen(chat_buffer), src_local, true); // not Cbuf_AddText to allow semiclons in args; however, this allows no variables then. Use aliases! else - Cmd_ForwardStringToServer(va(vabuf, sizeof(vabuf), "%s %s", chat_mode ? "say_team" : "say ", chat_buffer)); + CL_ForwardToServer(va(vabuf, sizeof(vabuf), "%s %s", chat_mode ? "say_team" : "say ", chat_buffer)); key_dest = key_game; chat_bufferpos = Key_ClearEditLine(false); @@ -1350,6 +1353,7 @@ the K_* names are matched up. int Key_StringToKeynum (const char *str) { + Uchar ch; const keyname_t *kn; if (!str || !str[0]) @@ -1361,7 +1365,11 @@ Key_StringToKeynum (const char *str) if (!strcasecmp (str, kn->name)) return kn->keynum; } - return -1; + + // non-ascii keys are Unicode codepoints, so give the character if it's valid; + // error message have more than one character, don't allow it + ch = u8_getnchar(str, &str, 3); + return (ch == 0 || *str != 0) ? -1 : (int)ch; } /* @@ -1386,13 +1394,9 @@ Key_KeynumToString (int keynum, char *tinystr, size_t tinystrlength) return kn->name; // if it is printable, output it as a single character - if (keynum > 32 && keynum < 256) + if (keynum > 32) { - if (tinystrlength >= 2) - { - tinystr[0] = keynum; - tinystr[1] = 0; - } + u8_fromchar(keynum, tinystr, tinystrlength); return tinystr; } @@ -1401,7 +1405,7 @@ Key_KeynumToString (int keynum, char *tinystr, size_t tinystrlength) } -qboolean +qbool Key_SetBinding (int keynum, int bindmap, const char *binding) { char *newbinding; @@ -1436,7 +1440,7 @@ void Key_GetBindMap(int *fg, int *bg) *bg = key_bmap2; } -qboolean Key_SetBindMap(int fg, int bg) +qbool Key_SetBindMap(int fg, int bg) { if(fg >= MAX_BINDMAPS) return false; @@ -1512,9 +1516,9 @@ Key_In_Bind_f(cmd_state_t *cmd) // copy the rest of the command line line[0] = 0; // start out with a null string for (i = 3; i < c; i++) { - strlcat (line, Cmd_Argv(cmd, i), sizeof (line)); + dp_strlcat (line, Cmd_Argv(cmd, i), sizeof (line)); if (i != (c - 1)) - strlcat (line, " ", sizeof (line)); + dp_strlcat (line, " ", sizeof (line)); } if(!Key_SetBinding (b, m, line)) @@ -1585,7 +1589,7 @@ static void Key_PrintBindList(int j) { char bindbuf[MAX_INPUTLINE]; - char tinystr[2]; + char tinystr[TINYSTR_LEN]; const char *p; int i; @@ -1596,9 +1600,9 @@ Key_PrintBindList(int j) { Cmd_QuoteString(bindbuf, sizeof(bindbuf), p, "\"\\", false); if (j == 0) - Con_Printf("^2%s ^7= \"%s\"\n", Key_KeynumToString (i, tinystr, sizeof(tinystr)), bindbuf); + Con_Printf("^2%s ^7= \"%s\"\n", Key_KeynumToString (i, tinystr, TINYSTR_LEN), bindbuf); else - Con_Printf("^3bindmap %d: ^2%s ^7= \"%s\"\n", j, Key_KeynumToString (i, tinystr, sizeof(tinystr)), bindbuf); + Con_Printf("^3bindmap %d: ^2%s ^7= \"%s\"\n", j, Key_KeynumToString (i, tinystr, TINYSTR_LEN), bindbuf); } } } @@ -1659,9 +1663,9 @@ Key_Bind_f(cmd_state_t *cmd) // copy the rest of the command line line[0] = 0; // start out with a null string for (i = 2; i < c; i++) { - strlcat (line, Cmd_Argv(cmd, i), sizeof (line)); + dp_strlcat (line, Cmd_Argv(cmd, i), sizeof (line)); if (i != (c - 1)) - strlcat (line, " ", sizeof (line)); + dp_strlcat (line, " ", sizeof (line)); } if(!Key_SetBinding (b, 0, line)) @@ -1678,7 +1682,7 @@ Key_WriteBindings (qfile_t *f) { int i, j; char bindbuf[MAX_INPUTLINE]; - char tinystr[2]; + char tinystr[TINYSTR_LEN]; const char *p; // Override default binds @@ -1693,9 +1697,9 @@ Key_WriteBindings (qfile_t *f) { Cmd_QuoteString(bindbuf, sizeof(bindbuf), p, "\"\\", false); // don't need to escape $ because cvars are not expanded inside bind if (j == 0) - FS_Printf(f, "bind %s \"%s\"\n", Key_KeynumToString (i, tinystr, sizeof(tinystr)), bindbuf); + FS_Printf(f, "bind %s \"%s\"\n", Key_KeynumToString (i, tinystr, TINYSTR_LEN), bindbuf); else - FS_Printf(f, "in_bind %d %s \"%s\"\n", j, Key_KeynumToString (i, tinystr, sizeof(tinystr)), bindbuf); + FS_Printf(f, "in_bind %d %s \"%s\"\n", j, Key_KeynumToString (i, tinystr, TINYSTR_LEN), bindbuf); } } } @@ -1711,18 +1715,18 @@ Key_Init (void) // // register our functions // - Cmd_AddCommand(CMD_CLIENT, "in_bind", Key_In_Bind_f, "binds a command to the specified key in the selected bindmap"); - Cmd_AddCommand(CMD_CLIENT, "in_unbind", Key_In_Unbind_f, "removes command on the specified key in the selected bindmap"); - Cmd_AddCommand(CMD_CLIENT, "in_bindlist", Key_In_BindList_f, "bindlist: displays bound keys for all bindmaps, or the given bindmap"); - Cmd_AddCommand(CMD_CLIENT, "in_bindmap", Key_In_Bindmap_f, "selects active foreground and background (used only if a key is not bound in the foreground) bindmaps for typing"); - Cmd_AddCommand(CMD_CLIENT, "in_releaseall", Key_ReleaseAll_f, "releases all currently pressed keys (debug command)"); + Cmd_AddCommand(CF_CLIENT, "in_bind", Key_In_Bind_f, "binds a command to the specified key in the selected bindmap"); + Cmd_AddCommand(CF_CLIENT, "in_unbind", Key_In_Unbind_f, "removes command on the specified key in the selected bindmap"); + Cmd_AddCommand(CF_CLIENT, "in_bindlist", Key_In_BindList_f, "bindlist: displays bound keys for all bindmaps, or the given bindmap"); + Cmd_AddCommand(CF_CLIENT, "in_bindmap", Key_In_Bindmap_f, "selects active foreground and background (used only if a key is not bound in the foreground) bindmaps for typing"); + Cmd_AddCommand(CF_CLIENT, "in_releaseall", Key_ReleaseAll_f, "releases all currently pressed keys (debug command)"); - Cmd_AddCommand(CMD_CLIENT, "bind", Key_Bind_f, "binds a command to the specified key in bindmap 0"); - Cmd_AddCommand(CMD_CLIENT, "unbind", Key_Unbind_f, "removes a command on the specified key in bindmap 0"); - Cmd_AddCommand(CMD_CLIENT, "bindlist", Key_BindList_f, "bindlist: displays bound keys for bindmap 0 bindmaps"); - Cmd_AddCommand(CMD_CLIENT, "unbindall", Key_Unbindall_f, "removes all commands from all keys in all bindmaps (leaving only shift-escape and escape)"); + Cmd_AddCommand(CF_CLIENT, "bind", Key_Bind_f, "binds a command to the specified key in bindmap 0"); + Cmd_AddCommand(CF_CLIENT, "unbind", Key_Unbind_f, "removes a command on the specified key in bindmap 0"); + Cmd_AddCommand(CF_CLIENT, "bindlist", Key_BindList_f, "bindlist: displays bound keys for bindmap 0 bindmaps"); + Cmd_AddCommand(CF_CLIENT, "unbindall", Key_Unbindall_f, "removes all commands from all keys in all bindmaps (leaving only shift-escape and escape)"); - Cmd_AddCommand(CMD_CLIENT, "history", Key_History_f, "prints the history of executed commands (history X prints the last X entries, history -c clears the whole history)"); + Cmd_AddCommand(CF_CLIENT, "history", Key_History_f, "prints the history of executed commands (history X prints the last X entries, history -c clears the whole history)"); Cvar_RegisterVariable (&con_closeontoggleconsole); } @@ -1794,14 +1798,14 @@ typedef struct eventqueueitem_s { int key; int ascii; - qboolean down; + qbool down; } eventqueueitem_t; static int events_blocked = 0; static eventqueueitem_t eventqueue[32]; static unsigned eventqueue_idx = 0; -static void Key_EventQueue_Add(int key, int ascii, qboolean down) +static void Key_EventQueue_Add(int key, int ascii, qbool down) { if(eventqueue_idx < sizeof(eventqueue) / sizeof(*eventqueue)) { @@ -1829,11 +1833,11 @@ void Key_EventQueue_Unblock(void) } void -Key_Event (int key, int ascii, qboolean down) +Key_Event (int key, int ascii, qbool down) { - cmd_state_t *cmd = &cmd_client; + cmd_state_t *cmd = cmd_local; const char *bind; - qboolean q; + qbool q; keydest_t keydest = key_dest; char vabuf[1024]; @@ -1909,7 +1913,7 @@ Key_Event (int key, int ascii, qboolean down) { if(down) { - Con_ToggleConsole_f(&cmd_client); + Con_ToggleConsole_f(cmd_local); tbl_keydest[key] = key_void; // esc release should go nowhere (especially not to key_menu or key_game) } return; @@ -1928,7 +1932,7 @@ Key_Event (int key, int ascii, qboolean down) #endif } else - Con_ToggleConsole_f(&cmd_client); + Con_ToggleConsole_f(cmd_local); } break; @@ -1969,14 +1973,14 @@ Key_Event (int key, int ascii, qboolean down) if(keydown[key] == 1 && down) { // button commands add keynum as a parm + // prepend to avoid delays from `wait` commands added by other sources if (bind[0] == '+') - Cbuf_AddText (cmd, va(vabuf, sizeof(vabuf), "%s %i\n", bind, key)); + Cbuf_InsertText(cmd, va(vabuf, sizeof(vabuf), "%s %i\n", bind, key)); else - { - Cbuf_AddText (cmd, bind); - Cbuf_AddText (cmd, "\n"); - } - } else if(bind[0] == '+' && !down && keydown[key] == 0) + Cbuf_InsertText(cmd, bind); + } + else if(bind[0] == '+' && !down && keydown[key] == 0) + // append -bind to ensure it's after the +bind in case they arrive in the same frame Cbuf_AddText(cmd, va(vabuf, sizeof(vabuf), "-%s %i\n", bind + 1, key)); } return; @@ -1992,11 +1996,11 @@ Key_Event (int key, int ascii, qboolean down) // (special exemption for german keyboard layouts) if (con_closeontoggleconsole.integer && bind && !strncmp(bind, "toggleconsole", strlen("toggleconsole")) && (key_consoleactive & KEY_CONSOLEACTIVE_USER) && (con_closeontoggleconsole.integer >= ((ascii != STRING_COLOR_TAG) ? 2 : 3) || key_linepos == 1)) { - Con_ToggleConsole_f(&cmd_client); + Con_ToggleConsole_f(cmd_local); return; } - if (COM_CheckParm ("-noconsole")) + if (Sys_CheckParm ("-noconsole")) return; // only allow the key bind to turn off console Key_Console (cmd, key, ascii); @@ -2008,7 +2012,7 @@ Key_Event (int key, int ascii, qboolean down) { if (down && con_closeontoggleconsole.integer && bind && !strncmp(bind, "toggleconsole", strlen("toggleconsole")) && ascii != STRING_COLOR_TAG) { - Cbuf_AddText(cmd, "toggleconsole\n"); // Deferred to next frame so we're not sending the text event to the console. + Cbuf_InsertText(cmd, "toggleconsole\n"); // Deferred to next frame so we're not sending the text event to the console. tbl_keydest[key] = key_void; // key release should go nowhere (especially not to key_menu or key_game) return; } @@ -2050,14 +2054,14 @@ Key_Event (int key, int ascii, qboolean down) if(keydown[key] == 1 && down) { // button commands add keynum as a parm + // prepend to avoid delays from `wait` commands added by other sources if (bind[0] == '+') - Cbuf_AddText (cmd, va(vabuf, sizeof(vabuf), "%s %i\n", bind, key)); + Cbuf_InsertText(cmd, va(vabuf, sizeof(vabuf), "%s %i\n", bind, key)); else - { - Cbuf_AddText (cmd, bind); - Cbuf_AddText (cmd, "\n"); - } - } else if(bind[0] == '+' && !down && keydown[key] == 0) + Cbuf_InsertText(cmd, bind); + } + else if(bind[0] == '+' && !down && keydown[key] == 0) + // append -bind to ensure it's after the +bind in case they arrive in the same frame Cbuf_AddText(cmd, va(vabuf, sizeof(vabuf), "-%s %i\n", bind + 1, key)); } break;