To: vim_dev@googlegroups.com Subject: Patch 7.4.1124 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.1124 Problem: MS-Windows: dead key behavior is not ideal. Solution: Handle dead keys differently when not in Insert or Select mode. (John Wellesz, closes #399) Files: src/gui_w48.c *** ../vim-7.4.1123/src/gui_w48.c 2015-09-25 15:00:16.146212248 +0200 --- src/gui_w48.c 2016-01-17 20:52:26.162477422 +0100 *************** *** 301,318 **** }; /* Local variables */ ! static int s_button_pending = -1; /* s_getting_focus is set when we got focus but didn't see mouse-up event yet, * so don't reset s_button_pending. */ ! static int s_getting_focus = FALSE; ! static int s_x_pending; ! static int s_y_pending; ! static UINT s_kFlags_pending; ! static UINT s_wait_timer = 0; /* Timer for get char from user */ ! static int s_timed_out = FALSE; ! static int dead_key = 0; /* 0 - no dead key, 1 - dead key pressed */ #ifdef WIN3264 static OSVERSIONINFO os_version; /* like it says. Init in gui_mch_init() */ --- 301,318 ---- }; /* Local variables */ ! static int s_button_pending = -1; /* s_getting_focus is set when we got focus but didn't see mouse-up event yet, * so don't reset s_button_pending. */ ! static int s_getting_focus = FALSE; ! static int s_x_pending; ! static int s_y_pending; ! static UINT s_kFlags_pending; ! static UINT s_wait_timer = 0; /* Timer for get char from user */ ! static int s_timed_out = FALSE; ! static int dead_key = 0; /* 0: no dead key, 1: dead key pressed */ #ifdef WIN3264 static OSVERSIONINFO os_version; /* like it says. Init in gui_mch_init() */ *************** *** 641,646 **** --- 641,648 ---- int modifiers; int ch = cch; /* special keys are negative */ + dead_key = 0; + /* TRACE("OnSysChar(%d, %c)\n", ch, ch); */ /* OK, we have a character key (given by ch) which was entered with the *************** *** 1710,1715 **** --- 1712,1745 ---- DeleteBrush(hbr); } + + /* + * Generates a VK_SPACE when the internal dead_key flag is set to output the + * dead key's nominal character and re-post the original message. + */ + static void + outputDeadKey_rePost(MSG originalMsg) + { + static MSG deadCharExpel; + + if (!dead_key) + return; + + dead_key = 0; + + /* Make Windows generate the dead key's character */ + deadCharExpel.message = originalMsg.message; + deadCharExpel.hwnd = originalMsg.hwnd; + deadCharExpel.wParam = VK_SPACE; + + MyTranslateMessage(&deadCharExpel); + + /* re-generate the current character free of the dead char influence */ + PostMessage(originalMsg.hwnd, originalMsg.message, originalMsg.wParam, + originalMsg.lParam); + } + + /* * Process a single Windows message. * If one is not available we hang until one is. *************** *** 1790,1810 **** if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN) { vk = (int) msg.wParam; /* ! * If a dead key was pressed and the user presses VK_SPACE, VK_BACK, or ! * VK_ESCAPE it means that he actually wants to deal with the dead char ! * now, so do nothing special and let Windows handle it. * ! * Note that VK_SPACE combines with the dead_key's character and only ! * one WM_CHAR will be generated by TranslateMessage(), in the two ! * other cases two WM_CHAR will be generated: the dead char and VK_BACK ! * or VK_ESCAPE. That is most likely what the user expects. */ ! if (dead_key && (vk == VK_SPACE || vk == VK_BACK || vk == VK_ESCAPE)) { ! dead_key = 0; ! MyTranslateMessage(&msg); ! return; } /* Check for CTRL-BREAK */ --- 1820,1867 ---- if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN) { vk = (int) msg.wParam; + /* ! * Handle dead keys in special conditions in other cases we let Windows ! * handle them and do not interfere. * ! * The dead_key flag must be reset on several occasions: ! * - in _OnChar() (or _OnSysChar()) as any dead key was necessarily ! * consumed at that point (This is when we let Windows combine the ! * dead character on its own) ! * ! * - Before doing something special such as regenerating keypresses to ! * expel the dead character as this could trigger an infinite loop if ! * for some reason MyTranslateMessage() do not trigger a call ! * immediately to _OnChar() (or _OnSysChar()). */ ! if (dead_key) { ! /* ! * If a dead key was pressed and the user presses VK_SPACE, ! * VK_BACK, or VK_ESCAPE it means that he actually wants to deal ! * with the dead char now, so do nothing special and let Windows ! * handle it. ! * ! * Note that VK_SPACE combines with the dead_key's character and ! * only one WM_CHAR will be generated by TranslateMessage(), in ! * the two other cases two WM_CHAR will be generated: the dead ! * char and VK_BACK or VK_ESCAPE. That is most likely what the ! * user expects. ! */ ! if ((vk == VK_SPACE || vk == VK_BACK || vk == VK_ESCAPE)) ! { ! dead_key = 0; ! MyTranslateMessage(&msg); ! return; ! } ! /* In modes where we are not typing, dead keys should behave ! * normally */ ! else if (!(get_real_state() & (INSERT | CMDLINE | SELECTMODE))) ! { ! outputDeadKey_rePost(msg); ! return; ! } } /* Check for CTRL-BREAK */ *************** *** 1822,1827 **** --- 1879,1897 ---- if (special_keys[i].key_sym == vk && (vk != VK_SPACE || !(GetKeyState(VK_MENU) & 0x8000))) { + /* + * Behave as exected if we have a dead key and the special key + * is a key that would normally trigger the dead key nominal + * character output (such as a NUMPAD printable character or + * the TAB key, etc...). + */ + if (dead_key && (special_keys[i].vim_code0 == 'K' + || vk == VK_TAB || vk == CAR)) + { + outputDeadKey_rePost(msg); + return; + } + #ifdef FEAT_MENU /* Check for : Windows selects the menu. When is * mapped we want to use the mapping instead. */ *** ../vim-7.4.1123/src/version.c 2016-01-17 19:38:56.147067400 +0100 --- src/version.c 2016-01-17 20:49:25.360478451 +0100 *************** *** 743,744 **** --- 743,746 ---- { /* Add new patch number below this line */ + /**/ + 1124, /**/ -- Female engineers become irresistible at the age of consent and remain that way until about thirty minutes after their clinical death. Longer if it's a warm day. (Scott Adams - The Dilbert principle) /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///