Separated the MZ loader and core DOS VM into dlls/winedos.
[wine] / msdos / int09.c
1 /*
2  * DOS interrupt 09h handler (IRQ1 - KEYBOARD)
3  */
4
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include "windef.h"
9 #include "winbase.h"
10 #include "wingdi.h"
11 #include "winuser.h"
12 #include "miscemu.h"
13 #include "debugtools.h"
14 #include "callback.h"
15 #include "dosexe.h"
16
17 DEFAULT_DEBUG_CHANNEL(int);
18
19 #define QUEUELEN 31
20
21 static struct
22 {
23   BYTE queuelen,queue[QUEUELEN],ascii[QUEUELEN];
24 } kbdinfo;
25
26
27 /**********************************************************************
28  *          INT_Int09Handler
29  *
30  * Handler for int 09h.
31  */
32 void WINAPI INT_Int09Handler( CONTEXT86 *context )
33 {
34   BYTE ascii, scan = INT_Int09ReadScan(&ascii);
35   BYTE ch[2];
36   int cnt, c2;
37
38   TRACE("scan=%02x\n",scan);
39   if (!(scan & 0x80)) {
40     if (ascii) {
41       /* we already have an ASCII code, no translation necessary */
42       ch[0] = ascii;
43       cnt = 1;
44     } else {
45 #if 0  /* FIXME: cannot call USER functions here */
46       UINT vkey = MapVirtualKeyA(scan&0x7f, 1);
47       /* as in TranslateMessage, windows/input.c */
48       cnt = ToAscii(vkey, scan, QueueKeyStateTable, (LPWORD)ch, 0);
49 #else
50       cnt = 0;
51 #endif
52     }
53     if (cnt>0) {
54       for (c2=0; c2<cnt; c2++)
55         INT_Int16AddChar(ch[c2], scan);
56     } else
57     if (cnt==0) {
58       /* FIXME: need to handle things like shift-F-keys,
59        * 0xE0 extended keys, etc */
60       INT_Int16AddChar(0, scan);
61     }
62   }
63   Dosvm.OutPIC(0x20, 0x20); /* send EOI */
64 }
65
66 static void KbdRelay( CONTEXT86 *context, void *data )
67 {
68   if (kbdinfo.queuelen) {
69     /* cleanup operation, called from Dosvm.OutPIC:
70      * we'll remove current scancode from keyboard buffer here,
71      * rather than in ReadScan, because some DOS apps depend on
72      * the scancode being available for reading multiple times... */
73     if (--kbdinfo.queuelen) {
74       memmove(kbdinfo.queue,kbdinfo.queue+1,kbdinfo.queuelen);
75       memmove(kbdinfo.ascii,kbdinfo.ascii+1,kbdinfo.queuelen);
76     }
77   }
78 }
79
80 void WINAPI INT_Int09SendScan( BYTE scan, BYTE ascii )
81 {
82   if (kbdinfo.queuelen == QUEUELEN) {
83     ERR("keyboard queue overflow\n");
84     return;
85   }
86   /* add scancode to queue */
87   kbdinfo.queue[kbdinfo.queuelen] = scan;
88   kbdinfo.ascii[kbdinfo.queuelen++] = ascii;
89   /* tell app to read it by triggering IRQ 1 (int 09) */
90   Dosvm.QueueEvent(1,DOS_PRIORITY_KEYBOARD,KbdRelay,NULL);
91 }
92
93 BYTE WINAPI INT_Int09ReadScan( BYTE*ascii )
94 {
95     if (ascii) *ascii = kbdinfo.ascii[0];
96     return kbdinfo.queue[0];
97 }