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