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