Fix non-ASCII input in non-GUI frames on MS-Windows. (Bug#12055)
[bpt/emacs.git] / src / w32inevt.c
1 /* Input event support for Emacs on the Microsoft W32 API.
2 Copyright (C) 1992-1993, 1995, 2001-2012 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 3 of the License, or
9 (at your option) 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. If not, see <http://www.gnu.org/licenses/>. */
18
19 /*
20 Drew Bliss 01-Oct-93
21 Adapted from ntkbd.c by Tim Fleehart
22 */
23
24
25 #include <config.h>
26 #include <stdio.h>
27 #include <windows.h>
28 #include <setjmp.h>
29
30 #ifndef MOUSE_MOVED
31 #define MOUSE_MOVED 1
32 #endif
33
34 #include "lisp.h"
35 #include "keyboard.h"
36 #include "frame.h"
37 #include "dispextern.h"
38 #include "window.h"
39 #include "blockinput.h"
40 #include "termhooks.h"
41 #include "termchar.h"
42 #include "w32heap.h"
43 #include "w32term.h"
44 #include "w32inevt.h"
45
46 /* stdin, from w32console.c */
47 extern HANDLE keyboard_handle;
48
49 /* Info for last mouse motion */
50 static COORD movement_pos;
51 static Time movement_time;
52
53 /* from w32fns.c */
54 extern unsigned int map_keypad_keys (unsigned int, unsigned int);
55 extern unsigned int w32_key_to_modifier (int key);
56
57 /* Event queue */
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;
61
62 /* Temporarily store lead byte of DBCS input sequences. */
63 static char dbcs_lead = 0;
64
65 static inline BOOL
66 w32_read_console_input (HANDLE h, INPUT_RECORD *rec, DWORD recsize,
67 DWORD *waiting)
68 {
69 return (w32_console_unicode_input
70 ? ReadConsoleInputW (h, rec, recsize, waiting)
71 : ReadConsoleInputA (h, rec, recsize, waiting));
72 }
73
74 static int
75 fill_queue (BOOL block)
76 {
77 BOOL rc;
78 DWORD events_waiting;
79
80 if (queue_ptr < queue_end)
81 return queue_end-queue_ptr;
82
83 if (!block)
84 {
85 /* Check to see if there are some events to read before we try
86 because we can't block. */
87 if (!GetNumberOfConsoleInputEvents (keyboard_handle, &events_waiting))
88 return -1;
89 if (events_waiting == 0)
90 return 0;
91 }
92
93 rc = w32_read_console_input (keyboard_handle, event_queue, EVENT_QUEUE_SIZE,
94 &events_waiting);
95 if (!rc)
96 return -1;
97 queue_ptr = event_queue;
98 queue_end = event_queue + events_waiting;
99 return (int) events_waiting;
100 }
101
102 /* In a generic, multi-frame world this should take a console handle
103 and return the frame for it
104
105 Right now, there's only one frame so return it. */
106 static FRAME_PTR
107 get_frame (void)
108 {
109 return SELECTED_FRAME ();
110 }
111
112 /* Translate console modifiers to emacs modifiers.
113 German keyboard support (Kai Morgan Zeise 2/18/95). */
114 int
115 w32_kbd_mods_to_emacs (DWORD mods, WORD key)
116 {
117 int retval = 0;
118
119 /* If we recognize right-alt and left-ctrl as AltGr, and it has been
120 pressed, first remove those modifiers. */
121 if (!NILP (Vw32_recognize_altgr)
122 && (mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
123 == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
124 mods &= ~ (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED);
125
126 if (mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
127 retval = ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier);
128
129 if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
130 {
131 retval |= ctrl_modifier;
132 if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
133 == (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
134 retval |= meta_modifier;
135 }
136
137 if (mods & LEFT_WIN_PRESSED)
138 retval |= w32_key_to_modifier (VK_LWIN);
139 if (mods & RIGHT_WIN_PRESSED)
140 retval |= w32_key_to_modifier (VK_RWIN);
141 if (mods & APPS_PRESSED)
142 retval |= w32_key_to_modifier (VK_APPS);
143 if (mods & SCROLLLOCK_ON)
144 retval |= w32_key_to_modifier (VK_SCROLL);
145
146 /* Just in case someone wanted the original behavior, make it
147 optional by setting w32-capslock-is-shiftlock to t. */
148 if (NILP (Vw32_capslock_is_shiftlock)
149 /* Keys that should _not_ be affected by CapsLock. */
150 && ( (key == VK_BACK)
151 || (key == VK_TAB)
152 || (key == VK_CLEAR)
153 || (key == VK_RETURN)
154 || (key == VK_ESCAPE)
155 || ((key >= VK_SPACE) && (key <= VK_HELP))
156 || ((key >= VK_NUMPAD0) && (key <= VK_F24))
157 || ((key >= VK_NUMPAD_CLEAR) && (key <= VK_NUMPAD_DELETE))
158 ))
159 {
160 /* Only consider shift state. */
161 if ((mods & SHIFT_PRESSED) != 0)
162 retval |= shift_modifier;
163 }
164 else
165 {
166 /* Ignore CapsLock state if not enabled. */
167 if (NILP (Vw32_enable_caps_lock))
168 mods &= ~CAPSLOCK_ON;
169 if ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) != 0)
170 retval |= shift_modifier;
171 }
172
173 return retval;
174 }
175
176 #if 0
177 /* Return nonzero if the virtual key is a dead key. */
178 static int
179 is_dead_key (int wparam)
180 {
181 unsigned int code = MapVirtualKey (wparam, 2);
182
183 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
184 return (code & 0x80008000) ? 1 : 0;
185 }
186 #endif
187
188 /* The return code indicates key code size. */
189 int
190 w32_kbd_patch_key (KEY_EVENT_RECORD *event)
191 {
192 unsigned int key_code = event->wVirtualKeyCode;
193 unsigned int mods = event->dwControlKeyState;
194 BYTE keystate[256];
195 static BYTE ansi_code[4];
196 static int isdead = 0;
197
198 if (isdead == 2)
199 {
200 event->uChar.AsciiChar = ansi_code[2];
201 isdead = 0;
202 return 1;
203 }
204 if (event->uChar.AsciiChar != 0)
205 return 1;
206
207 memset (keystate, 0, sizeof (keystate));
208 keystate[key_code] = 0x80;
209 if (mods & SHIFT_PRESSED)
210 keystate[VK_SHIFT] = 0x80;
211 if (mods & CAPSLOCK_ON)
212 keystate[VK_CAPITAL] = 1;
213 /* If we recognize right-alt and left-ctrl as AltGr, set the key
214 states accordingly before invoking ToAscii. */
215 if (!NILP (Vw32_recognize_altgr)
216 && (mods & LEFT_CTRL_PRESSED) && (mods & RIGHT_ALT_PRESSED))
217 {
218 keystate[VK_CONTROL] = 0x80;
219 keystate[VK_LCONTROL] = 0x80;
220 keystate[VK_MENU] = 0x80;
221 keystate[VK_RMENU] = 0x80;
222 }
223
224 #if 0
225 /* Because of an OS bug, ToAscii corrupts the stack when called to
226 convert a dead key in console mode on NT4. Unfortunately, trying
227 to check for dead keys using MapVirtualKey doesn't work either -
228 these functions apparently use internal information about keyboard
229 layout which doesn't get properly updated in console programs when
230 changing layout (though apparently it gets partly updated,
231 otherwise ToAscii wouldn't crash). */
232 if (is_dead_key (event->wVirtualKeyCode))
233 return 0;
234 #endif
235
236 /* On NT, call ToUnicode instead and then convert to the current
237 console input codepage. */
238 if (os_subtype == OS_NT)
239 {
240 WCHAR buf[128];
241
242 isdead = ToUnicode (event->wVirtualKeyCode, event->wVirtualScanCode,
243 keystate, buf, 128, 0);
244 if (isdead > 0)
245 {
246 int cpId = GetConsoleCP ();
247
248 event->uChar.UnicodeChar = buf[isdead - 1];
249 isdead = WideCharToMultiByte (cpId, 0, buf, isdead,
250 ansi_code, 4, NULL, NULL);
251 }
252 else
253 isdead = 0;
254 }
255 else
256 {
257 isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode,
258 keystate, (LPWORD) ansi_code, 0);
259 }
260
261 if (isdead == 0)
262 return 0;
263 event->uChar.AsciiChar = ansi_code[0];
264 return isdead;
265 }
266
267
268 static int faked_key = 0;
269
270 /* return code -1 means that event_queue_ptr won't be incremented.
271 In other word, this event makes two key codes. (by himi) */
272 static int
273 key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
274 {
275 static int mod_key_state = 0;
276 int wParam;
277
278 *isdead = 0;
279
280 /* Skip key-up events. */
281 if (!event->bKeyDown)
282 {
283 switch (event->wVirtualKeyCode)
284 {
285 case VK_LWIN:
286 mod_key_state &= ~LEFT_WIN_PRESSED;
287 break;
288 case VK_RWIN:
289 mod_key_state &= ~RIGHT_WIN_PRESSED;
290 break;
291 case VK_APPS:
292 mod_key_state &= ~APPS_PRESSED;
293 break;
294 }
295 return 0;
296 }
297
298 /* Ignore keystrokes we fake ourself; see below. */
299 if (faked_key == event->wVirtualKeyCode)
300 {
301 faked_key = 0;
302 return 0;
303 }
304
305 /* To make it easier to debug this code, ignore modifier keys! */
306 switch (event->wVirtualKeyCode)
307 {
308 case VK_LWIN:
309 if (NILP (Vw32_pass_lwindow_to_system))
310 {
311 /* Prevent system from acting on keyup (which opens the Start
312 menu if no other key was pressed) by simulating a press of
313 Space which we will ignore. */
314 if ((mod_key_state & LEFT_WIN_PRESSED) == 0)
315 {
316 if (NUMBERP (Vw32_phantom_key_code))
317 faked_key = XUINT (Vw32_phantom_key_code) & 255;
318 else
319 faked_key = VK_SPACE;
320 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
321 }
322 }
323 mod_key_state |= LEFT_WIN_PRESSED;
324 if (!NILP (Vw32_lwindow_modifier))
325 return 0;
326 break;
327 case VK_RWIN:
328 if (NILP (Vw32_pass_rwindow_to_system))
329 {
330 if ((mod_key_state & RIGHT_WIN_PRESSED) == 0)
331 {
332 if (NUMBERP (Vw32_phantom_key_code))
333 faked_key = XUINT (Vw32_phantom_key_code) & 255;
334 else
335 faked_key = VK_SPACE;
336 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
337 }
338 }
339 mod_key_state |= RIGHT_WIN_PRESSED;
340 if (!NILP (Vw32_rwindow_modifier))
341 return 0;
342 break;
343 case VK_APPS:
344 mod_key_state |= APPS_PRESSED;
345 if (!NILP (Vw32_apps_modifier))
346 return 0;
347 break;
348 case VK_CAPITAL:
349 /* Decide whether to treat as modifier or function key. */
350 if (NILP (Vw32_enable_caps_lock))
351 goto disable_lock_key;
352 return 0;
353 case VK_NUMLOCK:
354 /* Decide whether to treat as modifier or function key. */
355 if (NILP (Vw32_enable_num_lock))
356 goto disable_lock_key;
357 return 0;
358 case VK_SCROLL:
359 /* Decide whether to treat as modifier or function key. */
360 if (NILP (Vw32_scroll_lock_modifier))
361 goto disable_lock_key;
362 return 0;
363 disable_lock_key:
364 /* Ensure the appropriate lock key state is off (and the
365 indicator light as well). */
366 wParam = event->wVirtualKeyCode;
367 if (GetAsyncKeyState (wParam) & 0x8000)
368 {
369 /* Fake another press of the relevant key. Apparently, this
370 really is the only way to turn off the indicator. */
371 faked_key = wParam;
372 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
373 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
374 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
375 KEYEVENTF_EXTENDEDKEY | 0, 0);
376 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
377 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
378 }
379 break;
380 case VK_MENU:
381 case VK_CONTROL:
382 case VK_SHIFT:
383 return 0;
384 case VK_CANCEL:
385 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
386 which is confusing for purposes of key binding; convert
387 VK_CANCEL events into VK_PAUSE events. */
388 event->wVirtualKeyCode = VK_PAUSE;
389 break;
390 case VK_PAUSE:
391 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
392 for purposes of key binding; convert these back into
393 VK_NUMLOCK events, at least when we want to see NumLock key
394 presses. (Note that there is never any possibility that
395 VK_PAUSE with Ctrl really is C-Pause as per above.) */
396 if (NILP (Vw32_enable_num_lock)
397 && (event->dwControlKeyState
398 & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0)
399 event->wVirtualKeyCode = VK_NUMLOCK;
400 break;
401 }
402
403 /* Recognize state of Windows and Apps keys. */
404 event->dwControlKeyState |= mod_key_state;
405
406 /* Distinguish numeric keypad keys from extended keys. */
407 event->wVirtualKeyCode =
408 map_keypad_keys (event->wVirtualKeyCode,
409 (event->dwControlKeyState & ENHANCED_KEY));
410
411 if (lispy_function_keys[event->wVirtualKeyCode] == 0)
412 {
413 if (!NILP (Vw32_recognize_altgr)
414 && (event->dwControlKeyState & LEFT_CTRL_PRESSED)
415 && (event->dwControlKeyState & RIGHT_ALT_PRESSED))
416 {
417 /* Don't try to interpret AltGr key chords; ToAscii seems not
418 to process them correctly. */
419 }
420 /* Handle key chords including any modifiers other than shift
421 directly, in order to preserve as much modifier information as
422 possible. */
423 else if (event->dwControlKeyState
424 & ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED
425 | RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED
426 | (!NILP (Vw32_lwindow_modifier) ? LEFT_WIN_PRESSED : 0)
427 | (!NILP (Vw32_rwindow_modifier) ? RIGHT_WIN_PRESSED : 0)
428 | (!NILP (Vw32_apps_modifier) ? APPS_PRESSED : 0)
429 | (!NILP (Vw32_scroll_lock_modifier) ? SCROLLLOCK_ON : 0)))
430 {
431 /* Don't translate modified alphabetic keystrokes, so the user
432 doesn't need to constantly switch layout to type control or
433 meta keystrokes when the normal layout translates
434 alphabetic characters to non-ascii characters. */
435 if ('A' <= event->wVirtualKeyCode && event->wVirtualKeyCode <= 'Z')
436 {
437 event->uChar.AsciiChar = event->wVirtualKeyCode;
438 if ((event->dwControlKeyState & SHIFT_PRESSED) == 0)
439 event->uChar.AsciiChar += ('a' - 'A');
440 }
441 /* Try to handle unrecognized keystrokes by determining the
442 base character (ie. translating the base key plus shift
443 modifier). */
444 else if (event->uChar.AsciiChar == 0)
445 w32_kbd_patch_key (event);
446 }
447
448 if (event->uChar.AsciiChar == 0)
449 {
450 emacs_ev->kind = NO_EVENT;
451 return 0;
452 }
453 else if (event->uChar.AsciiChar > 0)
454 {
455 /* Pure ASCII characters < 128. */
456 emacs_ev->kind = ASCII_KEYSTROKE_EVENT;
457 emacs_ev->code = event->uChar.AsciiChar;
458 }
459 else if (event->uChar.UnicodeChar > 0
460 && w32_console_unicode_input)
461 {
462 /* Unicode codepoint; only valid if we are using Unicode
463 console input mode. */
464 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
465 emacs_ev->code = event->uChar.UnicodeChar;
466 }
467 else
468 {
469 /* Fallback handling of non-ASCII characters for non-Unicode
470 versions of Windows, and for non-Unicode input on NT
471 family of Windows. Only characters in the current
472 console codepage are supported by this fallback. */
473 wchar_t code;
474 char dbcs[2];
475 int cpId;
476
477 /* Get the current console input codepage to interpret this
478 key with. Note that the system defaults for the OEM
479 codepage could have been changed by calling SetConsoleCP
480 or w32-set-console-codepage, so using GetLocaleInfo to
481 get LOCALE_IDEFAULTCODEPAGE is not TRT here. */
482 cpId = GetConsoleCP ();
483
484 dbcs[0] = dbcs_lead;
485 dbcs[1] = event->uChar.AsciiChar;
486 if (dbcs_lead)
487 {
488 dbcs_lead = 0;
489 if (!MultiByteToWideChar (cpId, 0, dbcs, 2, &code, 1))
490 {
491 /* Garbage */
492 DebPrint (("Invalid DBCS sequence: %d %d\n",
493 dbcs[0], dbcs[1]));
494 emacs_ev->kind = NO_EVENT;
495 }
496 }
497 else if (IsDBCSLeadByteEx (cpId, dbcs[1]))
498 {
499 dbcs_lead = dbcs[1];
500 emacs_ev->kind = NO_EVENT;
501 }
502 else
503 {
504 if (!MultiByteToWideChar (cpId, 0, &dbcs[1], 1, &code, 1))
505 {
506 /* Garbage */
507 DebPrint (("Invalid character: %d\n", dbcs[1]));
508 emacs_ev->kind = NO_EVENT;
509 }
510 }
511 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
512 emacs_ev->code = code;
513 }
514 }
515 else
516 {
517 /* Function keys and other non-character keys. */
518 emacs_ev->kind = NON_ASCII_KEYSTROKE_EVENT;
519 emacs_ev->code = event->wVirtualKeyCode;
520 }
521
522 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
523 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState,
524 event->wVirtualKeyCode);
525 emacs_ev->timestamp = GetTickCount ();
526 return 1;
527 }
528
529 int
530 w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state)
531 {
532 int cur_state = (GetKeyState (vk_code) & 1);
533
534 if (NILP (new_state)
535 || (NUMBERP (new_state)
536 && ((XUINT (new_state)) & 1) != cur_state))
537 {
538 faked_key = vk_code;
539
540 keybd_event ((BYTE) vk_code,
541 (BYTE) MapVirtualKey (vk_code, 0),
542 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
543 keybd_event ((BYTE) vk_code,
544 (BYTE) MapVirtualKey (vk_code, 0),
545 KEYEVENTF_EXTENDEDKEY | 0, 0);
546 keybd_event ((BYTE) vk_code,
547 (BYTE) MapVirtualKey (vk_code, 0),
548 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
549 cur_state = !cur_state;
550 }
551
552 return cur_state;
553 }
554
555 /* Mouse position hook. */
556 void
557 w32_console_mouse_position (FRAME_PTR *f,
558 int insist,
559 Lisp_Object *bar_window,
560 enum scroll_bar_part *part,
561 Lisp_Object *x,
562 Lisp_Object *y,
563 Time *time)
564 {
565 BLOCK_INPUT;
566
567 insist = insist;
568
569 *f = get_frame ();
570 *bar_window = Qnil;
571 *part = 0;
572 SELECTED_FRAME ()->mouse_moved = 0;
573
574 XSETINT (*x, movement_pos.X);
575 XSETINT (*y, movement_pos.Y);
576 *time = movement_time;
577
578 UNBLOCK_INPUT;
579 }
580
581 /* Remember mouse motion and notify emacs. */
582 static void
583 mouse_moved_to (int x, int y)
584 {
585 /* If we're in the same place, ignore it. */
586 if (x != movement_pos.X || y != movement_pos.Y)
587 {
588 SELECTED_FRAME ()->mouse_moved = 1;
589 movement_pos.X = x;
590 movement_pos.Y = y;
591 movement_time = GetTickCount ();
592 }
593 }
594
595 /* Consoles return button bits in a strange order:
596 least significant - Leftmost button
597 next - Rightmost button
598 next - Leftmost+1
599 next - Leftmost+2...
600
601 Assume emacs likes three button mice, so
602 Left == 0
603 Middle == 1
604 Right == 2
605 Others increase from there. */
606
607 #define NUM_TRANSLATED_MOUSE_BUTTONS 3
608 static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] =
609 {
610 0, 2, 1
611 };
612
613 static int
614 do_mouse_event (MOUSE_EVENT_RECORD *event,
615 struct input_event *emacs_ev)
616 {
617 static DWORD button_state = 0;
618 static Lisp_Object last_mouse_window;
619 DWORD but_change, mask;
620 int i;
621
622 if (event->dwEventFlags == MOUSE_MOVED)
623 {
624 FRAME_PTR f = SELECTED_FRAME ();
625 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
626 int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y;
627
628 mouse_moved_to (mx, my);
629
630 if (f->mouse_moved)
631 {
632 if (hlinfo->mouse_face_hidden)
633 {
634 hlinfo->mouse_face_hidden = 0;
635 clear_mouse_face (hlinfo);
636 }
637
638 /* Generate SELECT_WINDOW_EVENTs when needed. */
639 if (!NILP (Vmouse_autoselect_window))
640 {
641 Lisp_Object mouse_window = window_from_coordinates (f, mx, my,
642 0, 0);
643 /* A window will be selected only when it is not
644 selected now, and the last mouse movement event was
645 not in it. A minibuffer window will be selected iff
646 it is active. */
647 if (WINDOWP (mouse_window)
648 && !EQ (mouse_window, last_mouse_window)
649 && !EQ (mouse_window, selected_window))
650 {
651 struct input_event event;
652
653 EVENT_INIT (event);
654 event.kind = SELECT_WINDOW_EVENT;
655 event.frame_or_window = mouse_window;
656 event.arg = Qnil;
657 event.timestamp = movement_time;
658 kbd_buffer_store_event (&event);
659 }
660 last_mouse_window = mouse_window;
661 }
662 else
663 last_mouse_window = Qnil;
664
665 previous_help_echo_string = help_echo_string;
666 help_echo_string = help_echo_object = help_echo_window = Qnil;
667 help_echo_pos = -1;
668 note_mouse_highlight (f, mx, my);
669 /* If the contents of the global variable help_echo has
670 changed (inside note_mouse_highlight), generate a HELP_EVENT. */
671 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
672 gen_help_event (help_echo_string, selected_frame, help_echo_window,
673 help_echo_object, help_echo_pos);
674 }
675 return 0;
676 }
677
678 /* It looks like the console code sends us a mouse event with
679 dwButtonState == 0 when a window is activated. Ignore this case. */
680 if (event->dwButtonState == button_state)
681 return 0;
682
683 emacs_ev->kind = MOUSE_CLICK_EVENT;
684
685 /* Find out what button has changed state since the last button event. */
686 but_change = button_state ^ event->dwButtonState;
687 mask = 1;
688 for (i = 0; mask; i++, mask <<= 1)
689 if (but_change & mask)
690 {
691 if (i < NUM_TRANSLATED_MOUSE_BUTTONS)
692 emacs_ev->code = emacs_button_translation[i];
693 else
694 emacs_ev->code = i;
695 break;
696 }
697
698 button_state = event->dwButtonState;
699 emacs_ev->timestamp = GetTickCount ();
700 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, 0) |
701 ((event->dwButtonState & mask) ? down_modifier : up_modifier);
702
703 XSETFASTINT (emacs_ev->x, event->dwMousePosition.X);
704 XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y);
705 /* for Mule 2.2 (Based on Emacs 19.28 */
706 #ifdef MULE
707 XSET (emacs_ev->frame_or_window, Lisp_Frame, get_frame ());
708 #else
709 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
710 #endif
711
712 return 1;
713 }
714
715 static void
716 resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
717 {
718 FRAME_PTR f = get_frame ();
719
720 change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1, 0);
721 SET_FRAME_GARBAGED (f);
722 }
723
724 static void
725 maybe_generate_resize_event (void)
726 {
727 CONSOLE_SCREEN_BUFFER_INFO info;
728 FRAME_PTR f = get_frame ();
729
730 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
731
732 /* It is okay to call this unconditionally, since it will do nothing
733 if the size hasn't actually changed. */
734 change_frame_size (f,
735 1 + info.srWindow.Bottom - info.srWindow.Top,
736 1 + info.srWindow.Right - info.srWindow.Left,
737 0, 0, 0);
738 }
739
740 int
741 w32_console_read_socket (struct terminal *terminal,
742 int expected,
743 struct input_event *hold_quit)
744 {
745 int nev, ret = 0, add;
746 int isdead;
747
748 if (interrupt_input_blocked)
749 {
750 interrupt_input_pending = 1;
751 return -1;
752 }
753
754 interrupt_input_pending = 0;
755 BLOCK_INPUT;
756
757 for (;;)
758 {
759 nev = fill_queue (0);
760 if (nev <= 0)
761 {
762 /* If nev == -1, there was some kind of error
763 If nev == 0 then waitp must be zero and no events were available
764 so return. */
765 UNBLOCK_INPUT;
766 return nev;
767 }
768
769 while (nev > 0)
770 {
771 struct input_event inev;
772
773 EVENT_INIT (inev);
774 inev.kind = NO_EVENT;
775 inev.arg = Qnil;
776
777 switch (queue_ptr->EventType)
778 {
779 case KEY_EVENT:
780 add = key_event (&queue_ptr->Event.KeyEvent, &inev, &isdead);
781 if (add == -1) /* 95.7.25 by himi */
782 {
783 queue_ptr--;
784 add = 1;
785 }
786 if (add)
787 kbd_buffer_store_event_hold (&inev, hold_quit);
788 break;
789
790 case MOUSE_EVENT:
791 add = do_mouse_event (&queue_ptr->Event.MouseEvent, &inev);
792 if (add)
793 kbd_buffer_store_event_hold (&inev, hold_quit);
794 break;
795
796 case WINDOW_BUFFER_SIZE_EVENT:
797 if (w32_use_full_screen_buffer)
798 resize_event (&queue_ptr->Event.WindowBufferSizeEvent);
799 break;
800
801 case MENU_EVENT:
802 case FOCUS_EVENT:
803 /* Internal event types, ignored. */
804 break;
805 }
806
807 queue_ptr++;
808 nev--;
809 }
810
811 if (ret > 0 || expected == 0)
812 break;
813 }
814
815 /* We don't get told about changes in the window size (only the buffer
816 size, which we no longer care about), so we have to check it
817 periodically. */
818 if (!w32_use_full_screen_buffer)
819 maybe_generate_resize_event ();
820
821 UNBLOCK_INPUT;
822 return ret;
823 }