3 * Copyright (C) 2002 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: base/setup/usetup/keytrans.c
23 * PURPOSE: Console support functions: keyboard translation
26 * NB: Hardcoded to US keyboard
34 static WORD KeyTable
[] = {
36 0x00, VK_ESCAPE
, 0x31, 0x32,
37 0x33, 0x34, 0x35, 0x36,
38 0x37, 0x38, 0x39, 0x30,
39 VK_OEM_MINUS
, VK_OEM_PLUS
, VK_BACK
, VK_TAB
,
41 0x51, 0x57, 0x45, 0x52,
42 0x54, 0x59, 0x55, 0x49,
43 0x4f, 0x50, VK_OEM_4
, VK_OEM_6
,
44 VK_RETURN
, VK_CONTROL
, 0x41, 0x53,
46 0x44, 0x46, 0x47, 0x48,
47 0x4a, 0x4b, 0x4c, VK_OEM_1
,
48 VK_OEM_7
, 0xc0, VK_LSHIFT
, VK_OEM_5
,
49 0x5a, 0x58, 0x43, 0x56,
51 0x42, 0x4e, 0x4d, VK_OEM_COMMA
,
52 VK_OEM_PERIOD
, VK_OEM_2
, VK_RSHIFT
, VK_MULTIPLY
,
53 VK_LMENU
, VK_SPACE
, VK_CAPITAL
, VK_F1
,
54 VK_F2
, VK_F3
, VK_F4
, VK_F5
,
56 VK_F6
, VK_F7
, VK_F8
, VK_F9
,
57 VK_F10
, VK_NUMLOCK
, VK_SCROLL
, VK_HOME
,
58 VK_UP
, VK_PRIOR
, VK_SUBTRACT
, VK_LEFT
,
59 0, VK_RIGHT
, VK_ADD
, VK_END
,
61 VK_DOWN
, VK_NEXT
, VK_INSERT
, VK_DELETE
,
77 static WORD KeyTableEnhanced
[] = {
87 VK_RETURN
, VK_RCONTROL
, 0, 0,
95 0, VK_DIVIDE
, 0, VK_SNAPSHOT
,
101 VK_UP
, VK_PRIOR
, 0, VK_LEFT
,
102 0, VK_RIGHT
, 0, VK_END
,
104 VK_DOWN
, VK_NEXT
, VK_INSERT
, VK_DELETE
,
120 static WORD KeyTableNumlock
[] = {
144 VK_NUMPAD8
, VK_NUMPAD9
, 0, VK_NUMPAD4
,
145 VK_NUMPAD5
, VK_NUMPAD6
, 0, VK_NUMPAD1
,
147 VK_NUMPAD2
, VK_NUMPAD3
, VK_NUMPAD0
, 0,
163 typedef struct _SCANTOASCII
{
170 } SCANTOASCII
, *PSCANTOASCII
;
172 SCANTOASCII ScanToAscii
[] = {
173 { 0x1e, 0, 'a', 'A', 0, TRUE
},
174 { 0x30, 0, 'b', 'B', 0, TRUE
},
175 { 0x2e, 0, 'c', 'C', 0, TRUE
},
176 { 0x20, 0, 'd', 'D', 0, TRUE
},
177 { 0x12, 0, 'e', 'E', 0, TRUE
},
178 { 0x21, 0, 'f', 'F', 0, TRUE
},
179 { 0x22, 0, 'g', 'G', 0, TRUE
},
180 { 0x23, 0, 'h', 'H', 0, TRUE
},
181 { 0x17, 0, 'i', 'I', 0, TRUE
},
182 { 0x24, 0, 'j', 'J', 0, TRUE
},
183 { 0x25, 0, 'k', 'K', 0, TRUE
},
184 { 0x26, 0, 'l', 'L', 0, TRUE
},
185 { 0x32, 0, 'm', 'M', 0, TRUE
},
186 { 0x31, 0, 'n', 'N', 0, TRUE
},
187 { 0x18, 0, 'o', 'O', 0, TRUE
},
188 { 0x19, 0, 'p', 'P', 0, TRUE
},
189 { 0x10, 0, 'q', 'Q', 0, TRUE
},
190 { 0x13, 0, 'r', 'R', 0, TRUE
},
191 { 0x1f, 0, 's', 'S', 0, TRUE
},
192 { 0x14, 0, 't', 'T', 0, TRUE
},
193 { 0x16, 0, 'u', 'U', 0, TRUE
},
194 { 0x2f, 0, 'v', 'V', 0, TRUE
},
195 { 0x11, 0, 'w', 'W', 0, TRUE
},
196 { 0x2d, 0, 'x', 'X', 0, TRUE
},
197 { 0x15, 0, 'y', 'Y', 0, TRUE
},
198 { 0x2c, 0, 'z', 'Z', 0, TRUE
},
200 { 0x02, 0, '1', '!', 0, FALSE
},
201 { 0x03, 0, '2', '@', 0, FALSE
},
202 { 0x04, 0, '3', '#', 0, FALSE
},
203 { 0x05, 0, '4', '$', 0, FALSE
},
204 { 0x06, 0, '5', '%', 0, FALSE
},
205 { 0x07, 0, '6', '^', 0, FALSE
},
206 { 0x08, 0, '7', '&', 0, FALSE
},
207 { 0x09, 0, '8', '*', 0, FALSE
},
208 { 0x0a, 0, '9', '(', 0, FALSE
},
209 { 0x0b, 0, '0', ')', 0, FALSE
},
211 { 0x29, 0, '\'', '~', 0, FALSE
},
212 { 0x0c, 0, '-', '_', 0, FALSE
},
213 { 0x0d, 0, '=', '+', 0, FALSE
},
214 { 0x1a, 0, '[', '{', 0, FALSE
},
215 { 0x1b, 0, ']', '}', 0, FALSE
},
216 { 0x2b, 0, '\\', '|', 0, FALSE
},
217 { 0x27, 0, ';', ':', 0, FALSE
},
218 { 0x28, 0, '\'', '"', 0, FALSE
},
219 { 0x33, 0, ',', '<', 0, FALSE
},
220 { 0x34, 0, '.', '>', 0, FALSE
},
221 { 0x35, 0, '/', '?', 0, FALSE
},
223 { 0x4f, 0, 0, 0, '1', FALSE
},
224 { 0x50, 0, 0, 0, '2', FALSE
},
225 { 0x51, 0, 0, 0, '3', FALSE
},
226 { 0x4b, 0, 0, 0, '4', FALSE
},
227 { 0x4c, 0, 0, 0, '5', FALSE
},
228 { 0x4d, 0, 0, 0, '6', FALSE
},
229 { 0x47, 0, 0, 0, '7', FALSE
},
230 { 0x48, 0, 0, 0, '8', FALSE
},
231 { 0x49, 0, 0, 0, '9', FALSE
},
232 { 0x52, 0, 0, 0, '0', FALSE
},
234 { 0x4a, 0, '-', '-', 0, FALSE
},
235 { 0x4e, 0, '+', '+', 0, FALSE
},
236 { 0x37, 0, '*', '*', 0, FALSE
},
237 { 0x35, 1, '/', '/', 0, FALSE
},
238 { 0x53, 0, 0, 0, '.', FALSE
},
240 { 0x39, 0, ' ', ' ', 0, FALSE
},
242 { 0x1c, 0, '\r', '\r', 0, FALSE
},
243 { 0x1c, 1, '\r', '\r', 0, FALSE
},
244 { 0x0e, 0, 0x08, 0x08, 0, FALSE
}, /* backspace */
246 { 0, 0, 0, 0, 0, FALSE
}
251 IntUpdateControlKeyState(HANDLE hConsoleInput
, LPDWORD State
, PKEYBOARD_INPUT_DATA InputData
)
254 DWORD oldState
, newState
;
256 if (InputData
->Flags
& KEY_E1
) /* Only the pause key has E1 */
259 oldState
= newState
= *State
;
261 if (!(InputData
->Flags
& KEY_E0
)) {
262 switch (InputData
->MakeCode
) {
265 Value
= SHIFT_PRESSED
;
269 Value
= LEFT_CTRL_PRESSED
;
273 Value
= LEFT_ALT_PRESSED
;
277 if (!(InputData
->Flags
& KEY_BREAK
))
278 newState
^= CAPSLOCK_ON
;
282 if (!(InputData
->Flags
& KEY_BREAK
))
283 newState
^= NUMLOCK_ON
;
287 if (!(InputData
->Flags
& KEY_BREAK
))
288 newState
^= SCROLLLOCK_ON
;
295 switch (InputData
->MakeCode
) {
297 Value
= RIGHT_CTRL_PRESSED
;
301 Value
= RIGHT_ALT_PRESSED
;
309 /* Check if the state of the indicators has been changed */
310 if ((oldState
^ newState
) & (NUMLOCK_ON
| CAPSLOCK_ON
| SCROLLLOCK_ON
))
312 IO_STATUS_BLOCK IoStatusBlock
;
314 KEYBOARD_INDICATOR_PARAMETERS kip
;
319 if ((newState
& NUMLOCK_ON
))
320 kip
.LedFlags
|= KEYBOARD_NUM_LOCK_ON
;
322 if ((newState
& CAPSLOCK_ON
))
323 kip
.LedFlags
|= KEYBOARD_CAPS_LOCK_ON
;
325 if ((newState
& SCROLLLOCK_ON
))
326 kip
.LedFlags
|= KEYBOARD_SCROLL_LOCK_ON
;
328 /* Update the state of the leds on primary keyboard */
329 DPRINT("NtDeviceIoControlFile dwLeds=%x\n", kip
.LedFlags
);
331 Status
= NtDeviceIoControlFile(
337 IOCTL_KEYBOARD_SET_INDICATORS
,
343 if (!NT_SUCCESS(Status
))
345 DPRINT1("NtDeviceIoControlFile(IOCTL_KEYBOARD_SET_INDICATORS) failed (Status %lx)\n", Status
);
348 /* Normal press/release state handling */
349 if (InputData
->Flags
& KEY_BREAK
)
358 IntVKFromKbdInput(PKEYBOARD_INPUT_DATA InputData
, DWORD KeyState
)
360 if (!(KeyState
& ENHANCED_KEY
)) {
361 if ((KeyState
& NUMLOCK_ON
) &&
362 KeyTableNumlock
[InputData
->MakeCode
& 0x7f]) {
363 DPRINT("Numlock, using %x\n",
364 InputData
->MakeCode
& 0x7f);
365 return KeyTableNumlock
[InputData
->MakeCode
& 0x7f];
367 DPRINT("Not enhanced, using %x\n", InputData
->MakeCode
& 0x7f);
368 return KeyTable
[InputData
->MakeCode
& 0x7f];
371 DPRINT("Enhanced, using %x\n", InputData
->MakeCode
& 0x7f);
372 return KeyTableEnhanced
[InputData
->MakeCode
& 0x7f];
376 IntAsciiFromInput(PKEYBOARD_INPUT_DATA InputData
, DWORD KeyState
)
381 if (KeyState
& ENHANCED_KEY
) Enhanced
= 1;
383 while (ScanToAscii
[Counter
].ScanCode
!= 0) {
384 if ((ScanToAscii
[Counter
].ScanCode
== InputData
->MakeCode
) &&
385 (ScanToAscii
[Counter
].Enhanced
== Enhanced
)) {
386 if (ScanToAscii
[Counter
].NumLock
) {
387 if ((KeyState
& NUMLOCK_ON
) &&
388 !(KeyState
& SHIFT_PRESSED
)) {
389 return ScanToAscii
[Counter
].NumLock
;
391 return ScanToAscii
[Counter
].Normal
;
395 if ((KeyState
& CAPSLOCK_ON
) && ScanToAscii
[Counter
].bCAPS
)
396 KeyState
^= SHIFT_PRESSED
;
398 if (KeyState
& SHIFT_PRESSED
)
399 return ScanToAscii
[Counter
].Shift
;
401 return ScanToAscii
[Counter
].Normal
;
409 /* This is going to be quick and messy. The usetup app runs in native mode
410 * so it cannot use the translation routines in win32k which means it'll have
411 * to be done here too.
413 * Only the bKeyDown, AsciiChar and wVirtualKeyCode members are used
414 * in the app so I'll just fill the others with somewhat sane values
417 IntTranslateKey(HANDLE hConsoleInput
, PKEYBOARD_INPUT_DATA InputData
, KEY_EVENT_RECORD
*Event
)
419 static DWORD dwControlKeyState
;
421 RtlZeroMemory(Event
, sizeof(KEY_EVENT_RECORD
));
423 if (!(InputData
->Flags
& KEY_BREAK
))
424 Event
->bKeyDown
= TRUE
;
426 Event
->bKeyDown
= FALSE
;
428 Event
->wRepeatCount
= 1;
429 Event
->wVirtualScanCode
= InputData
->MakeCode
;
431 DPRINT("Translating: %x\n", InputData
->MakeCode
);
433 IntUpdateControlKeyState(hConsoleInput
, &dwControlKeyState
, InputData
);
434 Event
->dwControlKeyState
= dwControlKeyState
;
436 if (InputData
->Flags
& KEY_E0
)
437 Event
->dwControlKeyState
|= ENHANCED_KEY
;
439 Event
->wVirtualKeyCode
= IntVKFromKbdInput(InputData
,
440 Event
->dwControlKeyState
);
442 DPRINT("Result: %x\n", Event
->wVirtualKeyCode
);
444 if (Event
->bKeyDown
) {
445 Event
->uChar
.AsciiChar
=
446 IntAsciiFromInput(InputData
,
447 Event
->dwControlKeyState
);
448 DPRINT("Char: %x\n", Event
->uChar
.AsciiChar
);
450 Event
->uChar
.AsciiChar
= 0;
453 return STATUS_SUCCESS
;