# HG changeset patch # User Bram Moolenaar # Date 1363199368 -3600 # Node ID ecf21be84def6033137d168e0a66500c29aeffec # Parent 34c1a0b257cb2cb9d39bfe62fff54fc7e61cda7e updated for version 7.3.859 Problem: 'ambiwidth' must be set by the user. Solution: Detects East Asian ambiguous width (UAX #11) state of the terminal at the start-up time and 'ambiwidth' accordingly. (Hayaki Saito) diff --git a/src/main.c b/src/main.c --- a/src/main.c +++ b/src/main.c @@ -804,6 +804,9 @@ vim_main2(int argc UNUSED, char **argv U starttermcap(); /* start termcap if not done by wait_return() */ TIME_MSG("start termcap"); +#if defined(FEAT_TERMRESPONSE) && defined(FEAT_MBYTE) + may_req_ambiguous_character_width(); +#endif #ifdef FEAT_MOUSE setmouse(); /* may start using the mouse */ diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -2900,6 +2900,7 @@ static struct vimoption p_term("t_op", T_OP) p_term("t_RI", T_CRI) p_term("t_RV", T_CRV) + p_term("t_u7", T_U7) p_term("t_Sb", T_CSB) p_term("t_Sf", T_CSF) p_term("t_se", T_SE) diff --git a/src/proto/term.pro b/src/proto/term.pro --- a/src/proto/term.pro +++ b/src/proto/term.pro @@ -34,6 +34,7 @@ void settmode __ARGS((int tmode)); void starttermcap __ARGS((void)); void stoptermcap __ARGS((void)); void may_req_termresponse __ARGS((void)); +void may_req_ambiguous_character_width __ARGS((void)); int swapping_screen __ARGS((void)); void setmouse __ARGS((void)); int mouse_has __ARGS((int c)); diff --git a/src/term.c b/src/term.c --- a/src/term.c +++ b/src/term.c @@ -111,6 +111,11 @@ char *tgetstr __ARGS((char *, char **)) # 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; # endif /* @@ -933,6 +938,7 @@ static struct builtin_term builtin_termc {(int)KS_CWP, IF_EB("\033[3;%d;%dt", ESC_STR "[3;%d;%dt")}, # endif {(int)KS_CRV, IF_EB("\033[>c", ESC_STR "[>c")}, + {(int)KS_U7, IF_EB("\033[6n", ESC_STR "[6n")}, {K_UP, IF_EB("\033O*A", ESC_STR "O*A")}, {K_DOWN, IF_EB("\033O*B", ESC_STR "O*B")}, @@ -1221,6 +1227,7 @@ static struct builtin_term builtin_termc {(int)KS_CWP, "[%dCWP%d]"}, # endif {(int)KS_CRV, "[CRV]"}, + {(int)KS_U7, "[U7]"}, {K_UP, "[KU]"}, {K_DOWN, "[KD]"}, {K_LEFT, "[KL]"}, @@ -1596,6 +1603,7 @@ set_termname(term) {KS_TS, "ts"}, {KS_FS, "fs"}, {KS_CWP, "WP"}, {KS_CWS, "WS"}, {KS_CSI, "SI"}, {KS_CEI, "EI"}, + {KS_U7, "u7"}, {(enum SpecialKey)0, NULL} }; @@ -3183,7 +3191,8 @@ settmode(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) + if (tmode != TMODE_RAW && (crv_status == CRV_SENT + || u7_status == U7_SENT)) (void)vpeekc_nomap(); check_for_codes_from_term(); } @@ -3245,7 +3254,7 @@ stoptermcap() # endif { /* May need to check for T_CRV response. */ - if (crv_status == CRV_SENT) + if (crv_status == CRV_SENT || u7_status == U7_SENT) (void)vpeekc_nomap(); /* Check for termcodes first, otherwise an external program may * get them. */ @@ -3299,6 +3308,48 @@ may_req_termresponse() (void)vpeekc_nomap(); } } + +# 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 + * \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). + * This function has the side effect that changes cursor position, so + * it must be called immediately after entering termcap mode. + */ + void +may_req_ambiguous_character_width() +{ + if (u7_status == U7_GET + && cur_tmode == TMODE_RAW + && termcap_active + && p_ek +# ifdef UNIX + && isatty(1) + && isatty(read_cmd_fd) +# endif + && *T_U7 != NUL + && !option_was_set((char_u *)"ambiwidth")) + { + char_u buf[16]; + + term_windgoto(0, 0); + buf[mb_char2bytes(0x25bd, buf)] = 0; + out_str(buf); + out_str(T_U7); + u7_status = U7_SENT; + term_windgoto(0, 0); + out_str((char_u *)" "); + term_windgoto(0, 0); + /* check for the characters now, otherwise they might be eaten by + * get_keystroke() */ + out_flush(); + (void)vpeekc_nomap(); + } +} +# endif #endif /* @@ -4049,13 +4100,22 @@ check_termcode(max_offset, buf, bufsize, /* URXVT mouse uses [#;#;#M, but we are matching [ */ || key_name[0] == KS_URXVT_MOUSE) { - /* Check for xterm version string: "[>{x};{vers};{y}c". Also - * eat other possible responses to t_RV, rxvt returns - * "[?1;2c". Also accept CSI instead of [. - * mrxvt has been reported to have "+" in the version. Assume - * the escape sequence ends with a letter or one of "{|}~". */ - if (*T_CRV != NUL && ((tp[0] == ESC && tp[1] == '[' && len >= 3) - || (tp[0] == CSI && len >= 2))) + /* Check for some responses from terminal start with "[" or + * CSI. + * + * - xterm version string: [>{x};{vers};{y}c + * Also eat other possible responses to t_RV, rxvt returns + * "[?1;2c". Also accept CSI instead of [. + * mrxvt has been reported to have "+" in the version. Assume + * the escape sequence ends with a letter or one of "{|}~". + * + * - cursor position report: [{row};{col}R + * The final byte is 'R'. now it is only used for checking for + * ambiguous-width character state. + */ + if ((*T_CRV != NUL || *T_U7 != NUL) + && ((tp[0] == ESC && tp[1] == '[' && len >= 3) + || (tp[0] == CSI && len >= 2))) { j = 0; extra = 0; @@ -4067,8 +4127,27 @@ check_termcode(max_offset, buf, bufsize, if (i == len) return -1; /* not enough characters */ +#ifdef FEAT_MBYTE + /* eat it when it has 2 arguments and ends in 'R' */ + if (u7_status == U7_SENT && j == 1 && tp[i] == 'R') + { + char *p = NULL; + + u7_status = U7_GOT; + if (extra == 2) + p = "single"; + else if (extra == 3) + p = "double"; + if (p != NULL) + set_option_value((char_u *)"ambw", 0L, (char_u *)p, 0); + key_name[0] = (int)KS_EXTRA; + key_name[1] = (int)KE_IGNORE; + slen = i + 1; + } + else +#endif /* eat it when at least one digit and ending in 'c' */ - if (i > 2 + (tp[0] != CSI) && tp[i] == 'c') + if (*T_CRV != NUL && i > 2 + (tp[0] != CSI) && tp[i] == 'c') { crv_status = CRV_GOT; diff --git a/src/term.h b/src/term.h --- a/src/term.h +++ b/src/term.h @@ -83,10 +83,11 @@ enum SpecialKey #ifdef FEAT_VERTSPLIT KS_CSV, /* scroll region vertical */ #endif - KS_OP /* original color pair */ + KS_OP, /* original color pair */ + KS_U7 /* request cursor position */ }; -#define KS_LAST KS_OP +#define KS_LAST KS_U7 /* * the terminal capabilities are stored in this array @@ -158,6 +159,7 @@ extern char_u *(term_strings[]); /* c #define T_CEI (term_str(KS_CEI)) /* end insert mode */ #define T_CRV (term_str(KS_CRV)) /* request version string */ #define T_OP (term_str(KS_OP)) /* original color pair */ +#define T_U7 (term_str(KS_U7)) /* request cursor position */ #define TMODE_COOK 0 /* terminal mode for external cmds and Ex mode */ #define TMODE_SLEEP 1 /* terminal mode for sleeping (cooked but no echo) */ 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 */ /**/ + 859, +/**/ 858, /**/ 857,