Mercurial > vim
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 |