When including config.h, include it first.
[wine] / msdos / int16.c
1 /*
2  * DOS interrupt 16h handler
3  */
4
5 #include "config.h"
6
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10
11 #include "module.h"
12 #include "callback.h"
13 #include "dosexe.h"
14 #include "wincon.h"
15 #include "debugtools.h"
16 #include "windef.h"
17 #include "wingdi.h"
18 #include "winuser.h"
19 #include "miscemu.h"
20
21 DEFAULT_DEBUG_CHANNEL(int16);
22
23 /**********************************************************************
24  *          INT_Int16Handler
25  *
26  * Handler for int 16h (keyboard)
27  *
28  * NOTE:
29  * 
30  *    KEYB.COM (DOS >3.2) adds functions to this interrupt, they are
31  *    not currently listed here.
32  */
33
34 void WINAPI INT_Int16Handler( CONTEXT86 *context )
35 {
36    switch AH_reg(context) {
37
38    case 0x00: /* Get Keystroke */
39       /* Returns: AH = Scan code
40                   AL = ASCII character */   
41       TRACE("Get Keystroke\n");
42       INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), FALSE);
43       break;
44
45    case 0x01: /* Check for Keystroke */
46       /* Returns: ZF set if no keystroke */
47       /*          AH = Scan code */
48       /*          AL = ASCII character */
49       TRACE("Check for Keystroke\n");
50       if (!INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), TRUE))
51       {
52           SET_ZFLAG(context);
53       }
54       else
55       {
56           RESET_ZFLAG(context);
57       }
58       break;
59
60    case 0x02: /* Get Shift Flags */      
61       AL_reg(context) = 0;
62
63 #if 0  /* FIXME: cannot call USER functions here */
64       if (GetAsyncKeyState(VK_RSHIFT))
65           AL_reg(context) |= 0x01;
66       if (GetAsyncKeyState(VK_LSHIFT))
67           AL_reg(context) |= 0x02;
68       if (GetAsyncKeyState(VK_LCONTROL) || GetAsyncKeyState(VK_RCONTROL))
69           AL_reg(context) |= 0x04;
70       if (GetAsyncKeyState(VK_LMENU) || GetAsyncKeyState(VK_RMENU))
71           AL_reg(context) |= 0x08;
72       if (GetAsyncKeyState(VK_SCROLL))
73           AL_reg(context) |= 0x10;
74       if (GetAsyncKeyState(VK_NUMLOCK))
75           AL_reg(context) |= 0x20;
76       if (GetAsyncKeyState(VK_CAPITAL))
77           AL_reg(context) |= 0x40;
78       if (GetAsyncKeyState(VK_INSERT))
79           AL_reg(context) |= 0x80;
80 #endif
81       TRACE("Get Shift Flags: returning 0x%02x\n", AL_reg(context));
82       break;
83
84    case 0x03: /* Set Typematic Rate and Delay */
85       FIXME("Set Typematic Rate and Delay - Not Supported\n");
86       break;
87
88    case 0x09: /* Get Keyboard Functionality */
89       FIXME("Get Keyboard Functionality - Not Supported\n");
90       /* As a temporary measure, say that "nothing" is supported... */
91       AL_reg(context) = 0;
92       break;
93
94    case 0x0a: /* Get Keyboard ID */
95       FIXME("Get Keyboard ID - Not Supported\n");
96       break;
97
98    case 0x10: /* Get Enhanced Keystroke */
99       TRACE("Get Enhanced Keystroke - Partially supported\n");
100       /* Returns: AH = Scan code
101                   AL = ASCII character */   
102       INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), FALSE);
103       break;
104   
105
106    case 0x11: /* Check for Enhanced Keystroke */
107       /* Returns: ZF set if no keystroke */
108       /*          AH = Scan code */
109       /*          AL = ASCII character */
110       TRACE("Check for Enhanced Keystroke - Partially supported\n");
111       if (!INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), TRUE))
112       {
113           SET_ZFLAG(context);
114       }
115       else
116       {
117           RESET_ZFLAG(context);
118       }
119       break;
120
121    case 0x12: /* Get Extended Shift States */
122       FIXME("Get Extended Shift States - Not Supported\n");
123       break;
124  
125    default:
126       FIXME("Unknown INT 16 function - 0x%x\n", AH_reg(context));   
127       break;
128
129    }
130 }
131
132 int WINAPI INT_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek)
133 {
134   BIOSDATA *data = DOSMEM_BiosData();
135   WORD CurOfs = data->NextKbdCharPtr;
136
137   /* check if there's data in buffer */
138   if (peek) {
139     if (CurOfs == data->FirstKbdCharPtr)
140       return 0;
141   } else {
142     while (CurOfs == data->FirstKbdCharPtr) {
143       /* no input available yet, so wait... */
144       Dosvm.Wait( -1, 0 );
145     }
146   }
147   /* read from keyboard queue */
148   TRACE("(%p,%p,%d) -> %02x %02x\n",ascii,scan,peek,((BYTE*)data)[CurOfs],((BYTE*)data)[CurOfs+1]);
149   if (ascii) *ascii = ((BYTE*)data)[CurOfs];
150   if (scan) *scan = ((BYTE*)data)[CurOfs+1];
151   if (!peek) {
152     CurOfs += 2;
153     if (CurOfs >= data->KbdBufferEnd) CurOfs = data->KbdBufferStart;
154     data->NextKbdCharPtr = CurOfs;
155   }
156   return 1;
157 }
158
159 int WINAPI INT_Int16AddChar(BYTE ascii,BYTE scan)
160 {
161   BIOSDATA *data = DOSMEM_BiosData();
162   WORD CurOfs = data->FirstKbdCharPtr;
163   WORD NextOfs = CurOfs + 2;
164
165   TRACE("(%02x,%02x)\n",ascii,scan);
166   if (NextOfs >= data->KbdBufferEnd) NextOfs = data->KbdBufferStart;
167   /* check if buffer is full */
168   if (NextOfs == data->NextKbdCharPtr) return 0;
169
170   /* okay, insert character in ring buffer */
171   ((BYTE*)data)[CurOfs] = ascii;
172   ((BYTE*)data)[CurOfs+1] = scan;
173
174   data->FirstKbdCharPtr = NextOfs;
175   return 1;
176 }