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