(make_lispy_event): Add string info to the event,
[emacs/old-mirror.git] / src / w32inevt.c
blobd2c37aa0b0b8fccef56824363dc2b44119e99ad0
1 /* Input event support for Emacs on the Microsoft W32 API.
2 Copyright (C) 1992, 1993, 1995 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 2, or (at your option)
9 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; 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.
21 Drew Bliss 01-Oct-93
22 Adapted from ntkbd.c by Tim Fleehart
26 #include "config.h"
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <windows.h>
32 #ifndef MOUSE_MOVED
33 #define MOUSE_MOVED 1
34 #endif
36 #include "lisp.h"
37 #include "keyboard.h"
38 #include "frame.h"
39 #include "blockinput.h"
40 #include "termhooks.h"
41 #include "w32heap.h"
42 #include "w32term.h"
44 /* stdin, from ntterm */
45 extern HANDLE keyboard_handle;
47 /* Info for last mouse motion */
48 static COORD movement_pos;
49 static DWORD movement_time;
51 /* from keyboard.c */
52 extern void reinvoke_input_signal (void);
54 /* from dispnew.c */
55 extern int change_frame_size (FRAME_PTR, int, int, int, int);
57 /* from w32console.c */
58 extern int w32_use_full_screen_buffer;
60 /* from w32fns.c */
61 extern Lisp_Object Vw32_alt_is_meta;
62 extern unsigned int map_keypad_keys (unsigned int, unsigned int);
64 /* from w32term */
65 extern Lisp_Object Vw32_capslock_is_shiftlock;
66 extern Lisp_Object Vw32_enable_caps_lock;
67 extern Lisp_Object Vw32_enable_num_lock;
68 extern Lisp_Object Vw32_recognize_altgr;
69 extern Lisp_Object Vw32_pass_lwindow_to_system;
70 extern Lisp_Object Vw32_pass_rwindow_to_system;
71 extern Lisp_Object Vw32_phantom_key_code;
72 extern Lisp_Object Vw32_lwindow_modifier;
73 extern Lisp_Object Vw32_rwindow_modifier;
74 extern Lisp_Object Vw32_apps_modifier;
75 extern Lisp_Object Vw32_scroll_lock_modifier;
76 extern unsigned int w32_key_to_modifier (int key);
78 /* Event queue */
79 #define EVENT_QUEUE_SIZE 50
80 static INPUT_RECORD event_queue[EVENT_QUEUE_SIZE];
81 static INPUT_RECORD *queue_ptr = event_queue, *queue_end = event_queue;
83 static int
84 fill_queue (BOOL block)
86 BOOL rc;
87 DWORD events_waiting;
89 if (queue_ptr < queue_end)
90 return queue_end-queue_ptr;
92 if (!block)
94 /* Check to see if there are some events to read before we try
95 because we can't block. */
96 if (!GetNumberOfConsoleInputEvents (keyboard_handle, &events_waiting))
97 return -1;
98 if (events_waiting == 0)
99 return 0;
102 rc = ReadConsoleInput (keyboard_handle, event_queue, EVENT_QUEUE_SIZE,
103 &events_waiting);
104 if (!rc)
105 return -1;
106 queue_ptr = event_queue;
107 queue_end = event_queue + events_waiting;
108 return (int) events_waiting;
111 /* In a generic, multi-frame world this should take a console handle
112 and return the frame for it
114 Right now, there's only one frame so return it. */
115 static FRAME_PTR
116 get_frame (void)
118 return SELECTED_FRAME ();
121 /* Translate console modifiers to emacs modifiers.
122 German keyboard support (Kai Morgan Zeise 2/18/95). */
124 w32_kbd_mods_to_emacs (DWORD mods, WORD key)
126 int retval = 0;
128 /* If we recognize right-alt and left-ctrl as AltGr, and it has been
129 pressed, first remove those modifiers. */
130 if (!NILP (Vw32_recognize_altgr)
131 && (mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
132 == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
133 mods &= ~ (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED);
135 if (mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
136 retval = ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier);
138 if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
140 retval |= ctrl_modifier;
141 if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
142 == (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
143 retval |= meta_modifier;
146 if (mods & LEFT_WIN_PRESSED)
147 retval |= w32_key_to_modifier (VK_LWIN);
148 if (mods & RIGHT_WIN_PRESSED)
149 retval |= w32_key_to_modifier (VK_RWIN);
150 if (mods & APPS_PRESSED)
151 retval |= w32_key_to_modifier (VK_APPS);
152 if (mods & SCROLLLOCK_ON)
153 retval |= w32_key_to_modifier (VK_SCROLL);
155 /* Just in case someone wanted the original behaviour, make it
156 optional by setting w32-capslock-is-shiftlock to t. */
157 if (NILP (Vw32_capslock_is_shiftlock)
158 /* Keys that should _not_ be affected by CapsLock. */
159 && ( (key == VK_BACK)
160 || (key == VK_TAB)
161 || (key == VK_CLEAR)
162 || (key == VK_RETURN)
163 || (key == VK_ESCAPE)
164 || ((key >= VK_SPACE) && (key <= VK_HELP))
165 || ((key >= VK_NUMPAD0) && (key <= VK_F24))
166 || ((key >= VK_NUMPAD_CLEAR) && (key <= VK_NUMPAD_DELETE))
169 /* Only consider shift state. */
170 if ((mods & SHIFT_PRESSED) != 0)
171 retval |= shift_modifier;
173 else
175 /* Ignore CapsLock state if not enabled. */
176 if (NILP (Vw32_enable_caps_lock))
177 mods &= ~CAPSLOCK_ON;
178 if ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) != 0)
179 retval |= shift_modifier;
182 return retval;
185 #if 0
186 /* Return nonzero if the virtual key is a dead key. */
187 static int
188 is_dead_key (int wparam)
190 unsigned int code = MapVirtualKey (wparam, 2);
192 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
193 return (code & 0x80008000) ? 1 : 0;
195 #endif
197 /* The return code indicates key code size. */
199 w32_kbd_patch_key (KEY_EVENT_RECORD *event)
201 unsigned int key_code = event->wVirtualKeyCode;
202 unsigned int mods = event->dwControlKeyState;
203 BYTE keystate[256];
204 static BYTE ansi_code[4];
205 static int isdead = 0;
207 if (isdead == 2)
209 event->uChar.AsciiChar = ansi_code[2];
210 isdead = 0;
211 return 1;
213 if (event->uChar.AsciiChar != 0)
214 return 1;
216 memset (keystate, 0, sizeof (keystate));
217 keystate[key_code] = 0x80;
218 if (mods & SHIFT_PRESSED)
219 keystate[VK_SHIFT] = 0x80;
220 if (mods & CAPSLOCK_ON)
221 keystate[VK_CAPITAL] = 1;
222 /* If we recognize right-alt and left-ctrl as AltGr, set the key
223 states accordingly before invoking ToAscii. */
224 if (!NILP (Vw32_recognize_altgr)
225 && (mods & LEFT_CTRL_PRESSED) && (mods & RIGHT_ALT_PRESSED))
227 keystate[VK_CONTROL] = 0x80;
228 keystate[VK_LCONTROL] = 0x80;
229 keystate[VK_MENU] = 0x80;
230 keystate[VK_RMENU] = 0x80;
233 #if 0
234 /* Because of an OS bug, ToAscii corrupts the stack when called to
235 convert a dead key in console mode on NT4. Unfortunately, trying
236 to check for dead keys using MapVirtualKey doesn't work either -
237 these functions apparently use internal information about keyboard
238 layout which doesn't get properly updated in console programs when
239 changing layout (though apparently it gets partly updated,
240 otherwise ToAscii wouldn't crash). */
241 if (is_dead_key (event->wVirtualKeyCode))
242 return 0;
243 #endif
245 /* On NT, call ToUnicode instead and then convert to the current
246 locale's default codepage. */
247 if (os_subtype == OS_NT)
249 WCHAR buf[128];
251 isdead = ToUnicode (event->wVirtualKeyCode, event->wVirtualScanCode,
252 keystate, buf, 128, 0);
253 if (isdead > 0)
255 char cp[20];
256 int cpId;
258 GetLocaleInfo (GetThreadLocale (),
259 LOCALE_IDEFAULTANSICODEPAGE, cp, 20);
260 cpId = atoi (cp);
261 isdead = WideCharToMultiByte (cpId, 0, buf, isdead,
262 ansi_code, 4, NULL, NULL);
264 else
265 isdead = 0;
267 else
269 isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode,
270 keystate, (LPWORD) ansi_code, 0);
273 if (isdead == 0)
274 return 0;
275 event->uChar.AsciiChar = ansi_code[0];
276 return isdead;
280 extern char *lispy_function_keys[];
282 static int faked_key = 0;
284 /* return code -1 means that event_queue_ptr won't be incremented.
285 In other word, this event makes two key codes. (by himi) */
286 int
287 key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
289 static int mod_key_state = 0;
290 int wParam;
292 *isdead = 0;
294 /* Skip key-up events. */
295 if (!event->bKeyDown)
297 switch (event->wVirtualKeyCode)
299 case VK_LWIN:
300 mod_key_state &= ~LEFT_WIN_PRESSED;
301 break;
302 case VK_RWIN:
303 mod_key_state &= ~RIGHT_WIN_PRESSED;
304 break;
305 case VK_APPS:
306 mod_key_state &= ~APPS_PRESSED;
307 break;
309 return 0;
312 /* Ignore keystrokes we fake ourself; see below. */
313 if (faked_key == event->wVirtualKeyCode)
315 faked_key = 0;
316 return 0;
319 /* To make it easier to debug this code, ignore modifier keys! */
320 switch (event->wVirtualKeyCode)
322 case VK_LWIN:
323 if (NILP (Vw32_pass_lwindow_to_system))
325 /* Prevent system from acting on keyup (which opens the Start
326 menu if no other key was pressed) by simulating a press of
327 Space which we will ignore. */
328 if ((mod_key_state & LEFT_WIN_PRESSED) == 0)
330 if (NUMBERP (Vw32_phantom_key_code))
331 faked_key = XUINT (Vw32_phantom_key_code) & 255;
332 else
333 faked_key = VK_SPACE;
334 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
337 mod_key_state |= LEFT_WIN_PRESSED;
338 if (!NILP (Vw32_lwindow_modifier))
339 return 0;
340 break;
341 case VK_RWIN:
342 if (NILP (Vw32_pass_rwindow_to_system))
344 if ((mod_key_state & RIGHT_WIN_PRESSED) == 0)
346 if (NUMBERP (Vw32_phantom_key_code))
347 faked_key = XUINT (Vw32_phantom_key_code) & 255;
348 else
349 faked_key = VK_SPACE;
350 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
353 mod_key_state |= RIGHT_WIN_PRESSED;
354 if (!NILP (Vw32_rwindow_modifier))
355 return 0;
356 break;
357 case VK_APPS:
358 mod_key_state |= APPS_PRESSED;
359 if (!NILP (Vw32_apps_modifier))
360 return 0;
361 break;
362 case VK_CAPITAL:
363 /* Decide whether to treat as modifier or function key. */
364 if (NILP (Vw32_enable_caps_lock))
365 goto disable_lock_key;
366 return 0;
367 case VK_NUMLOCK:
368 /* Decide whether to treat as modifier or function key. */
369 if (NILP (Vw32_enable_num_lock))
370 goto disable_lock_key;
371 return 0;
372 case VK_SCROLL:
373 /* Decide whether to treat as modifier or function key. */
374 if (NILP (Vw32_scroll_lock_modifier))
375 goto disable_lock_key;
376 return 0;
377 disable_lock_key:
378 /* Ensure the appropriate lock key state is off (and the
379 indicator light as well). */
380 wParam = event->wVirtualKeyCode;
381 if (GetAsyncKeyState (wParam) & 0x8000)
383 /* Fake another press of the relevant key. Apparently, this
384 really is the only way to turn off the indicator. */
385 faked_key = wParam;
386 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
387 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
388 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
389 KEYEVENTF_EXTENDEDKEY | 0, 0);
390 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
391 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
393 break;
394 case VK_MENU:
395 case VK_CONTROL:
396 case VK_SHIFT:
397 return 0;
398 case VK_CANCEL:
399 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
400 which is confusing for purposes of key binding; convert
401 VK_CANCEL events into VK_PAUSE events. */
402 event->wVirtualKeyCode = VK_PAUSE;
403 break;
404 case VK_PAUSE:
405 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
406 for purposes of key binding; convert these back into
407 VK_NUMLOCK events, at least when we want to see NumLock key
408 presses. (Note that there is never any possibility that
409 VK_PAUSE with Ctrl really is C-Pause as per above.) */
410 if (NILP (Vw32_enable_num_lock)
411 && (event->dwControlKeyState
412 & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0)
413 event->wVirtualKeyCode = VK_NUMLOCK;
414 break;
417 /* Recognize state of Windows and Apps keys. */
418 event->dwControlKeyState |= mod_key_state;
420 /* Distinguish numeric keypad keys from extended keys. */
421 event->wVirtualKeyCode =
422 map_keypad_keys (event->wVirtualKeyCode,
423 (event->dwControlKeyState & ENHANCED_KEY));
425 if (lispy_function_keys[event->wVirtualKeyCode] == 0)
427 emacs_ev->kind = ascii_keystroke;
429 if (!NILP (Vw32_recognize_altgr)
430 && (event->dwControlKeyState & LEFT_CTRL_PRESSED)
431 && (event->dwControlKeyState & RIGHT_ALT_PRESSED))
433 /* Don't try to interpret AltGr key chords; ToAscii seems not
434 to process them correctly. */
436 /* Handle key chords including any modifiers other than shift
437 directly, in order to preserve as much modifier information as
438 possible. */
439 else if (event->dwControlKeyState
440 & ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED
441 | RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED
442 | (!NILP (Vw32_lwindow_modifier) ? LEFT_WIN_PRESSED : 0)
443 | (!NILP (Vw32_rwindow_modifier) ? RIGHT_WIN_PRESSED : 0)
444 | (!NILP (Vw32_apps_modifier) ? APPS_PRESSED : 0)
445 | (!NILP (Vw32_scroll_lock_modifier) ? SCROLLLOCK_ON : 0)))
447 /* Don't translate modified alphabetic keystrokes, so the user
448 doesn't need to constantly switch layout to type control or
449 meta keystrokes when the normal layout translates
450 alphabetic characters to non-ascii characters. */
451 if ('A' <= event->wVirtualKeyCode && event->wVirtualKeyCode <= 'Z')
453 event->uChar.AsciiChar = event->wVirtualKeyCode;
454 if ((event->dwControlKeyState & SHIFT_PRESSED) == 0)
455 event->uChar.AsciiChar += ('a' - 'A');
457 /* Try to handle unrecognized keystrokes by determining the
458 base character (ie. translating the base key plus shift
459 modifier). */
460 else if (event->uChar.AsciiChar == 0)
461 w32_kbd_patch_key (event);
463 if (event->uChar.AsciiChar == 0)
464 return 0;
465 XSETINT (emacs_ev->code, event->uChar.AsciiChar);
467 else
469 emacs_ev->kind = non_ascii_keystroke;
470 XSETINT (emacs_ev->code, event->wVirtualKeyCode);
473 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
474 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState,
475 event->wVirtualKeyCode);
476 emacs_ev->timestamp = GetTickCount ();
477 return 1;
481 w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state)
483 int cur_state = (GetKeyState (vk_code) & 1);
485 if (NILP (new_state)
486 || (NUMBERP (new_state)
487 && ((XUINT (new_state)) & 1) != cur_state))
489 faked_key = vk_code;
491 keybd_event ((BYTE) vk_code,
492 (BYTE) MapVirtualKey (vk_code, 0),
493 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
494 keybd_event ((BYTE) vk_code,
495 (BYTE) MapVirtualKey (vk_code, 0),
496 KEYEVENTF_EXTENDEDKEY | 0, 0);
497 keybd_event ((BYTE) vk_code,
498 (BYTE) MapVirtualKey (vk_code, 0),
499 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
500 cur_state = !cur_state;
503 return cur_state;
506 /* Mouse position hook. */
507 void
508 w32_console_mouse_position (FRAME_PTR *f,
509 int insist,
510 Lisp_Object *bar_window,
511 enum scroll_bar_part *part,
512 Lisp_Object *x,
513 Lisp_Object *y,
514 unsigned long *time)
516 BLOCK_INPUT;
518 insist = insist;
520 *f = get_frame ();
521 *bar_window = Qnil;
522 *part = 0;
523 SELECTED_FRAME ()->mouse_moved = 0;
525 *x = movement_pos.X;
526 *y = movement_pos.Y;
527 *time = movement_time;
529 UNBLOCK_INPUT;
532 /* Remember mouse motion and notify emacs. */
533 static void
534 mouse_moved_to (int x, int y)
536 /* If we're in the same place, ignore it */
537 if (x != movement_pos.X || y != movement_pos.Y)
539 SELECTED_FRAME ()->mouse_moved = 1;
540 movement_pos.X = x;
541 movement_pos.Y = y;
542 movement_time = GetTickCount ();
546 /* Consoles return button bits in a strange order:
547 least significant - Leftmost button
548 next - Rightmost button
549 next - Leftmost+1
550 next - Leftmost+2...
552 Assume emacs likes three button mice, so
553 Left == 0
554 Middle == 1
555 Right == 2
556 Others increase from there. */
558 #define NUM_TRANSLATED_MOUSE_BUTTONS 3
559 static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] =
561 0, 2, 1
564 static int
565 do_mouse_event (MOUSE_EVENT_RECORD *event,
566 struct input_event *emacs_ev)
568 static DWORD button_state = 0;
569 DWORD but_change, mask;
570 int i;
572 if (event->dwEventFlags == MOUSE_MOVED)
574 /* For movement events we just note that the mouse has moved
575 so that emacs will generate drag events. */
576 mouse_moved_to (event->dwMousePosition.X, event->dwMousePosition.Y);
577 return 0;
580 /* It looks like the console code sends us a mouse event with
581 dwButtonState == 0 when a window is activated. Ignore this case. */
582 if (event->dwButtonState == button_state)
583 return 0;
585 emacs_ev->kind = mouse_click;
587 /* Find out what button has changed state since the last button event. */
588 but_change = button_state ^ event->dwButtonState;
589 mask = 1;
590 for (i = 0; mask; i++, mask <<= 1)
591 if (but_change & mask)
593 if (i < NUM_TRANSLATED_MOUSE_BUTTONS)
594 XSETINT (emacs_ev->code, emacs_button_translation[i]);
595 else
596 XSETINT (emacs_ev->code, i);
597 break;
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);
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
614 return 1;
617 static void
618 resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
620 FRAME_PTR f = get_frame ();
622 change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1);
623 SET_FRAME_GARBAGED (f);
626 static void
627 maybe_generate_resize_event ()
629 CONSOLE_SCREEN_BUFFER_INFO info;
630 FRAME_PTR f = get_frame ();
632 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
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);
642 int
643 w32_console_read_socket (int sd, struct input_event *bufp, int numchars,
644 int expected)
646 BOOL no_events = TRUE;
647 int nev, ret = 0, add;
648 int isdead;
650 if (interrupt_input_blocked)
652 interrupt_input_pending = 1;
653 return -1;
656 interrupt_input_pending = 0;
657 BLOCK_INPUT;
659 for (;;)
661 nev = fill_queue (0);
662 if (nev <= 0)
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;
671 while (nev > 0 && numchars > 0)
673 switch (queue_ptr->EventType)
675 case KEY_EVENT:
676 add = key_event (&queue_ptr->Event.KeyEvent, bufp, &isdead);
677 if (add == -1) /* 95.7.25 by himi */
679 queue_ptr--;
680 add = 1;
682 bufp += add;
683 ret += add;
684 numchars -= add;
685 break;
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;
694 case WINDOW_BUFFER_SIZE_EVENT:
695 if (w32_use_full_screen_buffer)
696 resize_event (&queue_ptr->Event.WindowBufferSizeEvent);
697 break;
699 case MENU_EVENT:
700 case FOCUS_EVENT:
701 /* Internal event types, ignored. */
702 break;
705 queue_ptr++;
706 nev--;
709 if (ret > 0 || expected == 0)
710 break;
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 ();
719 UNBLOCK_INPUT;
720 return ret;