@@ -301,18 +301,18 @@ static struct
301301};
302302
303303/* Local variables */
304- static int s_button_pending = -1 ;
304+ static int s_button_pending = -1 ;
305305
306306/* s_getting_focus is set when we got focus but didn't see mouse-up event yet,
307307 * so don't reset s_button_pending. */
308- static int s_getting_focus = FALSE;
308+ static int s_getting_focus = FALSE;
309309
310- static int s_x_pending ;
311- static int s_y_pending ;
312- static UINT s_kFlags_pending ;
313- static UINT s_wait_timer = 0 ; /* Timer for get char from user */
314- static int s_timed_out = FALSE;
315- static int dead_key = 0 ; /* 0 - no dead key, 1 - dead key pressed */
310+ static int s_x_pending ;
311+ static int s_y_pending ;
312+ static UINT s_kFlags_pending ;
313+ static UINT s_wait_timer = 0 ; /* Timer for get char from user */
314+ static int s_timed_out = FALSE;
315+ static int dead_key = 0 ; /* 0: no dead key, 1: dead key pressed */
316316
317317#ifdef WIN3264
318318static OSVERSIONINFO os_version ; /* like it says. Init in gui_mch_init() */
@@ -641,6 +641,8 @@ _OnSysChar(
641641 int modifiers ;
642642 int ch = cch ; /* special keys are negative */
643643
644+ dead_key = 0 ;
645+
644646 /* TRACE("OnSysChar(%d, %c)\n", ch, ch); */
645647
646648 /* OK, we have a character key (given by ch) which was entered with the
@@ -1710,6 +1712,34 @@ gui_mch_draw_part_cursor(
17101712 DeleteBrush (hbr );
17111713}
17121714
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+
17131743/*
17141744 * Process a single Windows message.
17151745 * If one is not available we hang until one is.
@@ -1790,21 +1820,48 @@ process_message(void)
17901820 if (msg .message == WM_KEYDOWN || msg .message == WM_SYSKEYDOWN )
17911821 {
17921822 vk = (int ) msg .wParam ;
1823+
17931824 /*
1794- * If a dead key was pressed and the user presses VK_SPACE, VK_BACK, or
1795- * VK_ESCAPE it means that he actually wants to deal with the dead char
1796- * now, so do nothing special and let Windows handle it.
1825+ * Handle dead keys in special conditions in other cases we let Windows
1826+ * handle them and do not interfere.
1827+ *
1828+ * The dead_key flag must be reset on several occasions:
1829+ * - in _OnChar() (or _OnSysChar()) as any dead key was necessarily
1830+ * consumed at that point (This is when we let Windows combine the
1831+ * dead character on its own)
17971832 *
1798- * Note that VK_SPACE combines with the dead_key's character and only
1799- * one WM_CHAR will be generated by TranslateMessage(), in the two
1800- * other cases two WM_CHAR will be generated: the dead char and VK_BACK
1801- * or VK_ESCAPE. That is most likely what the user expects .
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()) .
18021837 */
1803- if (dead_key && ( vk == VK_SPACE || vk == VK_BACK || vk == VK_ESCAPE ) )
1838+ if (dead_key )
18041839 {
1805- dead_key = 0 ;
1806- MyTranslateMessage (& msg );
1807- return ;
1840+ /*
1841+ * If a dead key was pressed and the user presses VK_SPACE,
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+ }
18081865 }
18091866
18101867 /* Check for CTRL-BREAK */
@@ -1822,6 +1879,19 @@ process_message(void)
18221879 if (special_keys [i ].key_sym == vk
18231880 && (vk != VK_SPACE || !(GetKeyState (VK_MENU ) & 0x8000 )))
18241881 {
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+
18251895#ifdef FEAT_MENU
18261896 /* Check for <F10>: Windows selects the menu. When <F10> is
18271897 * mapped we want to use the mapping instead. */
0 commit comments