1 /* Input event support for Emacs on the Microsoft W32 API.
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
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)
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.
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.
22 Adapted from ntkbd.c by Tim Fleehart
34 #include "blockinput.h"
35 #include "termhooks.h"
37 /* stdin, from ntterm */
38 extern HANDLE keyboard_handle
;
40 /* Info for last mouse motion */
41 static COORD movement_pos
;
42 static DWORD movement_time
;
45 extern void reinvoke_input_signal (void);
48 extern int change_frame_size (FRAME_PTR
, int, int, int, int);
51 extern Lisp_Object Vw32_alt_is_meta
;
54 extern Lisp_Object Vw32_capslock_is_shiftlock
;
55 extern Lisp_Object Vw32_recognize_altgr
;
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
;
63 fill_queue (BOOL block
)
68 if (queue_ptr
< queue_end
)
69 return queue_end
-queue_ptr
;
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
))
77 if (events_waiting
== 0)
81 rc
= ReadConsoleInput (keyboard_handle
, event_queue
, EVENT_QUEUE_SIZE
,
85 queue_ptr
= event_queue
;
86 queue_end
= event_queue
+ events_waiting
;
87 return (int) events_waiting
;
90 /* In a generic, multi-frame world this should take a console handle
91 and return the frame for it
93 Right now, there's only one frame so return it. */
97 return selected_frame
;
100 /* Translate console modifiers to emacs modifiers.
101 German keyboard support (Kai Morgan Zeise 2/18/95). */
103 w32_kbd_mods_to_emacs (DWORD mods
, WORD key
)
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
);
114 if (mods
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
115 retval
= ((NILP (Vw32_alt_is_meta
)) ? alt_modifier
: meta_modifier
);
117 if (mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
119 retval
|= ctrl_modifier
;
120 if ((mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
121 == (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
122 retval
|= meta_modifier
;
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
) &&
129 ( (key
== VK_BACK
) ||
132 (key
== VK_RETURN
) ||
133 (key
== VK_ESCAPE
) ||
134 ( (key
>= VK_SPACE
) && (key
<= VK_HELP
)) ||
135 ( (key
>= VK_NUMPAD0
) && (key
<= VK_F24
))
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') )
146 if ( (mods
& SHIFT_PRESSED
) == SHIFT_PRESSED
)
147 retval
|= shift_modifier
;
151 if (((mods
& (SHIFT_PRESSED
| CAPSLOCK_ON
)) == SHIFT_PRESSED
)
152 || ((mods
& (SHIFT_PRESSED
| CAPSLOCK_ON
)) == CAPSLOCK_ON
))
153 retval
|= shift_modifier
;
159 /* The return code indicates key code size. */
161 w32_kbd_patch_key (KEY_EVENT_RECORD
*event
)
163 unsigned int key_code
= event
->wVirtualKeyCode
;
164 unsigned int mods
= event
->dwControlKeyState
;
166 static BYTE ansi_code
[4];
167 static int isdead
= 0;
171 event
->uChar
.AsciiChar
= ansi_code
[2];
175 if (event
->uChar
.AsciiChar
!= 0)
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
))
188 keystate
[VK_CONTROL
] = 0x80;
189 keystate
[VK_LCONTROL
] = 0x80;
190 keystate
[VK_MENU
] = 0x80;
191 keystate
[VK_RMENU
] = 0x80;
194 isdead
= ToAscii (event
->wVirtualKeyCode
, event
->wVirtualScanCode
,
195 keystate
, (LPWORD
) ansi_code
, 0);
198 event
->uChar
.AsciiChar
= ansi_code
[0];
202 /* Map virtual key codes into:
205 Other - Map non-ASCII keys into X keysyms so that they are looked up
206 correctly in keyboard.c
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. */
211 static int map_virt_key
[256] =
220 0x69, /* VK_CANCEL */
234 -1, -1, -1, -1, -1, -1,
246 0x60, /* VK_SELECT */
248 0x62, /* VK_EXECUTE */
249 -1, /* VK_SNAPSHOT */
250 0x63, /* VK_INSERT */
251 0xff, /* VK_DELETE */
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,
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 */
272 0xac, /* VK_SEPARATOR */
273 0xad, /* VK_SUBTRACT */
274 0xae, /* VK_DECIMAL */
275 0xaf, /* VK_DIVIDE */
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 */
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 */
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 */
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) */
328 key_event (KEY_EVENT_RECORD
*event
, struct input_event
*emacs_ev
, int *isdead
)
332 static BOOL map_virt_key_init_done
;
336 /* Skip key-up events. */
337 if (!event
->bKeyDown
)
340 if (event
->wVirtualKeyCode
> 0xff)
342 printf ("Unknown key code %d\n", event
->wVirtualKeyCode
);
346 /* Patch needed for German keyboard. Ulrich Leodolter (1/11/95). */
347 if (! map_virt_key_init_done
)
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 */
354 map_virt_key_init_done
= TRUE
;
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. */
364 map
= map_virt_key
[event
->wVirtualKeyCode
];
372 emacs_ev
->kind
= ascii_keystroke
;
373 key_flag
= w32_kbd_patch_key (event
); /* 95.7.25 by himi */
378 XSETINT (emacs_ev
->code
, event
->uChar
.AsciiChar
);
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
))
390 emacs_ev
->kind
= ascii_keystroke
;
391 XSETINT (emacs_ev
->code
, event
->uChar
.AsciiChar
);
400 emacs_ev
->kind
= non_ascii_keystroke
;
402 /* use Windows keysym map */
403 XSETINT (emacs_ev
->code
, event
->wVirtualKeyCode
);
406 * make_lispy_event () now requires non-ascii codes to have
407 * the full X keysym values (2nd byte is 0xff). add it on.
410 XSETINT (emacs_ev
->code
, map
);
411 #endif /* HAVE_NTGUI */
413 /* for Mule 2.2 (Based on Emacs 19.28) */
415 XSET (emacs_ev
->frame_or_window
, Lisp_Frame
, get_frame ());
417 XSETFRAME (emacs_ev
->frame_or_window
, get_frame ());
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 */
426 /* Mouse position hook. */
428 w32_console_mouse_position (FRAME_PTR
*f
,
432 Lisp_Object
*bar_window
,
433 enum scroll_bar_part
*part
,
447 selected_frame
->mouse_moved
= 0;
451 *time
= movement_time
;
456 /* Remember mouse motion and notify emacs. */
458 mouse_moved_to (int x
, int y
)
460 /* If we're in the same place, ignore it */
461 if (x
!= movement_pos
.X
|| y
!= movement_pos
.Y
)
463 selected_frame
->mouse_moved
= 1;
466 movement_time
= GetTickCount ();
470 /* Consoles return button bits in a strange order:
471 least significant - Leftmost button
472 next - Rightmost button
476 Assume emacs likes three button mice, so
480 Others increase from there. */
482 static int emacs_button_translation
[NUM_MOUSE_BUTTONS
] =
488 do_mouse_event (MOUSE_EVENT_RECORD
*event
,
489 struct input_event
*emacs_ev
)
491 static DWORD button_state
= 0;
492 DWORD but_change
, mask
;
495 if (event
->dwEventFlags
== MOUSE_MOVED
)
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
);
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
)
508 emacs_ev
->kind
= mouse_click
;
510 /* Find out what button has changed state since the last button event. */
511 but_change
= button_state
^ event
->dwButtonState
;
513 for (i
= 0; i
< NUM_MOUSE_BUTTONS
; i
++, mask
<<= 1)
514 if (but_change
& mask
)
516 XSETINT (emacs_ev
->code
, emacs_button_translation
[i
]);
520 /* If the changed button is out of emacs' range (highly unlikely)
521 ignore this event. */
522 if (i
== NUM_MOUSE_BUTTONS
)
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
);
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 */
534 XSET (emacs_ev
->frame_or_window
, Lisp_Frame
, get_frame ());
536 XSETFRAME (emacs_ev
->frame_or_window
, get_frame ());
543 resize_event (WINDOW_BUFFER_SIZE_RECORD
*event
)
545 FRAME_PTR f
= get_frame ();
547 change_frame_size (f
, event
->dwSize
.Y
, event
->dwSize
.X
, 0, 1);
548 SET_FRAME_GARBAGED (f
);
552 w32_console_read_socket (int sd
, struct input_event
*bufp
, int numchars
,
555 BOOL no_events
= TRUE
;
556 int nev
, ret
= 0, add
;
559 if (interrupt_input_blocked
)
561 interrupt_input_pending
= 1;
565 interrupt_input_pending
= 0;
570 nev
= fill_queue (0);
573 /* If nev == -1, there was some kind of error
574 If nev == 0 then waitp must be zero and no events were available
580 while (nev
> 0 && numchars
> 0)
582 switch (queue_ptr
->EventType
)
585 add
= key_event (&queue_ptr
->Event
.KeyEvent
, bufp
, &isdead
);
586 if (add
== -1) /* 95.7.25 by himi */
597 add
= do_mouse_event (&queue_ptr
->Event
.MouseEvent
, bufp
);
603 case WINDOW_BUFFER_SIZE_EVENT
:
604 resize_event (&queue_ptr
->Event
.WindowBufferSizeEvent
);
609 /* Internal event types, ignored. */
617 if (ret
> 0 || expected
== 0)