(rmail-edit-current-message, rmail-cease-edit):
[bpt/emacs.git] / src / w32inevt.c
1 /* Input event support for Emacs on the Microsoft W32 API.
2 Copyright (C) 1992, 1993, 1995 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
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 */
38 extern HANDLE keyboard_handle;
39
40 /* Info for last mouse motion */
41 static COORD movement_pos;
42 static DWORD movement_time;
43
44 /* from keyboard.c */
45 extern void reinvoke_input_signal (void);
46
47 /* from dispnew.c */
48 extern int change_frame_size (FRAME_PTR, int, int, int, int);
49
50 /* from w32fns.c */
51 extern Lisp_Object Vw32_alt_is_meta;
52
53 /* from w32term */
54 extern Lisp_Object Vw32_capslock_is_shiftlock;
55 extern Lisp_Object Vw32_recognize_altgr;
56
57 /* Event queue */
58 #define EVENT_QUEUE_SIZE 50
59 static INPUT_RECORD event_queue[EVENT_QUEUE_SIZE];
60 static INPUT_RECORD *queue_ptr = event_queue, *queue_end = event_queue;
61
62 static int
63 fill_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. */
94 static FRAME_PTR
95 get_frame (void)
96 {
97 return selected_frame;
98 }
99
100 /* Translate console modifiers to emacs modifiers.
101 German keyboard support (Kai Morgan Zeise 2/18/95). */
102 int
103 w32_kbd_mods_to_emacs (DWORD mods, WORD key)
104 {
105 int retval = 0;
106
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))
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))
115 retval = ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier);
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
125 /* Just in case someone wanted the original behaviour, make it
126 optional by setting w32-capslock-is-shiftlock to t. */
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 )
145 {
146 if ( (mods & SHIFT_PRESSED) == SHIFT_PRESSED)
147 retval |= shift_modifier;
148 }
149 else
150 {
151 if (((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) == SHIFT_PRESSED)
152 || ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) == CAPSLOCK_ON))
153 retval |= shift_modifier;
154 }
155
156 return retval;
157 }
158
159 /* The return code indicates key code size. */
160 int
161 w32_kbd_patch_key (KEY_EVENT_RECORD *event)
162 {
163 unsigned int key_code = event->wVirtualKeyCode;
164 unsigned int mods = event->dwControlKeyState;
165 BYTE keystate[256];
166 static BYTE ansi_code[4];
167 static int isdead = 0;
168
169 if (isdead == 2)
170 {
171 event->uChar.AsciiChar = ansi_code[2];
172 isdead = 0;
173 return 1;
174 }
175 if (event->uChar.AsciiChar != 0)
176 return 1;
177
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;
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))
187 {
188 keystate[VK_CONTROL] = 0x80;
189 keystate[VK_LCONTROL] = 0x80;
190 keystate[VK_MENU] = 0x80;
191 keystate[VK_RMENU] = 0x80;
192 }
193
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;
200 }
201
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
211 static int map_virt_key[256] =
212 {
213 #ifdef MULE
214 -3,
215 #else
216 -1,
217 #endif
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 */
302 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x9f */
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, /* ` */
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 */
314 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xda */
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 */
323 };
324
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) */
327 int
328 key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
329 {
330 int map;
331 int key_flag = 0;
332 static BOOL map_virt_key_init_done;
333
334 *isdead = 0;
335
336 /* Skip key-up events. */
337 if (!event->bKeyDown)
338 return 0;
339
340 if (event->wVirtualKeyCode > 0xff)
341 {
342 printf ("Unknown key code %d\n", event->wVirtualKeyCode);
343 return 0;
344 }
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 }
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. */
363
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;
373 key_flag = w32_kbd_patch_key (event); /* 95.7.25 by himi */
374 if (key_flag == 0)
375 return 0;
376 if (key_flag < 0)
377 *isdead = 1;
378 XSETINT (emacs_ev->code, event->uChar.AsciiChar);
379 }
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
397 else
398 {
399 /* non-ASCII */
400 emacs_ev->kind = non_ascii_keystroke;
401 #ifdef HAVE_NTGUI
402 /* use Windows keysym map */
403 XSETINT (emacs_ev->code, event->wVirtualKeyCode);
404 #else
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;
410 XSETINT (emacs_ev->code, map);
411 #endif /* HAVE_NTGUI */
412 }
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
417 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
418 #endif
419 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState,
420 event->wVirtualKeyCode);
421 emacs_ev->timestamp = GetTickCount ();
422 if (key_flag == 2) return -1; /* 95.7.25 by himi */
423 return 1;
424 }
425
426 /* Mouse position hook. */
427 void
428 w32_console_mouse_position (FRAME_PTR *f,
429 #ifndef MULE
430 int insist,
431 #endif
432 Lisp_Object *bar_window,
433 enum scroll_bar_part *part,
434 Lisp_Object *x,
435 Lisp_Object *y,
436 unsigned long *time)
437 {
438 BLOCK_INPUT;
439
440 #ifndef MULE
441 insist = insist;
442 #endif
443
444 *f = get_frame ();
445 *bar_window = Qnil;
446 *part = 0;
447 selected_frame->mouse_moved = 0;
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. */
457 static void
458 mouse_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 {
463 selected_frame->mouse_moved = 1;
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
482 static int emacs_button_translation[NUM_MOUSE_BUTTONS] =
483 {
484 0, 2, 1, 3, 4,
485 };
486
487 static int
488 do_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 {
516 XSETINT (emacs_ev->code, emacs_button_translation[i]);
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 ();
527 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, 0) |
528 ((event->dwButtonState & mask) ? down_modifier : up_modifier);
529
530 XSETFASTINT (emacs_ev->x, event->dwMousePosition.X);
531 XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y);
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
536 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
537 #endif
538
539 return 1;
540 }
541
542 static void
543 resize_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
551 int
552 w32_console_read_socket (int sd, struct input_event *bufp, int numchars,
553 int expected)
554 {
555 BOOL no_events = TRUE;
556 int nev, ret = 0, add;
557 int isdead;
558
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 {
570 nev = fill_queue (0);
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:
585 add = key_event (&queue_ptr->Event.KeyEvent, bufp, &isdead);
586 if (add == -1) /* 95.7.25 by himi */
587 {
588 queue_ptr--;
589 add = 1;
590 }
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 }