Sync with trunk r63887.
[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(PCONSRV_CONSOLE 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 Fake = UnicodeChar &&
179 (msg->message != WM_CHAR && msg->message != WM_SYSCHAR &&
180 msg->message != WM_KEYUP && msg->message != WM_SYSKEYUP);
181 NotChar = (msg->message != WM_CHAR && msg->message != WM_SYSCHAR);
182 if (NotChar) LastVirtualKey = msg->wParam;
183
184 DPRINT("CONSRV: %s %s %s %s %02x %02x '%lc' %04x\n",
185 Down ? "down" : "up ",
186 (msg->message == WM_CHAR || msg->message == WM_SYSCHAR) ?
187 "char" : "key ",
188 Fake ? "fake" : "real",
189 NotChar ? "notc" : "char",
190 VirtualScanCode,
191 VirtualKeyCode,
192 (UnicodeChar >= L' ') ? UnicodeChar : L'.',
193 ShiftState);
194
195 if (Fake) return;
196
197 /* Send the key press to the console driver */
198 ConDrvProcessKey(Console,
199 Down,
200 VirtualKeyCode,
201 VirtualScanCode,
202 UnicodeChar,
203 ShiftState,
204 KeyState[VK_CONTROL]);
205 }
206
207 DWORD
208 ConioEffectiveCursorSize(PCONSRV_CONSOLE Console, DWORD Scale)
209 {
210 DWORD Size = (Console->ActiveBuffer->CursorInfo.dwSize * Scale + 99) / 100;
211 /* If line input in progress, perhaps adjust for insert toggle */
212 if (Console->LineBuffer && !Console->LineComplete && (Console->InsertMode ? !Console->LineInsertToggle : Console->LineInsertToggle))
213 return (Size * 2 <= Scale) ? (Size * 2) : (Size / 2);
214 return Size;
215 }
216
217 /* EOF */