home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quakeworld_src / client / keys.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  16.5 KB  |  840 lines

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