Fix MS-Windows build broken by 2012-09-15T07:06:56Z!eggert@cs.ucla.edu, completing...
[emacs.git] / src / w32inevt.c
blobee07db5335b4354d1bed2f08b4da51adcdb2c071
1 /* Input event support for Emacs on the Microsoft Windows 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>
29 #ifndef MOUSE_MOVED
30 #define MOUSE_MOVED 1
31 #endif
33 #include "lisp.h"
34 #include "keyboard.h"
35 #include "frame.h"
36 #include "dispextern.h"
37 #include "window.h"
38 #include "blockinput.h"
39 #include "termhooks.h"
40 #include "termchar.h"
41 #include "w32heap.h"
42 #include "w32term.h"
43 #include "w32inevt.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 inline BOOL
65 w32_read_console_input (HANDLE h, INPUT_RECORD *rec, DWORD recsize,
66 DWORD *waiting)
68 return (w32_console_unicode_input
69 ? ReadConsoleInputW (h, rec, recsize, waiting)
70 : ReadConsoleInputA (h, rec, recsize, waiting));
73 static int
74 fill_queue (BOOL block)
76 BOOL rc;
77 DWORD events_waiting;
79 if (queue_ptr < queue_end)
80 return queue_end-queue_ptr;
82 if (!block)
84 /* Check to see if there are some events to read before we try
85 because we can't block. */
86 if (!GetNumberOfConsoleInputEvents (keyboard_handle, &events_waiting))
87 return -1;
88 if (events_waiting == 0)
89 return 0;
92 rc = w32_read_console_input (keyboard_handle, event_queue, EVENT_QUEUE_SIZE,
93 &events_waiting);
94 if (!rc)
95 return -1;
96 queue_ptr = event_queue;
97 queue_end = event_queue + events_waiting;
98 return (int) events_waiting;
101 /* In a generic, multi-frame world this should take a console handle
102 and return the frame for it
104 Right now, there's only one frame so return it. */
105 static FRAME_PTR
106 get_frame (void)
108 return SELECTED_FRAME ();
111 /* Translate console modifiers to emacs modifiers.
112 German keyboard support (Kai Morgan Zeise 2/18/95). */
114 w32_kbd_mods_to_emacs (DWORD mods, WORD key)
116 int retval = 0;
118 /* If we recognize right-alt and left-ctrl as AltGr, and it has been
119 pressed, first remove those modifiers. */
120 if (!NILP (Vw32_recognize_altgr)
121 && (mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
122 == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
123 mods &= ~ (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED);
125 if (mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
126 retval = ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier);
128 if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
130 retval |= ctrl_modifier;
131 if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
132 == (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
133 retval |= meta_modifier;
136 if (mods & LEFT_WIN_PRESSED)
137 retval |= w32_key_to_modifier (VK_LWIN);
138 if (mods & RIGHT_WIN_PRESSED)
139 retval |= w32_key_to_modifier (VK_RWIN);
140 if (mods & APPS_PRESSED)
141 retval |= w32_key_to_modifier (VK_APPS);
142 if (mods & SCROLLLOCK_ON)
143 retval |= w32_key_to_modifier (VK_SCROLL);
145 /* Just in case someone wanted the original behavior, make it
146 optional by setting w32-capslock-is-shiftlock to t. */
147 if (NILP (Vw32_capslock_is_shiftlock)
148 /* Keys that should _not_ be affected by CapsLock. */
149 && ( (key == VK_BACK)
150 || (key == VK_TAB)
151 || (key == VK_CLEAR)
152 || (key == VK_RETURN)
153 || (key == VK_ESCAPE)
154 || ((key >= VK_SPACE) && (key <= VK_HELP))
155 || ((key >= VK_NUMPAD0) && (key <= VK_F24))
156 || ((key >= VK_NUMPAD_CLEAR) && (key <= VK_NUMPAD_DELETE))
159 /* Only consider shift state. */
160 if ((mods & SHIFT_PRESSED) != 0)
161 retval |= shift_modifier;
163 else
165 /* Ignore CapsLock state if not enabled. */
166 if (NILP (Vw32_enable_caps_lock))
167 mods &= ~CAPSLOCK_ON;
168 if ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) != 0)
169 retval |= shift_modifier;
172 return retval;
175 #if 0
176 /* Return nonzero if the virtual key is a dead key. */
177 static int
178 is_dead_key (int wparam)
180 unsigned int code = MapVirtualKey (wparam, 2);
182 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
183 return (code & 0x80008000) ? 1 : 0;
185 #endif
187 /* The return code indicates key code size. cpID is the codepage to
188 use for translation to Unicode; -1 means use the current console
189 input codepage. */
191 w32_kbd_patch_key (KEY_EVENT_RECORD *event, int cpId)
193 unsigned int key_code = event->wVirtualKeyCode;
194 unsigned int mods = event->dwControlKeyState;
195 BYTE keystate[256];
196 static BYTE ansi_code[4];
197 static int isdead = 0;
199 if (isdead == 2)
201 event->uChar.AsciiChar = ansi_code[2];
202 isdead = 0;
203 return 1;
205 if (event->uChar.AsciiChar != 0)
206 return 1;
208 memset (keystate, 0, sizeof (keystate));
209 keystate[key_code] = 0x80;
210 if (mods & SHIFT_PRESSED)
211 keystate[VK_SHIFT] = 0x80;
212 if (mods & CAPSLOCK_ON)
213 keystate[VK_CAPITAL] = 1;
214 /* If we recognize right-alt and left-ctrl as AltGr, set the key
215 states accordingly before invoking ToAscii. */
216 if (!NILP (Vw32_recognize_altgr)
217 && (mods & LEFT_CTRL_PRESSED) && (mods & RIGHT_ALT_PRESSED))
219 keystate[VK_CONTROL] = 0x80;
220 keystate[VK_LCONTROL] = 0x80;
221 keystate[VK_MENU] = 0x80;
222 keystate[VK_RMENU] = 0x80;
225 #if 0
226 /* Because of an OS bug, ToAscii corrupts the stack when called to
227 convert a dead key in console mode on NT4. Unfortunately, trying
228 to check for dead keys using MapVirtualKey doesn't work either -
229 these functions apparently use internal information about keyboard
230 layout which doesn't get properly updated in console programs when
231 changing layout (though apparently it gets partly updated,
232 otherwise ToAscii wouldn't crash). */
233 if (is_dead_key (event->wVirtualKeyCode))
234 return 0;
235 #endif
237 /* On NT, call ToUnicode instead and then convert to the current
238 console input codepage. */
239 if (os_subtype == OS_NT)
241 WCHAR buf[128];
243 isdead = ToUnicode (event->wVirtualKeyCode, event->wVirtualScanCode,
244 keystate, buf, 128, 0);
245 if (isdead > 0)
247 /* When we are called from the GUI message processing code,
248 we are passed the current keyboard codepage, a positive
249 number, to use below. */
250 if (cpId == -1)
251 cpId = GetConsoleCP ();
253 event->uChar.UnicodeChar = buf[isdead - 1];
254 isdead = WideCharToMultiByte (cpId, 0, buf, isdead,
255 ansi_code, 4, NULL, NULL);
257 else
258 isdead = 0;
260 else
262 isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode,
263 keystate, (LPWORD) ansi_code, 0);
266 if (isdead == 0)
267 return 0;
268 event->uChar.AsciiChar = ansi_code[0];
269 return isdead;
273 static int faked_key = 0;
275 /* return code -1 means that event_queue_ptr won't be incremented.
276 In other word, this event makes two key codes. (by himi) */
277 static int
278 key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
280 static int mod_key_state = 0;
281 int wParam;
283 *isdead = 0;
285 /* Skip key-up events. */
286 if (!event->bKeyDown)
288 switch (event->wVirtualKeyCode)
290 case VK_LWIN:
291 mod_key_state &= ~LEFT_WIN_PRESSED;
292 break;
293 case VK_RWIN:
294 mod_key_state &= ~RIGHT_WIN_PRESSED;
295 break;
296 case VK_APPS:
297 mod_key_state &= ~APPS_PRESSED;
298 break;
300 return 0;
303 /* Ignore keystrokes we fake ourself; see below. */
304 if (faked_key == event->wVirtualKeyCode)
306 faked_key = 0;
307 return 0;
310 /* To make it easier to debug this code, ignore modifier keys! */
311 switch (event->wVirtualKeyCode)
313 case VK_LWIN:
314 if (NILP (Vw32_pass_lwindow_to_system))
316 /* Prevent system from acting on keyup (which opens the Start
317 menu if no other key was pressed) by simulating a press of
318 Space which we will ignore. */
319 if ((mod_key_state & LEFT_WIN_PRESSED) == 0)
321 if (NUMBERP (Vw32_phantom_key_code))
322 faked_key = XUINT (Vw32_phantom_key_code) & 255;
323 else
324 faked_key = VK_SPACE;
325 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
328 mod_key_state |= LEFT_WIN_PRESSED;
329 if (!NILP (Vw32_lwindow_modifier))
330 return 0;
331 break;
332 case VK_RWIN:
333 if (NILP (Vw32_pass_rwindow_to_system))
335 if ((mod_key_state & RIGHT_WIN_PRESSED) == 0)
337 if (NUMBERP (Vw32_phantom_key_code))
338 faked_key = XUINT (Vw32_phantom_key_code) & 255;
339 else
340 faked_key = VK_SPACE;
341 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
344 mod_key_state |= RIGHT_WIN_PRESSED;
345 if (!NILP (Vw32_rwindow_modifier))
346 return 0;
347 break;
348 case VK_APPS:
349 mod_key_state |= APPS_PRESSED;
350 if (!NILP (Vw32_apps_modifier))
351 return 0;
352 break;
353 case VK_CAPITAL:
354 /* Decide whether to treat as modifier or function key. */
355 if (NILP (Vw32_enable_caps_lock))
356 goto disable_lock_key;
357 return 0;
358 case VK_NUMLOCK:
359 /* Decide whether to treat as modifier or function key. */
360 if (NILP (Vw32_enable_num_lock))
361 goto disable_lock_key;
362 return 0;
363 case VK_SCROLL:
364 /* Decide whether to treat as modifier or function key. */
365 if (NILP (Vw32_scroll_lock_modifier))
366 goto disable_lock_key;
367 return 0;
368 disable_lock_key:
369 /* Ensure the appropriate lock key state is off (and the
370 indicator light as well). */
371 wParam = event->wVirtualKeyCode;
372 if (GetAsyncKeyState (wParam) & 0x8000)
374 /* Fake another press of the relevant key. Apparently, this
375 really is the only way to turn off the indicator. */
376 faked_key = wParam;
377 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
378 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
379 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
380 KEYEVENTF_EXTENDEDKEY | 0, 0);
381 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
382 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
384 break;
385 case VK_MENU:
386 case VK_CONTROL:
387 case VK_SHIFT:
388 return 0;
389 case VK_CANCEL:
390 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
391 which is confusing for purposes of key binding; convert
392 VK_CANCEL events into VK_PAUSE events. */
393 event->wVirtualKeyCode = VK_PAUSE;
394 break;
395 case VK_PAUSE:
396 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
397 for purposes of key binding; convert these back into
398 VK_NUMLOCK events, at least when we want to see NumLock key
399 presses. (Note that there is never any possibility that
400 VK_PAUSE with Ctrl really is C-Pause as per above.) */
401 if (NILP (Vw32_enable_num_lock)
402 && (event->dwControlKeyState
403 & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0)
404 event->wVirtualKeyCode = VK_NUMLOCK;
405 break;
408 /* Recognize state of Windows and Apps keys. */
409 event->dwControlKeyState |= mod_key_state;
411 /* Distinguish numeric keypad keys from extended keys. */
412 event->wVirtualKeyCode =
413 map_keypad_keys (event->wVirtualKeyCode,
414 (event->dwControlKeyState & ENHANCED_KEY));
416 if (lispy_function_keys[event->wVirtualKeyCode] == 0)
418 if (!NILP (Vw32_recognize_altgr)
419 && (event->dwControlKeyState & LEFT_CTRL_PRESSED)
420 && (event->dwControlKeyState & RIGHT_ALT_PRESSED))
422 /* Don't try to interpret AltGr key chords; ToAscii seems not
423 to process them correctly. */
425 /* Handle key chords including any modifiers other than shift
426 directly, in order to preserve as much modifier information as
427 possible. */
428 else if (event->dwControlKeyState
429 & ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED
430 | RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED
431 | (!NILP (Vw32_lwindow_modifier) ? LEFT_WIN_PRESSED : 0)
432 | (!NILP (Vw32_rwindow_modifier) ? RIGHT_WIN_PRESSED : 0)
433 | (!NILP (Vw32_apps_modifier) ? APPS_PRESSED : 0)
434 | (!NILP (Vw32_scroll_lock_modifier) ? SCROLLLOCK_ON : 0)))
436 /* Don't translate modified alphabetic keystrokes, so the user
437 doesn't need to constantly switch layout to type control or
438 meta keystrokes when the normal layout translates
439 alphabetic characters to non-ascii characters. */
440 if ('A' <= event->wVirtualKeyCode && event->wVirtualKeyCode <= 'Z')
442 event->uChar.AsciiChar = event->wVirtualKeyCode;
443 if ((event->dwControlKeyState & SHIFT_PRESSED) == 0)
444 event->uChar.AsciiChar += ('a' - 'A');
446 /* Try to handle unrecognized keystrokes by determining the
447 base character (ie. translating the base key plus shift
448 modifier). */
449 else if (event->uChar.AsciiChar == 0)
450 w32_kbd_patch_key (event, -1);
453 if (event->uChar.AsciiChar == 0)
455 emacs_ev->kind = NO_EVENT;
456 return 0;
458 else if (event->uChar.AsciiChar > 0)
460 /* Pure ASCII characters < 128. */
461 emacs_ev->kind = ASCII_KEYSTROKE_EVENT;
462 emacs_ev->code = event->uChar.AsciiChar;
464 else if (event->uChar.UnicodeChar > 0
465 && w32_console_unicode_input)
467 /* Unicode codepoint; only valid if we are using Unicode
468 console input mode. */
469 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
470 emacs_ev->code = event->uChar.UnicodeChar;
472 else
474 /* Fallback handling of non-ASCII characters for non-Unicode
475 versions of Windows, and for non-Unicode input on NT
476 family of Windows. Only characters in the current
477 console codepage are supported by this fallback. */
478 wchar_t code;
479 char dbcs[2];
480 int cpId;
482 /* Get the current console input codepage to interpret this
483 key with. Note that the system defaults for the OEM
484 codepage could have been changed by calling SetConsoleCP
485 or w32-set-console-codepage, so using GetLocaleInfo to
486 get LOCALE_IDEFAULTCODEPAGE is not TRT here. */
487 cpId = GetConsoleCP ();
489 dbcs[0] = dbcs_lead;
490 dbcs[1] = event->uChar.AsciiChar;
491 if (dbcs_lead)
493 dbcs_lead = 0;
494 if (!MultiByteToWideChar (cpId, 0, dbcs, 2, &code, 1))
496 /* Garbage */
497 DebPrint (("Invalid DBCS sequence: %d %d\n",
498 dbcs[0], dbcs[1]));
499 emacs_ev->kind = NO_EVENT;
502 else if (IsDBCSLeadByteEx (cpId, dbcs[1]))
504 dbcs_lead = dbcs[1];
505 emacs_ev->kind = NO_EVENT;
507 else
509 if (!MultiByteToWideChar (cpId, 0, &dbcs[1], 1, &code, 1))
511 /* Garbage */
512 DebPrint (("Invalid character: %d\n", dbcs[1]));
513 emacs_ev->kind = NO_EVENT;
516 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
517 emacs_ev->code = code;
520 else
522 /* Function keys and other non-character keys. */
523 emacs_ev->kind = NON_ASCII_KEYSTROKE_EVENT;
524 emacs_ev->code = event->wVirtualKeyCode;
527 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
528 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState,
529 event->wVirtualKeyCode);
530 emacs_ev->timestamp = GetTickCount ();
531 return 1;
535 w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state)
537 int cur_state = (GetKeyState (vk_code) & 1);
539 if (NILP (new_state)
540 || (NUMBERP (new_state)
541 && ((XUINT (new_state)) & 1) != cur_state))
543 faked_key = vk_code;
545 keybd_event ((BYTE) vk_code,
546 (BYTE) MapVirtualKey (vk_code, 0),
547 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
548 keybd_event ((BYTE) vk_code,
549 (BYTE) MapVirtualKey (vk_code, 0),
550 KEYEVENTF_EXTENDEDKEY | 0, 0);
551 keybd_event ((BYTE) vk_code,
552 (BYTE) MapVirtualKey (vk_code, 0),
553 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
554 cur_state = !cur_state;
557 return cur_state;
560 /* Mouse position hook. */
561 void
562 w32_console_mouse_position (FRAME_PTR *f,
563 int insist,
564 Lisp_Object *bar_window,
565 enum scroll_bar_part *part,
566 Lisp_Object *x,
567 Lisp_Object *y,
568 Time *time)
570 BLOCK_INPUT;
572 insist = insist;
574 *f = get_frame ();
575 *bar_window = Qnil;
576 *part = 0;
577 SELECTED_FRAME ()->mouse_moved = 0;
579 XSETINT (*x, movement_pos.X);
580 XSETINT (*y, movement_pos.Y);
581 *time = movement_time;
583 UNBLOCK_INPUT;
586 /* Remember mouse motion and notify emacs. */
587 static void
588 mouse_moved_to (int x, int y)
590 /* If we're in the same place, ignore it. */
591 if (x != movement_pos.X || y != movement_pos.Y)
593 SELECTED_FRAME ()->mouse_moved = 1;
594 movement_pos.X = x;
595 movement_pos.Y = y;
596 movement_time = GetTickCount ();
600 /* Consoles return button bits in a strange order:
601 least significant - Leftmost button
602 next - Rightmost button
603 next - Leftmost+1
604 next - Leftmost+2...
606 Assume emacs likes three button mice, so
607 Left == 0
608 Middle == 1
609 Right == 2
610 Others increase from there. */
612 #define NUM_TRANSLATED_MOUSE_BUTTONS 3
613 static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] =
615 0, 2, 1
618 static int
619 do_mouse_event (MOUSE_EVENT_RECORD *event,
620 struct input_event *emacs_ev)
622 static DWORD button_state = 0;
623 static Lisp_Object last_mouse_window;
624 DWORD but_change, mask;
625 int i;
627 if (event->dwEventFlags == MOUSE_MOVED)
629 FRAME_PTR f = SELECTED_FRAME ();
630 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
631 int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y;
633 mouse_moved_to (mx, my);
635 if (f->mouse_moved)
637 if (hlinfo->mouse_face_hidden)
639 hlinfo->mouse_face_hidden = 0;
640 clear_mouse_face (hlinfo);
643 /* Generate SELECT_WINDOW_EVENTs when needed. */
644 if (!NILP (Vmouse_autoselect_window))
646 Lisp_Object mouse_window = window_from_coordinates (f, mx, my,
647 0, 0);
648 /* A window will be selected only when it is not
649 selected now, and the last mouse movement event was
650 not in it. A minibuffer window will be selected iff
651 it is active. */
652 if (WINDOWP (mouse_window)
653 && !EQ (mouse_window, last_mouse_window)
654 && !EQ (mouse_window, selected_window))
656 struct input_event event;
658 EVENT_INIT (event);
659 event.kind = SELECT_WINDOW_EVENT;
660 event.frame_or_window = mouse_window;
661 event.arg = Qnil;
662 event.timestamp = movement_time;
663 kbd_buffer_store_event (&event);
665 last_mouse_window = mouse_window;
667 else
668 last_mouse_window = Qnil;
670 previous_help_echo_string = help_echo_string;
671 help_echo_string = help_echo_object = help_echo_window = Qnil;
672 help_echo_pos = -1;
673 note_mouse_highlight (f, mx, my);
674 /* If the contents of the global variable help_echo has
675 changed (inside note_mouse_highlight), generate a HELP_EVENT. */
676 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
677 gen_help_event (help_echo_string, selected_frame, help_echo_window,
678 help_echo_object, help_echo_pos);
680 return 0;
683 /* It looks like the console code sends us a mouse event with
684 dwButtonState == 0 when a window is activated. Ignore this case. */
685 if (event->dwButtonState == button_state)
686 return 0;
688 emacs_ev->kind = MOUSE_CLICK_EVENT;
690 /* Find out what button has changed state since the last button event. */
691 but_change = button_state ^ event->dwButtonState;
692 mask = 1;
693 for (i = 0; mask; i++, mask <<= 1)
694 if (but_change & mask)
696 if (i < NUM_TRANSLATED_MOUSE_BUTTONS)
697 emacs_ev->code = emacs_button_translation[i];
698 else
699 emacs_ev->code = i;
700 break;
703 button_state = event->dwButtonState;
704 emacs_ev->timestamp = GetTickCount ();
705 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, 0) |
706 ((event->dwButtonState & mask) ? down_modifier : up_modifier);
708 XSETFASTINT (emacs_ev->x, event->dwMousePosition.X);
709 XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y);
710 /* for Mule 2.2 (Based on Emacs 19.28 */
711 #ifdef MULE
712 XSET (emacs_ev->frame_or_window, Lisp_Frame, get_frame ());
713 #else
714 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
715 #endif
717 return 1;
720 static void
721 resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
723 FRAME_PTR f = get_frame ();
725 change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1, 0);
726 SET_FRAME_GARBAGED (f);
729 static void
730 maybe_generate_resize_event (void)
732 CONSOLE_SCREEN_BUFFER_INFO info;
733 FRAME_PTR f = get_frame ();
735 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
737 /* It is okay to call this unconditionally, since it will do nothing
738 if the size hasn't actually changed. */
739 change_frame_size (f,
740 1 + info.srWindow.Bottom - info.srWindow.Top,
741 1 + info.srWindow.Right - info.srWindow.Left,
742 0, 0, 0);
746 w32_console_read_socket (struct terminal *terminal,
747 int expected,
748 struct input_event *hold_quit)
750 int nev, ret = 0, add;
751 int isdead;
753 if (interrupt_input_blocked)
755 interrupt_input_pending = 1;
756 return -1;
759 interrupt_input_pending = 0;
760 BLOCK_INPUT;
762 for (;;)
764 nev = fill_queue (0);
765 if (nev <= 0)
767 /* If nev == -1, there was some kind of error
768 If nev == 0 then waitp must be zero and no events were available
769 so return. */
770 UNBLOCK_INPUT;
771 return nev;
774 while (nev > 0)
776 struct input_event inev;
778 EVENT_INIT (inev);
779 inev.kind = NO_EVENT;
780 inev.arg = Qnil;
782 switch (queue_ptr->EventType)
784 case KEY_EVENT:
785 add = key_event (&queue_ptr->Event.KeyEvent, &inev, &isdead);
786 if (add == -1) /* 95.7.25 by himi */
788 queue_ptr--;
789 add = 1;
791 if (add)
792 kbd_buffer_store_event_hold (&inev, hold_quit);
793 break;
795 case MOUSE_EVENT:
796 add = do_mouse_event (&queue_ptr->Event.MouseEvent, &inev);
797 if (add)
798 kbd_buffer_store_event_hold (&inev, hold_quit);
799 break;
801 case WINDOW_BUFFER_SIZE_EVENT:
802 if (w32_use_full_screen_buffer)
803 resize_event (&queue_ptr->Event.WindowBufferSizeEvent);
804 break;
806 case MENU_EVENT:
807 case FOCUS_EVENT:
808 /* Internal event types, ignored. */
809 break;
812 queue_ptr++;
813 nev--;
816 if (ret > 0 || expected == 0)
817 break;
820 /* We don't get told about changes in the window size (only the buffer
821 size, which we no longer care about), so we have to check it
822 periodically. */
823 if (!w32_use_full_screen_buffer)
824 maybe_generate_resize_event ();
826 UNBLOCK_INPUT;
827 return ret;