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