More changes for itcl.
[emacs.git] / src / w32inevt.c
blob53876cb6ee0c1ab2ef5d8cdce7beead84570aa6b
1 /* Input event support for Windows NT port of GNU Emacs.
2 Copyright (C) 1992, 1993, 1995 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any later
9 version.
11 GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 more details.
16 You should have received a copy of the GNU General Public License along
17 with GNU Emacs; see the file COPYING. If not, write to the Free Software
18 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20 Drew Bliss 01-Oct-93
21 Adapted from ntkbd.c by Tim Fleehart
25 #include "config.h"
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <windows.h>
31 #include "lisp.h"
32 #include "frame.h"
33 #include "blockinput.h"
34 #include "termhooks.h"
36 /* stdin, from ntterm */
37 extern HANDLE keyboard_handle;
39 /* Indicate mouse motion, from keyboard.c */
40 extern int mouse_moved;
42 /* Info for last mouse motion */
43 static COORD movement_pos;
44 static DWORD movement_time;
46 /* from keyboard.c */
47 extern void reinvoke_input_signal (void);
49 /* from dispnew.c */
50 extern int change_frame_size (FRAME_PTR, int, int, int, int);
52 /* Event queue */
53 #define EVENT_QUEUE_SIZE 50
54 static INPUT_RECORD event_queue[EVENT_QUEUE_SIZE];
55 static INPUT_RECORD *queue_ptr = event_queue, *queue_end = event_queue;
57 static int
58 fill_queue (BOOL block)
60 BOOL rc;
61 DWORD events_waiting;
63 if (queue_ptr < queue_end)
64 return queue_end-queue_ptr;
66 if (!block)
68 /* Check to see if there are some events to read before we try
69 because we can't block. */
70 if (!GetNumberOfConsoleInputEvents (keyboard_handle, &events_waiting))
71 return -1;
72 if (events_waiting == 0)
73 return 0;
76 rc = ReadConsoleInput (keyboard_handle, event_queue, EVENT_QUEUE_SIZE,
77 &events_waiting);
78 if (!rc)
79 return -1;
80 queue_ptr = event_queue;
81 queue_end = event_queue + events_waiting;
82 return (int) events_waiting;
85 /* In a generic, multi-frame world this should take a console handle
86 and return the frame for it
88 Right now, there's only one frame so return it. */
89 static FRAME_PTR
90 get_frame (void)
92 return selected_frame;
95 /* Translate console modifiers to emacs modifiers.
96 German keyboard support (Kai Morgan Zeise 2/18/95). */
97 static int
98 win32_kbd_mods_to_emacs (DWORD mods)
100 int retval = 0;
102 /* If AltGr has been pressed, remove it. */
103 if ((mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
104 == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
105 mods &= ~ (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED);
107 if (mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
108 retval = meta_modifier;
110 if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
112 retval |= ctrl_modifier;
113 if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
114 == (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
115 retval |= meta_modifier;
118 if (((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) == SHIFT_PRESSED)
119 || ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) == CAPSLOCK_ON))
120 retval |= shift_modifier;
122 return retval;
125 /* Patch up NT keyboard events when info is missing that should be there,
126 assuming that map_virt_key says that the key is a valid ASCII char. */
127 static char win32_number_shift_map[] = {
128 ')', '!', '@', '#', '$', '%', '^', '&', '*', '('
131 #define WIN32_KEY_SHIFTED(mods, no, yes) \
132 ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) ? yes : no)
134 static void
135 win32_kbd_patch_key (KEY_EVENT_RECORD *event)
137 unsigned int key_code = event->wVirtualKeyCode;
138 unsigned int mods = event->dwControlKeyState;
139 int mapped_punct = 0;
141 /* map_virt_key says its a valid key, but the uChar.AsciiChar field
142 is empty. patch up the uChar.AsciiChar field using wVirtualKeyCode. */
143 if (event->uChar.AsciiChar == 0
144 && ((key_code >= '0' && key_code <= '9')
145 || (key_code >= 'A' && key_code <= 'Z')
146 || (key_code >= 0xBA && key_code <= 0xC0)
147 || (key_code >= 0xDB && key_code <= 0xDE)
148 )) {
149 if (key_code >= '0' && key_code <= '9') {
150 event->uChar.AsciiChar =
151 WIN32_KEY_SHIFTED (mods, key_code,
152 win32_number_shift_map[key_code - '0']);
153 return;
155 switch (key_code) {
156 case 0xBA: mapped_punct = WIN32_KEY_SHIFTED (mods, ';', ':'); break;
157 case 0xBB: mapped_punct = WIN32_KEY_SHIFTED (mods, '=', '+'); break;
158 case 0xBC: mapped_punct = WIN32_KEY_SHIFTED (mods, ',', '<'); break;
159 case 0xBD: mapped_punct = WIN32_KEY_SHIFTED (mods, '-', '_'); break;
160 case 0xBE: mapped_punct = WIN32_KEY_SHIFTED (mods, '.', '>'); break;
161 case 0xBF: mapped_punct = WIN32_KEY_SHIFTED (mods, '/', '?'); break;
162 case 0xC0: mapped_punct = WIN32_KEY_SHIFTED (mods, '`', '~'); break;
163 case 0xDB: mapped_punct = WIN32_KEY_SHIFTED (mods, '[', '{'); break;
164 case 0xDC: mapped_punct = WIN32_KEY_SHIFTED (mods, '\\', '|'); break;
165 case 0xDD: mapped_punct = WIN32_KEY_SHIFTED (mods, ']', '}'); break;
166 case 0xDE: mapped_punct = WIN32_KEY_SHIFTED (mods, '\'', '"'); break;
167 default:
168 mapped_punct = 0;
169 break;
171 if (mapped_punct) {
172 event->uChar.AsciiChar = mapped_punct;
173 return;
175 /* otherwise, it's a letter. */
176 event->uChar.AsciiChar = WIN32_KEY_SHIFTED (mods, key_code - 'A' + 'a',
177 key_code);
181 /* Map virtual key codes into:
182 -1 - Ignore this key
183 -2 - ASCII char
184 Other - Map non-ASCII keys into X keysyms so that they are looked up
185 correctly in keyboard.c
187 Return, escape and tab are mapped to ASCII rather than coming back
188 as non-ASCII to be more compatible with old-style keyboard support. */
190 static int map_virt_key[256] =
193 -1, /* VK_LBUTTON */
194 -1, /* VK_RBUTTON */
195 0x69, /* VK_CANCEL */
196 -1, /* VK_MBUTTON */
197 -1, -1, -1,
198 8, /* VK_BACK */
199 -2, /* VK_TAB */
200 -1, -1,
201 11, /* VK_CLEAR */
202 -2, /* VK_RETURN */
203 -1, -1,
204 -1, /* VK_SHIFT */
205 -1, /* VK_CONTROL */
206 -1, /* VK_MENU */
207 0x13, /* VK_PAUSE */
208 -1, /* VK_CAPITAL */
209 -1, -1, -1, -1, -1, -1,
210 -2, /* VK_ESCAPE */
211 -1, -1, -1, -1,
212 -2, /* VK_SPACE */
213 0x55, /* VK_PRIOR */
214 0x56, /* VK_NEXT */
215 0x57, /* VK_END */
216 0x50, /* VK_HOME */
217 0x51, /* VK_LEFT */
218 0x52, /* VK_UP */
219 0x53, /* VK_RIGHT */
220 0x54, /* VK_DOWN */
221 0x60, /* VK_SELECT */
222 0x61, /* VK_PRINT */
223 0x62, /* VK_EXECUTE */
224 -1, /* VK_SNAPSHOT */
225 0x63, /* VK_INSERT */
226 0xff, /* VK_DELETE */
227 0x6a, /* VK_HELP */
228 -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, /* 0 - 9 */
229 -1, -1, -1, -1, -1, -1, -1,
230 -2, -2, -2, -2, -2, -2, -2, -2, /* A - Z */
231 -2, -2, -2, -2, -2, -2, -2, -2,
232 -2, -2, -2, -2, -2, -2, -2, -2,
233 -2, -2,
234 -1, -1, -1, -1, -1,
235 0xb0, /* VK_NUMPAD0 */
236 0xb1, /* VK_NUMPAD1 */
237 0xb2, /* VK_NUMPAD2 */
238 0xb3, /* VK_NUMPAD3 */
239 0xb4, /* VK_NUMPAD4 */
240 0xb5, /* VK_NUMPAD5 */
241 0xb6, /* VK_NUMPAD6 */
242 0xb7, /* VK_NUMPAD7 */
243 0xb8, /* VK_NUMPAD8 */
244 0xb9, /* VK_NUMPAD9 */
245 0xaa, /* VK_MULTIPLY */
246 0xab, /* VK_ADD */
247 0xac, /* VK_SEPARATOR */
248 0xad, /* VK_SUBTRACT */
249 0xae, /* VK_DECIMAL */
250 0xaf, /* VK_DIVIDE */
251 0xbe, /* VK_F1 */
252 0xbf, /* VK_F2 */
253 0xc0, /* VK_F3 */
254 0xc1, /* VK_F4 */
255 0xc2, /* VK_F5 */
256 0xc3, /* VK_F6 */
257 0xc4, /* VK_F7 */
258 0xc5, /* VK_F8 */
259 0xc6, /* VK_F9 */
260 0xc7, /* VK_F10 */
261 0xc8, /* VK_F11 */
262 0xc9, /* VK_F12 */
263 0xca, /* VK_F13 */
264 0xcb, /* VK_F14 */
265 0xcc, /* VK_F15 */
266 0xcd, /* VK_F16 */
267 0xce, /* VK_F17 */
268 0xcf, /* VK_F18 */
269 0xd0, /* VK_F19 */
270 0xd1, /* VK_F20 */
271 0xd2, /* VK_F21 */
272 0xd3, /* VK_F22 */
273 0xd4, /* VK_F23 */
274 0xd5, /* VK_F24 */
275 -1, -1, -1, -1, -1, -1, -1, -1,
276 0x7f, /* VK_NUMLOCK */
277 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x9f */
278 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xaf */
279 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb9 */
280 -2, /* ; */
281 -2, /* = */
282 -2, /* , */
283 -2, /* \ */
284 -2, /* . */
285 -2, /* / */
286 -2, /* ` */
287 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xcf */
288 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xda */
289 -2, -2, -2, -2, -2, /* 0xdf */
290 -2, -2, -2, -2, -2,
291 -1, /* 0xe5 */
292 -2, /* oxe6 */
293 -1, -1, /* 0xe8 */
294 -2, -2, -2, -2, -2, -2, -2, /* 0xef */
295 -2, -2, -2, -2, -2, -2,
296 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xff */
299 static int
300 key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev)
302 int map;
303 static BOOL map_virt_key_init_done;
305 /* Skip key-up events. */
306 if (event->bKeyDown == FALSE)
307 return 0;
309 if (event->wVirtualKeyCode > 0xff)
311 printf ("Unknown key code %d\n", event->wVirtualKeyCode);
312 return 0;
315 /* Patch needed for German keyboard. Ulrich Leodolter (1/11/95). */
316 if (! map_virt_key_init_done)
318 short vk;
320 if ((vk = VkKeyScan (0x3c)) >= 0 && vk < 256) map_virt_key[vk] = -2; /* less */
321 if ((vk = VkKeyScan (0x3e)) >= 0 && vk < 256) map_virt_key[vk] = -2; /* greater */
323 map_virt_key_init_done = TRUE;
326 /* BUGBUG - Ignores the repeat count
327 It's questionable whether we want to obey the repeat count anyway
328 since keys usually aren't repeated unless key events back up in
329 the queue. If they're backing up then we don't generally want
330 to honor them later since that leads to significant slop in
331 cursor motion when the system is under heavy load. */
333 map = map_virt_key[event->wVirtualKeyCode];
334 if (map == -1)
336 return 0;
338 else if (map == -2)
340 /* ASCII */
341 emacs_ev->kind = ascii_keystroke;
342 win32_kbd_patch_key (event);
343 XSETINT (emacs_ev->code, event->uChar.AsciiChar);
345 else
347 /* non-ASCII */
348 emacs_ev->kind = non_ascii_keystroke;
350 * make_lispy_event () now requires non-ascii codes to have
351 * the full X keysym values (2nd byte is 0xff). add it on.
353 map |= 0xff00;
354 XSETINT (emacs_ev->code, map);
356 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
357 emacs_ev->modifiers = win32_kbd_mods_to_emacs (event->dwControlKeyState);
358 emacs_ev->timestamp = GetTickCount ();
359 return 1;
362 /* Mouse position hook. */
363 void
364 win32_mouse_position (FRAME_PTR *f,
365 int insist,
366 Lisp_Object *bar_window,
367 enum scroll_bar_part *part,
368 Lisp_Object *x,
369 Lisp_Object *y,
370 unsigned long *time)
372 BLOCK_INPUT;
374 insist = insist;
376 *f = get_frame ();
377 *bar_window = Qnil;
378 *part = 0;
379 mouse_moved = 0;
381 *x = movement_pos.X;
382 *y = movement_pos.Y;
383 *time = movement_time;
385 UNBLOCK_INPUT;
388 /* Remember mouse motion and notify emacs. */
389 static void
390 mouse_moved_to (int x, int y)
392 /* If we're in the same place, ignore it */
393 if (x != movement_pos.X || y != movement_pos.Y)
395 mouse_moved = 1;
396 movement_pos.X = x;
397 movement_pos.Y = y;
398 movement_time = GetTickCount ();
402 /* Consoles return button bits in a strange order:
403 least significant - Leftmost button
404 next - Rightmost button
405 next - Leftmost+1
406 next - Leftmost+2...
408 Assume emacs likes three button mice, so
409 Left == 0
410 Middle == 1
411 Right == 2
412 Others increase from there. */
414 static int emacs_button_translation[NUM_MOUSE_BUTTONS] =
416 0, 2, 1, 3, 4,
419 static int
420 do_mouse_event (MOUSE_EVENT_RECORD *event,
421 struct input_event *emacs_ev)
423 static DWORD button_state = 0;
424 DWORD but_change, mask;
425 int i;
427 if (event->dwEventFlags == MOUSE_MOVED)
429 /* For movement events we just note that the mouse has moved
430 so that emacs will generate drag events. */
431 mouse_moved_to (event->dwMousePosition.X, event->dwMousePosition.Y);
432 return 0;
435 /* It looks like the console code sends us a mouse event with
436 dwButtonState == 0 when a window is activated. Ignore this case. */
437 if (event->dwButtonState == button_state)
438 return 0;
440 emacs_ev->kind = mouse_click;
442 /* Find out what button has changed state since the last button event. */
443 but_change = button_state ^ event->dwButtonState;
444 mask = 1;
445 for (i = 0; i < NUM_MOUSE_BUTTONS; i++, mask <<= 1)
446 if (but_change & mask)
448 XSETINT (emacs_ev->code, emacs_button_translation[i]);
449 break;
452 /* If the changed button is out of emacs' range (highly unlikely)
453 ignore this event. */
454 if (i == NUM_MOUSE_BUTTONS)
455 return 0;
457 button_state = event->dwButtonState;
458 emacs_ev->timestamp = GetTickCount ();
459 emacs_ev->modifiers = win32_kbd_mods_to_emacs (event->dwControlKeyState) |
460 ((event->dwButtonState & mask) ? down_modifier : up_modifier);
462 XSETFASTINT (emacs_ev->x, event->dwMousePosition.X);
463 XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y);
464 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
466 return 1;
469 static void
470 resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
472 FRAME_PTR f = get_frame ();
474 change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1);
475 SET_FRAME_GARBAGED (f);
478 int
479 win32_read_socket (int sd, struct input_event *bufp, int numchars,
480 int waitp, int expected)
482 BOOL no_events = TRUE;
483 int nev, ret = 0, add;
485 if (interrupt_input_blocked)
487 interrupt_input_pending = 1;
488 return -1;
491 interrupt_input_pending = 0;
492 BLOCK_INPUT;
494 for (;;)
496 nev = fill_queue (waitp != 0);
497 if (nev <= 0)
499 /* If nev == -1, there was some kind of error
500 If nev == 0 then waitp must be zero and no events were available
501 so return. */
502 UNBLOCK_INPUT;
503 return nev;
506 while (nev > 0 && numchars > 0)
508 switch (queue_ptr->EventType)
510 case KEY_EVENT:
511 add = key_event (&queue_ptr->Event.KeyEvent, bufp);
512 bufp += add;
513 ret += add;
514 numchars -= add;
515 break;
517 case MOUSE_EVENT:
518 add = do_mouse_event (&queue_ptr->Event.MouseEvent, bufp);
519 bufp += add;
520 ret += add;
521 numchars -= add;
522 break;
524 case WINDOW_BUFFER_SIZE_EVENT:
525 resize_event (&queue_ptr->Event.WindowBufferSizeEvent);
526 break;
528 case MENU_EVENT:
529 case FOCUS_EVENT:
530 /* Internal event types, ignored. */
531 break;
534 queue_ptr++;
535 nev--;
538 if (ret > 0 || expected == 0)
539 break;
542 UNBLOCK_INPUT;
543 return ret;