# HG changeset patch # User Christian Brabandt # Date 1503164704 -7200 # Node ID 1345621ecdfbba90112c896fba8b2662005e458d # Parent 28f606bb906cdb1c56df7d27fb56d285134ee5d5 patch 8.0.0965: not restoring cursor shape after it was set in a terminal commit https://github.com/vim/vim/commit/3eee06e7d4c3a8e2dbb2577a1eef0e0f108e0288 Author: Bram Moolenaar Date: Sat Aug 19 19:40:50 2017 +0200 patch 8.0.0965: not restoring cursor shape after it was set in a terminal Problem: The cursor shape is not reset after it was changed in a terminal. Solution: Request the original cursor shape and restore it. Add t_RS. Do not add t_SH for now, it does not work properly. diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -3179,6 +3179,7 @@ static struct vimoption options[] = p_term("t_SC", T_CSC) p_term("t_EC", T_CEC) p_term("t_SH", T_CSH) + p_term("t_RS", T_CRS) p_term("t_IS", T_CIS) p_term("t_ke", T_KE) p_term("t_ks", T_KS) diff --git a/src/term.c b/src/term.c --- a/src/term.c +++ b/src/term.c @@ -114,21 +114,22 @@ char *tgetstr(char *, char **); # else # define LOG_TR(msg) # endif + +# define STATUS_GET 1 /* send request when switching to RAW mode */ +# define STATUS_SENT 2 /* did send request, waiting for response */ +# define STATUS_GOT 3 /* received response */ + /* Request Terminal Version status: */ -# define CRV_GET 1 /* send T_CRV when switched to RAW mode */ -# define CRV_SENT 2 /* did send T_CRV, waiting for answer */ -# define CRV_GOT 3 /* received T_CRV response */ -static int crv_status = CRV_GET; +static int crv_status = STATUS_GET; + /* Request Cursor position report: */ -# define U7_GET 1 /* send T_U7 when switched to RAW mode */ -# define U7_SENT 2 /* did send T_U7, waiting for answer */ -# define U7_GOT 3 /* received T_U7 response */ -static int u7_status = U7_GET; +static int u7_status = STATUS_GET; + /* Request background color report: */ -# define RBG_GET 1 /* send T_RBG when switched to RAW mode */ -# define RBG_SENT 2 /* did send T_RBG, waiting for answer */ -# define RBG_GOT 3 /* received T_RBG response */ -static int rbg_status = RBG_GET; +static int rbg_status = STATUS_GET; + +/* Request cursor mode report: */ +static int rcm_status = STATUS_GET; # endif /* @@ -160,6 +161,12 @@ static char_u *vim_tgetstr(char *s, char static int detected_8bit = FALSE; /* detected 8-bit terminal */ +/* When the cursor shape was detected these values are used: + * 1: block, 2: underline, 3: vertical bar + * initial_cursor_blink is only valid when initial_cursor_shape is not zero. */ +static int initial_cursor_shape = 0; +static int initial_cursor_blink = FALSE; + static struct builtin_term builtin_termcaps[] = { @@ -820,11 +827,16 @@ static struct builtin_term builtin_termc {(int)KS_VI, IF_EB("\033[?25l", ESC_STR "[?25l")}, {(int)KS_VE, IF_EB("\033[?25h", ESC_STR "[?25h")}, {(int)KS_VS, IF_EB("\033[?12h", ESC_STR "[?12h")}, +#if 0 + /* This is currently disabled, because we cannot reliably restore the + * cursor because of what appears to be an xterm bug. */ # ifdef TERMINFO {(int)KS_CSH, IF_EB("\033[%p1%d q", ESC_STR "[%p1%d q")}, # else {(int)KS_CSH, IF_EB("\033[%d q", ESC_STR "[%d q")}, # endif +#endif + {(int)KS_CRS, IF_EB("\033P$q q\033\\", ESC_STR "P$q q" ESC_STR "\\")}, # ifdef TERMINFO {(int)KS_CM, IF_EB("\033[%i%p1%d;%p2%dH", ESC_STR "[%i%p1%d;%p2%dH")}, @@ -1803,9 +1815,9 @@ set_termname(char_u *term) * is being used. * Don't do this when the GUI is active, it uses "t_kb" and "t_kD" directly. */ -#ifdef FEAT_GUI +# ifdef FEAT_GUI if (!gui.in_use) -#endif +# endif get_stty(); #endif @@ -1906,8 +1918,8 @@ set_termname(char_u *term) full_screen = TRUE; /* we can use termcap codes from now on */ set_term_defaults(); /* use current values as defaults */ #ifdef FEAT_TERMRESPONSE - LOG_TR("setting crv_status to CRV_GET"); - crv_status = CRV_GET; /* Get terminal version later */ + LOG_TR("setting crv_status to STATUS_GET"); + crv_status = STATUS_GET; /* Get terminal version later */ #endif /* @@ -3298,9 +3310,10 @@ settmode(int tmode) /* May need to check for T_CRV response and termcodes, it * doesn't work in Cooked mode, an external program may get * them. */ - if (tmode != TMODE_RAW && (crv_status == CRV_SENT - || u7_status == U7_SENT - || rbg_status == RBG_SENT)) + if (tmode != TMODE_RAW && (crv_status == STATUS_SENT + || u7_status == STATUS_SENT + || rbg_status == STATUS_SENT + || rcm_status == STATUS_SENT)) (void)vpeekc_nomap(); check_for_codes_from_term(); } @@ -3347,7 +3360,7 @@ starttermcap(void) may_req_termresponse(); /* Immediately check for a response. If t_Co changes, we don't * want to redraw with wrong colors first. */ - if (crv_status == CRV_SENT) + if (crv_status == STATUS_SENT) check_for_codes_from_term(); } #endif @@ -3367,8 +3380,10 @@ stoptermcap(void) # endif { /* May need to discard T_CRV, T_U7 or T_RBG response. */ - if (crv_status == CRV_SENT || u7_status == U7_SENT - || rbg_status == RBG_SENT) + if (crv_status == STATUS_SENT + || u7_status == STATUS_SENT + || rbg_status == STATUS_SENT + || rcm_status == STATUS_SENT) { # ifdef UNIX /* Give the terminal a chance to respond. */ @@ -3414,14 +3429,14 @@ stoptermcap(void) void may_req_termresponse(void) { - if (crv_status == CRV_GET + if (crv_status == STATUS_GET && can_get_termresponse() && starting == 0 && *T_CRV != NUL) { - LOG_TR("Sending CRV"); + LOG_TR("Sending CRV request"); out_str(T_CRV); - crv_status = CRV_SENT; + crv_status = STATUS_SENT; /* check for the characters now, otherwise they might be eaten by * get_keystroke() */ out_flush(); @@ -3442,7 +3457,7 @@ may_req_termresponse(void) void may_req_ambiguous_char_width(void) { - if (u7_status == U7_GET + if (u7_status == STATUS_GET && can_get_termresponse() && starting == 0 && *T_U7 != NUL @@ -3457,7 +3472,7 @@ may_req_ambiguous_char_width(void) buf[mb_char2bytes(0x25bd, buf)] = 0; out_str(buf); out_str(T_U7); - u7_status = U7_SENT; + u7_status = STATUS_SENT; out_flush(); /* This overwrites a few characters on the screen, a redraw is needed @@ -3477,19 +3492,40 @@ may_req_ambiguous_char_width(void) /* * Similar to requesting the version string: Request the terminal background * color when it is the right moment. + * Also request the cursor shape, if possible. */ void may_req_bg_color(void) { - if (rbg_status == RBG_GET - && can_get_termresponse() - && starting == 0 - && *T_RBG != NUL - && !option_was_set((char_u *)"bg")) + int done = FALSE; + + if (can_get_termresponse() && starting == 0) { - LOG_TR("Sending BG request"); - out_str(T_RBG); - rbg_status = RBG_SENT; + /* Only request background if t_RB is set and 'background' wasn't + * changed. */ + if (rbg_status == STATUS_GET + && *T_RBG != NUL + && !option_was_set((char_u *)"bg")) + { + LOG_TR("Sending BG request"); + out_str(T_RBG); + rbg_status = STATUS_SENT; + done = TRUE; + } + + /* Only request the cursor shape if t_SH and t_RS are set. */ + if (rcm_status == STATUS_GET + && *T_CSH != NUL + && *T_CRS != NUL) + { + LOG_TR("Sending cursor shape request"); + out_str(T_CRS); + rcm_status = STATUS_SENT; + done = TRUE; + } + } + if (done) + { /* check for the characters now, otherwise they might be eaten by * get_keystroke() */ out_flush(); @@ -3676,7 +3712,12 @@ term_cursor_mode(int forced) /* Only do something when redrawing the screen and we can restore the * mode. */ if (!full_screen || *T_CEI == NUL) + { + if (forced && initial_cursor_shape > 0) + /* Restore to initial values. */ + term_cursor_shape(initial_cursor_shape, initial_cursor_blink); return; + } if ((State & REPLACE) == REPLACE) { @@ -4290,7 +4331,8 @@ check_termcode( { /* Skip over the digits, the final char must * follow. */ - for (j = slen - 2; j < len && (isdigit(tp[j]) || tp[j] == ';'); ++j) + for (j = slen - 2; j < len && (isdigit(tp[j]) + || tp[j] == ';'); ++j) ; ++j; if (len < j) /* got a partial sequence */ @@ -4394,7 +4436,7 @@ check_termcode( char *aw = NULL; LOG_TR("Received U7 status"); - u7_status = U7_GOT; + u7_status = STATUS_GOT; # ifdef FEAT_AUTOCMD did_cursorhold = TRUE; # endif @@ -4433,8 +4475,8 @@ check_termcode( /* eat it when at least one digit and ending in 'c' */ if (*T_CRV != NUL && i > 2 + (tp[0] != CSI) && tp[i] == 'c') { - LOG_TR("Received CRV"); - crv_status = CRV_GOT; + LOG_TR("Received CRV response"); + crv_status = STATUS_GOT; # ifdef FEAT_AUTOCMD did_cursorhold = TRUE; # endif @@ -4566,8 +4608,8 @@ check_termcode( char *newval = (3 * '6' < tp[j+7] + tp[j+12] + tp[j+17]) ? "light" : "dark"; - LOG_TR("Received RBG"); - rbg_status = RBG_GOT; + LOG_TR("Received RBG response"); + rbg_status = STATUS_GOT; if (STRCMP(p_bg, newval) != 0) { /* value differs, apply it */ @@ -4592,24 +4634,33 @@ check_termcode( } /* Check for key code response from xterm: - * * {lead}{flag}+r<{tail} * * {lead} can be P or DCS * {flag} can be '0' or '1' * {tail} can be Esc>\ or STERM * - * Consume any code that starts with "{lead}.+r". + * Check for cursor shape response from xterm: + * {lead}1$r q{tail} + * + * {lead} can be P or DCS + * {tail} can be Esc>\ or STERM + * + * Consume any code that starts with "{lead}.+r" or "{lead}.$r". */ - else if (check_for_codes + else if ((check_for_codes || rcm_status == STATUS_SENT) && ((tp[0] == ESC && len >= 2 && tp[1] == 'P') || tp[0] == DCS)) { j = 1 + (tp[0] == ESC); - if (len >= j + 3 && (argp[1] != '+' || argp[2] != 'r')) + if (len < j + 3) + i = len; /* need more chars */ + else if ((argp[1] != '+' && argp[1] != '$') || argp[2] != 'r') i = 0; /* no match */ - else + else if (argp[1] == '+') + /* key code response */ for (i = j; i < len; ++i) + { if ((tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\') || tp[i] == STERM) { @@ -4620,6 +4671,32 @@ check_termcode( slen = i + 1 + (tp[i] == ESC); break; } + } + else if ((len >= j + 6 && isdigit(argp[3])) + && argp[4] == ' ' + && argp[5] == 'q') + { + /* cursor shape response */ + i = j + 6; + if ((tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\') + || tp[i] == STERM) + { + int number = argp[3] - '0'; + + /* 0, 1 = block blink, 2 = block + * 3 = underline blink, 4 = underline + * 5 = vertical bar blink, 6 = vertical bar */ + number = number == 0 ? 1 : number; + initial_cursor_shape = (number + 1) / 2; + initial_cursor_blink = (number & 1) ? TRUE : FALSE; + rcm_status = STATUS_GOT; + LOG_TR("Received cursor shape response"); + + key_name[0] = (int)KS_EXTRA; + key_name[1] = (int)KE_IGNORE; + slen = i + 1 + (tp[i] == ESC); + } + } if (i == len) { @@ -5837,7 +5914,7 @@ gather_termleader(void) termleader[len++] = CSI; /* the GUI codes are not in termcodes[] */ #endif #ifdef FEAT_TERMRESPONSE - if (check_for_codes) + if (check_for_codes || *T_CRS != NUL) termleader[len++] = DCS; /* the termcode response starts with DCS in 8-bit mode */ #endif diff --git a/src/term.h b/src/term.h --- a/src/term.h +++ b/src/term.h @@ -41,6 +41,7 @@ enum SpecialKey KS_VE, /* cursor visible */ KS_VS, /* cursor very visible */ KS_CSH, /* cursor shape */ + KS_CRS, /* request cursor shape */ KS_ME, /* normal mode */ KS_MR, /* reverse mode */ KS_MD, /* bold mode */ @@ -132,6 +133,7 @@ extern char_u *(term_strings[]); /* c #define T_VE (TERM_STR(KS_VE)) /* cursor visible */ #define T_VS (TERM_STR(KS_VS)) /* cursor very visible */ #define T_CSH (TERM_STR(KS_CSH)) /* cursor shape */ +#define T_CRS (TERM_STR(KS_CRS)) /* request cursor shape */ #define T_ME (TERM_STR(KS_ME)) /* normal mode */ #define T_MR (TERM_STR(KS_MR)) /* reverse mode */ #define T_MD (TERM_STR(KS_MD)) /* bold mode */ diff --git a/src/terminal.c b/src/terminal.c --- a/src/terminal.c +++ b/src/terminal.c @@ -38,6 +38,7 @@ * in tl_scrollback are no longer used. * * TODO: + * - help index for winptydll, optwin entry for winptydll * - make [range]terminal pipe [range] lines to the terminal * - implement term_setsize() * - add test for giving error for invalid 'termsize' value. @@ -1287,9 +1288,10 @@ may_restore_cursor_props(void) if (did_change_cursor) { did_change_cursor = FALSE; - ui_cursor_shape_forced(TRUE); term_cursor_color((char_u *)""); term_cursor_blink(FALSE); + /* this will restore the initial cursor style, if possible */ + ui_cursor_shape_forced(TRUE); } } diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -770,6 +770,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 965, +/**/ 964, /**/ 963,