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