comparison src/w32fns.c @ 23681:af0276da2059

(Vw32_pass_optional_keys_to_system): Variable removed. (Vw32_pass_lwindow_to_system): (Vw32_pass_rwindow_to_system): (Vw32_lwindow_modifier): (Vw32_rwindow_modifier): (Vw32_apps_modifier): (Vw32_enable_num_lock): (Vw32_enable_caps_lock): (Vw32_scroll_lock_modifier): New variables. (modifier_set): Return toggle state for Scroll Lock. (w32_key_to_modifier): New function. Returns chosen modifier bit for given key. (w32_get_modifiers): Returns modifier flags for non-keyboard input events. (construct_console_modifiers): Renamed from construct_modifiers; recognize Windows and Apps keys as modifiers. (w32_get_key_modifiers): New function. Returns modifier flags for keyboard input events. (map_keypad_keys): Make non-static. Use second arg as extended flag. (w32_grabbed_keys): New variable. (HOTKEY, HOTKEY_ID, HOTKEY_VK_CODE, HOTKEY_MODIFIERS): New macros. (register_hot_keys): (unregister_hot_keys): (lookup_vk_code): (w32_parse_hot_key): (Fw32_register_hot_key): (Fw32_unregister_hot_key): (Fw32_registered_hot_keys): (Fw32_reconstruct_hot_key): New functions to support hotkeys. (post_character_message): New function. (w32_msg_pump): Handle new messages for using hotkeys and changing keyboard layout/language. (w32_wnd_proc): Major rework of keyboard input handling: optionally recognize Windows keys and Apps key as modifiers; optionally treat NumLock, CapsLock and ScrollLock as function keys; let system translate keystrokes to characters to avoid system bugs relating to dead-key handling; preserve shift distinction for control characters; forward keyboard layout/language changes to lisp; detect and convert hot-key events to normal keystrokes. (syms_of_w32fns): Register new functions and variables. (w32_last_error): New function for use in debugging.
author Geoff Voelker <voelker@cs.washington.edu>
date Tue, 10 Nov 1998 20:54:46 +0000
parents 54b22e0a1f7b
children 119fd94ae526
comparison
equal deleted inserted replaced
23680:02e5da32da56 23681:af0276da2059
48 extern void abort (); 48 extern void abort ();
49 extern void free_frame_menubar (); 49 extern void free_frame_menubar ();
50 extern struct scroll_bar *x_window_to_scroll_bar (); 50 extern struct scroll_bar *x_window_to_scroll_bar ();
51 extern int quit_char; 51 extern int quit_char;
52 52
53 extern char *lispy_function_keys[];
54
53 /* The colormap for converting color names to RGB values */ 55 /* The colormap for converting color names to RGB values */
54 Lisp_Object Vw32_color_map; 56 Lisp_Object Vw32_color_map;
55 57
56 /* Non nil if alt key presses are passed on to Windows. */ 58 /* Non nil if alt key presses are passed on to Windows. */
57 Lisp_Object Vw32_pass_alt_to_system; 59 Lisp_Object Vw32_pass_alt_to_system;
58 60
59 /* Non nil if alt key is translated to meta_modifier, nil if it is translated 61 /* Non nil if alt key is translated to meta_modifier, nil if it is translated
60 to alt_modifier. */ 62 to alt_modifier. */
61 Lisp_Object Vw32_alt_is_meta; 63 Lisp_Object Vw32_alt_is_meta;
62 64
63 /* Non nil if left window, right window, and application key events 65 /* Non nil if left window key events are passed on to Windows (this only
64 are passed on to Windows. */ 66 affects whether "tapping" the key opens the Start menu). */
65 Lisp_Object Vw32_pass_optional_keys_to_system; 67 Lisp_Object Vw32_pass_lwindow_to_system;
68
69 /* Non nil if right window key events are passed on to Windows (this
70 only affects whether "tapping" the key opens the Start menu). */
71 Lisp_Object Vw32_pass_rwindow_to_system;
72
73 /* Modifier associated with the left "Windows" key, or nil to act as a
74 normal key. */
75 Lisp_Object Vw32_lwindow_modifier;
76
77 /* Modifier associated with the right "Windows" key, or nil to act as a
78 normal key. */
79 Lisp_Object Vw32_rwindow_modifier;
80
81 /* Modifier associated with the "Apps" key, or nil to act as a normal
82 key. */
83 Lisp_Object Vw32_apps_modifier;
84
85 /* Value is nil if Num Lock acts as a function key. */
86 Lisp_Object Vw32_enable_num_lock;
87
88 /* Value is nil if Caps Lock acts as a function key. */
89 Lisp_Object Vw32_enable_caps_lock;
90
91 /* Modifier associated with Scroll Lock, or nil to act as a normal key. */
92 Lisp_Object Vw32_scroll_lock_modifier;
66 93
67 /* Switch to control whether we inhibit requests for italicised fonts (which 94 /* Switch to control whether we inhibit requests for italicised fonts (which
68 are synthesized, look ugly, and are trashed by cursor movement under NT). */ 95 are synthesized, look ugly, and are trashed by cursor movement under NT). */
69 Lisp_Object Vw32_enable_italics; 96 Lisp_Object Vw32_enable_italics;
70 97
203 extern Lisp_Object last_mouse_scroll_bar; 230 extern Lisp_Object last_mouse_scroll_bar;
204 extern int last_mouse_scroll_bar_pos; 231 extern int last_mouse_scroll_bar_pos;
205 232
206 /* From w32term.c. */ 233 /* From w32term.c. */
207 extern Lisp_Object Vw32_num_mouse_buttons; 234 extern Lisp_Object Vw32_num_mouse_buttons;
235 extern Lisp_Object Vw32_recognize_altgr;
208 236
209 237
210 /* Error if we are not connected to MS-Windows. */ 238 /* Error if we are not connected to MS-Windows. */
211 void 239 void
212 check_w32 () 240 check_w32 ()
2957 /* Do this to discard the default setting specified by our parent. */ 2985 /* Do this to discard the default setting specified by our parent. */
2958 ShowWindow (hwnd, SW_HIDE); 2986 ShowWindow (hwnd, SW_HIDE);
2959 } 2987 }
2960 } 2988 }
2961 2989
2962 /* Convert between the modifier bits W32 uses and the modifier bits
2963 Emacs uses. */
2964 unsigned int
2965 w32_get_modifiers ()
2966 {
2967 return (((GetKeyState (VK_SHIFT)&0x8000) ? shift_modifier : 0) |
2968 ((GetKeyState (VK_CONTROL)&0x8000) ? ctrl_modifier : 0) |
2969 ((GetKeyState (VK_MENU)&0x8000) ?
2970 ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier) : 0));
2971 }
2972
2973 void 2990 void
2974 my_post_msg (wmsg, hwnd, msg, wParam, lParam) 2991 my_post_msg (wmsg, hwnd, msg, wParam, lParam)
2975 W32Msg * wmsg; 2992 W32Msg * wmsg;
2976 HWND hwnd; 2993 HWND hwnd;
2977 UINT msg; 2994 UINT msg;
3114 } 3131 }
3115 3132
3116 static int 3133 static int
3117 modifier_set (int vkey) 3134 modifier_set (int vkey)
3118 { 3135 {
3119 if (vkey == VK_CAPITAL) 3136 if (vkey == VK_CAPITAL || vkey == VK_SCROLL)
3120 return (GetKeyState (vkey) & 0x1); 3137 return (GetKeyState (vkey) & 0x1);
3121 if (!modifiers_recorded) 3138 if (!modifiers_recorded)
3122 return (GetKeyState (vkey) & 0x8000); 3139 return (GetKeyState (vkey) & 0x8000);
3123 3140
3124 switch (vkey) 3141 switch (vkey)
3129 return modifiers[EMACS_RCONTROL]; 3146 return modifiers[EMACS_RCONTROL];
3130 case VK_LMENU: 3147 case VK_LMENU:
3131 return modifiers[EMACS_LMENU]; 3148 return modifiers[EMACS_LMENU];
3132 case VK_RMENU: 3149 case VK_RMENU:
3133 return modifiers[EMACS_RMENU]; 3150 return modifiers[EMACS_RMENU];
3151 }
3152 return (GetKeyState (vkey) & 0x8000);
3153 }
3154
3155 /* Convert between the modifier bits W32 uses and the modifier bits
3156 Emacs uses. */
3157
3158 unsigned int
3159 w32_key_to_modifier (int key)
3160 {
3161 Lisp_Object key_mapping;
3162
3163 switch (key)
3164 {
3165 case VK_LWIN:
3166 key_mapping = Vw32_lwindow_modifier;
3167 break;
3168 case VK_RWIN:
3169 key_mapping = Vw32_rwindow_modifier;
3170 break;
3171 case VK_APPS:
3172 key_mapping = Vw32_apps_modifier;
3173 break;
3174 case VK_SCROLL:
3175 key_mapping = Vw32_scroll_lock_modifier;
3176 break;
3134 default: 3177 default:
3135 break; 3178 key_mapping = Qnil;
3136 } 3179 }
3137 return (GetKeyState (vkey) & 0x8000); 3180
3181 if (EQ (key_mapping, intern ("hyper")))
3182 return hyper_modifier;
3183 if (EQ (key_mapping, intern ("super")))
3184 return super_modifier;
3185 if (EQ (key_mapping, intern ("meta")))
3186 return meta_modifier;
3187 if (EQ (key_mapping, intern ("alt")))
3188 return alt_modifier;
3189 if (EQ (key_mapping, intern ("ctrl")))
3190 return ctrl_modifier;
3191 if (EQ (key_mapping, intern ("control"))) /* synonym for ctrl */
3192 return ctrl_modifier;
3193 if (EQ (key_mapping, intern ("shift")))
3194 return shift_modifier;
3195
3196 /* Don't generate any modifier if not explicitly requested. */
3197 return 0;
3198 }
3199
3200 unsigned int
3201 w32_get_modifiers ()
3202 {
3203 return ((modifier_set (VK_SHIFT) ? shift_modifier : 0) |
3204 (modifier_set (VK_CONTROL) ? ctrl_modifier : 0) |
3205 (modifier_set (VK_LWIN) ? w32_key_to_modifier (VK_LWIN) : 0) |
3206 (modifier_set (VK_RWIN) ? w32_key_to_modifier (VK_RWIN) : 0) |
3207 (modifier_set (VK_APPS) ? w32_key_to_modifier (VK_APPS) : 0) |
3208 (modifier_set (VK_SCROLL) ? w32_key_to_modifier (VK_SCROLL) : 0) |
3209 (modifier_set (VK_MENU) ?
3210 ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier) : 0));
3138 } 3211 }
3139 3212
3140 /* We map the VK_* modifiers into console modifier constants 3213 /* We map the VK_* modifiers into console modifier constants
3141 so that we can use the same routines to handle both console 3214 so that we can use the same routines to handle both console
3142 and window input. */ 3215 and window input. */
3143 3216
3144 static int 3217 static int
3145 construct_modifiers (unsigned int wparam, unsigned int lparam) 3218 construct_console_modifiers ()
3146 { 3219 {
3147 int mods; 3220 int mods;
3148
3149 if (wparam != VK_CONTROL && wparam != VK_MENU)
3150 mods = GetLastError ();
3151 3221
3152 mods = 0; 3222 mods = 0;
3153 mods |= (modifier_set (VK_SHIFT)) ? SHIFT_PRESSED : 0; 3223 mods |= (modifier_set (VK_SHIFT)) ? SHIFT_PRESSED : 0;
3154 mods |= (modifier_set (VK_CAPITAL)) ? CAPSLOCK_ON : 0; 3224 mods |= (modifier_set (VK_CAPITAL)) ? CAPSLOCK_ON : 0;
3225 mods |= (modifier_set (VK_SCROLL)) ? SCROLLLOCK_ON : 0;
3226 mods |= (modifier_set (VK_NUMLOCK)) ? NUMLOCK_ON : 0;
3155 mods |= (modifier_set (VK_LCONTROL)) ? LEFT_CTRL_PRESSED : 0; 3227 mods |= (modifier_set (VK_LCONTROL)) ? LEFT_CTRL_PRESSED : 0;
3156 mods |= (modifier_set (VK_RCONTROL)) ? RIGHT_CTRL_PRESSED : 0; 3228 mods |= (modifier_set (VK_RCONTROL)) ? RIGHT_CTRL_PRESSED : 0;
3157 mods |= (modifier_set (VK_LMENU)) ? LEFT_ALT_PRESSED : 0; 3229 mods |= (modifier_set (VK_LMENU)) ? LEFT_ALT_PRESSED : 0;
3158 mods |= (modifier_set (VK_RMENU)) ? RIGHT_ALT_PRESSED : 0; 3230 mods |= (modifier_set (VK_RMENU)) ? RIGHT_ALT_PRESSED : 0;
3231 mods |= (modifier_set (VK_LWIN)) ? LEFT_WIN_PRESSED : 0;
3232 mods |= (modifier_set (VK_RWIN)) ? RIGHT_WIN_PRESSED : 0;
3233 mods |= (modifier_set (VK_APPS)) ? APPS_PRESSED : 0;
3159 3234
3160 return mods; 3235 return mods;
3161 } 3236 }
3162 3237
3163 static unsigned int 3238 static int
3164 map_keypad_keys (unsigned int wparam, unsigned int lparam) 3239 w32_get_key_modifiers (unsigned int wparam, unsigned int lparam)
3165 { 3240 {
3166 unsigned int extended = (lparam & 0x1000000L); 3241 int mods;
3167 3242
3168 if (wparam < VK_CLEAR || wparam > VK_DELETE) 3243 /* Convert to emacs modifiers. */
3169 return wparam; 3244 mods = w32_kbd_mods_to_emacs (construct_console_modifiers (), wparam);
3170 3245
3171 if (wparam == VK_RETURN) 3246 return mods;
3247 }
3248
3249 unsigned int
3250 map_keypad_keys (unsigned int virt_key, unsigned int extended)
3251 {
3252 if (virt_key < VK_CLEAR || virt_key > VK_DELETE)
3253 return virt_key;
3254
3255 if (virt_key == VK_RETURN)
3172 return (extended ? VK_NUMPAD_ENTER : VK_RETURN); 3256 return (extended ? VK_NUMPAD_ENTER : VK_RETURN);
3173 3257
3174 if (wparam >= VK_PRIOR && wparam <= VK_DOWN) 3258 if (virt_key >= VK_PRIOR && virt_key <= VK_DOWN)
3175 return (!extended ? (VK_NUMPAD_PRIOR + (wparam - VK_PRIOR)) : wparam); 3259 return (!extended ? (VK_NUMPAD_PRIOR + (virt_key - VK_PRIOR)) : virt_key);
3176 3260
3177 if (wparam == VK_INSERT || wparam == VK_DELETE) 3261 if (virt_key == VK_INSERT || virt_key == VK_DELETE)
3178 return (!extended ? (VK_NUMPAD_INSERT + (wparam - VK_INSERT)) : wparam); 3262 return (!extended ? (VK_NUMPAD_INSERT + (virt_key - VK_INSERT)) : virt_key);
3179 3263
3180 if (wparam == VK_CLEAR) 3264 if (virt_key == VK_CLEAR)
3181 return (!extended ? VK_NUMPAD_CLEAR : wparam); 3265 return (!extended ? VK_NUMPAD_CLEAR : virt_key);
3182 3266
3183 return wparam; 3267 return virt_key;
3268 }
3269
3270 /* List of special key combinations which w32 would normally capture,
3271 but emacs should grab instead. Not directly visible to lisp, to
3272 simplify synchronization. Each item is an integer encoding a virtual
3273 key code and modifier combination to capture. */
3274 Lisp_Object w32_grabbed_keys;
3275
3276 #define HOTKEY(vk,mods) make_number (((vk) & 255) | ((mods) << 8))
3277 #define HOTKEY_ID(k) (XFASTINT (k) & 0xbfff)
3278 #define HOTKEY_VK_CODE(k) (XFASTINT (k) & 255)
3279 #define HOTKEY_MODIFIERS(k) (XFASTINT (k) >> 8)
3280
3281 /* Register hot-keys for reserved key combinations when Emacs has
3282 keyboard focus, since this is the only way Emacs can receive key
3283 combinations like Alt-Tab which are used by the system. */
3284
3285 static void
3286 register_hot_keys (hwnd)
3287 HWND hwnd;
3288 {
3289 Lisp_Object keylist;
3290
3291 /* Use GC_CONSP, since we are called asynchronously. */
3292 for (keylist = w32_grabbed_keys; GC_CONSP (keylist); keylist = XCDR (keylist))
3293 {
3294 Lisp_Object key = XCAR (keylist);
3295
3296 /* Deleted entries get set to nil. */
3297 if (!INTEGERP (key))
3298 continue;
3299
3300 RegisterHotKey (hwnd, HOTKEY_ID (key),
3301 HOTKEY_MODIFIERS (key), HOTKEY_VK_CODE (key));
3302 }
3303 }
3304
3305 static void
3306 unregister_hot_keys (hwnd)
3307 HWND hwnd;
3308 {
3309 Lisp_Object keylist;
3310
3311 /* Use GC_CONSP, since we are called asynchronously. */
3312 for (keylist = w32_grabbed_keys; GC_CONSP (keylist); keylist = XCDR (keylist))
3313 {
3314 Lisp_Object key = XCAR (keylist);
3315
3316 if (!INTEGERP (key))
3317 continue;
3318
3319 UnregisterHotKey (hwnd, HOTKEY_ID (key));
3320 }
3321 }
3322
3323 static void
3324 post_character_message (hwnd, msg, wParam, lParam, modifiers)
3325 HWND hwnd;
3326 UINT msg;
3327 WPARAM wParam;
3328 LPARAM lParam;
3329 DWORD modifiers;
3330
3331 {
3332 W32Msg wmsg;
3333
3334 wmsg.dwModifiers = modifiers;
3335
3336 /* Detect quit_char and set quit-flag directly. Note that we
3337 still need to post a message to ensure the main thread will be
3338 woken up if blocked in sys_select(), but we do NOT want to post
3339 the quit_char message itself (because it will usually be as if
3340 the user had typed quit_char twice). Instead, we post a dummy
3341 message that has no particular effect. */
3342 {
3343 int c = wParam;
3344 if (isalpha (c) && wmsg.dwModifiers == ctrl_modifier)
3345 c = make_ctrl_char (c) & 0377;
3346 if (c == quit_char)
3347 {
3348 Vquit_flag = Qt;
3349
3350 /* The choice of message is somewhat arbitrary, as long as
3351 the main thread handler just ignores it. */
3352 msg = WM_NULL;
3353
3354 /* Interrupt any blocking system calls. */
3355 signal_quit ();
3356 }
3357 }
3358
3359 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3184 } 3360 }
3185 3361
3186 /* Main message dispatch loop. */ 3362 /* Main message dispatch loop. */
3187 3363
3188 static void 3364 static void
3189 w32_msg_pump (deferred_msg * msg_buf) 3365 w32_msg_pump (deferred_msg * msg_buf)
3190 { 3366 {
3191 MSG msg; 3367 MSG msg;
3368 int result;
3369 HWND focus_window;
3192 3370
3193 msh_mousewheel = RegisterWindowMessage (MSH_MOUSEWHEEL); 3371 msh_mousewheel = RegisterWindowMessage (MSH_MOUSEWHEEL);
3194 3372
3195 while (GetMessage (&msg, NULL, 0, 0)) 3373 while (GetMessage (&msg, NULL, 0, 0))
3196 { 3374 {
3205 break; 3383 break;
3206 case WM_EMACS_SETLOCALE: 3384 case WM_EMACS_SETLOCALE:
3207 SetThreadLocale (msg.wParam); 3385 SetThreadLocale (msg.wParam);
3208 /* Reply is not expected. */ 3386 /* Reply is not expected. */
3209 break; 3387 break;
3388 case WM_EMACS_SETKEYBOARDLAYOUT:
3389 result = (int) ActivateKeyboardLayout ((HKL) msg.wParam, 0);
3390 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE,
3391 result, 0))
3392 abort ();
3393 break;
3394 case WM_EMACS_REGISTER_HOT_KEY:
3395 focus_window = GetFocus ();
3396 if (focus_window != NULL)
3397 RegisterHotKey (focus_window,
3398 HOTKEY_ID (msg.wParam),
3399 HOTKEY_MODIFIERS (msg.wParam),
3400 HOTKEY_VK_CODE (msg.wParam));
3401 /* Reply is not expected. */
3402 break;
3403 case WM_EMACS_UNREGISTER_HOT_KEY:
3404 focus_window = GetFocus ();
3405 if (focus_window != NULL)
3406 UnregisterHotKey (focus_window, HOTKEY_ID (msg.wParam));
3407 /* Mark item as erased. */
3408 XCAR ((Lisp_Object) msg.lParam) = Qnil;
3409 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
3410 abort ();
3411 break;
3210 default: 3412 default:
3211 /* No need to be so draconian! */
3212 /* abort (); */
3213 DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message)); 3413 DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message));
3214 } 3414 }
3215 } 3415 }
3216 else 3416 else
3217 { 3417 {
3323 3523
3324 return 0; 3524 return 0;
3325 } 3525 }
3326 3526
3327 /* Main window procedure */ 3527 /* Main window procedure */
3328
3329 extern char *lispy_function_keys[];
3330 3528
3331 LRESULT CALLBACK 3529 LRESULT CALLBACK
3332 w32_wnd_proc (hwnd, msg, wParam, lParam) 3530 w32_wnd_proc (hwnd, msg, wParam, lParam)
3333 HWND hwnd; 3531 HWND hwnd;
3334 UINT msg; 3532 UINT msg;
3390 my_post_msg (&wmsg, hwnd, msg, wParam, lParam); 3588 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3391 3589
3392 return (0); 3590 return (0);
3393 } 3591 }
3394 3592
3593 case WM_INPUTLANGCHANGE:
3594 /* Inform lisp thread of keyboard layout changes. */
3595 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3596
3597 /* Clear dead keys in the keyboard state; for simplicity only
3598 preserve modifier key states. */
3599 {
3600 int i;
3601 BYTE keystate[256];
3602
3603 GetKeyboardState (keystate);
3604 for (i = 0; i < 256; i++)
3605 if (1
3606 && i != VK_SHIFT
3607 && i != VK_LSHIFT
3608 && i != VK_RSHIFT
3609 && i != VK_CAPITAL
3610 && i != VK_NUMLOCK
3611 && i != VK_SCROLL
3612 && i != VK_CONTROL
3613 && i != VK_LCONTROL
3614 && i != VK_RCONTROL
3615 && i != VK_MENU
3616 && i != VK_LMENU
3617 && i != VK_RMENU
3618 && i != VK_LWIN
3619 && i != VK_RWIN)
3620 keystate[i] = 0;
3621 SetKeyboardState (keystate);
3622 }
3623 goto dflt;
3624
3625 case WM_HOTKEY:
3626 /* Synchronize hot keys with normal input. */
3627 PostMessage (hwnd, WM_KEYDOWN, HIWORD (lParam), 0);
3628 return (0);
3629
3395 case WM_KEYUP: 3630 case WM_KEYUP:
3396 case WM_SYSKEYUP: 3631 case WM_SYSKEYUP:
3397 record_keyup (wParam, lParam); 3632 record_keyup (wParam, lParam);
3398 goto dflt; 3633 goto dflt;
3399 3634
3400 case WM_KEYDOWN: 3635 case WM_KEYDOWN:
3401 case WM_SYSKEYDOWN: 3636 case WM_SYSKEYDOWN:
3637 /* Ignore keystrokes we fake ourself; see below. */
3638 if (dpyinfo->faked_key == wParam)
3639 {
3640 dpyinfo->faked_key = 0;
3641 return 0;
3642 }
3643
3402 /* Synchronize modifiers with current keystroke. */ 3644 /* Synchronize modifiers with current keystroke. */
3403 sync_modifiers (); 3645 sync_modifiers ();
3404
3405 record_keydown (wParam, lParam); 3646 record_keydown (wParam, lParam);
3406 3647 wParam = map_keypad_keys (wParam, (lParam & 0x1000000L) != 0);
3407 wParam = map_keypad_keys (wParam, lParam);
3408 3648
3409 windows_translate = 0; 3649 windows_translate = 0;
3410 switch (wParam) { 3650
3411 case VK_LWIN: 3651 switch (wParam)
3412 case VK_RWIN: 3652 {
3413 case VK_APPS: 3653 case VK_LWIN:
3414 /* More support for these keys will likely be necessary. */ 3654 if (NILP (Vw32_pass_lwindow_to_system))
3415 if (!NILP (Vw32_pass_optional_keys_to_system)) 3655 {
3656 /* Prevent system from acting on keyup (which opens the
3657 Start menu if no other key was pressed) by simulating a
3658 press of Space which we will ignore. */
3659 if (GetAsyncKeyState (wParam) & 1)
3660 {
3661 dpyinfo->faked_key = VK_SPACE;
3662 keybd_event (VK_SPACE,
3663 (BYTE) MapVirtualKey (VK_SPACE, 0), 0, 0);
3664 }
3665 }
3666 if (!NILP (Vw32_lwindow_modifier))
3667 return 0;
3668 break;
3669 case VK_RWIN:
3670 if (NILP (Vw32_pass_rwindow_to_system))
3671 {
3672 if (GetAsyncKeyState (wParam) & 1)
3673 {
3674 dpyinfo->faked_key = VK_SPACE;
3675 keybd_event (VK_SPACE,
3676 (BYTE) MapVirtualKey (VK_SPACE, 0), 0, 0);
3677 }
3678 }
3679 if (!NILP (Vw32_rwindow_modifier))
3680 return 0;
3681 break;
3682 case VK_APPS:
3683 if (!NILP (Vw32_apps_modifier))
3684 return 0;
3685 break;
3686 case VK_MENU:
3687 if (NILP (Vw32_pass_alt_to_system))
3688 return 0;
3416 windows_translate = 1; 3689 windows_translate = 1;
3417 break; 3690 break;
3418 case VK_MENU: 3691 case VK_CAPITAL:
3419 if (NILP (Vw32_pass_alt_to_system)) 3692 /* Decide whether to treat as modifier or function key. */
3693 if (NILP (Vw32_enable_caps_lock))
3694 goto disable_lock_key;
3420 return 0; 3695 return 0;
3421 windows_translate = 1; 3696 case VK_NUMLOCK:
3422 break; 3697 /* Decide whether to treat as modifier or function key. */
3423 case VK_CONTROL: 3698 if (NILP (Vw32_enable_num_lock))
3424 case VK_CAPITAL: 3699 goto disable_lock_key;
3425 case VK_SHIFT: 3700 return 0;
3426 case VK_NUMLOCK: 3701 case VK_SCROLL:
3427 case VK_SCROLL: 3702 /* Decide whether to treat as modifier or function key. */
3428 windows_translate = 1; 3703 if (NILP (Vw32_scroll_lock_modifier))
3429 break; 3704 goto disable_lock_key;
3430 default: 3705 return 0;
3431 /* If not defined as a function key, change it to a WM_CHAR message. */ 3706 disable_lock_key:
3432 if (lispy_function_keys[wParam] == 0) 3707 /* Ensure the appropriate lock key state is off (and the
3433 msg = WM_CHAR; 3708 indicator light as well). */
3434 break; 3709 if (GetAsyncKeyState (wParam) & 0x8000)
3435 } 3710 {
3711 /* Fake another press of the relevant key. Apparently,
3712 this really is the only way to turn off the indicator. */
3713 dpyinfo->faked_key = wParam;
3714 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
3715 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
3716 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
3717 KEYEVENTF_EXTENDEDKEY | 0, 0);
3718 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
3719 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
3720 }
3721 break;
3722 case VK_CONTROL:
3723 case VK_SHIFT:
3724 case VK_PROCESSKEY: /* Generated by IME. */
3725 windows_translate = 1;
3726 break;
3727 default:
3728 /* If not defined as a function key, change it to a WM_CHAR message. */
3729 if (lispy_function_keys[wParam] == 0)
3730 {
3731 if (!NILP (Vw32_recognize_altgr)
3732 && modifier_set (VK_LCONTROL) && modifier_set (VK_RMENU))
3733 {
3734 /* Always let TranslateMessage handle AltGr key chords;
3735 for some reason, ToAscii doesn't always process AltGr
3736 chords correctly. */
3737 windows_translate = 1;
3738 }
3739 else if (modifier_set (VK_CONTROL) || modifier_set (VK_MENU))
3740 {
3741 /* Handle key chords including any modifiers other than shift
3742 directly, in order to preserve as much modifier information as
3743 possible. */
3744 if ('A' <= wParam && wParam <= 'Z')
3745 {
3746 /* Don't translate modified alphabetic keystrokes,
3747 so the user doesn't need to constantly switch
3748 layout to type control or meta keystrokes when
3749 the normal layout translates alphabetic
3750 characters to non-ascii characters. */
3751 if (!modifier_set (VK_SHIFT))
3752 wParam += ('a' - 'A');
3753 msg = WM_CHAR;
3754 }
3755 else
3756 {
3757 /* Try to handle other keystrokes by determining the
3758 base character (ie. translating the base key plus
3759 shift modifier). */
3760 int add;
3761 int isdead = 0;
3762 KEY_EVENT_RECORD key;
3763
3764 key.bKeyDown = TRUE;
3765 key.wRepeatCount = 1;
3766 key.wVirtualKeyCode = wParam;
3767 key.wVirtualScanCode = (lParam & 0xFF0000) >> 16;
3768 key.uChar.AsciiChar = 0;
3769 key.dwControlKeyState = construct_console_modifiers ();
3770
3771 add = w32_kbd_patch_key (&key);
3772 /* 0 means an unrecognised keycode, negative means
3773 dead key. Ignore both. */
3774 while (--add >= 0)
3775 {
3776 /* Forward asciified character sequence. */
3777 post_character_message
3778 (hwnd, WM_CHAR, key.uChar.AsciiChar, lParam,
3779 w32_get_key_modifiers (wParam, lParam));
3780 w32_kbd_patch_key (&key);
3781 }
3782 return 0;
3783 }
3784 }
3785 else
3786 {
3787 /* Let TranslateMessage handle everything else. */
3788 windows_translate = 1;
3789 }
3790 }
3791 }
3436 3792
3437 if (windows_translate) 3793 if (windows_translate)
3438 { 3794 {
3439 MSG windows_msg = { hwnd, msg, wParam, lParam, 0, {0,0} }; 3795 MSG windows_msg = { hwnd, msg, wParam, lParam, 0, {0,0} };
3440 3796
3445 3801
3446 /* Fall through */ 3802 /* Fall through */
3447 3803
3448 case WM_SYSCHAR: 3804 case WM_SYSCHAR:
3449 case WM_CHAR: 3805 case WM_CHAR:
3450 wmsg.dwModifiers = construct_modifiers (wParam, lParam); 3806 post_character_message (hwnd, msg, wParam, lParam,
3451 3807 w32_get_key_modifiers (wParam, lParam));
3452 #if 1
3453 /* Detect quit_char and set quit-flag directly. Note that we
3454 still need to post a message to ensure the main thread will be
3455 woken up if blocked in sys_select(), but we do NOT want to post
3456 the quit_char message itself (because it will usually be as if
3457 the user had typed quit_char twice). Instead, we post a dummy
3458 message that has no particular effect. */
3459 {
3460 int c = wParam;
3461 if (isalpha (c) && (wmsg.dwModifiers == LEFT_CTRL_PRESSED
3462 || wmsg.dwModifiers == RIGHT_CTRL_PRESSED))
3463 c = make_ctrl_char (c) & 0377;
3464 if (c == quit_char)
3465 {
3466 Vquit_flag = Qt;
3467
3468 /* The choice of message is somewhat arbitrary, as long as
3469 the main thread handler just ignores it. */
3470 msg = WM_NULL;
3471
3472 /* Interrupt any blocking system calls. */
3473 signal_quit ();
3474 }
3475 }
3476 #endif
3477
3478 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3479
3480 break; 3808 break;
3481 3809
3482 /* Simulate middle mouse button events when left and right buttons 3810 /* Simulate middle mouse button events when left and right buttons
3483 are used together, but only if user has two button mouse. */ 3811 are used together, but only if user has two button mouse. */
3484 case WM_LBUTTONDOWN: 3812 case WM_LBUTTONDOWN:
3815 if (LOWORD (lParam) == HTCLIENT ) 4143 if (LOWORD (lParam) == HTCLIENT )
3816 return MA_ACTIVATEANDEAT; 4144 return MA_ACTIVATEANDEAT;
3817 goto dflt; 4145 goto dflt;
3818 #endif 4146 #endif
3819 4147
4148 case WM_ACTIVATEAPP:
4149 dpyinfo->faked_key = 0;
4150 reset_modifiers ();
3820 case WM_ACTIVATE: 4151 case WM_ACTIVATE:
3821 case WM_ACTIVATEAPP:
3822 case WM_WINDOWPOSCHANGED: 4152 case WM_WINDOWPOSCHANGED:
3823 case WM_SHOWWINDOW: 4153 case WM_SHOWWINDOW:
3824 /* Inform lisp thread that a frame might have just been obscured 4154 /* Inform lisp thread that a frame might have just been obscured
3825 or exposed, so should recheck visibility of all frames. */ 4155 or exposed, so should recheck visibility of all frames. */
3826 my_post_msg (&wmsg, hwnd, msg, wParam, lParam); 4156 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3827 goto dflt; 4157 goto dflt;
3828 4158
3829 case WM_SETFOCUS: 4159 case WM_SETFOCUS:
3830 reset_modifiers (); 4160 register_hot_keys (hwnd);
4161 goto command;
3831 case WM_KILLFOCUS: 4162 case WM_KILLFOCUS:
4163 unregister_hot_keys (hwnd);
3832 case WM_MOVE: 4164 case WM_MOVE:
3833 case WM_SIZE: 4165 case WM_SIZE:
3834 case WM_COMMAND: 4166 case WM_COMMAND:
4167 command:
3835 wmsg.dwModifiers = w32_get_modifiers (); 4168 wmsg.dwModifiers = w32_get_modifiers ();
3836 my_post_msg (&wmsg, hwnd, msg, wParam, lParam); 4169 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3837 goto dflt; 4170 goto dflt;
3838 4171
3839 case WM_CLOSE: 4172 case WM_CLOSE:
6084 PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, XINT (command), 0); 6417 PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, XINT (command), 0);
6085 6418
6086 return Qnil; 6419 return Qnil;
6087 } 6420 }
6088 6421
6422 /* Lookup virtual keycode from string representing the name of a
6423 non-ascii keystroke into the corresponding virtual key, using
6424 lispy_function_keys. */
6425 static int
6426 lookup_vk_code (char *key)
6427 {
6428 int i;
6429
6430 for (i = 0; i < 256; i++)
6431 if (lispy_function_keys[i] != 0
6432 && strcmp (lispy_function_keys[i], key) == 0)
6433 return i;
6434
6435 return -1;
6436 }
6437
6438 /* Convert a one-element vector style key sequence to a hot key
6439 definition. */
6440 static int
6441 w32_parse_hot_key (key)
6442 Lisp_Object key;
6443 {
6444 /* Copied from Fdefine_key and store_in_keymap. */
6445 register Lisp_Object c;
6446 int vk_code;
6447 int lisp_modifiers;
6448 int w32_modifiers;
6449 struct gcpro gcpro1;
6450
6451 CHECK_VECTOR (key, 0);
6452
6453 if (XFASTINT (Flength (key)) != 1)
6454 return Qnil;
6455
6456 GCPRO1 (key);
6457
6458 c = Faref (key, make_number (0));
6459
6460 if (CONSP (c) && lucid_event_type_list_p (c))
6461 c = Fevent_convert_list (c);
6462
6463 UNGCPRO;
6464
6465 if (! INTEGERP (c) && ! SYMBOLP (c))
6466 error ("Key definition is invalid");
6467
6468 /* Work out the base key and the modifiers. */
6469 if (SYMBOLP (c))
6470 {
6471 c = parse_modifiers (c);
6472 lisp_modifiers = Fcar (Fcdr (c));
6473 c = Fcar (c);
6474 if (!SYMBOLP (c))
6475 abort ();
6476 vk_code = lookup_vk_code (XSYMBOL (c)->name->data);
6477 }
6478 else if (INTEGERP (c))
6479 {
6480 lisp_modifiers = XINT (c) & ~CHARACTERBITS;
6481 /* Many ascii characters are their own virtual key code. */
6482 vk_code = XINT (c) & CHARACTERBITS;
6483 }
6484
6485 if (vk_code < 0 || vk_code > 255)
6486 return Qnil;
6487
6488 if ((lisp_modifiers & meta_modifier) != 0
6489 && !NILP (Vw32_alt_is_meta))
6490 lisp_modifiers |= alt_modifier;
6491
6492 /* Convert lisp modifiers to Windows hot-key form. */
6493 w32_modifiers = (lisp_modifiers & hyper_modifier) ? MOD_WIN : 0;
6494 w32_modifiers |= (lisp_modifiers & alt_modifier) ? MOD_ALT : 0;
6495 w32_modifiers |= (lisp_modifiers & ctrl_modifier) ? MOD_CONTROL : 0;
6496 w32_modifiers |= (lisp_modifiers & shift_modifier) ? MOD_SHIFT : 0;
6497
6498 return HOTKEY (vk_code, w32_modifiers);
6499 }
6500
6501 DEFUN ("w32-register-hot-key", Fw32_register_hot_key, Sw32_register_hot_key, 1, 1, 0,
6502 "Register KEY as a hot-key combination.\n\
6503 Certain key combinations like Alt-Tab are reserved for system use on\n\
6504 Windows, and therefore are normally intercepted by the system. However,\n\
6505 most of these key combinations can be received by registering them as\n\
6506 hot-keys, overriding their special meaning.\n\
6507 \n\
6508 KEY must be a one element key definition in vector form that would be\n\
6509 acceptable to `define-key' (e.g. [A-tab] for Alt-Tab). The meta\n\
6510 modifier is interpreted as Alt if `w32-alt-is-meta' is t, and hyper\n\
6511 is always interpreted as the Windows modifier keys.\n\
6512 \n\
6513 The return value is the hotkey-id if registered, otherwise nil.")
6514 (key)
6515 Lisp_Object key;
6516 {
6517 key = w32_parse_hot_key (key);
6518
6519 if (NILP (Fmemq (key, w32_grabbed_keys)))
6520 {
6521 /* Reuse an empty slot if possible. */
6522 Lisp_Object item = Fmemq (Qnil, w32_grabbed_keys);
6523
6524 /* Safe to add new key to list, even if we have focus. */
6525 if (NILP (item))
6526 w32_grabbed_keys = Fcons (key, w32_grabbed_keys);
6527 else
6528 XCAR (item) = key;
6529
6530 /* Notify input thread about new hot-key definition, so that it
6531 takes effect without needing to switch focus. */
6532 PostThreadMessage (dwWindowsThreadId, WM_EMACS_REGISTER_HOT_KEY,
6533 (WPARAM) key, 0);
6534 }
6535
6536 return key;
6537 }
6538
6539 DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key, Sw32_unregister_hot_key, 1, 1, 0,
6540 "Unregister HOTKEY as a hot-key combination.")
6541 (key)
6542 Lisp_Object key;
6543 {
6544 Lisp_Object item;
6545
6546 if (!INTEGERP (key))
6547 key = w32_parse_hot_key (key);
6548
6549 item = Fmemq (key, w32_grabbed_keys);
6550
6551 if (!NILP (item))
6552 {
6553 /* Notify input thread about hot-key definition being removed, so
6554 that it takes effect without needing focus switch. */
6555 if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_UNREGISTER_HOT_KEY,
6556 (WPARAM) XINT (XCAR (item)), (LPARAM) item))
6557 {
6558 MSG msg;
6559 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
6560 }
6561 return Qt;
6562 }
6563 return Qnil;
6564 }
6565
6566 DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys, Sw32_registered_hot_keys, 0, 0, 0,
6567 "Return list of registered hot-key IDs.")
6568 ()
6569 {
6570 return Fcopy_sequence (w32_grabbed_keys);
6571 }
6572
6573 DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key, Sw32_reconstruct_hot_key, 1, 1, 0,
6574 "Convert hot-key ID to a lisp key combination.")
6575 (hotkeyid)
6576 Lisp_Object hotkeyid;
6577 {
6578 int vk_code, w32_modifiers;
6579 Lisp_Object key;
6580
6581 CHECK_NUMBER (hotkeyid, 0);
6582
6583 vk_code = HOTKEY_VK_CODE (hotkeyid);
6584 w32_modifiers = HOTKEY_MODIFIERS (hotkeyid);
6585
6586 if (lispy_function_keys[vk_code])
6587 key = intern (lispy_function_keys[vk_code]);
6588 else
6589 key = make_number (vk_code);
6590
6591 key = Fcons (key, Qnil);
6592 if (w32_modifiers & MOD_SHIFT)
6593 key = Fcons (intern ("shift"), key);
6594 if (w32_modifiers & MOD_CONTROL)
6595 key = Fcons (intern ("control"), key);
6596 if (w32_modifiers & MOD_ALT)
6597 key = Fcons (intern (NILP (Vw32_alt_is_meta) ? "alt" : "meta"), key);
6598 if (w32_modifiers & MOD_WIN)
6599 key = Fcons (intern ("hyper"), key);
6600
6601 return key;
6602 }
6089 6603
6090 syms_of_w32fns () 6604 syms_of_w32fns ()
6091 { 6605 {
6092 /* This is zero if not using MS-Windows. */ 6606 /* This is zero if not using MS-Windows. */
6093 w32_in_use = 0; 6607 w32_in_use = 0;
6169 Fput (Qundefined_color, Qerror_conditions, 6683 Fput (Qundefined_color, Qerror_conditions,
6170 Fcons (Qundefined_color, Fcons (Qerror, Qnil))); 6684 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
6171 Fput (Qundefined_color, Qerror_message, 6685 Fput (Qundefined_color, Qerror_message,
6172 build_string ("Undefined color")); 6686 build_string ("Undefined color"));
6173 6687
6688 staticpro (&w32_grabbed_keys);
6689 w32_grabbed_keys = Qnil;
6690
6174 DEFVAR_LISP ("w32-color-map", &Vw32_color_map, 6691 DEFVAR_LISP ("w32-color-map", &Vw32_color_map,
6175 "A array of color name mappings for windows."); 6692 "An array of color name mappings for windows.");
6176 Vw32_color_map = Qnil; 6693 Vw32_color_map = Qnil;
6177 6694
6178 DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system, 6695 DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system,
6179 "Non-nil if alt key presses are passed on to Windows.\n\ 6696 "Non-nil if alt key presses are passed on to Windows.\n\
6180 When non-nil, for example, alt pressed and released and then space will\n\ 6697 When non-nil, for example, alt pressed and released and then space will\n\
6184 DEFVAR_LISP ("w32-alt-is-meta", &Vw32_alt_is_meta, 6701 DEFVAR_LISP ("w32-alt-is-meta", &Vw32_alt_is_meta,
6185 "Non-nil if the alt key is to be considered the same as the meta key.\n\ 6702 "Non-nil if the alt key is to be considered the same as the meta key.\n\
6186 When nil, Emacs will translate the alt key to the Alt modifier, and not Meta."); 6703 When nil, Emacs will translate the alt key to the Alt modifier, and not Meta.");
6187 Vw32_alt_is_meta = Qt; 6704 Vw32_alt_is_meta = Qt;
6188 6705
6189 DEFVAR_LISP ("w32-pass-optional-keys-to-system", 6706 DEFVAR_LISP ("w32-pass-lwindow-to-system",
6190 &Vw32_pass_optional_keys_to_system, 6707 &Vw32_pass_lwindow_to_system,
6191 "Non-nil if the 'optional' keys (left window, right window,\n\ 6708 "Non-nil if the left \"Windows\" key is passed on to Windows.\n\
6192 and application keys) are passed on to Windows."); 6709 When non-nil, the Start menu is opened by tapping the key.");
6193 Vw32_pass_optional_keys_to_system = Qnil; 6710 Vw32_pass_lwindow_to_system = Qt;
6711
6712 DEFVAR_LISP ("w32-pass-rwindow-to-system",
6713 &Vw32_pass_rwindow_to_system,
6714 "Non-nil if the right \"Windows\" key is passed on to Windows.\n\
6715 When non-nil, the Start menu is opened by tapping the key.");
6716 Vw32_pass_rwindow_to_system = Qt;
6717
6718 DEFVAR_LISP ("w32-enable-num-lock",
6719 &Vw32_enable_num_lock,
6720 "Non-nil if Num Lock should act normally.\n\
6721 Set to nil to see Num Lock as the key `kp-numlock'.");
6722 Vw32_enable_num_lock = Qt;
6723
6724 DEFVAR_LISP ("w32-enable-caps-lock",
6725 &Vw32_enable_caps_lock,
6726 "Non-nil if Caps Lock should act normally.\n\
6727 Set to nil to see Caps Lock as the key `capslock'.");
6728 Vw32_enable_caps_lock = Qt;
6729
6730 DEFVAR_LISP ("w32-scroll-lock-modifier",
6731 &Vw32_scroll_lock_modifier,
6732 "Modifier to use for the Scroll Lock on state.\n\
6733 The value can be hyper, super, meta, alt, control or shift for the\n\
6734 respective modifier, or nil to see Scroll Lock as the key `scroll'.\n\
6735 Any other value will cause the key to be ignored.");
6736 Vw32_scroll_lock_modifier = Qt;
6737
6738 DEFVAR_LISP ("w32-lwindow-modifier",
6739 &Vw32_lwindow_modifier,
6740 "Modifier to use for the left \"Windows\" key.\n\
6741 The value can be hyper, super, meta, alt, control or shift for the\n\
6742 respective modifier, or nil to appear as the key `lwindow'.\n\
6743 Any other value will cause the key to be ignored.");
6744 Vw32_lwindow_modifier = Qnil;
6745
6746 DEFVAR_LISP ("w32-rwindow-modifier",
6747 &Vw32_rwindow_modifier,
6748 "Modifier to use for the right \"Windows\" key.\n\
6749 The value can be hyper, super, meta, alt, control or shift for the\n\
6750 respective modifier, or nil to appear as the key `rwindow'.\n\
6751 Any other value will cause the key to be ignored.");
6752 Vw32_rwindow_modifier = Qnil;
6753
6754 DEFVAR_LISP ("w32-apps-modifier",
6755 &Vw32_apps_modifier,
6756 "Modifier to use for the \"Apps\" key.\n\
6757 The value can be hyper, super, meta, alt, control or shift for the\n\
6758 respective modifier, or nil to appear as the key `apps'.\n\
6759 Any other value will cause the key to be ignored.");
6760 Vw32_apps_modifier = Qnil;
6194 6761
6195 DEFVAR_LISP ("w32-enable-italics", &Vw32_enable_italics, 6762 DEFVAR_LISP ("w32-enable-italics", &Vw32_enable_italics,
6196 "Non-nil enables selection of artificially italicized fonts."); 6763 "Non-nil enables selection of artificially italicized fonts.");
6197 Vw32_enable_italics = Qnil; 6764 Vw32_enable_italics = Qnil;
6198 6765
6312 defsubr (&Sw32_select_font); 6879 defsubr (&Sw32_select_font);
6313 defsubr (&Sw32_define_rgb_color); 6880 defsubr (&Sw32_define_rgb_color);
6314 defsubr (&Sw32_default_color_map); 6881 defsubr (&Sw32_default_color_map);
6315 defsubr (&Sw32_load_color_file); 6882 defsubr (&Sw32_load_color_file);
6316 defsubr (&Sw32_send_sys_command); 6883 defsubr (&Sw32_send_sys_command);
6884 defsubr (&Sw32_register_hot_key);
6885 defsubr (&Sw32_unregister_hot_key);
6886 defsubr (&Sw32_registered_hot_keys);
6887 defsubr (&Sw32_reconstruct_hot_key);
6317 6888
6318 /* Setting callback functions for fontset handler. */ 6889 /* Setting callback functions for fontset handler. */
6319 get_font_info_func = w32_get_font_info; 6890 get_font_info_func = w32_get_font_info;
6320 list_fonts_func = w32_list_fonts; 6891 list_fonts_func = w32_list_fonts;
6321 load_font_func = w32_load_font; 6892 load_font_func = w32_load_font;
6326 } 6897 }
6327 6898
6328 #undef abort 6899 #undef abort
6329 6900
6330 void 6901 void
6902 /* For convenience when debugging. */
6903 int
6904 w32_last_error()
6905 {
6906 return GetLastError ();
6907 }
6331 w32_abort() 6908 w32_abort()
6332 { 6909 {
6333 int button; 6910 int button;
6334 button = MessageBox (NULL, 6911 button = MessageBox (NULL,
6335 "A fatal error has occurred!\n\n" 6912 "A fatal error has occurred!\n\n"