To: vim_dev@googlegroups.com Subject: Patch 9.0.1112 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.1112 Problem: test_mswin_event() can hang. Solution: Add the "execute" argument to process events right away. (Christopher Plewright, closes #11760) Files: runtime/doc/testing.txt, src/gui_w32.c, src/os_win32.c, src/testdir/test_gui.vim, src/testdir/test_mswin_event.vim *** ../vim-9.0.1111/runtime/doc/testing.txt 2022-12-20 20:01:09.620090910 +0000 --- runtime/doc/testing.txt 2022-12-30 16:40:51.789520106 +0000 *************** *** 274,280 **** event: The supported string values are: keyup generate a keyup event keydown generate a keydown event ! keycode: Keycode to use for a keyup or a keydown event. modifiers: Optional; key modifiers. The supported values are: 2 shift is pressed --- 274,280 ---- event: The supported string values are: keyup generate a keyup event keydown generate a keydown event ! keycode: Keycode to use for a keyup or a keydown event. modifiers: Optional; key modifiers. The supported values are: 2 shift is pressed *************** *** 282,290 **** 8 alt is pressed Note: These values are different from the mouse modifiers. ! *E1291* ! Returns TRUE if the event is successfully added, FALSE if ! there is a failure. Can also be used as a |method|: > GetEvent()->test_mswin_event({args}) --- 282,295 ---- 8 alt is pressed Note: These values are different from the mouse modifiers. ! execute: Optional. Similar to |feedkeys()| mode x. ! When this is included and set to true ! (non-zero) then Vim will process any buffered ! unprocessed key events. All other {args} ! items are optional when this is set and true. ! ! Returns TRUE if the event is successfully added or executed, ! FALSE if there is a failure. Can also be used as a |method|: > GetEvent()->test_mswin_event({args}) *** ../vim-9.0.1111/src/gui_w32.c 2022-12-20 20:01:09.624090908 +0000 --- src/gui_w32.c 2022-12-30 16:39:14.741599172 +0000 *************** *** 888,893 **** --- 888,899 ---- modifiers = get_active_modifiers(); ch = simplify_key(ch, &modifiers); + + // Some keys need adjustment when the Ctrl modifier is used. + ++no_reduce_keys; + ch = may_adjust_key_for_ctrl(modifiers, ch); + --no_reduce_keys; + // remove the SHIFT modifier for keys where it's already included, e.g., // '(' and '*' modifiers = may_remove_shift_modifier(modifiers, ch); *** ../vim-9.0.1111/src/os_win32.c 2022-12-22 21:06:35.047328431 +0000 --- src/os_win32.c 2022-12-30 16:39:14.745599171 +0000 *************** *** 1106,1136 **** break; } - // special cases - if ((nModifs & CTRL) != 0 && (nModifs & ~CTRL) == 0 - && (pker->uChar.UnicodeChar == NUL - || pker->uChar.UnicodeChar == 0xfffd)) - { - // Ctrl-6 is Ctrl-^ - if (pker->wVirtualKeyCode == '6') - { - *pch = Ctrl_HAT; - return TRUE; - } - // Ctrl-2 is Ctrl-@ - else if (pker->wVirtualKeyCode == '2') - { - *pch = NUL; - return TRUE; - } - // Ctrl-- is Ctrl-_ - else if (pker->wVirtualKeyCode == 0xBD) - { - *pch = Ctrl__; - return TRUE; - } - } - // Shift-TAB if (pker->wVirtualKeyCode == VK_TAB && (nModifs & SHIFT_PRESSED)) { --- 1106,1111 ---- *************** *** 1277,1289 **** ker.wVirtualKeyCode = vkCode; win32_kbd_patch_key(&ker); ! for (int i = ARRAY_LENGTH(VirtKeyMap); ! --i >= 0 && !ker.uChar.UnicodeChar; ) { if (VirtKeyMap[i].wVirtKey == vkCode) ker.uChar.UnicodeChar = 0xfffd; // REPLACEMENT CHARACTER } ir->Event.KeyEvent = ker; vim_free(event); } --- 1252,1274 ---- ker.wVirtualKeyCode = vkCode; win32_kbd_patch_key(&ker); ! for (int i = ARRAY_LENGTH(VirtKeyMap); i >= 0; --i) { if (VirtKeyMap[i].wVirtKey == vkCode) + { ker.uChar.UnicodeChar = 0xfffd; // REPLACEMENT CHARACTER + break; + } } + // The following are treated specially in Vim. + // Ctrl-6 is Ctrl-^ + // Ctrl-2 is Ctrl-@ + // Ctrl-- is Ctrl-_ + if ((vkCode == 0xBD || vkCode == '2' || vkCode == '6') + && (ker.dwControlKeyState & CTRL)) + ker.uChar.UnicodeChar = 0xfffd; // REPLACEMENT CHARACTER + ir->Event.KeyEvent = ker; vim_free(event); } *************** *** 1919,1928 **** INPUT_RECORD ir; BOOL input_encoded = FALSE; if (STRCMP(event, "key") == 0) ! input_encoded = encode_key_event(args, &ir); else if (STRCMP(event, "mouse") == 0) input_encoded = encode_mouse_event(args, &ir); else { semsg(_(e_invalid_value_for_argument_str_str), "event", event); --- 1904,1926 ---- INPUT_RECORD ir; BOOL input_encoded = FALSE; + BOOL execute = FALSE; if (STRCMP(event, "key") == 0) ! { ! execute = dict_get_bool(args, "execute", FALSE); ! if (dict_has_key(args, "event")) ! input_encoded = encode_key_event(args, &ir); ! else if (!execute) ! { ! semsg(_(e_missing_argument_str), "event"); ! return FALSE; ! } ! } else if (STRCMP(event, "mouse") == 0) + { + execute = TRUE; input_encoded = encode_mouse_event(args, &ir); + } else { semsg(_(e_invalid_value_for_argument_str_str), "event", event); *************** *** 1935,1942 **** if (input_encoded) lpEventsWritten = write_input_record_buffer(&ir, 1); ! if (STRCMP(event, "mouse") == 0) exec_normal(TRUE, TRUE, TRUE); # endif return lpEventsWritten; --- 1933,1948 ---- if (input_encoded) lpEventsWritten = write_input_record_buffer(&ir, 1); ! // Set flags to execute the event, ie. like feedkeys mode X. ! if (execute) ! { ! int save_msg_scroll = msg_scroll; ! // Avoid a 1 second delay when the keys start Insert mode. ! msg_scroll = FALSE; ! ch_log(NULL, "test_mswin_event() executing"); exec_normal(TRUE, TRUE, TRUE); + msg_scroll |= save_msg_scroll; + } # endif return lpEventsWritten; *************** *** 2426,2431 **** --- 2432,2446 ---- c = tgetch(&modifiers, &ch2); + // Some chars need adjustment when the Ctrl modifier is used. + ++no_reduce_keys; + c = may_adjust_key_for_ctrl(modifiers, c); + --no_reduce_keys; + + // remove the SHIFT modifier for keys where it's already included, + // e.g., '(' and '*' + modifiers = may_remove_shift_modifier(modifiers, c); + if (typebuf_changed(tb_change_cnt)) { // "buf" may be invalid now if a client put something in the *** ../vim-9.0.1111/src/testdir/test_gui.vim 2022-12-20 20:01:09.624090908 +0000 --- src/testdir/test_gui.vim 2022-12-30 16:39:14.745599171 +0000 *************** *** 1694,1700 **** \ [[0x11, 0x10, 0x28], "C-S-Down", 4], \ [[0x11, 0x30], "C-0", 4], \ [[0x11, 0x31], "C-1", 4], ! \ [[0x11, 0x32], "C-2", 4], \ [[0x11, 0x33], "C-3", 4], \ [[0x11, 0x34], "C-4", 4], \ [[0x11, 0x35], "C-5", 4], --- 1694,1700 ---- \ [[0x11, 0x10, 0x28], "C-S-Down", 4], \ [[0x11, 0x30], "C-0", 4], \ [[0x11, 0x31], "C-1", 4], ! \ [[0x11, 0x32], "C-@", 0], \ [[0x11, 0x33], "C-3", 4], \ [[0x11, 0x34], "C-4", 4], \ [[0x11, 0x35], "C-5", 4], *************** *** 1715,1720 **** --- 1715,1721 ---- \ [[0x11, 0x6A], "C-*", 4], \ [[0x11, 0x6B], "C-+", 4], \ [[0x11, 0x6D], "C--", 4], + \ [[0x11, 0xBD], "C-_", 0], \ [[0x11, 0x70], "C-F1", 4], \ [[0x11, 0x10, 0x70], "C-S-F1", 4], \ [[0x11, 0x71], "C-F2", 4], *** ../vim-9.0.1111/src/testdir/test_mswin_event.vim 2022-12-20 20:01:09.624090908 +0000 --- src/testdir/test_mswin_event.vim 2022-12-30 16:39:14.745599171 +0000 *************** *** 1,25 **** ! " Test MS-Windows console event handling. source check.vim CheckMSWindows - " The mswin events should also work in gui source mouse.vim ! " Helper function for sending a sequence of low level key presses ! " The modifer key(s) can be included as normal key presses in the sequence ! func SendKeys(keylist) ! for k in a:keylist ! call test_mswin_event("key", #{event: "keydown", keycode: k}) endfor ! for k in reverse(copy(a:keylist)) ! call test_mswin_event("key", #{event: "keyup", keycode: k}) endfor endfunc ! " Send an individual key press " the modifers for the key press can be specified in the modifiers arg. ! func SendKey(key, modifiers) let args = { } let args.keycode = a:key let args.modifiers = a:modifiers --- 1,27 ---- ! " Test MS-Windows input event handling. ! " Most of this works the same in Windows GUI as well as Windows console. source check.vim CheckMSWindows source mouse.vim ! " Helper function for sending a grouped sequence of low level key presses ! " The modifer key(s) can be included as VK Key Codes in the sequence ! " Keydown events will be sent, to to the end of the group, then keyup events ! " will be sent in reverse order to release the keys. ! func SendKeyGroup(keygroup) ! for k in a:keygroup ! call test_mswin_event("key", {'event': "keydown", 'keycode': k}) endfor ! for k in reverse(copy(a:keygroup)) ! call test_mswin_event("key", {'event': "keyup", 'keycode': k}) endfor endfunc ! " Send individual key press and release events. " the modifers for the key press can be specified in the modifiers arg. ! func SendKeyWithModifiers(key, modifiers) let args = { } let args.keycode = a:key let args.modifiers = a:modifiers *************** *** 30,260 **** unlet args endfunc ! " Test MS-Windows console key events ! func Test_mswin_key_event() ! CheckMSWindows ! new ! " flush out any garbage left in the buffer ! while getchar(0) ! endwhile ! let VK = #{ ! \ SPACE : 0x20, ! \ SHIFT : 0x10, ! \ LSHIFT : 0xA0, ! \ RSHIFT : 0xA1, ! \ CONTROL : 0x11, ! \ LCONTROL : 0xA2, ! \ RCONTROL : 0xA3, ! \ MENU : 0x12, ! \ ALT : 0x12, ! \ LMENU : 0xA4, ! \ LALT : 0xA4, ! \ RMENU : 0xA5, ! \ RALT : 0xA5, ! \ OEM_1 : 0xBA, ! \ OEM_2 : 0xBF, ! \ OEM_3 : 0xC0, ! \ OEM_4 : 0xDB, ! \ OEM_5 : 0xDC, ! \ OEM_6 : 0xDD, ! \ OEM_7 : 0xDE, ! \ OEM_PLUS : 0xBB, ! \ OEM_COMMA : 0xBC, ! \ OEM_MINUS : 0xBD, ! \ OEM_PERIOD : 0xBE, ! \ PRIOR : 0x21, ! \ NEXT : 0x22, ! \ END : 0x23, ! \ HOME : 0x24, ! \ LEFT : 0x25, ! \ UP : 0x26, ! \ RIGHT : 0x27, ! \ DOWN : 0x28, ! \ KEY_0 : 0x30, ! \ KEY_1 : 0x31, ! \ KEY_2 : 0x32, ! \ KEY_3 : 0x33, ! \ KEY_4 : 0x34, ! \ KEY_5 : 0x35, ! \ KEY_6 : 0x36, ! \ KEY_7 : 0x37, ! \ KEY_8 : 0x38, ! \ KEY_9 : 0x39, ! \ NUMPAD0 : 0x60, ! \ NUMPAD1 : 0x61, ! \ NUMPAD2 : 0x62, ! \ NUMPAD3 : 0x63, ! \ NUMPAD4 : 0x64, ! \ NUMPAD5 : 0x65, ! \ NUMPAD6 : 0x66, ! \ NUMPAD7 : 0x67, ! \ NUMPAD8 : 0x68, ! \ NUMPAD9 : 0x69, ! \ MULTIPLY : 0x6A, ! \ ADD : 0x6B, ! \ SUBTRACT : 0x6D, ! \ F1 : 0x70, ! \ F2 : 0x71, ! \ F3 : 0x72, ! \ F4 : 0x73, ! \ F5 : 0x74, ! \ F6 : 0x75, ! \ F7 : 0x76, ! \ F8 : 0x77, ! \ F9 : 0x78, ! \ F10 : 0x79, ! \ F11 : 0x7A, ! \ F12 : 0x7B, ! \ KEY_A : 0x41, ! \ KEY_B : 0x42, ! \ KEY_C : 0x43, ! \ KEY_D : 0x44, ! \ KEY_E : 0x45, ! \ KEY_F : 0x46, ! \ KEY_G : 0x47, ! \ KEY_H : 0x48, ! \ KEY_I : 0x49, ! \ KEY_J : 0x4A, ! \ KEY_K : 0x4B, ! \ KEY_L : 0x4C, ! \ KEY_M : 0x4D, ! \ KEY_N : 0x4E, ! \ KEY_O : 0x4F, ! \ KEY_P : 0x50, ! \ KEY_Q : 0x51, ! \ KEY_R : 0x52, ! \ KEY_S : 0x53, ! \ KEY_T : 0x54, ! \ KEY_U : 0x55, ! \ KEY_V : 0x56, ! \ KEY_W : 0x57, ! \ KEY_X : 0x58, ! \ KEY_Y : 0x59, ! \ KEY_Z : 0x5A ! \ } ! ! let vim_MOD_MASK_SHIFT = 0x02 ! let vim_MOD_MASK_CTRL = 0x04 ! let vim_MOD_MASK_ALT = 0x08 ! let vim_key_modifiers = [ \ ["", 0, []], ! \ ["S-", 2, [VK.SHIFT]], ! \ ["C-", 4, [VK.CONTROL]], ! \ ["C-S-", 6, [VK.CONTROL, VK.SHIFT]], ! \ ["A-", 8, [VK.MENU]], ! \ ["A-S-", 10, [VK.MENU, VK.SHIFT]], ! \ ["A-C-", 12, [VK.MENU, VK.CONTROL]], ! \ ["A-C-S-", 14, [VK.MENU, VK.CONTROL, VK.SHIFT]], \] - " Some punctuation characters " Assuming Standard US PC Keyboard layout ! let test_punctuation_keys = [ ! \ [[VK.SPACE], ' '], ! \ [[VK.OEM_1], ';'], ! \ [[VK.OEM_2], '/'], ! \ [[VK.OEM_3], '`'], ! \ [[VK.OEM_4], '['], ! \ [[VK.OEM_5], '\'], ! \ [[VK.OEM_6], ']'], ! \ [[VK.OEM_7], ''''], ! \ [[VK.OEM_PLUS], '='], ! \ [[VK.OEM_COMMA], ','], ! \ [[VK.OEM_MINUS], '-'], ! \ [[VK.OEM_PERIOD], '.'], ! \ [[VK.SHIFT, VK.OEM_1], ':'], ! \ [[VK.SHIFT, VK.OEM_2], '?'], ! \ [[VK.SHIFT, VK.OEM_3], '~'], ! \ [[VK.SHIFT, VK.OEM_4], '{'], ! \ [[VK.SHIFT, VK.OEM_5], '|'], ! \ [[VK.SHIFT, VK.OEM_6], '}'], ! \ [[VK.SHIFT, VK.OEM_7], '"'], ! \ [[VK.SHIFT, VK.OEM_PLUS], '+'], ! \ [[VK.SHIFT, VK.OEM_COMMA], '<'], ! \ [[VK.SHIFT, VK.OEM_MINUS], '_'], ! \ [[VK.SHIFT, VK.OEM_PERIOD], '>'], ! \ [[VK.SHIFT, VK.KEY_1], '!'], ! \ [[VK.SHIFT, VK.KEY_2], '@'], ! \ [[VK.SHIFT, VK.KEY_3], '#'], ! \ [[VK.SHIFT, VK.KEY_4], '$'], ! \ [[VK.SHIFT, VK.KEY_5], '%'], ! \ [[VK.SHIFT, VK.KEY_6], '^'], ! \ [[VK.SHIFT, VK.KEY_7], '&'], ! \ [[VK.SHIFT, VK.KEY_8], '*'], ! \ [[VK.SHIFT, VK.KEY_9], '('], ! \ [[VK.SHIFT, VK.KEY_0], ')'], ! \ [[VK.LSHIFT, VK.KEY_9], '('], ! \ [[VK.RSHIFT, VK.KEY_0], ')'] ! \ ] ! for [kcodes, kstr] in test_punctuation_keys ! call SendKeys(kcodes) let ch = getcharstr(0) ! call assert_equal($"{kstr}", $"{ch}") let mod_mask = getcharmod() " the mod_mask is zero when no modifiers are used ! " and when the virtual termcap maps shift the character call assert_equal(0, mod_mask, $"key = {kstr}") - endfor - - " flush out any garbage left in the buffer - while getchar(0) - endwhile ! for [kcodes, kstr] in test_punctuation_keys let modifiers = 0 let key = kcodes[0] - for key in kcodes ! if index([VK.SHIFT, VK.LSHIFT, VK.RSHIFT], key) >= 0 ! let modifiers = modifiers + vim_MOD_MASK_SHIFT endif ! if index([VK.CONTROL, VK.LCONTROL, VK.RCONTROL], key) >= 0 ! let modifiers = modifiers + vim_MOD_MASK_CTRL endif ! if index([VK.ALT, VK.LALT, VK.RALT], key) >= 0 ! let modifiers = modifiers + vim_MOD_MASK_ALT endif endfor ! ! call SendKey(key, modifiers) let ch = getcharstr(0) ! call assert_equal($"{kstr}", $"{ch}") ! let mod_mask = getcharmod() ! " workaround for the virtual termcap maps changing the character instead ! " of sending Shift ! if index([VK.SHIFT, VK.LSHIFT, VK.RSHIFT], kcodes[0]) >= 0 ! let modifiers = modifiers - vim_MOD_MASK_SHIFT endif ! call assert_equal(modifiers, mod_mask, $"key = {kstr}") endfor " flush out any garbage left in the buffer while getchar(0) endwhile " Test keyboard codes for digits " (0x30 - 0x39) : VK_0 - VK_9 are the same as ASCII '0' - '9' for kc in range(48, 57) ! call SendKeys([kc]) let ch = getcharstr(0) call assert_equal(nr2char(kc), ch) ! call SendKey(kc, 0) let ch = getcharstr(0) call assert_equal(nr2char(kc), ch) endfor " Test keyboard codes for Alt-0 to Alt-9 " Expect +128 from the digit char codes ! for modkey in [VK.ALT, VK.LALT, VK.RALT] for kc in range(48, 57) ! call SendKeys([modkey, kc]) let ch = getchar(0) call assert_equal(kc+128, ch) ! call SendKey(kc, vim_MOD_MASK_ALT) let ch = getchar(0) call assert_equal(kc+128, ch) endfor --- 32,430 ---- unlet args endfunc ! " Send an individual key press, without modifiers. ! func SendKey(key) ! call SendKeyWithModifiers(a:key, 0) ! endfunc ! " Send a string of individual key-press events, without modifiers. ! func SendKeyStr(keystring) ! for k in a:keystring ! call SendKey(k) ! endfor ! endfunc ! ! " This tells Vim to execute the buffered keys as user commands, ! " ie. same as feekdeys with mode X would do. ! func ExecuteBufferedKeys() ! if has('gui_running') ! call feedkeys("\", 'Lx!') ! else ! call test_mswin_event("key", {'execute': v:true}) ! endif ! endfunc ! ! let s:VK = { ! \ 'ENTER' : 0x0D, ! \ 'SPACE' : 0x20, ! \ 'SHIFT' : 0x10, ! \ 'LSHIFT' : 0xA0, ! \ 'RSHIFT' : 0xA1, ! \ 'CONTROL' : 0x11, ! \ 'LCONTROL' : 0xA2, ! \ 'RCONTROL' : 0xA3, ! \ 'MENU' : 0x12, ! \ 'ALT' : 0x12, ! \ 'LMENU' : 0xA4, ! \ 'LALT' : 0xA4, ! \ 'RMENU' : 0xA5, ! \ 'RALT' : 0xA5, ! \ 'OEM_1' : 0xBA, ! \ 'OEM_2' : 0xBF, ! \ 'OEM_3' : 0xC0, ! \ 'OEM_4' : 0xDB, ! \ 'OEM_5' : 0xDC, ! \ 'OEM_6' : 0xDD, ! \ 'OEM_7' : 0xDE, ! \ 'OEM_PLUS' : 0xBB, ! \ 'OEM_COMMA' : 0xBC, ! \ 'OEM_MINUS' : 0xBD, ! \ 'OEM_PERIOD' : 0xBE, ! \ 'PRIOR' : 0x21, ! \ 'NEXT' : 0x22, ! \ 'END' : 0x23, ! \ 'HOME' : 0x24, ! \ 'LEFT' : 0x25, ! \ 'UP' : 0x26, ! \ 'RIGHT' : 0x27, ! \ 'DOWN' : 0x28, ! \ 'KEY_0' : 0x30, ! \ 'KEY_1' : 0x31, ! \ 'KEY_2' : 0x32, ! \ 'KEY_3' : 0x33, ! \ 'KEY_4' : 0x34, ! \ 'KEY_5' : 0x35, ! \ 'KEY_6' : 0x36, ! \ 'KEY_7' : 0x37, ! \ 'KEY_8' : 0x38, ! \ 'KEY_9' : 0x39, ! \ 'KEY_A' : 0x41, ! \ 'KEY_B' : 0x42, ! \ 'KEY_C' : 0x43, ! \ 'KEY_D' : 0x44, ! \ 'KEY_E' : 0x45, ! \ 'KEY_F' : 0x46, ! \ 'KEY_G' : 0x47, ! \ 'KEY_H' : 0x48, ! \ 'KEY_I' : 0x49, ! \ 'KEY_J' : 0x4A, ! \ 'KEY_K' : 0x4B, ! \ 'KEY_L' : 0x4C, ! \ 'KEY_M' : 0x4D, ! \ 'KEY_N' : 0x4E, ! \ 'KEY_O' : 0x4F, ! \ 'KEY_P' : 0x50, ! \ 'KEY_Q' : 0x51, ! \ 'KEY_R' : 0x52, ! \ 'KEY_S' : 0x53, ! \ 'KEY_T' : 0x54, ! \ 'KEY_U' : 0x55, ! \ 'KEY_V' : 0x56, ! \ 'KEY_W' : 0x57, ! \ 'KEY_X' : 0x58, ! \ 'KEY_Y' : 0x59, ! \ 'KEY_Z' : 0x5A, ! \ 'NUMPAD0' : 0x60, ! \ 'NUMPAD1' : 0x61, ! \ 'NUMPAD2' : 0x62, ! \ 'NUMPAD3' : 0x63, ! \ 'NUMPAD4' : 0x64, ! \ 'NUMPAD5' : 0x65, ! \ 'NUMPAD6' : 0x66, ! \ 'NUMPAD7' : 0x67, ! \ 'NUMPAD8' : 0x68, ! \ 'NUMPAD9' : 0x69, ! \ 'MULTIPLY' : 0x6A, ! \ 'ADD' : 0x6B, ! \ 'SUBTRACT' : 0x6D, ! \ 'F1' : 0x70, ! \ 'F2' : 0x71, ! \ 'F3' : 0x72, ! \ 'F4' : 0x73, ! \ 'F5' : 0x74, ! \ 'F6' : 0x75, ! \ 'F7' : 0x76, ! \ 'F8' : 0x77, ! \ 'F9' : 0x78, ! \ 'F10' : 0x79, ! \ 'F11' : 0x7A, ! \ 'F12' : 0x7B, ! \ 'DELETE' : 0x2E, ! \ 'BACK' : 0x08, ! \ 'ESCAPE' : 0x1B ! \ } ! ! let s:vim_MOD_MASK_SHIFT = 0x02 ! let s:vim_MOD_MASK_CTRL = 0x04 ! let s:vim_MOD_MASK_ALT = 0x08 ! let s:vim_key_modifiers = [ \ ["", 0, []], ! \ ["S-", 2, [s:VK.SHIFT]], ! \ ["C-", 4, [s:VK.CONTROL]], ! \ ["C-S-", 6, [s:VK.CONTROL, s:VK.SHIFT]], ! \ ["A-", 8, [s:VK.MENU]], ! \ ["A-S-", 10, [s:VK.MENU, s:VK.SHIFT]], ! \ ["A-C-", 12, [s:VK.MENU, s:VK.CONTROL]], ! \ ["A-C-S-", 14, [s:VK.MENU, s:VK.CONTROL, s:VK.SHIFT]], \] " Assuming Standard US PC Keyboard layout ! let s:test_ascii_key_chars = [ ! \ [[s:VK.SPACE], ' '], ! \ [[s:VK.OEM_1], ';'], ! \ [[s:VK.OEM_2], '/'], ! \ [[s:VK.OEM_3], '`'], ! \ [[s:VK.OEM_4], '['], ! \ [[s:VK.OEM_5], '\'], ! \ [[s:VK.OEM_6], ']'], ! \ [[s:VK.OEM_7], ''''], ! \ [[s:VK.OEM_PLUS], '='], ! \ [[s:VK.OEM_COMMA], ','], ! \ [[s:VK.OEM_MINUS], '-'], ! \ [[s:VK.OEM_PERIOD], '.'], ! \ [[s:VK.SHIFT, s:VK.OEM_1], ':'], ! \ [[s:VK.SHIFT, s:VK.OEM_2], '?'], ! \ [[s:VK.SHIFT, s:VK.OEM_3], '~'], ! \ [[s:VK.SHIFT, s:VK.OEM_4], '{'], ! \ [[s:VK.SHIFT, s:VK.OEM_5], '|'], ! \ [[s:VK.SHIFT, s:VK.OEM_6], '}'], ! \ [[s:VK.SHIFT, s:VK.OEM_7], '"'], ! \ [[s:VK.SHIFT, s:VK.OEM_PLUS], '+'], ! \ [[s:VK.SHIFT, s:VK.OEM_COMMA], '<'], ! \ [[s:VK.SHIFT, s:VK.OEM_MINUS], '_'], ! \ [[s:VK.SHIFT, s:VK.OEM_PERIOD], '>'], ! \ [[s:VK.KEY_1], '1'], ! \ [[s:VK.KEY_2], '2'], ! \ [[s:VK.KEY_3], '3'], ! \ [[s:VK.KEY_4], '4'], ! \ [[s:VK.KEY_5], '5'], ! \ [[s:VK.KEY_6], '6'], ! \ [[s:VK.KEY_7], '7'], ! \ [[s:VK.KEY_8], '8'], ! \ [[s:VK.KEY_9], '9'], ! \ [[s:VK.KEY_0], '0'], ! \ [[s:VK.SHIFT, s:VK.KEY_1], '!'], ! \ [[s:VK.SHIFT, s:VK.KEY_2], '@'], ! \ [[s:VK.SHIFT, s:VK.KEY_3], '#'], ! \ [[s:VK.SHIFT, s:VK.KEY_4], '$'], ! \ [[s:VK.SHIFT, s:VK.KEY_5], '%'], ! \ [[s:VK.SHIFT, s:VK.KEY_6], '^'], ! \ [[s:VK.SHIFT, s:VK.KEY_7], '&'], ! \ [[s:VK.SHIFT, s:VK.KEY_8], '*'], ! \ [[s:VK.SHIFT, s:VK.KEY_9], '('], ! \ [[s:VK.SHIFT, s:VK.KEY_0], ')'], ! \ [[s:VK.KEY_A], 'a'], ! \ [[s:VK.KEY_B], 'b'], ! \ [[s:VK.KEY_C], 'c'], ! \ [[s:VK.KEY_D], 'd'], ! \ [[s:VK.KEY_E], 'e'], ! \ [[s:VK.KEY_F], 'f'], ! \ [[s:VK.KEY_G], 'g'], ! \ [[s:VK.KEY_H], 'h'], ! \ [[s:VK.KEY_I], 'i'], ! \ [[s:VK.KEY_J], 'j'], ! \ [[s:VK.KEY_K], 'k'], ! \ [[s:VK.KEY_L], 'l'], ! \ [[s:VK.KEY_M], 'm'], ! \ [[s:VK.KEY_N], 'n'], ! \ [[s:VK.KEY_O], 'o'], ! \ [[s:VK.KEY_P], 'p'], ! \ [[s:VK.KEY_Q], 'q'], ! \ [[s:VK.KEY_R], 'r'], ! \ [[s:VK.KEY_S], 's'], ! \ [[s:VK.KEY_T], 't'], ! \ [[s:VK.KEY_U], 'u'], ! \ [[s:VK.KEY_V], 'v'], ! \ [[s:VK.KEY_W], 'w'], ! \ [[s:VK.KEY_X], 'x'], ! \ [[s:VK.KEY_Y], 'y'], ! \ [[s:VK.KEY_Z], 'z'], ! \ [[s:VK.SHIFT, s:VK.KEY_A], 'A'], ! \ [[s:VK.SHIFT, s:VK.KEY_B], 'B'], ! \ [[s:VK.SHIFT, s:VK.KEY_C], 'C'], ! \ [[s:VK.SHIFT, s:VK.KEY_D], 'D'], ! \ [[s:VK.SHIFT, s:VK.KEY_E], 'E'], ! \ [[s:VK.SHIFT, s:VK.KEY_F], 'F'], ! \ [[s:VK.SHIFT, s:VK.KEY_G], 'G'], ! \ [[s:VK.SHIFT, s:VK.KEY_H], 'H'], ! \ [[s:VK.SHIFT, s:VK.KEY_I], 'I'], ! \ [[s:VK.SHIFT, s:VK.KEY_J], 'J'], ! \ [[s:VK.SHIFT, s:VK.KEY_K], 'K'], ! \ [[s:VK.SHIFT, s:VK.KEY_L], 'L'], ! \ [[s:VK.SHIFT, s:VK.KEY_M], 'M'], ! \ [[s:VK.SHIFT, s:VK.KEY_N], 'N'], ! \ [[s:VK.SHIFT, s:VK.KEY_O], 'O'], ! \ [[s:VK.SHIFT, s:VK.KEY_P], 'P'], ! \ [[s:VK.SHIFT, s:VK.KEY_Q], 'Q'], ! \ [[s:VK.SHIFT, s:VK.KEY_R], 'R'], ! \ [[s:VK.SHIFT, s:VK.KEY_S], 'S'], ! \ [[s:VK.SHIFT, s:VK.KEY_T], 'T'], ! \ [[s:VK.SHIFT, s:VK.KEY_U], 'U'], ! \ [[s:VK.SHIFT, s:VK.KEY_V], 'V'], ! \ [[s:VK.SHIFT, s:VK.KEY_W], 'W'], ! \ [[s:VK.SHIFT, s:VK.KEY_X], 'X'], ! \ [[s:VK.SHIFT, s:VK.KEY_Y], 'Y'], ! \ [[s:VK.SHIFT, s:VK.KEY_Z], 'Z'], ! \ [[s:VK.CONTROL, s:VK.KEY_A], 0x01], ! \ [[s:VK.CONTROL, s:VK.KEY_B], 0x02], ! \ [[s:VK.CONTROL, s:VK.KEY_C], 0x03], ! \ [[s:VK.CONTROL, s:VK.KEY_D], 0x04], ! \ [[s:VK.CONTROL, s:VK.KEY_E], 0x05], ! \ [[s:VK.CONTROL, s:VK.KEY_F], 0x06], ! \ [[s:VK.CONTROL, s:VK.KEY_G], 0x07], ! \ [[s:VK.CONTROL, s:VK.KEY_H], 0x08], ! \ [[s:VK.CONTROL, s:VK.KEY_I], 0x09], ! \ [[s:VK.CONTROL, s:VK.KEY_J], 0x0A], ! \ [[s:VK.CONTROL, s:VK.KEY_K], 0x0B], ! \ [[s:VK.CONTROL, s:VK.KEY_L], 0x0C], ! \ [[s:VK.CONTROL, s:VK.KEY_M], 0x0D], ! \ [[s:VK.CONTROL, s:VK.KEY_N], 0x0E], ! \ [[s:VK.CONTROL, s:VK.KEY_O], 0x0F], ! \ [[s:VK.CONTROL, s:VK.KEY_P], 0x10], ! \ [[s:VK.CONTROL, s:VK.KEY_Q], 0x11], ! \ [[s:VK.CONTROL, s:VK.KEY_R], 0x12], ! \ [[s:VK.CONTROL, s:VK.KEY_S], 0x13], ! \ [[s:VK.CONTROL, s:VK.KEY_T], 0x14], ! \ [[s:VK.CONTROL, s:VK.KEY_U], 0x15], ! \ [[s:VK.CONTROL, s:VK.KEY_V], 0x16], ! \ [[s:VK.CONTROL, s:VK.KEY_W], 0x17], ! \ [[s:VK.CONTROL, s:VK.KEY_X], 0x18], ! \ [[s:VK.CONTROL, s:VK.KEY_Y], 0x19], ! \ [[s:VK.CONTROL, s:VK.KEY_Z], 0x1A], ! \ [[s:VK.CONTROL, s:VK.OEM_4], 0x1B], ! \ [[s:VK.CONTROL, s:VK.OEM_5], 0x1C], ! \ [[s:VK.CONTROL, s:VK.OEM_6], 0x1D], ! \ ] ! " The following non-printable ascii chars fail in the GUI, but work in the ! " console. 0x1e [^^] Record separator (RS), and 0x1f [^_] Unit separator (US) ! " \ [[s:VK.CONTROL, s:VK.SHIFT, s:VK.KEY_6], 0x1E], ! " \ [[s:VK.CONTROL, s:VK.SHIFT, s:VK.OEM_MINUS], 0x1F], ! ! let s:test_extra_key_chars = [ ! \ [[s:VK.ALT, s:VK.KEY_1], '±'], ! \ [[s:VK.ALT, s:VK.KEY_2], '²'], ! \ [[s:VK.ALT, s:VK.KEY_3], '³'], ! \ [[s:VK.ALT, s:VK.KEY_4], '´'], ! \ [[s:VK.ALT, s:VK.KEY_5], 'µ'], ! \ [[s:VK.ALT, s:VK.KEY_6], '¶'], ! \ [[s:VK.ALT, s:VK.KEY_7], '·'], ! \ [[s:VK.ALT, s:VK.KEY_8], '¸'], ! \ [[s:VK.ALT, s:VK.KEY_9], '¹'], ! \ [[s:VK.ALT, s:VK.KEY_0], '°'], ! \ [[s:VK.ALT, s:VK.KEY_A], 'á'], ! \ [[s:VK.ALT, s:VK.KEY_B], 'â'], ! \ [[s:VK.ALT, s:VK.KEY_C], 'ã'], ! \ [[s:VK.ALT, s:VK.KEY_D], 'ä'], ! \ [[s:VK.ALT, s:VK.KEY_E], 'å'], ! \ [[s:VK.ALT, s:VK.KEY_F], 'æ'], ! \ [[s:VK.ALT, s:VK.KEY_G], 'ç'], ! \ [[s:VK.ALT, s:VK.KEY_H], 'è'], ! \ [[s:VK.ALT, s:VK.KEY_I], 'é'], ! \ [[s:VK.ALT, s:VK.KEY_J], 'ê'], ! \ [[s:VK.ALT, s:VK.KEY_K], 'ë'], ! \ [[s:VK.ALT, s:VK.KEY_L], 'ì'], ! \ [[s:VK.ALT, s:VK.KEY_M], 'í'], ! \ [[s:VK.ALT, s:VK.KEY_N], 'î'], ! \ [[s:VK.ALT, s:VK.KEY_O], 'ï'], ! \ [[s:VK.ALT, s:VK.KEY_P], 'ð'], ! \ [[s:VK.ALT, s:VK.KEY_Q], 'ñ'], ! \ [[s:VK.ALT, s:VK.KEY_R], 'ò'], ! \ [[s:VK.ALT, s:VK.KEY_S], 'ó'], ! \ [[s:VK.ALT, s:VK.KEY_T], 'ô'], ! \ [[s:VK.ALT, s:VK.KEY_U], 'õ'], ! \ [[s:VK.ALT, s:VK.KEY_V], 'ö'], ! \ [[s:VK.ALT, s:VK.KEY_W], '÷'], ! \ [[s:VK.ALT, s:VK.KEY_X], 'ø'], ! \ [[s:VK.ALT, s:VK.KEY_Y], 'ù'], ! \ [[s:VK.ALT, s:VK.KEY_Z], 'ú'], ! \ ] ! ! func s:LoopTestKeyArray(arr) ! " flush out any garbage left in the buffer ! while getchar(0) ! endwhile ! for [kcodes, kstr] in a:arr ! " Send as a sequence of key presses. ! call SendKeyGroup(kcodes) let ch = getcharstr(0) ! " need to deal a bit differently with the non-printable ascii chars < 0x20 ! if kstr < 0x20 && index([s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL], kcodes[0]) >= 0 ! call assert_equal(nr2char(kstr), $"{ch}") ! else ! call assert_equal(kstr, $"{ch}") ! endif let mod_mask = getcharmod() " the mod_mask is zero when no modifiers are used ! " and when the virtual termcap maps the character call assert_equal(0, mod_mask, $"key = {kstr}") ! " Send as a single key press with a modifers mask. let modifiers = 0 let key = kcodes[0] for key in kcodes ! if index([s:VK.SHIFT, s:VK.LSHIFT, s:VK.RSHIFT], key) >= 0 ! let modifiers = modifiers + s:vim_MOD_MASK_SHIFT endif ! if index([s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL], key) >= 0 ! let modifiers = modifiers + s:vim_MOD_MASK_CTRL endif ! if index([s:VK.ALT, s:VK.LALT, s:VK.RALT], key) >= 0 ! let modifiers = modifiers + s:vim_MOD_MASK_ALT endif endfor ! call SendKeyWithModifiers(key, modifiers) let ch = getcharstr(0) ! " need to deal a bit differently with the non-printable ascii chars < 0x20 ! if kstr < 0x20 && index([s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL], kcodes[0]) >= 0 ! call assert_equal(nr2char(kstr), $"{ch}") ! else ! call assert_equal(kstr, $"{ch}") endif ! let mod_mask = getcharmod() ! " the mod_mask is zero when no modifiers are used ! " and when the virtual termcap maps the character ! call assert_equal(0, mod_mask, $"key = {kstr}") endfor " flush out any garbage left in the buffer while getchar(0) endwhile + endfunc + + " Test MS-Windows key events + func Test_mswin_key_event() + CheckMSWindows + new + + call s:LoopTestKeyArray(s:test_ascii_key_chars) + + if !has('gui_running') + call s:LoopTestKeyArray(s:test_extra_key_chars) + endif + " Test keyboard codes for digits " (0x30 - 0x39) : VK_0 - VK_9 are the same as ASCII '0' - '9' for kc in range(48, 57) ! call SendKey(kc) let ch = getcharstr(0) call assert_equal(nr2char(kc), ch) ! call SendKeyWithModifiers(kc, 0) let ch = getcharstr(0) call assert_equal(nr2char(kc), ch) endfor " Test keyboard codes for Alt-0 to Alt-9 " Expect +128 from the digit char codes ! for modkey in [s:VK.ALT, s:VK.LALT, s:VK.RALT] for kc in range(48, 57) ! call SendKeyGroup([modkey, kc]) let ch = getchar(0) call assert_equal(kc+128, ch) ! call SendKeyWithModifiers(kc, s:vim_MOD_MASK_ALT) let ch = getchar(0) call assert_equal(kc+128, ch) endfor *************** *** 268,335 **** " char 'a' (91) as the output. The ASCII codes for the lowercase letters are " numbered 32 higher than their uppercase versions. for kc in range(65, 90) ! call SendKeys([kc]) let ch = getcharstr(0) call assert_equal(nr2char(kc + 32), ch) ! call SendKey(kc, 0) let ch = getcharstr(0) call assert_equal(nr2char(kc + 32), ch) endfor " Test for Uppercase 'A' - 'Z' keys " ie. with VK_SHIFT, expect the keycode = character code. ! for kc in range(65, 90) ! call SendKeys([VK.SHIFT, kc]) ! let ch = getcharstr(0) ! call assert_equal(nr2char(kc), ch) ! call SendKey(kc, vim_MOD_MASK_SHIFT) ! let ch = getcharstr(0) ! call assert_equal(nr2char(kc), ch) endfor " Test for to keys - " Same as for lowercase, except with Ctrl Key " Expect the unicode characters 0x01 to 0x1A ! for modkey in [VK.CONTROL, VK.LCONTROL, VK.RCONTROL] for kc in range(65, 90) ! call SendKeys([modkey, kc]) let ch = getcharstr(0) call assert_equal(nr2char(kc - 64), ch) ! call SendKey(kc, vim_MOD_MASK_CTRL) let ch = getcharstr(0) call assert_equal(nr2char(kc - 64), ch) endfor endfor if !has("gui_running") ! " Test for to keys " Expect the unicode characters 0xE1 to 0xFA " ie. 160 higher than the lowercase equivalent ! for kc in range(65, 90) ! call SendKeys([VK.LMENU, kc]) ! let ch = getchar(0) ! call assert_equal(kc+160, ch) ! call SendKey(kc, vim_MOD_MASK_ALT) ! let ch = getchar(0) ! call assert_equal(kc+160, ch) endfor endif if !has("gui_running") " Test for Function Keys 'F1' to 'F12' for n in range(1, 12) let kstr = $"F{n}" let keycode = eval('"\<' .. kstr .. '>"') ! call SendKeys([111+n]) let ch = getcharstr(0) call assert_equal(keycode, $"{ch}", $"key = <{kstr}>") endfor endif bw! endfunc ! " Test MS-Windows console mouse events func Test_mswin_mouse_event() CheckMSWindows new --- 438,646 ---- " char 'a' (91) as the output. The ASCII codes for the lowercase letters are " numbered 32 higher than their uppercase versions. for kc in range(65, 90) ! call SendKey(kc) let ch = getcharstr(0) call assert_equal(nr2char(kc + 32), ch) ! call SendKeyWithModifiers(kc, 0) let ch = getcharstr(0) call assert_equal(nr2char(kc + 32), ch) endfor " Test for Uppercase 'A' - 'Z' keys " ie. with VK_SHIFT, expect the keycode = character code. ! for modkey in [s:VK.SHIFT, s:VK.LSHIFT, s:VK.RSHIFT] ! for kc in range(65, 90) ! call SendKeyGroup([modkey, kc]) ! let ch = getcharstr(0) ! call assert_equal(nr2char(kc), ch) ! call SendKeyWithModifiers(kc, s:vim_MOD_MASK_SHIFT) ! let ch = getcharstr(0) ! call assert_equal(nr2char(kc), ch) ! endfor endfor " Test for to keys " Expect the unicode characters 0x01 to 0x1A ! for modkey in [s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL] for kc in range(65, 90) ! call SendKeyGroup([modkey, kc]) let ch = getcharstr(0) call assert_equal(nr2char(kc - 64), ch) ! call SendKeyWithModifiers(kc, s:vim_MOD_MASK_CTRL) let ch = getcharstr(0) call assert_equal(nr2char(kc - 64), ch) endfor endfor + " Windows intercepts some of these keys in the GUI. if !has("gui_running") ! " Test for to keys " Expect the unicode characters 0xE1 to 0xFA " ie. 160 higher than the lowercase equivalent ! for modkey in [s:VK.ALT, s:VK.LALT, s:VK.RALT] ! for kc in range(65, 90) ! call SendKeyGroup([modkey, kc]) ! let ch = getchar(0) ! call assert_equal(kc+160, ch) ! call SendKeyWithModifiers(kc, s:vim_MOD_MASK_ALT) ! let ch = getchar(0) ! call assert_equal(kc+160, ch) ! endfor endfor endif + " Windows intercepts some of these keys in the GUI if !has("gui_running") " Test for Function Keys 'F1' to 'F12' for n in range(1, 12) let kstr = $"F{n}" let keycode = eval('"\<' .. kstr .. '>"') ! call SendKey(111+n) let ch = getcharstr(0) call assert_equal(keycode, $"{ch}", $"key = <{kstr}>") endfor + " NOTE: mod + Fn Keys not working in CI Testing!? + " Test for Function Keys 'F1' to 'F12' + " VK codes 112(0x70) - 123(0x7B) + " With ALL permutatios of modifiers; Shift, Ctrl & Alt + for [mod_str, vim_mod_mask, mod_keycodes] in s:vim_key_modifiers + for n in range(1, 12) + let kstr = $"{mod_str}F{n}" + let keycode = eval('"\<' .. kstr .. '>"') + " call SendKeyGroup(mod_keycodes + [111+n]) + call SendKeyWithModifiers(111+n, vim_mod_mask) + let ch = getcharstr(0) + let mod_mask = getcharmod() + """""" call assert_equal(keycode, $"{ch}", $"key = {kstr}") + " workaround for the virtual termcap maps changing the character instead + " of sending Shift + for mod_key in mod_keycodes + if index([s:VK.SHIFT, s:VK.LSHIFT, s:VK.RSHIFT], mod_key) >= 0 + let mod_mask = mod_mask + s:vim_MOD_MASK_SHIFT + endif + endfor + """"""call assert_equal(vim_mod_mask, mod_mask, $"mod = {vim_mod_mask} for key = {kstr}") + endfor + endfor endif + " Test for the various Ctrl and Shift key combinations. + " Refer to the following page for the virtual key codes: + " https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes + let keytests = [ + \ [[s:VK.SHIFT, s:VK.PRIOR], "S-Pageup", 2], + \ [[s:VK.LSHIFT, s:VK.PRIOR], "S-Pageup", 2], + \ [[s:VK.RSHIFT, s:VK.PRIOR], "S-Pageup", 2], + \ [[s:VK.CONTROL, s:VK.PRIOR], "C-Pageup", 4], + \ [[s:VK.LCONTROL, s:VK.PRIOR], "C-Pageup", 4], + \ [[s:VK.RCONTROL, s:VK.PRIOR], "C-Pageup", 4], + \ [[s:VK.CONTROL, s:VK.SHIFT, s:VK.PRIOR], "C-S-Pageup", 6], + \ [[s:VK.SHIFT, s:VK.NEXT], "S-PageDown", 2], + \ [[s:VK.LSHIFT, s:VK.NEXT], "S-PageDown", 2], + \ [[s:VK.RSHIFT, s:VK.NEXT], "S-PageDown", 2], + \ [[s:VK.CONTROL, s:VK.NEXT], "C-PageDown", 4], + \ [[s:VK.LCONTROL, s:VK.NEXT], "C-PageDown", 4], + \ [[s:VK.RCONTROL, s:VK.NEXT], "C-PageDown", 4], + \ [[s:VK.CONTROL, s:VK.SHIFT, s:VK.NEXT], "C-S-PageDown", 6], + \ [[s:VK.SHIFT, s:VK.END], "S-End", 0], + \ [[s:VK.CONTROL, s:VK.END], "C-End", 0], + \ [[s:VK.CONTROL, s:VK.SHIFT, s:VK.END], "C-S-End", 4], + \ [[s:VK.SHIFT, s:VK.HOME], "S-Home", 0], + \ [[s:VK.CONTROL, s:VK.HOME], "C-Home", 0], + \ [[s:VK.CONTROL, s:VK.SHIFT, s:VK.HOME], "C-S-Home", 4], + \ [[s:VK.SHIFT, s:VK.LEFT], "S-Left", 0], + \ [[s:VK.CONTROL, s:VK.LEFT], "C-Left", 0], + \ [[s:VK.CONTROL, s:VK.SHIFT, s:VK.LEFT], "C-S-Left", 4], + \ [[s:VK.SHIFT, s:VK.UP], "S-Up", 0], + \ [[s:VK.CONTROL, s:VK.UP], "C-Up", 4], + \ [[s:VK.CONTROL, s:VK.SHIFT, s:VK.UP], "C-S-Up", 4], + \ [[s:VK.SHIFT, s:VK.RIGHT], "S-Right", 0], + \ [[s:VK.CONTROL, s:VK.RIGHT], "C-Right", 0], + \ [[s:VK.CONTROL, s:VK.SHIFT, s:VK.RIGHT], "C-S-Right", 4], + \ [[s:VK.SHIFT, s:VK.DOWN], "S-Down", 0], + \ [[s:VK.CONTROL, s:VK.DOWN], "C-Down", 4], + \ [[s:VK.CONTROL, s:VK.SHIFT, s:VK.DOWN], "C-S-Down", 4], + \ [[s:VK.CONTROL, s:VK.KEY_0], "C-0", 4], + \ [[s:VK.CONTROL, s:VK.KEY_1], "C-1", 4], + \ [[s:VK.CONTROL, s:VK.KEY_2], "C-@", 0], + \ [[s:VK.CONTROL, s:VK.KEY_3], "C-3", 4], + \ [[s:VK.CONTROL, s:VK.KEY_4], "C-4", 4], + \ [[s:VK.CONTROL, s:VK.KEY_5], "C-5", 4], + \ [[s:VK.CONTROL, s:VK.KEY_6], "C-^", 0], + \ [[s:VK.CONTROL, s:VK.KEY_7], "C-7", 4], + \ [[s:VK.CONTROL, s:VK.KEY_8], "C-8", 4], + \ [[s:VK.CONTROL, s:VK.KEY_9], "C-9", 4], + \ [[s:VK.CONTROL, s:VK.NUMPAD0], "C-0", 4], + \ [[s:VK.CONTROL, s:VK.NUMPAD1], "C-1", 4], + \ [[s:VK.CONTROL, s:VK.NUMPAD2], "C-2", 4], + \ [[s:VK.CONTROL, s:VK.NUMPAD3], "C-3", 4], + \ [[s:VK.CONTROL, s:VK.NUMPAD4], "C-4", 4], + \ [[s:VK.CONTROL, s:VK.NUMPAD5], "C-5", 4], + \ [[s:VK.CONTROL, s:VK.NUMPAD6], "C-6", 4], + \ [[s:VK.CONTROL, s:VK.NUMPAD7], "C-7", 4], + \ [[s:VK.CONTROL, s:VK.NUMPAD8], "C-8", 4], + \ [[s:VK.CONTROL, s:VK.NUMPAD9], "C-9", 4], + \ [[s:VK.CONTROL, s:VK.MULTIPLY], "C-*", 4], + \ [[s:VK.CONTROL, s:VK.ADD], "C-+", 4], + \ [[s:VK.CONTROL, s:VK.SUBTRACT], "C--", 4], + \ [[s:VK.CONTROL, s:VK.OEM_MINUS], "C-_", 0] + \ ] + + " Not working in CI Testing yet!? + for [kcodes, kstr, kmod] in keytests + call SendKeyGroup(kcodes) + let ch = getcharstr(0) + let mod = getcharmod() + let keycode = eval('"\<' .. kstr .. '>"') + " call assert_equal(keycode, ch, $"key = {kstr}") + " call assert_equal(kmod, mod, $"mod = {kmod} key = {kstr}") + endfor + + bw! + endfunc + + + " Test for QWERTY Ctrl+- which should result in ^_ + " issue #10817 + func Test_QWERTY_Ctrl_minus() + CheckMSWindows + new + + call SendKeyGroup([s:VK.CONTROL, s:VK.OEM_MINUS]) + let ch = getcharstr(0) + call assert_equal(nr2char(0x1f),ch) + + call SendKey(s:VK.KEY_I) + call SendKeyGroup([s:VK.CONTROL, s:VK.SUBTRACT]) + call SendKey(s:VK.ESCAPE) + call ExecuteBufferedKeys() + call assert_equal('-', getline('$')) + + %d _ + imapclear + imap BINGO + call SendKey(s:VK.KEY_I) + call SendKeyGroup([s:VK.CONTROL, s:VK.OEM_MINUS]) + call SendKey(s:VK.ESCAPE) + call ExecuteBufferedKeys() + call assert_equal('BINGO', getline('$')) + + %d _ + imapclear + exec "imap \x1f BILBO" + call SendKey(s:VK.KEY_I) + call SendKeyGroup([s:VK.CONTROL, s:VK.OEM_MINUS]) + call SendKey(s:VK.ESCAPE) + call ExecuteBufferedKeys() + call assert_equal('BILBO', getline('$')) + + + + imapclear bw! endfunc ! " Test MS-Windows mouse events func Test_mswin_mouse_event() CheckMSWindows new *** ../vim-9.0.1111/src/version.c 2022-12-30 11:15:56.462953467 +0000 --- src/version.c 2022-12-30 16:53:28.940988632 +0000 *************** *** 697,698 **** --- 697,700 ---- { /* Add new patch number below this line */ + /**/ + 1112, /**/ -- It is illegal for anyone to try and stop a child from playfully jumping over puddles of water. [real standing law in California, United States of America] /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///