* lisp/dired-aux.el (dired-diff): Add (require 'diff) because
[bpt/emacs.git] / src / w32inevt.c
CommitLineData
b46a6a83 1/* Input event support for Emacs on the Microsoft Windows API.
acaf905b 2 Copyright (C) 1992-1993, 1995, 2001-2012 Free Software Foundation, Inc.
6cdfb6e6 3
3b7ad313
EN
4This file is part of GNU Emacs.
5
9ec0b715 6GNU Emacs is free software: you can redistribute it and/or modify
3b7ad313 7it under the terms of the GNU General Public License as published by
9ec0b715
GM
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
3b7ad313
EN
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
9ec0b715 17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
6cdfb6e6 18
9ec0b715 19/*
6cdfb6e6
RS
20 Drew Bliss 01-Oct-93
21 Adapted from ntkbd.c by Tim Fleehart
22*/
23
24
4838e624 25#include <config.h>
6cdfb6e6
RS
26#include <stdio.h>
27#include <windows.h>
28
690e96a3
AI
29#ifndef MOUSE_MOVED
30#define MOUSE_MOVED 1
31#endif
32
6cdfb6e6 33#include "lisp.h"
690e96a3 34#include "keyboard.h"
6cdfb6e6 35#include "frame.h"
2165e881 36#include "dispextern.h"
f12fdf02 37#include "window.h"
6cdfb6e6
RS
38#include "blockinput.h"
39#include "termhooks.h"
42e3a361 40#include "termchar.h"
29a2c30f
GV
41#include "w32heap.h"
42#include "w32term.h"
01bd1b0d 43#include "w32inevt.h"
6cdfb6e6 44
7684e57b 45/* stdin, from w32console.c */
6cdfb6e6
RS
46extern HANDLE keyboard_handle;
47
6cdfb6e6
RS
48/* Info for last mouse motion */
49static COORD movement_pos;
9fbd6841 50static Time movement_time;
6cdfb6e6 51
7684e57b 52/* from w32fns.c */
29a2c30f 53extern unsigned int map_keypad_keys (unsigned int, unsigned int);
29a2c30f 54extern unsigned int w32_key_to_modifier (int key);
59131421 55
6cdfb6e6
RS
56/* Event queue */
57#define EVENT_QUEUE_SIZE 50
58static INPUT_RECORD event_queue[EVENT_QUEUE_SIZE];
59static INPUT_RECORD *queue_ptr = event_queue, *queue_end = event_queue;
60
7e233730
JR
61/* Temporarily store lead byte of DBCS input sequences. */
62static char dbcs_lead = 0;
63
01bd1b0d
EZ
64static inline BOOL
65w32_read_console_input (HANDLE h, INPUT_RECORD *rec, DWORD recsize,
66 DWORD *waiting)
67{
68 return (w32_console_unicode_input
69 ? ReadConsoleInputW (h, rec, recsize, waiting)
70 : ReadConsoleInputA (h, rec, recsize, waiting));
71}
72
177c0ea7 73static int
6cdfb6e6
RS
74fill_queue (BOOL block)
75{
76 BOOL rc;
77 DWORD events_waiting;
177c0ea7 78
6cdfb6e6
RS
79 if (queue_ptr < queue_end)
80 return queue_end-queue_ptr;
177c0ea7 81
6cdfb6e6
RS
82 if (!block)
83 {
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;
90 }
177c0ea7 91
01bd1b0d
EZ
92 rc = w32_read_console_input (keyboard_handle, event_queue, EVENT_QUEUE_SIZE,
93 &events_waiting);
6cdfb6e6
RS
94 if (!rc)
95 return -1;
96 queue_ptr = event_queue;
97 queue_end = event_queue + events_waiting;
98 return (int) events_waiting;
99}
100
101/* In a generic, multi-frame world this should take a console handle
102 and return the frame for it
103
104 Right now, there's only one frame so return it. */
177c0ea7 105static FRAME_PTR
6cdfb6e6
RS
106get_frame (void)
107{
4f4a5f69 108 return SELECTED_FRAME ();
6cdfb6e6
RS
109}
110
177c0ea7 111/* Translate console modifiers to emacs modifiers.
b02466e8 112 German keyboard support (Kai Morgan Zeise 2/18/95). */
407c1745 113int
59131421 114w32_kbd_mods_to_emacs (DWORD mods, WORD key)
6cdfb6e6 115{
b02466e8
KH
116 int retval = 0;
117
c0f1b02e 118 /* If we recognize right-alt and left-ctrl as AltGr, and it has been
29a2c30f 119 pressed, first remove those modifiers. */
177c0ea7
JB
120 if (!NILP (Vw32_recognize_altgr)
121 && (mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
b02466e8
KH
122 == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
123 mods &= ~ (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED);
124
125 if (mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
fbd6baed 126 retval = ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier);
177c0ea7 127
b02466e8
KH
128 if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
129 {
130 retval |= ctrl_modifier;
177c0ea7 131 if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
b02466e8
KH
132 == (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
133 retval |= meta_modifier;
134 }
135
29a2c30f
GV
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);
144
fffa137c 145 /* Just in case someone wanted the original behavior, make it
59131421 146 optional by setting w32-capslock-is-shiftlock to t. */
29a2c30f
GV
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))
157 ))
59131421 158 {
29a2c30f
GV
159 /* Only consider shift state. */
160 if ((mods & SHIFT_PRESSED) != 0)
59131421
GV
161 retval |= shift_modifier;
162 }
163 else
164 {
29a2c30f
GV
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;
59131421 170 }
b02466e8
KH
171
172 return retval;
173}
174
29a2c30f
GV
175#if 0
176/* Return nonzero if the virtual key is a dead key. */
177static int
178is_dead_key (int wparam)
179{
180 unsigned int code = MapVirtualKey (wparam, 2);
181
182 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
183 return (code & 0x80008000) ? 1 : 0;
184}
185#endif
186
302fc036
EZ
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. */
c0386d7e 190int
302fc036 191w32_kbd_patch_key (KEY_EVENT_RECORD *event, int cpId)
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 }
177c0ea7 205 if (event->uChar.AsciiChar != 0)
daf38066 206 return 1;
c0386d7e 207
daf38066 208 memset (keystate, 0, sizeof (keystate));
29a2c30f 209 keystate[key_code] = 0x80;
177c0ea7 210 if (mods & SHIFT_PRESSED)
daf38066 211 keystate[VK_SHIFT] = 0x80;
177c0ea7 212 if (mods & CAPSLOCK_ON)
daf38066 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
01bd1b0d 238 console input codepage. */
29a2c30f
GV
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 {
302fc036
EZ
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 ();
29a2c30f 252
7e233730 253 event->uChar.UnicodeChar = buf[isdead - 1];
7e233730 254 isdead = WideCharToMultiByte (cpId, 0, buf, isdead,
29a2c30f
GV
255 ansi_code, 4, NULL, NULL);
256 }
257 else
258 isdead = 0;
259 }
260 else
261 {
262 isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode,
263 keystate, (LPWORD) ansi_code, 0);
264 }
265
177c0ea7 266 if (isdead == 0)
daf38066
GV
267 return 0;
268 event->uChar.AsciiChar = ansi_code[0];
269 return isdead;
6cdfb6e6 270}
407c1745 271
6cdfb6e6 272
9ddef9c4
GV
273static int faked_key = 0;
274
177c0ea7 275/* return code -1 means that event_queue_ptr won't be incremented.
daf38066 276 In other word, this event makes two key codes. (by himi) */
24f981c9 277static int
59131421 278key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
6cdfb6e6 279{
29a2c30f
GV
280 static int mod_key_state = 0;
281 int wParam;
59131421
GV
282
283 *isdead = 0;
29a2c30f 284
6cdfb6e6 285 /* Skip key-up events. */
407c1745 286 if (!event->bKeyDown)
6cdfb6e6 287 {
29a2c30f
GV
288 switch (event->wVirtualKeyCode)
289 {
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;
299 }
6cdfb6e6
RS
300 return 0;
301 }
b02466e8 302
29a2c30f
GV
303 /* Ignore keystrokes we fake ourself; see below. */
304 if (faked_key == event->wVirtualKeyCode)
6cdfb6e6 305 {
29a2c30f 306 faked_key = 0;
6cdfb6e6
RS
307 return 0;
308 }
29a2c30f
GV
309
310 /* To make it easier to debug this code, ignore modifier keys! */
311 switch (event->wVirtualKeyCode)
6cdfb6e6 312 {
29a2c30f
GV
313 case VK_LWIN:
314 if (NILP (Vw32_pass_lwindow_to_system))
315 {
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)
320 {
9ddef9c4
GV
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);
29a2c30f
GV
326 }
327 }
328 mod_key_state |= LEFT_WIN_PRESSED;
329 if (!NILP (Vw32_lwindow_modifier))
daf38066 330 return 0;
29a2c30f
GV
331 break;
332 case VK_RWIN:
333 if (NILP (Vw32_pass_rwindow_to_system))
334 {
335 if ((mod_key_state & RIGHT_WIN_PRESSED) == 0)
336 {
9ddef9c4
GV
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);
29a2c30f
GV
342 }
343 }
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)
373 {
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);
383 }
384 break;
385 case VK_MENU:
386 case VK_CONTROL:
387 case VK_SHIFT:
388 return 0;
9ddef9c4
GV
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;
6cdfb6e6 406 }
29a2c30f
GV
407
408 /* Recognize state of Windows and Apps keys. */
409 event->dwControlKeyState |= mod_key_state;
410
411 /* Distinguish numeric keypad keys from extended keys. */
412 event->wVirtualKeyCode =
413 map_keypad_keys (event->wVirtualKeyCode,
414 (event->dwControlKeyState & ENHANCED_KEY));
415
416 if (lispy_function_keys[event->wVirtualKeyCode] == 0)
daf38066 417 {
29a2c30f
GV
418 if (!NILP (Vw32_recognize_altgr)
419 && (event->dwControlKeyState & LEFT_CTRL_PRESSED)
420 && (event->dwControlKeyState & RIGHT_ALT_PRESSED))
daf38066 421 {
29a2c30f
GV
422 /* Don't try to interpret AltGr key chords; ToAscii seems not
423 to process them correctly. */
daf38066 424 }
29a2c30f
GV
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)))
435 {
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')
441 {
442 event->uChar.AsciiChar = event->wVirtualKeyCode;
443 if ((event->dwControlKeyState & SHIFT_PRESSED) == 0)
444 event->uChar.AsciiChar += ('a' - 'A');
445 }
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)
302fc036 450 w32_kbd_patch_key (event, -1);
29a2c30f 451 }
7e233730 452
29a2c30f 453 if (event->uChar.AsciiChar == 0)
7e233730
JR
454 {
455 emacs_ev->kind = NO_EVENT;
456 return 0;
457 }
af93af83 458 else if (event->uChar.AsciiChar > 0)
7e233730 459 {
01bd1b0d 460 /* Pure ASCII characters < 128. */
7e233730
JR
461 emacs_ev->kind = ASCII_KEYSTROKE_EVENT;
462 emacs_ev->code = event->uChar.AsciiChar;
463 }
01bd1b0d
EZ
464 else if (event->uChar.UnicodeChar > 0
465 && w32_console_unicode_input)
7e233730 466 {
01bd1b0d
EZ
467 /* Unicode codepoint; only valid if we are using Unicode
468 console input mode. */
7e233730
JR
469 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
470 emacs_ev->code = event->uChar.UnicodeChar;
471 }
472 else
473 {
01bd1b0d
EZ
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. */
7e233730
JR
478 wchar_t code;
479 char dbcs[2];
7e233730
JR
480 int cpId;
481
01bd1b0d
EZ
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 ();
7e233730
JR
488
489 dbcs[0] = dbcs_lead;
490 dbcs[1] = event->uChar.AsciiChar;
491 if (dbcs_lead)
492 {
493 dbcs_lead = 0;
494 if (!MultiByteToWideChar (cpId, 0, dbcs, 2, &code, 1))
495 {
496 /* Garbage */
497 DebPrint (("Invalid DBCS sequence: %d %d\n",
498 dbcs[0], dbcs[1]));
dd5de7c6 499 emacs_ev->kind = NO_EVENT;
7e233730
JR
500 }
501 }
502 else if (IsDBCSLeadByteEx (cpId, dbcs[1]))
503 {
504 dbcs_lead = dbcs[1];
dd5de7c6 505 emacs_ev->kind = NO_EVENT;
7e233730
JR
506 }
507 else
508 {
509 if (!MultiByteToWideChar (cpId, 0, &dbcs[1], 1, &code, 1))
510 {
511 /* Garbage */
512 DebPrint (("Invalid character: %d\n", dbcs[1]));
dd5de7c6 513 emacs_ev->kind = NO_EVENT;
7e233730
JR
514 }
515 }
516 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
517 emacs_ev->code = code;
518 }
daf38066 519 }
6cdfb6e6
RS
520 else
521 {
01bd1b0d 522 /* Function keys and other non-character keys. */
e43bd4f5 523 emacs_ev->kind = NON_ASCII_KEYSTROKE_EVENT;
e3ec1dce 524 emacs_ev->code = event->wVirtualKeyCode;
6cdfb6e6 525 }
29a2c30f 526
b02466e8 527 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
59131421
GV
528 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState,
529 event->wVirtualKeyCode);
6cdfb6e6
RS
530 emacs_ev->timestamp = GetTickCount ();
531 return 1;
532}
533
9ddef9c4
GV
534int
535w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state)
536{
537 int cur_state = (GetKeyState (vk_code) & 1);
538
539 if (NILP (new_state)
540 || (NUMBERP (new_state)
a1bcc85a 541 && ((XUINT (new_state)) & 1) != cur_state))
9ddef9c4
GV
542 {
543 faked_key = vk_code;
544
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;
555 }
556
557 return cur_state;
558}
559
6cdfb6e6 560/* Mouse position hook. */
177c0ea7 561void
81e3e4fd 562w32_console_mouse_position (FRAME_PTR *f,
81e3e4fd 563 int insist,
81e3e4fd
GV
564 Lisp_Object *bar_window,
565 enum scroll_bar_part *part,
566 Lisp_Object *x,
567 Lisp_Object *y,
9fbd6841 568 Time *time)
6cdfb6e6
RS
569{
570 BLOCK_INPUT;
407c1745 571
b02466e8
KH
572 insist = insist;
573
6cdfb6e6
RS
574 *f = get_frame ();
575 *bar_window = Qnil;
576 *part = 0;
4f4a5f69 577 SELECTED_FRAME ()->mouse_moved = 0;
177c0ea7 578
ed3751c8
JB
579 XSETINT (*x, movement_pos.X);
580 XSETINT (*y, movement_pos.Y);
6cdfb6e6 581 *time = movement_time;
177c0ea7 582
6cdfb6e6
RS
583 UNBLOCK_INPUT;
584}
585
42e3a361 586/* Remember mouse motion and notify emacs. */
177c0ea7 587static void
6cdfb6e6
RS
588mouse_moved_to (int x, int y)
589{
eb3f6f01 590 /* If we're in the same place, ignore it. */
6cdfb6e6
RS
591 if (x != movement_pos.X || y != movement_pos.Y)
592 {
42e3a361 593 SELECTED_FRAME ()->mouse_moved = 1;
6cdfb6e6
RS
594 movement_pos.X = x;
595 movement_pos.Y = y;
596 movement_time = GetTickCount ();
597 }
598}
599
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...
605
606 Assume emacs likes three button mice, so
607 Left == 0
608 Middle == 1
609 Right == 2
610 Others increase from there. */
611
1f2fca4b
JR
612#define NUM_TRANSLATED_MOUSE_BUTTONS 3
613static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] =
6cdfb6e6 614{
1f2fca4b 615 0, 2, 1
6cdfb6e6
RS
616};
617
177c0ea7 618static int
6cdfb6e6
RS
619do_mouse_event (MOUSE_EVENT_RECORD *event,
620 struct input_event *emacs_ev)
621{
622 static DWORD button_state = 0;
f12fdf02 623 static Lisp_Object last_mouse_window;
6cdfb6e6
RS
624 DWORD but_change, mask;
625 int i;
177c0ea7 626
6cdfb6e6
RS
627 if (event->dwEventFlags == MOUSE_MOVED)
628 {
42e3a361
EZ
629 FRAME_PTR f = SELECTED_FRAME ();
630 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
f12fdf02 631 int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y;
42e3a361 632
f12fdf02 633 mouse_moved_to (mx, my);
42e3a361
EZ
634
635 if (f->mouse_moved)
636 {
637 if (hlinfo->mouse_face_hidden)
638 {
639 hlinfo->mouse_face_hidden = 0;
640 clear_mouse_face (hlinfo);
641 }
642
f12fdf02
EZ
643 /* Generate SELECT_WINDOW_EVENTs when needed. */
644 if (!NILP (Vmouse_autoselect_window))
645 {
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))
655 {
656 struct input_event event;
657
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);
664 }
665 last_mouse_window = mouse_window;
666 }
667 else
668 last_mouse_window = Qnil;
c4aeb92a
EZ
669
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);
42e3a361 679 }
6cdfb6e6
RS
680 return 0;
681 }
177c0ea7 682
6cdfb6e6
RS
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;
177c0ea7 687
e43bd4f5 688 emacs_ev->kind = MOUSE_CLICK_EVENT;
177c0ea7 689
6cdfb6e6
RS
690 /* Find out what button has changed state since the last button event. */
691 but_change = button_state ^ event->dwButtonState;
692 mask = 1;
1f2fca4b 693 for (i = 0; mask; i++, mask <<= 1)
6cdfb6e6
RS
694 if (but_change & mask)
695 {
1f2fca4b 696 if (i < NUM_TRANSLATED_MOUSE_BUTTONS)
e3ec1dce 697 emacs_ev->code = emacs_button_translation[i];
1f2fca4b 698 else
e3ec1dce 699 emacs_ev->code = i;
6cdfb6e6
RS
700 break;
701 }
702
6cdfb6e6
RS
703 button_state = event->dwButtonState;
704 emacs_ev->timestamp = GetTickCount ();
59131421 705 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, 0) |
6cdfb6e6 706 ((event->dwButtonState & mask) ? down_modifier : up_modifier);
177c0ea7 707
9e539a3c
KH
708 XSETFASTINT (emacs_ev->x, event->dwMousePosition.X);
709 XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y);
daf38066
GV
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
b02466e8 714 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
daf38066 715#endif
177c0ea7 716
6cdfb6e6
RS
717 return 1;
718}
719
177c0ea7 720static void
6cdfb6e6
RS
721resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
722{
723 FRAME_PTR f = get_frame ();
177c0ea7 724
8d59c5ed 725 change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1, 0);
6cdfb6e6
RS
726 SET_FRAME_GARBAGED (f);
727}
728
b7b97897 729static void
b56ceb92 730maybe_generate_resize_event (void)
b7b97897
AI
731{
732 CONSOLE_SCREEN_BUFFER_INFO info;
733 FRAME_PTR f = get_frame ();
734
735 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
736
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,
8d59c5ed 742 0, 0, 0);
b7b97897
AI
743}
744
177c0ea7 745int
9e511e9c
JR
746w32_console_read_socket (struct terminal *terminal,
747 int expected,
748 struct input_event *hold_quit)
6cdfb6e6 749{
6cdfb6e6 750 int nev, ret = 0, add;
59131421
GV
751 int isdead;
752
6cdfb6e6
RS
753 if (interrupt_input_blocked)
754 {
755 interrupt_input_pending = 1;
756 return -1;
757 }
177c0ea7 758
6cdfb6e6
RS
759 interrupt_input_pending = 0;
760 BLOCK_INPUT;
177c0ea7 761
6cdfb6e6
RS
762 for (;;)
763 {
06c2c73d 764 nev = fill_queue (0);
6cdfb6e6
RS
765 if (nev <= 0)
766 {
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;
772 }
773
9cd31aaf 774 while (nev > 0)
6cdfb6e6 775 {
9cd31aaf
KS
776 struct input_event inev;
777
778 EVENT_INIT (inev);
779 inev.kind = NO_EVENT;
780 inev.arg = Qnil;
781
6cdfb6e6
RS
782 switch (queue_ptr->EventType)
783 {
784 case KEY_EVENT:
9cd31aaf 785 add = key_event (&queue_ptr->Event.KeyEvent, &inev, &isdead);
daf38066 786 if (add == -1) /* 95.7.25 by himi */
177c0ea7 787 {
daf38066
GV
788 queue_ptr--;
789 add = 1;
790 }
9cd31aaf
KS
791 if (add)
792 kbd_buffer_store_event_hold (&inev, hold_quit);
6cdfb6e6
RS
793 break;
794
795 case MOUSE_EVENT:
9cd31aaf
KS
796 add = do_mouse_event (&queue_ptr->Event.MouseEvent, &inev);
797 if (add)
798 kbd_buffer_store_event_hold (&inev, hold_quit);
6cdfb6e6
RS
799 break;
800
801 case WINDOW_BUFFER_SIZE_EVENT:
d44c074d
AI
802 if (w32_use_full_screen_buffer)
803 resize_event (&queue_ptr->Event.WindowBufferSizeEvent);
6cdfb6e6 804 break;
177c0ea7 805
6cdfb6e6
RS
806 case MENU_EVENT:
807 case FOCUS_EVENT:
808 /* Internal event types, ignored. */
809 break;
810 }
177c0ea7 811
6cdfb6e6
RS
812 queue_ptr++;
813 nev--;
814 }
815
816 if (ret > 0 || expected == 0)
817 break;
818 }
b7b97897
AI
819
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. */
d44c074d
AI
823 if (!w32_use_full_screen_buffer)
824 maybe_generate_resize_event ();
b7b97897 825
6cdfb6e6
RS
826 UNBLOCK_INPUT;
827 return ret;
828}