To: vim_dev@googlegroups.com Subject: Patch 8.0.0965 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.0.0965 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. Files: src/term.c, src/term.h, src/option.c, src/terminal.c *** ../vim-8.0.0964/src/term.c 2017-08-12 20:11:49.756048579 +0200 --- src/term.c 2017-08-19 19:35:22.271098641 +0200 *************** *** 114,134 **** # else # define LOG_TR(msg) # endif /* 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; /* 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; /* 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; # endif /* --- 114,135 ---- # 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: */ ! static int crv_status = STATUS_GET; ! /* Request Cursor position report: */ ! static int u7_status = STATUS_GET; ! /* Request background color report: */ ! static int rbg_status = STATUS_GET; ! ! /* Request cursor mode report: */ ! static int rcm_status = STATUS_GET; # endif /* *************** *** 160,165 **** --- 161,172 ---- 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,830 **** --- 827,842 ---- {(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,1811 **** * is being used. * Don't do this when the GUI is active, it uses "t_kb" and "t_kD" directly. */ ! #ifdef FEAT_GUI if (!gui.in_use) ! #endif get_stty(); #endif --- 1815,1823 ---- * is being used. * Don't do this when the GUI is active, it uses "t_kb" and "t_kD" directly. */ ! # ifdef FEAT_GUI if (!gui.in_use) ! # endif get_stty(); #endif *************** *** 1906,1913 **** 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 */ #endif /* --- 1918,1925 ---- 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 STATUS_GET"); ! crv_status = STATUS_GET; /* Get terminal version later */ #endif /* *************** *** 3298,3306 **** /* 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)) (void)vpeekc_nomap(); check_for_codes_from_term(); } --- 3310,3319 ---- /* 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 == STATUS_SENT ! || u7_status == STATUS_SENT ! || rbg_status == STATUS_SENT ! || rcm_status == STATUS_SENT)) (void)vpeekc_nomap(); check_for_codes_from_term(); } *************** *** 3347,3353 **** 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) check_for_codes_from_term(); } #endif --- 3360,3366 ---- 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 == STATUS_SENT) check_for_codes_from_term(); } #endif *************** *** 3367,3374 **** # 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) { # ifdef UNIX /* Give the terminal a chance to respond. */ --- 3380,3389 ---- # endif { /* May need to discard T_CRV, T_U7 or T_RBG response. */ ! 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,3427 **** void may_req_termresponse(void) { ! if (crv_status == CRV_GET && can_get_termresponse() && starting == 0 && *T_CRV != NUL) { ! LOG_TR("Sending CRV"); out_str(T_CRV); ! crv_status = CRV_SENT; /* check for the characters now, otherwise they might be eaten by * get_keystroke() */ out_flush(); --- 3429,3442 ---- void may_req_termresponse(void) { ! if (crv_status == STATUS_GET && can_get_termresponse() && starting == 0 && *T_CRV != NUL) { ! LOG_TR("Sending CRV request"); out_str(T_CRV); ! crv_status = STATUS_SENT; /* check for the characters now, otherwise they might be eaten by * get_keystroke() */ out_flush(); *************** *** 3442,3448 **** void may_req_ambiguous_char_width(void) { ! if (u7_status == U7_GET && can_get_termresponse() && starting == 0 && *T_U7 != NUL --- 3457,3463 ---- void may_req_ambiguous_char_width(void) { ! if (u7_status == STATUS_GET && can_get_termresponse() && starting == 0 && *T_U7 != NUL *************** *** 3457,3463 **** buf[mb_char2bytes(0x25bd, buf)] = 0; out_str(buf); out_str(T_U7); ! u7_status = U7_SENT; out_flush(); /* This overwrites a few characters on the screen, a redraw is needed --- 3472,3478 ---- buf[mb_char2bytes(0x25bd, buf)] = 0; out_str(buf); out_str(T_U7); ! u7_status = STATUS_SENT; out_flush(); /* This overwrites a few characters on the screen, a redraw is needed *************** *** 3477,3495 **** /* * Similar to requesting the version string: Request the terminal background * color when it is the right moment. */ 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")) { - LOG_TR("Sending BG request"); - out_str(T_RBG); - rbg_status = RBG_SENT; /* check for the characters now, otherwise they might be eaten by * get_keystroke() */ out_flush(); --- 3492,3531 ---- /* * 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) { ! int done = FALSE; ! ! if (can_get_termresponse() && starting == 0) ! { ! /* 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,3682 **** --- 3712,3723 ---- /* 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,4296 **** { /* Skip over the digits, the final char must * follow. */ ! for (j = slen - 2; j < len && (isdigit(tp[j]) || tp[j] == ';'); ++j) ; ++j; if (len < j) /* got a partial sequence */ --- 4331,4338 ---- { /* Skip over the digits, the final char must * follow. */ ! for (j = slen - 2; j < len && (isdigit(tp[j]) ! || tp[j] == ';'); ++j) ; ++j; if (len < j) /* got a partial sequence */ *************** *** 4394,4400 **** char *aw = NULL; LOG_TR("Received U7 status"); ! u7_status = U7_GOT; # ifdef FEAT_AUTOCMD did_cursorhold = TRUE; # endif --- 4436,4442 ---- char *aw = NULL; LOG_TR("Received U7 status"); ! u7_status = STATUS_GOT; # ifdef FEAT_AUTOCMD did_cursorhold = TRUE; # endif *************** *** 4433,4440 **** /* 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; # ifdef FEAT_AUTOCMD did_cursorhold = TRUE; # endif --- 4475,4482 ---- /* 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 response"); ! crv_status = STATUS_GOT; # ifdef FEAT_AUTOCMD did_cursorhold = TRUE; # endif *************** *** 4566,4573 **** char *newval = (3 * '6' < tp[j+7] + tp[j+12] + tp[j+17]) ? "light" : "dark"; ! LOG_TR("Received RBG"); ! rbg_status = RBG_GOT; if (STRCMP(p_bg, newval) != 0) { /* value differs, apply it */ --- 4608,4615 ---- char *newval = (3 * '6' < tp[j+7] + tp[j+12] + tp[j+17]) ? "light" : "dark"; ! LOG_TR("Received RBG response"); ! rbg_status = STATUS_GOT; if (STRCMP(p_bg, newval) != 0) { /* value differs, apply it */ *************** *** 4592,4615 **** } /* 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". */ ! else if (check_for_codes && ((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')) i = 0; /* no match */ ! else for (i = j; i < len; ++i) if ((tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\') || tp[i] == STERM) { --- 4634,4666 ---- } /* 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 * ! * 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 || rcm_status == STATUS_SENT) && ((tp[0] == ESC && len >= 2 && tp[1] == 'P') || tp[0] == DCS)) { j = 1 + (tp[0] == ESC); ! if (len < j + 3) ! i = len; /* need more chars */ ! else if ((argp[1] != '+' && argp[1] != '$') || argp[2] != 'r') i = 0; /* no match */ ! 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,4625 **** --- 4671,4702 ---- 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,5843 **** termleader[len++] = CSI; /* the GUI codes are not in termcodes[] */ #endif #ifdef FEAT_TERMRESPONSE ! if (check_for_codes) termleader[len++] = DCS; /* the termcode response starts with DCS in 8-bit mode */ #endif --- 5914,5920 ---- termleader[len++] = CSI; /* the GUI codes are not in termcodes[] */ #endif #ifdef FEAT_TERMRESPONSE ! if (check_for_codes || *T_CRS != NUL) termleader[len++] = DCS; /* the termcode response starts with DCS in 8-bit mode */ #endif *** ../vim-8.0.0964/src/term.h 2017-08-12 19:51:37.819214168 +0200 --- src/term.h 2017-08-19 16:42:21.452046735 +0200 *************** *** 41,46 **** --- 41,47 ---- 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,137 **** --- 133,139 ---- #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 */ *** ../vim-8.0.0964/src/option.c 2017-08-17 11:33:37.704130217 +0200 --- src/option.c 2017-08-19 16:10:20.579934355 +0200 *************** *** 3179,3184 **** --- 3179,3185 ---- 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) *** ../vim-8.0.0964/src/terminal.c 2017-08-18 22:57:02.325403165 +0200 --- src/terminal.c 2017-08-19 19:37:05.018443835 +0200 *************** *** 38,43 **** --- 38,44 ---- * 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,1295 **** if (did_change_cursor) { did_change_cursor = FALSE; - ui_cursor_shape_forced(TRUE); term_cursor_color((char_u *)""); term_cursor_blink(FALSE); } } --- 1288,1297 ---- if (did_change_cursor) { did_change_cursor = FALSE; term_cursor_color((char_u *)""); term_cursor_blink(FALSE); + /* this will restore the initial cursor style, if possible */ + ui_cursor_shape_forced(TRUE); } } *** ../vim-8.0.0964/src/version.c 2017-08-19 15:51:55.590771449 +0200 --- src/version.c 2017-08-19 19:36:02.534841990 +0200 *************** *** 771,772 **** --- 771,774 ---- { /* Add new patch number below this line */ + /**/ + 965, /**/ -- ALL: A witch! A witch! WITCH: It's a fair cop. ALL: Burn her! Burn her! Let's make her into a ladder. "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///