Include lisp.h.
[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 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
50/* Event queue */
51#define EVENT_QUEUE_SIZE 50
52static INPUT_RECORD event_queue[EVENT_QUEUE_SIZE];
53static INPUT_RECORD *queue_ptr = event_queue, *queue_end = event_queue;
54
55static int
56fill_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. */
87static FRAME_PTR
88get_frame (void)
89{
90 return selected_frame;
91}
92
b02466e8
KH
93/* Translate console modifiers to emacs modifiers.
94 German keyboard support (Kai Morgan Zeise 2/18/95). */
c0386d7e 95int
b02466e8 96win32_kbd_mods_to_emacs (DWORD mods)
6cdfb6e6 97{
b02466e8
KH
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
daf38066 123/* The return code indicates key code size. */
c0386d7e 124int
b02466e8
KH
125win32_kbd_patch_key (KEY_EVENT_RECORD *event)
126{
127 unsigned int key_code = event->wVirtualKeyCode;
128 unsigned int mods = event->dwControlKeyState;
daf38066
GV
129 BYTE keystate[256];
130 static BYTE ansi_code[4];
131 static int isdead;
132
133 if (isdead == 2)
134 {
135 event->uChar.AsciiChar = ansi_code[2];
136 isdead = 0;
137 return 1;
b02466e8 138 }
daf38066
GV
139 if (event->uChar.AsciiChar != 0)
140 return 1;
c0386d7e 141
daf38066
GV
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;
c0386d7e
GV
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
daf38066
GV
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;
6cdfb6e6 161}
daf38066 162
6cdfb6e6
RS
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
172static int map_virt_key[256] =
173{
daf38066
GV
174#ifdef MULE
175 -3,
176#else
6cdfb6e6 177 -1,
daf38066 178#endif
6cdfb6e6
RS
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 */
4ba58dd4 263 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x9f */
6cdfb6e6
RS
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, /* ` */
4ba58dd4 273 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xcf */
6cdfb6e6 274 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xda */
4ba58dd4
RS
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 */
6cdfb6e6
RS
283};
284
daf38066
GV
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) */
c0386d7e 287int
6cdfb6e6
RS
288key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev)
289{
290 int map;
daf38066 291 int key_flag = 0;
b02466e8 292 static BOOL map_virt_key_init_done;
6cdfb6e6
RS
293
294 /* Skip key-up events. */
295 if (event->bKeyDown == FALSE)
296 return 0;
297
298 if (event->wVirtualKeyCode > 0xff)
299 {
300 printf ("Unknown key code %d\n", event->wVirtualKeyCode);
301 return 0;
302 }
b02466e8
KH
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 }
6cdfb6e6
RS
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;
daf38066
GV
331 key_flag = win32_kbd_patch_key (event); /* 95.7.25 by himi */
332 if (key_flag == 0)
333 return 0;
9e539a3c 334 XSETINT (emacs_ev->code, event->uChar.AsciiChar);
6cdfb6e6 335 }
daf38066
GV
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
6cdfb6e6
RS
353 else
354 {
355 /* non-ASCII */
356 emacs_ev->kind = non_ascii_keystroke;
357 /*
358 * make_lispy_event () now requires non-ascii codes to have
359 * the full X keysym values (2nd byte is 0xff). add it on.
360 */
c0386d7e 361#ifndef HAVE_NTGUI
6cdfb6e6 362 map |= 0xff00;
c0386d7e 363#endif
9e539a3c 364 XSETINT (emacs_ev->code, map);
6cdfb6e6 365 }
daf38066
GV
366/* for Mule 2.2 (Based on Emacs 19.28) */
367#ifdef MULE
368 XSET (emacs_ev->frame_or_window, Lisp_Frame, get_frame ());
369#else
b02466e8 370 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
daf38066 371#endif
b02466e8 372 emacs_ev->modifiers = win32_kbd_mods_to_emacs (event->dwControlKeyState);
6cdfb6e6 373 emacs_ev->timestamp = GetTickCount ();
daf38066 374 if (key_flag == 2) return -1; /* 95.7.25 by himi */
6cdfb6e6
RS
375 return 1;
376}
377
378/* Mouse position hook. */
379void
b02466e8 380win32_mouse_position (FRAME_PTR *f,
daf38066 381#ifndef MULE
b02466e8 382 int insist,
daf38066 383#endif
6cdfb6e6
RS
384 Lisp_Object *bar_window,
385 enum scroll_bar_part *part,
386 Lisp_Object *x,
387 Lisp_Object *y,
388 unsigned long *time)
389{
390 BLOCK_INPUT;
391
daf38066 392#ifndef MULE
b02466e8 393 insist = insist;
daf38066 394#endif
b02466e8 395
6cdfb6e6
RS
396 *f = get_frame ();
397 *bar_window = Qnil;
398 *part = 0;
0e7078f5 399 selected_frame->mouse_moved = 0;
6cdfb6e6
RS
400
401 *x = movement_pos.X;
402 *y = movement_pos.Y;
403 *time = movement_time;
404
405 UNBLOCK_INPUT;
406}
407
408/* Remember mouse motion and notify emacs. */
409static void
410mouse_moved_to (int x, int y)
411{
412 /* If we're in the same place, ignore it */
413 if (x != movement_pos.X || y != movement_pos.Y)
414 {
0e7078f5 415 selected_frame->mouse_moved = 1;
6cdfb6e6
RS
416 movement_pos.X = x;
417 movement_pos.Y = y;
418 movement_time = GetTickCount ();
419 }
420}
421
422/* Consoles return button bits in a strange order:
423 least significant - Leftmost button
424 next - Rightmost button
425 next - Leftmost+1
426 next - Leftmost+2...
427
428 Assume emacs likes three button mice, so
429 Left == 0
430 Middle == 1
431 Right == 2
432 Others increase from there. */
433
434static int emacs_button_translation[NUM_MOUSE_BUTTONS] =
435{
436 0, 2, 1, 3, 4,
437};
438
439static int
440do_mouse_event (MOUSE_EVENT_RECORD *event,
441 struct input_event *emacs_ev)
442{
443 static DWORD button_state = 0;
444 DWORD but_change, mask;
445 int i;
446
447 if (event->dwEventFlags == MOUSE_MOVED)
448 {
449 /* For movement events we just note that the mouse has moved
450 so that emacs will generate drag events. */
451 mouse_moved_to (event->dwMousePosition.X, event->dwMousePosition.Y);
452 return 0;
453 }
454
455 /* It looks like the console code sends us a mouse event with
456 dwButtonState == 0 when a window is activated. Ignore this case. */
457 if (event->dwButtonState == button_state)
458 return 0;
459
460 emacs_ev->kind = mouse_click;
461
462 /* Find out what button has changed state since the last button event. */
463 but_change = button_state ^ event->dwButtonState;
464 mask = 1;
465 for (i = 0; i < NUM_MOUSE_BUTTONS; i++, mask <<= 1)
466 if (but_change & mask)
467 {
9e539a3c 468 XSETINT (emacs_ev->code, emacs_button_translation[i]);
6cdfb6e6
RS
469 break;
470 }
471
472 /* If the changed button is out of emacs' range (highly unlikely)
473 ignore this event. */
474 if (i == NUM_MOUSE_BUTTONS)
475 return 0;
476
477 button_state = event->dwButtonState;
478 emacs_ev->timestamp = GetTickCount ();
b02466e8 479 emacs_ev->modifiers = win32_kbd_mods_to_emacs (event->dwControlKeyState) |
6cdfb6e6
RS
480 ((event->dwButtonState & mask) ? down_modifier : up_modifier);
481
9e539a3c
KH
482 XSETFASTINT (emacs_ev->x, event->dwMousePosition.X);
483 XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y);
daf38066
GV
484/* for Mule 2.2 (Based on Emacs 19.28 */
485#ifdef MULE
486 XSET (emacs_ev->frame_or_window, Lisp_Frame, get_frame ());
487#else
b02466e8 488 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
daf38066 489#endif
6cdfb6e6
RS
490
491 return 1;
492}
493
494static void
495resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
496{
497 FRAME_PTR f = get_frame ();
498
499 change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1);
500 SET_FRAME_GARBAGED (f);
501}
502
503int
504win32_read_socket (int sd, struct input_event *bufp, int numchars,
505 int waitp, int expected)
506{
507 BOOL no_events = TRUE;
508 int nev, ret = 0, add;
509
510 if (interrupt_input_blocked)
511 {
512 interrupt_input_pending = 1;
513 return -1;
514 }
515
516 interrupt_input_pending = 0;
517 BLOCK_INPUT;
518
519 for (;;)
520 {
521 nev = fill_queue (waitp != 0);
522 if (nev <= 0)
523 {
524 /* If nev == -1, there was some kind of error
525 If nev == 0 then waitp must be zero and no events were available
526 so return. */
527 UNBLOCK_INPUT;
528 return nev;
529 }
530
531 while (nev > 0 && numchars > 0)
532 {
533 switch (queue_ptr->EventType)
534 {
535 case KEY_EVENT:
536 add = key_event (&queue_ptr->Event.KeyEvent, bufp);
daf38066
GV
537 if (add == -1) /* 95.7.25 by himi */
538 {
539 queue_ptr--;
540 add = 1;
541 }
6cdfb6e6
RS
542 bufp += add;
543 ret += add;
544 numchars -= add;
545 break;
546
547 case MOUSE_EVENT:
548 add = do_mouse_event (&queue_ptr->Event.MouseEvent, bufp);
549 bufp += add;
550 ret += add;
551 numchars -= add;
552 break;
553
554 case WINDOW_BUFFER_SIZE_EVENT:
555 resize_event (&queue_ptr->Event.WindowBufferSizeEvent);
556 break;
557
558 case MENU_EVENT:
559 case FOCUS_EVENT:
560 /* Internal event types, ignored. */
561 break;
562 }
563
564 queue_ptr++;
565 nev--;
566 }
567
568 if (ret > 0 || expected == 0)
569 break;
570 }
571
572 UNBLOCK_INPUT;
573 return ret;
574}