[USETUP]
[reactos.git] / reactos / base / setup / usetup / native / utils / keytrans.c
index 706be84..6127963 100644 (file)
@@ -19,7 +19,7 @@
 /*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS text-mode setup
- * FILE:            subsys/system/usetup/keytrans.c
+ * FILE:            base/setup/usetup/native/utils/keytrans.c
  * PURPOSE:         Console support functions: keyboard translation
  * PROGRAMMER:      Tinus
  *
@@ -117,13 +117,6 @@ static WORD KeyTableEnhanced[] = {
        0,              0,              0,              0
 };
 
-/*
- * Note how the keyboard lights are not handled, so while NUMLOCK_ON can
- * be on, the light will never be. If this starts to be a problem it can be
- * fixed, but it's too much work for too little gain to do now.
- * Look in win32k/ntuser/input.c for an example.
- */
-
 static WORD KeyTableNumlock[] = {
 /* 0x00 */
        0,              0,              0,              0,
@@ -173,94 +166,98 @@ typedef struct _SCANTOASCII {
        UCHAR Normal;
        UCHAR Shift;
        UCHAR NumLock;
+       UCHAR bCAPS;
 } SCANTOASCII, *PSCANTOASCII;
 
 SCANTOASCII ScanToAscii[] = {
-{      0x1e,   0,      'a',    'A',    0       },
-{      0x30,   0,      'b',    'B',    0       },
-{      0x2e,   0,      'c',    'C',    0       },
-{      0x20,   0,      'd',    'D',    0       },
-{      0x12,   0,      'e',    'E',    0       },
-{      0x21,   0,      'f',    'F',    0       },
-{      0x22,   0,      'g',    'G',    0       },
-{      0x23,   0,      'h',    'H',    0       },
-{      0x17,   0,      'i',    'I',    0       },
-{      0x24,   0,      'j',    'J',    0       },
-{      0x25,   0,      'k',    'K',    0       },
-{      0x26,   0,      'l',    'L',    0       },
-{      0x32,   0,      'm',    'M',    0       },
-{      0x31,   0,      'n',    'N',    0       },
-{      0x18,   0,      'o',    'O',    0       },
-{      0x19,   0,      'p',    'P',    0       },
-{      0x10,   0,      'q',    'Q',    0       },
-{      0x13,   0,      'r',    'R',    0       },
-{      0x1f,   0,      's',    'S',    0       },
-{      0x14,   0,      't',    'T',    0       },
-{      0x16,   0,      'u',    'U',    0       },
-{      0x2f,   0,      'v',    'V',    0       },
-{      0x11,   0,      'w',    'W',    0       },
-{      0x2d,   0,      'x',    'X',    0       },
-{      0x15,   0,      'y',    'Y',    0       },
-{      0x2c,   0,      'z',    'Z',    0       },
-
-{      0x02,   0,      '1',    '!',    0       },
-{      0x03,   0,      '2',    '@',    0       },
-{      0x04,   0,      '3',    '#',    0       },
-{      0x05,   0,      '4',    '$',    0       },
-{      0x06,   0,      '5',    '%',    0       },
-{      0x07,   0,      '6',    '^',    0       },
-{      0x08,   0,      '7',    '&',    0       },
-{      0x09,   0,      '8',    '*',    0       },
-{      0x0a,   0,      '9',    '(',    0       },
-{      0x0b,   0,      '0',    ')',    0       },
-
-{      0x29,   0,      '\'',   '~',    0       },
-{      0x0c,   0,      '-',    '_',    0       },
-{      0x0d,   0,      '=',    '+',    0       },
-{      0x1a,   0,      '[',    '{',    0       },
-{      0x1b,   0,      ']',    '}',    0       },
-{      0x2b,   0,      '\\',   '|',    0       },
-{      0x27,   0,      ';',    ':',    0       },
-{      0x28,   0,      '\'',   '"',    0       },
-{      0x33,   0,      ',',    '<',    0       },
-{      0x34,   0,      '.',    '>',    0       },
-{      0x35,   0,      '/',    '?',    0       },
-
-{      0x4f,   0,      0,      0,      '1'     },
-{      0x50,   0,      0,      0,      '2'     },
-{      0x51,   0,      0,      0,      '3'     },
-{      0x4b,   0,      0,      0,      '4'     },
-{      0x4c,   0,      0,      0,      '5'     },
-{      0x4d,   0,      0,      0,      '6'     },
-{      0x47,   0,      0,      0,      '7'     },
-{      0x48,   0,      0,      0,      '8'     },
-{      0x49,   0,      0,      0,      '9'     },
-{      0x52,   0,      0,      0,      '0'     },
-
-{      0x4a,   0,      '-',    '-',    0       },
-{      0x4e,   0,      '+',    '+',    0       },
-{      0x37,   0,      '*',    '*',    0       },
-{      0x35,   1,      '/',    '/',    0       },
-{      0x53,   0,      0,      0,      '.'     },
-
-{      0x39,   0,      ' ',    ' ',    0       },
-
-{      0x1c,   0,      '\r',   '\r',   0       },
-{      0x1c,   1,      '\r',   '\r',   0       },
-{      0x0e,   0,      0x08,   0x08,   0       }, /* backspace */
-
-{      0,      0,      0,      0,      0       }
+{      0x1e,   0,      'a',    'A',    0, TRUE  },
+{      0x30,   0,      'b',    'B',    0, TRUE  },
+{      0x2e,   0,      'c',    'C',    0, TRUE  },
+{      0x20,   0,      'd',    'D',    0, TRUE  },
+{      0x12,   0,      'e',    'E',    0, TRUE  },
+{      0x21,   0,      'f',    'F',    0, TRUE  },
+{      0x22,   0,      'g',    'G',    0, TRUE  },
+{      0x23,   0,      'h',    'H',    0, TRUE  },
+{      0x17,   0,      'i',    'I',    0, TRUE  },
+{      0x24,   0,      'j',    'J',    0, TRUE  },
+{      0x25,   0,      'k',    'K',    0, TRUE  },
+{      0x26,   0,      'l',    'L',    0, TRUE  },
+{      0x32,   0,      'm',    'M',    0, TRUE  },
+{      0x31,   0,      'n',    'N',    0, TRUE  },
+{      0x18,   0,      'o',    'O',    0, TRUE  },
+{      0x19,   0,      'p',    'P',    0, TRUE  },
+{      0x10,   0,      'q',    'Q',    0, TRUE  },
+{      0x13,   0,      'r',    'R',    0, TRUE  },
+{      0x1f,   0,      's',    'S',    0, TRUE  },
+{      0x14,   0,      't',    'T',    0, TRUE  },
+{      0x16,   0,      'u',    'U',    0, TRUE  },
+{      0x2f,   0,      'v',    'V',    0, TRUE  },
+{      0x11,   0,      'w',    'W',    0, TRUE  },
+{      0x2d,   0,      'x',    'X',    0, TRUE  },
+{      0x15,   0,      'y',    'Y',    0, TRUE  },
+{      0x2c,   0,      'z',    'Z',    0, TRUE  },
+
+{      0x02,   0,      '1',    '!',    0, FALSE },
+{      0x03,   0,      '2',    '@',    0, FALSE },
+{      0x04,   0,      '3',    '#',    0, FALSE },
+{      0x05,   0,      '4',    '$',    0, FALSE },
+{      0x06,   0,      '5',    '%',    0, FALSE },
+{      0x07,   0,      '6',    '^',    0, FALSE },
+{      0x08,   0,      '7',    '&',    0, FALSE },
+{      0x09,   0,      '8',    '*',    0, FALSE },
+{      0x0a,   0,      '9',    '(',    0, FALSE },
+{      0x0b,   0,      '0',    ')',    0, FALSE },
+
+{      0x29,   0,      '\'',   '~',    0, FALSE },
+{      0x0c,   0,      '-',    '_',    0, FALSE },
+{      0x0d,   0,      '=',    '+',    0, FALSE },
+{      0x1a,   0,      '[',    '{',    0, FALSE },
+{      0x1b,   0,      ']',    '}',    0, FALSE },
+{      0x2b,   0,      '\\',   '|',    0, FALSE },
+{      0x27,   0,      ';',    ':',    0, FALSE },
+{      0x28,   0,      '\'',   '"',    0, FALSE },
+{      0x33,   0,      ',',    '<',    0, FALSE },
+{      0x34,   0,      '.',    '>',    0, FALSE },
+{      0x35,   0,      '/',    '?',    0, FALSE },
+
+{      0x4f,   0,      0,      0,      '1', FALSE },
+{      0x50,   0,      0,      0,      '2', FALSE },
+{      0x51,   0,      0,      0,      '3', FALSE },
+{      0x4b,   0,      0,      0,      '4', FALSE },
+{      0x4c,   0,      0,      0,      '5', FALSE },
+{      0x4d,   0,      0,      0,      '6', FALSE },
+{      0x47,   0,      0,      0,      '7', FALSE },
+{      0x48,   0,      0,      0,      '8', FALSE },
+{      0x49,   0,      0,      0,      '9', FALSE },
+{      0x52,   0,      0,      0,      '0', FALSE },
+
+{      0x4a,   0,      '-',    '-',    0, FALSE },
+{      0x4e,   0,      '+',    '+',    0, FALSE },
+{      0x37,   0,      '*',    '*',    0, FALSE },
+{      0x35,   1,      '/',    '/',    0, FALSE },
+{      0x53,   0,      0,      0,      '.', FALSE },
+
+{      0x39,   0,      ' ',    ' ',    0, FALSE },
+
+{      0x1c,   0,      '\r',   '\r',   0, FALSE },
+{      0x1c,   1,      '\r',   '\r',   0, FALSE },
+{      0x0e,   0,      0x08,   0x08,   0, FALSE }, /* backspace */
+
+{      0,      0,      0,      0,      0, FALSE }
 };
 
 
 static void
-IntUpdateControlKeyState(LPDWORD State, PKEYBOARD_INPUT_DATA InputData)
+IntUpdateControlKeyState(HANDLE hConsoleInput, LPDWORD State, PKEYBOARD_INPUT_DATA InputData)
 {
        DWORD Value = 0;
+    DWORD oldState, newState;
 
        if (InputData->Flags & KEY_E1) /* Only the pause key has E1 */
                return;
 
+    oldState = newState = *State;
+
        if (!(InputData->Flags & KEY_E0)) {
                switch (InputData->MakeCode) {
                        case 0x2a:
@@ -276,11 +273,21 @@ IntUpdateControlKeyState(LPDWORD State, PKEYBOARD_INPUT_DATA InputData)
                                Value = LEFT_ALT_PRESSED;
                                break;
 
+                       case 0x3A:
+                               if (!(InputData->Flags & KEY_BREAK))
+                                       newState ^= CAPSLOCK_ON;
+                               break;
+
                        case 0x45:
-                               Value = NUMLOCK_ON;
                                if (!(InputData->Flags & KEY_BREAK))
-                                       *State ^= Value;
-                               return;
+                                       newState ^= NUMLOCK_ON;
+                               break;
+
+                       case 0x46:
+                               if (!(InputData->Flags & KEY_BREAK))
+                                       newState ^= SCROLLLOCK_ON;
+                               break;
+
                        default:
                                return;
                }
@@ -299,10 +306,52 @@ IntUpdateControlKeyState(LPDWORD State, PKEYBOARD_INPUT_DATA InputData)
                }
        }
 
+    /* Check if the state of the indicators has been changed */
+    if ((oldState ^ newState) & (NUMLOCK_ON | CAPSLOCK_ON | SCROLLLOCK_ON))
+    {
+        IO_STATUS_BLOCK               IoStatusBlock;
+        NTSTATUS                      Status;
+        KEYBOARD_INDICATOR_PARAMETERS kip;
+
+        kip.LedFlags = 0;
+        kip.UnitId   = 0;
+
+        if ((newState & NUMLOCK_ON))
+            kip.LedFlags |= KEYBOARD_NUM_LOCK_ON;
+
+        if ((newState & CAPSLOCK_ON))
+            kip.LedFlags |= KEYBOARD_CAPS_LOCK_ON;
+
+        if ((newState & SCROLLLOCK_ON))
+            kip.LedFlags |= KEYBOARD_SCROLL_LOCK_ON;
+
+        /* Update the state of the leds on primary keyboard */
+        DPRINT("NtDeviceIoControlFile dwLeds=%x\n", kip.LedFlags);
+
+        Status = NtDeviceIoControlFile(
+              hConsoleInput,
+              NULL,
+              NULL,
+              NULL,
+              &IoStatusBlock,
+              IOCTL_KEYBOARD_SET_INDICATORS,
+                     &kip,
+              sizeof(kip),
+                     NULL,
+              0);
+
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("NtDeviceIoControlFile(IOCTL_KEYBOARD_SET_INDICATORS) failed (Status %lx)\n", Status);
+        }
+    } else
+    /* Normal press/release state handling */
        if (InputData->Flags & KEY_BREAK)
-               *State &= ~Value;
+               newState &= ~Value;
        else
-               *State |= Value;
+               newState |= Value;
+
+    *State = newState;
 }
 
 static DWORD
@@ -342,6 +391,10 @@ IntAsciiFromInput(PKEYBOARD_INPUT_DATA InputData, DWORD KeyState)
                                        return ScanToAscii[Counter].Normal;
                                }
                        }
+
+                       if ((KeyState & CAPSLOCK_ON) && ScanToAscii[Counter].bCAPS)
+                               KeyState ^= SHIFT_PRESSED;
+
                        if (KeyState & SHIFT_PRESSED)
                                return ScanToAscii[Counter].Shift;
 
@@ -361,7 +414,7 @@ IntAsciiFromInput(PKEYBOARD_INPUT_DATA InputData, DWORD KeyState)
  * in the app so I'll just fill the others with somewhat sane values
  */
 NTSTATUS
-IntTranslateKey(PKEYBOARD_INPUT_DATA InputData, KEY_EVENT_RECORD *Event)
+IntTranslateKey(HANDLE hConsoleInput, PKEYBOARD_INPUT_DATA InputData, KEY_EVENT_RECORD *Event)
 {
        static DWORD dwControlKeyState;
 
@@ -377,7 +430,7 @@ IntTranslateKey(PKEYBOARD_INPUT_DATA InputData, KEY_EVENT_RECORD *Event)
 
        DPRINT("Translating: %x\n", InputData->MakeCode);
 
-       IntUpdateControlKeyState(&dwControlKeyState, InputData);
+       IntUpdateControlKeyState(hConsoleInput, &dwControlKeyState, InputData);
        Event->dwControlKeyState = dwControlKeyState;
 
        if (InputData->Flags & KEY_E0)