Patch 9.0.0087
Problem:    MS-Windows: CTRL-[ on Belgian keyboard does not work like Esc.
Solution:   Figure out what the key code means. (Anton Sharonov,
            closes #10687, closes #10454)
Files:      src/gui_w32.c


*** ../vim-9.0.0086/src/gui_w32.c       2022-07-23 09:52:00.337814264 +0100
--- src/gui_w32.c       2022-07-26 21:25:43.632789990 +0100
***************
*** 29,34 ****
--- 29,40 ----
  # include "gui_dwrite.h"
  #endif
  
+ // values for "dead_key"
+ #define DEAD_KEY_OFF                  0       // no dead key
+ #define DEAD_KEY_SET_DEFAULT          1       // dead key pressed
+ #define DEAD_KEY_TRANSIENT_IN_ON_CHAR 2       // wait for next key press
+ #define DEAD_KEY_SKIP_ON_CHAR         3       // skip next _OnChar()
+ 
  #if defined(FEAT_DIRECTX)
  static DWriteContext *s_dwc = NULL;
  static int s_directx_enabled = 0;
***************
*** 533,539 ****
  static UINT   s_kFlags_pending;
  static UINT_PTR       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
  static UINT   surrogate_pending_ch = 0; // 0: no surrogate pending,
                                          // else a high surrogate
  
--- 539,545 ----
  static UINT   s_kFlags_pending;
  static UINT_PTR       s_wait_timer = 0;         // Timer for get char from 
user
  static int    s_timed_out = FALSE;
! static int    dead_key = DEAD_KEY_OFF;
  static UINT   surrogate_pending_ch = 0; // 0: no surrogate pending,
                                          // else a high surrogate
  
***************
*** 866,872 ****
      int               modifiers;
      int               ch = cch;   // special keys are negative
  
!     dead_key = 0;
  
      modifiers = get_active_modifiers();
  
--- 872,884 ----
      int               modifiers;
      int               ch = cch;   // special keys are negative
  
!     if (dead_key == DEAD_KEY_SKIP_ON_CHAR)
!       return;
! 
!     //  keep DEAD_KEY_TRANSIENT_IN_ON_CHAR value for later handling in
!     //  process_message()
!     if (dead_key != DEAD_KEY_TRANSIENT_IN_ON_CHAR)
!       dead_key = DEAD_KEY_OFF;
  
      modifiers = get_active_modifiers();
  
***************
*** 912,918 ****
      int               modifiers;
      int               ch = cch;   // special keys are negative
  
!     dead_key = 0;
  
      // OK, we have a character key (given by ch) which was entered with the
      // ALT key pressed. Eg, if the user presses Alt-A, then ch == 'A'. Note
--- 924,930 ----
      int               modifiers;
      int               ch = cch;   // special keys are negative
  
!     dead_key = DEAD_KEY_OFF;
  
      // OK, we have a character key (given by ch) which was entered with the
      // ALT key pressed. Eg, if the user presses Alt-A, then ch == 'A'. Note
***************
*** 1844,1857 ****
   * 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;
--- 1856,1869 ----
   * dead key's nominal character and re-post the original message.
   */
      static void
! outputDeadKey_rePost_Ex(MSG originalMsg, int dead_key2set)
  {
      static MSG deadCharExpel;
  
!     if (dead_key == DEAD_KEY_OFF)
        return;
  
!     dead_key = dead_key2set;
  
      // Make Windows generate the dead key's character
      deadCharExpel.message = originalMsg.message;
***************
*** 1866,1871 ****
--- 1878,1892 ----
  }
  
  /*
+  * Wrapper for outputDeadKey_rePost_Ex which always reset dead_key value.
+  */
+     static void
+ outputDeadKey_rePost(MSG originalMsg)
+ {
+     outputDeadKey_rePost_Ex(originalMsg, DEAD_KEY_OFF);
+ }
+ 
+ /*
   * Process a single Windows message.
   * If one is not available we hang until one is.
   */
***************
*** 1936,1944 ****
         *   for some reason TranslateMessage() 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
--- 1957,2004 ----
         *   for some reason TranslateMessage() do not trigger a call
         *   immediately to _OnChar() (or _OnSysChar()).
         */
! 
!       /*
!        * We are at the moment after WM_CHAR with DEAD_KEY_SKIP_ON_CHAR event
!        * was handled by _WndProc, this keypress we want to process normally
!        */
!       if (dead_key == DEAD_KEY_SKIP_ON_CHAR)
!           dead_key = DEAD_KEY_OFF;
! 
!       if (dead_key != DEAD_KEY_OFF)
        {
            /*
+            * Expell the dead key pressed with Ctrl in a special way.
+            *
+            * After dead key was pressed with Ctrl in some cases, ESC was
+            * artificially injected and handled by _OnChar(), now we are
+            * dealing with completely new key press from the user. If we don't
+            * do anything, ToUnicode() call will interpret this vk+scan_code
+            * under influence of "dead-modifier". To prevent this we translate
+            * this message replacing current char from user with VK_SPACE,
+            * which will cause WM_CHAR with dead_key's character itself. Using
+            * DEAD_KEY_SKIP_ON_CHAR value of dead_char we force _OnChar() to
+            * ignore this one WM_CHAR event completely. Afterwards (due to
+            * usage of PostMessage), this procedure is scheduled to be called
+            * again with user char and on next entry we will clean
+            * DEAD_KEY_SKIP_ON_CHAR. We cannot use original
+            * outputDeadKey_rePost() since we do not wish to reset dead_key
+            * value.
+            */
+           if (dead_key == DEAD_KEY_TRANSIENT_IN_ON_CHAR)
+           {
+               outputDeadKey_rePost_Ex(msg,
+                                      /*dead_key2set=*/DEAD_KEY_SKIP_ON_CHAR);
+               return;
+           }
+ 
+           if (dead_key != DEAD_KEY_SET_DEFAULT)
+           {
+               // should never happen - is there a way to make ASSERT here?
+               return;
+           }
+ 
+           /*
             * 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
***************
*** 1952,1958 ****
             */
            if ((vk == VK_SPACE || vk == VK_BACK || vk == VK_ESCAPE))
            {
!               dead_key = 0;
                TranslateMessage(&msg);
                return;
            }
--- 2012,2018 ----
             */
            if ((vk == VK_SPACE || vk == VK_BACK || vk == VK_ESCAPE))
            {
!               dead_key = DEAD_KEY_OFF;
                TranslateMessage(&msg);
                return;
            }
***************
*** 1995,2001 ****
                 * 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);
--- 2055,2061 ----
                 * character output (such as a NUMPAD printable character or
                 * the TAB key, etc...).
                 */
!               if (dead_key == DEAD_KEY_SET_DEFAULT && 
(special_keys[i].vim_code0 == 'K'
                                                || vk == VK_TAB || vk == CAR))
                {
                    outputDeadKey_rePost(msg);
***************
*** 2081,2090 ****
            // If this is a dead key ToUnicode returns a negative value.
            len = ToUnicode(vk, scan_code, keyboard_state, ch, ARRAY_LENGTH(ch),
                    0);
!           dead_key = len < 0;
  
            if (len <= 0)
                return;
  
            // Post the message as TranslateMessage would do.
            if (msg.message == WM_KEYDOWN)
--- 2141,2168 ----
            // If this is a dead key ToUnicode returns a negative value.
            len = ToUnicode(vk, scan_code, keyboard_state, ch, ARRAY_LENGTH(ch),
                    0);
!           if (len < 0)
!               dead_key = DEAD_KEY_SET_DEFAULT;
  
            if (len <= 0)
+           {
+               if (   dead_key == DEAD_KEY_SET_DEFAULT
+                   && (GetKeyState(VK_CONTROL) & 0x8000)
+                   && (   (vk == 221 && scan_code == 26) // AZERTY 
CTRL+dead_circumflex
+                       || (vk == 220 && scan_code == 41) // QWERTZ 
CTRL+dead_circumflex
+                      )
+                  )
+               {
+                   // post WM_CHAR='[' - which will be interpreted with CTRL
+                   // stil hold as ESC
+                   PostMessageW(msg.hwnd, WM_CHAR, '[', msg.lParam);
+                   // ask _OnChar() to not touch this state, wait for next key
+                   // press and maintain knowledge that we are "poisoned" with
+                   // "dead state"
+                   dead_key = DEAD_KEY_TRANSIENT_IN_ON_CHAR;
+               }
                return;
+           }
  
            // Post the message as TranslateMessage would do.
            if (msg.message == WM_KEYDOWN)
*** ../vim-9.0.0086/src/version.c       2022-07-26 20:42:21.822448308 +0100
--- src/version.c       2022-07-26 21:14:39.729664352 +0100
***************
*** 737,738 ****
--- 737,740 ----
  {   /* Add new patch number below this line */
+ /**/
+     87,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
143. You dream in pallettes of 216 websafe colors.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20220726202657.C61131C07D3%40moolenaar.net.

Raspunde prin e-mail lui