diff options
| author | Ilya Zakharevich | 2015-07-31 11:50:23 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2015-07-31 11:50:23 +0300 |
| commit | 123c82e8307ca386ba7f161dc725e3953dffc5c0 (patch) | |
| tree | b52752e19fe6f93384c6b6d0b1d74380b05f701f /src | |
| parent | b07ca177d449e58e6e5c14e21e140e63354e335c (diff) | |
| download | emacs-123c82e8307ca386ba7f161dc725e3953dffc5c0.tar.gz emacs-123c82e8307ca386ba7f161dc725e3953dffc5c0.zip | |
Improve handling of Unicode keyboard input on MS-Windows
* src/w32fns.c (get_wm_chars, deliver_wm_chars): New functions.
(FPRINTF_WM_CHARS) [DEBUG_WM_CHARS]: New macro for debugging.
(w32_wnd_proc): Call deliver_wm_chars to process non-special keys
upon receiving WM_KEYDOWN or WM_SYSKEYDOWN messages. If that is
successful, don't call TranslateMessage. (Bug#19994)
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32fns.c | 979 |
1 files changed, 718 insertions, 261 deletions
diff --git a/src/w32fns.c b/src/w32fns.c index c742ca8534f..fecdf7cb72d 100644 --- a/src/w32fns.c +++ b/src/w32fns.c | |||
| @@ -270,7 +270,7 @@ check_x_display_info (Lisp_Object object) | |||
| 270 | struct terminal *t = decode_live_terminal (object); | 270 | struct terminal *t = decode_live_terminal (object); |
| 271 | 271 | ||
| 272 | if (t->type != output_w32) | 272 | if (t->type != output_w32) |
| 273 | error ("Terminal %d is not a W32 display", t->id); | 273 | error ("Terminal %d is not a W32 display", t->id); |
| 274 | 274 | ||
| 275 | return t->display_info.w32; | 275 | return t->display_info.w32; |
| 276 | } | 276 | } |
| @@ -304,7 +304,7 @@ x_window_to_frame (struct w32_display_info *dpyinfo, HWND wdesc) | |||
| 304 | continue; | 304 | continue; |
| 305 | 305 | ||
| 306 | if (FRAME_W32_WINDOW (f) == wdesc) | 306 | if (FRAME_W32_WINDOW (f) == wdesc) |
| 307 | return f; | 307 | return f; |
| 308 | } | 308 | } |
| 309 | return 0; | 309 | return 0; |
| 310 | } | 310 | } |
| @@ -366,7 +366,7 @@ w32_fullscreen_rect (HWND hwnd, int fsmode, RECT normal, RECT *rect) | |||
| 366 | if (monitor_from_window_fn && get_monitor_info_fn) | 366 | if (monitor_from_window_fn && get_monitor_info_fn) |
| 367 | { | 367 | { |
| 368 | HMONITOR monitor = | 368 | HMONITOR monitor = |
| 369 | monitor_from_window_fn (hwnd, MONITOR_DEFAULT_TO_NEAREST); | 369 | monitor_from_window_fn (hwnd, MONITOR_DEFAULT_TO_NEAREST); |
| 370 | get_monitor_info_fn (monitor, &mi); | 370 | get_monitor_info_fn (monitor, &mi); |
| 371 | } | 371 | } |
| 372 | else | 372 | else |
| @@ -949,8 +949,8 @@ x_to_w32_color (const char * colorname) | |||
| 949 | break; | 949 | break; |
| 950 | val = (UINT)(0x100 * value); | 950 | val = (UINT)(0x100 * value); |
| 951 | /* We used 0x100 instead of 0xFF to give a continuous | 951 | /* We used 0x100 instead of 0xFF to give a continuous |
| 952 | range between 0.0 and 1.0 inclusive. The next statement | 952 | range between 0.0 and 1.0 inclusive. The next statement |
| 953 | fixes the 1.0 case. */ | 953 | fixes the 1.0 case. */ |
| 954 | if (val == 0x100) | 954 | if (val == 0x100) |
| 955 | val = 0xFF; | 955 | val = 0xFF; |
| 956 | colorval |= (val << pos); | 956 | colorval |= (val << pos); |
| @@ -1060,7 +1060,7 @@ w32_map_color (struct frame *f, COLORREF color) | |||
| 1060 | while (list) | 1060 | while (list) |
| 1061 | { | 1061 | { |
| 1062 | if (W32_COLOR (list->entry) == color) | 1062 | if (W32_COLOR (list->entry) == color) |
| 1063 | { | 1063 | { |
| 1064 | ++list->refcount; | 1064 | ++list->refcount; |
| 1065 | return; | 1065 | return; |
| 1066 | } | 1066 | } |
| @@ -1092,7 +1092,7 @@ w32_unmap_color (struct frame *f, COLORREF color) | |||
| 1092 | while (list) | 1092 | while (list) |
| 1093 | { | 1093 | { |
| 1094 | if (W32_COLOR (list->entry) == color) | 1094 | if (W32_COLOR (list->entry) == color) |
| 1095 | { | 1095 | { |
| 1096 | if (--list->refcount == 0) | 1096 | if (--list->refcount == 0) |
| 1097 | { | 1097 | { |
| 1098 | *prev = list->next; | 1098 | *prev = list->next; |
| @@ -1121,9 +1121,9 @@ gamma_correct (struct frame *f, COLORREF *color) | |||
| 1121 | if (f->gamma) | 1121 | if (f->gamma) |
| 1122 | { | 1122 | { |
| 1123 | *color = PALETTERGB ( | 1123 | *color = PALETTERGB ( |
| 1124 | pow (GetRValue (*color) / 255.0, f->gamma) * 255.0 + 0.5, | 1124 | pow (GetRValue (*color) / 255.0, f->gamma) * 255.0 + 0.5, |
| 1125 | pow (GetGValue (*color) / 255.0, f->gamma) * 255.0 + 0.5, | 1125 | pow (GetGValue (*color) / 255.0, f->gamma) * 255.0 + 0.5, |
| 1126 | pow (GetBValue (*color) / 255.0, f->gamma) * 255.0 + 0.5); | 1126 | pow (GetBValue (*color) / 255.0, f->gamma) * 255.0 + 0.5); |
| 1127 | } | 1127 | } |
| 1128 | } | 1128 | } |
| 1129 | 1129 | ||
| @@ -1144,12 +1144,12 @@ w32_defined_color (struct frame *f, const char *color, XColor *color_def, | |||
| 1144 | if (!NILP (tem)) | 1144 | if (!NILP (tem)) |
| 1145 | { | 1145 | { |
| 1146 | if (f) | 1146 | if (f) |
| 1147 | { | 1147 | { |
| 1148 | /* Apply gamma correction. */ | 1148 | /* Apply gamma correction. */ |
| 1149 | w32_color_ref = XUINT (tem); | 1149 | w32_color_ref = XUINT (tem); |
| 1150 | gamma_correct (f, &w32_color_ref); | 1150 | gamma_correct (f, &w32_color_ref); |
| 1151 | XSETINT (tem, w32_color_ref); | 1151 | XSETINT (tem, w32_color_ref); |
| 1152 | } | 1152 | } |
| 1153 | 1153 | ||
| 1154 | /* Map this color to the palette if it is enabled. */ | 1154 | /* Map this color to the palette if it is enabled. */ |
| 1155 | if (!NILP (Vw32_enable_palette)) | 1155 | if (!NILP (Vw32_enable_palette)) |
| @@ -1258,7 +1258,7 @@ x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | |||
| 1258 | 1258 | ||
| 1259 | update_face_from_frame_parameter (f, Qforeground_color, arg); | 1259 | update_face_from_frame_parameter (f, Qforeground_color, arg); |
| 1260 | if (FRAME_VISIBLE_P (f)) | 1260 | if (FRAME_VISIBLE_P (f)) |
| 1261 | redraw_frame (f); | 1261 | redraw_frame (f); |
| 1262 | } | 1262 | } |
| 1263 | } | 1263 | } |
| 1264 | 1264 | ||
| @@ -1271,12 +1271,12 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | |||
| 1271 | if (FRAME_W32_WINDOW (f) != 0) | 1271 | if (FRAME_W32_WINDOW (f) != 0) |
| 1272 | { | 1272 | { |
| 1273 | SetWindowLong (FRAME_W32_WINDOW (f), WND_BACKGROUND_INDEX, | 1273 | SetWindowLong (FRAME_W32_WINDOW (f), WND_BACKGROUND_INDEX, |
| 1274 | FRAME_BACKGROUND_PIXEL (f)); | 1274 | FRAME_BACKGROUND_PIXEL (f)); |
| 1275 | 1275 | ||
| 1276 | update_face_from_frame_parameter (f, Qbackground_color, arg); | 1276 | update_face_from_frame_parameter (f, Qbackground_color, arg); |
| 1277 | 1277 | ||
| 1278 | if (FRAME_VISIBLE_P (f)) | 1278 | if (FRAME_VISIBLE_P (f)) |
| 1279 | redraw_frame (f); | 1279 | redraw_frame (f); |
| 1280 | } | 1280 | } |
| 1281 | } | 1281 | } |
| 1282 | 1282 | ||
| @@ -1399,9 +1399,9 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | |||
| 1399 | XRecolorCursor (FRAME_W32_DISPLAY (f), mode_cursor, | 1399 | XRecolorCursor (FRAME_W32_DISPLAY (f), mode_cursor, |
| 1400 | &fore_color, &back_color); | 1400 | &fore_color, &back_color); |
| 1401 | XRecolorCursor (FRAME_W32_DISPLAY (f), hand_cursor, | 1401 | XRecolorCursor (FRAME_W32_DISPLAY (f), hand_cursor, |
| 1402 | &fore_color, &back_color); | 1402 | &fore_color, &back_color); |
| 1403 | XRecolorCursor (FRAME_W32_DISPLAY (f), hourglass_cursor, | 1403 | XRecolorCursor (FRAME_W32_DISPLAY (f), hourglass_cursor, |
| 1404 | &fore_color, &back_color); | 1404 | &fore_color, &back_color); |
| 1405 | } | 1405 | } |
| 1406 | 1406 | ||
| 1407 | if (FRAME_W32_WINDOW (f) != 0) | 1407 | if (FRAME_W32_WINDOW (f) != 0) |
| @@ -1445,7 +1445,7 @@ x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | |||
| 1445 | 1445 | ||
| 1446 | if (!NILP (Vx_cursor_fore_pixel)) | 1446 | if (!NILP (Vx_cursor_fore_pixel)) |
| 1447 | fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel, | 1447 | fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel, |
| 1448 | WHITE_PIX_DEFAULT (f)); | 1448 | WHITE_PIX_DEFAULT (f)); |
| 1449 | else | 1449 | else |
| 1450 | fore_pixel = FRAME_BACKGROUND_PIXEL (f); | 1450 | fore_pixel = FRAME_BACKGROUND_PIXEL (f); |
| 1451 | 1451 | ||
| @@ -1494,7 +1494,7 @@ x_set_border_pixel (struct frame *f, int pix) | |||
| 1494 | if (FRAME_W32_WINDOW (f) != 0 && f->border_width > 0) | 1494 | if (FRAME_W32_WINDOW (f) != 0 && f->border_width > 0) |
| 1495 | { | 1495 | { |
| 1496 | if (FRAME_VISIBLE_P (f)) | 1496 | if (FRAME_VISIBLE_P (f)) |
| 1497 | redraw_frame (f); | 1497 | redraw_frame (f); |
| 1498 | } | 1498 | } |
| 1499 | } | 1499 | } |
| 1500 | 1500 | ||
| @@ -1771,7 +1771,7 @@ w32_set_title_bar_text (struct frame *f, Lisp_Object name) | |||
| 1771 | block_input (); | 1771 | block_input (); |
| 1772 | #ifdef __CYGWIN__ | 1772 | #ifdef __CYGWIN__ |
| 1773 | GUI_FN (SetWindowText) (FRAME_W32_WINDOW (f), | 1773 | GUI_FN (SetWindowText) (FRAME_W32_WINDOW (f), |
| 1774 | GUI_SDATA (GUI_ENCODE_SYSTEM (name))); | 1774 | GUI_SDATA (GUI_ENCODE_SYSTEM (name))); |
| 1775 | #else | 1775 | #else |
| 1776 | /* The frame's title many times shows the name of the file | 1776 | /* The frame's title many times shows the name of the file |
| 1777 | visited in the selected window's buffer, so it makes sense to | 1777 | visited in the selected window's buffer, so it makes sense to |
| @@ -2319,7 +2319,7 @@ w32_get_modifiers (void) | |||
| 2319 | (modifier_set (VK_RWIN) ? w32_key_to_modifier (VK_RWIN) : 0) | | 2319 | (modifier_set (VK_RWIN) ? w32_key_to_modifier (VK_RWIN) : 0) | |
| 2320 | (modifier_set (VK_APPS) ? w32_key_to_modifier (VK_APPS) : 0) | | 2320 | (modifier_set (VK_APPS) ? w32_key_to_modifier (VK_APPS) : 0) | |
| 2321 | (modifier_set (VK_SCROLL) ? w32_key_to_modifier (VK_SCROLL) : 0) | | 2321 | (modifier_set (VK_SCROLL) ? w32_key_to_modifier (VK_SCROLL) : 0) | |
| 2322 | (modifier_set (VK_MENU) ? | 2322 | (modifier_set (VK_MENU) ? |
| 2323 | ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier) : 0)); | 2323 | ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier) : 0)); |
| 2324 | } | 2324 | } |
| 2325 | 2325 | ||
| @@ -2541,13 +2541,13 @@ w32_msg_pump (deferred_msg * msg_buf) | |||
| 2541 | /* Produced by complete_deferred_msg; just ignore. */ | 2541 | /* Produced by complete_deferred_msg; just ignore. */ |
| 2542 | break; | 2542 | break; |
| 2543 | case WM_EMACS_CREATEWINDOW: | 2543 | case WM_EMACS_CREATEWINDOW: |
| 2544 | /* Initialize COM for this window. Even though we don't use it, | 2544 | /* Initialize COM for this window. Even though we don't use it, |
| 2545 | some third party shell extensions can cause it to be used in | 2545 | some third party shell extensions can cause it to be used in |
| 2546 | system dialogs, which causes a crash if it is not initialized. | 2546 | system dialogs, which causes a crash if it is not initialized. |
| 2547 | This is a known bug in Windows, which was fixed long ago, but | 2547 | This is a known bug in Windows, which was fixed long ago, but |
| 2548 | the patch for XP is not publicly available until XP SP3, | 2548 | the patch for XP is not publicly available until XP SP3, |
| 2549 | and older versions will never be patched. */ | 2549 | and older versions will never be patched. */ |
| 2550 | CoInitialize (NULL); | 2550 | CoInitialize (NULL); |
| 2551 | w32_createwindow ((struct frame *) msg.wParam, | 2551 | w32_createwindow ((struct frame *) msg.wParam, |
| 2552 | (int *) msg.lParam); | 2552 | (int *) msg.lParam); |
| 2553 | if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0)) | 2553 | if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0)) |
| @@ -2577,9 +2577,9 @@ w32_msg_pump (deferred_msg * msg_buf) | |||
| 2577 | if (focus_window != NULL) | 2577 | if (focus_window != NULL) |
| 2578 | UnregisterHotKey (focus_window, RAW_HOTKEY_ID (msg.wParam)); | 2578 | UnregisterHotKey (focus_window, RAW_HOTKEY_ID (msg.wParam)); |
| 2579 | /* Mark item as erased. NB: this code must be | 2579 | /* Mark item as erased. NB: this code must be |
| 2580 | thread-safe. The next line is okay because the cons | 2580 | thread-safe. The next line is okay because the cons |
| 2581 | cell is never made into garbage and is not relocated by | 2581 | cell is never made into garbage and is not relocated by |
| 2582 | GC. */ | 2582 | GC. */ |
| 2583 | XSETCAR (make_lisp_ptr ((void *)msg.lParam, Lisp_Cons), Qnil); | 2583 | XSETCAR (make_lisp_ptr ((void *)msg.lParam, Lisp_Cons), Qnil); |
| 2584 | if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0)) | 2584 | if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0)) |
| 2585 | emacs_abort (); | 2585 | emacs_abort (); |
| @@ -2612,10 +2612,10 @@ w32_msg_pump (deferred_msg * msg_buf) | |||
| 2612 | } | 2612 | } |
| 2613 | break; | 2613 | break; |
| 2614 | #ifdef MSG_DEBUG | 2614 | #ifdef MSG_DEBUG |
| 2615 | /* Broadcast messages make it here, so you need to be looking | 2615 | /* Broadcast messages make it here, so you need to be looking |
| 2616 | for something in particular for this to be useful. */ | 2616 | for something in particular for this to be useful. */ |
| 2617 | default: | 2617 | default: |
| 2618 | DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message)); | 2618 | DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message)); |
| 2619 | #endif | 2619 | #endif |
| 2620 | } | 2620 | } |
| 2621 | } | 2621 | } |
| @@ -2809,19 +2809,19 @@ post_character_message (HWND hwnd, UINT msg, | |||
| 2809 | signal_quit (); | 2809 | signal_quit (); |
| 2810 | 2810 | ||
| 2811 | /* As a safety precaution, forcibly complete any deferred | 2811 | /* As a safety precaution, forcibly complete any deferred |
| 2812 | messages. This is a kludge, but I don't see any particularly | 2812 | messages. This is a kludge, but I don't see any particularly |
| 2813 | clean way to handle the situation where a deferred message is | 2813 | clean way to handle the situation where a deferred message is |
| 2814 | "dropped" in the lisp thread, and will thus never be | 2814 | "dropped" in the lisp thread, and will thus never be |
| 2815 | completed, eg. by the user trying to activate the menubar | 2815 | completed, eg. by the user trying to activate the menubar |
| 2816 | when the lisp thread is busy, and then typing C-g when the | 2816 | when the lisp thread is busy, and then typing C-g when the |
| 2817 | menubar doesn't open promptly (with the result that the | 2817 | menubar doesn't open promptly (with the result that the |
| 2818 | menubar never responds at all because the deferred | 2818 | menubar never responds at all because the deferred |
| 2819 | WM_INITMENU message is never completed). Another problem | 2819 | WM_INITMENU message is never completed). Another problem |
| 2820 | situation is when the lisp thread calls SendMessage (to send | 2820 | situation is when the lisp thread calls SendMessage (to send |
| 2821 | a window manager command) when a message has been deferred; | 2821 | a window manager command) when a message has been deferred; |
| 2822 | the lisp thread gets blocked indefinitely waiting for the | 2822 | the lisp thread gets blocked indefinitely waiting for the |
| 2823 | deferred message to be completed, which itself is waiting for | 2823 | deferred message to be completed, which itself is waiting for |
| 2824 | the lisp thread to respond. | 2824 | the lisp thread to respond. |
| 2825 | 2825 | ||
| 2826 | Note that we don't want to block the input thread waiting for | 2826 | Note that we don't want to block the input thread waiting for |
| 2827 | a response from the lisp thread (although that would at least | 2827 | a response from the lisp thread (although that would at least |
| @@ -2836,6 +2836,407 @@ post_character_message (HWND hwnd, UINT msg, | |||
| 2836 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); | 2836 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); |
| 2837 | } | 2837 | } |
| 2838 | 2838 | ||
| 2839 | static int | ||
| 2840 | get_wm_chars (HWND aWnd, int *buf, int buflen, int ignore_ctrl, int ctrl, | ||
| 2841 | int *ctrl_cnt, int *is_dead, int vk, int exp) | ||
| 2842 | { | ||
| 2843 | MSG msg; | ||
| 2844 | /* If doubled is at the end, ignore it. */ | ||
| 2845 | int i = buflen, doubled = 0, code_unit; | ||
| 2846 | |||
| 2847 | if (ctrl_cnt) | ||
| 2848 | *ctrl_cnt = 0; | ||
| 2849 | if (is_dead) | ||
| 2850 | *is_dead = -1; | ||
| 2851 | eassert(w32_unicode_gui); | ||
| 2852 | while (buflen | ||
| 2853 | /* Should be called only when w32_unicode_gui: */ | ||
| 2854 | && PeekMessageW(&msg, aWnd, WM_KEYFIRST, WM_KEYLAST, | ||
| 2855 | PM_NOREMOVE | PM_NOYIELD) | ||
| 2856 | && (msg.message == WM_CHAR || msg.message == WM_SYSCHAR | ||
| 2857 | || msg.message == WM_DEADCHAR || msg.message == WM_SYSDEADCHAR | ||
| 2858 | || msg.message == WM_UNICHAR)) | ||
| 2859 | { | ||
| 2860 | /* We extract character payload, but in this call we handle only the | ||
| 2861 | characters which comes BEFORE the next keyup/keydown message. */ | ||
| 2862 | int dead; | ||
| 2863 | |||
| 2864 | GetMessageW(&msg, aWnd, msg.message, msg.message); | ||
| 2865 | dead = (msg.message == WM_DEADCHAR || msg.message == WM_SYSDEADCHAR); | ||
| 2866 | if (is_dead) | ||
| 2867 | *is_dead = (dead ? msg.wParam : -1); | ||
| 2868 | if (dead) | ||
| 2869 | continue; | ||
| 2870 | code_unit = msg.wParam; | ||
| 2871 | if (doubled) | ||
| 2872 | { | ||
| 2873 | /* Had surrogate. */ | ||
| 2874 | if (msg.message == WM_UNICHAR | ||
| 2875 | || code_unit < 0xDC00 || code_unit > 0xDFFF) | ||
| 2876 | { /* Mismatched first surrogate. | ||
| 2877 | Pass both code units as if they were two characters. */ | ||
| 2878 | *buf++ = doubled; | ||
| 2879 | if (!--buflen) | ||
| 2880 | return i; /* Drop the 2nd char if at the end of the buffer. */ | ||
| 2881 | } | ||
| 2882 | else /* see https://en.wikipedia.org/wiki/UTF-16 */ | ||
| 2883 | code_unit = (doubled << 10) + code_unit - 0x35FDC00; | ||
| 2884 | doubled = 0; | ||
| 2885 | } | ||
| 2886 | else if (code_unit >= 0xD800 && code_unit <= 0xDBFF) | ||
| 2887 | { | ||
| 2888 | /* Handle mismatched 2nd surrogate the same as a normal character. */ | ||
| 2889 | doubled = code_unit; | ||
| 2890 | continue; | ||
| 2891 | } | ||
| 2892 | |||
| 2893 | /* The only "fake" characters delivered by ToUnicode() or | ||
| 2894 | TranslateMessage() are: | ||
| 2895 | 0x01 .. 0x1a for Ctrl-letter, Enter, Tab, Ctrl-Break, Esc, Backspace | ||
| 2896 | 0x00 and 0x1b .. 0x1f for Control- []\@^_ | ||
| 2897 | 0x7f for Control-BackSpace | ||
| 2898 | 0x20 for Control-Space */ | ||
| 2899 | if (ignore_ctrl | ||
| 2900 | && (code_unit < 0x20 || code_unit == 0x7f | ||
| 2901 | || (code_unit == 0x20 && ctrl))) | ||
| 2902 | { | ||
| 2903 | /* Non-character payload in a WM_CHAR | ||
| 2904 | (Ctrl-something pressed, see above). Ignore, and report. */ | ||
| 2905 | if (ctrl_cnt) | ||
| 2906 | *ctrl_cnt++; | ||
| 2907 | continue; | ||
| 2908 | } | ||
| 2909 | /* Traditionally, Emacs would ignore the character payload of VK_NUMPAD* | ||
| 2910 | keys, and would treat them later via `function-key-map'. In addition | ||
| 2911 | to usual 102-key NUMPAD keys, this map also treats `kp-'-variants of | ||
| 2912 | space, tab, enter, separator, equal. TAB and EQUAL, apparently, | ||
| 2913 | cannot be generated on Win-GUI branch. ENTER is already handled | ||
| 2914 | by the code above. According to `lispy_function_keys', kp_space is | ||
| 2915 | generated by not-extended VK_CLEAR. (kp-tab != VK_OEM_NEC_EQUAL!). | ||
| 2916 | |||
| 2917 | We do similarly for backward-compatibility, but ignore only the | ||
| 2918 | characters restorable later by `function-key-map'. */ | ||
| 2919 | if (code_unit < 0x7f | ||
| 2920 | && ((vk >= VK_NUMPAD0 && vk <= VK_DIVIDE) | ||
| 2921 | || (exp && ((vk >= VK_PRIOR && vk <= VK_DOWN) || | ||
| 2922 | vk == VK_INSERT || vk == VK_DELETE || vk == VK_CLEAR))) | ||
| 2923 | && strchr("0123456789/*-+.,", code_unit)) | ||
| 2924 | continue; | ||
| 2925 | *buf++ = code_unit; | ||
| 2926 | buflen--; | ||
| 2927 | } | ||
| 2928 | return i - buflen; | ||
| 2929 | } | ||
| 2930 | |||
| 2931 | #ifdef DBG_WM_CHARS | ||
| 2932 | # define FPRINTF_WM_CHARS(ARG) fprintf ARG | ||
| 2933 | #else | ||
| 2934 | # define FPRINTF_WM_CHARS(ARG) 0 | ||
| 2935 | #endif | ||
| 2936 | |||
| 2937 | /* This is a heuristic only. This is supposed to track the state of the | ||
| 2938 | finite automaton in the language environment of Windows. | ||
| 2939 | |||
| 2940 | However, separate windows (if with the same different language | ||
| 2941 | environments!) should have different values. Moreover, switching to a | ||
| 2942 | non-Emacs window with the same language environment, and using (dead)keys | ||
| 2943 | there would change the value stored in the kernel, but not this value. */ | ||
| 2944 | static int after_deadkey = 0; | ||
| 2945 | |||
| 2946 | int | ||
| 2947 | deliver_wm_chars (int do_translate, HWND hwnd, UINT msg, UINT wParam, | ||
| 2948 | UINT lParam, int legacy_alt_meta) | ||
| 2949 | { | ||
| 2950 | /* An "old style" keyboard description may assign up to 125 UTF-16 code | ||
| 2951 | points to a keypress. | ||
| 2952 | (However, the "old style" TranslateMessage() would deliver at most 16 of | ||
| 2953 | them.) Be on a safe side, and prepare to treat many more. */ | ||
| 2954 | int ctrl_cnt, buf[1024], count, is_dead, after_dead = (after_deadkey != -1); | ||
| 2955 | |||
| 2956 | /* Since the keypress processing logic of Windows has a lot of state, it | ||
| 2957 | is important to call TranslateMessage() for every keyup/keydown, AND | ||
| 2958 | do it exactly once. (The actual change of state is done by | ||
| 2959 | ToUnicode[Ex](), which is called by TranslateMessage(). So one can | ||
| 2960 | call ToUnicode[Ex]() instead.) | ||
| 2961 | |||
| 2962 | The "usual" message pump calls TranslateMessage() for EVERY event. | ||
| 2963 | Emacs calls TranslateMessage() very selectively (is it needed for doing | ||
| 2964 | some tricky stuff with Win95??? With newer Windows, selectiveness is, | ||
| 2965 | most probably, not needed - and harms a lot). | ||
| 2966 | |||
| 2967 | So, with the usual message pump, the following call to TranslateMessage() | ||
| 2968 | is not needed (and is going to be VERY harmful). With Emacs' message | ||
| 2969 | pump, the call is needed. */ | ||
| 2970 | if (do_translate) | ||
| 2971 | { | ||
| 2972 | MSG windows_msg = { hwnd, msg, wParam, lParam, 0, {0,0} }; | ||
| 2973 | |||
| 2974 | windows_msg.time = GetMessageTime (); | ||
| 2975 | TranslateMessage (&windows_msg); | ||
| 2976 | } | ||
| 2977 | count = get_wm_chars (hwnd, buf, sizeof(buf)/sizeof(*buf), 1, | ||
| 2978 | /* The message may have been synthesized by | ||
| 2979 | who knows what; be conservative. */ | ||
| 2980 | modifier_set (VK_LCONTROL) | ||
| 2981 | || modifier_set (VK_RCONTROL) | ||
| 2982 | || modifier_set (VK_CONTROL), | ||
| 2983 | &ctrl_cnt, &is_dead, wParam, | ||
| 2984 | (lParam & 0x1000000L) != 0); | ||
| 2985 | if (count) | ||
| 2986 | { | ||
| 2987 | W32Msg wmsg; | ||
| 2988 | DWORD console_modifiers = construct_console_modifiers (); | ||
| 2989 | int *b = buf, strip_Alt = 1, strip_ExtraMods = 1, hairy = 0; | ||
| 2990 | char *type_CtrlAlt = NULL; | ||
| 2991 | |||
| 2992 | /* XXXX In fact, there may be another case when we need to do the same: | ||
| 2993 | What happens if the string defined in the LIGATURES has length | ||
| 2994 | 0? Probably, we will get count==0, but the state of the finite | ||
| 2995 | automaton would reset to 0??? */ | ||
| 2996 | after_deadkey = -1; | ||
| 2997 | |||
| 2998 | /* wParam is checked when converting CapsLock to Shift; this is a clone | ||
| 2999 | of w32_get_key_modifiers (). */ | ||
| 3000 | wmsg.dwModifiers = w32_kbd_mods_to_emacs (console_modifiers, wParam); | ||
| 3001 | |||
| 3002 | /* What follows is just heuristics; the correct treatement requires | ||
| 3003 | non-destructive ToUnicode(): | ||
| 3004 | http://search.cpan.org/~ilyaz/UI-KeyboardLayout/lib/UI/KeyboardLayout.pm#Can_an_application_on_Windows_accept_keyboard_events?_Part_IV:_application-specific_modifiers | ||
| 3005 | |||
| 3006 | What one needs to find is: | ||
| 3007 | * which of the present modifiers AFFECT the resulting char(s) | ||
| 3008 | (so should be stripped, since their EFFECT is "already | ||
| 3009 | taken into account" in the string in buf), and | ||
| 3010 | * which modifiers are not affecting buf, so should be reported to | ||
| 3011 | the application for further treatment. | ||
| 3012 | |||
| 3013 | Example: assume that we know: | ||
| 3014 | (A) lCtrl+rCtrl+rAlt modifiers with VK_A key produce a Latin "f" | ||
| 3015 | ("may be logical" in JCUKEN-flavored Russian keyboard flavors); | ||
| 3016 | (B) removing any of lCtrl, rCtrl, rAlt changes the produced char; | ||
| 3017 | (C) Win-modifier is not affecting the produced character | ||
| 3018 | (this is the common case: happens with all "standard" layouts). | ||
| 3019 | |||
| 3020 | Suppose the user presses Win+lCtrl+rCtrl+rAlt modifiers with VK_A. | ||
| 3021 | What is the intent of the user? We need to guess the intent to decide | ||
| 3022 | which event to deliver to the application. | ||
| 3023 | |||
| 3024 | This looks like a reasonable logic: since Win- modifier doesn't affect | ||
| 3025 | the output string, the user was pressing Win for SOME OTHER purpose. | ||
| 3026 | So the user wanted to generate Win-SOMETHING event. Now, what is | ||
| 3027 | something? If one takes the mantra that "character payload is more | ||
| 3028 | important than the combination of keypresses which resulted in this | ||
| 3029 | payload", then one should ignore lCtrl+rCtrl+rAlt, ignore VK_A, and | ||
| 3030 | assume that the user wanted to generate Win-f. | ||
| 3031 | |||
| 3032 | Unfortunately, without non-destructive ToUnicode(), checking (B),(C) | ||
| 3033 | is out of question. So we use heuristics (hopefully, covering | ||
| 3034 | 99.9999% of cases). */ | ||
| 3035 | |||
| 3036 | /* Another thing to watch for is a possibility to use AltGr-* and | ||
| 3037 | Ctrl-Alt-* with different semantic. | ||
| 3038 | |||
| 3039 | Background: the layout defining the KLLF_ALTGR bit are treated | ||
| 3040 | specially by the kernel: when VK_RMENU (=rightAlt, =AltGr) is pressed | ||
| 3041 | (released), a press (release) of VK_LCONTROL is emulated (unless Ctrl | ||
| 3042 | is already down). As a result, any press/release of AltGr is seen | ||
| 3043 | by applications as a press/release of lCtrl AND rAlt. This is | ||
| 3044 | applicable, in particular, to ToUnicode[Ex](). (Keyrepeat is covered | ||
| 3045 | the same way!) | ||
| 3046 | |||
| 3047 | NOTE: it IS possible to see bare rAlt even with KLLF_ALTGR; but this | ||
| 3048 | requires a good finger coordination: doing (physically) | ||
| 3049 | Down-lCtrl Down-rAlt Up-lCtrl Down-a | ||
| 3050 | (doing quick enough, so that key repeat of rAlt [which would | ||
| 3051 | generate new "fake" Down-lCtrl events] does not happens before 'a' | ||
| 3052 | is down) results in no "fake" events, so the application will see | ||
| 3053 | only rAlt down when 'a' is pressed. (However, fake Up-lCtrl WILL | ||
| 3054 | be generated when rAlt goes UP.) | ||
| 3055 | |||
| 3056 | In fact, note also that KLLF_ALTGR does not prohibit construction of | ||
| 3057 | rCtrl-rAlt (just press them in this order!). | ||
| 3058 | |||
| 3059 | Moreover: "traditional" layouts do not define distinct modifier-masks | ||
| 3060 | for VK_LMENU and VK_RMENU (same for VK_L/RCONTROL). Instead, they | ||
| 3061 | rely on the KLLF_ALTGR bit to make the behaviour of VK_LMENU and | ||
| 3062 | VK_RMENU distinct. As a corollary, for such layouts, the produced | ||
| 3063 | character is the same for AltGr-* (=rAlt-*) and Ctrl-Alt-* (in any | ||
| 3064 | combination of handedness). For description of masks, see | ||
| 3065 | |||
| 3066 | http://search.cpan.org/~ilyaz/UI-KeyboardLayout/lib/UI/KeyboardLayout.pm#Keyboard_input_on_Windows,_Part_I:_what_is_the_kernel_doing? | ||
| 3067 | |||
| 3068 | By default, Emacs was using these coincidences via the following | ||
| 3069 | heuristics: it was treating: | ||
| 3070 | (*) keypresses with lCtrl-rAlt modifiers as if they are carrying | ||
| 3071 | ONLY the character payload (no matter what the actual keyboard | ||
| 3072 | was defining: if lCtrl-lAlt-b was delivering U+05df=beta, then | ||
| 3073 | Emacs saw [beta]; if lCtrl-lAlt-b was undefined in the layout, | ||
| 3074 | the keypress was completely ignored), and | ||
| 3075 | (*) keypresses with the other combinations of handedness of Ctrl-Alt | ||
| 3076 | modifiers (e.g., lCtrl-lAlt) as if they NEVER carry a character | ||
| 3077 | payload (so they were reported "raw": if lCtrl-lAlt-b was | ||
| 3078 | delivering beta, then Emacs saw event [C-A-b], and not [beta]). | ||
| 3079 | This worked good for "traditional" layouts: users could type both | ||
| 3080 | AltGr-x and Ctrl-Alt-x, and one was a character, another a bindable | ||
| 3081 | event. | ||
| 3082 | |||
| 3083 | However, for layouts which deliver different characters for AltGr-x | ||
| 3084 | and lCtrl-lAlt-x, this scheme makes the latter character unaccessible | ||
| 3085 | in Emacs. While it is easy to access functionality of [C-M-x] in | ||
| 3086 | Emacs by other means (for example, by the `controlify' prefix, or | ||
| 3087 | using lCtrl-rCtrl-x, or rCtrl-rAlt-x [in this order]), missing | ||
| 3088 | characters cannot be reconstructed without a tedious manual work. */ | ||
| 3089 | |||
| 3090 | /* These two cases are often going to be distinguishable, since at most | ||
| 3091 | one of these character is defined with KBDCTRL | KBDMENU modifier | ||
| 3092 | bitmap. (This heuristic breaks if both lCtrl-lAlt- AND lCtrl-rAlt- | ||
| 3093 | are translated to modifier bitmaps distinct from KBDCTRL | KBDMENU, | ||
| 3094 | or in the cases when lCtrl-lAlt-* and lCtrl-rAlt-* are generally | ||
| 3095 | different, but lCtrl-lAlt-x and lCtrl-rAlt-x happen to deliver the | ||
| 3096 | same character.) | ||
| 3097 | |||
| 3098 | So we have 2 chunks of info: | ||
| 3099 | (A) is it lCtrl-rAlt-, or lCtrl-lAlt, or some other combination? | ||
| 3100 | (B) is the delivered character defined with KBDCTRL | KBDMENU bits? | ||
| 3101 | Basing on (A) and (B), we should decide whether to ignore the | ||
| 3102 | delivered character. (Before, Emacs was completely ignoring (B), and | ||
| 3103 | was treating the 3-state of (A) as a bit.) This means that we have 6 | ||
| 3104 | bits of customization. | ||
| 3105 | |||
| 3106 | Additionally, a presence of two Ctrl down may be AltGr-rCtrl-. */ | ||
| 3107 | |||
| 3108 | /* Strip all non-Shift modifiers if: | ||
| 3109 | - more than one UTF-16 code point delivered (can't call VkKeyScanW ()) | ||
| 3110 | - or the character is a result of combining with a prefix key. */ | ||
| 3111 | if (!after_dead && count == 1 && *b < 0x10000) | ||
| 3112 | { | ||
| 3113 | if (console_modifiers & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED) | ||
| 3114 | && console_modifiers & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) | ||
| 3115 | { | ||
| 3116 | type_CtrlAlt = "bB"; /* generic bindable Ctrl-Alt- modifiers */ | ||
| 3117 | if (console_modifiers & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) | ||
| 3118 | == (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) | ||
| 3119 | /* double-Ctrl: | ||
| 3120 | e.g. AltGr-rCtrl on some layouts (in this order!) */ | ||
| 3121 | type_CtrlAlt = "dD"; | ||
| 3122 | else if (console_modifiers | ||
| 3123 | & (LEFT_CTRL_PRESSED | LEFT_ALT_PRESSED) | ||
| 3124 | == (LEFT_CTRL_PRESSED | LEFT_ALT_PRESSED)) | ||
| 3125 | type_CtrlAlt = "lL"; /* Ctrl-Alt- modifiers on the left */ | ||
| 3126 | else if (!NILP (Vw32_recognize_altgr) | ||
| 3127 | && (console_modifiers | ||
| 3128 | & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) | ||
| 3129 | == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) | ||
| 3130 | type_CtrlAlt = "gG"; /* modifiers as in AltGr */ | ||
| 3131 | } | ||
| 3132 | else if (wmsg.dwModifiers & (alt_modifier | meta_modifier) | ||
| 3133 | || (console_modifiers | ||
| 3134 | & (RIGHT_WIN_PRESSED | RIGHT_WIN_PRESSED | ||
| 3135 | | APPS_PRESSED | SCROLLLOCK_ON))) | ||
| 3136 | { | ||
| 3137 | /* Pure Alt (or combination of Alt, Win, APPS, scrolllock. */ | ||
| 3138 | type_CtrlAlt = "aA"; | ||
| 3139 | } | ||
| 3140 | if (type_CtrlAlt) | ||
| 3141 | { | ||
| 3142 | /* Out of bound bitmap: */ | ||
| 3143 | SHORT r = VkKeyScanW( *b ), bitmap = 0x1FF; | ||
| 3144 | |||
| 3145 | FPRINTF_WM_CHARS((stderr, "VkKeyScanW %#06x %#04x\n", (int)r, | ||
| 3146 | wParam)); | ||
| 3147 | if ((r & 0xFF) == wParam) | ||
| 3148 | bitmap = r>>8; /* *b is reachable via simple interface */ | ||
| 3149 | if (*type_CtrlAlt == 'a') /* Simple Alt seen */ | ||
| 3150 | { | ||
| 3151 | if ((bitmap & ~1) == 0) /* 1: KBDSHIFT */ | ||
| 3152 | { | ||
| 3153 | /* In "traditional" layouts, Alt without Ctrl does not | ||
| 3154 | change the delivered character. This detects this | ||
| 3155 | situation; it is safe to report this as Alt-something | ||
| 3156 | - as opposed to delivering the reported character | ||
| 3157 | without modifiers. */ | ||
| 3158 | if (legacy_alt_meta | ||
| 3159 | && *b > 0x7f && ('A' <= wParam && wParam <= 'Z')) | ||
| 3160 | /* For backward-compatibility with older Emacsen, let | ||
| 3161 | this be processed by another branch below (which | ||
| 3162 | would convert it to Alt-Latin char via wParam). */ | ||
| 3163 | return 0; | ||
| 3164 | } | ||
| 3165 | else | ||
| 3166 | hairy = 1; | ||
| 3167 | } | ||
| 3168 | /* Check whether the delivered character(s) is accessible via | ||
| 3169 | KBDCTRL | KBDALT ( | KBDSHIFT ) modifier mask (which is 7). */ | ||
| 3170 | else if ((bitmap & ~1) != 6) | ||
| 3171 | { | ||
| 3172 | /* The character is not accessible via plain Ctrl-Alt(-Shift) | ||
| 3173 | (which is, probably, same as AltGr) modifiers. | ||
| 3174 | Either it was after a prefix key, or is combined with | ||
| 3175 | modifier keys which we don't see, or there is an asymmetry | ||
| 3176 | between left-hand and right-hand modifiers, or other hairy | ||
| 3177 | stuff. */ | ||
| 3178 | hairy = 1; | ||
| 3179 | } | ||
| 3180 | /* The best solution is to delegate these tough (but rarely | ||
| 3181 | needed) choices to the user. Temporarily (???), it is | ||
| 3182 | implemented as C macros. | ||
| 3183 | |||
| 3184 | Essentially, there are 3 things to do: return 0 (handle to the | ||
| 3185 | legacy processing code [ignoring the character payload]; keep | ||
| 3186 | some modifiers (so that they will be processed by the binding | ||
| 3187 | system [on top of the character payload]; strip modifiers [so | ||
| 3188 | that `self-insert' is going to be triggered with the character | ||
| 3189 | payload]). | ||
| 3190 | |||
| 3191 | The default below should cover 99.9999% of cases: | ||
| 3192 | (a) strip Alt- in the hairy case only; | ||
| 3193 | (stripping = not ignoring) | ||
| 3194 | (l) for lAlt-lCtrl, ignore the char in simple cases only; | ||
| 3195 | (g) for what looks like AltGr, ignore the modifiers; | ||
| 3196 | (d) for what looks like lCtrl-rCtrl-Alt (probably | ||
| 3197 | AltGr-rCtrl), ignore the character in simple cases only; | ||
| 3198 | (b) for other cases of Ctrl-Alt, ignore the character in | ||
| 3199 | simple cases only. | ||
| 3200 | |||
| 3201 | Essentially, in all hairy cases, and in looks-like-AltGr case, | ||
| 3202 | we keep the character, ignoring the modifiers. In all the | ||
| 3203 | other cases, we ignore the delivered character. */ | ||
| 3204 | #define S_TYPES_TO_IGNORE_CHARACTER_PAYLOAD "aldb" | ||
| 3205 | #define S_TYPES_TO_REPORT_CHARACTER_PAYLOAD_WITH_MODIFIERS "" | ||
| 3206 | if (strchr(S_TYPES_TO_IGNORE_CHARACTER_PAYLOAD, | ||
| 3207 | type_CtrlAlt[hairy])) | ||
| 3208 | return 0; | ||
| 3209 | /* If in neither list, report all the modifiers we see COMBINED | ||
| 3210 | WITH the reported character. */ | ||
| 3211 | if (strchr(S_TYPES_TO_REPORT_CHARACTER_PAYLOAD_WITH_MODIFIERS, | ||
| 3212 | type_CtrlAlt[hairy])) | ||
| 3213 | strip_ExtraMods = 0; | ||
| 3214 | } | ||
| 3215 | } | ||
| 3216 | if (strip_ExtraMods) | ||
| 3217 | wmsg.dwModifiers = wmsg.dwModifiers & shift_modifier; | ||
| 3218 | |||
| 3219 | signal_user_input (); | ||
| 3220 | while (count--) | ||
| 3221 | { | ||
| 3222 | FPRINTF_WM_CHARS((stderr, "unichar %#06x\n", *b)); | ||
| 3223 | my_post_msg (&wmsg, hwnd, WM_UNICHAR, *b++, lParam); | ||
| 3224 | } | ||
| 3225 | if (!ctrl_cnt) /* Process ALSO as ctrl */ | ||
| 3226 | return 1; | ||
| 3227 | else | ||
| 3228 | FPRINTF_WM_CHARS((stderr, "extra ctrl char\n")); | ||
| 3229 | return -1; | ||
| 3230 | } | ||
| 3231 | else if (is_dead >= 0) | ||
| 3232 | { | ||
| 3233 | FPRINTF_WM_CHARS((stderr, "dead %#06x\n", is_dead)); | ||
| 3234 | after_deadkey = is_dead; | ||
| 3235 | return 1; | ||
| 3236 | } | ||
| 3237 | return 0; | ||
| 3238 | } | ||
| 3239 | |||
| 2839 | /* Main window procedure */ | 3240 | /* Main window procedure */ |
| 2840 | 3241 | ||
| 2841 | static LRESULT CALLBACK | 3242 | static LRESULT CALLBACK |
| @@ -2869,15 +3270,15 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 2869 | f = x_window_to_frame (dpyinfo, hwnd); | 3270 | f = x_window_to_frame (dpyinfo, hwnd); |
| 2870 | if (f) | 3271 | if (f) |
| 2871 | { | 3272 | { |
| 2872 | HDC hdc = get_frame_dc (f); | 3273 | HDC hdc = get_frame_dc (f); |
| 2873 | GetUpdateRect (hwnd, &wmsg.rect, FALSE); | 3274 | GetUpdateRect (hwnd, &wmsg.rect, FALSE); |
| 2874 | w32_clear_rect (f, hdc, &wmsg.rect); | 3275 | w32_clear_rect (f, hdc, &wmsg.rect); |
| 2875 | release_frame_dc (f, hdc); | 3276 | release_frame_dc (f, hdc); |
| 2876 | 3277 | ||
| 2877 | #if defined (W32_DEBUG_DISPLAY) | 3278 | #if defined (W32_DEBUG_DISPLAY) |
| 2878 | DebPrint (("WM_ERASEBKGND (frame %p): erasing %d,%d-%d,%d\n", | 3279 | DebPrint (("WM_ERASEBKGND (frame %p): erasing %d,%d-%d,%d\n", |
| 2879 | f, | 3280 | f, |
| 2880 | wmsg.rect.left, wmsg.rect.top, | 3281 | wmsg.rect.left, wmsg.rect.top, |
| 2881 | wmsg.rect.right, wmsg.rect.bottom)); | 3282 | wmsg.rect.right, wmsg.rect.bottom)); |
| 2882 | #endif /* W32_DEBUG_DISPLAY */ | 3283 | #endif /* W32_DEBUG_DISPLAY */ |
| 2883 | } | 3284 | } |
| @@ -2885,7 +3286,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 2885 | case WM_PALETTECHANGED: | 3286 | case WM_PALETTECHANGED: |
| 2886 | /* ignore our own changes */ | 3287 | /* ignore our own changes */ |
| 2887 | if ((HWND)wParam != hwnd) | 3288 | if ((HWND)wParam != hwnd) |
| 2888 | { | 3289 | { |
| 2889 | f = x_window_to_frame (dpyinfo, hwnd); | 3290 | f = x_window_to_frame (dpyinfo, hwnd); |
| 2890 | if (f) | 3291 | if (f) |
| 2891 | /* get_frame_dc will realize our palette and force all | 3292 | /* get_frame_dc will realize our palette and force all |
| @@ -2895,24 +3296,24 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 2895 | return 0; | 3296 | return 0; |
| 2896 | case WM_PAINT: | 3297 | case WM_PAINT: |
| 2897 | { | 3298 | { |
| 2898 | PAINTSTRUCT paintStruct; | 3299 | PAINTSTRUCT paintStruct; |
| 2899 | RECT update_rect; | 3300 | RECT update_rect; |
| 2900 | memset (&update_rect, 0, sizeof (update_rect)); | 3301 | memset (&update_rect, 0, sizeof (update_rect)); |
| 2901 | 3302 | ||
| 2902 | f = x_window_to_frame (dpyinfo, hwnd); | 3303 | f = x_window_to_frame (dpyinfo, hwnd); |
| 2903 | if (f == 0) | 3304 | if (f == 0) |
| 2904 | { | 3305 | { |
| 2905 | DebPrint (("WM_PAINT received for unknown window %p\n", hwnd)); | 3306 | DebPrint (("WM_PAINT received for unknown window %p\n", hwnd)); |
| 2906 | return 0; | 3307 | return 0; |
| 2907 | } | 3308 | } |
| 2908 | 3309 | ||
| 2909 | /* MSDN Docs say not to call BeginPaint if GetUpdateRect | 3310 | /* MSDN Docs say not to call BeginPaint if GetUpdateRect |
| 2910 | fails. Apparently this can happen under some | 3311 | fails. Apparently this can happen under some |
| 2911 | circumstances. */ | 3312 | circumstances. */ |
| 2912 | if (GetUpdateRect (hwnd, &update_rect, FALSE) || !w32_strict_painting) | 3313 | if (GetUpdateRect (hwnd, &update_rect, FALSE) || !w32_strict_painting) |
| 2913 | { | 3314 | { |
| 2914 | enter_crit (); | 3315 | enter_crit (); |
| 2915 | BeginPaint (hwnd, &paintStruct); | 3316 | BeginPaint (hwnd, &paintStruct); |
| 2916 | 3317 | ||
| 2917 | /* The rectangles returned by GetUpdateRect and BeginPaint | 3318 | /* The rectangles returned by GetUpdateRect and BeginPaint |
| 2918 | do not always match. Play it safe by assuming both areas | 3319 | do not always match. Play it safe by assuming both areas |
| @@ -2920,40 +3321,49 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 2920 | UnionRect (&(wmsg.rect), &update_rect, &(paintStruct.rcPaint)); | 3321 | UnionRect (&(wmsg.rect), &update_rect, &(paintStruct.rcPaint)); |
| 2921 | 3322 | ||
| 2922 | #if defined (W32_DEBUG_DISPLAY) | 3323 | #if defined (W32_DEBUG_DISPLAY) |
| 2923 | DebPrint (("WM_PAINT (frame %p): painting %d,%d-%d,%d\n", | 3324 | DebPrint (("WM_PAINT (frame %p): painting %d,%d-%d,%d\n", |
| 2924 | f, | 3325 | f, |
| 2925 | wmsg.rect.left, wmsg.rect.top, | 3326 | wmsg.rect.left, wmsg.rect.top, |
| 2926 | wmsg.rect.right, wmsg.rect.bottom)); | 3327 | wmsg.rect.right, wmsg.rect.bottom)); |
| 2927 | DebPrint ((" [update region is %d,%d-%d,%d]\n", | 3328 | DebPrint ((" [update region is %d,%d-%d,%d]\n", |
| 2928 | update_rect.left, update_rect.top, | 3329 | update_rect.left, update_rect.top, |
| 2929 | update_rect.right, update_rect.bottom)); | 3330 | update_rect.right, update_rect.bottom)); |
| 2930 | #endif | 3331 | #endif |
| 2931 | EndPaint (hwnd, &paintStruct); | 3332 | EndPaint (hwnd, &paintStruct); |
| 2932 | leave_crit (); | 3333 | leave_crit (); |
| 2933 | 3334 | ||
| 2934 | /* Change the message type to prevent Windows from | 3335 | /* Change the message type to prevent Windows from |
| 2935 | combining WM_PAINT messages in the Lisp thread's queue, | 3336 | combining WM_PAINT messages in the Lisp thread's queue, |
| 2936 | since Windows assumes that each message queue is | 3337 | since Windows assumes that each message queue is |
| 2937 | dedicated to one frame and does not bother checking | 3338 | dedicated to one frame and does not bother checking |
| 2938 | that hwnd matches before combining them. */ | 3339 | that hwnd matches before combining them. */ |
| 2939 | my_post_msg (&wmsg, hwnd, WM_EMACS_PAINT, wParam, lParam); | 3340 | my_post_msg (&wmsg, hwnd, WM_EMACS_PAINT, wParam, lParam); |
| 2940 | 3341 | ||
| 2941 | return 0; | 3342 | return 0; |
| 2942 | } | 3343 | } |
| 2943 | 3344 | ||
| 2944 | /* If GetUpdateRect returns 0 (meaning there is no update | 3345 | /* If GetUpdateRect returns 0 (meaning there is no update |
| 2945 | region), assume the whole window needs to be repainted. */ | 3346 | region), assume the whole window needs to be repainted. */ |
| 2946 | GetClientRect (hwnd, &wmsg.rect); | 3347 | GetClientRect (hwnd, &wmsg.rect); |
| 2947 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); | 3348 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); |
| 2948 | return 0; | 3349 | return 0; |
| 2949 | } | 3350 | } |
| 2950 | 3351 | ||
| 2951 | case WM_INPUTLANGCHANGE: | 3352 | case WM_INPUTLANGCHANGE: |
| 2952 | /* Inform lisp thread of keyboard layout changes. */ | 3353 | /* Inform lisp thread of keyboard layout changes. */ |
| 2953 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); | 3354 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); |
| 2954 | 3355 | ||
| 3356 | /* The state of the finite automaton is separate per every input | ||
| 3357 | language environment (so it does not change when one switches | ||
| 3358 | to a different window with the same environment). Moreover, | ||
| 3359 | the experiments show that the state is not remembered when | ||
| 3360 | one switches back to the pre-previous environment. */ | ||
| 3361 | after_deadkey = -1; | ||
| 3362 | |||
| 3363 | /* XXXX??? What follows is a COMPLETE misunderstanding of Windows! */ | ||
| 3364 | |||
| 2955 | /* Clear dead keys in the keyboard state; for simplicity only | 3365 | /* Clear dead keys in the keyboard state; for simplicity only |
| 2956 | preserve modifier key states. */ | 3366 | preserve modifier key states. */ |
| 2957 | { | 3367 | { |
| 2958 | int i; | 3368 | int i; |
| 2959 | BYTE keystate[256]; | 3369 | BYTE keystate[256]; |
| @@ -3011,7 +3421,6 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3011 | /* Synchronize modifiers with current keystroke. */ | 3421 | /* Synchronize modifiers with current keystroke. */ |
| 3012 | sync_modifiers (); | 3422 | sync_modifiers (); |
| 3013 | record_keydown (wParam, lParam); | 3423 | record_keydown (wParam, lParam); |
| 3014 | wParam = map_keypad_keys (wParam, (lParam & 0x1000000L) != 0); | ||
| 3015 | 3424 | ||
| 3016 | windows_translate = 0; | 3425 | windows_translate = 0; |
| 3017 | 3426 | ||
| @@ -3052,14 +3461,14 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3052 | if (!NILP (Vw32_rwindow_modifier)) | 3461 | if (!NILP (Vw32_rwindow_modifier)) |
| 3053 | return 0; | 3462 | return 0; |
| 3054 | break; | 3463 | break; |
| 3055 | case VK_APPS: | 3464 | case VK_APPS: |
| 3056 | if (!NILP (Vw32_apps_modifier)) | 3465 | if (!NILP (Vw32_apps_modifier)) |
| 3057 | return 0; | 3466 | return 0; |
| 3058 | break; | 3467 | break; |
| 3059 | case VK_MENU: | 3468 | case VK_MENU: |
| 3060 | if (NILP (Vw32_pass_alt_to_system)) | 3469 | if (NILP (Vw32_pass_alt_to_system)) |
| 3061 | /* Prevent DefWindowProc from activating the menu bar if an | 3470 | /* Prevent DefWindowProc from activating the menu bar if an |
| 3062 | Alt key is pressed and released by itself. */ | 3471 | Alt key is pressed and released by itself. */ |
| 3063 | return 0; | 3472 | return 0; |
| 3064 | windows_translate = 1; | 3473 | windows_translate = 1; |
| 3065 | break; | 3474 | break; |
| @@ -3083,9 +3492,9 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3083 | break; | 3492 | break; |
| 3084 | disable_lock_key: | 3493 | disable_lock_key: |
| 3085 | /* Ensure the appropriate lock key state (and indicator light) | 3494 | /* Ensure the appropriate lock key state (and indicator light) |
| 3086 | remains in the same state. We do this by faking another | 3495 | remains in the same state. We do this by faking another |
| 3087 | press of the relevant key. Apparently, this really is the | 3496 | press of the relevant key. Apparently, this really is the |
| 3088 | only way to toggle the state of the indicator lights. */ | 3497 | only way to toggle the state of the indicator lights. */ |
| 3089 | dpyinfo->faked_key = wParam; | 3498 | dpyinfo->faked_key = wParam; |
| 3090 | keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), | 3499 | keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), |
| 3091 | KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); | 3500 | KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); |
| @@ -3094,8 +3503,8 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3094 | keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), | 3503 | keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), |
| 3095 | KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); | 3504 | KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); |
| 3096 | /* Ensure indicator lights are updated promptly on Windows 9x | 3505 | /* Ensure indicator lights are updated promptly on Windows 9x |
| 3097 | (TranslateMessage apparently does this), after forwarding | 3506 | (TranslateMessage apparently does this), after forwarding |
| 3098 | input event. */ | 3507 | input event. */ |
| 3099 | post_character_message (hwnd, msg, wParam, lParam, | 3508 | post_character_message (hwnd, msg, wParam, lParam, |
| 3100 | w32_get_key_modifiers (wParam, lParam)); | 3509 | w32_get_key_modifiers (wParam, lParam)); |
| 3101 | windows_translate = 1; | 3510 | windows_translate = 1; |
| @@ -3107,21 +3516,67 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3107 | break; | 3516 | break; |
| 3108 | case VK_CANCEL: | 3517 | case VK_CANCEL: |
| 3109 | /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL, | 3518 | /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL, |
| 3110 | which is confusing for purposes of key binding; convert | 3519 | which is confusing for purposes of key binding; convert |
| 3111 | VK_CANCEL events into VK_PAUSE events. */ | 3520 | VK_CANCEL events into VK_PAUSE events. */ |
| 3112 | wParam = VK_PAUSE; | 3521 | wParam = VK_PAUSE; |
| 3113 | break; | 3522 | break; |
| 3114 | case VK_PAUSE: | 3523 | case VK_PAUSE: |
| 3115 | /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing | 3524 | /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing |
| 3116 | for purposes of key binding; convert these back into | 3525 | for purposes of key binding; convert these back into |
| 3117 | VK_NUMLOCK events, at least when we want to see NumLock key | 3526 | VK_NUMLOCK events, at least when we want to see NumLock key |
| 3118 | presses. (Note that there is never any possibility that | 3527 | presses. (Note that there is never any possibility that |
| 3119 | VK_PAUSE with Ctrl really is C-Pause as per above.) */ | 3528 | VK_PAUSE with Ctrl really is C-Pause as per above.) */ |
| 3120 | if (NILP (Vw32_enable_num_lock) && modifier_set (VK_CONTROL)) | 3529 | if (NILP (Vw32_enable_num_lock) && modifier_set (VK_CONTROL)) |
| 3121 | wParam = VK_NUMLOCK; | 3530 | wParam = VK_NUMLOCK; |
| 3122 | break; | 3531 | break; |
| 3123 | default: | 3532 | default: |
| 3124 | /* If not defined as a function key, change it to a WM_CHAR message. */ | 3533 | if (w32_unicode_gui) |
| 3534 | { | ||
| 3535 | /* If this event generates characters or deadkeys, do | ||
| 3536 | not interpret it as a "raw combination of modifiers | ||
| 3537 | and keysym". Hide deadkeys, and use the generated | ||
| 3538 | character(s) instead of the keysym. (Backward | ||
| 3539 | compatibility: exceptions for numpad keys generating | ||
| 3540 | 0-9 . , / * - +, and for extra-Alt combined with a | ||
| 3541 | non-Latin char.) | ||
| 3542 | |||
| 3543 | Try to not report modifiers which have effect on | ||
| 3544 | which character or deadkey is generated. | ||
| 3545 | |||
| 3546 | Example (contrived): if rightAlt-? generates f (on a | ||
| 3547 | Cyrillic keyboard layout), and Ctrl, leftAlt do not | ||
| 3548 | affect the generated character, one wants to report | ||
| 3549 | Ctrl-leftAlt-f if the user presses | ||
| 3550 | Ctrl-leftAlt-rightAlt-?. */ | ||
| 3551 | int res; | ||
| 3552 | #if 0 | ||
| 3553 | /* Some of WM_CHAR may be fed to us directly, some are | ||
| 3554 | results of TranslateMessage(). Using 0 as the first | ||
| 3555 | argument (in a separate call) might help us | ||
| 3556 | distinguish these two cases. | ||
| 3557 | |||
| 3558 | However, the keypress feeders would most probably | ||
| 3559 | expect the "standard" message pump, when | ||
| 3560 | TranslateMessage() is called on EVERY KeyDown/Keyup | ||
| 3561 | event. So they may feed us Down-Ctrl Down-FAKE | ||
| 3562 | Char-o and expect us to recognize it as Ctrl-o. | ||
| 3563 | Using 0 as the first argument would interfere with | ||
| 3564 | this. */ | ||
| 3565 | deliver_wm_chars (0, hwnd, msg, wParam, lParam, 1); | ||
| 3566 | #endif | ||
| 3567 | /* Processing the generated WM_CHAR messages *WHILE* we | ||
| 3568 | handle KEYDOWN/UP event is the best choice, since | ||
| 3569 | withoug any fuss, we know all 3 of: scancode, virtual | ||
| 3570 | keycode, and expansion. (Additionally, one knows | ||
| 3571 | boundaries of expansion of different keypresses.) */ | ||
| 3572 | res = deliver_wm_chars (1, hwnd, msg, wParam, lParam, 1); | ||
| 3573 | windows_translate = -( res != 0 ); | ||
| 3574 | if (res > 0) /* Bound to character(s) or a deadkey */ | ||
| 3575 | break; | ||
| 3576 | /* deliver_wm_chars may make some branches after this vestigal. */ | ||
| 3577 | } | ||
| 3578 | wParam = map_keypad_keys (wParam, (lParam & 0x1000000L) != 0); | ||
| 3579 | /* If not defined as a function key, change it to a WM_CHAR message. */ | ||
| 3125 | if (wParam > 255 || !lispy_function_keys[wParam]) | 3580 | if (wParam > 255 || !lispy_function_keys[wParam]) |
| 3126 | { | 3581 | { |
| 3127 | DWORD modifiers = construct_console_modifiers (); | 3582 | DWORD modifiers = construct_console_modifiers (); |
| @@ -3173,7 +3628,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3173 | /* Forward asciified character sequence. */ | 3628 | /* Forward asciified character sequence. */ |
| 3174 | post_character_message | 3629 | post_character_message |
| 3175 | (hwnd, WM_CHAR, | 3630 | (hwnd, WM_CHAR, |
| 3176 | (unsigned char) key.uChar.AsciiChar, lParam, | 3631 | (unsigned char) key.uChar.AsciiChar, lParam, |
| 3177 | w32_get_key_modifiers (wParam, lParam)); | 3632 | w32_get_key_modifiers (wParam, lParam)); |
| 3178 | w32_kbd_patch_key (&key, w32_keyboard_codepage); | 3633 | w32_kbd_patch_key (&key, w32_keyboard_codepage); |
| 3179 | } | 3634 | } |
| @@ -3188,6 +3643,8 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3188 | } | 3643 | } |
| 3189 | } | 3644 | } |
| 3190 | 3645 | ||
| 3646 | if (windows_translate == -1) | ||
| 3647 | break; | ||
| 3191 | translate: | 3648 | translate: |
| 3192 | if (windows_translate) | 3649 | if (windows_translate) |
| 3193 | { | 3650 | { |
| @@ -3202,73 +3659,73 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3202 | case WM_SYSCHAR: | 3659 | case WM_SYSCHAR: |
| 3203 | case WM_CHAR: | 3660 | case WM_CHAR: |
| 3204 | if (wParam > 255 ) | 3661 | if (wParam > 255 ) |
| 3205 | { | 3662 | { |
| 3206 | W32Msg wmsg; | 3663 | W32Msg wmsg; |
| 3207 | 3664 | ||
| 3208 | wmsg.dwModifiers = w32_get_key_modifiers (wParam, lParam); | 3665 | wmsg.dwModifiers = w32_get_key_modifiers (wParam, lParam); |
| 3209 | signal_user_input (); | 3666 | signal_user_input (); |
| 3210 | my_post_msg (&wmsg, hwnd, WM_UNICHAR, wParam, lParam); | 3667 | my_post_msg (&wmsg, hwnd, WM_UNICHAR, wParam, lParam); |
| 3211 | 3668 | ||
| 3212 | } | 3669 | } |
| 3213 | else | 3670 | else |
| 3214 | post_character_message (hwnd, msg, wParam, lParam, | 3671 | post_character_message (hwnd, msg, wParam, lParam, |
| 3215 | w32_get_key_modifiers (wParam, lParam)); | 3672 | w32_get_key_modifiers (wParam, lParam)); |
| 3216 | break; | 3673 | break; |
| 3217 | 3674 | ||
| 3218 | case WM_UNICHAR: | 3675 | case WM_UNICHAR: |
| 3219 | /* WM_UNICHAR looks promising from the docs, but the exact | 3676 | /* WM_UNICHAR looks promising from the docs, but the exact |
| 3220 | circumstances in which TranslateMessage sends it is one of those | 3677 | circumstances in which TranslateMessage sends it is one of those |
| 3221 | Microsoft secret API things that EU and US courts are supposed | 3678 | Microsoft secret API things that EU and US courts are supposed |
| 3222 | to have put a stop to already. Spy++ shows it being sent to Notepad | 3679 | to have put a stop to already. Spy++ shows it being sent to Notepad |
| 3223 | and other MS apps, but never to Emacs. | 3680 | and other MS apps, but never to Emacs. |
| 3224 | 3681 | ||
| 3225 | Some third party IMEs send it in accordance with the official | 3682 | Some third party IMEs send it in accordance with the official |
| 3226 | documentation though, so handle it here. | 3683 | documentation though, so handle it here. |
| 3227 | 3684 | ||
| 3228 | UNICODE_NOCHAR is used to test for support for this message. | 3685 | UNICODE_NOCHAR is used to test for support for this message. |
| 3229 | TRUE indicates that the message is supported. */ | 3686 | TRUE indicates that the message is supported. */ |
| 3230 | if (wParam == UNICODE_NOCHAR) | 3687 | if (wParam == UNICODE_NOCHAR) |
| 3231 | return TRUE; | 3688 | return TRUE; |
| 3232 | 3689 | ||
| 3233 | { | 3690 | { |
| 3234 | W32Msg wmsg; | 3691 | W32Msg wmsg; |
| 3235 | wmsg.dwModifiers = w32_get_key_modifiers (wParam, lParam); | 3692 | wmsg.dwModifiers = w32_get_key_modifiers (wParam, lParam); |
| 3236 | signal_user_input (); | 3693 | signal_user_input (); |
| 3237 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); | 3694 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); |
| 3238 | } | 3695 | } |
| 3239 | break; | 3696 | break; |
| 3240 | 3697 | ||
| 3241 | case WM_IME_CHAR: | 3698 | case WM_IME_CHAR: |
| 3242 | /* If we can't get the IME result as Unicode, use default processing, | 3699 | /* If we can't get the IME result as Unicode, use default processing, |
| 3243 | which will at least allow characters decodable in the system locale | 3700 | which will at least allow characters decodable in the system locale |
| 3244 | get through. */ | 3701 | get through. */ |
| 3245 | if (!get_composition_string_fn) | 3702 | if (!get_composition_string_fn) |
| 3246 | goto dflt; | 3703 | goto dflt; |
| 3247 | 3704 | ||
| 3248 | else if (!ignore_ime_char) | 3705 | else if (!ignore_ime_char) |
| 3249 | { | 3706 | { |
| 3250 | wchar_t * buffer; | 3707 | wchar_t * buffer; |
| 3251 | int size, i; | 3708 | int size, i; |
| 3252 | W32Msg wmsg; | 3709 | W32Msg wmsg; |
| 3253 | HIMC context = get_ime_context_fn (hwnd); | 3710 | HIMC context = get_ime_context_fn (hwnd); |
| 3254 | wmsg.dwModifiers = w32_get_key_modifiers (wParam, lParam); | 3711 | wmsg.dwModifiers = w32_get_key_modifiers (wParam, lParam); |
| 3255 | /* Get buffer size. */ | 3712 | /* Get buffer size. */ |
| 3256 | size = get_composition_string_fn (context, GCS_RESULTSTR, NULL, 0); | 3713 | size = get_composition_string_fn (context, GCS_RESULTSTR, NULL, 0); |
| 3257 | buffer = alloca (size); | 3714 | buffer = alloca (size); |
| 3258 | size = get_composition_string_fn (context, GCS_RESULTSTR, | 3715 | size = get_composition_string_fn (context, GCS_RESULTSTR, |
| 3259 | buffer, size); | 3716 | buffer, size); |
| 3260 | release_ime_context_fn (hwnd, context); | 3717 | release_ime_context_fn (hwnd, context); |
| 3261 | 3718 | ||
| 3262 | signal_user_input (); | 3719 | signal_user_input (); |
| 3263 | for (i = 0; i < size / sizeof (wchar_t); i++) | 3720 | for (i = 0; i < size / sizeof (wchar_t); i++) |
| 3264 | { | 3721 | { |
| 3265 | my_post_msg (&wmsg, hwnd, WM_UNICHAR, (WPARAM) buffer[i], | 3722 | my_post_msg (&wmsg, hwnd, WM_UNICHAR, (WPARAM) buffer[i], |
| 3266 | lParam); | 3723 | lParam); |
| 3267 | } | 3724 | } |
| 3268 | /* Ignore the messages for the rest of the | 3725 | /* Ignore the messages for the rest of the |
| 3269 | characters in the string that was output above. */ | 3726 | characters in the string that was output above. */ |
| 3270 | ignore_ime_char = (size / sizeof (wchar_t)) - 1; | 3727 | ignore_ime_char = (size / sizeof (wchar_t)) - 1; |
| 3271 | } | 3728 | } |
| 3272 | else | 3729 | else |
| 3273 | ignore_ime_char--; | 3730 | ignore_ime_char--; |
| 3274 | 3731 | ||
| @@ -3490,7 +3947,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3490 | signal_user_input (); | 3947 | signal_user_input (); |
| 3491 | 3948 | ||
| 3492 | /* Need to return true for XBUTTON messages, false for others, | 3949 | /* Need to return true for XBUTTON messages, false for others, |
| 3493 | to indicate that we processed the message. */ | 3950 | to indicate that we processed the message. */ |
| 3494 | return (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONUP); | 3951 | return (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONUP); |
| 3495 | 3952 | ||
| 3496 | case WM_MOUSEMOVE: | 3953 | case WM_MOUSEMOVE: |
| @@ -3553,11 +4010,11 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3553 | case WM_VSCROLL: | 4010 | case WM_VSCROLL: |
| 3554 | if (w32_mouse_move_interval <= 0 | 4011 | if (w32_mouse_move_interval <= 0 |
| 3555 | || (msg == WM_MOUSEMOVE && button_state == 0)) | 4012 | || (msg == WM_MOUSEMOVE && button_state == 0)) |
| 3556 | { | 4013 | { |
| 3557 | wmsg.dwModifiers = w32_get_modifiers (); | 4014 | wmsg.dwModifiers = w32_get_modifiers (); |
| 3558 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); | 4015 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); |
| 3559 | return 0; | 4016 | return 0; |
| 3560 | } | 4017 | } |
| 3561 | 4018 | ||
| 3562 | /* Hang onto mouse move and scroll messages for a bit, to avoid | 4019 | /* Hang onto mouse move and scroll messages for a bit, to avoid |
| 3563 | sending such events to Emacs faster than it can process them. | 4020 | sending such events to Emacs faster than it can process them. |
| @@ -3588,15 +4045,15 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3588 | 4045 | ||
| 3589 | case WM_APPCOMMAND: | 4046 | case WM_APPCOMMAND: |
| 3590 | if (w32_pass_multimedia_buttons_to_system) | 4047 | if (w32_pass_multimedia_buttons_to_system) |
| 3591 | goto dflt; | 4048 | goto dflt; |
| 3592 | /* Otherwise, pass to lisp, the same way we do with mousehwheel. */ | 4049 | /* Otherwise, pass to lisp, the same way we do with mousehwheel. */ |
| 3593 | case WM_MOUSEHWHEEL: | 4050 | case WM_MOUSEHWHEEL: |
| 3594 | wmsg.dwModifiers = w32_get_modifiers (); | 4051 | wmsg.dwModifiers = w32_get_modifiers (); |
| 3595 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); | 4052 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); |
| 3596 | signal_user_input (); | 4053 | signal_user_input (); |
| 3597 | /* Non-zero must be returned when WM_MOUSEHWHEEL messages are | 4054 | /* Non-zero must be returned when WM_MOUSEHWHEEL messages are |
| 3598 | handled, to prevent the system trying to handle it by faking | 4055 | handled, to prevent the system trying to handle it by faking |
| 3599 | scroll bar events. */ | 4056 | scroll bar events. */ |
| 3600 | return 1; | 4057 | return 1; |
| 3601 | 4058 | ||
| 3602 | case WM_TIMER: | 4059 | case WM_TIMER: |
| @@ -3627,15 +4084,15 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3627 | KillTimer (hwnd, menu_free_timer); | 4084 | KillTimer (hwnd, menu_free_timer); |
| 3628 | menu_free_timer = 0; | 4085 | menu_free_timer = 0; |
| 3629 | f = x_window_to_frame (dpyinfo, hwnd); | 4086 | f = x_window_to_frame (dpyinfo, hwnd); |
| 3630 | /* If a popup menu is active, don't wipe its strings. */ | 4087 | /* If a popup menu is active, don't wipe its strings. */ |
| 3631 | if (menubar_in_use | 4088 | if (menubar_in_use |
| 3632 | && current_popup_menu == NULL) | 4089 | && current_popup_menu == NULL) |
| 3633 | { | 4090 | { |
| 3634 | /* Free memory used by owner-drawn and help-echo strings. */ | 4091 | /* Free memory used by owner-drawn and help-echo strings. */ |
| 3635 | w32_free_menu_strings (hwnd); | 4092 | w32_free_menu_strings (hwnd); |
| 3636 | if (f) | 4093 | if (f) |
| 3637 | f->output_data.w32->menubar_active = 0; | 4094 | f->output_data.w32->menubar_active = 0; |
| 3638 | menubar_in_use = 0; | 4095 | menubar_in_use = 0; |
| 3639 | } | 4096 | } |
| 3640 | } | 4097 | } |
| 3641 | return 0; | 4098 | return 0; |
| @@ -3687,7 +4144,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3687 | if (find_deferred_msg (hwnd, msg) != NULL) | 4144 | if (find_deferred_msg (hwnd, msg) != NULL) |
| 3688 | emacs_abort (); | 4145 | emacs_abort (); |
| 3689 | 4146 | ||
| 3690 | menubar_in_use = 1; | 4147 | menubar_in_use = 1; |
| 3691 | 4148 | ||
| 3692 | return send_deferred_msg (&msg_buf, hwnd, msg, wParam, lParam); | 4149 | return send_deferred_msg (&msg_buf, hwnd, msg, wParam, lParam); |
| 3693 | } | 4150 | } |
| @@ -3698,8 +4155,8 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3698 | /* If a menu is still active, check again after a short delay, | 4155 | /* If a menu is still active, check again after a short delay, |
| 3699 | since Windows often (always?) sends the WM_EXITMENULOOP | 4156 | since Windows often (always?) sends the WM_EXITMENULOOP |
| 3700 | before the corresponding WM_COMMAND message. | 4157 | before the corresponding WM_COMMAND message. |
| 3701 | Don't do this if a popup menu is active, since it is only | 4158 | Don't do this if a popup menu is active, since it is only |
| 3702 | menubar menus that require cleaning up in this way. | 4159 | menubar menus that require cleaning up in this way. |
| 3703 | */ | 4160 | */ |
| 3704 | if (f && menubar_in_use && current_popup_menu == NULL) | 4161 | if (f && menubar_in_use && current_popup_menu == NULL) |
| 3705 | menu_free_timer = SetTimer (hwnd, MENU_FREE_ID, MENU_FREE_DELAY, NULL); | 4162 | menu_free_timer = SetTimer (hwnd, MENU_FREE_ID, MENU_FREE_DELAY, NULL); |
| @@ -3744,9 +4201,9 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3744 | menu_font = CreateFontIndirect (&menu_logfont); | 4201 | menu_font = CreateFontIndirect (&menu_logfont); |
| 3745 | old_font = SelectObject (hdc, menu_font); | 4202 | old_font = SelectObject (hdc, menu_font); |
| 3746 | 4203 | ||
| 3747 | pMis->itemHeight = GetSystemMetrics (SM_CYMENUSIZE); | 4204 | pMis->itemHeight = GetSystemMetrics (SM_CYMENUSIZE); |
| 3748 | if (title) | 4205 | if (title) |
| 3749 | { | 4206 | { |
| 3750 | if (unicode_append_menu) | 4207 | if (unicode_append_menu) |
| 3751 | GetTextExtentPoint32W (hdc, (WCHAR *) title, | 4208 | GetTextExtentPoint32W (hdc, (WCHAR *) title, |
| 3752 | wcslen ((WCHAR *) title), | 4209 | wcslen ((WCHAR *) title), |
| @@ -3754,12 +4211,12 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3754 | else | 4211 | else |
| 3755 | GetTextExtentPoint32 (hdc, title, strlen (title), &size); | 4212 | GetTextExtentPoint32 (hdc, title, strlen (title), &size); |
| 3756 | 4213 | ||
| 3757 | pMis->itemWidth = size.cx; | 4214 | pMis->itemWidth = size.cx; |
| 3758 | if (pMis->itemHeight < size.cy) | 4215 | if (pMis->itemHeight < size.cy) |
| 3759 | pMis->itemHeight = size.cy; | 4216 | pMis->itemHeight = size.cy; |
| 3760 | } | 4217 | } |
| 3761 | else | 4218 | else |
| 3762 | pMis->itemWidth = 0; | 4219 | pMis->itemWidth = 0; |
| 3763 | 4220 | ||
| 3764 | SelectObject (hdc, old_font); | 4221 | SelectObject (hdc, old_font); |
| 3765 | DeleteObject (menu_font); | 4222 | DeleteObject (menu_font); |
| @@ -3779,17 +4236,17 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3779 | { | 4236 | { |
| 3780 | /* Draw popup menu title. */ | 4237 | /* Draw popup menu title. */ |
| 3781 | char * title = (char *) pDis->itemData; | 4238 | char * title = (char *) pDis->itemData; |
| 3782 | if (title) | 4239 | if (title) |
| 3783 | { | 4240 | { |
| 3784 | HDC hdc = pDis->hDC; | 4241 | HDC hdc = pDis->hDC; |
| 3785 | HFONT menu_font = GetCurrentObject (hdc, OBJ_FONT); | 4242 | HFONT menu_font = GetCurrentObject (hdc, OBJ_FONT); |
| 3786 | LOGFONT menu_logfont; | 4243 | LOGFONT menu_logfont; |
| 3787 | HFONT old_font; | 4244 | HFONT old_font; |
| 3788 | 4245 | ||
| 3789 | GetObject (menu_font, sizeof (menu_logfont), &menu_logfont); | 4246 | GetObject (menu_font, sizeof (menu_logfont), &menu_logfont); |
| 3790 | menu_logfont.lfWeight = FW_BOLD; | 4247 | menu_logfont.lfWeight = FW_BOLD; |
| 3791 | menu_font = CreateFontIndirect (&menu_logfont); | 4248 | menu_font = CreateFontIndirect (&menu_logfont); |
| 3792 | old_font = SelectObject (hdc, menu_font); | 4249 | old_font = SelectObject (hdc, menu_font); |
| 3793 | 4250 | ||
| 3794 | /* Always draw title as if not selected. */ | 4251 | /* Always draw title as if not selected. */ |
| 3795 | if (unicode_append_menu) | 4252 | if (unicode_append_menu) |
| @@ -3808,9 +4265,9 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3808 | ETO_OPAQUE, &pDis->rcItem, | 4265 | ETO_OPAQUE, &pDis->rcItem, |
| 3809 | title, strlen (title), NULL); | 4266 | title, strlen (title), NULL); |
| 3810 | 4267 | ||
| 3811 | SelectObject (hdc, old_font); | 4268 | SelectObject (hdc, old_font); |
| 3812 | DeleteObject (menu_font); | 4269 | DeleteObject (menu_font); |
| 3813 | } | 4270 | } |
| 3814 | return TRUE; | 4271 | return TRUE; |
| 3815 | } | 4272 | } |
| 3816 | } | 4273 | } |
| @@ -3891,16 +4348,16 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3891 | /* Don't restrict the sizing of any kind of frames. If the window | 4348 | /* Don't restrict the sizing of any kind of frames. If the window |
| 3892 | manager doesn't, there's no reason to do it ourselves. */ | 4349 | manager doesn't, there's no reason to do it ourselves. */ |
| 3893 | #if 0 | 4350 | #if 0 |
| 3894 | if (frame_resize_pixelwise || hwnd == tip_window) | 4351 | if (frame_resize_pixelwise || hwnd == tip_window) |
| 3895 | #endif | 4352 | #endif |
| 3896 | return 0; | 4353 | return 0; |
| 3897 | 4354 | ||
| 3898 | #if 0 | 4355 | #if 0 |
| 3899 | /* Don't restrict the sizing of fullscreened frames, allowing them to be | 4356 | /* Don't restrict the sizing of fullscreened frames, allowing them to be |
| 3900 | flush with the sides of the screen. */ | 4357 | flush with the sides of the screen. */ |
| 3901 | f = x_window_to_frame (dpyinfo, hwnd); | 4358 | f = x_window_to_frame (dpyinfo, hwnd); |
| 3902 | if (f && FRAME_PREV_FSMODE (f) != FULLSCREEN_NONE) | 4359 | if (f && FRAME_PREV_FSMODE (f) != FULLSCREEN_NONE) |
| 3903 | return 0; | 4360 | return 0; |
| 3904 | 4361 | ||
| 3905 | { | 4362 | { |
| 3906 | WINDOWPLACEMENT wp; | 4363 | WINDOWPLACEMENT wp; |
| @@ -4049,30 +4506,30 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 4049 | case WM_EMACS_BRINGTOTOP: | 4506 | case WM_EMACS_BRINGTOTOP: |
| 4050 | case WM_EMACS_SETFOREGROUND: | 4507 | case WM_EMACS_SETFOREGROUND: |
| 4051 | { | 4508 | { |
| 4052 | HWND foreground_window; | 4509 | HWND foreground_window; |
| 4053 | DWORD foreground_thread, retval; | 4510 | DWORD foreground_thread, retval; |
| 4054 | 4511 | ||
| 4055 | /* On NT 5.0, and apparently Windows 98, it is necessary to | 4512 | /* On NT 5.0, and apparently Windows 98, it is necessary to |
| 4056 | attach to the thread that currently has focus in order to | 4513 | attach to the thread that currently has focus in order to |
| 4057 | pull the focus away from it. */ | 4514 | pull the focus away from it. */ |
| 4058 | foreground_window = GetForegroundWindow (); | 4515 | foreground_window = GetForegroundWindow (); |
| 4059 | foreground_thread = GetWindowThreadProcessId (foreground_window, NULL); | 4516 | foreground_thread = GetWindowThreadProcessId (foreground_window, NULL); |
| 4060 | if (!foreground_window | 4517 | if (!foreground_window |
| 4061 | || foreground_thread == GetCurrentThreadId () | 4518 | || foreground_thread == GetCurrentThreadId () |
| 4062 | || !AttachThreadInput (GetCurrentThreadId (), | 4519 | || !AttachThreadInput (GetCurrentThreadId (), |
| 4063 | foreground_thread, TRUE)) | 4520 | foreground_thread, TRUE)) |
| 4064 | foreground_thread = 0; | 4521 | foreground_thread = 0; |
| 4065 | 4522 | ||
| 4066 | retval = SetForegroundWindow ((HWND) wParam); | 4523 | retval = SetForegroundWindow ((HWND) wParam); |
| 4067 | if (msg == WM_EMACS_BRINGTOTOP) | 4524 | if (msg == WM_EMACS_BRINGTOTOP) |
| 4068 | retval = BringWindowToTop ((HWND) wParam); | 4525 | retval = BringWindowToTop ((HWND) wParam); |
| 4069 | 4526 | ||
| 4070 | /* Detach from the previous foreground thread. */ | 4527 | /* Detach from the previous foreground thread. */ |
| 4071 | if (foreground_thread) | 4528 | if (foreground_thread) |
| 4072 | AttachThreadInput (GetCurrentThreadId (), | 4529 | AttachThreadInput (GetCurrentThreadId (), |
| 4073 | foreground_thread, FALSE); | 4530 | foreground_thread, FALSE); |
| 4074 | 4531 | ||
| 4075 | return retval; | 4532 | return retval; |
| 4076 | } | 4533 | } |
| 4077 | 4534 | ||
| 4078 | case WM_EMACS_SETWINDOWPOS: | 4535 | case WM_EMACS_SETWINDOWPOS: |
| @@ -4145,7 +4602,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 4145 | button_state = 0; | 4602 | button_state = 0; |
| 4146 | 4603 | ||
| 4147 | /* Use menubar_active to indicate that WM_INITMENU is from | 4604 | /* Use menubar_active to indicate that WM_INITMENU is from |
| 4148 | TrackPopupMenu below, and should be ignored. */ | 4605 | TrackPopupMenu below, and should be ignored. */ |
| 4149 | f = x_window_to_frame (dpyinfo, hwnd); | 4606 | f = x_window_to_frame (dpyinfo, hwnd); |
| 4150 | if (f) | 4607 | if (f) |
| 4151 | f->output_data.w32->menubar_active = 1; | 4608 | f->output_data.w32->menubar_active = 1; |
| @@ -4452,20 +4909,20 @@ x_default_font_parameter (struct frame *f, Lisp_Object parms) | |||
| 4452 | { | 4909 | { |
| 4453 | int i; | 4910 | int i; |
| 4454 | static char *names[] | 4911 | static char *names[] |
| 4455 | = { "Courier New-10", | 4912 | = { "Courier New-10", |
| 4456 | "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1", | 4913 | "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1", |
| 4457 | "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1", | 4914 | "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1", |
| 4458 | "Fixedsys", | 4915 | "Fixedsys", |
| 4459 | NULL }; | 4916 | NULL }; |
| 4460 | 4917 | ||
| 4461 | for (i = 0; names[i]; i++) | 4918 | for (i = 0; names[i]; i++) |
| 4462 | { | 4919 | { |
| 4463 | font = font_open_by_name (f, build_unibyte_string (names[i])); | 4920 | font = font_open_by_name (f, build_unibyte_string (names[i])); |
| 4464 | if (! NILP (font)) | 4921 | if (! NILP (font)) |
| 4465 | break; | 4922 | break; |
| 4466 | } | 4923 | } |
| 4467 | if (NILP (font)) | 4924 | if (NILP (font)) |
| 4468 | error ("No suitable font was found"); | 4925 | error ("No suitable font was found"); |
| 4469 | } | 4926 | } |
| 4470 | else if (!NILP (font_param)) | 4927 | else if (!NILP (font_param)) |
| 4471 | { | 4928 | { |
| @@ -4573,7 +5030,7 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 4573 | 5030 | ||
| 4574 | fset_icon_name | 5031 | fset_icon_name |
| 4575 | (f, x_get_arg (dpyinfo, parameters, Qicon_name, "iconName", "Title", | 5032 | (f, x_get_arg (dpyinfo, parameters, Qicon_name, "iconName", "Title", |
| 4576 | RES_TYPE_STRING)); | 5033 | RES_TYPE_STRING)); |
| 4577 | if (! STRINGP (f->icon_name)) | 5034 | if (! STRINGP (f->icon_name)) |
| 4578 | fset_icon_name (f, Qnil); | 5035 | fset_icon_name (f, Qnil); |
| 4579 | 5036 | ||
| @@ -4797,7 +5254,7 @@ This function is an internal primitive--use `make-frame' instead. */) | |||
| 4797 | frame on this terminal. */ | 5254 | frame on this terminal. */ |
| 4798 | if (FRAME_HAS_MINIBUF_P (f) | 5255 | if (FRAME_HAS_MINIBUF_P (f) |
| 4799 | && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame)) | 5256 | && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame)) |
| 4800 | || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))) | 5257 | || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))) |
| 4801 | kset_default_minibuffer_frame (kb, frame); | 5258 | kset_default_minibuffer_frame (kb, frame); |
| 4802 | 5259 | ||
| 4803 | /* All remaining specified parameters, which have not been "used" | 5260 | /* All remaining specified parameters, which have not been "used" |
| @@ -5522,7 +5979,7 @@ If TERMINAL is omitted or nil, that stands for the selected frame's display. */ | |||
| 5522 | 5979 | ||
| 5523 | 5980 | ||
| 5524 | /*********************************************************************** | 5981 | /*********************************************************************** |
| 5525 | Window properties | 5982 | Window properties |
| 5526 | ***********************************************************************/ | 5983 | ***********************************************************************/ |
| 5527 | 5984 | ||
| 5528 | #if 0 /* TODO : port window properties to W32 */ | 5985 | #if 0 /* TODO : port window properties to W32 */ |
| @@ -5658,9 +6115,9 @@ no value of TYPE (always string in the MS Windows case). */) | |||
| 5658 | ***********************************************************************/ | 6115 | ***********************************************************************/ |
| 5659 | 6116 | ||
| 5660 | static Lisp_Object x_create_tip_frame (struct w32_display_info *, | 6117 | static Lisp_Object x_create_tip_frame (struct w32_display_info *, |
| 5661 | Lisp_Object, Lisp_Object); | 6118 | Lisp_Object, Lisp_Object); |
| 5662 | static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object, | 6119 | static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object, |
| 5663 | Lisp_Object, int, int, int *, int *); | 6120 | Lisp_Object, int, int, int *, int *); |
| 5664 | 6121 | ||
| 5665 | /* The frame of a currently visible tooltip. */ | 6122 | /* The frame of a currently visible tooltip. */ |
| 5666 | 6123 | ||
| @@ -5868,7 +6325,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, | |||
| 5868 | "cursorType", "CursorType", RES_TYPE_SYMBOL); | 6325 | "cursorType", "CursorType", RES_TYPE_SYMBOL); |
| 5869 | /* Process alpha here (Bug#17344). */ | 6326 | /* Process alpha here (Bug#17344). */ |
| 5870 | x_default_parameter (f, parms, Qalpha, Qnil, | 6327 | x_default_parameter (f, parms, Qalpha, Qnil, |
| 5871 | "alpha", "Alpha", RES_TYPE_NUMBER); | 6328 | "alpha", "Alpha", RES_TYPE_NUMBER); |
| 5872 | 6329 | ||
| 5873 | /* Dimensions, especially FRAME_LINES (f), must be done via | 6330 | /* Dimensions, especially FRAME_LINES (f), must be done via |
| 5874 | change_frame_size. Change will not be effected unless different | 6331 | change_frame_size. Change will not be effected unless different |
| @@ -6766,25 +7223,25 @@ value of DIR as in previous invocations; this is standard Windows behavior. */) | |||
| 6766 | 7223 | ||
| 6767 | if (file_opened) | 7224 | if (file_opened) |
| 6768 | { | 7225 | { |
| 6769 | /* Get an Emacs string from the value Windows gave us. */ | 7226 | /* Get an Emacs string from the value Windows gave us. */ |
| 6770 | #ifdef NTGUI_UNICODE | 7227 | #ifdef NTGUI_UNICODE |
| 6771 | filename = from_unicode_buffer (filename_buf_w); | 7228 | filename = from_unicode_buffer (filename_buf_w); |
| 6772 | #else /* !NTGUI_UNICODE */ | 7229 | #else /* !NTGUI_UNICODE */ |
| 6773 | if (use_unicode) | 7230 | if (use_unicode) |
| 6774 | filename_from_utf16 (filename_buf_w, fname_ret); | 7231 | filename_from_utf16 (filename_buf_w, fname_ret); |
| 6775 | else | 7232 | else |
| 6776 | filename_from_ansi (filename_buf_a, fname_ret); | 7233 | filename_from_ansi (filename_buf_a, fname_ret); |
| 6777 | dostounix_filename (fname_ret); | 7234 | dostounix_filename (fname_ret); |
| 6778 | filename = DECODE_FILE (build_unibyte_string (fname_ret)); | 7235 | filename = DECODE_FILE (build_unibyte_string (fname_ret)); |
| 6779 | #endif /* NTGUI_UNICODE */ | 7236 | #endif /* NTGUI_UNICODE */ |
| 6780 | 7237 | ||
| 6781 | #ifdef CYGWIN | 7238 | #ifdef CYGWIN |
| 6782 | filename = Fcygwin_convert_file_name_from_windows (filename, Qt); | 7239 | filename = Fcygwin_convert_file_name_from_windows (filename, Qt); |
| 6783 | #endif /* CYGWIN */ | 7240 | #endif /* CYGWIN */ |
| 6784 | 7241 | ||
| 6785 | /* Strip the dummy filename off the end of the string if we | 7242 | /* Strip the dummy filename off the end of the string if we |
| 6786 | added it to select a directory. */ | 7243 | added it to select a directory. */ |
| 6787 | if ((use_unicode && file_details_w->nFilterIndex == 2) | 7244 | if ((use_unicode && file_details_w->nFilterIndex == 2) |
| 6788 | #ifndef NTGUI_UNICODE | 7245 | #ifndef NTGUI_UNICODE |
| 6789 | || (!use_unicode && file_details_a->nFilterIndex == 2) | 7246 | || (!use_unicode && file_details_a->nFilterIndex == 2) |
| 6790 | #endif | 7247 | #endif |
| @@ -6797,14 +7254,14 @@ value of DIR as in previous invocations; this is standard Windows behavior. */) | |||
| 6797 | /* An error occurred, fallback on reading from the mini-buffer. */ | 7254 | /* An error occurred, fallback on reading from the mini-buffer. */ |
| 6798 | else | 7255 | else |
| 6799 | filename = Fcompleting_read ( | 7256 | filename = Fcompleting_read ( |
| 6800 | orig_prompt, | 7257 | orig_prompt, |
| 6801 | intern ("read-file-name-internal"), | 7258 | intern ("read-file-name-internal"), |
| 6802 | orig_dir, | 7259 | orig_dir, |
| 6803 | mustmatch, | 7260 | mustmatch, |
| 6804 | orig_dir, | 7261 | orig_dir, |
| 6805 | Qfile_name_history, | 7262 | Qfile_name_history, |
| 6806 | default_filename, | 7263 | default_filename, |
| 6807 | Qnil); | 7264 | Qnil); |
| 6808 | 7265 | ||
| 6809 | UNGCPRO; | 7266 | UNGCPRO; |
| 6810 | } | 7267 | } |
| @@ -6917,7 +7374,7 @@ DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash, | |||
| 6917 | 7374 | ||
| 6918 | 7375 | ||
| 6919 | /*********************************************************************** | 7376 | /*********************************************************************** |
| 6920 | w32 specialized functions | 7377 | w32 specialized functions |
| 6921 | ***********************************************************************/ | 7378 | ***********************************************************************/ |
| 6922 | 7379 | ||
| 6923 | DEFUN ("w32-send-sys-command", Fw32_send_sys_command, | 7380 | DEFUN ("w32-send-sys-command", Fw32_send_sys_command, |
| @@ -6952,37 +7409,37 @@ handler application, but typically it is one of the following common | |||
| 6952 | operations: | 7409 | operations: |
| 6953 | 7410 | ||
| 6954 | \"open\" - open DOCUMENT, which could be a file, a directory, or an | 7411 | \"open\" - open DOCUMENT, which could be a file, a directory, or an |
| 6955 | executable program (application). If it is an application, | 7412 | executable program (application). If it is an application, |
| 6956 | that application is launched in the current buffer's default | 7413 | that application is launched in the current buffer's default |
| 6957 | directory. Otherwise, the application associated with | 7414 | directory. Otherwise, the application associated with |
| 6958 | DOCUMENT is launched in the buffer's default directory. | 7415 | DOCUMENT is launched in the buffer's default directory. |
| 6959 | \"opennew\" - like \"open\", but instruct the application to open | 7416 | \"opennew\" - like \"open\", but instruct the application to open |
| 6960 | DOCUMENT in a new window. | 7417 | DOCUMENT in a new window. |
| 6961 | \"openas\" - open the \"Open With\" dialog for DOCUMENT. | 7418 | \"openas\" - open the \"Open With\" dialog for DOCUMENT. |
| 6962 | \"print\" - print DOCUMENT, which must be a file. | 7419 | \"print\" - print DOCUMENT, which must be a file. |
| 6963 | \"printto\" - print DOCUMENT, which must be a file, to a specified printer. | 7420 | \"printto\" - print DOCUMENT, which must be a file, to a specified printer. |
| 6964 | The printer should be provided in PARAMETERS, see below. | 7421 | The printer should be provided in PARAMETERS, see below. |
| 6965 | \"explore\" - start the Windows Explorer on DOCUMENT. | 7422 | \"explore\" - start the Windows Explorer on DOCUMENT. |
| 6966 | \"edit\" - launch an editor and open DOCUMENT for editing; which | 7423 | \"edit\" - launch an editor and open DOCUMENT for editing; which |
| 6967 | editor is launched depends on the association for the | 7424 | editor is launched depends on the association for the |
| 6968 | specified DOCUMENT. | 7425 | specified DOCUMENT. |
| 6969 | \"find\" - initiate search starting from DOCUMENT, which must specify | 7426 | \"find\" - initiate search starting from DOCUMENT, which must specify |
| 6970 | a directory. | 7427 | a directory. |
| 6971 | \"delete\" - move DOCUMENT, a file or a directory, to Recycle Bin. | 7428 | \"delete\" - move DOCUMENT, a file or a directory, to Recycle Bin. |
| 6972 | \"copy\" - copy DOCUMENT, which must be a file or a directory, into | 7429 | \"copy\" - copy DOCUMENT, which must be a file or a directory, into |
| 6973 | the clipboard. | 7430 | the clipboard. |
| 6974 | \"cut\" - move DOCUMENT, a file or a directory, into the clipboard. | 7431 | \"cut\" - move DOCUMENT, a file or a directory, into the clipboard. |
| 6975 | \"paste\" - paste the file whose name is in the clipboard into DOCUMENT, | 7432 | \"paste\" - paste the file whose name is in the clipboard into DOCUMENT, |
| 6976 | which must be a directory. | 7433 | which must be a directory. |
| 6977 | \"pastelink\" | 7434 | \"pastelink\" |
| 6978 | - create a shortcut in DOCUMENT (which must be a directory) | 7435 | - create a shortcut in DOCUMENT (which must be a directory) |
| 6979 | the file or directory whose name is in the clipboard. | 7436 | the file or directory whose name is in the clipboard. |
| 6980 | \"runas\" - run DOCUMENT, which must be an excutable file, with | 7437 | \"runas\" - run DOCUMENT, which must be an excutable file, with |
| 6981 | elevated privileges (a.k.a. \"as Administrator\"). | 7438 | elevated privileges (a.k.a. \"as Administrator\"). |
| 6982 | \"properties\" | 7439 | \"properties\" |
| 6983 | - open the property sheet dialog for DOCUMENT. | 7440 | - open the property sheet dialog for DOCUMENT. |
| 6984 | nil - invoke the default OPERATION, or \"open\" if default is | 7441 | nil - invoke the default OPERATION, or \"open\" if default is |
| 6985 | not defined or unavailable. | 7442 | not defined or unavailable. |
| 6986 | 7443 | ||
| 6987 | DOCUMENT is typically the name of a document file or a URL, but can | 7444 | DOCUMENT is typically the name of a document file or a URL, but can |
| 6988 | also be an executable program to run, or a directory to open in the | 7445 | also be an executable program to run, or a directory to open in the |
| @@ -7678,7 +8135,7 @@ elements (all size values are in pixels). | |||
| 7678 | ? Fcons (make_number (0), make_number (0)) | 8135 | ? Fcons (make_number (0), make_number (0)) |
| 7679 | : Fcons (make_number (border_width), | 8136 | : Fcons (make_number (border_width), |
| 7680 | make_number (border_height)))), | 8137 | make_number (border_height)))), |
| 7681 | Fcons (Qtitle_height, | 8138 | Fcons (Qtitle_height, |
| 7682 | ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen)) | 8139 | ((EQ (fullscreen, Qfullboth) || EQ (fullscreen, Qfullscreen)) |
| 7683 | ? make_number (0) | 8140 | ? make_number (0) |
| 7684 | : make_number (title_height))), | 8141 | : make_number (title_height))), |
| @@ -8063,14 +8520,14 @@ w32_strerror (int error_no) | |||
| 8063 | error_no = GetLastError (); | 8520 | error_no = GetLastError (); |
| 8064 | 8521 | ||
| 8065 | ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | | 8522 | ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | |
| 8066 | FORMAT_MESSAGE_IGNORE_INSERTS, | 8523 | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 8067 | NULL, | 8524 | NULL, |
| 8068 | error_no, | 8525 | error_no, |
| 8069 | 0, /* choose most suitable language */ | 8526 | 0, /* choose most suitable language */ |
| 8070 | buf, sizeof (buf), NULL); | 8527 | buf, sizeof (buf), NULL); |
| 8071 | 8528 | ||
| 8072 | while (ret > 0 && (buf[ret - 1] == '\n' || | 8529 | while (ret > 0 && (buf[ret - 1] == '\n' || |
| 8073 | buf[ret - 1] == '\r' )) | 8530 | buf[ret - 1] == '\r' )) |
| 8074 | --ret; | 8531 | --ret; |
| 8075 | buf[ret] = '\0'; | 8532 | buf[ret] = '\0'; |
| 8076 | if (!ret) | 8533 | if (!ret) |
| @@ -8316,7 +8773,7 @@ w32_kbd_patch_key (KEY_EVENT_RECORD *event, int cpId) | |||
| 8316 | else | 8773 | else |
| 8317 | { | 8774 | { |
| 8318 | isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode, | 8775 | isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode, |
| 8319 | keystate, (LPWORD) ansi_code, 0); | 8776 | keystate, (LPWORD) ansi_code, 0); |
| 8320 | } | 8777 | } |
| 8321 | 8778 | ||
| 8322 | if (isdead == 0) | 8779 | if (isdead == 0) |
| @@ -8580,8 +9037,8 @@ system to handle them. */); | |||
| 8580 | w32_pass_extra_mouse_buttons_to_system = 0; | 9037 | w32_pass_extra_mouse_buttons_to_system = 0; |
| 8581 | 9038 | ||
| 8582 | DEFVAR_BOOL ("w32-pass-multimedia-buttons-to-system", | 9039 | DEFVAR_BOOL ("w32-pass-multimedia-buttons-to-system", |
| 8583 | w32_pass_multimedia_buttons_to_system, | 9040 | w32_pass_multimedia_buttons_to_system, |
| 8584 | doc: /* If non-nil, media buttons are passed to Windows. | 9041 | doc: /* If non-nil, media buttons are passed to Windows. |
| 8585 | Some modern keyboards contain buttons for controlling media players, web | 9042 | Some modern keyboards contain buttons for controlling media players, web |
| 8586 | browsers and other applications. Generally these buttons are handled on a | 9043 | browsers and other applications. Generally these buttons are handled on a |
| 8587 | system wide basis, but by setting this to nil they are made available | 9044 | system wide basis, but by setting this to nil they are made available |
| @@ -8669,12 +9126,12 @@ Chinese, Japanese, and Korean. */); | |||
| 8669 | Vx_pixel_size_width_font_regexp = Qnil; | 9126 | Vx_pixel_size_width_font_regexp = Qnil; |
| 8670 | 9127 | ||
| 8671 | DEFVAR_LISP ("w32-bdf-filename-alist", | 9128 | DEFVAR_LISP ("w32-bdf-filename-alist", |
| 8672 | Vw32_bdf_filename_alist, | 9129 | Vw32_bdf_filename_alist, |
| 8673 | doc: /* List of bdf fonts and their corresponding filenames. */); | 9130 | doc: /* List of bdf fonts and their corresponding filenames. */); |
| 8674 | Vw32_bdf_filename_alist = Qnil; | 9131 | Vw32_bdf_filename_alist = Qnil; |
| 8675 | 9132 | ||
| 8676 | DEFVAR_BOOL ("w32-strict-fontnames", | 9133 | DEFVAR_BOOL ("w32-strict-fontnames", |
| 8677 | w32_strict_fontnames, | 9134 | w32_strict_fontnames, |
| 8678 | doc: /* Non-nil means only use fonts that are exact matches for those requested. | 9135 | doc: /* Non-nil means only use fonts that are exact matches for those requested. |
| 8679 | Default is nil, which allows old fontnames that are not XLFD compliant, | 9136 | Default is nil, which allows old fontnames that are not XLFD compliant, |
| 8680 | and allows third-party CJK display to work by specifying false charset | 9137 | and allows third-party CJK display to work by specifying false charset |
| @@ -8684,7 +9141,7 @@ fontsets are automatically created. */); | |||
| 8684 | w32_strict_fontnames = 0; | 9141 | w32_strict_fontnames = 0; |
| 8685 | 9142 | ||
| 8686 | DEFVAR_BOOL ("w32-strict-painting", | 9143 | DEFVAR_BOOL ("w32-strict-painting", |
| 8687 | w32_strict_painting, | 9144 | w32_strict_painting, |
| 8688 | doc: /* Non-nil means use strict rules for repainting frames. | 9145 | doc: /* Non-nil means use strict rules for repainting frames. |
| 8689 | Set this to nil to get the old behavior for repainting; this should | 9146 | Set this to nil to get the old behavior for repainting; this should |
| 8690 | only be necessary if the default setting causes problems. */); | 9147 | only be necessary if the default setting causes problems. */); |