keys.c 18 KB

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