1/* Input event support for Emacs on the Microsoft W32 API. 2 Copyright (C) 1992, 1993, 1995, 2001, 2002, 2003, 2004, 3 2005, 2006, 2007 Free Software Foundation, Inc. 4 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 19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20Boston, MA 02110-1301, USA. 21 22 Drew Bliss 01-Oct-93 23 Adapted from ntkbd.c by Tim Fleehart 24*/ 25 26 27#ifdef HAVE_CONFIG_H 28#include <config.h> 29#endif 30 31#include <stdlib.h> 32#include <stdio.h> 33#include <windows.h> 34 35#ifndef MOUSE_MOVED 36#define MOUSE_MOVED 1 37#endif 38 39#include "lisp.h" 40#include "keyboard.h" 41#include "frame.h" 42#include "blockinput.h" 43#include "termhooks.h" 44#include "w32heap.h" 45#include "w32term.h" 46 47/* stdin, from ntterm */ 48extern HANDLE keyboard_handle; 49 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 60/* from w32console.c */ 61extern int w32_use_full_screen_buffer; 62 63/* from w32fns.c */ 64extern Lisp_Object Vw32_alt_is_meta; 65extern unsigned int map_keypad_keys (unsigned int, unsigned int); 66 67/* from w32term */ 68extern Lisp_Object Vw32_capslock_is_shiftlock; 69extern Lisp_Object Vw32_enable_caps_lock; 70extern Lisp_Object Vw32_enable_num_lock; 71extern Lisp_Object Vw32_recognize_altgr; 72extern Lisp_Object Vw32_pass_lwindow_to_system; 73extern Lisp_Object Vw32_pass_rwindow_to_system; 74extern Lisp_Object Vw32_phantom_key_code; 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); 80 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 86static int 87fill_queue (BOOL block) 88{ 89 BOOL rc; 90 DWORD events_waiting; 91 92 if (queue_ptr < queue_end) 93 return queue_end-queue_ptr; 94 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 } 104 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. */ 118static FRAME_PTR 119get_frame (void) 120{ 121 return SELECTED_FRAME (); 122} 123 124/* Translate console modifiers to emacs modifiers. 125 German keyboard support (Kai Morgan Zeise 2/18/95). */ 126int 127w32_kbd_mods_to_emacs (DWORD mods, WORD key) 128{ 129 int retval = 0; 130 131 /* If we recognize right-alt and left-ctrl as AltGr, and it has been 132 pressed, first remove those modifiers. */ 133 if (!NILP (Vw32_recognize_altgr) 134 && (mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) 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)) 139 retval = ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier); 140 141 if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) 142 { 143 retval |= ctrl_modifier; 144 if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) 145 == (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) 146 retval |= meta_modifier; 147 } 148 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 158 /* Just in case someone wanted the original behaviour, make it 159 optional by setting w32-capslock-is-shiftlock to t. */ 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 )) 171 { 172 /* Only consider shift state. */ 173 if ((mods & SHIFT_PRESSED) != 0) 174 retval |= shift_modifier; 175 } 176 else 177 { 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; 183 } 184 185 return retval; 186} 187 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 200/* The return code indicates key code size. */ 201int 202w32_kbd_patch_key (KEY_EVENT_RECORD *event) 203{ 204 unsigned int key_code = event->wVirtualKeyCode; 205 unsigned int mods = event->dwControlKeyState; 206 BYTE keystate[256]; 207 static BYTE ansi_code[4]; 208 static int isdead = 0; 209 210 if (isdead == 2) 211 { 212 event->uChar.AsciiChar = ansi_code[2]; 213 isdead = 0; 214 return 1; 215 } 216 if (event->uChar.AsciiChar != 0) 217 return 1; 218 219 memset (keystate, 0, sizeof (keystate)); 220 keystate[key_code] = 0x80; 221 if (mods & SHIFT_PRESSED) 222 keystate[VK_SHIFT] = 0x80; 223 if (mods & CAPSLOCK_ON) 224 keystate[VK_CAPITAL] = 1; 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)) 229 { 230 keystate[VK_CONTROL] = 0x80; 231 keystate[VK_LCONTROL] = 0x80; 232 keystate[VK_MENU] = 0x80; 233 keystate[VK_RMENU] = 0x80; 234 } 235 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 276 if (isdead == 0) 277 return 0; 278 event->uChar.AsciiChar = ansi_code[0]; 279 return isdead; 280} 281 282 283extern char *lispy_function_keys[]; 284 285static int faked_key = 0; 286 287/* return code -1 means that event_queue_ptr won't be incremented. 288 In other word, this event makes two key codes. (by himi) */ 289int 290key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead) 291{ 292 static int mod_key_state = 0; 293 int wParam; 294 295 *isdead = 0; 296 297 /* Skip key-up events. */ 298 if (!event->bKeyDown) 299 { 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 } 312 return 0; 313 } 314 315 /* Ignore keystrokes we fake ourself; see below. */ 316 if (faked_key == event->wVirtualKeyCode) 317 { 318 faked_key = 0; 319 return 0; 320 } 321 322 /* To make it easier to debug this code, ignore modifier keys! */ 323 switch (event->wVirtualKeyCode) 324 { 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 { 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); 338 } 339 } 340 mod_key_state |= LEFT_WIN_PRESSED; 341 if (!NILP (Vw32_lwindow_modifier)) 342 return 0; 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 { 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); 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; 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; 418 } 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) 429 { 430 emacs_ev->kind = ASCII_KEYSTROKE_EVENT; 431 432 if (!NILP (Vw32_recognize_altgr) 433 && (event->dwControlKeyState & LEFT_CTRL_PRESSED) 434 && (event->dwControlKeyState & RIGHT_ALT_PRESSED)) 435 { 436 /* Don't try to interpret AltGr key chords; ToAscii seems not 437 to process them correctly. */ 438 } 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) 467 return 0; 468 emacs_ev->code = event->uChar.AsciiChar; 469 } 470 else 471 { 472 emacs_ev->kind = NON_ASCII_KEYSTROKE_EVENT; 473 emacs_ev->code = event->wVirtualKeyCode; 474 } 475 476 XSETFRAME (emacs_ev->frame_or_window, get_frame ()); 477 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, 478 event->wVirtualKeyCode); 479 emacs_ev->timestamp = GetTickCount (); 480 return 1; 481} 482 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) 490 && ((XUINT (new_state)) & 1) != cur_state)) 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 509/* Mouse position hook. */ 510void 511w32_console_mouse_position (FRAME_PTR *f, 512 int insist, 513 Lisp_Object *bar_window, 514 enum scroll_bar_part *part, 515 Lisp_Object *x, 516 Lisp_Object *y, 517 unsigned long *time) 518{ 519 BLOCK_INPUT; 520 521 insist = insist; 522 523 *f = get_frame (); 524 *bar_window = Qnil; 525 *part = 0; 526 SELECTED_FRAME ()->mouse_moved = 0; 527 528 XSETINT(*x, movement_pos.X); 529 XSETINT(*y, movement_pos.Y); 530 *time = movement_time; 531 532 UNBLOCK_INPUT; 533} 534 535/* Remember mouse motion and notify emacs. */ 536static void 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 { 542 SELECTED_FRAME ()->mouse_moved = 1; 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 561#define NUM_TRANSLATED_MOUSE_BUTTONS 3 562static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] = 563{ 564 0, 2, 1 565}; 566 567static int 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; 574 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 } 582 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; 587 588 emacs_ev->kind = MOUSE_CLICK_EVENT; 589 590 /* Find out what button has changed state since the last button event. */ 591 but_change = button_state ^ event->dwButtonState; 592 mask = 1; 593 for (i = 0; mask; i++, mask <<= 1) 594 if (but_change & mask) 595 { 596 if (i < NUM_TRANSLATED_MOUSE_BUTTONS) 597 emacs_ev->code = emacs_button_translation[i]; 598 else 599 emacs_ev->code = i; 600 break; 601 } 602 603 button_state = event->dwButtonState; 604 emacs_ev->timestamp = GetTickCount (); 605 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, 0) | 606 ((event->dwButtonState & mask) ? down_modifier : up_modifier); 607 608 XSETFASTINT (emacs_ev->x, event->dwMousePosition.X); 609 XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y); 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 614 XSETFRAME (emacs_ev->frame_or_window, get_frame ()); 615#endif 616 617 return 1; 618} 619 620static void 621resize_event (WINDOW_BUFFER_SIZE_RECORD *event) 622{ 623 FRAME_PTR f = get_frame (); 624 625 change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1); 626 SET_FRAME_GARBAGED (f); 627} 628 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 645int 646w32_console_read_socket (int sd, int expected, struct input_event *hold_quit) 647{ 648 BOOL no_events = TRUE; 649 int nev, ret = 0, add; 650 int isdead; 651 652 if (interrupt_input_blocked) 653 { 654 interrupt_input_pending = 1; 655 return -1; 656 } 657 658 interrupt_input_pending = 0; 659 BLOCK_INPUT; 660 661 for (;;) 662 { 663 nev = fill_queue (0); 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 673 while (nev > 0) 674 { 675 struct input_event inev; 676 677 EVENT_INIT (inev); 678 inev.kind = NO_EVENT; 679 inev.arg = Qnil; 680 681 switch (queue_ptr->EventType) 682 { 683 case KEY_EVENT: 684 add = key_event (&queue_ptr->Event.KeyEvent, &inev, &isdead); 685 if (add == -1) /* 95.7.25 by himi */ 686 { 687 queue_ptr--; 688 add = 1; 689 } 690 if (add) 691 kbd_buffer_store_event_hold (&inev, hold_quit); 692 break; 693 694 case MOUSE_EVENT: 695 add = do_mouse_event (&queue_ptr->Event.MouseEvent, &inev); 696 if (add) 697 kbd_buffer_store_event_hold (&inev, hold_quit); 698 break; 699 700 case WINDOW_BUFFER_SIZE_EVENT: 701 if (w32_use_full_screen_buffer) 702 resize_event (&queue_ptr->Event.WindowBufferSizeEvent); 703 break; 704 705 case MENU_EVENT: 706 case FOCUS_EVENT: 707 /* Internal event types, ignored. */ 708 break; 709 } 710 711 queue_ptr++; 712 nev--; 713 } 714 715 if (ret > 0 || expected == 0) 716 break; 717 } 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. */ 722 if (!w32_use_full_screen_buffer) 723 maybe_generate_resize_event (); 724 725 UNBLOCK_INPUT; 726 return ret; 727} 728 729/* arch-tag: 0bcb39b7-d085-4b85-9070-6750e8c03047 730 (do not change this comment) */ 731