* vc/vc-hooks.el (vc-before-save): Clear cache if file has been
[emacs.git] / src / w32inevt.c
bloba85fdbbe43570e7e5821b6051f752fd9f23f266c
1 /* Input event support for Emacs on the Microsoft W32 API.
2 Copyright (C) 1992-1993, 1995, 2001-2012 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 3 of the License, or
9 (at your option) 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. If not, see <http://www.gnu.org/licenses/>. */
20 Drew Bliss 01-Oct-93
21 Adapted from ntkbd.c by Tim Fleehart
25 #include <config.h>
26 #include <stdio.h>
27 #include <windows.h>
28 #include <setjmp.h>
30 #ifndef MOUSE_MOVED
31 #define MOUSE_MOVED 1
32 #endif
34 #include "lisp.h"
35 #include "keyboard.h"
36 #include "frame.h"
37 #include "dispextern.h"
38 #include "window.h"
39 #include "blockinput.h"
40 #include "termhooks.h"
41 #include "termchar.h"
42 #include "w32heap.h"
43 #include "w32term.h"
45 /* stdin, from w32console.c */
46 extern HANDLE keyboard_handle;
48 /* Info for last mouse motion */
49 static COORD movement_pos;
50 static Time movement_time;
52 /* from w32fns.c */
53 extern unsigned int map_keypad_keys (unsigned int, unsigned int);
54 extern unsigned int w32_key_to_modifier (int key);
56 /* Event queue */
57 #define EVENT_QUEUE_SIZE 50
58 static INPUT_RECORD event_queue[EVENT_QUEUE_SIZE];
59 static INPUT_RECORD *queue_ptr = event_queue, *queue_end = event_queue;
61 /* Temporarily store lead byte of DBCS input sequences. */
62 static char dbcs_lead = 0;
64 static int
65 fill_queue (BOOL block)
67 BOOL rc;
68 DWORD events_waiting;
70 if (queue_ptr < queue_end)
71 return queue_end-queue_ptr;
73 if (!block)
75 /* Check to see if there are some events to read before we try
76 because we can't block. */
77 if (!GetNumberOfConsoleInputEvents (keyboard_handle, &events_waiting))
78 return -1;
79 if (events_waiting == 0)
80 return 0;
83 rc = ReadConsoleInput (keyboard_handle, event_queue, EVENT_QUEUE_SIZE,
84 &events_waiting);
85 if (!rc)
86 return -1;
87 queue_ptr = event_queue;
88 queue_end = event_queue + events_waiting;
89 return (int) events_waiting;
92 /* In a generic, multi-frame world this should take a console handle
93 and return the frame for it
95 Right now, there's only one frame so return it. */
96 static FRAME_PTR
97 get_frame (void)
99 return SELECTED_FRAME ();
102 /* Translate console modifiers to emacs modifiers.
103 German keyboard support (Kai Morgan Zeise 2/18/95). */
105 w32_kbd_mods_to_emacs (DWORD mods, WORD key)
107 int retval = 0;
109 /* If we recognize right-alt and left-ctrl as AltGr, and it has been
110 pressed, first remove those modifiers. */
111 if (!NILP (Vw32_recognize_altgr)
112 && (mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
113 == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
114 mods &= ~ (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED);
116 if (mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
117 retval = ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier);
119 if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
121 retval |= ctrl_modifier;
122 if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
123 == (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
124 retval |= meta_modifier;
127 if (mods & LEFT_WIN_PRESSED)
128 retval |= w32_key_to_modifier (VK_LWIN);
129 if (mods & RIGHT_WIN_PRESSED)
130 retval |= w32_key_to_modifier (VK_RWIN);
131 if (mods & APPS_PRESSED)
132 retval |= w32_key_to_modifier (VK_APPS);
133 if (mods & SCROLLLOCK_ON)
134 retval |= w32_key_to_modifier (VK_SCROLL);
136 /* Just in case someone wanted the original behavior, make it
137 optional by setting w32-capslock-is-shiftlock to t. */
138 if (NILP (Vw32_capslock_is_shiftlock)
139 /* Keys that should _not_ be affected by CapsLock. */
140 && ( (key == VK_BACK)
141 || (key == VK_TAB)
142 || (key == VK_CLEAR)
143 || (key == VK_RETURN)
144 || (key == VK_ESCAPE)
145 || ((key >= VK_SPACE) && (key <= VK_HELP))
146 || ((key >= VK_NUMPAD0) && (key <= VK_F24))
147 || ((key >= VK_NUMPAD_CLEAR) && (key <= VK_NUMPAD_DELETE))
150 /* Only consider shift state. */
151 if ((mods & SHIFT_PRESSED) != 0)
152 retval |= shift_modifier;
154 else
156 /* Ignore CapsLock state if not enabled. */
157 if (NILP (Vw32_enable_caps_lock))
158 mods &= ~CAPSLOCK_ON;
159 if ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) != 0)
160 retval |= shift_modifier;
163 return retval;
166 #if 0
167 /* Return nonzero if the virtual key is a dead key. */
168 static int
169 is_dead_key (int wparam)
171 unsigned int code = MapVirtualKey (wparam, 2);
173 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
174 return (code & 0x80008000) ? 1 : 0;
176 #endif
178 /* The return code indicates key code size. */
180 w32_kbd_patch_key (KEY_EVENT_RECORD *event)
182 unsigned int key_code = event->wVirtualKeyCode;
183 unsigned int mods = event->dwControlKeyState;
184 BYTE keystate[256];
185 static BYTE ansi_code[4];
186 static int isdead = 0;
188 if (isdead == 2)
190 event->uChar.AsciiChar = ansi_code[2];
191 isdead = 0;
192 return 1;
194 if (event->uChar.AsciiChar != 0)
195 return 1;
197 memset (keystate, 0, sizeof (keystate));
198 keystate[key_code] = 0x80;
199 if (mods & SHIFT_PRESSED)
200 keystate[VK_SHIFT] = 0x80;
201 if (mods & CAPSLOCK_ON)
202 keystate[VK_CAPITAL] = 1;
203 /* If we recognize right-alt and left-ctrl as AltGr, set the key
204 states accordingly before invoking ToAscii. */
205 if (!NILP (Vw32_recognize_altgr)
206 && (mods & LEFT_CTRL_PRESSED) && (mods & RIGHT_ALT_PRESSED))
208 keystate[VK_CONTROL] = 0x80;
209 keystate[VK_LCONTROL] = 0x80;
210 keystate[VK_MENU] = 0x80;
211 keystate[VK_RMENU] = 0x80;
214 #if 0
215 /* Because of an OS bug, ToAscii corrupts the stack when called to
216 convert a dead key in console mode on NT4. Unfortunately, trying
217 to check for dead keys using MapVirtualKey doesn't work either -
218 these functions apparently use internal information about keyboard
219 layout which doesn't get properly updated in console programs when
220 changing layout (though apparently it gets partly updated,
221 otherwise ToAscii wouldn't crash). */
222 if (is_dead_key (event->wVirtualKeyCode))
223 return 0;
224 #endif
226 /* On NT, call ToUnicode instead and then convert to the current
227 locale's default codepage. */
228 if (os_subtype == OS_NT)
230 WCHAR buf[128];
232 isdead = ToUnicode (event->wVirtualKeyCode, event->wVirtualScanCode,
233 keystate, buf, 128, 0);
234 if (isdead > 0)
236 char cp[20];
237 int cpId;
239 event->uChar.UnicodeChar = buf[isdead - 1];
241 GetLocaleInfo (GetThreadLocale (),
242 LOCALE_IDEFAULTANSICODEPAGE, cp, 20);
243 cpId = atoi (cp);
244 isdead = WideCharToMultiByte (cpId, 0, buf, isdead,
245 ansi_code, 4, NULL, NULL);
247 else
248 isdead = 0;
250 else
252 isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode,
253 keystate, (LPWORD) ansi_code, 0);
256 if (isdead == 0)
257 return 0;
258 event->uChar.AsciiChar = ansi_code[0];
259 return isdead;
263 static int faked_key = 0;
265 /* return code -1 means that event_queue_ptr won't be incremented.
266 In other word, this event makes two key codes. (by himi) */
267 static int
268 key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
270 static int mod_key_state = 0;
271 int wParam;
273 *isdead = 0;
275 /* Skip key-up events. */
276 if (!event->bKeyDown)
278 switch (event->wVirtualKeyCode)
280 case VK_LWIN:
281 mod_key_state &= ~LEFT_WIN_PRESSED;
282 break;
283 case VK_RWIN:
284 mod_key_state &= ~RIGHT_WIN_PRESSED;
285 break;
286 case VK_APPS:
287 mod_key_state &= ~APPS_PRESSED;
288 break;
290 return 0;
293 /* Ignore keystrokes we fake ourself; see below. */
294 if (faked_key == event->wVirtualKeyCode)
296 faked_key = 0;
297 return 0;
300 /* To make it easier to debug this code, ignore modifier keys! */
301 switch (event->wVirtualKeyCode)
303 case VK_LWIN:
304 if (NILP (Vw32_pass_lwindow_to_system))
306 /* Prevent system from acting on keyup (which opens the Start
307 menu if no other key was pressed) by simulating a press of
308 Space which we will ignore. */
309 if ((mod_key_state & LEFT_WIN_PRESSED) == 0)
311 if (NUMBERP (Vw32_phantom_key_code))
312 faked_key = XUINT (Vw32_phantom_key_code) & 255;
313 else
314 faked_key = VK_SPACE;
315 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
318 mod_key_state |= LEFT_WIN_PRESSED;
319 if (!NILP (Vw32_lwindow_modifier))
320 return 0;
321 break;
322 case VK_RWIN:
323 if (NILP (Vw32_pass_rwindow_to_system))
325 if ((mod_key_state & RIGHT_WIN_PRESSED) == 0)
327 if (NUMBERP (Vw32_phantom_key_code))
328 faked_key = XUINT (Vw32_phantom_key_code) & 255;
329 else
330 faked_key = VK_SPACE;
331 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
334 mod_key_state |= RIGHT_WIN_PRESSED;
335 if (!NILP (Vw32_rwindow_modifier))
336 return 0;
337 break;
338 case VK_APPS:
339 mod_key_state |= APPS_PRESSED;
340 if (!NILP (Vw32_apps_modifier))
341 return 0;
342 break;
343 case VK_CAPITAL:
344 /* Decide whether to treat as modifier or function key. */
345 if (NILP (Vw32_enable_caps_lock))
346 goto disable_lock_key;
347 return 0;
348 case VK_NUMLOCK:
349 /* Decide whether to treat as modifier or function key. */
350 if (NILP (Vw32_enable_num_lock))
351 goto disable_lock_key;
352 return 0;
353 case VK_SCROLL:
354 /* Decide whether to treat as modifier or function key. */
355 if (NILP (Vw32_scroll_lock_modifier))
356 goto disable_lock_key;
357 return 0;
358 disable_lock_key:
359 /* Ensure the appropriate lock key state is off (and the
360 indicator light as well). */
361 wParam = event->wVirtualKeyCode;
362 if (GetAsyncKeyState (wParam) & 0x8000)
364 /* Fake another press of the relevant key. Apparently, this
365 really is the only way to turn off the indicator. */
366 faked_key = wParam;
367 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
368 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
369 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
370 KEYEVENTF_EXTENDEDKEY | 0, 0);
371 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
372 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
374 break;
375 case VK_MENU:
376 case VK_CONTROL:
377 case VK_SHIFT:
378 return 0;
379 case VK_CANCEL:
380 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
381 which is confusing for purposes of key binding; convert
382 VK_CANCEL events into VK_PAUSE events. */
383 event->wVirtualKeyCode = VK_PAUSE;
384 break;
385 case VK_PAUSE:
386 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
387 for purposes of key binding; convert these back into
388 VK_NUMLOCK events, at least when we want to see NumLock key
389 presses. (Note that there is never any possibility that
390 VK_PAUSE with Ctrl really is C-Pause as per above.) */
391 if (NILP (Vw32_enable_num_lock)
392 && (event->dwControlKeyState
393 & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0)
394 event->wVirtualKeyCode = VK_NUMLOCK;
395 break;
398 /* Recognize state of Windows and Apps keys. */
399 event->dwControlKeyState |= mod_key_state;
401 /* Distinguish numeric keypad keys from extended keys. */
402 event->wVirtualKeyCode =
403 map_keypad_keys (event->wVirtualKeyCode,
404 (event->dwControlKeyState & ENHANCED_KEY));
406 if (lispy_function_keys[event->wVirtualKeyCode] == 0)
408 if (!NILP (Vw32_recognize_altgr)
409 && (event->dwControlKeyState & LEFT_CTRL_PRESSED)
410 && (event->dwControlKeyState & RIGHT_ALT_PRESSED))
412 /* Don't try to interpret AltGr key chords; ToAscii seems not
413 to process them correctly. */
415 /* Handle key chords including any modifiers other than shift
416 directly, in order to preserve as much modifier information as
417 possible. */
418 else if (event->dwControlKeyState
419 & ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED
420 | RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED
421 | (!NILP (Vw32_lwindow_modifier) ? LEFT_WIN_PRESSED : 0)
422 | (!NILP (Vw32_rwindow_modifier) ? RIGHT_WIN_PRESSED : 0)
423 | (!NILP (Vw32_apps_modifier) ? APPS_PRESSED : 0)
424 | (!NILP (Vw32_scroll_lock_modifier) ? SCROLLLOCK_ON : 0)))
426 /* Don't translate modified alphabetic keystrokes, so the user
427 doesn't need to constantly switch layout to type control or
428 meta keystrokes when the normal layout translates
429 alphabetic characters to non-ascii characters. */
430 if ('A' <= event->wVirtualKeyCode && event->wVirtualKeyCode <= 'Z')
432 event->uChar.AsciiChar = event->wVirtualKeyCode;
433 if ((event->dwControlKeyState & SHIFT_PRESSED) == 0)
434 event->uChar.AsciiChar += ('a' - 'A');
436 /* Try to handle unrecognized keystrokes by determining the
437 base character (ie. translating the base key plus shift
438 modifier). */
439 else if (event->uChar.AsciiChar == 0)
440 w32_kbd_patch_key (event);
443 if (event->uChar.AsciiChar == 0)
445 emacs_ev->kind = NO_EVENT;
446 return 0;
448 else if (event->uChar.AsciiChar > 0)
450 emacs_ev->kind = ASCII_KEYSTROKE_EVENT;
451 emacs_ev->code = event->uChar.AsciiChar;
453 else if (event->uChar.UnicodeChar > 0)
455 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
456 emacs_ev->code = event->uChar.UnicodeChar;
458 else
460 /* Fallback for non-Unicode versions of Windows. */
461 wchar_t code;
462 char dbcs[2];
463 char cp[20];
464 int cpId;
466 /* Get the codepage to interpret this key with. */
467 GetLocaleInfo (GetThreadLocale (),
468 LOCALE_IDEFAULTANSICODEPAGE, cp, 20);
469 cpId = atoi (cp);
471 dbcs[0] = dbcs_lead;
472 dbcs[1] = event->uChar.AsciiChar;
473 if (dbcs_lead)
475 dbcs_lead = 0;
476 if (!MultiByteToWideChar (cpId, 0, dbcs, 2, &code, 1))
478 /* Garbage */
479 DebPrint (("Invalid DBCS sequence: %d %d\n",
480 dbcs[0], dbcs[1]));
481 emacs_ev->kind = NO_EVENT;
484 else if (IsDBCSLeadByteEx (cpId, dbcs[1]))
486 dbcs_lead = dbcs[1];
487 emacs_ev->kind = NO_EVENT;
489 else
491 if (!MultiByteToWideChar (cpId, 0, &dbcs[1], 1, &code, 1))
493 /* Garbage */
494 DebPrint (("Invalid character: %d\n", dbcs[1]));
495 emacs_ev->kind = NO_EVENT;
498 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
499 emacs_ev->code = code;
502 else
504 emacs_ev->kind = NON_ASCII_KEYSTROKE_EVENT;
505 emacs_ev->code = event->wVirtualKeyCode;
508 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
509 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState,
510 event->wVirtualKeyCode);
511 emacs_ev->timestamp = GetTickCount ();
512 return 1;
516 w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state)
518 int cur_state = (GetKeyState (vk_code) & 1);
520 if (NILP (new_state)
521 || (NUMBERP (new_state)
522 && ((XUINT (new_state)) & 1) != cur_state))
524 faked_key = vk_code;
526 keybd_event ((BYTE) vk_code,
527 (BYTE) MapVirtualKey (vk_code, 0),
528 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
529 keybd_event ((BYTE) vk_code,
530 (BYTE) MapVirtualKey (vk_code, 0),
531 KEYEVENTF_EXTENDEDKEY | 0, 0);
532 keybd_event ((BYTE) vk_code,
533 (BYTE) MapVirtualKey (vk_code, 0),
534 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
535 cur_state = !cur_state;
538 return cur_state;
541 /* Mouse position hook. */
542 void
543 w32_console_mouse_position (FRAME_PTR *f,
544 int insist,
545 Lisp_Object *bar_window,
546 enum scroll_bar_part *part,
547 Lisp_Object *x,
548 Lisp_Object *y,
549 Time *time)
551 BLOCK_INPUT;
553 insist = insist;
555 *f = get_frame ();
556 *bar_window = Qnil;
557 *part = 0;
558 SELECTED_FRAME ()->mouse_moved = 0;
560 XSETINT (*x, movement_pos.X);
561 XSETINT (*y, movement_pos.Y);
562 *time = movement_time;
564 UNBLOCK_INPUT;
567 /* Remember mouse motion and notify emacs. */
568 static void
569 mouse_moved_to (int x, int y)
571 /* If we're in the same place, ignore it. */
572 if (x != movement_pos.X || y != movement_pos.Y)
574 SELECTED_FRAME ()->mouse_moved = 1;
575 movement_pos.X = x;
576 movement_pos.Y = y;
577 movement_time = GetTickCount ();
581 /* Consoles return button bits in a strange order:
582 least significant - Leftmost button
583 next - Rightmost button
584 next - Leftmost+1
585 next - Leftmost+2...
587 Assume emacs likes three button mice, so
588 Left == 0
589 Middle == 1
590 Right == 2
591 Others increase from there. */
593 #define NUM_TRANSLATED_MOUSE_BUTTONS 3
594 static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] =
596 0, 2, 1
599 static int
600 do_mouse_event (MOUSE_EVENT_RECORD *event,
601 struct input_event *emacs_ev)
603 static DWORD button_state = 0;
604 static Lisp_Object last_mouse_window;
605 DWORD but_change, mask;
606 int i;
608 if (event->dwEventFlags == MOUSE_MOVED)
610 FRAME_PTR f = SELECTED_FRAME ();
611 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
612 int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y;
614 mouse_moved_to (mx, my);
616 if (f->mouse_moved)
618 if (hlinfo->mouse_face_hidden)
620 hlinfo->mouse_face_hidden = 0;
621 clear_mouse_face (hlinfo);
624 /* Generate SELECT_WINDOW_EVENTs when needed. */
625 if (!NILP (Vmouse_autoselect_window))
627 Lisp_Object mouse_window = window_from_coordinates (f, mx, my,
628 0, 0);
629 /* A window will be selected only when it is not
630 selected now, and the last mouse movement event was
631 not in it. A minibuffer window will be selected iff
632 it is active. */
633 if (WINDOWP (mouse_window)
634 && !EQ (mouse_window, last_mouse_window)
635 && !EQ (mouse_window, selected_window))
637 struct input_event event;
639 EVENT_INIT (event);
640 event.kind = SELECT_WINDOW_EVENT;
641 event.frame_or_window = mouse_window;
642 event.arg = Qnil;
643 event.timestamp = movement_time;
644 kbd_buffer_store_event (&event);
646 last_mouse_window = mouse_window;
648 else
649 last_mouse_window = Qnil;
651 previous_help_echo_string = help_echo_string;
652 help_echo_string = help_echo_object = help_echo_window = Qnil;
653 help_echo_pos = -1;
654 note_mouse_highlight (f, mx, my);
655 /* If the contents of the global variable help_echo has
656 changed (inside note_mouse_highlight), generate a HELP_EVENT. */
657 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
658 gen_help_event (help_echo_string, selected_frame, help_echo_window,
659 help_echo_object, help_echo_pos);
661 return 0;
664 /* It looks like the console code sends us a mouse event with
665 dwButtonState == 0 when a window is activated. Ignore this case. */
666 if (event->dwButtonState == button_state)
667 return 0;
669 emacs_ev->kind = MOUSE_CLICK_EVENT;
671 /* Find out what button has changed state since the last button event. */
672 but_change = button_state ^ event->dwButtonState;
673 mask = 1;
674 for (i = 0; mask; i++, mask <<= 1)
675 if (but_change & mask)
677 if (i < NUM_TRANSLATED_MOUSE_BUTTONS)
678 emacs_ev->code = emacs_button_translation[i];
679 else
680 emacs_ev->code = i;
681 break;
684 button_state = event->dwButtonState;
685 emacs_ev->timestamp = GetTickCount ();
686 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, 0) |
687 ((event->dwButtonState & mask) ? down_modifier : up_modifier);
689 XSETFASTINT (emacs_ev->x, event->dwMousePosition.X);
690 XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y);
691 /* for Mule 2.2 (Based on Emacs 19.28 */
692 #ifdef MULE
693 XSET (emacs_ev->frame_or_window, Lisp_Frame, get_frame ());
694 #else
695 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
696 #endif
698 return 1;
701 static void
702 resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
704 FRAME_PTR f = get_frame ();
706 change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1, 0);
707 SET_FRAME_GARBAGED (f);
710 static void
711 maybe_generate_resize_event (void)
713 CONSOLE_SCREEN_BUFFER_INFO info;
714 FRAME_PTR f = get_frame ();
716 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
718 /* It is okay to call this unconditionally, since it will do nothing
719 if the size hasn't actually changed. */
720 change_frame_size (f,
721 1 + info.srWindow.Bottom - info.srWindow.Top,
722 1 + info.srWindow.Right - info.srWindow.Left,
723 0, 0, 0);
727 w32_console_read_socket (struct terminal *terminal,
728 int expected,
729 struct input_event *hold_quit)
731 int nev, ret = 0, add;
732 int isdead;
734 if (interrupt_input_blocked)
736 interrupt_input_pending = 1;
737 return -1;
740 interrupt_input_pending = 0;
741 BLOCK_INPUT;
743 for (;;)
745 nev = fill_queue (0);
746 if (nev <= 0)
748 /* If nev == -1, there was some kind of error
749 If nev == 0 then waitp must be zero and no events were available
750 so return. */
751 UNBLOCK_INPUT;
752 return nev;
755 while (nev > 0)
757 struct input_event inev;
759 EVENT_INIT (inev);
760 inev.kind = NO_EVENT;
761 inev.arg = Qnil;
763 switch (queue_ptr->EventType)
765 case KEY_EVENT:
766 add = key_event (&queue_ptr->Event.KeyEvent, &inev, &isdead);
767 if (add == -1) /* 95.7.25 by himi */
769 queue_ptr--;
770 add = 1;
772 if (add)
773 kbd_buffer_store_event_hold (&inev, hold_quit);
774 break;
776 case MOUSE_EVENT:
777 add = do_mouse_event (&queue_ptr->Event.MouseEvent, &inev);
778 if (add)
779 kbd_buffer_store_event_hold (&inev, hold_quit);
780 break;
782 case WINDOW_BUFFER_SIZE_EVENT:
783 if (w32_use_full_screen_buffer)
784 resize_event (&queue_ptr->Event.WindowBufferSizeEvent);
785 break;
787 case MENU_EVENT:
788 case FOCUS_EVENT:
789 /* Internal event types, ignored. */
790 break;
793 queue_ptr++;
794 nev--;
797 if (ret > 0 || expected == 0)
798 break;
801 /* We don't get told about changes in the window size (only the buffer
802 size, which we no longer care about), so we have to check it
803 periodically. */
804 if (!w32_use_full_screen_buffer)
805 maybe_generate_resize_event ();
807 UNBLOCK_INPUT;
808 return ret;