Fix GDB mode line for gdb-create-source-file-list nil.
[emacs.git] / src / w32inevt.c
blobfddde61663f1b9bf2e9a11649f7052a8ef181833
1 /* Input event support for Emacs on the Microsoft W32 API.
2 Copyright (C) 1992-1993, 1995, 2001-2011 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 3 of the License, or
9 (at your option) any later version.
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. If not, see <http://www.gnu.org/licenses/>. */
20 Drew Bliss 01-Oct-93
21 Adapted from ntkbd.c by Tim Fleehart
25 #include <config.h>
26 #include <stdio.h>
27 #include <windows.h>
28 #include <setjmp.h>
30 #ifndef MOUSE_MOVED
31 #define MOUSE_MOVED 1
32 #endif
34 #include "lisp.h"
35 #include "keyboard.h"
36 #include "frame.h"
37 #include "dispextern.h"
38 #include "blockinput.h"
39 #include "termhooks.h"
40 #include "w32heap.h"
41 #include "w32term.h"
43 /* stdin, from w32console.c */
44 extern HANDLE keyboard_handle;
46 /* Info for last mouse motion */
47 static COORD movement_pos;
48 static Time movement_time;
50 /* from w32fns.c */
51 extern unsigned int map_keypad_keys (unsigned int, unsigned int);
52 extern unsigned int w32_key_to_modifier (int key);
54 /* Event queue */
55 #define EVENT_QUEUE_SIZE 50
56 static INPUT_RECORD event_queue[EVENT_QUEUE_SIZE];
57 static INPUT_RECORD *queue_ptr = event_queue, *queue_end = event_queue;
59 /* Temporarily store lead byte of DBCS input sequences. */
60 static char dbcs_lead = 0;
62 static int
63 fill_queue (BOOL block)
65 BOOL rc;
66 DWORD events_waiting;
68 if (queue_ptr < queue_end)
69 return queue_end-queue_ptr;
71 if (!block)
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))
76 return -1;
77 if (events_waiting == 0)
78 return 0;
81 rc = ReadConsoleInput (keyboard_handle, event_queue, EVENT_QUEUE_SIZE,
82 &events_waiting);
83 if (!rc)
84 return -1;
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. */
94 static FRAME_PTR
95 get_frame (void)
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)
105 int retval = 0;
107 /* If we recognize right-alt and left-ctrl as AltGr, and it has been
108 pressed, first remove those 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 if (mods & LEFT_WIN_PRESSED)
126 retval |= w32_key_to_modifier (VK_LWIN);
127 if (mods & RIGHT_WIN_PRESSED)
128 retval |= w32_key_to_modifier (VK_RWIN);
129 if (mods & APPS_PRESSED)
130 retval |= w32_key_to_modifier (VK_APPS);
131 if (mods & SCROLLLOCK_ON)
132 retval |= w32_key_to_modifier (VK_SCROLL);
134 /* Just in case someone wanted the original behavior, make it
135 optional by setting w32-capslock-is-shiftlock to t. */
136 if (NILP (Vw32_capslock_is_shiftlock)
137 /* Keys that should _not_ be affected by CapsLock. */
138 && ( (key == VK_BACK)
139 || (key == VK_TAB)
140 || (key == VK_CLEAR)
141 || (key == VK_RETURN)
142 || (key == VK_ESCAPE)
143 || ((key >= VK_SPACE) && (key <= VK_HELP))
144 || ((key >= VK_NUMPAD0) && (key <= VK_F24))
145 || ((key >= VK_NUMPAD_CLEAR) && (key <= VK_NUMPAD_DELETE))
148 /* Only consider shift state. */
149 if ((mods & SHIFT_PRESSED) != 0)
150 retval |= shift_modifier;
152 else
154 /* Ignore CapsLock state if not enabled. */
155 if (NILP (Vw32_enable_caps_lock))
156 mods &= ~CAPSLOCK_ON;
157 if ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) != 0)
158 retval |= shift_modifier;
161 return retval;
164 #if 0
165 /* Return nonzero if the virtual key is a dead key. */
166 static int
167 is_dead_key (int wparam)
169 unsigned int code = MapVirtualKey (wparam, 2);
171 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
172 return (code & 0x80008000) ? 1 : 0;
174 #endif
176 /* The return code indicates key code size. */
178 w32_kbd_patch_key (KEY_EVENT_RECORD *event)
180 unsigned int key_code = event->wVirtualKeyCode;
181 unsigned int mods = event->dwControlKeyState;
182 BYTE keystate[256];
183 static BYTE ansi_code[4];
184 static int isdead = 0;
186 if (isdead == 2)
188 event->uChar.AsciiChar = ansi_code[2];
189 isdead = 0;
190 return 1;
192 if (event->uChar.AsciiChar != 0)
193 return 1;
195 memset (keystate, 0, sizeof (keystate));
196 keystate[key_code] = 0x80;
197 if (mods & SHIFT_PRESSED)
198 keystate[VK_SHIFT] = 0x80;
199 if (mods & CAPSLOCK_ON)
200 keystate[VK_CAPITAL] = 1;
201 /* If we recognize right-alt and left-ctrl as AltGr, set the key
202 states accordingly before invoking ToAscii. */
203 if (!NILP (Vw32_recognize_altgr)
204 && (mods & LEFT_CTRL_PRESSED) && (mods & RIGHT_ALT_PRESSED))
206 keystate[VK_CONTROL] = 0x80;
207 keystate[VK_LCONTROL] = 0x80;
208 keystate[VK_MENU] = 0x80;
209 keystate[VK_RMENU] = 0x80;
212 #if 0
213 /* Because of an OS bug, ToAscii corrupts the stack when called to
214 convert a dead key in console mode on NT4. Unfortunately, trying
215 to check for dead keys using MapVirtualKey doesn't work either -
216 these functions apparently use internal information about keyboard
217 layout which doesn't get properly updated in console programs when
218 changing layout (though apparently it gets partly updated,
219 otherwise ToAscii wouldn't crash). */
220 if (is_dead_key (event->wVirtualKeyCode))
221 return 0;
222 #endif
224 /* On NT, call ToUnicode instead and then convert to the current
225 locale's default codepage. */
226 if (os_subtype == OS_NT)
228 WCHAR buf[128];
230 isdead = ToUnicode (event->wVirtualKeyCode, event->wVirtualScanCode,
231 keystate, buf, 128, 0);
232 if (isdead > 0)
234 char cp[20];
235 int cpId;
237 event->uChar.UnicodeChar = buf[isdead - 1];
239 GetLocaleInfo (GetThreadLocale (),
240 LOCALE_IDEFAULTANSICODEPAGE, cp, 20);
241 cpId = atoi (cp);
242 isdead = WideCharToMultiByte (cpId, 0, buf, isdead,
243 ansi_code, 4, NULL, NULL);
245 else
246 isdead = 0;
248 else
250 isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode,
251 keystate, (LPWORD) ansi_code, 0);
254 if (isdead == 0)
255 return 0;
256 event->uChar.AsciiChar = ansi_code[0];
257 return isdead;
261 static int faked_key = 0;
263 /* return code -1 means that event_queue_ptr won't be incremented.
264 In other word, this event makes two key codes. (by himi) */
265 static int
266 key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
268 static int mod_key_state = 0;
269 int wParam;
271 *isdead = 0;
273 /* Skip key-up events. */
274 if (!event->bKeyDown)
276 switch (event->wVirtualKeyCode)
278 case VK_LWIN:
279 mod_key_state &= ~LEFT_WIN_PRESSED;
280 break;
281 case VK_RWIN:
282 mod_key_state &= ~RIGHT_WIN_PRESSED;
283 break;
284 case VK_APPS:
285 mod_key_state &= ~APPS_PRESSED;
286 break;
288 return 0;
291 /* Ignore keystrokes we fake ourself; see below. */
292 if (faked_key == event->wVirtualKeyCode)
294 faked_key = 0;
295 return 0;
298 /* To make it easier to debug this code, ignore modifier keys! */
299 switch (event->wVirtualKeyCode)
301 case VK_LWIN:
302 if (NILP (Vw32_pass_lwindow_to_system))
304 /* Prevent system from acting on keyup (which opens the Start
305 menu if no other key was pressed) by simulating a press of
306 Space which we will ignore. */
307 if ((mod_key_state & LEFT_WIN_PRESSED) == 0)
309 if (NUMBERP (Vw32_phantom_key_code))
310 faked_key = XUINT (Vw32_phantom_key_code) & 255;
311 else
312 faked_key = VK_SPACE;
313 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
316 mod_key_state |= LEFT_WIN_PRESSED;
317 if (!NILP (Vw32_lwindow_modifier))
318 return 0;
319 break;
320 case VK_RWIN:
321 if (NILP (Vw32_pass_rwindow_to_system))
323 if ((mod_key_state & RIGHT_WIN_PRESSED) == 0)
325 if (NUMBERP (Vw32_phantom_key_code))
326 faked_key = XUINT (Vw32_phantom_key_code) & 255;
327 else
328 faked_key = VK_SPACE;
329 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
332 mod_key_state |= RIGHT_WIN_PRESSED;
333 if (!NILP (Vw32_rwindow_modifier))
334 return 0;
335 break;
336 case VK_APPS:
337 mod_key_state |= APPS_PRESSED;
338 if (!NILP (Vw32_apps_modifier))
339 return 0;
340 break;
341 case VK_CAPITAL:
342 /* Decide whether to treat as modifier or function key. */
343 if (NILP (Vw32_enable_caps_lock))
344 goto disable_lock_key;
345 return 0;
346 case VK_NUMLOCK:
347 /* Decide whether to treat as modifier or function key. */
348 if (NILP (Vw32_enable_num_lock))
349 goto disable_lock_key;
350 return 0;
351 case VK_SCROLL:
352 /* Decide whether to treat as modifier or function key. */
353 if (NILP (Vw32_scroll_lock_modifier))
354 goto disable_lock_key;
355 return 0;
356 disable_lock_key:
357 /* Ensure the appropriate lock key state is off (and the
358 indicator light as well). */
359 wParam = event->wVirtualKeyCode;
360 if (GetAsyncKeyState (wParam) & 0x8000)
362 /* Fake another press of the relevant key. Apparently, this
363 really is the only way to turn off the indicator. */
364 faked_key = wParam;
365 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
366 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
367 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
368 KEYEVENTF_EXTENDEDKEY | 0, 0);
369 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
370 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
372 break;
373 case VK_MENU:
374 case VK_CONTROL:
375 case VK_SHIFT:
376 return 0;
377 case VK_CANCEL:
378 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
379 which is confusing for purposes of key binding; convert
380 VK_CANCEL events into VK_PAUSE events. */
381 event->wVirtualKeyCode = VK_PAUSE;
382 break;
383 case VK_PAUSE:
384 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
385 for purposes of key binding; convert these back into
386 VK_NUMLOCK events, at least when we want to see NumLock key
387 presses. (Note that there is never any possibility that
388 VK_PAUSE with Ctrl really is C-Pause as per above.) */
389 if (NILP (Vw32_enable_num_lock)
390 && (event->dwControlKeyState
391 & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0)
392 event->wVirtualKeyCode = VK_NUMLOCK;
393 break;
396 /* Recognize state of Windows and Apps keys. */
397 event->dwControlKeyState |= mod_key_state;
399 /* Distinguish numeric keypad keys from extended keys. */
400 event->wVirtualKeyCode =
401 map_keypad_keys (event->wVirtualKeyCode,
402 (event->dwControlKeyState & ENHANCED_KEY));
404 if (lispy_function_keys[event->wVirtualKeyCode] == 0)
406 if (!NILP (Vw32_recognize_altgr)
407 && (event->dwControlKeyState & LEFT_CTRL_PRESSED)
408 && (event->dwControlKeyState & RIGHT_ALT_PRESSED))
410 /* Don't try to interpret AltGr key chords; ToAscii seems not
411 to process them correctly. */
413 /* Handle key chords including any modifiers other than shift
414 directly, in order to preserve as much modifier information as
415 possible. */
416 else if (event->dwControlKeyState
417 & ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED
418 | RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED
419 | (!NILP (Vw32_lwindow_modifier) ? LEFT_WIN_PRESSED : 0)
420 | (!NILP (Vw32_rwindow_modifier) ? RIGHT_WIN_PRESSED : 0)
421 | (!NILP (Vw32_apps_modifier) ? APPS_PRESSED : 0)
422 | (!NILP (Vw32_scroll_lock_modifier) ? SCROLLLOCK_ON : 0)))
424 /* Don't translate modified alphabetic keystrokes, so the user
425 doesn't need to constantly switch layout to type control or
426 meta keystrokes when the normal layout translates
427 alphabetic characters to non-ascii characters. */
428 if ('A' <= event->wVirtualKeyCode && event->wVirtualKeyCode <= 'Z')
430 event->uChar.AsciiChar = event->wVirtualKeyCode;
431 if ((event->dwControlKeyState & SHIFT_PRESSED) == 0)
432 event->uChar.AsciiChar += ('a' - 'A');
434 /* Try to handle unrecognized keystrokes by determining the
435 base character (ie. translating the base key plus shift
436 modifier). */
437 else if (event->uChar.AsciiChar == 0)
438 w32_kbd_patch_key (event);
441 if (event->uChar.AsciiChar == 0)
443 emacs_ev->kind = NO_EVENT;
444 return 0;
446 else if (event->uChar.AsciiChar > 0)
448 emacs_ev->kind = ASCII_KEYSTROKE_EVENT;
449 emacs_ev->code = event->uChar.AsciiChar;
451 else if (event->uChar.UnicodeChar > 0)
453 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
454 emacs_ev->code = event->uChar.UnicodeChar;
456 else
458 /* Fallback for non-Unicode versions of Windows. */
459 wchar_t code;
460 char dbcs[2];
461 char cp[20];
462 int cpId;
464 /* Get the codepage to interpret this key with. */
465 GetLocaleInfo (GetThreadLocale (),
466 LOCALE_IDEFAULTANSICODEPAGE, cp, 20);
467 cpId = atoi (cp);
469 dbcs[0] = dbcs_lead;
470 dbcs[1] = event->uChar.AsciiChar;
471 if (dbcs_lead)
473 dbcs_lead = 0;
474 if (!MultiByteToWideChar (cpId, 0, dbcs, 2, &code, 1))
476 /* Garbage */
477 DebPrint (("Invalid DBCS sequence: %d %d\n",
478 dbcs[0], dbcs[1]));
479 emacs_ev->kind = NO_EVENT;
482 else if (IsDBCSLeadByteEx (cpId, dbcs[1]))
484 dbcs_lead = dbcs[1];
485 emacs_ev->kind = NO_EVENT;
487 else
489 if (!MultiByteToWideChar (cpId, 0, &dbcs[1], 1, &code, 1))
491 /* Garbage */
492 DebPrint (("Invalid character: %d\n", dbcs[1]));
493 emacs_ev->kind = NO_EVENT;
496 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
497 emacs_ev->code = code;
500 else
502 emacs_ev->kind = NON_ASCII_KEYSTROKE_EVENT;
503 emacs_ev->code = event->wVirtualKeyCode;
506 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
507 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState,
508 event->wVirtualKeyCode);
509 emacs_ev->timestamp = GetTickCount ();
510 return 1;
514 w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state)
516 int cur_state = (GetKeyState (vk_code) & 1);
518 if (NILP (new_state)
519 || (NUMBERP (new_state)
520 && ((XUINT (new_state)) & 1) != cur_state))
522 faked_key = vk_code;
524 keybd_event ((BYTE) vk_code,
525 (BYTE) MapVirtualKey (vk_code, 0),
526 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
527 keybd_event ((BYTE) vk_code,
528 (BYTE) MapVirtualKey (vk_code, 0),
529 KEYEVENTF_EXTENDEDKEY | 0, 0);
530 keybd_event ((BYTE) vk_code,
531 (BYTE) MapVirtualKey (vk_code, 0),
532 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
533 cur_state = !cur_state;
536 return cur_state;
539 /* Mouse position hook. */
540 void
541 w32_console_mouse_position (FRAME_PTR *f,
542 int insist,
543 Lisp_Object *bar_window,
544 enum scroll_bar_part *part,
545 Lisp_Object *x,
546 Lisp_Object *y,
547 Time *time)
549 BLOCK_INPUT;
551 insist = insist;
553 *f = get_frame ();
554 *bar_window = Qnil;
555 *part = 0;
556 SELECTED_FRAME ()->mouse_moved = 0;
558 XSETINT (*x, movement_pos.X);
559 XSETINT (*y, movement_pos.Y);
560 *time = movement_time;
562 UNBLOCK_INPUT;
565 /* Remember mouse motion and notify emacs. */
566 static void
567 mouse_moved_to (int x, int y)
569 /* If we're in the same place, ignore it */
570 if (x != movement_pos.X || y != movement_pos.Y)
572 SELECTED_FRAME ()->mouse_moved = 1;
573 movement_pos.X = x;
574 movement_pos.Y = y;
575 movement_time = GetTickCount ();
579 /* Consoles return button bits in a strange order:
580 least significant - Leftmost button
581 next - Rightmost button
582 next - Leftmost+1
583 next - Leftmost+2...
585 Assume emacs likes three button mice, so
586 Left == 0
587 Middle == 1
588 Right == 2
589 Others increase from there. */
591 #define NUM_TRANSLATED_MOUSE_BUTTONS 3
592 static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] =
594 0, 2, 1
597 static int
598 do_mouse_event (MOUSE_EVENT_RECORD *event,
599 struct input_event *emacs_ev)
601 static DWORD button_state = 0;
602 DWORD but_change, mask;
603 int i;
605 if (event->dwEventFlags == MOUSE_MOVED)
607 /* For movement events we just note that the mouse has moved
608 so that emacs will generate drag events. */
609 mouse_moved_to (event->dwMousePosition.X, event->dwMousePosition.Y);
610 return 0;
613 /* It looks like the console code sends us a mouse event with
614 dwButtonState == 0 when a window is activated. Ignore this case. */
615 if (event->dwButtonState == button_state)
616 return 0;
618 emacs_ev->kind = MOUSE_CLICK_EVENT;
620 /* Find out what button has changed state since the last button event. */
621 but_change = button_state ^ event->dwButtonState;
622 mask = 1;
623 for (i = 0; mask; i++, mask <<= 1)
624 if (but_change & mask)
626 if (i < NUM_TRANSLATED_MOUSE_BUTTONS)
627 emacs_ev->code = emacs_button_translation[i];
628 else
629 emacs_ev->code = i;
630 break;
633 button_state = event->dwButtonState;
634 emacs_ev->timestamp = GetTickCount ();
635 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, 0) |
636 ((event->dwButtonState & mask) ? down_modifier : up_modifier);
638 XSETFASTINT (emacs_ev->x, event->dwMousePosition.X);
639 XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y);
640 /* for Mule 2.2 (Based on Emacs 19.28 */
641 #ifdef MULE
642 XSET (emacs_ev->frame_or_window, Lisp_Frame, get_frame ());
643 #else
644 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
645 #endif
647 return 1;
650 static void
651 resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
653 FRAME_PTR f = get_frame ();
655 change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1, 0);
656 SET_FRAME_GARBAGED (f);
659 static void
660 maybe_generate_resize_event (void)
662 CONSOLE_SCREEN_BUFFER_INFO info;
663 FRAME_PTR f = get_frame ();
665 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
667 /* It is okay to call this unconditionally, since it will do nothing
668 if the size hasn't actually changed. */
669 change_frame_size (f,
670 1 + info.srWindow.Bottom - info.srWindow.Top,
671 1 + info.srWindow.Right - info.srWindow.Left,
672 0, 0, 0);
676 w32_console_read_socket (struct terminal *terminal,
677 int expected,
678 struct input_event *hold_quit)
680 int nev, ret = 0, add;
681 int isdead;
683 if (interrupt_input_blocked)
685 interrupt_input_pending = 1;
686 return -1;
689 interrupt_input_pending = 0;
690 BLOCK_INPUT;
692 for (;;)
694 nev = fill_queue (0);
695 if (nev <= 0)
697 /* If nev == -1, there was some kind of error
698 If nev == 0 then waitp must be zero and no events were available
699 so return. */
700 UNBLOCK_INPUT;
701 return nev;
704 while (nev > 0)
706 struct input_event inev;
708 EVENT_INIT (inev);
709 inev.kind = NO_EVENT;
710 inev.arg = Qnil;
712 switch (queue_ptr->EventType)
714 case KEY_EVENT:
715 add = key_event (&queue_ptr->Event.KeyEvent, &inev, &isdead);
716 if (add == -1) /* 95.7.25 by himi */
718 queue_ptr--;
719 add = 1;
721 if (add)
722 kbd_buffer_store_event_hold (&inev, hold_quit);
723 break;
725 case MOUSE_EVENT:
726 add = do_mouse_event (&queue_ptr->Event.MouseEvent, &inev);
727 if (add)
728 kbd_buffer_store_event_hold (&inev, hold_quit);
729 break;
731 case WINDOW_BUFFER_SIZE_EVENT:
732 if (w32_use_full_screen_buffer)
733 resize_event (&queue_ptr->Event.WindowBufferSizeEvent);
734 break;
736 case MENU_EVENT:
737 case FOCUS_EVENT:
738 /* Internal event types, ignored. */
739 break;
742 queue_ptr++;
743 nev--;
746 if (ret > 0 || expected == 0)
747 break;
750 /* We don't get told about changes in the window size (only the buffer
751 size, which we no longer care about), so we have to check it
752 periodically. */
753 if (!w32_use_full_screen_buffer)
754 maybe_generate_resize_event ();
756 UNBLOCK_INPUT;
757 return ret;