(ctrl_c_handler): Ignore CTRL_BREAK_EVENT signals.
[bpt/emacs.git] / src / w32inevt.c
CommitLineData
6cdfb6e6 1/* Input event support for Windows NT port of GNU Emacs.
b02466e8 2 Copyright (C) 1992, 1993, 1995 Free Software Foundation, Inc.
6cdfb6e6
RS
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any later
9 version.
10
11 GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 more details.
15
16 You should have received a copy of the GNU General Public License along
17 with GNU Emacs; see the file COPYING. If not, write to the Free Software
18 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19
20 Drew Bliss 01-Oct-93
21 Adapted from ntkbd.c by Tim Fleehart
22*/
23
24
25#include "config.h"
26
27#include <stdlib.h>
28#include <stdio.h>
29#include <windows.h>
30
31#include "lisp.h"
32#include "frame.h"
33#include "blockinput.h"
34#include "termhooks.h"
35
36/* stdin, from ntterm */
37extern HANDLE keyboard_handle;
38
39/* Indicate mouse motion, from keyboard.c */
40extern int mouse_moved;
41
42/* Info for last mouse motion */
43static COORD movement_pos;
44static DWORD movement_time;
45
46/* from keyboard.c */
47extern void reinvoke_input_signal (void);
48
49/* from dispnew.c */
50extern int change_frame_size (FRAME_PTR, int, int, int, int);
51
52/* Event queue */
53#define EVENT_QUEUE_SIZE 50
54static INPUT_RECORD event_queue[EVENT_QUEUE_SIZE];
55static INPUT_RECORD *queue_ptr = event_queue, *queue_end = event_queue;
56
57static int
58fill_queue (BOOL block)
59{
60 BOOL rc;
61 DWORD events_waiting;
62
63 if (queue_ptr < queue_end)
64 return queue_end-queue_ptr;
65
66 if (!block)
67 {
68 /* Check to see if there are some events to read before we try
69 because we can't block. */
70 if (!GetNumberOfConsoleInputEvents (keyboard_handle, &events_waiting))
71 return -1;
72 if (events_waiting == 0)
73 return 0;
74 }
75
76 rc = ReadConsoleInput (keyboard_handle, event_queue, EVENT_QUEUE_SIZE,
77 &events_waiting);
78 if (!rc)
79 return -1;
80 queue_ptr = event_queue;
81 queue_end = event_queue + events_waiting;
82 return (int) events_waiting;
83}
84
85/* In a generic, multi-frame world this should take a console handle
86 and return the frame for it
87
88 Right now, there's only one frame so return it. */
89static FRAME_PTR
90get_frame (void)
91{
92 return selected_frame;
93}
94
b02466e8
KH
95/* Translate console modifiers to emacs modifiers.
96 German keyboard support (Kai Morgan Zeise 2/18/95). */
6cdfb6e6 97static int
b02466e8 98win32_kbd_mods_to_emacs (DWORD mods)
6cdfb6e6 99{
b02466e8
KH
100 int retval = 0;
101
102 /* If AltGr has been pressed, remove it. */
103 if ((mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
104 == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
105 mods &= ~ (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED);
106
107 if (mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
108 retval = meta_modifier;
109
110 if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
111 {
112 retval |= ctrl_modifier;
113 if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
114 == (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
115 retval |= meta_modifier;
116 }
117
118 if (((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) == SHIFT_PRESSED)
119 || ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) == CAPSLOCK_ON))
120 retval |= shift_modifier;
121
122 return retval;
123}
124
125/* Patch up NT keyboard events when info is missing that should be there,
126 assuming that map_virt_key says that the key is a valid ASCII char. */
127static char win32_number_shift_map[] = {
128 ')', '!', '@', '#', '$', '%', '^', '&', '*', '('
129};
130
131#define WIN32_KEY_SHIFTED(mods, no, yes) \
132 ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) ? yes : no)
133
134static void
135win32_kbd_patch_key (KEY_EVENT_RECORD *event)
136{
137 unsigned int key_code = event->wVirtualKeyCode;
138 unsigned int mods = event->dwControlKeyState;
139 int mapped_punct = 0;
140
141 /* map_virt_key says its a valid key, but the uChar.AsciiChar field
142 is empty. patch up the uChar.AsciiChar field using wVirtualKeyCode. */
143 if (event->uChar.AsciiChar == 0
144 && ((key_code >= '0' && key_code <= '9')
145 || (key_code >= 'A' && key_code <= 'Z')
146 || (key_code >= 0xBA && key_code <= 0xC0)
147 || (key_code >= 0xDB && key_code <= 0xDE)
148 )) {
149 if (key_code >= '0' && key_code <= '9') {
150 event->uChar.AsciiChar =
151 WIN32_KEY_SHIFTED (mods, key_code,
152 win32_number_shift_map[key_code - '0']);
153 return;
154 }
155 switch (key_code) {
156 case 0xBA: mapped_punct = WIN32_KEY_SHIFTED (mods, ';', ':'); break;
157 case 0xBB: mapped_punct = WIN32_KEY_SHIFTED (mods, '=', '+'); break;
158 case 0xBC: mapped_punct = WIN32_KEY_SHIFTED (mods, ',', '<'); break;
159 case 0xBD: mapped_punct = WIN32_KEY_SHIFTED (mods, '-', '_'); break;
160 case 0xBE: mapped_punct = WIN32_KEY_SHIFTED (mods, '.', '>'); break;
161 case 0xBF: mapped_punct = WIN32_KEY_SHIFTED (mods, '/', '?'); break;
162 case 0xC0: mapped_punct = WIN32_KEY_SHIFTED (mods, '`', '~'); break;
163 case 0xDB: mapped_punct = WIN32_KEY_SHIFTED (mods, '[', '{'); break;
164 case 0xDC: mapped_punct = WIN32_KEY_SHIFTED (mods, '\\', '|'); break;
165 case 0xDD: mapped_punct = WIN32_KEY_SHIFTED (mods, ']', '}'); break;
166 case 0xDE: mapped_punct = WIN32_KEY_SHIFTED (mods, '\'', '"'); break;
167 default:
168 mapped_punct = 0;
169 break;
170 }
171 if (mapped_punct) {
172 event->uChar.AsciiChar = mapped_punct;
173 return;
174 }
175 /* otherwise, it's a letter. */
176 event->uChar.AsciiChar = WIN32_KEY_SHIFTED (mods, key_code - 'A' + 'a',
177 key_code);
178 }
6cdfb6e6
RS
179}
180
181/* Map virtual key codes into:
182 -1 - Ignore this key
183 -2 - ASCII char
184 Other - Map non-ASCII keys into X keysyms so that they are looked up
185 correctly in keyboard.c
186
187 Return, escape and tab are mapped to ASCII rather than coming back
188 as non-ASCII to be more compatible with old-style keyboard support. */
189
190static int map_virt_key[256] =
191{
192 -1,
193 -1, /* VK_LBUTTON */
194 -1, /* VK_RBUTTON */
195 0x69, /* VK_CANCEL */
196 -1, /* VK_MBUTTON */
197 -1, -1, -1,
198 8, /* VK_BACK */
199 -2, /* VK_TAB */
200 -1, -1,
201 11, /* VK_CLEAR */
202 -2, /* VK_RETURN */
203 -1, -1,
204 -1, /* VK_SHIFT */
205 -1, /* VK_CONTROL */
206 -1, /* VK_MENU */
207 0x13, /* VK_PAUSE */
208 -1, /* VK_CAPITAL */
209 -1, -1, -1, -1, -1, -1,
210 -2, /* VK_ESCAPE */
211 -1, -1, -1, -1,
212 -2, /* VK_SPACE */
213 0x55, /* VK_PRIOR */
214 0x56, /* VK_NEXT */
215 0x57, /* VK_END */
216 0x50, /* VK_HOME */
217 0x51, /* VK_LEFT */
218 0x52, /* VK_UP */
219 0x53, /* VK_RIGHT */
220 0x54, /* VK_DOWN */
221 0x60, /* VK_SELECT */
222 0x61, /* VK_PRINT */
223 0x62, /* VK_EXECUTE */
224 -1, /* VK_SNAPSHOT */
225 0x63, /* VK_INSERT */
226 0xff, /* VK_DELETE */
227 0x6a, /* VK_HELP */
228 -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, /* 0 - 9 */
229 -1, -1, -1, -1, -1, -1, -1,
230 -2, -2, -2, -2, -2, -2, -2, -2, /* A - Z */
231 -2, -2, -2, -2, -2, -2, -2, -2,
232 -2, -2, -2, -2, -2, -2, -2, -2,
233 -2, -2,
234 -1, -1, -1, -1, -1,
235 0xb0, /* VK_NUMPAD0 */
236 0xb1, /* VK_NUMPAD1 */
237 0xb2, /* VK_NUMPAD2 */
238 0xb3, /* VK_NUMPAD3 */
239 0xb4, /* VK_NUMPAD4 */
240 0xb5, /* VK_NUMPAD5 */
241 0xb6, /* VK_NUMPAD6 */
242 0xb7, /* VK_NUMPAD7 */
243 0xb8, /* VK_NUMPAD8 */
244 0xb9, /* VK_NUMPAD9 */
245 0xaa, /* VK_MULTIPLY */
246 0xab, /* VK_ADD */
247 0xac, /* VK_SEPARATOR */
248 0xad, /* VK_SUBTRACT */
249 0xae, /* VK_DECIMAL */
250 0xaf, /* VK_DIVIDE */
251 0xbe, /* VK_F1 */
252 0xbf, /* VK_F2 */
253 0xc0, /* VK_F3 */
254 0xc1, /* VK_F4 */
255 0xc2, /* VK_F5 */
256 0xc3, /* VK_F6 */
257 0xc4, /* VK_F7 */
258 0xc5, /* VK_F8 */
259 0xc6, /* VK_F9 */
260 0xc7, /* VK_F10 */
261 0xc8, /* VK_F11 */
262 0xc9, /* VK_F12 */
263 0xca, /* VK_F13 */
264 0xcb, /* VK_F14 */
265 0xcc, /* VK_F15 */
266 0xcd, /* VK_F16 */
267 0xce, /* VK_F17 */
268 0xcf, /* VK_F18 */
269 0xd0, /* VK_F19 */
270 0xd1, /* VK_F20 */
271 0xd2, /* VK_F21 */
272 0xd3, /* VK_F22 */
273 0xd4, /* VK_F23 */
274 0xd5, /* VK_F24 */
275 -1, -1, -1, -1, -1, -1, -1, -1,
276 0x7f, /* VK_NUMLOCK */
277 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x9f */
278 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xaf */
279 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb9 */
280 -2, /* ; */
281 -2, /* = */
282 -2, /* , */
283 -2, /* \ */
284 -2, /* . */
285 -2, /* / */
286 -2, /* ` */
287 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xcf */
288 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xda */
289 -2, /* [ */
290 -2, /* - */
291 -2, /* ] */
292 -2, /* ' */
293 -1, /* 0xdf */
b02466e8
KH
294 -1, -1, -2, /* VK_OEM_102 */
295 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xef */
6cdfb6e6
RS
296 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xff */
297};
298
299static int
300key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev)
301{
302 int map;
b02466e8 303 static BOOL map_virt_key_init_done;
6cdfb6e6
RS
304
305 /* Skip key-up events. */
306 if (event->bKeyDown == FALSE)
307 return 0;
308
309 if (event->wVirtualKeyCode > 0xff)
310 {
311 printf ("Unknown key code %d\n", event->wVirtualKeyCode);
312 return 0;
313 }
b02466e8
KH
314
315 /* Patch needed for German keyboard. Ulrich Leodolter (1/11/95). */
316 if (! map_virt_key_init_done)
317 {
318 short vk;
319
320 if ((vk = VkKeyScan (0x3c)) >= 0 && vk < 256) map_virt_key[vk] = -2; /* less */
321 if ((vk = VkKeyScan (0x3e)) >= 0 && vk < 256) map_virt_key[vk] = -2; /* greater */
322
323 map_virt_key_init_done = TRUE;
324 }
6cdfb6e6
RS
325
326 /* BUGBUG - Ignores the repeat count
327 It's questionable whether we want to obey the repeat count anyway
328 since keys usually aren't repeated unless key events back up in
329 the queue. If they're backing up then we don't generally want
330 to honor them later since that leads to significant slop in
331 cursor motion when the system is under heavy load. */
332
333 map = map_virt_key[event->wVirtualKeyCode];
334 if (map == -1)
335 {
336 return 0;
337 }
338 else if (map == -2)
339 {
340 /* ASCII */
341 emacs_ev->kind = ascii_keystroke;
b02466e8 342 win32_kbd_patch_key (event);
9e539a3c 343 XSETINT (emacs_ev->code, event->uChar.AsciiChar);
6cdfb6e6
RS
344 }
345 else
346 {
347 /* non-ASCII */
348 emacs_ev->kind = non_ascii_keystroke;
349 /*
350 * make_lispy_event () now requires non-ascii codes to have
351 * the full X keysym values (2nd byte is 0xff). add it on.
352 */
353 map |= 0xff00;
9e539a3c 354 XSETINT (emacs_ev->code, map);
6cdfb6e6 355 }
b02466e8
KH
356 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
357 emacs_ev->modifiers = win32_kbd_mods_to_emacs (event->dwControlKeyState);
6cdfb6e6
RS
358 emacs_ev->timestamp = GetTickCount ();
359 return 1;
360}
361
362/* Mouse position hook. */
363void
b02466e8
KH
364win32_mouse_position (FRAME_PTR *f,
365 int insist,
6cdfb6e6
RS
366 Lisp_Object *bar_window,
367 enum scroll_bar_part *part,
368 Lisp_Object *x,
369 Lisp_Object *y,
370 unsigned long *time)
371{
372 BLOCK_INPUT;
373
b02466e8
KH
374 insist = insist;
375
6cdfb6e6
RS
376 *f = get_frame ();
377 *bar_window = Qnil;
378 *part = 0;
379 mouse_moved = 0;
380
381 *x = movement_pos.X;
382 *y = movement_pos.Y;
383 *time = movement_time;
384
385 UNBLOCK_INPUT;
386}
387
388/* Remember mouse motion and notify emacs. */
389static void
390mouse_moved_to (int x, int y)
391{
392 /* If we're in the same place, ignore it */
393 if (x != movement_pos.X || y != movement_pos.Y)
394 {
395 mouse_moved = 1;
396 movement_pos.X = x;
397 movement_pos.Y = y;
398 movement_time = GetTickCount ();
399 }
400}
401
402/* Consoles return button bits in a strange order:
403 least significant - Leftmost button
404 next - Rightmost button
405 next - Leftmost+1
406 next - Leftmost+2...
407
408 Assume emacs likes three button mice, so
409 Left == 0
410 Middle == 1
411 Right == 2
412 Others increase from there. */
413
414static int emacs_button_translation[NUM_MOUSE_BUTTONS] =
415{
416 0, 2, 1, 3, 4,
417};
418
419static int
420do_mouse_event (MOUSE_EVENT_RECORD *event,
421 struct input_event *emacs_ev)
422{
423 static DWORD button_state = 0;
424 DWORD but_change, mask;
425 int i;
426
427 if (event->dwEventFlags == MOUSE_MOVED)
428 {
429 /* For movement events we just note that the mouse has moved
430 so that emacs will generate drag events. */
431 mouse_moved_to (event->dwMousePosition.X, event->dwMousePosition.Y);
432 return 0;
433 }
434
435 /* It looks like the console code sends us a mouse event with
436 dwButtonState == 0 when a window is activated. Ignore this case. */
437 if (event->dwButtonState == button_state)
438 return 0;
439
440 emacs_ev->kind = mouse_click;
441
442 /* Find out what button has changed state since the last button event. */
443 but_change = button_state ^ event->dwButtonState;
444 mask = 1;
445 for (i = 0; i < NUM_MOUSE_BUTTONS; i++, mask <<= 1)
446 if (but_change & mask)
447 {
9e539a3c 448 XSETINT (emacs_ev->code, emacs_button_translation[i]);
6cdfb6e6
RS
449 break;
450 }
451
452 /* If the changed button is out of emacs' range (highly unlikely)
453 ignore this event. */
454 if (i == NUM_MOUSE_BUTTONS)
455 return 0;
456
457 button_state = event->dwButtonState;
458 emacs_ev->timestamp = GetTickCount ();
b02466e8 459 emacs_ev->modifiers = win32_kbd_mods_to_emacs (event->dwControlKeyState) |
6cdfb6e6
RS
460 ((event->dwButtonState & mask) ? down_modifier : up_modifier);
461
9e539a3c
KH
462 XSETFASTINT (emacs_ev->x, event->dwMousePosition.X);
463 XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y);
b02466e8 464 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
6cdfb6e6
RS
465
466 return 1;
467}
468
469static void
470resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
471{
472 FRAME_PTR f = get_frame ();
473
474 change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1);
475 SET_FRAME_GARBAGED (f);
476}
477
478int
479win32_read_socket (int sd, struct input_event *bufp, int numchars,
480 int waitp, int expected)
481{
482 BOOL no_events = TRUE;
483 int nev, ret = 0, add;
484
485 if (interrupt_input_blocked)
486 {
487 interrupt_input_pending = 1;
488 return -1;
489 }
490
491 interrupt_input_pending = 0;
492 BLOCK_INPUT;
493
494 for (;;)
495 {
496 nev = fill_queue (waitp != 0);
497 if (nev <= 0)
498 {
499 /* If nev == -1, there was some kind of error
500 If nev == 0 then waitp must be zero and no events were available
501 so return. */
502 UNBLOCK_INPUT;
503 return nev;
504 }
505
506 while (nev > 0 && numchars > 0)
507 {
508 switch (queue_ptr->EventType)
509 {
510 case KEY_EVENT:
511 add = key_event (&queue_ptr->Event.KeyEvent, bufp);
512 bufp += add;
513 ret += add;
514 numchars -= add;
515 break;
516
517 case MOUSE_EVENT:
518 add = do_mouse_event (&queue_ptr->Event.MouseEvent, bufp);
519 bufp += add;
520 ret += add;
521 numchars -= add;
522 break;
523
524 case WINDOW_BUFFER_SIZE_EVENT:
525 resize_event (&queue_ptr->Event.WindowBufferSizeEvent);
526 break;
527
528 case MENU_EVENT:
529 case FOCUS_EVENT:
530 /* Internal event types, ignored. */
531 break;
532 }
533
534 queue_ptr++;
535 nev--;
536 }
537
538 if (ret > 0 || expected == 0)
539 break;
540 }
541
542 UNBLOCK_INPUT;
543 return ret;
544}