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