Fix a few conversion bugs. For example, GLshort->GLfloat conversion
[mesa.git] / src / glut / dos / PC_HW / pc_keyb.c
1 /*
2 * PC/HW routine collection v1.3 for DOS/DJGPP
3 *
4 * Copyright (C) 2002 - Daniel Borca
5 * Email : dborca@yahoo.com
6 * Web : http://www.geocities.com/dborca
7 */
8
9
10 #include <pc.h>
11 #include <sys/exceptn.h>
12 #include <sys/farptr.h>
13
14 #include "pc_hw.h"
15
16
17 #define KEYB_IRQ 1
18
19 #define KEY_BUFFER_SIZE 64
20
21 #define KB_MODIFIERS (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG | KB_LWIN_FLAG | KB_RWIN_FLAG | KB_MENU_FLAG)
22 #define KB_LED_FLAGS (KB_SCROLOCK_FLAG | KB_NUMLOCK_FLAG | KB_CAPSLOCK_FLAG)
23
24 static int keyboard_installed;
25
26 static volatile struct {
27 volatile int start, end;
28 volatile int key[KEY_BUFFER_SIZE];
29 } key_buffer;
30
31 static volatile int key_enhanced, key_pause_loop, key_shifts;
32 static int leds_ok = TRUE;
33 static int in_a_terrupt = FALSE;
34 static volatile char pc_key[KEY_MAX];
35
36
37 /* convert Allegro format scancodes into key_shifts flag bits */
38 static unsigned short modifier_table[KEY_MAX - KEY_MODIFIERS] = {
39 KB_SHIFT_FLAG, KB_SHIFT_FLAG, KB_CTRL_FLAG,
40 KB_CTRL_FLAG, KB_ALT_FLAG, KB_ALT_FLAG,
41 KB_LWIN_FLAG, KB_RWIN_FLAG, KB_MENU_FLAG,
42 KB_SCROLOCK_FLAG, KB_NUMLOCK_FLAG, KB_CAPSLOCK_FLAG
43 };
44
45
46 /* lookup table for converting hardware scancodes into Allegro format */
47 static unsigned char hw_to_mycode[128] = {
48 /* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2,
49 /* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6,
50 /* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0,
51 /* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB,
52 /* 0x10 */ KEY_Q, KEY_W, KEY_E, KEY_R,
53 /* 0x14 */ KEY_T, KEY_Y, KEY_U, KEY_I,
54 /* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE,
55 /* 0x1C */ KEY_ENTER, KEY_LCONTROL, KEY_A, KEY_S,
56 /* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H,
57 /* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_COLON,
58 /* 0x28 */ KEY_QUOTE, KEY_TILDE, KEY_LSHIFT, KEY_BACKSLASH,
59 /* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V,
60 /* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA,
61 /* 0x34 */ KEY_STOP, KEY_SLASH, KEY_RSHIFT, KEY_ASTERISK,
62 /* 0x38 */ KEY_ALT, KEY_SPACE, KEY_CAPSLOCK, KEY_F1,
63 /* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5,
64 /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9,
65 /* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_SCRLOCK, KEY_7_PAD,
66 /* 0x48 */ KEY_8_PAD, KEY_9_PAD, KEY_MINUS_PAD, KEY_4_PAD,
67 /* 0x4C */ KEY_5_PAD, KEY_6_PAD, KEY_PLUS_PAD, KEY_1_PAD,
68 /* 0x50 */ KEY_2_PAD, KEY_3_PAD, KEY_0_PAD, KEY_DEL_PAD,
69 /* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11,
70 /* 0x58 */ KEY_F12, 0, 0, KEY_LWIN,
71 /* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0,
72 /* 0x60 */ 0, 0, 0, 0,
73 /* 0x64 */ 0, 0, 0, 0,
74 /* 0x68 */ 0, 0, 0, 0,
75 /* 0x6C */ 0, 0, 0, 0,
76 /* 0x70 */ KEY_KANA, 0, 0, KEY_ABNT_C1,
77 /* 0x74 */ 0, 0, 0, 0,
78 /* 0x78 */ 0, KEY_CONVERT, 0, KEY_NOCONVERT,
79 /* 0x7C */ 0, KEY_YEN, 0, 0
80 };
81
82
83 /* lookup table for converting extended hardware codes into Allegro format */
84 static unsigned char hw_to_mycode_ex[128] = {
85 /* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2,
86 /* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6,
87 /* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0,
88 /* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB,
89 /* 0x10 */ KEY_CIRCUMFLEX, KEY_AT, KEY_COLON2, KEY_R,
90 /* 0x14 */ KEY_KANJI, KEY_Y, KEY_U, KEY_I,
91 /* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE,
92 /* 0x1C */ KEY_ENTER_PAD, KEY_RCONTROL, KEY_A, KEY_S,
93 /* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H,
94 /* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_COLON,
95 /* 0x28 */ KEY_QUOTE, KEY_TILDE, 0, KEY_BACKSLASH,
96 /* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V,
97 /* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA,
98 /* 0x34 */ KEY_STOP, KEY_SLASH_PAD, 0, KEY_PRTSCR,
99 /* 0x38 */ KEY_ALTGR, KEY_SPACE, KEY_CAPSLOCK, KEY_F1,
100 /* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5,
101 /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9,
102 /* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_PAUSE, KEY_HOME,
103 /* 0x48 */ KEY_UP, KEY_PGUP, KEY_MINUS_PAD, KEY_LEFT,
104 /* 0x4C */ KEY_5_PAD, KEY_RIGHT, KEY_PLUS_PAD, KEY_END,
105 /* 0x50 */ KEY_DOWN, KEY_PGDN, KEY_INSERT, KEY_DEL,
106 /* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11,
107 /* 0x58 */ KEY_F12, 0, 0, KEY_LWIN,
108 /* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0,
109 /* 0x60 */ 0, 0, 0, 0,
110 /* 0x64 */ 0, 0, 0, 0,
111 /* 0x68 */ 0, 0, 0, 0,
112 /* 0x6C */ 0, 0, 0, 0,
113 /* 0x70 */ 0, 0, 0, 0,
114 /* 0x74 */ 0, 0, 0, 0,
115 /* 0x78 */ 0, 0, 0, 0,
116 /* 0x7C */ 0, 0, 0, 0
117 };
118
119
120 /* default mapping table for the US keyboard layout */
121 static unsigned short standard_key_ascii_table[KEY_MAX] = {
122 /* start */ 0,
123 /* alphabet */ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
124 /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
125 /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
126 /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
127 /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ',
128 /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
129 /* numpad */ '/', '*', '-', '+', '.', 13,
130 /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
131 };
132
133
134 /* capslock mapping table for the US keyboard layout */
135 static unsigned short standard_key_capslock_table[KEY_MAX] = {
136 /* start */ 0,
137 /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
138 /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
139 /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
140 /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
141 /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ',
142 /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
143 /* numpad */ '/', '*', '-', '+', '.', 13,
144 /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
145 };
146
147
148 /* shifted mapping table for the US keyboard layout */
149 static unsigned short standard_key_shift_table[KEY_MAX] = {
150 /* start */ 0,
151 /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
152 /* numbers */ ')', '!', '@', '#', '$', '%', '^', '&', '*', '(',
153 /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
154 /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
155 /* misc chars */ 27, '~', '_', '+', 8, 9, '{', '}', 13, ':', '"', '|', '|', '<', '>', '?', ' ',
156 /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
157 /* numpad */ '/', '*', '-', '+', '.', 13,
158 /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
159 };
160
161
162 /* ctrl+key mapping table for the US keyboard layout */
163 static unsigned short standard_key_control_table[KEY_MAX] = {
164 /* start */ 0,
165 /* alphabet */ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
166 /* numbers */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
167 /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
168 /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
169 /* misc chars */ 27, 2, 2, 2, 127, 127, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2,
170 /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
171 /* numpad */ 2, 2, 2, 2, 2, 10,
172 /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
173 };
174
175
176 /* convert numeric pad scancodes into arrow codes */
177 static unsigned char numlock_table[10] = {
178 KEY_INSERT, KEY_END, KEY_DOWN, KEY_PGDN, KEY_LEFT,
179 KEY_5_PAD, KEY_RIGHT, KEY_HOME, KEY_UP, KEY_PGUP
180 };
181
182
183 /* kb_wait_for_write_ready:
184 * Wait for the keyboard controller to set the ready-for-write bit.
185 */
186 static __inline int
187 kb_wait_for_write_ready (void)
188 {
189 int timeout = 4096;
190
191 while ((timeout > 0) && (inportb(0x64) & 2)) timeout--;
192
193 return (timeout > 0);
194 }
195
196
197 /* kb_wait_for_read_ready:
198 * Wait for the keyboard controller to set the ready-for-read bit.
199 */
200 static __inline int
201 kb_wait_for_read_ready (void)
202 {
203 int timeout = 16384;
204
205 while ((timeout > 0) && (!(inportb(0x64) & 1))) timeout--;
206
207 return (timeout > 0);
208 }
209
210
211 /* kb_send_data:
212 * Sends a byte to the keyboard controller. Returns 1 if all OK.
213 */
214 static __inline int
215 kb_send_data (unsigned char data)
216 {
217 int resends = 4;
218 int timeout, temp;
219
220 do {
221 if (!kb_wait_for_write_ready())
222 return 0;
223
224 outportb(0x60, data);
225 timeout = 4096;
226
227 while (--timeout > 0) {
228 if (!kb_wait_for_read_ready())
229 return 0;
230
231 temp = inportb(0x60);
232
233 if (temp == 0xFA)
234 return 1;
235
236 if (temp == 0xFE)
237 break;
238 }
239 } while ((resends-- > 0) && (timeout > 0));
240
241 return 0;
242 }
243
244
245 static void
246 update_leds (int leds)
247 {
248 if (leds_ok) {
249 if (!in_a_terrupt)
250 DISABLE();
251
252 if (!kb_send_data(0xED)) {
253 kb_send_data(0xF4);
254 leds_ok = FALSE;
255 } else if (!kb_send_data((leds >> 8) & 7)) {
256 kb_send_data(0xF4);
257 leds_ok = FALSE;
258 }
259
260 if (!in_a_terrupt)
261 ENABLE();
262 }
263 } ENDOFUNC(update_leds)
264
265
266 static void
267 inject_key (int scancode)
268 {
269 unsigned short *table;
270
271 if ((scancode >= KEY_0_PAD) && (scancode <= KEY_9_PAD)) {
272 if (((key_shifts & KB_NUMLOCK_FLAG) != 0) == ((key_shifts & KB_SHIFT_FLAG) != 0)) {
273 scancode = numlock_table[scancode - KEY_0_PAD];
274 }
275 table = standard_key_ascii_table;
276 } else if (key_shifts & KB_CTRL_FLAG) {
277 table = standard_key_control_table;
278 } else if (key_shifts & KB_SHIFT_FLAG) {
279 if (key_shifts & KB_CAPSLOCK_FLAG) {
280 if (standard_key_ascii_table[scancode] == standard_key_capslock_table[scancode]) {
281 table = standard_key_shift_table;
282 } else {
283 table = standard_key_ascii_table;
284 }
285 } else {
286 table = standard_key_shift_table;
287 }
288 } else if (key_shifts & KB_CAPSLOCK_FLAG) {
289 table = standard_key_capslock_table;
290 } else {
291 table = standard_key_ascii_table;
292 }
293
294 key_buffer.key[key_buffer.end++] = (scancode << 16) | table[scancode];
295
296 if (key_buffer.end >= KEY_BUFFER_SIZE)
297 key_buffer.end = 0;
298 if (key_buffer.end == key_buffer.start) {
299 key_buffer.start++;
300 if (key_buffer.start >= KEY_BUFFER_SIZE)
301 key_buffer.start = 0;
302 }
303 } ENDOFUNC(inject_key)
304
305
306 static void
307 handle_code (int scancode, int keycode)
308 {
309 in_a_terrupt++;
310
311 if (keycode == 0) { /* pause */
312 inject_key(scancode);
313 pc_key[KEY_PAUSE] ^= TRUE;
314 } else if (scancode) {
315 int flag;
316
317 if (scancode >= KEY_MODIFIERS) {
318 flag = modifier_table[scancode - KEY_MODIFIERS];
319 } else {
320 flag = 0;
321 }
322 if ((char)keycode < 0) { /* release */
323 pc_key[scancode] = FALSE;
324 if (flag & KB_MODIFIERS) {
325 key_shifts &= ~flag;
326 }
327 } else { /* keypress */
328 pc_key[scancode] = TRUE;
329 if (flag & KB_MODIFIERS) {
330 key_shifts |= flag;
331 }
332 if (flag & KB_LED_FLAGS) {
333 key_shifts ^= flag;
334 update_leds(key_shifts);
335 }
336 if (scancode < KEY_MODIFIERS) {
337 inject_key(scancode);
338 }
339 }
340 }
341
342 in_a_terrupt--;
343 } ENDOFUNC(handle_code)
344
345
346 static int
347 keyboard ()
348 {
349 unsigned char temp, scancode;
350
351 temp = inportb(0x60);
352
353 if (temp <= 0xe1) {
354 if (key_pause_loop) {
355 if (!--key_pause_loop) handle_code(KEY_PAUSE, 0);
356 } else
357 switch (temp) {
358 case 0xe0:
359 key_enhanced = TRUE;
360 break;
361 case 0xe1:
362 key_pause_loop = 5;
363 break;
364 default:
365 if (key_enhanced) {
366 key_enhanced = FALSE;
367 scancode = hw_to_mycode_ex[temp & 0x7f];
368 } else {
369 scancode = hw_to_mycode[temp & 0x7f];
370 }
371 handle_code(scancode, temp);
372 }
373 }
374
375 if (((temp==0x4F)||(temp==0x53))&&(key_shifts&KB_CTRL_FLAG)&&(key_shifts&KB_ALT_FLAG)) {
376 /* Hack alert:
377 * only SIGINT (but not Ctrl-Break)
378 * calls the destructors and will safely clean up
379 */
380 __asm("\n\
381 movb $0x79, %%al \n\
382 call ___djgpp_hw_exception \n\
383 ":::"%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
384 }
385
386 __asm("\n\
387 inb $0x61, %%al \n\
388 movb %%al, %%ah \n\
389 orb $0x80, %%al \n\
390 outb %%al, $0x61 \n\
391 xchgb %%al, %%ah \n\
392 outb %%al, $0x61 \n\
393 movb $0x20, %%al \n\
394 outb %%al, $0x20 \n\
395 ":::"%eax");
396 return 0;
397 } ENDOFUNC(keyboard)
398
399
400 int
401 pc_keypressed (void)
402 {
403 return (key_buffer.start!=key_buffer.end);
404 }
405
406
407 int
408 pc_readkey (void)
409 {
410 if (keyboard_installed) {
411 int key;
412
413 while (key_buffer.start == key_buffer.end) {
414 __dpmi_yield();
415 }
416
417 DISABLE();
418 key = key_buffer.key[key_buffer.start++];
419 if (key_buffer.start >= KEY_BUFFER_SIZE)
420 key_buffer.start = 0;
421 ENABLE();
422
423 return key;
424 } else {
425 return 0;
426 }
427 }
428
429
430 int
431 pc_keydown (int code)
432 {
433 return pc_key[code];
434 }
435
436
437 int
438 pc_keyshifts (void)
439 {
440 return key_shifts;
441 }
442
443
444 void
445 pc_remove_keyb (void)
446 {
447 if (keyboard_installed) {
448 int s1, s2, s3;
449
450 keyboard_installed = FALSE;
451 pc_clexit(pc_remove_keyb);
452
453 DISABLE();
454 _farsetsel(__djgpp_dos_sel);
455 _farnspokew(0x41c, _farnspeekw(0x41a));
456
457 s1 = _farnspeekb(0x417) & 0x80;
458 s2 = _farnspeekb(0x418) & 0xFC;
459 s3 = _farnspeekb(0x496) & 0xF3;
460
461 if (pc_key[KEY_RSHIFT]) { s1 |= 1; }
462 if (pc_key[KEY_LSHIFT]) { s1 |= 2; }
463 if (pc_key[KEY_LCONTROL]) { s2 |= 1; s1 |= 4; }
464 if (pc_key[KEY_ALT]) { s1 |= 8; s2 |= 2; }
465 if (pc_key[KEY_RCONTROL]) { s1 |= 4; s3 |= 4; }
466 if (pc_key[KEY_ALTGR]) { s1 |= 8; s3 |= 8; }
467
468 if (key_shifts & KB_SCROLOCK_FLAG) s1 |= 16;
469 if (key_shifts & KB_NUMLOCK_FLAG) s1 |= 32;
470 if (key_shifts & KB_CAPSLOCK_FLAG) s1 |= 64;
471
472 _farnspokeb(0x417, s1);
473 _farnspokeb(0x418, s2);
474 _farnspokeb(0x496, s3);
475 update_leds(key_shifts);
476
477 ENABLE();
478 pc_remove_irq(KEYB_IRQ);
479 }
480 }
481
482
483 int
484 pc_install_keyb (void)
485 {
486 if (keyboard_installed || pc_install_irq(KEYB_IRQ, keyboard)) {
487 return -1;
488 } else {
489 int s1, s2, s3;
490
491 LOCKDATA(key_buffer);
492 LOCKDATA(key_enhanced);
493 LOCKDATA(key_pause_loop);
494 LOCKDATA(key_shifts);
495 LOCKDATA(leds_ok);
496 LOCKDATA(in_a_terrupt);
497 LOCKDATA(pc_key);
498 LOCKDATA(modifier_table);
499 LOCKDATA(hw_to_mycode);
500 LOCKDATA(hw_to_mycode_ex);
501 LOCKDATA(standard_key_ascii_table);
502 LOCKDATA(standard_key_capslock_table);
503 LOCKDATA(standard_key_shift_table);
504 LOCKDATA(standard_key_control_table);
505 LOCKDATA(numlock_table);
506 LOCKFUNC(update_leds);
507 LOCKFUNC(inject_key);
508 LOCKFUNC(handle_code);
509 LOCKFUNC(keyboard);
510
511 DISABLE();
512 _farsetsel(__djgpp_dos_sel);
513 _farnspokew(0x41c, _farnspeekw(0x41a));
514
515 key_shifts = 0;
516 s1 = _farnspeekb(0x417);
517 s2 = _farnspeekb(0x418);
518 s3 = _farnspeekb(0x496);
519
520 if (s1 & 1) { key_shifts |= KB_SHIFT_FLAG; pc_key[KEY_RSHIFT] = TRUE; }
521 if (s1 & 2) { key_shifts |= KB_SHIFT_FLAG; pc_key[KEY_LSHIFT] = TRUE; }
522 if (s2 & 1) { key_shifts |= KB_CTRL_FLAG; pc_key[KEY_LCONTROL] = TRUE; }
523 if (s2 & 2) { key_shifts |= KB_ALT_FLAG; pc_key[KEY_ALT] = TRUE; }
524 if (s3 & 4) { key_shifts |= KB_CTRL_FLAG; pc_key[KEY_RCONTROL] = TRUE; }
525 if (s3 & 8) { key_shifts |= KB_ALT_FLAG; pc_key[KEY_ALTGR] = TRUE; }
526
527 if (s1 & 16) key_shifts |= KB_SCROLOCK_FLAG;
528 if (s1 & 32) key_shifts |= KB_NUMLOCK_FLAG;
529 if (s1 & 64) key_shifts |= KB_CAPSLOCK_FLAG;
530 update_leds(key_shifts);
531
532 key_enhanced = key_pause_loop = 0;
533 key_buffer.start = key_buffer.end = 0;
534 ENABLE();
535
536 pc_atexit(pc_remove_keyb);
537 keyboard_installed = TRUE;
538 return 0;
539 }
540 }