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