last fuzzy translated...
[midnight-commander.git] / slang / slw32tty.c
blob990e220f4b22d46a91107bed673d6ecdbfd58b87
1 /* Copyright (c) 1992, 1999, 2001, 2002 John E. Davis
2 * This file is part of the S-Lang library.
4 * You may distribute under the terms of either the GNU General Public
5 * License or the Perl Artistic License.
6 */
8 #include "slinclud.h"
10 #include <windows.h>
11 #include <winbase.h>
13 #include "slang.h"
14 #include "_slang.h"
16 #ifdef __cplusplus
17 # define _DOTS_ ...
18 #else
19 # define _DOTS_ void
20 #endif
22 static int Process_Mouse_Events;
24 /*----------------------------------------------------------------------*\
25 * Function: static void set_ctrl_break (int state);
27 * set the control-break setting
28 \*----------------------------------------------------------------------*/
29 static void set_ctrl_break (int state)
33 /*----------------------------------------------------------------------*\
34 * Function: int SLang_init_tty (int abort_char, int no_flow_control,
35 * int opost);
37 * initialize the keyboard interface and attempt to set-up the interrupt 9
38 * handler if ABORT_CHAR is non-zero.
39 * NO_FLOW_CONTROL and OPOST are only for compatiblity and are ignored.
40 \*----------------------------------------------------------------------*/
42 HANDLE _SLw32_Hstdin = INVALID_HANDLE_VALUE;
44 int SLang_init_tty (int abort_char, int no_flow_control, int opost)
46 (void) opost;
47 (void) no_flow_control;
49 if (_SLw32_Hstdin != INVALID_HANDLE_VALUE)
50 return 0;
52 #if 1
53 /* stdin may have been redirected. So try this */
54 _SLw32_Hstdin = CreateFile ("CONIN$", GENERIC_READ|GENERIC_WRITE,
55 FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
56 OPEN_EXISTING, 0, NULL);
57 if (_SLw32_Hstdin == INVALID_HANDLE_VALUE)
58 return -1;
59 #else
60 if (INVALID_HANDLE_VALUE == (_SLw32_Hstdin = GetStdHandle(STD_INPUT_HANDLE)))
61 return -1;
62 #endif
64 if (FALSE == SetConsoleMode(_SLw32_Hstdin, ENABLE_WINDOW_INPUT|ENABLE_MOUSE_INPUT))
66 _SLw32_Hstdin = INVALID_HANDLE_VALUE;
67 return -1;
70 if (abort_char > 0)
71 SLang_Abort_Char = abort_char;
73 return 0;
75 /* SLang_init_tty */
77 /*----------------------------------------------------------------------*\
78 * Function: void SLang_reset_tty (void);
80 * reset the tty before exiting
81 \*----------------------------------------------------------------------*/
82 void SLang_reset_tty (void)
84 _SLw32_Hstdin = INVALID_HANDLE_VALUE;
85 set_ctrl_break (1);
88 static int process_mouse_event (MOUSE_EVENT_RECORD *m)
90 char buf [8];
92 if (Process_Mouse_Events == 0)
93 return -1;
95 if (m->dwEventFlags)
96 return -1; /* double click or movement event */
98 /* A button was either pressed or released. Now make sure that
99 * the shift keys were not also pressed.
101 if (m->dwControlKeyState
102 & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED
103 |LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED
104 |SHIFT_PRESSED))
105 return -1;
107 /* We have a simple press or release. Encode it as an escape sequence
108 * and buffer the result. The encoding is:
109 * 'ESC [ M b x y'
110 * where b represents the button state, and x,y represent the coordinates.
111 * The ESC is handled by the calling routine.
113 if (m->dwButtonState & 1) buf[3] = ' ';
114 else if (m->dwButtonState & 2) buf[3] = ' ' + 2;
115 else if (m->dwButtonState & 4) buf[3] = ' ' + 1;
116 else return -1;
118 buf[0] = 27;
119 buf[1] = '[';
120 buf[2] = 'M';
123 buf[4] = 1 + ' ' + m->dwMousePosition.X;
124 buf[5] = 1 + ' ' + m->dwMousePosition.Y;
126 return SLang_buffer_keystring ((unsigned char *)buf, 6);
129 static int process_key_event (KEY_EVENT_RECORD *key)
131 unsigned int key_state = 0;
132 unsigned int scan;
133 char c1;
134 DWORD d = key->dwControlKeyState;
135 unsigned char buf[4];
137 if (!key->bKeyDown) return 0;
138 if (d & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
139 key_state |= _SLTT_KEY_ALT;
140 if (d & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
141 key_state |= _SLTT_KEY_CTRL;
142 if (d & SHIFT_PRESSED)
143 key_state |= _SLTT_KEY_SHIFT;
145 scan = key->wVirtualScanCode;
147 switch (scan)
149 case 0x00E: /* backspace */
150 return SLang_buffer_keystring ((unsigned char *)"\x7F", 1);
152 case 0x003: /* 2 key */
153 if (key_state & _SLTT_KEY_ALT)
154 break;
155 /* Drop */
156 case 0x039: /* space */
157 if (key_state & _SLTT_KEY_CTRL)
158 return SLang_buffer_keystring ((unsigned char *)"\x00\x03", 2);
159 break;
161 case 0x007: /* 6 key */
162 if (_SLTT_KEY_CTRL == (key_state & (_SLTT_KEY_ALT|_SLTT_KEY_CTRL)))
163 return SLang_buffer_keystring ((unsigned char *)"\x1E", 1); /* Ctrl-^ */
164 break;
166 case 0x00C: /* -/_ key */
167 if (_SLTT_KEY_CTRL == (key_state & (_SLTT_KEY_ALT|_SLTT_KEY_CTRL)))
168 return SLang_buffer_keystring ((unsigned char *)"\x1F", 1);
169 break;
171 case 0x00F: /* TAB */
172 if (_SLTT_KEY_SHIFT == key_state)
173 return SLang_buffer_keystring ((unsigned char *)"\x00\x09", 2);
174 break;
176 case 0xE02F: /* KEYPAD SLASH */
177 case 0x037: /* KEYPAD STAR */
178 case 0x04A: /* KEYPAD MINUS */
179 case 0x04E: /* KEYPAD PLUS */
180 if (d & NUMLOCK_ON)
181 break;
182 case 0x047: /* KEYPAD HOME */
183 case 0x048: /* KEYPAD UP */
184 case 0x049: /* KEYPAD PGUP */
185 case 0x04B: /* KEYPAD LEFT */
186 case 0x04C: /* KEYPAD 5 */
187 case 0x04D: /* KEYPAD RIGHT */
188 case 0x04F: /* KEYPAD END */
189 case 0x050: /* KEYPAD DOWN */
190 case 0x051: /* KEYPAD PGDN */
191 case 0x052: /* KEYPAD INSERT */
192 case 0x053: /* KEYPAD DEL */
193 if (d & ENHANCED_KEY)
194 scan |= 0xE000;
195 else
197 if (d & NUMLOCK_ON)
198 break;
200 (void) _SLpc_convert_scancode (scan, key_state, 0);
201 return 0;
203 case 0x3b: /* F1 */
204 case 0x3c:
205 case 0x3d:
206 case 0x3e:
207 case 0x3f:
208 case 0x40:
209 case 0x41:
210 case 0x42:
211 case 0x43:
212 case 0x44:
213 case 0x57:
214 case 0x58: /* F12 */
215 (void) _SLpc_convert_scancode (scan, key_state, 0);
218 c1 = key->uChar.AsciiChar;
219 if (c1 != 0)
221 if (_SLTT_KEY_ALT == (key_state & (_SLTT_KEY_ALT|_SLTT_KEY_CTRL)))
223 buf[0] = 27;
224 buf[1] = c1;
225 return SLang_buffer_keystring (buf, 2);
227 if (c1 == SLang_Abort_Char)
229 if (SLang_Ignore_User_Abort == 0) SLang_Error = USER_BREAK;
230 SLKeyBoard_Quit = 1;
232 buf[0] = c1;
233 return SLang_buffer_keystring (buf, 1);
235 return 0;
239 static void process_console_records(void)
241 INPUT_RECORD record;
242 DWORD bytesRead;
243 DWORD n = 0;
245 if (FALSE == GetNumberOfConsoleInputEvents(_SLw32_Hstdin, &n))
246 return;
248 while (n > 0)
250 ReadConsoleInput(_SLw32_Hstdin, &record, 1, &bytesRead);
251 switch (record.EventType)
253 case KEY_EVENT:
254 (void) process_key_event(&record.Event.KeyEvent);
255 break;
257 case MOUSE_EVENT:
258 process_mouse_event(&record.Event.MouseEvent);
259 break;
261 case WINDOW_BUFFER_SIZE_EVENT:
262 /* process_resize_records(&record.Event.WindowBufferSizeEvent); */
263 break;
265 n--;
269 /*----------------------------------------------------------------------*\
270 * Function: int _SLsys_input_pending (int tsecs);
272 * sleep for *tsecs tenths of a sec waiting for input
273 \*----------------------------------------------------------------------*/
274 int _SLsys_input_pending (int tsecs)
276 long ms;
278 if (_SLw32_Hstdin == INVALID_HANDLE_VALUE)
279 return -1;
281 if (tsecs < 0) ms = -tsecs; /* specifies 1/1000 */
282 else ms = tsecs * 100L; /* convert 1/10 to 1/1000 secs */
284 process_console_records ();
285 while ((ms > 0)
286 && (SLang_Input_Buffer_Len == 0))
288 long t;
290 t = GetTickCount ();
292 (void) WaitForSingleObject (_SLw32_Hstdin, ms);
293 process_console_records ();
294 ms -= GetTickCount () - t;
297 return SLang_Input_Buffer_Len;
300 /*----------------------------------------------------------------------*\
301 * Function: unsigned int _SLsys_getkey (void);
303 * wait for and get the next available keystroke.
304 * Also re-maps some useful keystrokes.
306 * Backspace (^H) => Del (127)
307 * Ctrl-Space => ^@ (^@^3 - a pc NUL char)
308 * extended keys are prefixed by a null character
309 \*----------------------------------------------------------------------*/
310 unsigned int _SLsys_getkey (void)
312 /* Check the input buffer because _SLsys_input_pending may have been
313 * called prior to this to stuff the input buffer.
315 if (SLang_Input_Buffer_Len)
316 return SLang_getkey ();
318 if (_SLw32_Hstdin == INVALID_HANDLE_VALUE)
319 return SLANG_GETKEY_ERROR;
321 while (1)
323 int status;
325 if (SLKeyBoard_Quit)
326 return SLang_Abort_Char;
328 status = _SLsys_input_pending (600);
329 if (status == -1)
330 return SLANG_GETKEY_ERROR;
332 if (status > 0)
333 return SLang_getkey ();
337 /*----------------------------------------------------------------------*\
338 * Function: int SLang_set_abort_signal (void (*handler)(int));
339 \*----------------------------------------------------------------------*/
340 int SLang_set_abort_signal (void (*handler)(int))
342 if (_SLw32_Hstdin == INVALID_HANDLE_VALUE)
343 return -1;
345 return 0;
348 int SLtt_set_mouse_mode (int mode, int force)
350 (void) force;
352 Process_Mouse_Events = mode;
353 return 0;