changeset 5090:8b7baf39a345 v7.3.1288

updated for version 7.3.1288 Problem: The first ":echo 'hello'" command output doesn't show. Mapping for <S-F3> 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 <S-F3>.
author Bram Moolenaar <bram@vim.org>
date Wed, 03 Jul 2013 12:45:31 +0200
parents 941318315ace
children 310b766002fe
files src/proto/screen.pro src/screen.c src/term.c src/version.c
diffstat 4 files changed, 246 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- 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));
--- 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.
--- 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 <S-F3>. */
+	 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", <S-F3> 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
--- 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,