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];
49 void Con_OSK_f (char *input
, char *output
, int outlen
);
50 void Con_SetOSKActive(qboolean active
);
51 qboolean
Con_isSetOSKActive(void);
52 void Con_OSK_Key (int key
);
60 keyname_t keynames
[] =
66 {"BACKSPACE", K_BACKSPACE
},
67 {"UPARROW", K_UPARROW
},
68 {"DOWNARROW", K_DOWNARROW
},
69 {"LEFTARROW", K_LEFTARROW
},
70 {"RIGHTARROW", K_RIGHTARROW
},
101 {"TRIANGLE", K_JOY1
},
113 {"LTRIGGER", K_AUX1
},
114 {"RTRIGGER", K_AUX2
},
152 {"MWHEELUP", K_MWHEELUP
},
153 {"MWHEELDOWN", K_MWHEELDOWN
},
155 {"SEMICOLON", ';'}, // because a raw semicolon seperates commands
160 char consoleInput
[MAXCMDLINE
];
161 qboolean consoleOskDone
= false;
164 ==============================================================================
166 LINE TYPING INTO THE CONSOLE
168 ==============================================================================
176 Interactive line editing and console scrollback
179 void Key_Console (int key
)
184 if (Con_isSetOSKActive()) {
187 else if (key
== K_JOY2
)
188 Con_OSK_Key (K_ESCAPE
);
189 else if (key
== K_JOY3
)
190 Con_OSK_Key (K_ENTER
);
191 else if (key
== K_JOY4
)
198 if ( key
== K_JOY4
|| key
== K_INS
)
200 consoleOskDone
= false;
201 Con_SetOSKActive(true);
202 Con_OSK_f(key_lines
[edit_line
]+1, consoleInput
, 72);
207 if (key
== K_JOY3
|| key
== K_ENTER
)
209 Cbuf_AddText (key_lines
[edit_line
]+1); // skip the >
211 Con_Printf ("%s\n",key_lines
[edit_line
]);
212 edit_line
= (edit_line
+ 1) & 31;
213 history_line
= edit_line
;
214 key_lines
[edit_line
][0] = ']';
216 if (cls
.state
== ca_disconnected
)
217 SCR_UpdateScreen (); // force an update, because the command
218 // may take some time
224 if (key
== K_TAB
|| key
== K_RIGHTARROW
)
225 { // command completion
226 cmd
= Cmd_CompleteCommand (key_lines
[edit_line
]+1);
228 cmd
= Cvar_CompleteVariable (key_lines
[edit_line
]+1);
231 Q_strcpy (key_lines
[edit_line
]+1, cmd
);
232 key_linepos
= Q_strlen(cmd
)+1;
233 key_lines
[edit_line
][key_linepos
] = ' ';
235 key_lines
[edit_line
][key_linepos
] = 0;
240 if (key
== K_BACKSPACE
|| key
== K_LEFTARROW
)
247 if (key
== K_UPARROW
)
251 history_line
= (history_line
- 1) & 31;
252 } while (history_line
!= edit_line
253 && !key_lines
[history_line
][1]);
254 if (history_line
== edit_line
)
255 history_line
= (edit_line
+1)&31;
256 Q_strcpy(key_lines
[edit_line
], key_lines
[history_line
]);
257 key_linepos
= Q_strlen(key_lines
[edit_line
]);
261 if (key
== K_DOWNARROW
)
263 if (history_line
== edit_line
) return;
266 history_line
= (history_line
+ 1) & 31;
268 while (history_line
!= edit_line
269 && !key_lines
[history_line
][1]);
270 if (history_line
== edit_line
)
272 key_lines
[edit_line
][0] = ']';
277 Q_strcpy(key_lines
[edit_line
], key_lines
[history_line
]);
278 key_linepos
= Q_strlen(key_lines
[edit_line
]);
283 if (key
== K_PGUP
|| key
==K_MWHEELUP
)
286 if (con_backscroll
> con_totallines
- (vid
.height
>>3) - 1)
287 con_backscroll
= con_totallines
- (vid
.height
>>3) - 1;
291 if (key
== K_PGDN
|| key
==K_MWHEELDOWN
)
294 if (con_backscroll
< 0)
301 con_backscroll
= con_totallines
- (vid
.height
>>3) - 1;
311 if (key
< 32 || key
> 127)
312 return; // non printable
314 if (key_linepos
< MAXCMDLINE
-1)
316 key_lines
[edit_line
][key_linepos
] = key
;
318 key_lines
[edit_line
][key_linepos
] = 0;
323 //============================================================================
325 char chat_buffer
[32];
326 qboolean team_message
= false;
328 void Key_Message (int key
)
330 static int chat_bufferlen
= 0;
334 if (Con_isSetOSKActive()) {
337 else if (key == K_JOY2)
338 Con_OSK_Key (K_ESCAPE);
339 else if (key == K_JOY3)
340 Con_OSK_Key (K_ENTER);
341 else if (key == K_JOY4)
348 if ( key == K_JOY4 || key == K_INS)
350 consoleOskDone = false;
351 Con_SetOSKActive(true);
352 Con_OSK_f(key_lines[edit_line]+1, consoleInput, 72);
361 Cbuf_AddText ("say_team \"");
363 Cbuf_AddText ("say \"");
364 Cbuf_AddText(chat_buffer
);
365 Cbuf_AddText("\"\n");
381 if (key
< 32 || key
> 127)
382 return; // non printable
384 if (key
== K_BACKSPACE
)
389 chat_buffer
[chat_bufferlen
] = 0;
394 if (chat_bufferlen
== 31)
397 chat_buffer
[chat_bufferlen
++] = key
;
398 chat_buffer
[chat_bufferlen
] = 0;
401 //============================================================================
408 Returns a key number to be used to index keybindings[] by looking at
409 the given string. Single ascii characters return themselves, while
410 the K_* names are matched up.
413 int Key_StringToKeynum (char *str
)
422 for (kn
=keynames
; kn
->name
; kn
++)
424 if (!Q_strcasecmp(str
,kn
->name
))
434 Returns a string (either a single ascii char, or a K_* name) for the
436 FIXME: handle quote special (general escape sequence?)
439 char *Key_KeynumToString (int keynum
)
442 static char tinystr
[2];
445 return "<KEY NOT FOUND>";
446 if (keynum
> 32 && keynum
< 127)
453 for (kn
=keynames
; kn
->name
; kn
++)
454 if (keynum
== kn
->keynum
)
457 return "<UNKNOWN KEYNUM>";
466 void Key_SetBinding (int keynum
, char *binding
)
475 if (keybindings
[keynum
])
477 Z_Free (keybindings
[keynum
]);
478 keybindings
[keynum
] = NULL
;
481 // allocate memory for new binding
482 l
= Q_strlen (binding
);
483 new = Z_Malloc (l
+1);
484 Q_strcpy (new, binding
);
486 keybindings
[keynum
] = new;
494 void Key_Unbind_f (void)
500 Con_Printf ("unbind <key> : remove commands from a key\n");
504 b
= Key_StringToKeynum (Cmd_Argv(1));
507 Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1));
511 Key_SetBinding (b
, "");
514 void Key_Unbindall_f (void)
518 for (i
=0 ; i
<256 ; i
++)
520 Key_SetBinding (i
, "");
529 void Key_Bind_f (void)
536 if (c
!= 2 && c
!= 3)
538 Con_Printf ("bind <key> [command] : attach a command to a key\n");
541 b
= Key_StringToKeynum (Cmd_Argv(1));
544 Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1));
551 Con_Printf ("\"%s\" = \"%s\"\n", Cmd_Argv(1), keybindings
[b
] );
553 Con_Printf ("\"%s\" is not bound\n", Cmd_Argv(1) );
557 // copy the rest of the command line
558 cmd
[0] = 0; // start out with a null string
559 for (i
=2 ; i
< c
; i
++)
563 strcat (cmd
, Cmd_Argv(i
));
566 Key_SetBinding (b
, cmd
);
573 Writes lines containing "bind key value"
576 void Key_WriteBindings (FILE *f
)
580 for (i
=0 ; i
<256 ; i
++)
583 fprintf (f
, "bind \"%s\" \"%s\"\n", Key_KeynumToString(i
), keybindings
[i
]);
596 for (i
=0 ; i
<32 ; i
++)
598 key_lines
[i
][0] = ']';
604 // init ascii characters in console mode
606 for (i
=32 ; i
<128 ; i
++)
607 consolekeys
[i
] = true;
608 consolekeys
[K_ENTER
] = true;
609 consolekeys
[K_TAB
] = true;
610 consolekeys
[K_LEFTARROW
] = true;
611 consolekeys
[K_RIGHTARROW
] = true;
612 consolekeys
[K_UPARROW
] = true;
613 consolekeys
[K_DOWNARROW
] = true;
614 consolekeys
[K_BACKSPACE
] = true;
615 consolekeys
[K_PGUP
] = true;
616 consolekeys
[K_PGDN
] = true;
617 consolekeys
[K_SHIFT
] = true;
618 consolekeys
[K_MWHEELUP
] = true;
619 consolekeys
[K_MWHEELDOWN
] = true;
620 consolekeys
['`'] = false;
621 consolekeys
['~'] = false;
623 consolekeys
[K_INS
] = true;
624 consolekeys
[K_JOY1
] = true;
625 consolekeys
[K_JOY2
] = true;
626 consolekeys
[K_JOY3
] = true;
627 consolekeys
[K_JOY4
] = true;
630 for (i
=0 ; i
<256 ; i
++)
632 for (i
='a' ; i
<='z' ; i
++)
633 keyshift
[i
] = i
- 'a' + 'A';
650 keyshift
['\''] = '"';
654 keyshift
['\\'] = '|';
656 menubound
[K_ESCAPE
] = true;
657 for (i
=0 ; i
<12 ; i
++)
658 menubound
[K_F1
+i
] = true;
661 // register our functions
663 Cmd_AddCommand ("bind",Key_Bind_f
);
664 Cmd_AddCommand ("unbind",Key_Unbind_f
);
665 Cmd_AddCommand ("unbindall",Key_Unbindall_f
);
674 Called by the system between frames for both key up and key down events
675 Should NOT be called during an interrupt!
678 void Key_Event (int key
, qboolean down
)
686 if (Con_isSetOSKActive() && down
) {
689 else if (key
== K_JOY2
)
690 Con_OSK_Key (K_ESCAPE
);
691 else if (key
== K_JOY3
)
692 Con_OSK_Key (K_ENTER
);
693 else if (key
== K_JOY4
)
698 if (!Con_isSetOSKActive()) {
699 consoleOskDone
= true;
700 strcpy(key_lines
[edit_line
]+1, consoleInput
);
701 key_linepos
= Q_strlen(key_lines
[edit_line
]);
702 consoleOskDone
= false;
713 key_repeats
[key
] = 0;
719 return; // just catching keys for Con_NotifyBox
722 // update auto-repeat status
726 if (key
!= K_PAUSE
&& key_repeats
[key
] > 1)
728 return; // ignore most autorepeats
731 if (key
>= 200 && !keybindings
[key
])
733 Con_Printf ("%s is unbound, hit START to set.\n", Key_KeynumToString (key
) );
735 Con_Printf ("%s is unbound, hit F4 to set.\n", Key_KeynumToString (key
) );
743 // handle escape specialy, so the user can never unbind it
762 Sys_Error ("Bad key_dest");
768 // key up events only generate commands if the game key binding is
769 // a button command (leading + sign). These will occur even in console mode,
770 // to keep the character from continuing an action started before a console
771 // switch. Button commands include the kenum as a parameter, so multiple
772 // downs can be matched with ups
776 kb
= keybindings
[key
];
777 if (kb
&& kb
[0] == '+')
779 sprintf (cmd
, "-%s %i\n", kb
+1, key
);
782 if (keyshift
[key
] != key
)
784 kb
= keybindings
[keyshift
[key
]];
785 if (kb
&& kb
[0] == '+')
787 sprintf (cmd
, "-%s %i\n", kb
+1, key
);
795 // during demo playback, most keys bring up the main menu
797 if (cls
.demoplayback
&& down
&& consolekeys
[key
] && key_dest
== key_game
)
804 // if not a consolekey, send to the interpreter no matter what mode is
806 if ( (key_dest
== key_menu
&& menubound
[key
])
807 || (key_dest
== key_console
&& !consolekeys
[key
])
808 || (key_dest
== key_game
&& ( !con_forcedup
|| !consolekeys
[key
] ) ) )
810 kb
= keybindings
[key
];
814 { // button commands add keynum as a parm
815 sprintf (cmd
, "%s %i\n", kb
, key
);
828 return; // other systems only care about key down events
849 Sys_Error ("Bad key_dest");
859 void Key_ClearStates (void)
863 for (i
=0 ; i
<256 ; i
++)