This commit was generated by cvs2svn to compensate for changes in r5,
[btb/d2x.git] / arch / dos / key.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
11 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13 /*
14  * $Source: /cvs/cvsroot/d2x/arch/dos/key.c,v $
15  * $Revision: 1.1.1.2 $
16  * $Author: bradleyb $
17  * $Date: 2001-01-19 03:33:52 $
18  * 
19  * Functions for keyboard handler.
20  * 
21  * $Log: not supported by cvs2svn $
22  * Revision 1.1.1.1  1999/06/14 21:58:32  donut
23  * Import of d1x 1.37 source.
24  *
25  * Revision 1.35  1995/01/25  20:13:30  john
26  * Took out not passing keys to debugger if w10.
27  * 
28  * Revision 1.34  1995/01/14  19:19:31  john
29  * Made so when you press Shift+Baskspace, it release keys autmatically.
30  * 
31  * Revision 1.33  1994/12/13  09:21:48  john
32  * Took out keyd_editor_mode, and KEY_DEBUGGED stuff for NDEBUG versions.
33  * 
34  * Revision 1.32  1994/11/12  13:52:01  john
35  * Fixed bug with code that cleared bios buffer.
36  * 
37  * Revision 1.31  1994/10/24  15:16:16  john
38  * Added code to detect KEY_PAUSE.
39  * 
40  * Revision 1.30  1994/10/24  13:57:53  john
41  * Hacked in support for pause key onto code 0x61.
42  * 
43  * Revision 1.29  1994/10/21  15:18:13  john
44  * *** empty log message ***
45  * 
46  * Revision 1.28  1994/10/21  15:17:24  john
47  * Made LSHIFT+BACKSPACE do what PrtScr used to.
48  * 
49  * Revision 1.27  1994/09/22  16:09:18  john
50  * Fixed some virtual memory lockdown problems with timer and
51  * joystick.
52  * 
53  * Revision 1.26  1994/09/15  21:32:47  john
54  * Added bounds checking for down_count scancode
55  * parameter.
56  * 
57  * Revision 1.25  1994/08/31  12:22:20  john
58  * Added KEY_DEBUGGED
59  * 
60  * Revision 1.24  1994/08/24  18:53:48  john
61  * Made Cyberman read like normal mouse; added dpmi module; moved
62  * mouse from assembly to c. Made mouse buttons return time_down.
63  * 
64  * Revision 1.23  1994/08/18  15:17:51  john
65  * *** empty log message ***
66  * 
67  * Revision 1.22  1994/08/18  15:16:38  john
68  * fixed some bugs with clear_key_times and then
69  * removed it because i fixed key_flush to do the
70  * same.
71  * 
72  * Revision 1.21  1994/08/17  19:01:25  john
73  * Attempted to fix a bug with a key being held down
74  * key_flush called, then the key released having too 
75  * long of a time.
76  * 
77  * Revision 1.20  1994/08/08  10:43:48  john
78  * Recorded when a key was pressed for key_inkey_time.
79  * 
80  * Revision 1.19  1994/06/22  15:00:03  john
81  * Made keyboard close automatically on exit.
82  * 
83  * Revision 1.18  1994/06/21  09:16:29  john
84  * *** empty log message ***
85  * 
86  * Revision 1.17  1994/06/21  09:08:23  john
87  * *** empty log message ***
88  * 
89  * Revision 1.16  1994/06/21  09:05:01  john
90  * *** empty log message ***
91  * 
92  * Revision 1.15  1994/06/21  09:04:24  john
93  * Made PrtScreen do an int5
94  * 
95  * Revision 1.14  1994/06/17  17:17:06  john
96  * Added keyd_time_last_key_was_pressed or something like that.
97  * 
98  * Revision 1.13  1994/05/14  13:55:16  matt
99  * Added #define to control key passing to bios
100  * 
101  * Revision 1.12  1994/05/05  18:09:39  john
102  * Took out BIOS to prevent stuck keys.
103  * 
104  * Revision 1.11  1994/05/03  17:39:12  john
105  * *** empty log message ***
106  * 
107  * Revision 1.10  1994/04/29  12:14:20  john
108  * Locked all memory used during interrupts so that program
109  * won't hang when using virtual memory.
110  * 
111  * Revision 1.9  1994/04/28  23:49:41  john
112  * Made key_flush flush more keys and also did something else but i forget what.
113  * 
114  * Revision 1.8  1994/04/22  12:52:12  john
115  * *** empty log message ***
116  * 
117  * Revision 1.7  1994/04/01  10:44:59  mike
118  * Change key_getch() to call getch() if our interrupt hasn't been installed.
119  * 
120  * Revision 1.6  1994/03/09  10:45:48  john
121  * Neatend code a bit.
122  * 
123  * Revision 1.5  1994/02/17  17:24:16  john
124  * Neatened up a bit.
125  * 
126  * Revision 1.4  1994/02/17  16:30:29  john
127  * Put in code to pass keys when in debugger.
128  * 
129  * Revision 1.3  1994/02/17  15:57:59  john
130  * Made handler not chain to BIOS handler.
131  * 
132  * Revision 1.2  1994/02/17  15:56:06  john
133  * Initial version.
134  * 
135  * Revision 1.1  1994/02/17  15:54:07  john
136  * Initial revision
137  * 
138  * 
139  */
140
141 //#define PASS_KEYS_TO_BIOS     1                       //if set, bios gets keys
142
143 #include <conf.h>
144 #include <stdlib.h>
145 #include <stdio.h>
146 #include <dos.h>
147
148 //#define WATCOM_10
149 #ifdef __DJGPP__
150 #include <dpmi.h>
151 #define _far
152 #define __far
153 #define __interrupt
154 #define near
155 _go32_dpmi_seginfo kbd_hand_info;
156 #endif
157 #include "error.h"
158 #include "key.h"
159 #include "timer.h"
160 #include "u_dpmi.h"
161
162 #define KEY_BUFFER_SIZE 16
163
164
165 //-------- Variable accessed by outside functions ---------
166 unsigned char                           keyd_buffer_type;               // 0=No buffer, 1=buffer ASCII, 2=buffer scans
167 unsigned char                           keyd_repeat;
168 unsigned char                           keyd_editor_mode;
169 volatile unsigned char  keyd_last_pressed;
170 volatile unsigned char  keyd_last_released;
171 volatile unsigned char  keyd_pressed[256];
172 volatile int                            keyd_time_when_last_pressed;
173
174 typedef struct keyboard {
175         unsigned short          keybuffer[KEY_BUFFER_SIZE];
176         fix                                     time_pressed[KEY_BUFFER_SIZE];
177         fix                                     TimeKeyWentDown[256];
178         fix                                     TimeKeyHeldDown[256];
179         unsigned int            NumDowns[256];
180         unsigned int            NumUps[256];
181         unsigned int            keyhead, keytail;
182         unsigned char           E0Flag;
183         unsigned char           E1Flag;
184         int                                     in_key_handler;
185 #ifdef __DJGPP__
186         _go32_dpmi_seginfo prev_int_9;
187 #else
188         void (__interrupt __far *prev_int_9)();
189 #endif
190 } keyboard;
191
192 static volatile keyboard key_data;
193
194 static unsigned char Installed=0;
195
196 unsigned char ascii_table[128] = 
197 { 255, 255, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=',255,255,
198   'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 255, 255,
199   'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', 39, '`',
200   255, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 255,'*',
201   255, ' ', 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255,255,
202   255, 255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
203   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
204   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
205   255,255,255,255,255,255,255,255 };
206
207 unsigned char shifted_ascii_table[128] = 
208 { 255, 255, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+',255,255,
209   'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 255, 255,
210   'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', 
211   255, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 255,255,
212   255, ' ', 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255,255,
213   255, 255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
214   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
215   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
216   255,255,255,255,255,255,255,255 };
217 /*
218 char * key_text[256] = {
219 "","ESC","1","2","3","4","5","6","7","8","9","0","-",
220 "=","BSPC","TAB","Q","W","E","R","T","Y","U","I","O",
221 "P","[","]","\83","LCTRL","A","S","D","F",
222 "G","H","J","K","L",";","'","`",
223 "LSHFT","\\","Z","X","C","V","B","N","M",",",
224 ".","/","RSHFT","PAD*","LALT","SPC",
225 "CPSLK","F1","F2","F3","F4","F5","F6","F7","F8","F9",
226 "F10","NMLCK","SCLK","PAD7","PAD8","PAD9","PAD-",
227 "PAD4","PAD5","PAD6","PAD+","PAD1","PAD2","PAD3","PAD0",
228 "PAD.","","","","F11","F12","","","","","","","","","",
229 "","","","","","","","","","","","","","","","","","","","",
230 "","","","","","","","","","","","","","","","","","","","",
231 "","","","","","","","","","","","","","","","","","",
232 "PAD\83","RCTRL","","","","","","","","","","","","","",
233 "","","","","","","","","","","PAD/","","","RALT","",
234 "","","","","","","","","","","","","","HOME","\82","PGUP",
235 "","\81","","\7f","","END","\80","PGDN","INS",
236 "DEL","","","","","","","","","","","","","","","","","",
237 "","","","","","","","","","","","","","","","","","","","",
238 "","","","","","","" };
239 */
240 unsigned char key_to_ascii(int keycode )
241 {
242         int shifted;
243
244         shifted = keycode & KEY_SHIFTED;
245         keycode &= 0xFF;
246
247         if ( keycode>=127 )
248                 return 255;
249
250         if (shifted)
251                 return shifted_ascii_table[keycode];
252         else
253                 return ascii_table[keycode];
254 }
255
256 void key_clear_bios_buffer_all()
257 {
258 #ifdef __WATCOMC__
259         // Clear keyboard buffer...
260         *(ushort *)0x41a=*(ushort *)0x41c;
261         // Clear the status bits...
262         *(ubyte *)0x417 = 0;
263         *(ubyte *)0x418 = 0;
264 #else
265         _farpokew(_dos_ds,0x41a, _farpeekw(_dos_ds, 0x41c));
266         _farpokeb(_dos_ds,0x417, 0);
267         _farpokeb(_dos_ds,0x418, 0);
268 #endif
269 }
270
271 void key_clear_bios_buffer()
272 {
273 #ifdef __WATCOMC__
274         // Clear keyboard buffer...
275         *(ushort *)0x41a=*(ushort *)0x41c;
276 #else
277         _farpokew(_dos_ds,0x41a, _farpeekw(_dos_ds, 0x41c));
278 #endif
279 }
280
281 void key_flush()
282 {
283         int i;
284         fix CurTime;
285
286         _disable();
287
288         // Clear the BIOS buffer
289         key_clear_bios_buffer();
290
291         key_data.keyhead = key_data.keytail = 0;
292
293         //Clear the keyboard buffer
294         for (i=0; i<KEY_BUFFER_SIZE; i++ )      {
295                 key_data.keybuffer[i] = 0;
296                 key_data.time_pressed[i] = 0;
297         }
298         
299         //Clear the keyboard array
300
301         CurTime =timer_get_fixed_secondsX();
302
303         for (i=0; i<256; i++ )  {
304                 keyd_pressed[i] = 0;
305                 key_data.TimeKeyWentDown[i] = CurTime;
306                 key_data.TimeKeyHeldDown[i] = 0;
307                 key_data.NumDowns[i]=0;
308                 key_data.NumUps[i]=0;
309         }
310         _enable();
311 }
312
313 int add_one( int n )
314 {
315         n++;
316         if ( n >= KEY_BUFFER_SIZE ) n=0;
317         return n;
318 }
319
320 // Returns 1 if character waiting... 0 otherwise
321 int key_checkch()
322 {
323         int is_one_waiting = 0;
324
325         _disable();
326
327         key_clear_bios_buffer();
328
329         if (key_data.keytail!=key_data.keyhead)
330                 is_one_waiting = 1;
331         _enable();
332         return is_one_waiting;
333 }
334
335 int key_inkey()
336 {
337         int key = 0;
338
339         _disable();
340
341         key_clear_bios_buffer();
342
343         if (key_data.keytail!=key_data.keyhead) {
344                 key = key_data.keybuffer[key_data.keyhead];
345                 key_data.keyhead = add_one(key_data.keyhead);
346         }
347         _enable();
348         return key;
349 }
350
351 int key_inkey_time(fix * time)
352 {
353         int key = 0;
354
355         _disable();
356
357         key_clear_bios_buffer();
358
359         if (key_data.keytail!=key_data.keyhead) {
360                 key = key_data.keybuffer[key_data.keyhead];
361                 *time = key_data.time_pressed[key_data.keyhead];
362                 key_data.keyhead = add_one(key_data.keyhead);
363         }
364         _enable();
365         return key;
366 }
367
368
369
370 int key_peekkey()
371 {
372         int key = 0;
373
374         _disable();
375
376         key_clear_bios_buffer();
377
378         if (key_data.keytail!=key_data.keyhead) {
379                 key = key_data.keybuffer[key_data.keyhead];
380         }
381         _enable();
382         return key;
383 }
384
385 // If not installed, uses BIOS and returns getch();
386 //      Else returns pending key (or waits for one if none waiting).
387 int key_getch()
388 {
389         int dummy=0;
390         
391         if (!Installed)
392                 return getch();
393
394         while (!key_checkch())
395                 dummy++;
396         return key_inkey();
397 }
398
399 unsigned int key_get_shift_status()
400 {
401         unsigned int shift_status = 0;
402
403         _disable();
404
405         key_clear_bios_buffer();
406
407         if ( keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT] )
408                 shift_status |= KEY_SHIFTED;
409
410         if ( keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT] )
411                 shift_status |= KEY_ALTED;
412
413         if ( keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL] )
414                 shift_status |= KEY_CTRLED;
415
416 #ifndef NDEBUG
417         if (keyd_pressed[KEY_DELETE])
418                 shift_status |=KEY_DEBUGGED;
419 #endif
420
421         _enable();
422
423         return shift_status;
424 }
425
426 // Returns the number of seconds this key has been down since last call.
427 fix key_down_time(int scancode) {
428         fix time_down, time;
429
430         if ((scancode<0)|| (scancode>255)) return 0;
431
432 #ifndef NDEBUG
433         if (keyd_editor_mode && key_get_shift_status() )
434                 return 0;  
435 #endif
436
437         _disable();
438
439         if ( !keyd_pressed[scancode] )  {
440                 time_down = key_data.TimeKeyHeldDown[scancode];
441                 key_data.TimeKeyHeldDown[scancode] = 0;
442         } else  {
443                 time = timer_get_fixed_secondsX();
444                 time_down =  time - key_data.TimeKeyWentDown[scancode];
445                 key_data.TimeKeyWentDown[scancode] = time;
446         }
447         _enable();
448
449         return time_down;
450 }
451
452 // Returns number of times key has went from up to down since last call.
453 unsigned int key_down_count(int scancode)       {
454         int n;
455
456         if ((scancode<0)|| (scancode>255)) return 0;
457
458         _disable();
459         n = key_data.NumDowns[scancode];
460         key_data.NumDowns[scancode] = 0;
461         _enable();
462
463         return n;
464 }
465
466
467 // Returns number of times key has went from down to up since last call.
468 unsigned int key_up_count(int scancode) {
469         int n;
470
471         if ((scancode<0)|| (scancode>255)) return 0;
472
473         _disable();
474         n = key_data.NumUps[scancode];
475         key_data.NumUps[scancode] = 0;
476         _enable();
477
478         return n;
479 }
480
481 // Use intrinsic forms so that we stay in the locked interrup code.
482
483 #ifdef __WATCOMC__
484 void Int5();
485 #pragma aux Int5 = "int 5";
486 #else
487 #ifdef __GNUC__
488 #define Int5() asm volatile("int $5")
489 #endif
490 #endif
491
492 #pragma off (check_stack)
493 void __interrupt __far key_handler()
494 {
495         unsigned char scancode, breakbit, temp;
496         unsigned short keycode;
497
498 #ifndef WATCOM_10
499 #ifndef NDEBUG
500 #ifdef __WATCOMC__ /* must have _chain_intr */
501         ubyte * MONO = (ubyte *)(0x0b0000+24*80*2);
502         if (  ((MONO[0]=='D') && (MONO[2]=='B') && (MONO[4]=='G') && (MONO[6]=='>')) ||
503                         ((MONO[14]=='<') && (MONO[16]=='i') && (MONO[18]=='>') && (MONO[20]==' ') && (MONO[22]=='-')) ||
504                         ((MONO[0]==200 ) && (MONO[2]==27) && (MONO[4]==17) )
505                 )
506                 _chain_intr( key_data.prev_int_9 );
507 #endif
508 #endif
509 #endif
510
511         // Read in scancode
512         scancode = inp( 0x60 );
513
514         switch( scancode )      {
515         case 0xE0:
516                 key_data.E0Flag = 0x80;
517                 break;
518         default:
519                 // Parse scancode and break bit
520                 if (key_data.E1Flag > 0 )       {               // Special code for Pause, which is E1 1D 45 E1 9D C5
521                         key_data.E1Flag--;
522                         if ( scancode == 0x1D ) {
523                                 scancode        = KEY_PAUSE;
524                                 breakbit        = 0;
525                         } else if ( scancode == 0x9d ) {
526                                 scancode        = KEY_PAUSE;
527                                 breakbit        = 1;
528                         } else {
529                                 break;          // skip this keycode
530                         }
531                 } else if ( scancode==0xE1 )    {
532                         key_data.E1Flag = 2;
533                         break;
534                 } else {
535                         breakbit        = scancode & 0x80;              // Get make/break bit
536                         scancode &= 0x7f;                                               // Strip make/break bit off of scancode
537                         scancode |= key_data.E0Flag;                                    // Add in extended key code
538                 }
539                 key_data.E0Flag = 0;                                                            // Clear extended key code
540
541                 if (breakbit)   {
542                         // Key going up
543                         keyd_last_released = scancode;
544                         keyd_pressed[scancode] = 0;
545                         key_data.NumUps[scancode]++;
546                         temp = 0;
547                         temp |= keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT];
548                         temp |= keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT];
549                         temp |= keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL];
550 #ifndef NDEBUG
551                         temp |= keyd_pressed[KEY_DELETE];
552                         if ( !(keyd_editor_mode && temp) )
553 #endif          // NOTICE LINK TO ABOVE IF!!!!
554                                 key_data.TimeKeyHeldDown[scancode] += timer_get_fixed_secondsX() - key_data.TimeKeyWentDown[scancode];
555                 } else {
556                         // Key going down
557                         keyd_last_pressed = scancode;
558                         keyd_time_when_last_pressed = timer_get_fixed_secondsX();
559                         if (!keyd_pressed[scancode])    {
560                                 // First time down
561                                 key_data.TimeKeyWentDown[scancode] = timer_get_fixed_secondsX();
562                                 keyd_pressed[scancode] = 1;
563                                 key_data.NumDowns[scancode]++;
564 #ifndef NDEBUG
565                                 if ( (keyd_pressed[KEY_LSHIFT]) && (scancode == KEY_BACKSP) )   {
566                                         keyd_pressed[KEY_LSHIFT] = 0;
567                                         Int5();
568                                 }
569 #endif
570                         } else if (!keyd_repeat) {
571                                 // Don't buffer repeating key if repeat mode is off
572                                 scancode = 0xAA;
573                         }
574
575                         if ( scancode!=0xAA ) {
576                                 keycode = scancode;
577
578                                 if ( keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT] )
579                                         keycode |= KEY_SHIFTED;
580
581                                 if ( keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT] )
582                                         keycode |= KEY_ALTED;
583
584                                 if ( keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL] )
585                                         keycode |= KEY_CTRLED;
586
587 #ifndef NDEBUG
588                                 if ( keyd_pressed[KEY_DELETE] )
589                                         keycode |= KEY_DEBUGGED;
590 #endif
591
592                                 temp = key_data.keytail+1;
593                                 if ( temp >= KEY_BUFFER_SIZE ) temp=0;
594
595                                 if (temp!=key_data.keyhead)     {
596                                         key_data.keybuffer[key_data.keytail] = keycode;
597                                         key_data.time_pressed[key_data.keytail] = keyd_time_when_last_pressed;
598                                         key_data.keytail = temp;
599                                 }
600                         }
601                 }
602         }
603
604 #ifndef NDEBUG
605 #ifdef PASS_KEYS_TO_BIOS
606         _chain_intr( key_data.prev_int_9 );
607 #endif
608 #endif
609
610         temp = inp(0x61);               // Get current port 61h state
611         temp |= 0x80;                   // Turn on bit 7 to signal clear keybrd
612         outp( 0x61, temp );     // Send to port
613         temp &= 0x7f;                   // Turn off bit 7 to signal break
614         outp( 0x61, temp );     // Send to port
615         outp( 0x20, 0x20 );     // Reset interrupt controller
616 }
617
618 #pragma on (check_stack)
619
620 void key_handler_end()  {               // Dummy function to help calculate size of keyboard handler function
621 }
622
623 void key_init()
624 {
625         // Initialize queue
626
627         keyd_time_when_last_pressed = timer_get_fixed_seconds();
628         keyd_buffer_type = 1;
629         keyd_repeat = 1;
630         key_data.in_key_handler = 0;
631         key_data.E0Flag = 0;
632         key_data.E1Flag = 0;
633
634         // Clear the keyboard array
635         key_flush();
636
637         if (Installed) return;
638         Installed = 1;
639
640         //--------------- lock everything for the virtal memory ----------------------------------
641         if (!dpmi_lock_region ((void near *)key_handler, (char *)key_handler_end - (char near *)key_handler))   {
642                 printf( "Error locking keyboard handler!\n" );
643                 exit(1);
644         }
645         if (!dpmi_lock_region ((void *)&key_data, sizeof(keyboard)))    {
646                 printf( "Error locking keyboard handler's data1!\n" );
647                 exit(1);
648         }
649         if (!dpmi_lock_region (&keyd_buffer_type, sizeof(char)))        {
650                 printf( "Error locking keyboard handler's data2!\n" );
651                 exit(1);
652         }
653         if (!dpmi_lock_region (&keyd_repeat, sizeof(char)))     {
654                 printf( "Error locking keyboard handler's data3!\n" );
655                 exit(1);
656         }
657         if (!dpmi_lock_region (&keyd_editor_mode, sizeof(char)))        {
658                 printf( "Error locking keyboard handler's data4!\n" );
659                 exit(1);
660         }
661         if (!dpmi_lock_region ((void *)&keyd_last_pressed, sizeof(char)))       {
662                 printf( "Error locking keyboard handler's data5!\n" );
663                 exit(1);
664         }
665         if (!dpmi_lock_region ((void *)&keyd_last_released, sizeof(char)))      {
666                 printf( "Error locking keyboard handler's data6!\n" );
667                 exit(1);
668         }
669         if (!dpmi_lock_region ((void *)&keyd_pressed, sizeof(char)*256))        {
670                 printf( "Error locking keyboard handler's data7!\n" );
671                 exit(1);
672         }
673         if (!dpmi_lock_region ((void *)&keyd_time_when_last_pressed, sizeof(int)))      {
674                 printf( "Error locking keyboard handler's data8!\n" );
675                 exit(1);
676         }
677
678 #ifndef __DJGPP__
679         key_data.prev_int_9 = (void *)_dos_getvect( 9 );
680     _dos_setvect( 9, key_handler );
681 #else
682         _go32_dpmi_get_protected_mode_interrupt_vector(9,
683          (_go32_dpmi_seginfo *)&key_data.prev_int_9);
684         kbd_hand_info.pm_offset = (int)key_handler;
685         kbd_hand_info.pm_selector = _my_cs();
686         _go32_dpmi_allocate_iret_wrapper(&kbd_hand_info);
687         _go32_dpmi_set_protected_mode_interrupt_vector(9, &kbd_hand_info);
688 #endif
689
690         atexit( key_close );
691 }
692
693 void key_close()
694 {
695         if (!Installed) return;
696         Installed = 0;
697         
698 #ifndef __DJGPP__
699         _dos_setvect( 9, key_data.prev_int_9 );
700 #else
701         _go32_dpmi_set_protected_mode_interrupt_vector(9,
702          (_go32_dpmi_seginfo *)&key_data.prev_int_9);
703 #endif
704
705         _disable();
706         key_clear_bios_buffer_all();
707         _enable();
708
709 }