X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/5a6816daacc3e7c9becacec7588f91c418e08683..4d46d6da26dec27e033459c55902c8ee8d5e1d43:/src/w32inevt.c diff --git a/src/w32inevt.c b/src/w32inevt.c index 2549d1609d..6a0b5e5f1a 100644 --- a/src/w32inevt.c +++ b/src/w32inevt.c @@ -1,4 +1,4 @@ -/* Input event support for Windows NT port of GNU Emacs. +/* Input event support for Emacs on the Microsoft W32 API. Copyright (C) 1992, 1993, 1995 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -23,16 +23,25 @@ Boston, MA 02111-1307, USA. */ -#include "config.h" +#ifdef HAVE_CONFIG_H +#include +#endif #include #include #include +#ifndef MOUSE_MOVED +#define MOUSE_MOVED 1 +#endif + #include "lisp.h" +#include "keyboard.h" #include "frame.h" #include "blockinput.h" #include "termhooks.h" +#include "w32heap.h" +#include "w32term.h" /* stdin, from ntterm */ extern HANDLE keyboard_handle; @@ -47,8 +56,26 @@ extern void reinvoke_input_signal (void); /* from dispnew.c */ extern int change_frame_size (FRAME_PTR, int, int, int, int); +/* from w32console.c */ +extern int w32_use_full_screen_buffer; + /* from w32fns.c */ -extern Lisp_Object Vwin32_alt_is_meta; +extern Lisp_Object Vw32_alt_is_meta; +extern unsigned int map_keypad_keys (unsigned int, unsigned int); + +/* from w32term */ +extern Lisp_Object Vw32_capslock_is_shiftlock; +extern Lisp_Object Vw32_enable_caps_lock; +extern Lisp_Object Vw32_enable_num_lock; +extern Lisp_Object Vw32_recognize_altgr; +extern Lisp_Object Vw32_pass_lwindow_to_system; +extern Lisp_Object Vw32_pass_rwindow_to_system; +extern Lisp_Object Vw32_phantom_key_code; +extern Lisp_Object Vw32_lwindow_modifier; +extern Lisp_Object Vw32_rwindow_modifier; +extern Lisp_Object Vw32_apps_modifier; +extern Lisp_Object Vw32_scroll_lock_modifier; +extern unsigned int w32_key_to_modifier (int key); /* Event queue */ #define EVENT_QUEUE_SIZE 50 @@ -90,23 +117,25 @@ fill_queue (BOOL block) static FRAME_PTR get_frame (void) { - return selected_frame; + return SELECTED_FRAME (); } /* Translate console modifiers to emacs modifiers. German keyboard support (Kai Morgan Zeise 2/18/95). */ int -win32_kbd_mods_to_emacs (DWORD mods) +w32_kbd_mods_to_emacs (DWORD mods, WORD key) { int retval = 0; - /* If AltGr has been pressed, remove it. */ - if ((mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) + /* If we recognize right-alt and left-ctrl as AltGr, and it has been + pressed, first remove those modifiers. */ + if (!NILP (Vw32_recognize_altgr) + && (mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) mods &= ~ (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED); if (mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) - retval = ((NILP (Vwin32_alt_is_meta)) ? alt_modifier : meta_modifier); + retval = ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier); if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) { @@ -116,16 +145,60 @@ win32_kbd_mods_to_emacs (DWORD mods) retval |= meta_modifier; } - if (((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) == SHIFT_PRESSED) - || ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) == CAPSLOCK_ON)) - retval |= shift_modifier; + if (mods & LEFT_WIN_PRESSED) + retval |= w32_key_to_modifier (VK_LWIN); + if (mods & RIGHT_WIN_PRESSED) + retval |= w32_key_to_modifier (VK_RWIN); + if (mods & APPS_PRESSED) + retval |= w32_key_to_modifier (VK_APPS); + if (mods & SCROLLLOCK_ON) + retval |= w32_key_to_modifier (VK_SCROLL); + + /* Just in case someone wanted the original behaviour, make it + optional by setting w32-capslock-is-shiftlock to t. */ + if (NILP (Vw32_capslock_is_shiftlock) + /* Keys that should _not_ be affected by CapsLock. */ + && ( (key == VK_BACK) + || (key == VK_TAB) + || (key == VK_CLEAR) + || (key == VK_RETURN) + || (key == VK_ESCAPE) + || ((key >= VK_SPACE) && (key <= VK_HELP)) + || ((key >= VK_NUMPAD0) && (key <= VK_F24)) + || ((key >= VK_NUMPAD_CLEAR) && (key <= VK_NUMPAD_DELETE)) + )) + { + /* Only consider shift state. */ + if ((mods & SHIFT_PRESSED) != 0) + retval |= shift_modifier; + } + else + { + /* Ignore CapsLock state if not enabled. */ + if (NILP (Vw32_enable_caps_lock)) + mods &= ~CAPSLOCK_ON; + if ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) != 0) + retval |= shift_modifier; + } return retval; } +#if 0 +/* Return nonzero if the virtual key is a dead key. */ +static int +is_dead_key (int wparam) +{ + unsigned int code = MapVirtualKey (wparam, 2); + + /* Windows 95 returns 0x8000, NT returns 0x80000000. */ + return (code & 0x80008000) ? 1 : 0; +} +#endif + /* The return code indicates key code size. */ int -win32_kbd_patch_key (KEY_EVENT_RECORD *event) +w32_kbd_patch_key (KEY_EVENT_RECORD *event) { unsigned int key_code = event->wVirtualKeyCode; unsigned int mods = event->dwControlKeyState; @@ -143,11 +216,15 @@ win32_kbd_patch_key (KEY_EVENT_RECORD *event) return 1; memset (keystate, 0, sizeof (keystate)); + keystate[key_code] = 0x80; if (mods & SHIFT_PRESSED) keystate[VK_SHIFT] = 0x80; if (mods & CAPSLOCK_ON) keystate[VK_CAPITAL] = 1; - if ((mods & LEFT_CTRL_PRESSED) && (mods & RIGHT_ALT_PRESSED)) + /* If we recognize right-alt and left-ctrl as AltGr, set the key + states accordingly before invoking ToAscii. */ + if (!NILP (Vw32_recognize_altgr) + && (mods & LEFT_CTRL_PRESSED) && (mods & RIGHT_ALT_PRESSED)) { keystate[VK_CONTROL] = 0x80; keystate[VK_LCONTROL] = 0x80; @@ -155,254 +232,297 @@ win32_kbd_patch_key (KEY_EVENT_RECORD *event) keystate[VK_RMENU] = 0x80; } - isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode, - keystate, (LPWORD) ansi_code, 0); +#if 0 + /* Because of an OS bug, ToAscii corrupts the stack when called to + convert a dead key in console mode on NT4. Unfortunately, trying + to check for dead keys using MapVirtualKey doesn't work either - + these functions apparently use internal information about keyboard + layout which doesn't get properly updated in console programs when + changing layout (though apparently it gets partly updated, + otherwise ToAscii wouldn't crash). */ + if (is_dead_key (event->wVirtualKeyCode)) + return 0; +#endif + + /* On NT, call ToUnicode instead and then convert to the current + locale's default codepage. */ + if (os_subtype == OS_NT) + { + WCHAR buf[128]; + + isdead = ToUnicode (event->wVirtualKeyCode, event->wVirtualScanCode, + keystate, buf, 128, 0); + if (isdead > 0) + { + char cp[20]; + int cpId; + + GetLocaleInfo (GetThreadLocale (), + LOCALE_IDEFAULTANSICODEPAGE, cp, 20); + cpId = atoi (cp); + isdead = WideCharToMultiByte (cpId, 0, buf, isdead, + ansi_code, 4, NULL, NULL); + } + else + isdead = 0; + } + else + { + isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode, + keystate, (LPWORD) ansi_code, 0); + } + if (isdead == 0) return 0; event->uChar.AsciiChar = ansi_code[0]; return isdead; } -/* Map virtual key codes into: - -1 - Ignore this key - -2 - ASCII char - Other - Map non-ASCII keys into X keysyms so that they are looked up - correctly in keyboard.c - Return, escape and tab are mapped to ASCII rather than coming back - as non-ASCII to be more compatible with old-style keyboard support. */ +extern char *lispy_function_keys[]; -static int map_virt_key[256] = -{ -#ifdef MULE - -3, -#else - -1, -#endif - -1, /* VK_LBUTTON */ - -1, /* VK_RBUTTON */ - 0x69, /* VK_CANCEL */ - -1, /* VK_MBUTTON */ - -1, -1, -1, - 8, /* VK_BACK */ - -2, /* VK_TAB */ - -1, -1, - 11, /* VK_CLEAR */ - -2, /* VK_RETURN */ - -1, -1, - -1, /* VK_SHIFT */ - -1, /* VK_CONTROL */ - -1, /* VK_MENU */ - 0x13, /* VK_PAUSE */ - -1, /* VK_CAPITAL */ - -1, -1, -1, -1, -1, -1, - -2, /* VK_ESCAPE */ - -1, -1, -1, -1, - -2, /* VK_SPACE */ - 0x55, /* VK_PRIOR */ - 0x56, /* VK_NEXT */ - 0x57, /* VK_END */ - 0x50, /* VK_HOME */ - 0x51, /* VK_LEFT */ - 0x52, /* VK_UP */ - 0x53, /* VK_RIGHT */ - 0x54, /* VK_DOWN */ - 0x60, /* VK_SELECT */ - 0x61, /* VK_PRINT */ - 0x62, /* VK_EXECUTE */ - -1, /* VK_SNAPSHOT */ - 0x63, /* VK_INSERT */ - 0xff, /* VK_DELETE */ - 0x6a, /* VK_HELP */ - -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, /* 0 - 9 */ - -1, -1, -1, -1, -1, -1, -1, - -2, -2, -2, -2, -2, -2, -2, -2, /* A - Z */ - -2, -2, -2, -2, -2, -2, -2, -2, - -2, -2, -2, -2, -2, -2, -2, -2, - -2, -2, - -1, -1, -1, -1, -1, - 0xb0, /* VK_NUMPAD0 */ - 0xb1, /* VK_NUMPAD1 */ - 0xb2, /* VK_NUMPAD2 */ - 0xb3, /* VK_NUMPAD3 */ - 0xb4, /* VK_NUMPAD4 */ - 0xb5, /* VK_NUMPAD5 */ - 0xb6, /* VK_NUMPAD6 */ - 0xb7, /* VK_NUMPAD7 */ - 0xb8, /* VK_NUMPAD8 */ - 0xb9, /* VK_NUMPAD9 */ - 0xaa, /* VK_MULTIPLY */ - 0xab, /* VK_ADD */ - 0xac, /* VK_SEPARATOR */ - 0xad, /* VK_SUBTRACT */ - 0xae, /* VK_DECIMAL */ - 0xaf, /* VK_DIVIDE */ - 0xbe, /* VK_F1 */ - 0xbf, /* VK_F2 */ - 0xc0, /* VK_F3 */ - 0xc1, /* VK_F4 */ - 0xc2, /* VK_F5 */ - 0xc3, /* VK_F6 */ - 0xc4, /* VK_F7 */ - 0xc5, /* VK_F8 */ - 0xc6, /* VK_F9 */ - 0xc7, /* VK_F10 */ - 0xc8, /* VK_F11 */ - 0xc9, /* VK_F12 */ - 0xca, /* VK_F13 */ - 0xcb, /* VK_F14 */ - 0xcc, /* VK_F15 */ - 0xcd, /* VK_F16 */ - 0xce, /* VK_F17 */ - 0xcf, /* VK_F18 */ - 0xd0, /* VK_F19 */ - 0xd1, /* VK_F20 */ - 0xd2, /* VK_F21 */ - 0xd3, /* VK_F22 */ - 0xd4, /* VK_F23 */ - 0xd5, /* VK_F24 */ - -1, -1, -1, -1, -1, -1, -1, -1, - 0x7f, /* VK_NUMLOCK */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x9f */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xaf */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb9 */ - -2, /* ; */ - -2, /* = */ - -2, /* , */ - -2, /* \ */ - -2, /* . */ - -2, /* / */ - -2, /* ` */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xcf */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xda */ - -2, -2, -2, -2, -2, /* 0xdf */ - -2, -2, -2, -2, -2, - -1, /* 0xe5 */ - -2, /* oxe6 */ - -1, -1, /* 0xe8 */ - -2, -2, -2, -2, -2, -2, -2, /* 0xef */ - -2, -2, -2, -2, -2, -2, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xff */ -}; +static int faked_key = 0; /* return code -1 means that event_queue_ptr won't be incremented. In other word, this event makes two key codes. (by himi) */ int -key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev) +key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead) { - int map; - int key_flag = 0; - static BOOL map_virt_key_init_done; - + static int mod_key_state = 0; + int wParam; + + *isdead = 0; + /* Skip key-up events. */ if (!event->bKeyDown) - return 0; - - if (event->wVirtualKeyCode > 0xff) { - printf ("Unknown key code %d\n", event->wVirtualKeyCode); + switch (event->wVirtualKeyCode) + { + case VK_LWIN: + mod_key_state &= ~LEFT_WIN_PRESSED; + break; + case VK_RWIN: + mod_key_state &= ~RIGHT_WIN_PRESSED; + break; + case VK_APPS: + mod_key_state &= ~APPS_PRESSED; + break; + } return 0; } - /* Patch needed for German keyboard. Ulrich Leodolter (1/11/95). */ - if (! map_virt_key_init_done) - { - short vk; - - if ((vk = VkKeyScan (0x3c)) >= 0 && vk < 256) map_virt_key[vk] = -2; /* less */ - if ((vk = VkKeyScan (0x3e)) >= 0 && vk < 256) map_virt_key[vk] = -2; /* greater */ - - map_virt_key_init_done = TRUE; - } - - /* BUGBUG - Ignores the repeat count - It's questionable whether we want to obey the repeat count anyway - since keys usually aren't repeated unless key events back up in - the queue. If they're backing up then we don't generally want - to honor them later since that leads to significant slop in - cursor motion when the system is under heavy load. */ - - map = map_virt_key[event->wVirtualKeyCode]; - if (map == -1) + /* Ignore keystrokes we fake ourself; see below. */ + if (faked_key == event->wVirtualKeyCode) { + faked_key = 0; return 0; } - else if (map == -2) + + /* To make it easier to debug this code, ignore modifier keys! */ + switch (event->wVirtualKeyCode) { - /* ASCII */ - emacs_ev->kind = ascii_keystroke; - key_flag = win32_kbd_patch_key (event); /* 95.7.25 by himi */ - if (key_flag == 0) + case VK_LWIN: + if (NILP (Vw32_pass_lwindow_to_system)) + { + /* Prevent system from acting on keyup (which opens the Start + menu if no other key was pressed) by simulating a press of + Space which we will ignore. */ + if ((mod_key_state & LEFT_WIN_PRESSED) == 0) + { + if (NUMBERP (Vw32_phantom_key_code)) + faked_key = XUINT (Vw32_phantom_key_code) & 255; + else + faked_key = VK_SPACE; + keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0); + } + } + mod_key_state |= LEFT_WIN_PRESSED; + if (!NILP (Vw32_lwindow_modifier)) return 0; - XSETINT (emacs_ev->code, event->uChar.AsciiChar); + break; + case VK_RWIN: + if (NILP (Vw32_pass_rwindow_to_system)) + { + if ((mod_key_state & RIGHT_WIN_PRESSED) == 0) + { + if (NUMBERP (Vw32_phantom_key_code)) + faked_key = XUINT (Vw32_phantom_key_code) & 255; + else + faked_key = VK_SPACE; + keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0); + } + } + mod_key_state |= RIGHT_WIN_PRESSED; + if (!NILP (Vw32_rwindow_modifier)) + return 0; + break; + case VK_APPS: + mod_key_state |= APPS_PRESSED; + if (!NILP (Vw32_apps_modifier)) + return 0; + break; + case VK_CAPITAL: + /* Decide whether to treat as modifier or function key. */ + if (NILP (Vw32_enable_caps_lock)) + goto disable_lock_key; + return 0; + case VK_NUMLOCK: + /* Decide whether to treat as modifier or function key. */ + if (NILP (Vw32_enable_num_lock)) + goto disable_lock_key; + return 0; + case VK_SCROLL: + /* Decide whether to treat as modifier or function key. */ + if (NILP (Vw32_scroll_lock_modifier)) + goto disable_lock_key; + return 0; + disable_lock_key: + /* Ensure the appropriate lock key state is off (and the + indicator light as well). */ + wParam = event->wVirtualKeyCode; + if (GetAsyncKeyState (wParam) & 0x8000) + { + /* Fake another press of the relevant key. Apparently, this + really is the only way to turn off the indicator. */ + faked_key = wParam; + keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), + KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); + keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), + KEYEVENTF_EXTENDEDKEY | 0, 0); + keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), + KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); + } + break; + case VK_MENU: + case VK_CONTROL: + case VK_SHIFT: + return 0; + case VK_CANCEL: + /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL, + which is confusing for purposes of key binding; convert + VK_CANCEL events into VK_PAUSE events. */ + event->wVirtualKeyCode = VK_PAUSE; + break; + case VK_PAUSE: + /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing + for purposes of key binding; convert these back into + VK_NUMLOCK events, at least when we want to see NumLock key + presses. (Note that there is never any possibility that + VK_PAUSE with Ctrl really is C-Pause as per above.) */ + if (NILP (Vw32_enable_num_lock) + && (event->dwControlKeyState + & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0) + event->wVirtualKeyCode = VK_NUMLOCK; + break; } -#ifdef MULE - /* for IME */ - else if (map == -3) + + /* Recognize state of Windows and Apps keys. */ + event->dwControlKeyState |= mod_key_state; + + /* Distinguish numeric keypad keys from extended keys. */ + event->wVirtualKeyCode = + map_keypad_keys (event->wVirtualKeyCode, + (event->dwControlKeyState & ENHANCED_KEY)); + + if (lispy_function_keys[event->wVirtualKeyCode] == 0) { - if ((event->dwControlKeyState & NLS_IME_CONVERSION) - && !(event->dwControlKeyState & RIGHT_ALT_PRESSED) - && !(event->dwControlKeyState & LEFT_ALT_PRESSED) - && !(event->dwControlKeyState & RIGHT_CTRL_PRESSED) - && !(event->dwControlKeyState & LEFT_CTRL_PRESSED)) + emacs_ev->kind = ASCII_KEYSTROKE_EVENT; + + if (!NILP (Vw32_recognize_altgr) + && (event->dwControlKeyState & LEFT_CTRL_PRESSED) + && (event->dwControlKeyState & RIGHT_ALT_PRESSED)) { - emacs_ev->kind = ascii_keystroke; - XSETINT (emacs_ev->code, event->uChar.AsciiChar); + /* Don't try to interpret AltGr key chords; ToAscii seems not + to process them correctly. */ } - else + /* Handle key chords including any modifiers other than shift + directly, in order to preserve as much modifier information as + possible. */ + else if (event->dwControlKeyState + & ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED + | RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED + | (!NILP (Vw32_lwindow_modifier) ? LEFT_WIN_PRESSED : 0) + | (!NILP (Vw32_rwindow_modifier) ? RIGHT_WIN_PRESSED : 0) + | (!NILP (Vw32_apps_modifier) ? APPS_PRESSED : 0) + | (!NILP (Vw32_scroll_lock_modifier) ? SCROLLLOCK_ON : 0))) + { + /* Don't translate modified alphabetic keystrokes, so the user + doesn't need to constantly switch layout to type control or + meta keystrokes when the normal layout translates + alphabetic characters to non-ascii characters. */ + if ('A' <= event->wVirtualKeyCode && event->wVirtualKeyCode <= 'Z') + { + event->uChar.AsciiChar = event->wVirtualKeyCode; + if ((event->dwControlKeyState & SHIFT_PRESSED) == 0) + event->uChar.AsciiChar += ('a' - 'A'); + } + /* Try to handle unrecognized keystrokes by determining the + base character (ie. translating the base key plus shift + modifier). */ + else if (event->uChar.AsciiChar == 0) + w32_kbd_patch_key (event); + } + if (event->uChar.AsciiChar == 0) return 0; + XSETINT (emacs_ev->code, event->uChar.AsciiChar); } -#endif else { - /* non-ASCII */ - emacs_ev->kind = non_ascii_keystroke; -#ifdef HAVE_NTGUI - /* use Windows keysym map */ + emacs_ev->kind = NON_ASCII_KEYSTROKE_EVENT; XSETINT (emacs_ev->code, event->wVirtualKeyCode); -#else - /* - * make_lispy_event () now requires non-ascii codes to have - * the full X keysym values (2nd byte is 0xff). add it on. - */ - map |= 0xff00; - XSETINT (emacs_ev->code, map); -#endif /* HAVE_NTGUI */ } -/* for Mule 2.2 (Based on Emacs 19.28) */ -#ifdef MULE - XSET (emacs_ev->frame_or_window, Lisp_Frame, get_frame ()); -#else + XSETFRAME (emacs_ev->frame_or_window, get_frame ()); -#endif - emacs_ev->modifiers = win32_kbd_mods_to_emacs (event->dwControlKeyState); + emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, + event->wVirtualKeyCode); emacs_ev->timestamp = GetTickCount (); - if (key_flag == 2) return -1; /* 95.7.25 by himi */ return 1; } +int +w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state) +{ + int cur_state = (GetKeyState (vk_code) & 1); + + if (NILP (new_state) + || (NUMBERP (new_state) + && ((XUINT (new_state)) & 1) != cur_state)) + { + faked_key = vk_code; + + keybd_event ((BYTE) vk_code, + (BYTE) MapVirtualKey (vk_code, 0), + KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); + keybd_event ((BYTE) vk_code, + (BYTE) MapVirtualKey (vk_code, 0), + KEYEVENTF_EXTENDEDKEY | 0, 0); + keybd_event ((BYTE) vk_code, + (BYTE) MapVirtualKey (vk_code, 0), + KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); + cur_state = !cur_state; + } + + return cur_state; +} + /* Mouse position hook. */ void -win32_mouse_position (FRAME_PTR *f, -#ifndef MULE - int insist, -#endif - Lisp_Object *bar_window, - enum scroll_bar_part *part, - Lisp_Object *x, - Lisp_Object *y, - unsigned long *time) +w32_console_mouse_position (FRAME_PTR *f, + int insist, + Lisp_Object *bar_window, + enum scroll_bar_part *part, + Lisp_Object *x, + Lisp_Object *y, + unsigned long *time) { BLOCK_INPUT; -#ifndef MULE insist = insist; -#endif *f = get_frame (); *bar_window = Qnil; *part = 0; - selected_frame->mouse_moved = 0; + SELECTED_FRAME ()->mouse_moved = 0; *x = movement_pos.X; *y = movement_pos.Y; @@ -418,7 +538,7 @@ mouse_moved_to (int x, int y) /* If we're in the same place, ignore it */ if (x != movement_pos.X || y != movement_pos.Y) { - selected_frame->mouse_moved = 1; + SELECTED_FRAME ()->mouse_moved = 1; movement_pos.X = x; movement_pos.Y = y; movement_time = GetTickCount (); @@ -437,9 +557,10 @@ mouse_moved_to (int x, int y) Right == 2 Others increase from there. */ -static int emacs_button_translation[NUM_MOUSE_BUTTONS] = +#define NUM_TRANSLATED_MOUSE_BUTTONS 3 +static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] = { - 0, 2, 1, 3, 4, + 0, 2, 1 }; static int @@ -463,26 +584,24 @@ do_mouse_event (MOUSE_EVENT_RECORD *event, if (event->dwButtonState == button_state) return 0; - emacs_ev->kind = mouse_click; + emacs_ev->kind = MOUSE_CLICK_EVENT; /* Find out what button has changed state since the last button event. */ but_change = button_state ^ event->dwButtonState; mask = 1; - for (i = 0; i < NUM_MOUSE_BUTTONS; i++, mask <<= 1) + for (i = 0; mask; i++, mask <<= 1) if (but_change & mask) { - XSETINT (emacs_ev->code, emacs_button_translation[i]); + if (i < NUM_TRANSLATED_MOUSE_BUTTONS) + XSETINT (emacs_ev->code, emacs_button_translation[i]); + else + XSETINT (emacs_ev->code, i); break; } - /* If the changed button is out of emacs' range (highly unlikely) - ignore this event. */ - if (i == NUM_MOUSE_BUTTONS) - return 0; - button_state = event->dwButtonState; emacs_ev->timestamp = GetTickCount (); - emacs_ev->modifiers = win32_kbd_mods_to_emacs (event->dwControlKeyState) | + emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, 0) | ((event->dwButtonState & mask) ? down_modifier : up_modifier); XSETFASTINT (emacs_ev->x, event->dwMousePosition.X); @@ -506,13 +625,30 @@ resize_event (WINDOW_BUFFER_SIZE_RECORD *event) SET_FRAME_GARBAGED (f); } +static void +maybe_generate_resize_event () +{ + CONSOLE_SCREEN_BUFFER_INFO info; + FRAME_PTR f = get_frame (); + + GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info); + + /* It is okay to call this unconditionally, since it will do nothing + if the size hasn't actually changed. */ + change_frame_size (f, + 1 + info.srWindow.Bottom - info.srWindow.Top, + 1 + info.srWindow.Right - info.srWindow.Left, + 0, 0); +} + int -win32_read_socket (int sd, struct input_event *bufp, int numchars, - int waitp, int expected) +w32_console_read_socket (int sd, struct input_event *bufp, int numchars, + int expected) { BOOL no_events = TRUE; int nev, ret = 0, add; - + int isdead; + if (interrupt_input_blocked) { interrupt_input_pending = 1; @@ -524,7 +660,7 @@ win32_read_socket (int sd, struct input_event *bufp, int numchars, for (;;) { - nev = fill_queue (waitp != 0); + nev = fill_queue (0); if (nev <= 0) { /* If nev == -1, there was some kind of error @@ -539,7 +675,7 @@ win32_read_socket (int sd, struct input_event *bufp, int numchars, switch (queue_ptr->EventType) { case KEY_EVENT: - add = key_event (&queue_ptr->Event.KeyEvent, bufp); + add = key_event (&queue_ptr->Event.KeyEvent, bufp, &isdead); if (add == -1) /* 95.7.25 by himi */ { queue_ptr--; @@ -558,7 +694,8 @@ win32_read_socket (int sd, struct input_event *bufp, int numchars, break; case WINDOW_BUFFER_SIZE_EVENT: - resize_event (&queue_ptr->Event.WindowBufferSizeEvent); + if (w32_use_full_screen_buffer) + resize_event (&queue_ptr->Event.WindowBufferSizeEvent); break; case MENU_EVENT: @@ -574,7 +711,13 @@ win32_read_socket (int sd, struct input_event *bufp, int numchars, if (ret > 0 || expected == 0) break; } - + + /* We don't get told about changes in the window size (only the buffer + size, which we no longer care about), so we have to check it + periodically. */ + if (!w32_use_full_screen_buffer) + maybe_generate_resize_event (); + UNBLOCK_INPUT; return ret; }