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