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