comparison src/gui_w48.c @ 7649:4d97a97495bb v7.4.1124

commit https://github.com/vim/vim/commit/25b2b94ea73eff2aeef624d2ba7f59a1a265a0c1 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jan 17 20:53:12 2016 +0100 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 https://github.com/vim/vim/issues/399)
author Christian Brabandt <cb@256bit.org>
date Sun, 17 Jan 2016 21:00:05 +0100
parents 52a7ba315f03
children 42c1a4e63d12
comparison
equal deleted inserted replaced
7648:bfc4a1d7725c 7649:4d97a97495bb
299 /* End of list marker: */ 299 /* End of list marker: */
300 {0, 0, 0} 300 {0, 0, 0}
301 }; 301 };
302 302
303 /* Local variables */ 303 /* Local variables */
304 static int s_button_pending = -1; 304 static int s_button_pending = -1;
305 305
306 /* s_getting_focus is set when we got focus but didn't see mouse-up event yet, 306 /* s_getting_focus is set when we got focus but didn't see mouse-up event yet,
307 * so don't reset s_button_pending. */ 307 * so don't reset s_button_pending. */
308 static int s_getting_focus = FALSE; 308 static int s_getting_focus = FALSE;
309 309
310 static int s_x_pending; 310 static int s_x_pending;
311 static int s_y_pending; 311 static int s_y_pending;
312 static UINT s_kFlags_pending; 312 static UINT s_kFlags_pending;
313 static UINT s_wait_timer = 0; /* Timer for get char from user */ 313 static UINT s_wait_timer = 0; /* Timer for get char from user */
314 static int s_timed_out = FALSE; 314 static int s_timed_out = FALSE;
315 static int dead_key = 0; /* 0 - no dead key, 1 - dead key pressed */ 315 static int dead_key = 0; /* 0: no dead key, 1: dead key pressed */
316 316
317 #ifdef WIN3264 317 #ifdef WIN3264
318 static OSVERSIONINFO os_version; /* like it says. Init in gui_mch_init() */ 318 static OSVERSIONINFO os_version; /* like it says. Init in gui_mch_init() */
319 #endif 319 #endif
320 320
638 { 638 {
639 char_u string[40]; /* Enough for multibyte character */ 639 char_u string[40]; /* Enough for multibyte character */
640 int len; 640 int len;
641 int modifiers; 641 int modifiers;
642 int ch = cch; /* special keys are negative */ 642 int ch = cch; /* special keys are negative */
643
644 dead_key = 0;
643 645
644 /* TRACE("OnSysChar(%d, %c)\n", ch, ch); */ 646 /* TRACE("OnSysChar(%d, %c)\n", ch, ch); */
645 647
646 /* OK, we have a character key (given by ch) which was entered with the 648 /* OK, we have a character key (given by ch) which was entered with the
647 * ALT key pressed. Eg, if the user presses Alt-A, then ch == 'A'. Note 649 * ALT key pressed. Eg, if the user presses Alt-A, then ch == 'A'. Note
1708 hbr = CreateSolidBrush(color); 1710 hbr = CreateSolidBrush(color);
1709 FillRect(s_hdc, &rc, hbr); 1711 FillRect(s_hdc, &rc, hbr);
1710 DeleteBrush(hbr); 1712 DeleteBrush(hbr);
1711 } 1713 }
1712 1714
1715
1716 /*
1717 * Generates a VK_SPACE when the internal dead_key flag is set to output the
1718 * dead key's nominal character and re-post the original message.
1719 */
1720 static void
1721 outputDeadKey_rePost(MSG originalMsg)
1722 {
1723 static MSG deadCharExpel;
1724
1725 if (!dead_key)
1726 return;
1727
1728 dead_key = 0;
1729
1730 /* Make Windows generate the dead key's character */
1731 deadCharExpel.message = originalMsg.message;
1732 deadCharExpel.hwnd = originalMsg.hwnd;
1733 deadCharExpel.wParam = VK_SPACE;
1734
1735 MyTranslateMessage(&deadCharExpel);
1736
1737 /* re-generate the current character free of the dead char influence */
1738 PostMessage(originalMsg.hwnd, originalMsg.message, originalMsg.wParam,
1739 originalMsg.lParam);
1740 }
1741
1742
1713 /* 1743 /*
1714 * Process a single Windows message. 1744 * Process a single Windows message.
1715 * If one is not available we hang until one is. 1745 * If one is not available we hang until one is.
1716 */ 1746 */
1717 static void 1747 static void
1788 * TranslateMessage(). 1818 * TranslateMessage().
1789 */ 1819 */
1790 if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN) 1820 if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN)
1791 { 1821 {
1792 vk = (int) msg.wParam; 1822 vk = (int) msg.wParam;
1823
1793 /* 1824 /*
1794 * If a dead key was pressed and the user presses VK_SPACE, VK_BACK, or 1825 * Handle dead keys in special conditions in other cases we let Windows
1795 * VK_ESCAPE it means that he actually wants to deal with the dead char 1826 * handle them and do not interfere.
1796 * now, so do nothing special and let Windows handle it.
1797 * 1827 *
1798 * Note that VK_SPACE combines with the dead_key's character and only 1828 * The dead_key flag must be reset on several occasions:
1799 * one WM_CHAR will be generated by TranslateMessage(), in the two 1829 * - in _OnChar() (or _OnSysChar()) as any dead key was necessarily
1800 * other cases two WM_CHAR will be generated: the dead char and VK_BACK 1830 * consumed at that point (This is when we let Windows combine the
1801 * or VK_ESCAPE. That is most likely what the user expects. 1831 * dead character on its own)
1832 *
1833 * - Before doing something special such as regenerating keypresses to
1834 * expel the dead character as this could trigger an infinite loop if
1835 * for some reason MyTranslateMessage() do not trigger a call
1836 * immediately to _OnChar() (or _OnSysChar()).
1802 */ 1837 */
1803 if (dead_key && (vk == VK_SPACE || vk == VK_BACK || vk == VK_ESCAPE)) 1838 if (dead_key)
1804 { 1839 {
1805 dead_key = 0; 1840 /*
1806 MyTranslateMessage(&msg); 1841 * If a dead key was pressed and the user presses VK_SPACE,
1807 return; 1842 * VK_BACK, or VK_ESCAPE it means that he actually wants to deal
1843 * with the dead char now, so do nothing special and let Windows
1844 * handle it.
1845 *
1846 * Note that VK_SPACE combines with the dead_key's character and
1847 * only one WM_CHAR will be generated by TranslateMessage(), in
1848 * the two other cases two WM_CHAR will be generated: the dead
1849 * char and VK_BACK or VK_ESCAPE. That is most likely what the
1850 * user expects.
1851 */
1852 if ((vk == VK_SPACE || vk == VK_BACK || vk == VK_ESCAPE))
1853 {
1854 dead_key = 0;
1855 MyTranslateMessage(&msg);
1856 return;
1857 }
1858 /* In modes where we are not typing, dead keys should behave
1859 * normally */
1860 else if (!(get_real_state() & (INSERT | CMDLINE | SELECTMODE)))
1861 {
1862 outputDeadKey_rePost(msg);
1863 return;
1864 }
1808 } 1865 }
1809 1866
1810 /* Check for CTRL-BREAK */ 1867 /* Check for CTRL-BREAK */
1811 if (vk == VK_CANCEL) 1868 if (vk == VK_CANCEL)
1812 { 1869 {
1820 { 1877 {
1821 /* ignore VK_SPACE when ALT key pressed: system menu */ 1878 /* ignore VK_SPACE when ALT key pressed: system menu */
1822 if (special_keys[i].key_sym == vk 1879 if (special_keys[i].key_sym == vk
1823 && (vk != VK_SPACE || !(GetKeyState(VK_MENU) & 0x8000))) 1880 && (vk != VK_SPACE || !(GetKeyState(VK_MENU) & 0x8000)))
1824 { 1881 {
1882 /*
1883 * Behave as exected if we have a dead key and the special key
1884 * is a key that would normally trigger the dead key nominal
1885 * character output (such as a NUMPAD printable character or
1886 * the TAB key, etc...).
1887 */
1888 if (dead_key && (special_keys[i].vim_code0 == 'K'
1889 || vk == VK_TAB || vk == CAR))
1890 {
1891 outputDeadKey_rePost(msg);
1892 return;
1893 }
1894
1825 #ifdef FEAT_MENU 1895 #ifdef FEAT_MENU
1826 /* Check for <F10>: Windows selects the menu. When <F10> is 1896 /* Check for <F10>: Windows selects the menu. When <F10> is
1827 * mapped we want to use the mapping instead. */ 1897 * mapped we want to use the mapping instead. */
1828 if (vk == VK_F10 1898 if (vk == VK_F10
1829 && gui.menu_is_active 1899 && gui.menu_is_active