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