2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
24 key up events are sent even if in console mode
29 #define MAXCMDLINE 256
30 char key_lines
[32][MAXCMDLINE
];
40 int key_count
; // incremented every key event
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];
55 keyname_t keynames
[] =
61 {"BACKSPACE", K_BACKSPACE
},
62 {"UPARROW", K_UPARROW
},
63 {"DOWNARROW", K_DOWNARROW
},
64 {"LEFTARROW", K_LEFTARROW
},
65 {"RIGHTARROW", K_RIGHTARROW
},
135 {"MWHEELUP", K_MWHEELUP
},
136 {"MWHEELDOWN", K_MWHEELDOWN
},
138 {"SEMICOLON", ';'}, // because a raw semicolon seperates commands
144 ==============================================================================
146 LINE TYPING INTO THE CONSOLE
148 ==============================================================================
156 Interactive line editing and console scrollback
159 void Key_Console (int key
)
165 Cbuf_AddText (key_lines
[edit_line
]+1); // skip the >
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] = ']';
172 if (cls
.state
== ca_disconnected
)
173 SCR_UpdateScreen (); // force an update, because the command
174 // may take some time
179 { // command completion
180 cmd
= Cmd_CompleteCommand (key_lines
[edit_line
]+1);
182 cmd
= Cvar_CompleteVariable (key_lines
[edit_line
]+1);
185 Q_strcpy (key_lines
[edit_line
]+1, cmd
);
186 key_linepos
= Q_strlen(cmd
)+1;
187 key_lines
[edit_line
][key_linepos
] = ' ';
189 key_lines
[edit_line
][key_linepos
] = 0;
194 if (key
== K_BACKSPACE
|| key
== K_LEFTARROW
)
201 if (key
== K_UPARROW
)
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
]);
215 if (key
== K_DOWNARROW
)
217 if (history_line
== edit_line
) return;
220 history_line
= (history_line
+ 1) & 31;
222 while (history_line
!= edit_line
223 && !key_lines
[history_line
][1]);
224 if (history_line
== edit_line
)
226 key_lines
[edit_line
][0] = ']';
231 Q_strcpy(key_lines
[edit_line
], key_lines
[history_line
]);
232 key_linepos
= Q_strlen(key_lines
[edit_line
]);
237 if (key
== K_PGUP
|| key
==K_MWHEELUP
)
240 if (con_backscroll
> con_totallines
- (vid
.height
>>3) - 1)
241 con_backscroll
= con_totallines
- (vid
.height
>>3) - 1;
245 if (key
== K_PGDN
|| key
==K_MWHEELDOWN
)
248 if (con_backscroll
< 0)
255 con_backscroll
= con_totallines
- (vid
.height
>>3) - 1;
265 if (key
< 32 || key
> 127)
266 return; // non printable
268 if (key_linepos
< MAXCMDLINE
-1)
270 key_lines
[edit_line
][key_linepos
] = key
;
272 key_lines
[edit_line
][key_linepos
] = 0;
277 //============================================================================
279 char chat_buffer
[32];
280 qboolean team_message
= false;
282 void Key_Message (int key
)
284 static int chat_bufferlen
= 0;
289 Cbuf_AddText ("say_team \"");
291 Cbuf_AddText ("say \"");
292 Cbuf_AddText(chat_buffer
);
293 Cbuf_AddText("\"\n");
309 if (key
< 32 || key
> 127)
310 return; // non printable
312 if (key
== K_BACKSPACE
)
317 chat_buffer
[chat_bufferlen
] = 0;
322 if (chat_bufferlen
== 31)
325 chat_buffer
[chat_bufferlen
++] = key
;
326 chat_buffer
[chat_bufferlen
] = 0;
329 //============================================================================
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.
341 int Key_StringToKeynum (char *str
)
350 for (kn
=keynames
; kn
->name
; kn
++)
352 if (!Q_strcasecmp(str
,kn
->name
))
362 Returns a string (either a single ascii char, or a K_* name) for the
364 FIXME: handle quote special (general escape sequence?)
367 char *Key_KeynumToString (int keynum
)
370 static char tinystr
[2];
373 return "<KEY NOT FOUND>";
374 if (keynum
> 32 && keynum
< 127)
381 for (kn
=keynames
; kn
->name
; kn
++)
382 if (keynum
== kn
->keynum
)
385 return "<UNKNOWN KEYNUM>";
394 void Key_SetBinding (int keynum
, char *binding
)
403 if (keybindings
[keynum
])
405 Z_Free (keybindings
[keynum
]);
406 keybindings
[keynum
] = NULL
;
409 // allocate memory for new binding
410 l
= Q_strlen (binding
);
411 new = Z_Malloc (l
+1);
412 Q_strcpy (new, binding
);
414 keybindings
[keynum
] = new;
422 void Key_Unbind_f (void)
428 Con_Printf ("unbind <key> : remove commands from a key\n");
432 b
= Key_StringToKeynum (Cmd_Argv(1));
435 Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1));
439 Key_SetBinding (b
, "");
442 void Key_Unbindall_f (void)
446 for (i
=0 ; i
<256 ; i
++)
448 Key_SetBinding (i
, "");
457 void Key_Bind_f (void)
464 if (c
!= 2 && c
!= 3)
466 Con_Printf ("bind <key> [command] : attach a command to a key\n");
469 b
= Key_StringToKeynum (Cmd_Argv(1));
472 Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1));
479 Con_Printf ("\"%s\" = \"%s\"\n", Cmd_Argv(1), keybindings
[b
] );
481 Con_Printf ("\"%s\" is not bound\n", Cmd_Argv(1) );
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
++)
491 strcat (cmd
, Cmd_Argv(i
));
494 Key_SetBinding (b
, cmd
);
501 Writes lines containing "bind key value"
504 void Key_WriteBindings (FILE *f
)
508 for (i
=0 ; i
<256 ; i
++)
511 fprintf (f
, "bind \"%s\" \"%s\"\n", Key_KeynumToString(i
), keybindings
[i
]);
524 for (i
=0 ; i
<32 ; i
++)
526 key_lines
[i
][0] = ']';
532 // init ascii characters in console mode
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;
551 for (i
=0 ; i
<256 ; i
++)
553 for (i
='a' ; i
<='z' ; i
++)
554 keyshift
[i
] = i
- 'a' + 'A';
571 keyshift
['\''] = '"';
575 keyshift
['\\'] = '|';
577 menubound
[K_ESCAPE
] = true;
578 for (i
=0 ; i
<12 ; i
++)
579 menubound
[K_F1
+i
] = true;
582 // register our functions
584 Cmd_AddCommand ("bind",Key_Bind_f
);
585 Cmd_AddCommand ("unbind",Key_Unbind_f
);
586 Cmd_AddCommand ("unbindall",Key_Unbindall_f
);
595 Called by the system between frames for both key up and key down events
596 Should NOT be called during an interrupt!
599 void Key_Event (int key
, qboolean down
)
607 key_repeats
[key
] = 0;
613 return; // just catching keys for Con_NotifyBox
616 // update auto-repeat status
620 if (key
!= K_BACKSPACE
&& key
!= K_PAUSE
&& key_repeats
[key
] > 1)
622 return; // ignore most autorepeats
625 if (key
>= 200 && !keybindings
[key
])
626 Con_Printf ("%s is unbound, hit F4 to set.\n", Key_KeynumToString (key
) );
633 // handle escape specialy, so the user can never unbind it
652 Sys_Error ("Bad key_dest");
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
666 kb
= keybindings
[key
];
667 if (kb
&& kb
[0] == '+')
669 sprintf (cmd
, "-%s %i\n", kb
+1, key
);
672 if (keyshift
[key
] != key
)
674 kb
= keybindings
[keyshift
[key
]];
675 if (kb
&& kb
[0] == '+')
677 sprintf (cmd
, "-%s %i\n", kb
+1, key
);
685 // during demo playback, most keys bring up the main menu
687 if (cls
.demoplayback
&& down
&& consolekeys
[key
] && key_dest
== key_game
)
694 // if not a consolekey, send to the interpreter no matter what mode is
696 if ( (key_dest
== key_menu
&& menubound
[key
])
697 || (key_dest
== key_console
&& !consolekeys
[key
])
698 || (key_dest
== key_game
&& ( !con_forcedup
|| !consolekeys
[key
] ) ) )
700 kb
= keybindings
[key
];
704 { // button commands add keynum as a parm
705 sprintf (cmd
, "%s %i\n", kb
, key
);
718 return; // other systems only care about key down events
739 Sys_Error ("Bad key_dest");
749 void Key_ClearStates (void)
753 for (i
=0 ; i
<256 ; i
++)