# HG changeset patch # User Bram Moolenaar # Date 1372848331 -7200 # Node ID 8b7baf39a345aecf00a6116b5da211b51c6e3457 # Parent 941318315acee2d9840fb4e4776035678a510b60 updated for version 7.3.1288 Problem: The first ":echo 'hello'" command output doesn't show. Mapping for gets triggered during startup. Solution: Add debugging code for the termresponse. When receiving the "Co" entry and when setting 'ambiwidth' redraw right away if possible. Add redraw_asap(). Don't set 'ambiwidth' if it already had the right value. Do the 'ambiwidth' check in the second row to avoid confusion with . diff --git a/src/proto/screen.pro b/src/proto/screen.pro --- a/src/proto/screen.pro +++ b/src/proto/screen.pro @@ -5,6 +5,7 @@ void redraw_later_clear __ARGS((void)); void redraw_all_later __ARGS((int type)); void redraw_curbuf_later __ARGS((int type)); void redraw_buf_later __ARGS((buf_T *buf, int type)); +int redraw_asap __ARGS((int type)); void redrawWinline __ARGS((linenr_T lnum, int invalid)); void update_curbuf __ARGS((int type)); void update_screen __ARGS((int type)); diff --git a/src/screen.c b/src/screen.c --- a/src/screen.c +++ b/src/screen.c @@ -268,6 +268,147 @@ redraw_buf_later(buf, type) } /* + * Redraw as soon as possible. When the command line is not scrolled redraw + * right away and restore what was on the command line. + * Return a code indicating what happened. + */ + int +redraw_asap(type) + int type; +{ + int rows; + int r; + int ret = 0; + schar_T *screenline; /* copy from ScreenLines[] */ + sattr_T *screenattr; /* copy from ScreenAttrs[] */ +#ifdef FEAT_MBYTE + int i; + u8char_T *screenlineUC; /* copy from ScreenLinesUC[] */ + u8char_T *screenlineC[MAX_MCO]; /* copy from ScreenLinesC[][] */ + schar_T *screenline2; /* copy from ScreenLines2[] */ +#endif + + redraw_later(type); + if (msg_scrolled || (State != NORMAL && State != NORMAL_BUSY)) + return ret; + + /* Allocate space to save the text displayed in the command line area. */ + rows = Rows - cmdline_row; + screenline = (schar_T *)lalloc( + (long_u)(rows * Columns * sizeof(schar_T)), FALSE); + screenattr = (sattr_T *)lalloc( + (long_u)(rows * Columns * sizeof(sattr_T)), FALSE); + if (screenline == NULL || screenattr == NULL) + ret = 2; +#ifdef FEAT_MBYTE + if (enc_utf8) + { + screenlineUC = (u8char_T *)lalloc( + (long_u)(rows * Columns * sizeof(u8char_T)), FALSE); + if (screenlineUC == NULL) + ret = 2; + for (i = 0; i < p_mco; ++i) + { + screenlineC[i] = (u8char_T *)lalloc( + (long_u)(rows * Columns * sizeof(u8char_T)), FALSE); + if (screenlineC[i] == NULL) + ret = 2; + } + } + if (enc_dbcs == DBCS_JPNU) + { + screenline2 = (schar_T *)lalloc( + (long_u)(rows * Columns * sizeof(schar_T)), FALSE); + if (screenline2 == NULL) + ret = 2; + } +#endif + + if (ret != 2) + { + /* Save the text displayed in the command line area. */ + for (r = 0; r < rows; ++r) + { + mch_memmove(screenline + r * Columns, + ScreenLines + LineOffset[cmdline_row + r], + (size_t)Columns * sizeof(schar_T)); + mch_memmove(screenattr + r * Columns, + ScreenAttrs + LineOffset[cmdline_row + r], + (size_t)Columns * sizeof(sattr_T)); +#ifdef FEAT_MBYTE + if (enc_utf8) + { + mch_memmove(screenlineUC + r * Columns, + ScreenLinesUC + LineOffset[cmdline_row + r], + (size_t)Columns * sizeof(u8char_T)); + for (i = 0; i < p_mco; ++i) + mch_memmove(screenlineC[i] + r * Columns, + ScreenLinesC[r] + LineOffset[cmdline_row + r], + (size_t)Columns * sizeof(u8char_T)); + } + if (enc_dbcs == DBCS_JPNU) + mch_memmove(screenline2 + r * Columns, + ScreenLines2 + LineOffset[cmdline_row + r], + (size_t)Columns * sizeof(schar_T)); +#endif + } + + update_screen(0); + ret = 3; + + if (must_redraw == 0) + { + int off = (int)(current_ScreenLine - ScreenLines); + + /* Restore the text displayed in the command line area. */ + for (r = 0; r < rows; ++r) + { + mch_memmove(current_ScreenLine, + screenline + r * Columns, + (size_t)Columns * sizeof(schar_T)); + mch_memmove(ScreenAttrs + off, + screenattr + r * Columns, + (size_t)Columns * sizeof(sattr_T)); +#ifdef FEAT_MBYTE + if (enc_utf8) + { + mch_memmove(ScreenLinesUC + off, + screenlineUC + r * Columns, + (size_t)Columns * sizeof(u8char_T)); + for (i = 0; i < p_mco; ++i) + mch_memmove(ScreenLinesC[i] + off, + screenlineC[i] + r * Columns, + (size_t)Columns * sizeof(u8char_T)); + } + if (enc_dbcs == DBCS_JPNU) + mch_memmove(ScreenLines2 + off, + screenline2 + r * Columns, + (size_t)Columns * sizeof(schar_T)); +#endif + SCREEN_LINE(cmdline_row + r, 0, Columns, Columns, FALSE); + } + ret = 4; + } + setcursor(); + } + + vim_free(screenline); + vim_free(screenattr); +#ifdef FEAT_MBYTE + if (enc_utf8) + { + vim_free(screenlineUC); + for (i = 0; i < p_mco; ++i) + vim_free(screenlineC[i]); + } + if (enc_dbcs == DBCS_JPNU) + vim_free(screenline2); +#endif + + return ret; +} + +/* * Changed something in the current window, at buffer line "lnum", that * requires that line and possibly other lines to be redrawn. * Used when entering/leaving Insert mode with the cursor on a folded line. diff --git a/src/term.c b/src/term.c --- a/src/term.c +++ b/src/term.c @@ -106,6 +106,14 @@ static char_u *tgetent_error __ARGS((cha char *tgetstr __ARGS((char *, char **)); # ifdef FEAT_TERMRESPONSE + /* Change this to "if 1" to debug what happens with termresponse. */ +# if 0 +# define DEBUG_TERMRESPONSE + static void log_tr(char *msg); +# define LOG_TR(msg) log_tr(msg) +# 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 */ @@ -1936,6 +1944,7 @@ set_termname(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 */ #endif @@ -3326,6 +3335,7 @@ may_req_termresponse() # endif && *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 @@ -3338,10 +3348,10 @@ may_req_termresponse() # if defined(FEAT_MBYTE) || defined(PROTO) /* * Check how the terminal treats ambiguous character width (UAX #11). - * First, we move the cursor to (0, 0) and print a test ambiguous character + * First, we move the cursor to (1, 0) and print a test ambiguous character * \u25bd (WHITE DOWN-POINTING TRIANGLE) and query current cursor position. - * If the terminal treats \u25bd as single width, the position is (0, 1), - * or if it is treated as double width, that will be (0, 2). + * If the terminal treats \u25bd as single width, the position is (1, 1), + * or if it is treated as double width, that will be (1, 2). * This function has the side effect that changes cursor position, so * it must be called immediately after entering termcap mode. */ @@ -3361,7 +3371,10 @@ may_req_ambiguous_character_width() { char_u buf[16]; - term_windgoto(0, 0); + LOG_TR("Sending U7 request"); + /* Do this in the second row. In the first row the returned sequence + * may be CSI 1;2R, which is the same as . */ + term_windgoto(1, 0); buf[mb_char2bytes(0x25bd, buf)] = 0; out_str(buf); out_str(T_U7); @@ -3376,6 +3389,29 @@ may_req_ambiguous_character_width() } } # endif + +# ifdef DEBUG_TERMRESPONSE + static void +log_tr(char *msg) +{ + static FILE *fd_tr = NULL; + static proftime_T start; + proftime_T now; + + if (fd_tr == NULL) + { + fd_tr = fopen("termresponse.log", "w"); + profile_start(&start); + } + now = start; + profile_end(&now); + fprintf(fd_tr, "%s: %s %s\n", + profile_msg(&now), + must_redraw == NOT_VALID ? "NV" + : must_redraw == CLEAR ? "CL" : " ", + msg); +} +# endif #endif /* @@ -3847,6 +3883,7 @@ switch_to_8bit() need_gather = TRUE; /* need to fill termleader[] */ } detected_8bit = TRUE; + LOG_TR("Switching to 8 bit"); } #endif @@ -4156,14 +4193,20 @@ check_termcode(max_offset, buf, bufsize, if (tp[i] == ';' && ++j == 1) extra = i + 1; if (i == len) - return -1; /* not enough characters */ + { + LOG_TR("Not enough characters for CRV"); + return -1; + } #ifdef FEAT_MBYTE - /* eat it when it has 2 arguments and ends in 'R' */ - if (j == 1 && tp[i] == 'R') + /* Eat it when it has 2 arguments and ends in 'R'. Ignore it + * when u7_status is not "sent", sends something + * similar. */ + if (j == 1 && tp[i] == 'R' && u7_status == U7_SENT) { char *aw = NULL; + LOG_TR("Received U7 status"); u7_status = U7_GOT; # ifdef FEAT_AUTOCMD did_cursorhold = TRUE; @@ -4174,8 +4217,24 @@ check_termcode(max_offset, buf, bufsize, aw = "single"; else if (extra == 3) aw = "double"; - if (aw != NULL) + if (aw != NULL && STRCMP(aw, p_ambw) != 0) + { + /* Setting the option causes a screen redraw. Do that + * right away if possible, keeping any messages. */ set_option_value((char_u *)"ambw", 0L, (char_u *)aw, 0); +#ifdef DEBUG_TERMRESPONSE + { + char buf[100]; + int r = redraw_asap(CLEAR); + + sprintf(buf, "set 'ambiwidth', redraw_asap(): %d", + r); + log_tr(buf); + } +#else + redraw_asap(CLEAR); +#endif + } key_name[0] = (int)KS_EXTRA; key_name[1] = (int)KE_IGNORE; slen = i + 1; @@ -4185,6 +4244,7 @@ check_termcode(max_offset, buf, bufsize, /* 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; @@ -4224,6 +4284,7 @@ check_termcode(max_offset, buf, bufsize, /* if xterm version >= 141 try to get termcap codes */ if (extra >= 141) { + LOG_TR("Enable checking for XT codes"); check_for_codes = TRUE; need_gather = TRUE; req_codes_from_term(); @@ -4262,7 +4323,10 @@ check_termcode(max_offset, buf, bufsize, } if (i == len) + { + LOG_TR("not enough characters for XT"); return -1; /* not enough characters */ + } } } #endif @@ -5207,6 +5271,10 @@ check_termcode(max_offset, buf, bufsize, return retval == 0 ? (len + extra + offset) : retval; } +#ifdef FEAT_TERMRESPONSE + LOG_TR("normal character"); +#endif + return 0; /* no match found */ } @@ -5661,6 +5729,13 @@ req_more_codes_from_term() * many, there can be a buffer overflow somewhere. */ while (xt_index_out < xt_index_in + 10 && key_names[xt_index_out] != NULL) { +# ifdef DEBUG_TERMRESPONSE + char dbuf[100]; + + sprintf(dbuf, "Requesting XT %d: %s", + xt_index_out, key_names[xt_index_out]); + log_tr(dbuf); +# endif sprintf(buf, "\033P+q%02x%02x\033\\", key_names[xt_index_out][0], key_names[xt_index_out][1]); out_str_nf((char_u *)buf); @@ -5707,6 +5782,14 @@ got_code_from_term(code, len) break; } } +# ifdef DEBUG_TERMRESPONSE + { + char buf[100]; + + sprintf(buf, "Received XT %d: %s", xt_index_in, (char *)name); + log_tr(buf); + } +# endif if (key_names[i] != NULL) { for (i = 8; (c = hexhex2nr(code + i)) >= 0; i += 2) @@ -5725,7 +5808,17 @@ got_code_from_term(code, len) set_keep_msg_from_hist(); set_color_count(i); init_highlight(TRUE, FALSE); - redraw_later(CLEAR); +#ifdef DEBUG_TERMRESPONSE + { + char buf[100]; + int r = redraw_asap(CLEAR); + + sprintf(buf, "Received t_Co, redraw_asap(): %d", r); + log_tr(buf); + } +#else + redraw_asap(CLEAR); +#endif } } else diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -729,6 +729,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1288, +/**/ 1287, /**/ 1286,