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