X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=keys.c;h=18765a167e2c0c6c050dd6e915502c858ac1d654;hb=ccb5fe100fa4f0005123933dcdf4e9d3ad878687;hp=f01ee9f0d01d49c590bef6a8364542d7a115e529;hpb=8a853358887980224785fa5c753afb4769178251;p=xonotic%2Fdarkplaces.git diff --git a/keys.c b/keys.c index f01ee9f0..18765a16 100644 --- a/keys.c +++ b/keys.c @@ -22,6 +22,7 @@ #include "quakedef.h" #include "cl_video.h" +#include "utf8lib.h" cvar_t con_closeontoggleconsole = {CVAR_SAVE, "con_closeontoggleconsole","1", "allows toggleconsole binds to close the console as well"}; @@ -475,7 +476,7 @@ Interactive line editing and console scrollback ==================== */ static void -Key_Console (int key, int ascii) +Key_Console (int key, int unicode) { // LordHavoc: copied most of this from Q2 to improve keyboard handling switch (key) @@ -552,6 +553,7 @@ Key_Console (int key, int ascii) if (i > 0) { // terencehill: insert the clipboard text between the characters of the line + /* char *temp = (char *) Z_Malloc(MAX_INPUTLINE); cbd[i]=0; temp[0]=0; @@ -563,6 +565,12 @@ Key_Console (int key, int ascii) strlcat(key_line, temp, sizeof(key_line)); Z_Free(temp); key_linepos += i; + */ + // blub: I'm changing this to use memmove() like the rest of the code does. + cbd[i] = 0; + memmove(key_line + key_linepos + i, key_line + key_linepos, sizeof(key_line) - key_linepos - i); + memcpy(key_line + key_linepos, cbd, i); + key_linepos += i; } Z_Free(cbd); } @@ -704,7 +712,8 @@ Key_Console (int key, int ascii) else if(keydown[K_SHIFT]) // move cursor to the previous character ignoring colors { int pos; - pos = key_linepos-1; + size_t inchar = 0; + pos = u8_prevbyte(key_line, key_linepos); while (pos) if(pos-1 > 0 && key_line[pos-1] == STRING_COLOR_TAG && isdigit(key_line[pos])) pos-=2; @@ -718,10 +727,14 @@ Key_Console (int key, int ascii) pos--; break; } - key_linepos = pos + 1; + // we need to move to the beginning of the character when in a wide character: + u8_charidx(key_line, pos + 1, &inchar); + key_linepos = pos + 1 - inchar; } else - key_linepos--; + { + key_linepos = u8_prevbyte(key_line, key_linepos); + } return; } @@ -730,8 +743,9 @@ Key_Console (int key, int ascii) { if (key_linepos > 1) { - strlcpy(key_line + key_linepos - 1, key_line + key_linepos, sizeof(key_line) + 1 - key_linepos); - key_linepos--; + int newpos = u8_prevbyte(key_line, key_linepos); + strlcpy(key_line + newpos, key_line + key_linepos, sizeof(key_line) + 1 - key_linepos); + key_linepos = newpos; } return; } @@ -742,7 +756,7 @@ Key_Console (int key, int ascii) size_t linelen; linelen = strlen(key_line); if (key_linepos < (int)linelen) - memmove(key_line + key_linepos, key_line + key_linepos + 1, linelen - key_linepos); + memmove(key_line + key_linepos, key_line + key_linepos + u8_bytelen(key_line + key_linepos, 1), linelen - key_linepos); return; } @@ -796,7 +810,7 @@ Key_Console (int key, int ascii) // skip the char if (key_line[pos] == STRING_COLOR_TAG && key_line[pos+1] == STRING_COLOR_TAG) // consider ^^ as a character pos++; - pos++; + pos += u8_bytelen(key_line + pos, 1); // now go beyond all next consecutive color tags, if any if(pos < len) @@ -812,7 +826,7 @@ Key_Console (int key, int ascii) key_linepos = pos; } else - key_linepos++; + key_linepos += u8_bytelen(key_line + key_linepos, 1); return; } @@ -907,7 +921,7 @@ Key_Console (int key, int ascii) if (key == K_HOME || key == K_KP_HOME) { if (keydown[K_CTRL]) - con_backscroll = INT_MAX; + con_backscroll = CON_TEXTSIZE; else key_linepos = 1; return; @@ -923,22 +937,31 @@ Key_Console (int key, int ascii) } // non printable - if (ascii < 32) + if (unicode < 32) return; if (key_linepos < MAX_INPUTLINE-1) { + char buf[16]; int len; + int blen; + blen = u8_fromchar(unicode, buf, sizeof(buf)); + if (!blen) + return; 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_line[key_linepos + 1], &key_line[key_linepos], len); + //memmove(&key_line[key_linepos + u8_bytelen(key_line + key_linepos, 1)], &key_line[key_linepos], len); + memmove(&key_line[key_linepos + blen], &key_line[key_linepos], len); } - key_line[key_linepos] = ascii; - key_linepos++; + memcpy(key_line + key_linepos, buf, blen); + key_linepos += blen; + //key_linepos += u8_fromchar(unicode, key_line + key_linepos, sizeof(key_line) - key_linepos - 1); + //key_line[key_linepos] = ascii; + //key_linepos++; } } @@ -953,7 +976,6 @@ extern int Nicks_CompleteChatLine(char *buffer, size_t size, unsigned int pos); static void Key_Message (int key, int ascii) { - if (key == K_ENTER || ascii == 10 || ascii == 13) { if(chat_mode < 0) @@ -978,7 +1000,7 @@ Key_Message (int key, int ascii) if (key == K_BACKSPACE) { if (chat_bufferlen) { - chat_bufferlen--; + chat_bufferlen = u8_prevbyte(chat_buffer, chat_bufferlen); chat_buffer[chat_bufferlen] = 0; } return; @@ -995,8 +1017,10 @@ Key_Message (int key, int ascii) if (!ascii) return; // non printable - chat_buffer[chat_bufferlen++] = ascii; - chat_buffer[chat_bufferlen] = 0; + chat_bufferlen += u8_fromchar(ascii, chat_buffer+chat_bufferlen, sizeof(chat_buffer) - chat_bufferlen - 1); + + //chat_buffer[chat_bufferlen++] = ascii; + //chat_buffer[chat_bufferlen] = 0; } //============================================================================ @@ -1061,14 +1085,16 @@ Key_KeynumToString (int keynum) } -void +qboolean Key_SetBinding (int keynum, int bindmap, const char *binding) { char *newbinding; size_t l; if (keynum == -1 || keynum >= MAX_KEYS) - return; + return false; + if ((bindmap < 0) || (bindmap >= MAX_BINDMAPS)) + return false; // free old bindings if (keybindings[bindmap][keynum]) { @@ -1076,13 +1102,35 @@ Key_SetBinding (int keynum, int bindmap, const char *binding) keybindings[bindmap][keynum] = NULL; } if(!binding[0]) // make "" binds be removed --blub - return; + return true; // allocate memory for new binding l = strlen (binding); newbinding = (char *)Z_Malloc (l + 1); memcpy (newbinding, binding, l + 1); newbinding[l] = 0; keybindings[bindmap][keynum] = newbinding; + return true; +} + +void Key_GetBindMap(int *fg, int *bg) +{ + if(fg) + *fg = key_bmap; + if(bg) + *bg = key_bmap2; +} + +qboolean Key_SetBindMap(int fg, int bg) +{ + if(fg >= MAX_BINDMAPS) + return false; + if(bg >= MAX_BINDMAPS) + return false; + if(fg >= 0) + key_bmap = fg; + if(bg >= 0) + key_bmap2 = bg; + return true; } static void @@ -1097,7 +1145,7 @@ Key_In_Unbind_f (void) } m = strtol(Cmd_Argv (1), &errchar, 0); - if ((m < 0) || (m >= 8) || (errchar && *errchar)) { + if ((m < 0) || (m >= MAX_BINDMAPS) || (errchar && *errchar)) { Con_Printf("%s isn't a valid bindmap\n", Cmd_Argv(1)); return; } @@ -1108,7 +1156,8 @@ Key_In_Unbind_f (void) return; } - Key_SetBinding (b, m, ""); + if(!Key_SetBinding (b, m, "")) + Con_Printf("Key_SetBinding failed for unknown reason\n"); } static void @@ -1126,7 +1175,7 @@ Key_In_Bind_f (void) } m = strtol(Cmd_Argv (1), &errchar, 0); - if ((m < 0) || (m >= 8) || (errchar && *errchar)) { + if ((m < 0) || (m >= MAX_BINDMAPS) || (errchar && *errchar)) { Con_Printf("%s isn't a valid bindmap\n", Cmd_Argv(1)); return; } @@ -1152,7 +1201,8 @@ Key_In_Bind_f (void) strlcat (cmd, " ", sizeof (cmd)); } - Key_SetBinding (b, m, cmd); + if(!Key_SetBinding (b, m, cmd)) + Con_Printf("Key_SetBinding failed for unknown reason\n"); } static void @@ -1169,13 +1219,13 @@ Key_In_Bindmap_f (void) } m1 = strtol(Cmd_Argv (1), &errchar, 0); - if ((m1 < 0) || (m1 >= 8) || (errchar && *errchar)) { + if ((m1 < 0) || (m1 >= MAX_BINDMAPS) || (errchar && *errchar)) { Con_Printf("%s isn't a valid bindmap\n", Cmd_Argv(1)); return; } m2 = strtol(Cmd_Argv (2), &errchar, 0); - if ((m2 < 0) || (m2 >= 8) || (errchar && *errchar)) { + if ((m2 < 0) || (m2 >= MAX_BINDMAPS) || (errchar && *errchar)) { Con_Printf("%s isn't a valid bindmap\n", Cmd_Argv(2)); return; } @@ -1200,7 +1250,8 @@ Key_Unbind_f (void) return; } - Key_SetBinding (b, 0, ""); + if(!Key_SetBinding (b, 0, "")) + Con_Printf("Key_SetBinding failed for unknown reason\n"); } static void @@ -1208,7 +1259,7 @@ Key_Unbindall_f (void) { int i, j; - for (j = 0; j < 8; j++) + for (j = 0; j < MAX_BINDMAPS; j++) for (i = 0; i < (int)(sizeof(keybindings[0])/sizeof(keybindings[0][0])); i++) if (keybindings[j][i]) Key_SetBinding (i, j, ""); @@ -1244,7 +1295,7 @@ Key_In_BindList_f (void) if(Cmd_Argc() >= 2) { m = strtol(Cmd_Argv(1), &errchar, 0); - if ((m < 0) || (m >= 8) || (errchar && *errchar)) { + if ((m < 0) || (m >= MAX_BINDMAPS) || (errchar && *errchar)) { Con_Printf("%s isn't a valid bindmap\n", Cmd_Argv(1)); return; } @@ -1296,7 +1347,8 @@ Key_Bind_f (void) strlcat (cmd, " ", sizeof (cmd)); } - Key_SetBinding (b, 0, cmd); + if(!Key_SetBinding (b, 0, cmd)) + Con_Printf("Key_SetBinding failed for unknown reason\n"); } /* @@ -1359,17 +1411,54 @@ Key_Shutdown (void) Key_History_Shutdown(); } -const char *Key_GetBind (int key) +const char *Key_GetBind (int key, int bindmap) { const char *bind; if (key < 0 || key >= MAX_KEYS) return NULL; - bind = keybindings[key_bmap][key]; - if (!bind) - bind = keybindings[key_bmap2][key]; + if(bindmap >= MAX_BINDMAPS) + return NULL; + if(bindmap >= 0) + { + bind = keybindings[bindmap][key]; + } + else + { + bind = keybindings[key_bmap][key]; + if (!bind) + bind = keybindings[key_bmap2][key]; + } return bind; } +void Key_FindKeysForCommand (const char *command, int *keys, int numkeys, int bindmap) +{ + int count; + int j; + const char *b; + + for (j = 0;j < numkeys;j++) + keys[j] = -1; + + if(bindmap >= MAX_BINDMAPS) + return; + + count = 0; + + for (j = 0; j < MAX_KEYS; ++j) + { + b = Key_GetBind(j, bindmap); + if (!b) + continue; + if (!strcmp (b, command) ) + { + keys[count++] = j; + if (count == numkeys) + break; + } + } +} + qboolean CL_VM_InputEvent (qboolean down, int key, int ascii); /* @@ -1381,6 +1470,44 @@ Should NOT be called during an interrupt! static char tbl_keyascii[MAX_KEYS]; static keydest_t tbl_keydest[MAX_KEYS]; +typedef struct eventqueueitem_s +{ + int key; + int ascii; + qboolean 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) +{ + if(eventqueue_idx < sizeof(eventqueue) / sizeof(*eventqueue)) + { + eventqueue[eventqueue_idx].key = key; + eventqueue[eventqueue_idx].ascii = ascii; + eventqueue[eventqueue_idx].down = down; + ++eventqueue_idx; + } +} + +void Key_EventQueue_Block(void) +{ + // block key events until call to Unblock + events_blocked = true; +} + +void Key_EventQueue_Unblock(void) +{ + // unblocks key events again + unsigned i; + events_blocked = false; + for(i = 0; i < eventqueue_idx; ++i) + Key_Event(eventqueue[i].key, eventqueue[i].ascii, eventqueue[i].down); + eventqueue_idx = 0; +} + void Key_Event (int key, int ascii, qboolean down) { @@ -1391,13 +1518,19 @@ Key_Event (int key, int ascii, qboolean down) if (key < 0 || key >= MAX_KEYS) return; + if(events_blocked) + { + Key_EventQueue_Add(key, ascii, down); + return; + } + // get key binding bind = keybindings[key_bmap][key]; if (!bind) bind = keybindings[key_bmap2][key]; - if (developer.integer >= 1000) - Con_Printf("Key_Event(%i, '%c', %s) keydown %i bind \"%s\"\n", key, ascii, down ? "down" : "up", keydown[key], bind ? bind : ""); + if (developer_insane.integer) + Con_DPrintf("Key_Event(%i, '%c', %s) keydown %i bind \"%s\"\n", key, ascii ? ascii : '?', down ? "down" : "up", keydown[key], bind ? bind : ""); if(key_consoleactive) keydest = key_console; @@ -1468,7 +1601,7 @@ Key_Event (int key, int ascii, qboolean down) if(key_consoleactive & KEY_CONSOLEACTIVE_FORCED) { key_consoleactive &= ~KEY_CONSOLEACTIVE_USER; - MR_ToggleMenu_f (); + MR_ToggleMenu(1); } else Con_ToggleConsole_f(); @@ -1489,7 +1622,7 @@ Key_Event (int key, int ascii, qboolean down) // csqc has priority over toggle menu if it wants to (e.g. handling escape for UI stuff in-game.. :sick:) q = CL_VM_InputEvent(down, key, ascii); if (!q && down) - MR_ToggleMenu_f (); + MR_ToggleMenu(1); break; default: @@ -1499,8 +1632,9 @@ Key_Event (int key, int ascii, qboolean down) } // send function keydowns to interpreter no matter what mode is (unless the menu has specifically grabbed the keyboard, for rebinding keys) + // VorteX: Omnicide does bind F* keys if (keydest != key_menu_grabbed) - if (key >= K_F1 && key <= K_F12) + if (key >= K_F1 && key <= K_F12 && gamemode != GAME_BLOODOMNICIDE) { if (bind) {