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