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