keys.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. #include "quakedef.h"
  16. #ifdef _WINDOWS
  17. #include <windows.h>
  18. #endif
  19. /*
  20. key up events are sent even if in console mode
  21. */
  22. #define MAXCMDLINE 256
  23. char key_lines[32][MAXCMDLINE];
  24. int key_linepos;
  25. int shift_down=false;
  26. int key_lastpress;
  27. int edit_line=0;
  28. int history_line=0;
  29. keydest_t key_dest;
  30. int key_count; // incremented every key event
  31. char *keybindings[256];
  32. qboolean consolekeys[256]; // if true, can't be rebound while in console
  33. qboolean menubound[256]; // if true, can't be rebound while in menu
  34. int keyshift[256]; // key to map to if shift held down in console
  35. int key_repeats[256]; // if > 1, it is autorepeating
  36. qboolean keydown[256];
  37. typedef struct
  38. {
  39. char *name;
  40. int keynum;
  41. } keyname_t;
  42. keyname_t keynames[] =
  43. {
  44. {"TAB", K_TAB},
  45. {"ENTER", K_ENTER},
  46. {"ESCAPE", K_ESCAPE},
  47. {"SPACE", K_SPACE},
  48. {"BACKSPACE", K_BACKSPACE},
  49. {"UPARROW", K_UPARROW},
  50. {"DOWNARROW", K_DOWNARROW},
  51. {"LEFTARROW", K_LEFTARROW},
  52. {"RIGHTARROW", K_RIGHTARROW},
  53. {"ALT", K_ALT},
  54. {"CTRL", K_CTRL},
  55. {"SHIFT", K_SHIFT},
  56. {"F1", K_F1},
  57. {"F2", K_F2},
  58. {"F3", K_F3},
  59. {"F4", K_F4},
  60. {"F5", K_F5},
  61. {"F6", K_F6},
  62. {"F7", K_F7},
  63. {"F8", K_F8},
  64. {"F9", K_F9},
  65. {"F10", K_F10},
  66. {"F11", K_F11},
  67. {"F12", K_F12},
  68. {"INS", K_INS},
  69. {"DEL", K_DEL},
  70. {"PGDN", K_PGDN},
  71. {"PGUP", K_PGUP},
  72. {"HOME", K_HOME},
  73. {"END", K_END},
  74. {"MOUSE1", K_MOUSE1},
  75. {"MOUSE2", K_MOUSE2},
  76. {"MOUSE3", K_MOUSE3},
  77. {"JOY1", K_JOY1},
  78. {"JOY2", K_JOY2},
  79. {"JOY3", K_JOY3},
  80. {"JOY4", K_JOY4},
  81. {"AUX1", K_AUX1},
  82. {"AUX2", K_AUX2},
  83. {"AUX3", K_AUX3},
  84. {"AUX4", K_AUX4},
  85. {"AUX5", K_AUX5},
  86. {"AUX6", K_AUX6},
  87. {"AUX7", K_AUX7},
  88. {"AUX8", K_AUX8},
  89. {"AUX9", K_AUX9},
  90. {"AUX10", K_AUX10},
  91. {"AUX11", K_AUX11},
  92. {"AUX12", K_AUX12},
  93. {"AUX13", K_AUX13},
  94. {"AUX14", K_AUX14},
  95. {"AUX15", K_AUX15},
  96. {"AUX16", K_AUX16},
  97. {"AUX17", K_AUX17},
  98. {"AUX18", K_AUX18},
  99. {"AUX19", K_AUX19},
  100. {"AUX20", K_AUX20},
  101. {"AUX21", K_AUX21},
  102. {"AUX22", K_AUX22},
  103. {"AUX23", K_AUX23},
  104. {"AUX24", K_AUX24},
  105. {"AUX25", K_AUX25},
  106. {"AUX26", K_AUX26},
  107. {"AUX27", K_AUX27},
  108. {"AUX28", K_AUX28},
  109. {"AUX29", K_AUX29},
  110. {"AUX30", K_AUX30},
  111. {"AUX31", K_AUX31},
  112. {"AUX32", K_AUX32},
  113. {"PAUSE", K_PAUSE},
  114. {"MWHEELUP", K_MWHEELUP},
  115. {"MWHEELDOWN", K_MWHEELDOWN},
  116. {"SEMICOLON", ';'}, // because a raw semicolon seperates commands
  117. {NULL,0}
  118. };
  119. /*
  120. ==============================================================================
  121. LINE TYPING INTO THE CONSOLE
  122. ==============================================================================
  123. */
  124. qboolean CheckForCommand (void)
  125. {
  126. char command[128];
  127. char *cmd, *s;
  128. int i;
  129. s = key_lines[edit_line]+1;
  130. for (i=0 ; i<127 ; i++)
  131. if (s[i] <= ' ')
  132. break;
  133. else
  134. command[i] = s[i];
  135. command[i] = 0;
  136. cmd = Cmd_CompleteCommand (command);
  137. if (!cmd || strcmp (cmd, command))
  138. cmd = Cvar_CompleteVariable (command);
  139. if (!cmd || strcmp (cmd, command) )
  140. return false; // just a chat message
  141. return true;
  142. }
  143. void CompleteCommand (void)
  144. {
  145. char *cmd, *s;
  146. s = key_lines[edit_line]+1;
  147. if (*s == '\\' || *s == '/')
  148. s++;
  149. cmd = Cmd_CompleteCommand (s);
  150. if (!cmd)
  151. cmd = Cvar_CompleteVariable (s);
  152. if (cmd)
  153. {
  154. key_lines[edit_line][1] = '/';
  155. Q_strcpy (key_lines[edit_line]+2, cmd);
  156. key_linepos = Q_strlen(cmd)+2;
  157. key_lines[edit_line][key_linepos] = ' ';
  158. key_linepos++;
  159. key_lines[edit_line][key_linepos] = 0;
  160. return;
  161. }
  162. }
  163. /*
  164. ====================
  165. Key_Console
  166. Interactive line editing and console scrollback
  167. ====================
  168. */
  169. void Key_Console (int key)
  170. {
  171. #ifdef _WIN32
  172. char *cmd, *s;
  173. int i;
  174. HANDLE th;
  175. char *clipText, *textCopied;
  176. #endif
  177. if (key == K_ENTER)
  178. { // backslash text are commands, else chat
  179. if (key_lines[edit_line][1] == '\\' || key_lines[edit_line][1] == '/')
  180. Cbuf_AddText (key_lines[edit_line]+2); // skip the >
  181. else if (CheckForCommand())
  182. Cbuf_AddText (key_lines[edit_line]+1); // valid command
  183. else
  184. { // convert to a chat message
  185. if (cls.state >= ca_connected)
  186. Cbuf_AddText ("say ");
  187. Cbuf_AddText (key_lines[edit_line]+1); // skip the >
  188. }
  189. Cbuf_AddText ("\n");
  190. Con_Printf ("%s\n",key_lines[edit_line]);
  191. edit_line = (edit_line + 1) & 31;
  192. history_line = edit_line;
  193. key_lines[edit_line][0] = ']';
  194. key_linepos = 1;
  195. if (cls.state == ca_disconnected)
  196. SCR_UpdateScreen (); // force an update, because the command
  197. // may take some time
  198. return;
  199. }
  200. if (key == K_TAB)
  201. { // command completion
  202. CompleteCommand ();
  203. return;
  204. }
  205. if (key == K_BACKSPACE || key == K_LEFTARROW)
  206. {
  207. if (key_linepos > 1)
  208. key_linepos--;
  209. return;
  210. }
  211. if (key == K_UPARROW)
  212. {
  213. do
  214. {
  215. history_line = (history_line - 1) & 31;
  216. } while (history_line != edit_line
  217. && !key_lines[history_line][1]);
  218. if (history_line == edit_line)
  219. history_line = (edit_line+1)&31;
  220. Q_strcpy(key_lines[edit_line], key_lines[history_line]);
  221. key_linepos = Q_strlen(key_lines[edit_line]);
  222. return;
  223. }
  224. if (key == K_DOWNARROW)
  225. {
  226. if (history_line == edit_line) return;
  227. do
  228. {
  229. history_line = (history_line + 1) & 31;
  230. }
  231. while (history_line != edit_line
  232. && !key_lines[history_line][1]);
  233. if (history_line == edit_line)
  234. {
  235. key_lines[edit_line][0] = ']';
  236. key_linepos = 1;
  237. }
  238. else
  239. {
  240. Q_strcpy(key_lines[edit_line], key_lines[history_line]);
  241. key_linepos = Q_strlen(key_lines[edit_line]);
  242. }
  243. return;
  244. }
  245. if (key == K_PGUP || key==K_MWHEELUP)
  246. {
  247. con->display -= 2;
  248. return;
  249. }
  250. if (key == K_PGDN || key==K_MWHEELDOWN)
  251. {
  252. con->display += 2;
  253. if (con->display > con->current)
  254. con->display = con->current;
  255. return;
  256. }
  257. if (key == K_HOME)
  258. {
  259. con->display = con->current - con_totallines + 10;
  260. return;
  261. }
  262. if (key == K_END)
  263. {
  264. con->display = con->current;
  265. return;
  266. }
  267. #ifdef _WIN32
  268. if ((key=='V' || key=='v') && GetKeyState(VK_CONTROL)<0) {
  269. if (OpenClipboard(NULL)) {
  270. th = GetClipboardData(CF_TEXT);
  271. if (th) {
  272. clipText = GlobalLock(th);
  273. if (clipText) {
  274. textCopied = malloc(GlobalSize(th)+1);
  275. strcpy(textCopied, clipText);
  276. /* Substitutes a NULL for every token */strtok(textCopied, "\n\r\b");
  277. i = strlen(textCopied);
  278. if (i+key_linepos>=MAXCMDLINE)
  279. i=MAXCMDLINE-key_linepos;
  280. if (i>0) {
  281. textCopied[i]=0;
  282. strcat(key_lines[edit_line], textCopied);
  283. key_linepos+=i;;
  284. }
  285. free(textCopied);
  286. }
  287. GlobalUnlock(th);
  288. }
  289. CloseClipboard();
  290. return;
  291. }
  292. }
  293. #endif
  294. if (key < 32 || key > 127)
  295. return; // non printable
  296. if (key_linepos < MAXCMDLINE-1)
  297. {
  298. key_lines[edit_line][key_linepos] = key;
  299. key_linepos++;
  300. key_lines[edit_line][key_linepos] = 0;
  301. }
  302. }
  303. //============================================================================
  304. qboolean chat_team;
  305. char chat_buffer[MAXCMDLINE];
  306. int chat_bufferlen = 0;
  307. void Key_Message (int key)
  308. {
  309. if (key == K_ENTER)
  310. {
  311. if (chat_team)
  312. Cbuf_AddText ("say_team \"");
  313. else
  314. Cbuf_AddText ("say \"");
  315. Cbuf_AddText(chat_buffer);
  316. Cbuf_AddText("\"\n");
  317. key_dest = key_game;
  318. chat_bufferlen = 0;
  319. chat_buffer[0] = 0;
  320. return;
  321. }
  322. if (key == K_ESCAPE)
  323. {
  324. key_dest = key_game;
  325. chat_bufferlen = 0;
  326. chat_buffer[0] = 0;
  327. return;
  328. }
  329. if (key < 32 || key > 127)
  330. return; // non printable
  331. if (key == K_BACKSPACE)
  332. {
  333. if (chat_bufferlen)
  334. {
  335. chat_bufferlen--;
  336. chat_buffer[chat_bufferlen] = 0;
  337. }
  338. return;
  339. }
  340. if (chat_bufferlen == sizeof(chat_buffer)-1)
  341. return; // all full
  342. chat_buffer[chat_bufferlen++] = key;
  343. chat_buffer[chat_bufferlen] = 0;
  344. }
  345. //============================================================================
  346. /*
  347. ===================
  348. Key_StringToKeynum
  349. Returns a key number to be used to index keybindings[] by looking at
  350. the given string. Single ascii characters return themselves, while
  351. the K_* names are matched up.
  352. ===================
  353. */
  354. int Key_StringToKeynum (char *str)
  355. {
  356. keyname_t *kn;
  357. if (!str || !str[0])
  358. return -1;
  359. if (!str[1])
  360. return str[0];
  361. for (kn=keynames ; kn->name ; kn++)
  362. {
  363. if (!Q_strcasecmp(str,kn->name))
  364. return kn->keynum;
  365. }
  366. return -1;
  367. }
  368. /*
  369. ===================
  370. Key_KeynumToString
  371. Returns a string (either a single ascii char, or a K_* name) for the
  372. given keynum.
  373. FIXME: handle quote special (general escape sequence?)
  374. ===================
  375. */
  376. char *Key_KeynumToString (int keynum)
  377. {
  378. keyname_t *kn;
  379. static char tinystr[2];
  380. if (keynum == -1)
  381. return "<KEY NOT FOUND>";
  382. if (keynum > 32 && keynum < 127)
  383. { // printable ascii
  384. tinystr[0] = keynum;
  385. tinystr[1] = 0;
  386. return tinystr;
  387. }
  388. for (kn=keynames ; kn->name ; kn++)
  389. if (keynum == kn->keynum)
  390. return kn->name;
  391. return "<UNKNOWN KEYNUM>";
  392. }
  393. /*
  394. ===================
  395. Key_SetBinding
  396. ===================
  397. */
  398. void Key_SetBinding (int keynum, char *binding)
  399. {
  400. char *new;
  401. int l;
  402. if (keynum == -1)
  403. return;
  404. // free old bindings
  405. if (keybindings[keynum])
  406. {
  407. Z_Free (keybindings[keynum]);
  408. keybindings[keynum] = NULL;
  409. }
  410. // allocate memory for new binding
  411. l = Q_strlen (binding);
  412. new = Z_Malloc (l+1);
  413. Q_strcpy (new, binding);
  414. new[l] = 0;
  415. keybindings[keynum] = new;
  416. }
  417. /*
  418. ===================
  419. Key_Unbind_f
  420. ===================
  421. */
  422. void Key_Unbind_f (void)
  423. {
  424. int b;
  425. if (Cmd_Argc() != 2)
  426. {
  427. Con_Printf ("unbind <key> : remove commands from a key\n");
  428. return;
  429. }
  430. b = Key_StringToKeynum (Cmd_Argv(1));
  431. if (b==-1)
  432. {
  433. Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1));
  434. return;
  435. }
  436. Key_SetBinding (b, "");
  437. }
  438. void Key_Unbindall_f (void)
  439. {
  440. int i;
  441. for (i=0 ; i<256 ; i++)
  442. if (keybindings[i])
  443. Key_SetBinding (i, "");
  444. }
  445. /*
  446. ===================
  447. Key_Bind_f
  448. ===================
  449. */
  450. void Key_Bind_f (void)
  451. {
  452. int i, c, b;
  453. char cmd[1024];
  454. c = Cmd_Argc();
  455. if (c != 2 && c != 3)
  456. {
  457. Con_Printf ("bind <key> [command] : attach a command to a key\n");
  458. return;
  459. }
  460. b = Key_StringToKeynum (Cmd_Argv(1));
  461. if (b==-1)
  462. {
  463. Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1));
  464. return;
  465. }
  466. if (c == 2)
  467. {
  468. if (keybindings[b])
  469. Con_Printf ("\"%s\" = \"%s\"\n", Cmd_Argv(1), keybindings[b] );
  470. else
  471. Con_Printf ("\"%s\" is not bound\n", Cmd_Argv(1) );
  472. return;
  473. }
  474. // copy the rest of the command line
  475. cmd[0] = 0; // start out with a null string
  476. for (i=2 ; i< c ; i++)
  477. {
  478. strcat (cmd, Cmd_Argv(i));
  479. if (i != (c-1))
  480. strcat (cmd, " ");
  481. }
  482. Key_SetBinding (b, cmd);
  483. }
  484. /*
  485. ============
  486. Key_WriteBindings
  487. Writes lines containing "bind key value"
  488. ============
  489. */
  490. void Key_WriteBindings (FILE *f)
  491. {
  492. int i;
  493. for (i=0 ; i<256 ; i++)
  494. if (keybindings[i])
  495. fprintf (f, "bind %s \"%s\"\n", Key_KeynumToString(i), keybindings[i]);
  496. }
  497. /*
  498. ===================
  499. Key_Init
  500. ===================
  501. */
  502. void Key_Init (void)
  503. {
  504. int i;
  505. for (i=0 ; i<32 ; i++)
  506. {
  507. key_lines[i][0] = ']';
  508. key_lines[i][1] = 0;
  509. }
  510. key_linepos = 1;
  511. //
  512. // init ascii characters in console mode
  513. //
  514. for (i=32 ; i<128 ; i++)
  515. consolekeys[i] = true;
  516. consolekeys[K_ENTER] = true;
  517. consolekeys[K_TAB] = true;
  518. consolekeys[K_LEFTARROW] = true;
  519. consolekeys[K_RIGHTARROW] = true;
  520. consolekeys[K_UPARROW] = true;
  521. consolekeys[K_DOWNARROW] = true;
  522. consolekeys[K_BACKSPACE] = true;
  523. consolekeys[K_HOME] = true;
  524. consolekeys[K_END] = true;
  525. consolekeys[K_PGUP] = true;
  526. consolekeys[K_PGDN] = true;
  527. consolekeys[K_SHIFT] = true;
  528. consolekeys[K_MWHEELUP] = true;
  529. consolekeys[K_MWHEELDOWN] = true;
  530. consolekeys['`'] = false;
  531. consolekeys['~'] = false;
  532. for (i=0 ; i<256 ; i++)
  533. keyshift[i] = i;
  534. for (i='a' ; i<='z' ; i++)
  535. keyshift[i] = i - 'a' + 'A';
  536. keyshift['1'] = '!';
  537. keyshift['2'] = '@';
  538. keyshift['3'] = '#';
  539. keyshift['4'] = '$';
  540. keyshift['5'] = '%';
  541. keyshift['6'] = '^';
  542. keyshift['7'] = '&';
  543. keyshift['8'] = '*';
  544. keyshift['9'] = '(';
  545. keyshift['0'] = ')';
  546. keyshift['-'] = '_';
  547. keyshift['='] = '+';
  548. keyshift[','] = '<';
  549. keyshift['.'] = '>';
  550. keyshift['/'] = '?';
  551. keyshift[';'] = ':';
  552. keyshift['\''] = '"';
  553. keyshift['['] = '{';
  554. keyshift[']'] = '}';
  555. keyshift['`'] = '~';
  556. keyshift['\\'] = '|';
  557. menubound[K_ESCAPE] = true;
  558. for (i=0 ; i<12 ; i++)
  559. menubound[K_F1+i] = true;
  560. //
  561. // register our functions
  562. //
  563. Cmd_AddCommand ("bind",Key_Bind_f);
  564. Cmd_AddCommand ("unbind",Key_Unbind_f);
  565. Cmd_AddCommand ("unbindall",Key_Unbindall_f);
  566. }
  567. /*
  568. ===================
  569. Key_Event
  570. Called by the system between frames for both key up and key down events
  571. Should NOT be called during an interrupt!
  572. ===================
  573. */
  574. void Key_Event (int key, qboolean down)
  575. {
  576. char *kb;
  577. char cmd[1024];
  578. // Con_Printf ("%i : %i\n", key, down); //@@@
  579. keydown[key] = down;
  580. if (!down)
  581. key_repeats[key] = 0;
  582. key_lastpress = key;
  583. key_count++;
  584. if (key_count <= 0)
  585. {
  586. return; // just catching keys for Con_NotifyBox
  587. }
  588. // update auto-repeat status
  589. if (down)
  590. {
  591. key_repeats[key]++;
  592. if (key != K_BACKSPACE
  593. && key != K_PAUSE
  594. && key != K_PGUP
  595. && key != K_PGDN
  596. && key_repeats[key] > 1)
  597. return; // ignore most autorepeats
  598. if (key >= 200 && !keybindings[key])
  599. Con_Printf ("%s is unbound, hit F4 to set.\n", Key_KeynumToString (key) );
  600. }
  601. if (key == K_SHIFT)
  602. shift_down = down;
  603. //
  604. // handle escape specialy, so the user can never unbind it
  605. //
  606. if (key == K_ESCAPE)
  607. {
  608. if (!down)
  609. return;
  610. switch (key_dest)
  611. {
  612. case key_message:
  613. Key_Message (key);
  614. break;
  615. case key_menu:
  616. M_Keydown (key);
  617. break;
  618. case key_game:
  619. case key_console:
  620. M_ToggleMenu_f ();
  621. break;
  622. default:
  623. Sys_Error ("Bad key_dest");
  624. }
  625. return;
  626. }
  627. //
  628. // key up events only generate commands if the game key binding is
  629. // a button command (leading + sign). These will occur even in console mode,
  630. // to keep the character from continuing an action started before a console
  631. // switch. Button commands include the kenum as a parameter, so multiple
  632. // downs can be matched with ups
  633. //
  634. if (!down)
  635. {
  636. kb = keybindings[key];
  637. if (kb && kb[0] == '+')
  638. {
  639. sprintf (cmd, "-%s %i\n", kb+1, key);
  640. Cbuf_AddText (cmd);
  641. }
  642. if (keyshift[key] != key)
  643. {
  644. kb = keybindings[keyshift[key]];
  645. if (kb && kb[0] == '+')
  646. {
  647. sprintf (cmd, "-%s %i\n", kb+1, key);
  648. Cbuf_AddText (cmd);
  649. }
  650. }
  651. return;
  652. }
  653. //
  654. // during demo playback, most keys bring up the main menu
  655. //
  656. if (cls.demoplayback && down && consolekeys[key] && key_dest == key_game)
  657. {
  658. M_ToggleMenu_f ();
  659. return;
  660. }
  661. //
  662. // if not a consolekey, send to the interpreter no matter what mode is
  663. //
  664. if ( (key_dest == key_menu && menubound[key])
  665. || (key_dest == key_console && !consolekeys[key])
  666. || (key_dest == key_game && ( cls.state == ca_active || !consolekeys[key] ) ) )
  667. {
  668. kb = keybindings[key];
  669. if (kb)
  670. {
  671. if (kb[0] == '+')
  672. { // button commands add keynum as a parm
  673. sprintf (cmd, "%s %i\n", kb, key);
  674. Cbuf_AddText (cmd);
  675. }
  676. else
  677. {
  678. Cbuf_AddText (kb);
  679. Cbuf_AddText ("\n");
  680. }
  681. }
  682. return;
  683. }
  684. if (!down)
  685. return; // other systems only care about key down events
  686. if (shift_down)
  687. key = keyshift[key];
  688. switch (key_dest)
  689. {
  690. case key_message:
  691. Key_Message (key);
  692. break;
  693. case key_menu:
  694. M_Keydown (key);
  695. break;
  696. case key_game:
  697. case key_console:
  698. Key_Console (key);
  699. break;
  700. default:
  701. Sys_Error ("Bad key_dest");
  702. }
  703. }
  704. /*
  705. ===================
  706. Key_ClearStates
  707. ===================
  708. */
  709. void Key_ClearStates (void)
  710. {
  711. int i;
  712. for (i=0 ; i<256 ; i++)
  713. {
  714. keydown[i] = false;
  715. key_repeats[i] = false;
  716. }
  717. }