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