Skip to content

Commit c896adb

Browse files
committed
patch 9.0.0912: libvterm with modifyOtherKeys level 2 does not match xterm
Problem: libvterm with modifyOtherKeys level 2 does not match xterm. Solution: Adjust key code escape sequences to be the same as what xterm sends in modifyOtherKeys level 2 mode. Check the value of no_reduce_keys before using it.
1 parent e6392b1 commit c896adb

8 files changed

Lines changed: 70 additions & 13 deletions

File tree

src/getchar.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2778,6 +2778,9 @@ handle_mapping(
27782778

27792779
// If no termcode matched, try to include the modifier into the
27802780
// key. This is for when modifyOtherKeys is working.
2781+
#ifdef FEAT_TERMINAL
2782+
check_no_reduce_keys(); // may update the no_reduce_keys flag
2783+
#endif
27812784
if (keylen == 0 && !no_reduce_keys)
27822785
{
27832786
keylen = check_simplify_modifier(max_mlen + 1);
@@ -3919,9 +3922,9 @@ getcmdkeycmd(
39193922
{
39203923
// CTRL-V is followed by octal, hex or other characters, reverses
39213924
// what AppendToRedobuffLit() does.
3922-
no_reduce_keys = TRUE; // don't merge modifyOtherKeys
3925+
++no_reduce_keys; // don't merge modifyOtherKeys
39233926
c1 = get_literal(TRUE);
3924-
no_reduce_keys = FALSE;
3927+
--no_reduce_keys;
39253928
}
39263929

39273930
if (got_int)

src/libvterm/src/keyboard.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ int vterm_is_modify_other_keys(VTerm *vt)
1414
void vterm_keyboard_unichar(VTerm *vt, uint32_t c, VTermModifier mod)
1515
{
1616
// VIM: added modifyOtherKeys support
17-
if (vt->state->mode.modify_other_keys && mod != 0) {
17+
if (vterm_is_modify_other_keys(vt) && mod != 0) {
1818
vterm_push_output_sprintf_ctrl(vt, C1_CSI, "27;%d;%d~", mod+1, c);
1919
return;
2020
}
@@ -184,7 +184,9 @@ void vterm_keyboard_key(VTerm *vt, VTermKey key, VTermModifier mod)
184184
break;
185185

186186
case KEYCODE_LITERAL: case_LITERAL:
187-
if(mod & (VTERM_MOD_SHIFT|VTERM_MOD_CTRL))
187+
if (vterm_is_modify_other_keys(vt) && mod != 0)
188+
vterm_push_output_sprintf_ctrl(vt, C1_CSI, "27;%d;%d~", mod+1, k.literal);
189+
else if(mod & (VTERM_MOD_SHIFT|VTERM_MOD_CTRL))
188190
vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%d;%du", k.literal, mod+1);
189191
else
190192
vterm_push_output_sprintf(vt, mod & VTERM_MOD_ALT ? ESC_S "%c" : "%c", k.literal);

src/misc2.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1516,7 +1516,8 @@ find_special_key(
15161516
* CTRL-2 is CTRL-@
15171517
* CTRL-6 is CTRL-^
15181518
* CTRL-- is CTRL-_
1519-
* Also, <C-H> and <C-h> mean the same thing, always use "H".
1519+
* Also, unless no_reduce_keys is set then <C-H> and <C-h> mean the same thing,
1520+
* use "H".
15201521
* Returns the possibly adjusted key.
15211522
*/
15221523
int
@@ -1525,7 +1526,12 @@ may_adjust_key_for_ctrl(int modifiers, int key)
15251526
if (modifiers & MOD_MASK_CTRL)
15261527
{
15271528
if (ASCII_ISALPHA(key))
1528-
return TOUPPER_ASC(key);
1529+
{
1530+
#ifdef FEAT_TERMINAL
1531+
check_no_reduce_keys(); // may update the no_reduce_keys flag
1532+
#endif
1533+
return no_reduce_keys == 0 ? TOUPPER_ASC(key) : key;
1534+
}
15291535
if (key == '2')
15301536
return '@';
15311537
if (key == '6')

src/proto/terminal.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ int term_try_stop_job(buf_T *buf);
1515
int term_check_timers(int next_due_arg, proftime_T *now);
1616
int term_in_normal_mode(void);
1717
void term_enter_job_mode(void);
18+
void check_no_reduce_keys(void);
1819
int send_keys_to_term(term_T *term, int c, int modmask, int typed);
1920
int terminal_is_active(void);
2021
cursorentry_T *term_get_cursor_shape(guicolor_T *fg, guicolor_T *bg);

src/terminal.c

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2167,6 +2167,38 @@ term_enter_job_mode()
21672167
#endif
21682168
}
21692169

2170+
/*
2171+
* When "modify_other_keys" is set then vgetc() should not reduce a key with
2172+
* modifiers into a basic key. However, we may only find out after calling
2173+
* vgetc(). Therefore vgetorpeek() will call check_no_reduce_keys() to update
2174+
* "no_reduce_keys" before using it.
2175+
*/
2176+
typedef enum {
2177+
NRKS_NONE, // initial value
2178+
NRKS_CHECK, // modify_other_keys was off before calling vgetc()
2179+
NRKS_SET, // no_reduce_keys was incremented in term_vgetc() or
2180+
// check_no_reduce_keys(), must be decremented.
2181+
} reduce_key_state_T;
2182+
2183+
static reduce_key_state_T no_reduce_key_state = NRKS_NONE;
2184+
2185+
void
2186+
check_no_reduce_keys(void)
2187+
{
2188+
if (no_reduce_key_state != NRKS_CHECK
2189+
|| no_reduce_keys >= 1
2190+
|| curbuf->b_term == NULL
2191+
|| curbuf->b_term->tl_vterm == NULL)
2192+
return;
2193+
2194+
if (vterm_is_modify_other_keys(curbuf->b_term->tl_vterm))
2195+
{
2196+
// "modify_other_keys" was enabled while waiting.
2197+
no_reduce_key_state = NRKS_SET;
2198+
++no_reduce_keys;
2199+
}
2200+
}
2201+
21702202
/*
21712203
* Get a key from the user with terminal mode mappings.
21722204
* Note: while waiting a terminal may be closed and freed if the channel is
@@ -2177,21 +2209,32 @@ term_vgetc()
21772209
{
21782210
int c;
21792211
int save_State = State;
2180-
int modify_other_keys = curbuf->b_term->tl_vterm == NULL ? FALSE
2181-
: vterm_is_modify_other_keys(curbuf->b_term->tl_vterm);
21822212

21832213
State = MODE_TERMINAL;
21842214
got_int = FALSE;
21852215
#ifdef MSWIN
21862216
ctrl_break_was_pressed = FALSE;
21872217
#endif
2188-
if (modify_other_keys)
2218+
2219+
if (curbuf->b_term->tl_vterm != NULL
2220+
&& vterm_is_modify_other_keys(curbuf->b_term->tl_vterm))
2221+
{
21892222
++no_reduce_keys;
2223+
no_reduce_key_state = NRKS_SET;
2224+
}
2225+
else
2226+
{
2227+
no_reduce_key_state = NRKS_CHECK;
2228+
}
2229+
21902230
c = vgetc();
21912231
got_int = FALSE;
21922232
State = save_State;
2193-
if (modify_other_keys)
2233+
2234+
if (no_reduce_key_state == NRKS_SET)
21942235
--no_reduce_keys;
2236+
no_reduce_key_state = NRKS_NONE;
2237+
21952238
return c;
21962239
}
21972240

src/testdir/keycode_check.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"12xterm":{"Space":"20","version":"1b5b3e34313b3335363b3063","C-Tab":"1b5b32373b353b397e","A-Esc":"1b5b32373b333b32377e","C-Space":"1b5b32373b353b33327e","status":"","S-C-I":"1b5b32373b363b37337e","C-I":"1b5b32373b353b3130357e","S-Tab":"1b5b5a","Tab":"09","S-Space":"1b5b32373b323b33327e","A-Tab":"1b5b32373b333b397e","C-Esc":"1b5b32373b353b32377e","protocol":"mok2","A-Space":"1b5b32373b333b33327e","S-Esc":"1b","Esc":"1b"},"2kitty":{"Space":"20","version":"1b5b3e313b343030303b323163","C-Tab":"","A-Esc":"1b5b32373b313175","C-Space":"1b5b33323b3575","status":"1b5b3f3175","S-C-I":"1b5b3130353b3675","C-I":"1b5b3130353b3575","S-Tab":"1b5b393b3275","Tab":"09","S-Space":"20","A-Tab":"1b5b393b313175","C-Esc":"1b5b32373b3575","protocol":"kitty","A-Space":"1b5b33323b313175","S-Esc":"1b5b32373b3275","Esc":"1b5b323775"},"11xterm":{"Space":"20","version":"1b5b3e34313b3335363b3063","C-Tab":"09","A-Esc":"9b00","status":"","S-C-I":"09","C-I":"09","S-Tab":"1b5b5a","Tab":"09","S-Space":"20","A-Tab":"8900","C-Esc":"1b","protocol":"none","A-Space":"a000","S-Esc":"1b","Esc":"1b"}}
1+
{"12xterm":{"Space":"20","version":"1b5b3e34313b3335363b3063","C-Tab":"1b5b32373b353b397e","A-Esc":"1b5b32373b333b32377e","C-Space":"1b5b32373b353b33327e","status":"","S-C-I":"1b5b32373b363b37337e","C-I":"1b5b32373b353b3130357e","S-Tab":"1b5b5a","Tab":"09","S-Space":"1b5b32373b323b33327e","A-Tab":"1b5b32373b333b397e","C-Esc":"1b5b32373b353b32377e","protocol":"mok2","A-Space":"1b5b32373b333b33327e","S-Esc":"1b","Esc":"1b"},"libvterm":{"Space":"20","version":"1b5b3e303b3130303b3063","C-Tab":"1b5b32373b353b397e","A-Esc":"1b5b32373b333b32377e","C-Space":"1b5b32373b353b33327e","status":"","S-C-I":"1b5b32373b363b37337e","C-I":"1b5b32373b353b3130357e","S-Tab":"1b5b5a","Tab":"09","resource":"","A-Tab":"1b5b32373b333b397e","S-Space":"1b5b32373b323b33327e","C-Esc":"1b5b32373b353b32377e","protocol":"mok2","A-Space":"1b5b32373b333b33327e","S-Esc":"1b","Esc":"1b"},"2kitty":{"Space":"20","version":"1b5b3e313b343030303b323163","C-Tab":"","A-Esc":"1b5b32373b313175","C-Space":"1b5b33323b3575","status":"1b5b3f3175","S-C-I":"1b5b3130353b3675","C-I":"1b5b3130353b3575","S-Tab":"1b5b393b3275","Tab":"09","S-Space":"20","A-Tab":"1b5b393b313175","C-Esc":"1b5b32373b3575","protocol":"kitty","A-Space":"1b5b33323b313175","S-Esc":"1b5b32373b3275","Esc":"1b5b323775"},"11xterm":{"Space":"20","version":"1b5b3e34313b3335363b3063","C-Tab":"09","A-Esc":"9b00","status":"","S-C-I":"09","C-I":"09","S-Tab":"1b5b5a","Tab":"09","S-Space":"20","A-Tab":"8900","C-Esc":"1b","protocol":"none","A-Space":"a000","S-Esc":"1b","Esc":"1b"}}

src/testdir/keycode_check.vim

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,10 +319,10 @@ def DoTerm(name: string)
319319
ch_logfile('keylog-ignore', 'a')
320320
while 1
321321
sleep 100m
322-
if !getchar(1)
322+
if getchar(1) == 0
323323
break
324324
endif
325-
while getchar(1)
325+
while getchar(1) != 0
326326
getchar()
327327
endwhile
328328
endwhile

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,8 @@ static char *(features[]) =
695695

696696
static int included_patches[] =
697697
{ /* Add new patch number below this line */
698+
/**/
699+
912,
698700
/**/
699701
911,
700702
/**/

0 commit comments

Comments
 (0)