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