-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmkeybr.c
366 lines (294 loc) · 8.46 KB
/
mkeybr.c
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
/*
mKEYBR.C - minimum keyboard handler for international keyboards
******* RESIDENT PART **********
requires only ~500-600 byte of precious memory to do what it does.
for details, please see readme.txt
Copyright (C) 2002 by [email protected]
*/
#include <dos.h>
#define RESIDENT
#include "mkeyb.h"
#ifdef FASTSWITCH
#define NO_DECIDINGSBUMS
#define NO_REPLACESCAN
#define NO_ALTGREY
#define NAME(x) x##_fastswitch
#elif defined(STANDARD)
#define NO_FASTSWITCH
#define NO_ALTGREY
#define NAME(x) x##_standard
#elif defined(STD_FULL)
#define NO_FASTSWITCH
#define NO_ALTGREY
#define COMBI
#define STANDARD
#define NAME(x) x##_stdfull
#elif defined(COMBI)
#define NO_FASTSWITCH
#define NAME(x) x##_full
#else
#define NO_FASTSWITCH
#define NAME(x) x##_normal
#endif
#ifdef __WATCOMC__
/* all the resident code goes to segment 'I_TEXT' of special class 'INIT' */
#pragma code_seg(I_TEXT, INIT)
#endif
/** 'normal' data **********************************/
extern uchar usebiosonly_flag;
extern uchar lastisctrl_flag;
extern uchar debug_scancode;
extern uint RESIDENT currentCombi ;
extern char *RESIDENT ResidentCombiTables[6] ;
extern uchar RESIDENT DecimalDingsBums ; /* grey , or . */
/* MUST BE LAST DATA MEMBER */
extern uchar *pResidentScancodetable;
/** normal data end, ONE last member - the scan code translation table
//
// scan code translation table
// this also marks the end of our resident data
//
//
// the format for each entry is
//
// [0] scancode to search
// [1] different shift states handled (SHIFT,CTRL,ALTGREY,...)
// also implies table entry size
// [2..n] keycode to send into BIOS buffer
//
*/
/** data end **********************************/
/* use BIOS INT16/05 to enter keystroke into key buffer */
#ifdef __WATCOMC__
static void GENERATE_KEYSTROKE(uchar scancode, uchar keycode);
#pragma aux GENERATE_KEYSTROKE = \
"mov ah, 5" \
"int 0x16" \
__parm [ch] [cl] \
__modify [ax];
#else
#define GENERATE_KEYSTROKE(scancode,keycode) \
_CL = keycode, \
_CH = scancode, \
_AH = 5; \
__int__(0x16);
#endif
/* tech note: as michael Tyc found out, this interrupt
_asm mov AX,0x9102;
_asm int 0x15;
isn't executed on all BIOS for INT16/05
this might be added here. As the details aren't that clear,
and the interrupt seems not to be in use (nowadays),
it's left out here, but may be added later.
*/
int cdecl NAME(cint15_handler)(uchar scancode)
{
uchar RESIDENT *tbl;
ushort BIOSstate;
uchar keyflags;
BIOSstate = *(short far*)MK_FP(0x40,0x17);
debug_scancode = scancode; /* very nice for debugging */
/* hit ESC - and we are gone */
if (SilentKeyboard)
{
return 0; /* absorb all keyboard input :
tell the BIOS to ignore scancode */
}
#ifdef NO_FASTSWITCH
if (BIOSstate & 0x08 && BIOSstate & 0x04) /* Ctrl+Alt+F1/F2 */
{
if (scancode == 0x3b || scancode == 0x3c)
{
usebiosonly_flag = 0x3b - scancode; /* 0x00 or 0xff */
return 0;
}
}
#else
if (! lastisctrl_flag && /* the last key was Ctrl */
*(char far*)MK_FP(0x40, 0x96) & 0x04 && /* was the Right Ctrl */
scancode == (0x1d + 0x80)) /* and now Ctrl key is released */
{
usebiosonly_flag = ~usebiosonly_flag; /* toggles between 0x00 and 0xff */
}
if (scancode > 0 && scancode < 0x80) /* Any key pressed */
lastisctrl_flag = 0xff;
if (scancode == 0x1d) /* Ctrl */
lastisctrl_flag = 0;
#endif
if (usebiosonly_flag == 0)
return scancode;
/*
** E0 scancode handling
** don't handle ANYTHING, if E0 was pressed
*/
if (*(char far*)MK_FP(0x40, 0x96) & 0x02) /* last code was E0 hidden code */
{
return scancode;
}
#ifndef NO_DECIDINGSBUMS
/* explicit handling of numeric '.' */
if ( scancode == 0x53 &&
DecimalDingsBums &&
BIOSstate & 0x20) /* NUMLOCK pressed */
{
/* the grey . is particular ugly */
GENERATE_KEYSTROKE(scancode,DecimalDingsBums);
return 0;
}
#endif /* NO_DECIDINGSBUMS */
/* CAPS handling:
logical shift state = CapsPressed ^ ShiftPressed */
if (BIOSstate & 3)
BIOSstate ^= 0x40;
#ifdef COMBI
/* all that swedish, spanish stuff ;-)
these keys are generated
by 2 character combinations
*/
if (currentCombi != 0)
{
/* key release - handled by BIOS*/
if (scancode & 0x80)
return scancode;
if (scancode == 0x2a || /* left shift - handled by BIOS*/
scancode == 0x36) /* right shift - handled by BIOS*/
{
return scancode;
}
tbl = (uchar*)ResidentCombiTables[currentCombi - COMBI1];
currentCombi = 0;
for ( ; tbl[0] != 0; tbl += 3)
{
if (tbl[0] == scancode)
{ /* these character all use CAPS */
GENERATE_KEYSTROKE(0, BIOSstate & 0x40 ? tbl[2] : tbl[1]);
return 0;
}
}
/* not found ? then the last entry before holds the character to generate */
GENERATE_KEYSTROKE(0, BIOSstate & 0x40 ? tbl[-3+2] : tbl[-3+1]);
/* and fall through to generate the key */
}
#endif
/*
'conventional' keyboard mappings
search our table and locate the scancode
*/
for ( tbl = pResidentScancodetable;
tbl[0] != scancode;
tbl += (tbl[1] & SIZEFIELD) )
{
/* end of table --> not found -->
let the BIOS do it's work
*/
if (tbl[0] == 0)
return scancode;
}
/* now tbl points to entry in scancodetable */
keyflags = tbl[1];
tbl += 2; /* points to normal key */
#ifndef NO_REPLACESCAN
/* simple scancode exchange */
if (keyflags == REPLACESCAN)
return tbl[0];
#endif /* NO_REPLACESCAN */
/* we found the table entry for the scancode
match the shiftstate in the table against
the current shift state
*/
/* now advance tbl in a way, that it
finally points to the key to be generated
*/
#ifndef NO_ALTGREY
if (keyflags & _KALTGR && /* has ALTGREY definition */
*(char far*)MK_FP(0x40,0x96) & 0x08) /* and right ALT pressed */
{
if (keyflags & _KCHAR) /* skip over other characters */
tbl+=2;
if (keyflags & _KCTRL)
tbl += 1;
if (BIOSstate & 0x40) /* is Shift pressed ? */
{
if (keyflags & _KALTGRSHIFT) /* uses ALTGREY with shifts if defined */
{
tbl += 1;
} else {
return scancode; /* let the BIOS do its work if not */
}
}
goto simulateKeyPress;
}
#endif /* NO_ALTGREY */
if (BIOSstate & 0x08) /* any ALT pressed */
{
#ifdef STANDARD
if (keyflags & _KALTGR && /* has ALTGREY definition */
BIOSstate & 0x04) /* and CTRL is also pressed */
{
if (keyflags & _KCHAR) /* skip over other characters */
tbl+=2;
if (BIOSstate & 0x40) /* is Shift pressed ? */
{
if (keyflags & _KALTGRSHIFT) /* uses ALTGREY with shifts if defined */
{
tbl += 1;
} else {
return scancode; /* let the BIOS do its work if not */
}
}
goto simulateKeyPress;
}
#endif /* STANDARD */
return scancode; /* leave the work to BIOS */
}
if(BIOSstate & 0x04) /* either CTRL pressed */
{
if((keyflags & _KCTRL) == 0) /* but no Ctrl definition given */
return scancode;
if(keyflags & _KCHAR)
tbl += 2;
goto simulateCtrlKeyPress; /* Skip check for COMBIs to avoid clash with ^A..^F */
}
if ((keyflags & _KCHAR) == 0) /* it should have _KCHAR defined */
{
return scancode; /* if not, give it to BIOS */
}
if(keyflags & _KCAPS)
{
if(BIOSstate & 0x40) /* CAPS pressed */
tbl++;
}
else
{
if(BIOSstate & 0x03) /* either SHIFT pressed */
tbl++;
}
simulateKeyPress:
#ifdef COMBI
if (tbl[0] >= COMBI1 && tbl[0] <= COMBI6)
{
currentCombi = tbl[0];
return 0;
}
#endif
simulateCtrlKeyPress:
if (tbl[0] == IGNORE)
return scancode; /* let BIOS do its work */
/* strange, but necessary */
if (tbl[0] == 0xf0 || /* this is a BIOS 'feature' */
tbl[0] == 0xe0) /* this too */
{
scancode = 0;
}
GENERATE_KEYSTROKE(scancode,tbl[0]);
return 0;
}
// MARKER for end of resident part
#ifdef __WATCOMC__
void __declspec(naked) NAME(END_cint15_handler)(void){
_asm{ nop };
}
#pragma aux NAME(END_cint15_handler) "_*"
#else
void NAME(END_cint15_handler)(void){};
#endif