error.[ch]: fix keyword usage
[0verkill.git] / kbd.c
blob4f2392c6d3f10019165e36046646448589907399
1 #ifndef WIN32
3 #include <fcntl.h>
4 #include <signal.h>
5 #include <ctype.h>
6 #include <sys/ioctl.h>
7 #include <unistd.h>
8 #include <sys/types.h>
9 #include <sys/time.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
14 #include "config.h"
16 #ifdef HAVE_SYS_SELECT_H
17 #include <sys/select.h>
18 #endif
20 #ifdef HAVE_LINUX_KD_H
21 #define HAVE_RAW_KEYBOARD
22 #include <linux/kd.h>
23 #endif
25 #ifdef HAVE_LINUX_VT_H
26 #define HAVE_VT_SWITCH
27 #include <linux/vt.h>
28 #endif
30 #ifdef __EMX__
31 #define INCL_DOS
32 #define INCL_DOSERRORS
33 #define INCL_DOSMONITORS
34 #define INCL_KBD
35 #include <os2.h>
36 #define HAVE_OS2_KEYBOARD
37 #endif
39 #include "kbd.h"
40 #include "console.h"
42 #define KBD_RAW 0
43 #define KBD_STD 1
45 #define KBD_BUFFER_SIZE 256 /* size of buffer for incoming keys */
47 #ifdef HAVE_RAW_KEYBOARD
48 static int oldkbmode; /* original keyboard mode */
49 #endif
50 int keyboard_type;
52 /* RAW-MODE KEYBOARD */
53 /* keyboard bitmaps: current and previous */
54 static unsigned char keyboard[128]; /* 0=not pressed, !0=pressed */
55 static unsigned char old_keyboard[128]; /* 0=not pressed, !0=pressed */
57 /* NON-RAW KEYBOARD: */
58 int current_key;
59 int shift_pressed;
61 #ifdef HAVE_OS2_KEYBOARD
63 #define OS2_ALIGN(var) (_THUNK_PTR_STRUCT_OK(&var##1) ? &var##1 : &var##2)
65 HMONITOR os2_hmon;
67 struct os2_key_packet {
68 USHORT mon_flag;
69 UCHAR chr;
70 UCHAR scan;
71 UCHAR dbcs;
72 UCHAR dbcs_shift;
73 USHORT shift_state;
74 ULONG ms;
75 USHORT dd_flag;
78 struct os2_buffer {
79 USHORT cb;
80 struct os2_key_packet packet;
81 char pad[20];
84 struct os2_key_packet *os2_key;
85 struct os2_buffer *os2_in;
86 struct os2_buffer *os2_out;
88 int os2_read_mon(unsigned char *data, int len)
90 static int prefix = 0;
91 int bytes_read = 0;
92 int r;
93 USHORT count = sizeof(struct os2_key_packet);
94 while (bytes_read < len) {
95 int scan;
96 r = DosMonRead((void *)os2_in, IO_NOWAIT, (void *)os2_key, &count);
97 if (r == ERROR_MON_BUFFER_EMPTY) break;
98 if (r) {
99 fprintf(stderr, "DosMonRead: %d\n", r);
100 sleep(1);
101 break;
103 /*fprintf(stderr, "monflag: %04x, scan %02x, shift %04x\n", os2_key->mon_flag, os2_key->scan, os2_key->shift_state);*/
104 scan = os2_key->mon_flag >> 8;
105 /*fprintf(stderr, "scan: %02x\n", scan); fflush(stderr);*/
106 if (scan == 0xE0) {
107 prefix = 1;
108 c:continue;
110 if (prefix) {
111 prefix = 0;
112 switch (scan & 0x7f) {
113 case 29: scan = scan & 0x80 | 97; break;
114 case 71: scan = scan & 0x80 | 102; break;
115 case 72: scan = scan & 0x80 | 103; break;
116 case 73: scan = scan & 0x80 | 104; break;
117 case 75: scan = scan & 0x80 | 105; break;
118 case 77: scan = scan & 0x80 | 106; break;
119 case 79: scan = scan & 0x80 | 107; break;
120 case 80: scan = scan & 0x80 | 108; break;
121 case 81: scan = scan & 0x80 | 109; break;
122 case 82: scan = scan & 0x80 | 110; break;
123 case 83: scan = scan & 0x80 | 111; break;
124 default:
125 /*fprintf(stderr, "scan: %02x\n", scan); fflush(stderr);*/
126 goto c;
129 data[bytes_read++] = scan;
131 return bytes_read;
134 #endif
136 /* reads byte from input */
137 int my_getchar(void)
139 unsigned char a;
140 ssize_t ret = 0;
141 ret = read(0,&a,1);
142 return a;
146 /* test if there's something on input */
147 int kbhit(void)
149 fd_set fds;
150 struct timeval tv;
152 FD_ZERO(&fds);
153 FD_SET(0,&fds);
154 tv.tv_sec=0;
155 tv.tv_usec=0;
157 return !!(select(1,&fds,NULL,NULL,&tv));
161 void test_shift(int k)
163 switch(k)
165 case '~':
166 case '!':
167 case '@':
168 case '#':
169 case '$':
170 case '%':
171 case '^':
172 case '&':
173 case '*':
174 case '(':
175 case ')':
176 case '_':
177 case '+':
178 case '|':
179 case 'Q':
180 case 'W':
181 case 'E':
182 case 'R':
183 case 'T':
184 case 'Y':
185 case 'U':
186 case 'I':
187 case 'O':
188 case 'P':
189 case '{':
190 case '}':
191 case 'A':
192 case 'S':
193 case 'D':
194 case 'F':
195 case 'G':
196 case 'H':
197 case 'J':
198 case 'K':
199 case 'L':
200 case ':':
201 case '"':
202 case 'Z':
203 case 'X':
204 case 'C':
205 case 'V':
206 case 'B':
207 case 'N':
208 case 'M':
209 case '<':
210 case '>':
211 case '?':
212 shift_pressed=1;
217 /* non-raw keyboard */
218 int getkey(void)
220 int k;
221 k=my_getchar();
222 shift_pressed=0;
223 switch(k)
225 case 0:
226 switch(my_getchar())
228 case 72:
229 return K_UP;
231 case 75:
232 return K_LEFT;
234 case 77:
235 return K_RIGHT;
237 case 80:
238 return K_DOWN;
240 default:
241 return 0;
244 case 8:
245 return K_BACKSPACE;
247 case 9:
248 return K_TAB;
250 case 13:
251 return K_ENTER;
253 case 27:
254 if (kbhit())
255 switch(my_getchar())
257 case 91:
258 switch(my_getchar())
260 case 65:
261 return K_UP;
263 case 66:
264 return K_DOWN;
266 case 67:
267 return K_RIGHT;
269 case 68:
270 return K_LEFT;
273 return K_ESCAPE;
275 case 127:
276 return K_BACKSPACE;
278 default:
279 test_shift(k);
280 return tolower(k);
285 /* on error returns 1 */
286 void kbd_init(void)
288 #ifdef HAVE_RAW_KEYBOARD
290 keyboard_type=KBD_RAW;
292 /* raw keyboard */
293 if (ioctl(0,KDGKBMODE,&oldkbmode))goto std;
294 if (ioctl(0,KDSKBMODE,K_MEDIUMRAW))goto std;
296 /* GREAT EXPLANATION TO A SMALL FCNTL: */
297 /* ----------------------------------- */
299 /* this fcntl is a great cheat */
300 /* it switches STDOUT!!!!! to noblocking mode */
301 /* as i know 0 is STDIN so why it changes STDOUT settings?????? */
302 /* (does anyone know why???? (if you know send me a mail - you win million:-) (stupid joke...))) */
303 /* it causes scrambled picture on xterm and telnet */
304 /* because terminal doesn't manage and loses characters */
305 /* fortunatelly this fcntl is necessary only with raw keyboard */
306 /* and to switch keyboard to raw mode you must physically sit on the machine */
307 /* and when you sit on the machine, terminal is fast enough to manage ;-) */
308 fcntl(0,F_SETFL,fcntl(0,F_GETFL)|O_NONBLOCK);
310 memset(keyboard,0,128);
311 memset(old_keyboard,0,128);
312 return;
313 std:
314 #endif
316 #ifdef HAVE_OS2_KEYBOARD
317 keyboard_type=KBD_RAW;
319 static struct os2_key_packet os2_key1, os2_key2;
320 static struct os2_buffer os2_in1, os2_in2, os2_out1, os2_out2;
321 int r;
322 if ((r = DosMonOpen("KBD$", &os2_hmon))) {
323 fprintf(stderr, "DosMonOpen: %d\n", r);
324 sleep(1);
325 goto std;
327 os2_key = OS2_ALIGN(os2_key);
328 os2_in = OS2_ALIGN(os2_in);
329 os2_out = OS2_ALIGN(os2_out);
330 os2_in->cb = sizeof(struct os2_buffer) - sizeof(USHORT);
331 os2_out->cb = sizeof(struct os2_buffer) - sizeof(USHORT);
332 if ((r = DosMonReg(os2_hmon, (void *)os2_in, (void *)os2_out, MONITOR_END, -1))) {
333 if (r = ERROR_MONITORS_NOT_SUPPORTED) {
334 fprintf(stderr, "RAW keyboard is disabled. Please run 0verkill in full-screen session.%c%c%c", (char)7, (char)7, (char)7);
335 sleep(5);
336 } else {
337 fprintf(stderr, "DosMonReg: %d\n", r);
338 sleep(1);
340 goto std1;
343 memset(keyboard,0,128);
344 memset(old_keyboard,0,128);
345 return;
346 std1: DosMonClose(os2_hmon);
347 std:
348 #endif
350 /* standard keyboard */
351 keyboard_type=KBD_STD;
352 /* nothing to initialize */
353 current_key=0;
354 return;
358 void kbd_close(void)
360 switch(keyboard_type)
362 #ifdef HAVE_RAW_KEYBOARD
363 case KBD_RAW:
364 ioctl(0,KDSKBMODE,oldkbmode);
365 return;
366 #endif
368 #ifdef HAVE_OS2_KEYBOARD
369 case KBD_RAW:
370 DosMonClose(os2_hmon);
371 return;
372 #endif
374 case KBD_STD:
375 /* nothing to close */
376 return;
381 /* convert key from scancode to key constant */
382 int remap_out(int k)
384 int remap_table[128]={
385 0,K_ESCAPE,'1','2','3','4','5','6','7','8','9','0','-','=',K_BACKSPACE,K_TAB,
386 'q','w','e','r','t','y','u','i','o','p','[',']',K_ENTER,K_LEFT_CTRL,'a','s',
387 'd','f','g','h','j','k','l',';','\'','`',K_LEFT_SHIFT,'\\','z','x','c','v',
388 'b','n','m',',','.','/',K_RIGHT_SHIFT,K_NUM_ASTERISK,K_LEFT_ALT,' ',K_CAPS_LOCK,K_F1,K_F2,K_F3,K_F4,K_F5,
389 K_F6,K_F7,K_F8,K_F9,K_F10,K_NUM_LOCK,K_SCROLL_LOCK,K_NUM7,K_NUM8,K_NUM9,K_NUM_MINUS,K_NUM4,K_NUM5,K_NUM6,K_NUM_PLUS,K_NUM1,
390 K_NUM2,K_NUM3,K_NUM0,K_NUM_DOT,0,0,0,K_F11,K_F12,0,0,0,0,0,0,0,
391 K_NUM_ENTER,K_RIGHT_CTRL,K_NUM_SLASH,K_SYSRQ,K_RIGHT_ALT,0,K_HOME,K_UP,K_PGUP,K_LEFT,K_RIGHT,K_END,K_DOWN,K_PGDOWN,K_INSERT,K_DELETE,
392 0,0,0,0,0,0,0,K_PAUSE,0,0,0,0,0,0,0,0
395 return remap_table[k];
399 /* convert key constant to scancode */
400 int remap_in(int k)
402 switch (k)
404 case K_ESCAPE: return 1;
405 case '1': return 2;
406 case '2': return 3;
407 case '3': return 4;
408 case '4': return 5;
409 case '5': return 6;
410 case '6': return 7;
411 case '7': return 8;
412 case '8': return 9;
413 case '9': return 10;
414 case '0': return 11;
415 case '-': return 12;
416 case '=': return 13;
417 case K_BACKSPACE: return 14;
418 case K_TAB: return 15;
419 case 'q': return 16;
420 case 'w': return 17;
421 case 'e': return 18;
422 case 'r': return 19;
423 case 't': return 20;
424 case 'y': return 21;
425 case 'u': return 22;
426 case 'i': return 23;
427 case 'o': return 24;
428 case 'p': return 25;
429 case '[': return 26;
430 case ']': return 27;
431 case K_ENTER: return 28;
432 case K_LEFT_CTRL: return 29;
433 case 'a': return 30;
434 case 's': return 31;
435 case 'd': return 32;
436 case 'f': return 33;
437 case 'g': return 34;
438 case 'h': return 35;
439 case 'j': return 36;
440 case 'k': return 37;
441 case 'l': return 38;
442 case ';': return 39;
443 case '\'': return 40;
444 case '`': return 41;
445 case K_LEFT_SHIFT: return 42;
446 case '\\': return 43;
447 case 'z': return 44;
448 case 'x': return 45;
449 case 'c': return 46;
450 case 'v': return 47;
451 case 'b': return 48;
452 case 'n': return 49;
453 case 'm': return 50;
454 case ',': return 51;
455 case '.': return 52;
456 case '/': return 53;
457 case K_RIGHT_SHIFT: return 54;
458 case K_NUM_ASTERISK: return 55;
459 case K_LEFT_ALT: return 56;
460 case ' ': return 57;
461 case K_CAPS_LOCK: return 58;
462 case K_F1: return 59;
463 case K_F2: return 60;
464 case K_F3: return 61;
465 case K_F4: return 62;
466 case K_F5: return 63;
467 case K_F6: return 64;
468 case K_F7: return 65;
469 case K_F8: return 66;
470 case K_F9: return 67;
471 case K_F10: return 68;
472 case K_NUM_LOCK: return 69;
473 case K_SCROLL_LOCK: return 70;
474 case K_NUM7: return 71;
475 case K_NUM8: return 72;
476 case K_NUM9: return 73;
477 case K_NUM_MINUS: return 74;
478 case K_NUM4: return 75;
479 case K_NUM5: return 76;
480 case K_NUM6: return 77;
481 case K_NUM_PLUS: return 78;
482 case K_NUM1: return 79;
483 case K_NUM2: return 80;
484 case K_NUM3: return 81;
485 case K_NUM0: return 82;
486 case K_NUM_DOT: return 83;
487 case K_F11: return 87;
488 case K_F12: return 88;
489 case K_NUM_ENTER: return 96;
490 case K_RIGHT_CTRL: return 97;
491 case K_NUM_SLASH: return 98;
492 case K_SYSRQ: return 99;
493 case K_RIGHT_ALT: return 100;
494 case K_HOME: return 102;
495 case K_UP: return 103;
496 case K_PGUP: return 104;
497 case K_LEFT: return 105;
498 case K_RIGHT: return 106;
499 case K_END: return 107;
500 case K_DOWN: return 108;
501 case K_PGDOWN: return 109;
502 case K_INSERT: return 110;
503 case K_DELETE: return 111;
504 case K_PAUSE: return 119;
505 default: return 0;
511 /* returns zero if nothing was read, non-zero otherwise */
512 int kbd_update(void)
514 unsigned char buffer[KBD_BUFFER_SIZE];
515 int bytesread,a;
517 switch(keyboard_type)
519 case KBD_RAW:
520 memcpy(old_keyboard,keyboard,128);
521 #ifndef HAVE_OS2_KEYBOARD
522 bytesread=read(0,buffer,KBD_BUFFER_SIZE);
523 #else
524 bytesread=os2_read_mon(buffer, KBD_BUFFER_SIZE);
525 #endif
526 if (bytesread<=0)return 0;
527 read_again:
528 for (a=0;a<bytesread;a++)
529 keyboard[(buffer[a])&127]=!((buffer[a])&128);
530 if (bytesread==KBD_BUFFER_SIZE)
532 #ifndef HAVE_OS2_KEYBOARD
533 bytesread=read(0,buffer,KBD_BUFFER_SIZE);
534 #else
535 bytesread=os2_read_mon(buffer, KBD_BUFFER_SIZE);
536 #endif
537 if (bytesread<=0)return 1;
538 goto read_again;
541 /* CTRL-C */
542 if ((keyboard[29]||keyboard[97])&&keyboard[46])
543 raise(SIGINT);
545 #ifdef HAVE_VT_SWITCH
546 /* console switching */
547 if (keyboard[56]||keyboard[100]) /* alt */
549 for(a=59;a<=68;a++) /* function keys */
550 if (keyboard[a])
552 memset(keyboard,0,128); /* terminal is inactive=>keys can't be pressed */
553 memset(old_keyboard,0,128); /* terminal is inactive=>keys can't be pressed */
554 ioctl(0,VT_ACTIVATE,a-58); /* VT switch */
555 break;
557 if (keyboard[87])
559 memset(keyboard,0,128); /* terminal is inactive=>keys can't be pressed */
560 memset(old_keyboard,0,128); /* terminal is inactive=>keys can't be pressed */
561 ioctl(0,VT_ACTIVATE,11); /* VT switch */
563 else if (keyboard[88])
565 memset(keyboard,0,128); /* terminal is inactive=>keys can't be pressed */
566 memset(old_keyboard,0,128); /* terminal is inactive=>keys can't be pressed */
567 ioctl(0,VT_ACTIVATE,12); /* VT switch */
570 #endif
571 return 1;
573 case KBD_STD:
574 current_key=0;
575 if (!kbhit())return 0;
576 current_key=getkey();
577 return 1;
579 return 0;
583 /* returns 1 if given key is pressed, 0 otherwise */
584 int kbd_is_pressed(int key)
586 switch(keyboard_type)
588 case KBD_RAW:
589 return keyboard[remap_in(key)];
591 case KBD_STD:
592 if (key==K_LEFT_SHIFT||key==K_RIGHT_SHIFT)return shift_pressed;
593 return (current_key==key);
595 return 0;
599 /* same as kbd_is_pressed but tests rising edge of the key */
600 int kbd_was_pressed(int key)
602 switch(keyboard_type)
604 case KBD_RAW:
605 return !old_keyboard[remap_in(key)]&&keyboard[remap_in(key)];
607 case KBD_STD:
608 return kbd_is_pressed(key);
610 return 0;
614 void kbd_wait_for_key(void)
616 fd_set fds;
618 #ifdef __EMX__
619 if (keyboard_type == KBD_RAW) return;
620 #endif
621 FD_ZERO(&fds);
622 FD_SET(0,&fds);
623 select(1,&fds,NULL,NULL,0);
626 #else
627 #include "winkbd.c"
628 #endif