Implement cygw32
[bpt/emacs.git] / src / w32inevt.c
CommitLineData
b46a6a83 1/* Input event support for Emacs on the Microsoft Windows API.
acaf905b 2 Copyright (C) 1992-1993, 1995, 2001-2012 Free Software Foundation, Inc.
6cdfb6e6 3
3b7ad313
EN
4This file is part of GNU Emacs.
5
9ec0b715 6GNU Emacs is free software: you can redistribute it and/or modify
3b7ad313 7it under the terms of the GNU General Public License as published by
9ec0b715
GM
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
3b7ad313
EN
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
9ec0b715 17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
6cdfb6e6 18
9ec0b715 19/*
6cdfb6e6
RS
20 Drew Bliss 01-Oct-93
21 Adapted from ntkbd.c by Tim Fleehart
22*/
23
24
4838e624 25#include <config.h>
6cdfb6e6
RS
26#include <stdio.h>
27#include <windows.h>
d7306fe6 28#include <setjmp.h>
6cdfb6e6 29
690e96a3
AI
30#ifndef MOUSE_MOVED
31#define MOUSE_MOVED 1
32#endif
33
6cdfb6e6 34#include "lisp.h"
690e96a3 35#include "keyboard.h"
6cdfb6e6 36#include "frame.h"
2165e881 37#include "dispextern.h"
f12fdf02 38#include "window.h"
6cdfb6e6
RS
39#include "blockinput.h"
40#include "termhooks.h"
42e3a361 41#include "termchar.h"
29a2c30f
GV
42#include "w32heap.h"
43#include "w32term.h"
01bd1b0d 44#include "w32inevt.h"
6cdfb6e6 45
7684e57b 46/* stdin, from w32console.c */
6cdfb6e6
RS
47extern HANDLE keyboard_handle;
48
6cdfb6e6
RS
49/* Info for last mouse motion */
50static COORD movement_pos;
9fbd6841 51static Time movement_time;
6cdfb6e6 52
7684e57b 53/* from w32fns.c */
29a2c30f 54extern unsigned int map_keypad_keys (unsigned int, unsigned int);
29a2c30f 55extern unsigned int w32_key_to_modifier (int key);
59131421 56
6cdfb6e6
RS
57/* Event queue */
58#define EVENT_QUEUE_SIZE 50
59static INPUT_RECORD event_queue[EVENT_QUEUE_SIZE];
60static INPUT_RECORD *queue_ptr = event_queue, *queue_end = event_queue;
61
7e233730
JR
62/* Temporarily store lead byte of DBCS input sequences. */
63static char dbcs_lead = 0;
64
01bd1b0d
EZ
65static inline BOOL
66w32_read_console_input (HANDLE h, INPUT_RECORD *rec, DWORD recsize,
67 DWORD *waiting)
68{
69 return (w32_console_unicode_input
70 ? ReadConsoleInputW (h, rec, recsize, waiting)
71 : ReadConsoleInputA (h, rec, recsize, waiting));
72}
73
0fda9b75
DC
74/* Set by w32_console_toggle_lock_key. */
75int faked_key;
76
177c0ea7 77static int
6cdfb6e6
RS
78fill_queue (BOOL block)
79{
80 BOOL rc;
81 DWORD events_waiting;
177c0ea7 82
6cdfb6e6
RS
83 if (queue_ptr < queue_end)
84 return queue_end-queue_ptr;
177c0ea7 85
6cdfb6e6
RS
86 if (!block)
87 {
88 /* Check to see if there are some events to read before we try
89 because we can't block. */
90 if (!GetNumberOfConsoleInputEvents (keyboard_handle, &events_waiting))
91 return -1;
92 if (events_waiting == 0)
93 return 0;
94 }
177c0ea7 95
01bd1b0d
EZ
96 rc = w32_read_console_input (keyboard_handle, event_queue, EVENT_QUEUE_SIZE,
97 &events_waiting);
6cdfb6e6
RS
98 if (!rc)
99 return -1;
100 queue_ptr = event_queue;
101 queue_end = event_queue + events_waiting;
102 return (int) events_waiting;
103}
104
105/* In a generic, multi-frame world this should take a console handle
106 and return the frame for it
107
108 Right now, there's only one frame so return it. */
177c0ea7 109static FRAME_PTR
6cdfb6e6
RS
110get_frame (void)
111{
4f4a5f69 112 return SELECTED_FRAME ();
6cdfb6e6
RS
113}
114
177c0ea7 115/* Translate console modifiers to emacs modifiers.
b02466e8 116 German keyboard support (Kai Morgan Zeise 2/18/95). */
b02466e8 117
b02466e8 118
29a2c30f
GV
119#if 0
120/* Return nonzero if the virtual key is a dead key. */
121static int
122is_dead_key (int wparam)
123{
124 unsigned int code = MapVirtualKey (wparam, 2);
125
126 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
127 return (code & 0x80008000) ? 1 : 0;
128}
129#endif
130
302fc036
EZ
131/* The return code indicates key code size. cpID is the codepage to
132 use for translation to Unicode; -1 means use the current console
133 input codepage. */
407c1745 134
6cdfb6e6 135
177c0ea7 136/* return code -1 means that event_queue_ptr won't be incremented.
daf38066 137 In other word, this event makes two key codes. (by himi) */
24f981c9 138static int
59131421 139key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
6cdfb6e6 140{
29a2c30f
GV
141 static int mod_key_state = 0;
142 int wParam;
59131421
GV
143
144 *isdead = 0;
29a2c30f 145
6cdfb6e6 146 /* Skip key-up events. */
407c1745 147 if (!event->bKeyDown)
6cdfb6e6 148 {
29a2c30f
GV
149 switch (event->wVirtualKeyCode)
150 {
151 case VK_LWIN:
152 mod_key_state &= ~LEFT_WIN_PRESSED;
153 break;
154 case VK_RWIN:
155 mod_key_state &= ~RIGHT_WIN_PRESSED;
156 break;
157 case VK_APPS:
158 mod_key_state &= ~APPS_PRESSED;
159 break;
160 }
6cdfb6e6
RS
161 return 0;
162 }
b02466e8 163
29a2c30f
GV
164 /* Ignore keystrokes we fake ourself; see below. */
165 if (faked_key == event->wVirtualKeyCode)
6cdfb6e6 166 {
29a2c30f 167 faked_key = 0;
6cdfb6e6
RS
168 return 0;
169 }
29a2c30f
GV
170
171 /* To make it easier to debug this code, ignore modifier keys! */
172 switch (event->wVirtualKeyCode)
6cdfb6e6 173 {
29a2c30f
GV
174 case VK_LWIN:
175 if (NILP (Vw32_pass_lwindow_to_system))
176 {
177 /* Prevent system from acting on keyup (which opens the Start
178 menu if no other key was pressed) by simulating a press of
179 Space which we will ignore. */
180 if ((mod_key_state & LEFT_WIN_PRESSED) == 0)
181 {
9ddef9c4
GV
182 if (NUMBERP (Vw32_phantom_key_code))
183 faked_key = XUINT (Vw32_phantom_key_code) & 255;
184 else
185 faked_key = VK_SPACE;
186 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
29a2c30f
GV
187 }
188 }
189 mod_key_state |= LEFT_WIN_PRESSED;
190 if (!NILP (Vw32_lwindow_modifier))
daf38066 191 return 0;
29a2c30f
GV
192 break;
193 case VK_RWIN:
194 if (NILP (Vw32_pass_rwindow_to_system))
195 {
196 if ((mod_key_state & RIGHT_WIN_PRESSED) == 0)
197 {
9ddef9c4
GV
198 if (NUMBERP (Vw32_phantom_key_code))
199 faked_key = XUINT (Vw32_phantom_key_code) & 255;
200 else
201 faked_key = VK_SPACE;
202 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
29a2c30f
GV
203 }
204 }
205 mod_key_state |= RIGHT_WIN_PRESSED;
206 if (!NILP (Vw32_rwindow_modifier))
207 return 0;
208 break;
209 case VK_APPS:
210 mod_key_state |= APPS_PRESSED;
211 if (!NILP (Vw32_apps_modifier))
212 return 0;
213 break;
214 case VK_CAPITAL:
215 /* Decide whether to treat as modifier or function key. */
216 if (NILP (Vw32_enable_caps_lock))
217 goto disable_lock_key;
218 return 0;
219 case VK_NUMLOCK:
220 /* Decide whether to treat as modifier or function key. */
221 if (NILP (Vw32_enable_num_lock))
222 goto disable_lock_key;
223 return 0;
224 case VK_SCROLL:
225 /* Decide whether to treat as modifier or function key. */
226 if (NILP (Vw32_scroll_lock_modifier))
227 goto disable_lock_key;
228 return 0;
229 disable_lock_key:
230 /* Ensure the appropriate lock key state is off (and the
231 indicator light as well). */
232 wParam = event->wVirtualKeyCode;
233 if (GetAsyncKeyState (wParam) & 0x8000)
234 {
235 /* Fake another press of the relevant key. Apparently, this
236 really is the only way to turn off the indicator. */
237 faked_key = wParam;
238 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
239 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
240 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
241 KEYEVENTF_EXTENDEDKEY | 0, 0);
242 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
243 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
244 }
245 break;
246 case VK_MENU:
247 case VK_CONTROL:
248 case VK_SHIFT:
249 return 0;
9ddef9c4
GV
250 case VK_CANCEL:
251 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
252 which is confusing for purposes of key binding; convert
253 VK_CANCEL events into VK_PAUSE events. */
254 event->wVirtualKeyCode = VK_PAUSE;
255 break;
256 case VK_PAUSE:
257 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
258 for purposes of key binding; convert these back into
259 VK_NUMLOCK events, at least when we want to see NumLock key
260 presses. (Note that there is never any possibility that
261 VK_PAUSE with Ctrl really is C-Pause as per above.) */
262 if (NILP (Vw32_enable_num_lock)
263 && (event->dwControlKeyState
264 & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0)
265 event->wVirtualKeyCode = VK_NUMLOCK;
266 break;
6cdfb6e6 267 }
29a2c30f
GV
268
269 /* Recognize state of Windows and Apps keys. */
270 event->dwControlKeyState |= mod_key_state;
271
272 /* Distinguish numeric keypad keys from extended keys. */
273 event->wVirtualKeyCode =
274 map_keypad_keys (event->wVirtualKeyCode,
275 (event->dwControlKeyState & ENHANCED_KEY));
276
277 if (lispy_function_keys[event->wVirtualKeyCode] == 0)
daf38066 278 {
29a2c30f
GV
279 if (!NILP (Vw32_recognize_altgr)
280 && (event->dwControlKeyState & LEFT_CTRL_PRESSED)
281 && (event->dwControlKeyState & RIGHT_ALT_PRESSED))
daf38066 282 {
29a2c30f
GV
283 /* Don't try to interpret AltGr key chords; ToAscii seems not
284 to process them correctly. */
daf38066 285 }
29a2c30f
GV
286 /* Handle key chords including any modifiers other than shift
287 directly, in order to preserve as much modifier information as
288 possible. */
289 else if (event->dwControlKeyState
290 & ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED
291 | RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED
292 | (!NILP (Vw32_lwindow_modifier) ? LEFT_WIN_PRESSED : 0)
293 | (!NILP (Vw32_rwindow_modifier) ? RIGHT_WIN_PRESSED : 0)
294 | (!NILP (Vw32_apps_modifier) ? APPS_PRESSED : 0)
295 | (!NILP (Vw32_scroll_lock_modifier) ? SCROLLLOCK_ON : 0)))
296 {
297 /* Don't translate modified alphabetic keystrokes, so the user
298 doesn't need to constantly switch layout to type control or
299 meta keystrokes when the normal layout translates
300 alphabetic characters to non-ascii characters. */
301 if ('A' <= event->wVirtualKeyCode && event->wVirtualKeyCode <= 'Z')
302 {
303 event->uChar.AsciiChar = event->wVirtualKeyCode;
304 if ((event->dwControlKeyState & SHIFT_PRESSED) == 0)
305 event->uChar.AsciiChar += ('a' - 'A');
306 }
307 /* Try to handle unrecognized keystrokes by determining the
308 base character (ie. translating the base key plus shift
309 modifier). */
310 else if (event->uChar.AsciiChar == 0)
302fc036 311 w32_kbd_patch_key (event, -1);
29a2c30f 312 }
7e233730 313
29a2c30f 314 if (event->uChar.AsciiChar == 0)
7e233730
JR
315 {
316 emacs_ev->kind = NO_EVENT;
317 return 0;
318 }
af93af83 319 else if (event->uChar.AsciiChar > 0)
7e233730 320 {
01bd1b0d 321 /* Pure ASCII characters < 128. */
7e233730
JR
322 emacs_ev->kind = ASCII_KEYSTROKE_EVENT;
323 emacs_ev->code = event->uChar.AsciiChar;
324 }
01bd1b0d
EZ
325 else if (event->uChar.UnicodeChar > 0
326 && w32_console_unicode_input)
7e233730 327 {
01bd1b0d
EZ
328 /* Unicode codepoint; only valid if we are using Unicode
329 console input mode. */
7e233730
JR
330 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
331 emacs_ev->code = event->uChar.UnicodeChar;
332 }
333 else
334 {
01bd1b0d
EZ
335 /* Fallback handling of non-ASCII characters for non-Unicode
336 versions of Windows, and for non-Unicode input on NT
337 family of Windows. Only characters in the current
338 console codepage are supported by this fallback. */
7e233730
JR
339 wchar_t code;
340 char dbcs[2];
7e233730
JR
341 int cpId;
342
01bd1b0d
EZ
343 /* Get the current console input codepage to interpret this
344 key with. Note that the system defaults for the OEM
345 codepage could have been changed by calling SetConsoleCP
346 or w32-set-console-codepage, so using GetLocaleInfo to
347 get LOCALE_IDEFAULTCODEPAGE is not TRT here. */
348 cpId = GetConsoleCP ();
7e233730
JR
349
350 dbcs[0] = dbcs_lead;
351 dbcs[1] = event->uChar.AsciiChar;
352 if (dbcs_lead)
353 {
354 dbcs_lead = 0;
355 if (!MultiByteToWideChar (cpId, 0, dbcs, 2, &code, 1))
356 {
357 /* Garbage */
358 DebPrint (("Invalid DBCS sequence: %d %d\n",
359 dbcs[0], dbcs[1]));
dd5de7c6 360 emacs_ev->kind = NO_EVENT;
7e233730
JR
361 }
362 }
363 else if (IsDBCSLeadByteEx (cpId, dbcs[1]))
364 {
365 dbcs_lead = dbcs[1];
dd5de7c6 366 emacs_ev->kind = NO_EVENT;
7e233730
JR
367 }
368 else
369 {
370 if (!MultiByteToWideChar (cpId, 0, &dbcs[1], 1, &code, 1))
371 {
372 /* Garbage */
373 DebPrint (("Invalid character: %d\n", dbcs[1]));
dd5de7c6 374 emacs_ev->kind = NO_EVENT;
7e233730
JR
375 }
376 }
377 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
378 emacs_ev->code = code;
379 }
daf38066 380 }
6cdfb6e6
RS
381 else
382 {
01bd1b0d 383 /* Function keys and other non-character keys. */
e43bd4f5 384 emacs_ev->kind = NON_ASCII_KEYSTROKE_EVENT;
e3ec1dce 385 emacs_ev->code = event->wVirtualKeyCode;
6cdfb6e6 386 }
29a2c30f 387
b02466e8 388 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
59131421
GV
389 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState,
390 event->wVirtualKeyCode);
6cdfb6e6
RS
391 emacs_ev->timestamp = GetTickCount ();
392 return 1;
393}
394
395/* Mouse position hook. */
177c0ea7 396void
81e3e4fd 397w32_console_mouse_position (FRAME_PTR *f,
81e3e4fd 398 int insist,
81e3e4fd
GV
399 Lisp_Object *bar_window,
400 enum scroll_bar_part *part,
401 Lisp_Object *x,
402 Lisp_Object *y,
9fbd6841 403 Time *time)
6cdfb6e6
RS
404{
405 BLOCK_INPUT;
407c1745 406
b02466e8
KH
407 insist = insist;
408
6cdfb6e6
RS
409 *f = get_frame ();
410 *bar_window = Qnil;
411 *part = 0;
4f4a5f69 412 SELECTED_FRAME ()->mouse_moved = 0;
177c0ea7 413
ed3751c8
JB
414 XSETINT (*x, movement_pos.X);
415 XSETINT (*y, movement_pos.Y);
6cdfb6e6 416 *time = movement_time;
177c0ea7 417
6cdfb6e6
RS
418 UNBLOCK_INPUT;
419}
420
42e3a361 421/* Remember mouse motion and notify emacs. */
177c0ea7 422static void
6cdfb6e6
RS
423mouse_moved_to (int x, int y)
424{
eb3f6f01 425 /* If we're in the same place, ignore it. */
6cdfb6e6
RS
426 if (x != movement_pos.X || y != movement_pos.Y)
427 {
42e3a361 428 SELECTED_FRAME ()->mouse_moved = 1;
6cdfb6e6
RS
429 movement_pos.X = x;
430 movement_pos.Y = y;
431 movement_time = GetTickCount ();
432 }
433}
434
435/* Consoles return button bits in a strange order:
436 least significant - Leftmost button
437 next - Rightmost button
438 next - Leftmost+1
439 next - Leftmost+2...
440
441 Assume emacs likes three button mice, so
442 Left == 0
443 Middle == 1
444 Right == 2
445 Others increase from there. */
446
1f2fca4b
JR
447#define NUM_TRANSLATED_MOUSE_BUTTONS 3
448static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] =
6cdfb6e6 449{
1f2fca4b 450 0, 2, 1
6cdfb6e6
RS
451};
452
177c0ea7 453static int
6cdfb6e6
RS
454do_mouse_event (MOUSE_EVENT_RECORD *event,
455 struct input_event *emacs_ev)
456{
457 static DWORD button_state = 0;
f12fdf02 458 static Lisp_Object last_mouse_window;
6cdfb6e6
RS
459 DWORD but_change, mask;
460 int i;
177c0ea7 461
6cdfb6e6
RS
462 if (event->dwEventFlags == MOUSE_MOVED)
463 {
42e3a361
EZ
464 FRAME_PTR f = SELECTED_FRAME ();
465 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
f12fdf02 466 int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y;
42e3a361 467
f12fdf02 468 mouse_moved_to (mx, my);
42e3a361
EZ
469
470 if (f->mouse_moved)
471 {
472 if (hlinfo->mouse_face_hidden)
473 {
474 hlinfo->mouse_face_hidden = 0;
475 clear_mouse_face (hlinfo);
476 }
477
f12fdf02
EZ
478 /* Generate SELECT_WINDOW_EVENTs when needed. */
479 if (!NILP (Vmouse_autoselect_window))
480 {
481 Lisp_Object mouse_window = window_from_coordinates (f, mx, my,
482 0, 0);
483 /* A window will be selected only when it is not
484 selected now, and the last mouse movement event was
485 not in it. A minibuffer window will be selected iff
486 it is active. */
487 if (WINDOWP (mouse_window)
488 && !EQ (mouse_window, last_mouse_window)
489 && !EQ (mouse_window, selected_window))
490 {
491 struct input_event event;
492
493 EVENT_INIT (event);
494 event.kind = SELECT_WINDOW_EVENT;
495 event.frame_or_window = mouse_window;
496 event.arg = Qnil;
497 event.timestamp = movement_time;
498 kbd_buffer_store_event (&event);
499 }
500 last_mouse_window = mouse_window;
501 }
502 else
503 last_mouse_window = Qnil;
c4aeb92a
EZ
504
505 previous_help_echo_string = help_echo_string;
506 help_echo_string = help_echo_object = help_echo_window = Qnil;
507 help_echo_pos = -1;
508 note_mouse_highlight (f, mx, my);
509 /* If the contents of the global variable help_echo has
510 changed (inside note_mouse_highlight), generate a HELP_EVENT. */
511 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
512 gen_help_event (help_echo_string, selected_frame, help_echo_window,
513 help_echo_object, help_echo_pos);
42e3a361 514 }
6cdfb6e6
RS
515 return 0;
516 }
177c0ea7 517
6cdfb6e6
RS
518 /* It looks like the console code sends us a mouse event with
519 dwButtonState == 0 when a window is activated. Ignore this case. */
520 if (event->dwButtonState == button_state)
521 return 0;
177c0ea7 522
e43bd4f5 523 emacs_ev->kind = MOUSE_CLICK_EVENT;
177c0ea7 524
6cdfb6e6
RS
525 /* Find out what button has changed state since the last button event. */
526 but_change = button_state ^ event->dwButtonState;
527 mask = 1;
1f2fca4b 528 for (i = 0; mask; i++, mask <<= 1)
6cdfb6e6
RS
529 if (but_change & mask)
530 {
1f2fca4b 531 if (i < NUM_TRANSLATED_MOUSE_BUTTONS)
e3ec1dce 532 emacs_ev->code = emacs_button_translation[i];
1f2fca4b 533 else
e3ec1dce 534 emacs_ev->code = i;
6cdfb6e6
RS
535 break;
536 }
537
6cdfb6e6
RS
538 button_state = event->dwButtonState;
539 emacs_ev->timestamp = GetTickCount ();
59131421 540 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, 0) |
6cdfb6e6 541 ((event->dwButtonState & mask) ? down_modifier : up_modifier);
177c0ea7 542
9e539a3c
KH
543 XSETFASTINT (emacs_ev->x, event->dwMousePosition.X);
544 XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y);
daf38066
GV
545/* for Mule 2.2 (Based on Emacs 19.28 */
546#ifdef MULE
547 XSET (emacs_ev->frame_or_window, Lisp_Frame, get_frame ());
548#else
b02466e8 549 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
daf38066 550#endif
177c0ea7 551
6cdfb6e6
RS
552 return 1;
553}
554
177c0ea7 555static void
6cdfb6e6
RS
556resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
557{
558 FRAME_PTR f = get_frame ();
177c0ea7 559
8d59c5ed 560 change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1, 0);
6cdfb6e6
RS
561 SET_FRAME_GARBAGED (f);
562}
563
b7b97897 564static void
b56ceb92 565maybe_generate_resize_event (void)
b7b97897
AI
566{
567 CONSOLE_SCREEN_BUFFER_INFO info;
568 FRAME_PTR f = get_frame ();
569
570 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
571
572 /* It is okay to call this unconditionally, since it will do nothing
573 if the size hasn't actually changed. */
574 change_frame_size (f,
575 1 + info.srWindow.Bottom - info.srWindow.Top,
576 1 + info.srWindow.Right - info.srWindow.Left,
8d59c5ed 577 0, 0, 0);
b7b97897
AI
578}
579
177c0ea7 580int
9e511e9c
JR
581w32_console_read_socket (struct terminal *terminal,
582 int expected,
583 struct input_event *hold_quit)
6cdfb6e6 584{
6cdfb6e6 585 int nev, ret = 0, add;
59131421
GV
586 int isdead;
587
6cdfb6e6
RS
588 if (interrupt_input_blocked)
589 {
590 interrupt_input_pending = 1;
591 return -1;
592 }
177c0ea7 593
6cdfb6e6
RS
594 interrupt_input_pending = 0;
595 BLOCK_INPUT;
177c0ea7 596
6cdfb6e6
RS
597 for (;;)
598 {
06c2c73d 599 nev = fill_queue (0);
6cdfb6e6
RS
600 if (nev <= 0)
601 {
602 /* If nev == -1, there was some kind of error
603 If nev == 0 then waitp must be zero and no events were available
604 so return. */
605 UNBLOCK_INPUT;
606 return nev;
607 }
608
9cd31aaf 609 while (nev > 0)
6cdfb6e6 610 {
9cd31aaf
KS
611 struct input_event inev;
612
613 EVENT_INIT (inev);
614 inev.kind = NO_EVENT;
615 inev.arg = Qnil;
616
6cdfb6e6
RS
617 switch (queue_ptr->EventType)
618 {
619 case KEY_EVENT:
9cd31aaf 620 add = key_event (&queue_ptr->Event.KeyEvent, &inev, &isdead);
daf38066 621 if (add == -1) /* 95.7.25 by himi */
177c0ea7 622 {
daf38066
GV
623 queue_ptr--;
624 add = 1;
625 }
9cd31aaf
KS
626 if (add)
627 kbd_buffer_store_event_hold (&inev, hold_quit);
6cdfb6e6
RS
628 break;
629
630 case MOUSE_EVENT:
9cd31aaf
KS
631 add = do_mouse_event (&queue_ptr->Event.MouseEvent, &inev);
632 if (add)
633 kbd_buffer_store_event_hold (&inev, hold_quit);
6cdfb6e6
RS
634 break;
635
636 case WINDOW_BUFFER_SIZE_EVENT:
d44c074d
AI
637 if (w32_use_full_screen_buffer)
638 resize_event (&queue_ptr->Event.WindowBufferSizeEvent);
6cdfb6e6 639 break;
177c0ea7 640
6cdfb6e6
RS
641 case MENU_EVENT:
642 case FOCUS_EVENT:
643 /* Internal event types, ignored. */
644 break;
645 }
177c0ea7 646
6cdfb6e6
RS
647 queue_ptr++;
648 nev--;
649 }
650
651 if (ret > 0 || expected == 0)
652 break;
653 }
b7b97897
AI
654
655 /* We don't get told about changes in the window size (only the buffer
656 size, which we no longer care about), so we have to check it
657 periodically. */
d44c074d
AI
658 if (!w32_use_full_screen_buffer)
659 maybe_generate_resize_event ();
b7b97897 660
6cdfb6e6
RS
661 UNBLOCK_INPUT;
662 return ret;
663}