1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Console Server DLL 4 * FILE: win32ss/user/winsrv/consrv/frontends/input.c 5 * PURPOSE: Common Front-Ends Input functions 6 * PROGRAMMERS: Jeffrey Morlan 7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr) 8 */ 9 10 /* INCLUDES *******************************************************************/ 11 12 #include "consrv.h" 13 #include "include/term.h" 14 #include "coninput.h" 15 16 #define NDEBUG 17 #include <debug.h> 18 19 20 /* PRIVATE FUNCTIONS **********************************************************/ 21 22 static DWORD 23 ConioGetShiftState(PBYTE KeyState, LPARAM lParam) 24 { 25 DWORD ssOut = 0; 26 27 if (KeyState[VK_CAPITAL] & 0x01) 28 ssOut |= CAPSLOCK_ON; 29 30 if (KeyState[VK_NUMLOCK] & 0x01) 31 ssOut |= NUMLOCK_ON; 32 33 if (KeyState[VK_SCROLL] & 0x01) 34 ssOut |= SCROLLLOCK_ON; 35 36 if (KeyState[VK_SHIFT] & 0x80) 37 ssOut |= SHIFT_PRESSED; 38 39 if (KeyState[VK_LCONTROL] & 0x80) 40 ssOut |= LEFT_CTRL_PRESSED; 41 if (KeyState[VK_RCONTROL] & 0x80) 42 ssOut |= RIGHT_CTRL_PRESSED; 43 44 if (KeyState[VK_LMENU] & 0x80) 45 ssOut |= LEFT_ALT_PRESSED; 46 if (KeyState[VK_RMENU] & 0x80) 47 ssOut |= RIGHT_ALT_PRESSED; 48 49 /* See WM_CHAR MSDN documentation for instance */ 50 if (lParam & 0x01000000) 51 ssOut |= ENHANCED_KEY; 52 53 return ssOut; 54 } 55 56 VOID NTAPI 57 ConioProcessKey(PCONSRV_CONSOLE Console, MSG* msg) 58 { 59 static BYTE KeyState[256] = { 0 }; 60 /* MSDN mentions that you should use the last virtual key code received 61 * when putting a virtual key identity to a WM_CHAR message since multiple 62 * or translated keys may be involved. */ 63 static UINT LastVirtualKey = 0; 64 DWORD ShiftState; 65 WCHAR UnicodeChar; 66 UINT VirtualKeyCode; 67 UINT VirtualScanCode; 68 BOOL Down = FALSE; 69 BOOLEAN Fake; // Synthesized, not a real event 70 BOOLEAN NotChar; // Message should not be used to return a character 71 72 INPUT_RECORD er; 73 74 if (Console == NULL) 75 { 76 DPRINT1("No Active Console!\n"); 77 return; 78 } 79 80 VirtualScanCode = HIWORD(msg->lParam) & 0xFF; 81 Down = msg->message == WM_KEYDOWN || msg->message == WM_CHAR || 82 msg->message == WM_SYSKEYDOWN || msg->message == WM_SYSCHAR; 83 84 GetKeyboardState(KeyState); 85 ShiftState = ConioGetShiftState(KeyState, msg->lParam); 86 87 if (msg->message == WM_CHAR || msg->message == WM_SYSCHAR) 88 { 89 VirtualKeyCode = LastVirtualKey; 90 UnicodeChar = msg->wParam; 91 } 92 else 93 { 94 WCHAR Chars[2]; 95 INT RetChars = 0; 96 97 VirtualKeyCode = msg->wParam; 98 RetChars = ToUnicodeEx(VirtualKeyCode, 99 VirtualScanCode, 100 KeyState, 101 Chars, 102 2, 103 0, 104 NULL); 105 UnicodeChar = (RetChars == 1 ? Chars[0] : 0); 106 } 107 108 Fake = UnicodeChar && 109 (msg->message != WM_CHAR && msg->message != WM_SYSCHAR && 110 msg->message != WM_KEYUP && msg->message != WM_SYSKEYUP); 111 NotChar = (msg->message != WM_CHAR && msg->message != WM_SYSCHAR); 112 if (NotChar) LastVirtualKey = msg->wParam; 113 114 DPRINT("CONSRV: %s %s %s %s %02x %02x '%lc' %04x\n", 115 Down ? "down" : "up ", 116 (msg->message == WM_CHAR || msg->message == WM_SYSCHAR) ? 117 "char" : "key ", 118 Fake ? "fake" : "real", 119 NotChar ? "notc" : "char", 120 VirtualScanCode, 121 VirtualKeyCode, 122 (UnicodeChar >= L' ') ? UnicodeChar : L'.', 123 ShiftState); 124 125 if (Fake) return; 126 127 /* Process Ctrl-C and Ctrl-Break */ 128 if ( Console->InputBuffer.Mode & ENABLE_PROCESSED_INPUT && 129 Down && (VirtualKeyCode == VK_PAUSE || VirtualKeyCode == 'C') && 130 (ShiftState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) || KeyState[VK_CONTROL] & 0x80) ) 131 { 132 DPRINT1("Console_Api Ctrl-C\n"); 133 ConSrvConsoleProcessCtrlEvent(Console, 0, CTRL_C_EVENT); 134 135 if (Console->LineBuffer && !Console->LineComplete) 136 { 137 /* Line input is in progress; end it */ 138 Console->LinePos = Console->LineSize = 0; 139 Console->LineComplete = TRUE; 140 } 141 return; 142 } 143 144 if ( (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) != 0 && 145 (VirtualKeyCode == VK_UP || VirtualKeyCode == VK_DOWN) ) 146 { 147 if (!Down) return; 148 149 /* Scroll up or down */ 150 if (VirtualKeyCode == VK_UP) 151 { 152 /* Only scroll up if there is room to scroll up into */ 153 if (Console->ActiveBuffer->CursorPosition.Y != Console->ActiveBuffer->ScreenBufferSize.Y - 1) 154 { 155 Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + 156 Console->ActiveBuffer->ScreenBufferSize.Y - 1) % 157 Console->ActiveBuffer->ScreenBufferSize.Y; 158 Console->ActiveBuffer->CursorPosition.Y++; 159 } 160 } 161 else 162 { 163 /* Only scroll down if there is room to scroll down into */ 164 if (Console->ActiveBuffer->CursorPosition.Y != 0) 165 { 166 Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + 1) % 167 Console->ActiveBuffer->ScreenBufferSize.Y; 168 Console->ActiveBuffer->CursorPosition.Y--; 169 } 170 } 171 172 ConioDrawConsole(Console); 173 return; 174 } 175 176 /* Send the key press to the console driver */ 177 178 er.EventType = KEY_EVENT; 179 er.Event.KeyEvent.bKeyDown = Down; 180 er.Event.KeyEvent.wRepeatCount = 1; 181 er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode; 182 er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode; 183 er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar; 184 er.Event.KeyEvent.dwControlKeyState = ShiftState; 185 186 ConioProcessInputEvent(Console, &er); 187 } 188 189 DWORD 190 ConioEffectiveCursorSize(PCONSRV_CONSOLE Console, DWORD Scale) 191 { 192 DWORD Size = (Console->ActiveBuffer->CursorInfo.dwSize * Scale + 99) / 100; 193 /* If line input in progress, perhaps adjust for insert toggle */ 194 if (Console->LineBuffer && !Console->LineComplete && (Console->InsertMode ? !Console->LineInsertToggle : Console->LineInsertToggle)) 195 return (Size * 2 <= Scale) ? (Size * 2) : (Size / 2); 196 return Size; 197 } 198 199 /* EOF */ 200