summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/keys.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/sdl/progs/quake/keys.c')
-rw-r--r--apps/plugins/sdl/progs/quake/keys.c804
1 files changed, 804 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/keys.c b/apps/plugins/sdl/progs/quake/keys.c
new file mode 100644
index 0000000000..896bbaa795
--- /dev/null
+++ b/apps/plugins/sdl/progs/quake/keys.c
@@ -0,0 +1,804 @@
1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19*/
20#include "quakedef.h"
21
22/*
23
24key up events are sent even if in console mode
25
26*/
27
28
29#define MAXCMDLINE 256
30char key_lines[32][MAXCMDLINE];
31int key_linepos;
32int shift_down=false;
33int key_lastpress;
34
35int edit_line=0;
36int history_line=0;
37
38keydest_t key_dest;
39
40int key_count; // incremented every key event
41
42char *keybindings[256];
43qboolean consolekeys[256]; // if true, can't be rebound while in console
44qboolean menubound[256]; // if true, can't be rebound while in menu
45int keyshift[256]; // key to map to if shift held down in console
46int key_repeats[256]; // if > 1, it is autorepeating
47qboolean keydown[256];
48
49typedef struct
50{
51 char *name;
52 int keynum;
53} keyname_t;
54
55keyname_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/* Rockbox hack */
152void rb_console(void)
153{
154 rb->kbd_input(key_lines[edit_line] + 1, MAXCMDLINE-1);
155}
156
157/*
158====================
159Key_Console
160
161Interactive line editing and console scrollback
162====================
163*/
164void Key_Console (int key)
165{
166 char *cmd;
167
168 if (key == K_ENTER)
169 {
170 Cbuf_AddText (key_lines[edit_line]+1); // skip the >
171 Cbuf_AddText ("\n");
172 Con_Printf ("%s\n",key_lines[edit_line]);
173 edit_line = (edit_line + 1) & 31;
174 history_line = edit_line;
175 key_lines[edit_line][0] = ']';
176 key_linepos = 1;
177 if (cls.state == ca_disconnected)
178 SCR_UpdateScreen (); // force an update, because the command
179 // may take some time
180 return;
181 }
182
183 if (key == K_TAB)
184 { // command completion
185 cmd = Cmd_CompleteCommand (key_lines[edit_line]+1);
186 if (!cmd)
187 cmd = Cvar_CompleteVariable (key_lines[edit_line]+1);
188 if (cmd)
189 {
190 Q_strcpy (key_lines[edit_line]+1, cmd);
191 key_linepos = Q_strlen(cmd)+1;
192 key_lines[edit_line][key_linepos] = ' ';
193 key_linepos++;
194 key_lines[edit_line][key_linepos] = 0;
195 return;
196 }
197 }
198
199 if (key == K_BACKSPACE || key == K_LEFTARROW)
200 {
201 if (key_linepos > 1)
202 key_linepos--;
203 return;
204 }
205
206 if (key == K_UPARROW)
207 {
208 do
209 {
210 history_line = (history_line - 1) & 31;
211 } while (history_line != edit_line
212 && !key_lines[history_line][1]);
213 if (history_line == edit_line)
214 history_line = (edit_line+1)&31;
215 Q_strcpy(key_lines[edit_line], key_lines[history_line]);
216 key_linepos = Q_strlen(key_lines[edit_line]);
217 return;
218 }
219
220 if (key == K_DOWNARROW)
221 {
222 if (history_line == edit_line) return;
223 do
224 {
225 history_line = (history_line + 1) & 31;
226 }
227 while (history_line != edit_line
228 && !key_lines[history_line][1]);
229 if (history_line == edit_line)
230 {
231 key_lines[edit_line][0] = ']';
232 key_linepos = 1;
233 }
234 else
235 {
236 Q_strcpy(key_lines[edit_line], key_lines[history_line]);
237 key_linepos = Q_strlen(key_lines[edit_line]);
238 }
239 return;
240 }
241
242 if (key == K_PGUP || key==K_MWHEELUP)
243 {
244 con_backscroll += 2;
245 if (con_backscroll > con_totallines - (vid.height>>3) - 1)
246 con_backscroll = con_totallines - (vid.height>>3) - 1;
247 return;
248 }
249
250 if (key == K_PGDN || key==K_MWHEELDOWN)
251 {
252 con_backscroll -= 2;
253 if (con_backscroll < 0)
254 con_backscroll = 0;
255 return;
256 }
257
258 if (key == K_HOME)
259 {
260 con_backscroll = con_totallines - (vid.height>>3) - 1;
261 return;
262 }
263
264 if (key == K_END)
265 {
266 con_backscroll = 0;
267 return;
268 }
269
270 if (key < 32 || key > 127)
271 return; // non printable
272
273 if (key_linepos < MAXCMDLINE-1)
274 {
275 key_lines[edit_line][key_linepos] = key;
276 key_linepos++;
277 key_lines[edit_line][key_linepos] = 0;
278 }
279
280}
281
282//============================================================================
283
284char chat_buffer[32];
285qboolean team_message = false;
286
287void Key_Message (int key)
288{
289 static int chat_bufferlen = 0;
290
291 if (key == K_ENTER)
292 {
293 if (team_message)
294 Cbuf_AddText ("say_team \"");
295 else
296 Cbuf_AddText ("say \"");
297 Cbuf_AddText(chat_buffer);
298 Cbuf_AddText("\"\n");
299
300 key_dest = key_game;
301 chat_bufferlen = 0;
302 chat_buffer[0] = 0;
303 return;
304 }
305
306 if (key == K_ESCAPE)
307 {
308 key_dest = key_game;
309 chat_bufferlen = 0;
310 chat_buffer[0] = 0;
311 return;
312 }
313
314 if (key < 32 || key > 127)
315 return; // non printable
316
317 if (key == K_BACKSPACE)
318 {
319 if (chat_bufferlen)
320 {
321 chat_bufferlen--;
322 chat_buffer[chat_bufferlen] = 0;
323 }
324 return;
325 }
326
327 if (chat_bufferlen == 31)
328 return; // all full
329
330 chat_buffer[chat_bufferlen++] = key;
331 chat_buffer[chat_bufferlen] = 0;
332}
333
334//============================================================================
335
336
337/*
338===================
339Key_StringToKeynum
340
341Returns a key number to be used to index keybindings[] by looking at
342the given string. Single ascii characters return themselves, while
343the K_* names are matched up.
344===================
345*/
346int Key_StringToKeynum (char *str)
347{
348 keyname_t *kn;
349
350 if (!str || !str[0])
351 return -1;
352 if (!str[1])
353 return str[0];
354
355 for (kn=keynames ; kn->name ; kn++)
356 {
357 if (!Q_strcasecmp(str,kn->name))
358 return kn->keynum;
359 }
360 return -1;
361}
362
363/*
364===================
365Key_KeynumToString
366
367Returns a string (either a single ascii char, or a K_* name) for the
368given keynum.
369FIXME: handle quote special (general escape sequence?)
370===================
371*/
372char *Key_KeynumToString (int keynum)
373{
374 keyname_t *kn;
375 static char tinystr[2];
376
377 if (keynum == -1)
378 return "<KEY NOT FOUND>";
379 if (keynum > 32 && keynum < 127)
380 { // printable ascii
381 tinystr[0] = keynum;
382 tinystr[1] = 0;
383 return tinystr;
384 }
385
386 for (kn=keynames ; kn->name ; kn++)
387 if (keynum == kn->keynum)
388 return kn->name;
389
390 return "<UNKNOWN KEYNUM>";
391}
392
393
394/*
395===================
396Key_SetBinding
397===================
398*/
399void Key_SetBinding (int keynum, char *binding)
400{
401 LOGF("binding %d -> %s\n", keynum, binding);
402
403 char *new;
404 int l;
405
406 if (keynum == -1)
407 return;
408
409// free old bindings
410 if (keybindings[keynum])
411 {
412 Z_Free (keybindings[keynum]);
413 keybindings[keynum] = NULL;
414 }
415
416// allocate memory for new binding
417 l = Q_strlen (binding);
418 new = Z_Malloc (l+1);
419 Q_strcpy (new, binding);
420 new[l] = 0;
421 keybindings[keynum] = new;
422}
423
424/*
425===================
426Key_Unbind_f
427===================
428*/
429void Key_Unbind_f (void)
430{
431 int b;
432
433 if (Cmd_Argc() != 2)
434 {
435 Con_Printf ("unbind <key> : remove commands from a key\n");
436 return;
437 }
438
439 b = Key_StringToKeynum (Cmd_Argv(1));
440 if (b==-1)
441 {
442 Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1));
443 return;
444 }
445
446 Key_SetBinding (b, "");
447}
448
449void Key_Unbindall_f (void)
450{
451 int i;
452
453 for (i=0 ; i<256 ; i++)
454 if (keybindings[i])
455 Key_SetBinding (i, "");
456}
457
458int bind_nooverride = 0;
459
460/*
461===================
462Key_Bind_f
463===================
464*/
465void Key_Bind_f (void)
466{
467 int i, c, b;
468 char cmd[1024];
469
470 c = Cmd_Argc();
471
472 if (c != 2 && c != 3)
473 {
474 Con_Printf ("bind <key> [command] : attach a command to a key\n");
475 return;
476 }
477 b = Key_StringToKeynum (Cmd_Argv(1));
478 if (b==-1)
479 {
480 Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1));
481 return;
482 }
483
484 if (c == 2)
485 {
486 if (keybindings[b])
487 Con_Printf ("\"%s\" = \"%s\"\n", Cmd_Argv(1), keybindings[b] );
488 else
489 Con_Printf ("\"%s\" is not bound\n", Cmd_Argv(1) );
490 return;
491 }
492
493 bool overridden = false;
494
495 // Rockbox hack to set defaults
496 if(!bind_nooverride)
497 {
498 //rb->splashf(HZ, "overriding defaults");
499
500 switch(b)
501 {
502 case K_ENTER:
503 overridden = true;
504 strcpy(cmd, "+attack");
505 break;
506 case K_DOWNARROW:
507 overridden = true;
508 strcpy(cmd, "impulse 10; +jump; wait; -jump");
509 break;
510 case 'a':
511 overridden = true;
512 strcpy(cmd, "+moveleft");
513 break;
514 case 'd':
515 overridden = true;
516 strcpy(cmd, "+moveright");
517 break;
518 }
519 }
520
521 if(!overridden)
522 {
523// copy the rest of the command line
524 cmd[0] = 0; // start out with a null string
525 for (i=2 ; i< c ; i++)
526 {
527 if (i > 2)
528 strcat (cmd, " ");
529 strcat (cmd, Cmd_Argv(i));
530 }
531 }
532
533 Key_SetBinding (b, cmd);
534}
535
536/*
537============
538Key_WriteBindings
539
540Writes lines containing "bind key value"
541============
542*/
543void Key_WriteBindings (FILE *f)
544{
545 int i;
546
547 for (i=0 ; i<256 ; i++)
548 if (keybindings[i])
549 if (*keybindings[i])
550 fprintf (f, "bind \"%s\" \"%s\"\n", Key_KeynumToString(i), keybindings[i]);
551}
552
553
554/*
555===================
556Key_Init
557===================
558*/
559void Key_Init (void)
560{
561 int i;
562
563 for (i=0 ; i<32 ; i++)
564 {
565 key_lines[i][0] = ']';
566 key_lines[i][1] = 0;
567 }
568 key_linepos = 1;
569
570//
571// init ascii characters in console mode
572//
573 for (i=32 ; i<128 ; i++)
574 consolekeys[i] = true;
575 consolekeys[K_ENTER] = true;
576 consolekeys[K_TAB] = true;
577 consolekeys[K_LEFTARROW] = true;
578 consolekeys[K_RIGHTARROW] = true;
579 consolekeys[K_UPARROW] = true;
580 consolekeys[K_DOWNARROW] = true;
581 consolekeys[K_BACKSPACE] = true;
582 consolekeys[K_PGUP] = true;
583 consolekeys[K_PGDN] = true;
584 consolekeys[K_SHIFT] = true;
585 consolekeys[K_MWHEELUP] = true;
586 consolekeys[K_MWHEELDOWN] = true;
587 consolekeys['`'] = false;
588 consolekeys['~'] = false;
589
590 for (i=0 ; i<256 ; i++)
591 keyshift[i] = i;
592 for (i='a' ; i<='z' ; i++)
593 keyshift[i] = i - 'a' + 'A';
594 keyshift['1'] = '!';
595 keyshift['2'] = '@';
596 keyshift['3'] = '#';
597 keyshift['4'] = '$';
598 keyshift['5'] = '%';
599 keyshift['6'] = '^';
600 keyshift['7'] = '&';
601 keyshift['8'] = '*';
602 keyshift['9'] = '(';
603 keyshift['0'] = ')';
604 keyshift['-'] = '_';
605 keyshift['='] = '+';
606 keyshift[','] = '<';
607 keyshift['.'] = '>';
608 keyshift['/'] = '?';
609 keyshift[';'] = ':';
610 keyshift['\''] = '"';
611 keyshift['['] = '{';
612 keyshift[']'] = '}';
613 keyshift['`'] = '~';
614 keyshift['\\'] = '|';
615
616 menubound[K_ESCAPE] = true;
617 for (i=0 ; i<12 ; i++)
618 menubound[K_F1+i] = true;
619
620//
621// register our functions
622//
623 Cmd_AddCommand ("bind",Key_Bind_f);
624 Cmd_AddCommand ("unbind",Key_Unbind_f);
625 Cmd_AddCommand ("unbindall",Key_Unbindall_f);
626
627
628}
629
630/*
631===================
632Key_Event
633
634Called by the system between frames for both key up and key down events
635Should NOT be called during an interrupt!
636===================
637*/
638void Key_Event (int key, qboolean down)
639{
640 char *kb;
641 char cmd[1024];
642
643 keydown[key] = down;
644
645 if (!down)
646 key_repeats[key] = 0;
647
648 key_lastpress = key;
649 key_count++;
650 if (key_count <= 0)
651 {
652 return; // just catching keys for Con_NotifyBox
653 }
654
655// update auto-repeat status
656 if (down)
657 {
658 key_repeats[key]++;
659 if (key != K_BACKSPACE && key != K_PAUSE && key_repeats[key] > 1)
660 {
661 return; // ignore most autorepeats
662 }
663
664 if (key >= 200 && !keybindings[key])
665 Con_Printf ("%s is unbound, hit F4 to set.\n", Key_KeynumToString (key) );
666 }
667
668 if (key == K_SHIFT)
669 shift_down = down;
670
671//
672// handle escape specialy, so the user can never unbind it
673//
674 if (key == K_ESCAPE)
675 {
676 if (!down)
677 return;
678 switch (key_dest)
679 {
680 case key_message:
681 Key_Message (key);
682 break;
683 case key_menu:
684 M_Keydown (key);
685 break;
686 case key_game:
687 case key_console:
688 M_ToggleMenu_f ();
689 break;
690 default:
691 Sys_Error ("Bad key_dest");
692 }
693 return;
694 }
695
696//
697// key up events only generate commands if the game key binding is
698// a button command (leading + sign). These will occur even in console mode,
699// to keep the character from continuing an action started before a console
700// switch. Button commands include the kenum as a parameter, so multiple
701// downs can be matched with ups
702//
703 if (!down)
704 {
705 kb = keybindings[key];
706 if (kb && kb[0] == '+')
707 {
708 sprintf (cmd, "-%s %i\n", kb+1, key);
709 Cbuf_AddText (cmd);
710 }
711 if (keyshift[key] != key)
712 {
713 kb = keybindings[keyshift[key]];
714 if (kb && kb[0] == '+')
715 {
716 sprintf (cmd, "-%s %i\n", kb+1, key);
717 Cbuf_AddText (cmd);
718 }
719 }
720 return;
721 }
722
723//
724// during demo playback, most keys bring up the main menu
725//
726 if (cls.demoplayback && down && consolekeys[key] && key_dest == key_game)
727 {
728 M_ToggleMenu_f ();
729 return;
730 }
731
732//
733// if not a consolekey, send to the interpreter no matter what mode is
734//
735 if ( (key_dest == key_menu && menubound[key])
736 || (key_dest == key_console && !consolekeys[key])
737 || (key_dest == key_game && ( !con_forcedup || !consolekeys[key] ) ) )
738 {
739 kb = keybindings[key];
740 if (kb)
741 {
742 if (kb[0] == '+')
743 { // button commands add keynum as a parm
744 sprintf (cmd, "%s %i\n", kb, key);
745 Cbuf_AddText (cmd);
746 }
747 else
748 {
749 Cbuf_AddText (kb);
750 Cbuf_AddText ("\n");
751 }
752 }
753 return;
754 }
755
756 if (!down)
757 return; // other systems only care about key down events
758
759 if (shift_down)
760 {
761 key = keyshift[key];
762 }
763
764 switch (key_dest)
765 {
766 case key_message:
767 Key_Message (key);
768 break;
769 case key_menu:
770 M_Keydown (key);
771 break;
772
773 case key_game:
774 case key_console:
775 if(key == K_ENTER)
776 {
777 rb_console();
778 Key_Console (K_ENTER);
779 }
780 else
781 Key_Console (key);
782 break;
783 default:
784 Sys_Error ("Bad key_dest");
785 }
786}
787
788
789/*
790===================
791Key_ClearStates
792===================
793*/
794void Key_ClearStates (void)
795{
796 int i;
797
798 for (i=0 ; i<256 ; i++)
799 {
800 keydown[i] = false;
801 key_repeats[i] = 0;
802 }
803}
804