update cvsingnore files
[reactos.git] / rosapps / mc / pc / key_nt.c
1 /* Keyboard support routines.
2 for Windows NT system.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 Bugs:
19 Have trouble with non-US keyboards, "Alt-gr"+keys (API tells CTRL-ALT is pressed)
20 */
21 #include <config.h>
22 #ifndef _OS_NT
23 #error This file is for Win32 systems.
24 #else
25
26 #include <windows.h>
27 #include <stdio.h>
28 #include "../src/mouse.h"
29 #include "../src/global.h"
30 #include "../src/main.h"
31 #include "../src/key.h"
32 #include "../vfs/vfs.h"
33 #include "../src/tty.h"
34 #include "trace_nt.h"
35
36 /* Global variables */
37 int old_esc_mode = 0;
38 HANDLE hConsoleInput;
39 DWORD dwSaved_ControlState;
40 Gpm_Event evSaved_Event;
41
42 /* Unused variables */
43 int double_click_speed; /* they are here to keep linker happy */
44 int mou_auto_repeat;
45 int use_8th_bit_as_meta = 0;
46
47 /* Static Tables */
48 struct {
49 int key_code;
50 int vkcode;
51 } key_table [] = {
52 { KEY_F(1), VK_F1 },
53 { KEY_F(2), VK_F2 },
54 { KEY_F(3), VK_F3 },
55 { KEY_F(4), VK_F4 },
56 { KEY_F(5), VK_F5 },
57 { KEY_F(6), VK_F6 },
58 { KEY_F(7), VK_F7 },
59 { KEY_F(8), VK_F8 },
60 { KEY_F(9), VK_F9 },
61 { KEY_F(10), VK_F10 },
62 { KEY_F(11), VK_F11 },
63 { KEY_F(12), VK_F12 },
64 { KEY_F(13), VK_F13 },
65 { KEY_F(14), VK_F14 },
66 { KEY_F(15), VK_F15 },
67 { KEY_F(16), VK_F16 },
68 { KEY_F(17), VK_F17 },
69 { KEY_F(18), VK_F18 },
70 { KEY_F(19), VK_F19 },
71 { KEY_F(20), VK_F20 },
72 { KEY_IC, VK_INSERT },
73 { KEY_DC, VK_DELETE },
74 { KEY_BACKSPACE, VK_BACK },
75
76 { KEY_PPAGE, VK_PRIOR },
77 { KEY_NPAGE, VK_NEXT },
78 { KEY_LEFT, VK_LEFT },
79 { KEY_RIGHT, VK_RIGHT },
80 { KEY_UP, VK_UP },
81 { KEY_DOWN, VK_DOWN },
82 { KEY_HOME, VK_HOME },
83 { KEY_END, VK_END },
84
85 { ALT('*'), VK_MULTIPLY },
86 { ALT('+'), VK_ADD },
87 { ALT('-'), VK_SUBTRACT },
88
89 { ALT('\t'), VK_PAUSE }, /* Added to make Complete work press Pause */
90
91 { ESC_CHAR, VK_ESCAPE },
92
93 { 0, 0}
94 };
95
96 /* init_key - Called in main.c to initialize ourselves
97 Get handle to console input
98 */
99 void init_key (void)
100 {
101 win32APICALL_HANDLE (hConsoleInput, GetStdHandle (STD_INPUT_HANDLE));
102 }
103
104 int ctrl_pressed ()
105 {
106 if(dwSaved_ControlState & RIGHT_ALT_PRESSED) return 0;
107 /* The line above fixes the BUG with the AltGr Keys*/
108 return dwSaved_ControlState & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED);
109 }
110
111 int shift_pressed ()
112 {
113 if(dwSaved_ControlState & RIGHT_ALT_PRESSED) return 0;
114 /* The line above fixes the BUG with the AltGr Keys*/
115 return dwSaved_ControlState & SHIFT_PRESSED;
116 }
117
118 int alt_pressed ()
119 {
120 return dwSaved_ControlState & (/* RIGHT_ALT_PRESSED | */ LEFT_ALT_PRESSED);
121 }
122
123 static int VKtoCurses (int a_vkc)
124 {
125 int i;
126
127 for (i = 0; key_table[i].vkcode != 0; i++)
128 if (a_vkc == key_table[i].vkcode) {
129 return key_table[i].key_code;
130 }
131 return 0;
132 }
133
134 static int translate_key_code(int asc, int scan)
135 {
136 int c;
137 switch(scan){
138 case 106: /* KP_MULT*/
139 return ALT('*');
140 case 107: /* KP_PLUS*/
141 return ALT('+');
142 case 109: /* KP_MINUS*/
143 return ALT('-');
144 }
145 c = VKtoCurses (scan);
146 if (!asc && !c)
147 return 0;
148 if (asc && c)
149 return c;
150 if (!asc || asc=='\t' )
151 {
152 if (shift_pressed() && (c >= KEY_F(1)) && (c <= KEY_F(10)))
153 c += 10;
154 if (alt_pressed() && (c >= KEY_F(1)) && (c <= KEY_F(2)))
155 c += 10;
156 if (alt_pressed() && (c == KEY_F(7)))
157 c = ALT('?');
158 if (asc == '\t'){
159 if(ctrl_pressed())c = ALT('\t');
160 else c=asc;
161 }
162 return c;
163 }
164 if (ctrl_pressed())
165 return XCTRL(asc);
166 if (alt_pressed())
167 return ALT(asc);
168 if (asc == 13)
169 return 10;
170 return asc;
171 }
172
173 int get_key_code (int no_delay)
174 {
175 INPUT_RECORD ir; /* Input record */
176 DWORD dw; /* number of records actually read */
177 int ch, vkcode, j;
178
179 if (no_delay) {
180 /* Check if any input pending, otherwise return */
181 nodelay (stdscr, TRUE);
182 win32APICALL(PeekConsoleInput(hConsoleInput, &ir, 1, &dw));
183 if (!dw)
184 return 0;
185 }
186
187 do {
188 win32APICALL(ReadConsoleInput(hConsoleInput, &ir, 1, &dw));
189 switch (ir.EventType) {
190 case KEY_EVENT:
191 if (!ir.Event.KeyEvent.bKeyDown) /* Process key just once: when pressed */
192 break;
193
194 vkcode = ir.Event.KeyEvent.wVirtualKeyCode;
195 //#ifndef __MINGW32__
196 ch = ir.Event.KeyEvent.uChar.AsciiChar;
197 //#else
198 // ch = ir.Event.KeyEvent.AsciiChar;
199 //#endif
200 dwSaved_ControlState = ir.Event.KeyEvent.dwControlKeyState;
201 j = translate_key_code (ch, vkcode);
202 if (j)
203 return j;
204 break;
205
206 case MOUSE_EVENT:
207 /* Save event as a GPM-like event */
208 evSaved_Event.x = ir.Event.MouseEvent.dwMousePosition.X;
209 evSaved_Event.y = ir.Event.MouseEvent.dwMousePosition.Y+1;
210 evSaved_Event.buttons = ir.Event.MouseEvent.dwButtonState;
211 switch (ir.Event.MouseEvent.dwEventFlags) {
212 case 0:
213 evSaved_Event.type = GPM_DOWN | GPM_SINGLE;
214 break;
215 case MOUSE_MOVED:
216 evSaved_Event.type = GPM_MOVE;
217 break;
218 case DOUBLE_CLICK:
219 evSaved_Event.type = GPM_DOWN | GPM_DOUBLE;
220 break;
221 };
222 return 0;
223 }
224 } while (!no_delay);
225 return 0;
226 }
227
228 static int getch_with_delay (void)
229 {
230 int c;
231
232 while (1) {
233 /* Try to get a character */
234 c = get_key_code (0);
235 if (c != ERR)
236 break;
237 }
238 /* Success -> return the character */
239 return c;
240 }
241
242 /* Returns a character read from stdin with appropriate interpretation */
243 int get_event (Gpm_Event *event, int redo_event, int block)
244 {
245 int c;
246 static int flag; /* Return value from select */
247 static int dirty = 3;
248
249 if ((dirty == 1) || is_idle ()){
250 refresh ();
251 doupdate ();
252 dirty = 1;
253 } else
254 dirty++;
255
256 vfs_timeout_handler ();
257
258 c = block ? getch_with_delay () : get_key_code (1);
259
260 if (!c) {
261 /* Code is 0, so this is a Control key or mouse event */
262 return EV_NONE; /* FIXME: mouse not supported */
263 }
264
265 return c;
266 }
267
268 /* Returns a key press, mouse events are discarded */
269 int mi_getch ()
270 {
271 Gpm_Event ev;
272 int key;
273
274 while ((key = get_event (&ev, 0, 1)) == 0)
275 ;
276 return key;
277 }
278
279 /*
280 is_idle - A function to check if we're idle.
281 It checks for any waiting event (that can be a Key, Mouse event,
282 and other internal events like focus or menu)
283 */
284 int is_idle (void)
285 {
286 DWORD dw;
287 if (GetNumberOfConsoleInputEvents (hConsoleInput, &dw))
288 if (dw > 15)
289 return 0;
290 return 1;
291 }
292
293 /* get_modifier */
294 int get_modifier()
295 {
296 int retval = 0;
297
298 if (dwSaved_ControlState & LEFT_ALT_PRESSED) /* code is not clean, because we return Linux-like bitcodes*/
299 retval |= ALTL_PRESSED;
300 if (dwSaved_ControlState & RIGHT_ALT_PRESSED)
301 retval |= ALTR_PRESSED;
302
303 if (dwSaved_ControlState & RIGHT_CTRL_PRESSED ||
304 dwSaved_ControlState & LEFT_CTRL_PRESSED)
305 retval |= CONTROL_PRESSED;
306
307 if (dwSaved_ControlState & SHIFT_PRESSED)
308 retval |= SHIFT_PRESSED;
309
310 return retval;
311 }
312
313 /* void functions for UNIX compatibility */
314 void define_sequence (int code, char* vkcode, int action) {}
315 void channels_up() {}
316 void channels_down() {}
317 void init_key_input_fd (void) {}
318 void numeric_keypad_mode (void) {}
319 void application_keypad_mode (void) {}
320
321 /* mouse is not yet supported, sorry */
322 void init_mouse (void) {}
323 void shut_mouse (void) {}
324
325 #endif /* _OS_NT */