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
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
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.
21 Adapted from ntkbd.c by Tim Fleehart
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
;
47 extern void reinvoke_input_signal (void);
50 extern int change_frame_size (FRAME_PTR
, int, int, int, int);
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
;
58 fill_queue (BOOL block
)
63 if (queue_ptr
< queue_end
)
64 return queue_end
-queue_ptr
;
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
))
72 if (events_waiting
== 0)
76 rc
= ReadConsoleInput (keyboard_handle
, event_queue
, EVENT_QUEUE_SIZE
,
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. */
92 return selected_frame
;
95 /* Translate console modifiers to emacs modifiers.
96 German keyboard support (Kai Morgan Zeise 2/18/95). */
98 win32_kbd_mods_to_emacs (DWORD mods
)
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
;
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)
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)
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']);
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;
172 event
->uChar
.AsciiChar
= mapped_punct
;
175 /* otherwise, it's a letter. */
176 event
->uChar
.AsciiChar
= WIN32_KEY_SHIFTED (mods
, key_code
- 'A' + 'a',
181 /* Map virtual key codes into:
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] =
195 0x69, /* VK_CANCEL */
209 -1, -1, -1, -1, -1, -1,
221 0x60, /* VK_SELECT */
223 0x62, /* VK_EXECUTE */
224 -1, /* VK_SNAPSHOT */
225 0x63, /* VK_INSERT */
226 0xff, /* VK_DELETE */
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,
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 */
247 0xac, /* VK_SEPARATOR */
248 0xad, /* VK_SUBTRACT */
249 0xae, /* VK_DECIMAL */
250 0xaf, /* VK_DIVIDE */
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 */
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 */
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 */
300 key_event (KEY_EVENT_RECORD
*event
, struct input_event
*emacs_ev
)
303 static BOOL map_virt_key_init_done
;
305 /* Skip key-up events. */
306 if (event
->bKeyDown
== FALSE
)
309 if (event
->wVirtualKeyCode
> 0xff)
311 printf ("Unknown key code %d\n", event
->wVirtualKeyCode
);
315 /* Patch needed for German keyboard. Ulrich Leodolter (1/11/95). */
316 if (! map_virt_key_init_done
)
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
];
341 emacs_ev
->kind
= ascii_keystroke
;
342 win32_kbd_patch_key (event
);
343 XSETINT (emacs_ev
->code
, event
->uChar
.AsciiChar
);
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.
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 ();
362 /* Mouse position hook. */
364 win32_mouse_position (FRAME_PTR
*f
,
366 Lisp_Object
*bar_window
,
367 enum scroll_bar_part
*part
,
383 *time
= movement_time
;
388 /* Remember mouse motion and notify emacs. */
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
)
398 movement_time
= GetTickCount ();
402 /* Consoles return button bits in a strange order:
403 least significant - Leftmost button
404 next - Rightmost button
408 Assume emacs likes three button mice, so
412 Others increase from there. */
414 static int emacs_button_translation
[NUM_MOUSE_BUTTONS
] =
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
;
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
);
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
)
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
;
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
]);
452 /* If the changed button is out of emacs' range (highly unlikely)
453 ignore this event. */
454 if (i
== NUM_MOUSE_BUTTONS
)
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 ());
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
);
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;
491 interrupt_input_pending
= 0;
496 nev
= fill_queue (waitp
!= 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
506 while (nev
> 0 && numchars
> 0)
508 switch (queue_ptr
->EventType
)
511 add
= key_event (&queue_ptr
->Event
.KeyEvent
, bufp
);
518 add
= do_mouse_event (&queue_ptr
->Event
.MouseEvent
, bufp
);
524 case WINDOW_BUFFER_SIZE_EVENT
:
525 resize_event (&queue_ptr
->Event
.WindowBufferSizeEvent
);
530 /* Internal event types, ignored. */
538 if (ret
> 0 || expected
== 0)