To: vim-dev@vim.org Subject: Patch 5.6.061 Fcc: outbox From: Bram Moolenaar ------------ Patch 5.6.061 Problem: When xterm sends 8-bit controls, recognizing the version response doesn't work. When using CSI instead of [ for the termcap color codes, using 16 colors doesn't work. (Neil Bird) Solution: Also accept CSI in place of [ for the version string. Also check for CSI when handling colors 8-15 in term_color(). Use CSI for builtin xterm termcap entries when 'term' contains "8bit". Files: runtime/doc/term.txt, src/ex_cmds.c, src/option.c, src/term.c, src/os_unix.c, src/proto/option.pro, src/proto/term.pro *** ../vim-5.6.60/runtime/doc/term.txt Sun Jan 16 14:13:00 2000 --- runtime/doc/term.txt Fri Apr 7 09:50:58 2000 *************** *** 1,4 **** ! *term.txt* For Vim version 5.6. Last change: 1999 Oct 01 VIM REFERENCE MANUAL by Bram Moolenaar --- 1,4 ---- ! *term.txt* For Vim version 5.6. Last change: 2000 Apr 07 VIM REFERENCE MANUAL by Bram Moolenaar *************** *** 180,185 **** --- 180,196 ---- *VT100.Translations: #override \n\ Home: string("0x1b") string("[7~") \n\ End: string("0x1b") string("[8~") + + *xterm-8bit* + Xterm can be run in a mode where it uses 8bit escape sequences. The CSI ode + is used instead of [. The advantage is that an can quickly be + recognized in Insert mode, because it can't be confused with the start of a + special key. + For the builtin termcap entries, Vim checks if the 'term' option contains + "8bit" anywhere. It then uses 8-bit characters for the termcap entries, the + mouse and a few other things. You would normally set $TERM in your shell to + "xterm-8bit" and Vim picks this up and adjusts to the 8-bit setting + automatically. ============================================================================== 2. Terminal options *terminal-options* *** ../vim-5.6.60/src/ex_cmds.c Tue Apr 4 20:49:34 2000 --- src/ex_cmds.c Wed Apr 5 20:11:52 2000 *************** *** 1791,1797 **** p = find_termcode((char_u *)"kb"); add_termcode((char_u *)"kD", p != NULL && *p == 0x7f ? ! (char_u *)"\010" : (char_u *)"\177"); } void --- 1791,1797 ---- p = find_termcode((char_u *)"kb"); add_termcode((char_u *)"kD", p != NULL && *p == 0x7f ? ! (char_u *)"\010" : (char_u *)"\177", FALSE); } void *** ../vim-5.6.60/src/option.c Fri Mar 31 19:32:38 2000 --- src/option.c Fri Apr 7 10:05:32 2000 *************** *** 2588,2594 **** } nextchar = *p; *p = NUL; ! add_termcode(name, arg); *p = nextchar; } if (full_screen) --- 2592,2598 ---- } nextchar = *p; *p = NUL; ! add_termcode(name, arg, FALSE); *p = nextchar; } if (full_screen) *************** *** 2875,2880 **** --- 2879,2902 ---- { if (p != empty_option) vim_free(p); + } + + /* + * Mark a terminal option as allocated, found by a pointer into term_strings[]. + */ + void + set_term_option_alloced(p) + char_u **p; + { + int opt_idx; + + for (opt_idx = 1; options[opt_idx].fullname != NULL; opt_idx++) + if (options[opt_idx].var == (char_u *)p) + { + options[opt_idx].flags |= P_ALLOCED; + return; + } + return; /* cannot happen: didn't find it! */ } /* *** ../vim-5.6.60/src/term.c Fri Mar 31 14:23:13 2000 --- src/term.c Fri Apr 7 10:05:41 2000 *************** *** 79,85 **** || (defined(USE_MOUSE) && (!defined(UNIX) || defined(XTERM_MOUSE))) static int get_bytes_from_buf __ARGS((char_u *, char_u *, int)); #endif ! static int term_is_builtin __ARGS((char_u *)); #ifdef HAVE_TGETENT static char_u *tgetent_error __ARGS((char_u *, char_u *)); --- 79,86 ---- || (defined(USE_MOUSE) && (!defined(UNIX) || defined(XTERM_MOUSE))) static int get_bytes_from_buf __ARGS((char_u *, char_u *, int)); #endif ! static int term_is_builtin __ARGS((char_u *name)); ! static int term_7to8bit __ARGS((char_u *p)); #ifdef HAVE_TGETENT static char_u *tgetent_error __ARGS((char_u *, char_u *)); *************** *** 1331,1352 **** { struct builtin_term *p; char_u name[2]; p = find_builtin_term(term); for (++p; p->bt_entry != (int)KS_NAME && p->bt_entry != BT_EXTRA_KEYS; ++p) { if ((int)p->bt_entry < 0x100) /* KS_xx entry */ { ! if (term_strings[p->bt_entry] == NULL || ! term_strings[p->bt_entry] == empty_option) ! term_strings[p->bt_entry] = (char_u *)p->bt_string; } else { name[0] = KEY2TERMCAP0((int)p->bt_entry); name[1] = KEY2TERMCAP1((int)p->bt_entry); if (find_termcode(name) == NULL) ! add_termcode(name, (char_u *)p->bt_string); } } } --- 1332,1378 ---- { struct builtin_term *p; char_u name[2]; + int term_8bit; p = find_builtin_term(term); + term_8bit = term_is_8bit(term); + for (++p; p->bt_entry != (int)KS_NAME && p->bt_entry != BT_EXTRA_KEYS; ++p) { if ((int)p->bt_entry < 0x100) /* KS_xx entry */ { ! /* Only set the value if it wasn't set yet. */ ! if (term_strings[p->bt_entry] == NULL ! || term_strings[p->bt_entry] == empty_option) ! { ! /* 8bit terminal: use CSI instead of [ */ ! if (term_8bit && term_7to8bit(p->bt_string) != 0) ! { ! char_u *s, *t; ! ! s = vim_strsave(p->bt_string); ! if (s != NULL) ! { ! for (t = s; *t; ++t) ! if (term_7to8bit(t)) ! { ! *t = term_7to8bit(t); ! STRCPY(t + 1, t + 2); ! } ! term_strings[p->bt_entry] = s; ! set_term_option_alloced(&term_strings[p->bt_entry]); ! } ! } ! else ! term_strings[p->bt_entry] = (char_u *)p->bt_string; ! } } else { name[0] = KEY2TERMCAP0((int)p->bt_entry); name[1] = KEY2TERMCAP1((int)p->bt_entry); if (find_termcode(name) == NULL) ! add_termcode(name, (char_u *)p->bt_string, term_8bit); } } } *************** *** 1477,1483 **** { if (find_termcode((char_u *)key_names[i]) == NULL) add_termcode((char_u *)key_names[i], ! TGETSTR(key_names[i], &tp)); } /* if cursor-left == backspace, ignore it (televideo 925) */ --- 1503,1509 ---- { if (find_termcode((char_u *)key_names[i]) == NULL) add_termcode((char_u *)key_names[i], ! TGETSTR(key_names[i], &tp), FALSE); } /* if cursor-left == backspace, ignore it (televideo 925) */ *************** *** 1485,1491 **** { p = TGETSTR("kl", &tp); if (p != NULL && *p != Ctrl('H')) ! add_termcode((char_u *)"kl", p); } if (height == 0) --- 1511,1517 ---- { p = TGETSTR("kl", &tp); if (p != NULL && *p != Ctrl('H')) ! add_termcode((char_u *)"kl", p, FALSE); } if (height == 0) *************** *** 1678,1687 **** bs_p = find_termcode((char_u *)"kb"); del_p = find_termcode((char_u *)"kD"); if (bs_p == NULL || *bs_p == NUL) ! add_termcode((char_u *)"kb", (bs_p = (char_u *)"\010")); if ((del_p == NULL || *del_p == NUL) && (bs_p == NULL || *bs_p != '\177')) ! add_termcode((char_u *)"kD", (char_u *)"\177"); } #ifdef USE_MOUSE --- 1704,1713 ---- bs_p = find_termcode((char_u *)"kb"); del_p = find_termcode((char_u *)"kD"); if (bs_p == NULL || *bs_p == NUL) ! add_termcode((char_u *)"kb", (bs_p = (char_u *)"\010"), FALSE); if ((del_p == NULL || *del_p == NUL) && (bs_p == NULL || *bs_p != '\177')) ! add_termcode((char_u *)"kD", (char_u *)"\177", FALSE); } #ifdef USE_MOUSE *************** *** 1734,1740 **** name[0] = (int)KS_EXTRA; name[1] = (int)KE_SNIFF; ! add_termcode(name, (char_u *)"\233sniff"); } #endif --- 1760,1766 ---- name[0] = (int)KS_EXTRA; name[1] = (int)KE_SNIFF; ! add_termcode(name, (char_u *)"\233sniff", FALSE); } #endif *************** *** 1851,1857 **** name[0] = n; name[1] = K_FILLER; ! add_termcode(name, s); # ifdef NETTERM_MOUSE if (n == KS_NETTERM_MOUSE) has_mouse_termcode |= HMT_NETTERM; --- 1877,1883 ---- name[0] = n; name[1] = K_FILLER; ! add_termcode(name, s, FALSE); # ifdef NETTERM_MOUSE if (n == KS_NETTERM_MOUSE) has_mouse_termcode |= HMT_NETTERM; *************** *** 2032,2038 **** { if ((int)termp->bt_entry == key) { ! add_termcode(name, (char_u *)termp->bt_string); return OK; } ++termp; --- 2058,2065 ---- { if ((int)termp->bt_entry == key) { ! add_termcode(name, (char_u *)termp->bt_string, ! term_is_8bit(term)); return OK; } ++termp; *************** *** 2051,2057 **** string = TGETSTR((char *)name, &tp); if (string != NULL && *string != NUL) { ! add_termcode(name, string); return OK; } } --- 2078,2084 ---- string = TGETSTR((char *)name, &tp); if (string != NULL && *string != NUL) { ! add_termcode(name, string, FALSE); return OK; } } *************** *** 2078,2083 **** --- 2105,2144 ---- return (STRNCMP(name, "builtin_", (size_t)8) == 0); } + /* + * Return TRUE if terminal "name" uses CSI instead of [. + * Assume that the terminal is using 8-bit controls when the name contains + * "8bit", like in "xterm-8bit". + */ + int + term_is_8bit(name) + char_u *name; + { + return (strstr((char *)name, "8bit") != NULL); + } + + /* + * Translate terminal control chars from 7-bit to 8-bit: + * [ -> CSI + * ] -> + * O -> + */ + static int + term_7to8bit(p) + char_u *p; + { + if (*p == ESC) + { + if (p[1] == '[') + return CSI; + if (p[1] == ']') + return 0x9d; + if (p[1] == 'O') + return 0x8f; + } + return 0; + } + #ifdef USE_GUI int term_is_gui(name) *************** *** 2431,2457 **** char_u *s; int n; { /* Special handling of 16 colors, because termcap can't handle it */ /* Also accept "\e[3%dm" for TERMINFO, it is sometimes used */ if (n > 7 && atoi((char *)T_CCO) == 16 ! && s[0] == ESC && s[1] == '[' && s[2] != NUL ! && (STRCMP(s + 3, "%p1%dm") == 0 || STRCMP(s + 3, "%dm") == 0)) { ! if (s[2] == '3') /* foreground */ { #ifdef TERMINFO ! OUT_STR(tgoto("\033[9%p1%dm", 0, n - 8)); #else ! OUT_STR(tgoto("\033[9%dm", 0, n - 8)); #endif return; } ! if (s[2] == '4') /* background */ { #ifdef TERMINFO ! OUT_STR(tgoto("\033[10%p1%dm", 0, n - 8)); #else ! OUT_STR(tgoto("\033[10%dm", 0, n - 8)); #endif return; } --- 2492,2526 ---- char_u *s; int n; { + int i = 2; /* index in s[] just after [ or CSI */ + /* Special handling of 16 colors, because termcap can't handle it */ /* Also accept "\e[3%dm" for TERMINFO, it is sometimes used */ + /* Also accept CSI instead of [ */ if (n > 7 && atoi((char *)T_CCO) == 16 ! && ((s[0] == ESC && s[1] == '[') || (s[0] == CSI && (i = 1))) ! && s[i] != NUL ! && (STRCMP(s + i + 1, "%p1%dm") == 0 ! || STRCMP(s + i + 1, "%dm") == 0)) { ! if (s[i] == '3') /* foreground */ { #ifdef TERMINFO ! OUT_STR(tgoto(i == 2 ? "\033[9%p1%dm" ! : "\233\071%p1%dm", 0, n - 8)); #else ! OUT_STR(tgoto(i == 2 ? "\033[9%dm" : "\233\071%dm", 0, n - 8)); #endif return; } ! if (s[i] == '4') /* background */ { #ifdef TERMINFO ! OUT_STR(tgoto(i == 2 ? "\033[10%p1%dm" ! : "\233\061\060%p1%dm", 0, n - 8)); #else ! OUT_STR(tgoto(i == 2 ? "\033[10%dm" ! : "\233\061\060%dm", 0, n - 8)); #endif return; } *************** *** 3061,3069 **** * The list is kept alphabetical for ":set termcap" */ void ! add_termcode(name, string) ! char_u *name; ! char_u *string; { struct termcode *new_tc; int i, j; --- 3130,3139 ---- * The list is kept alphabetical for ":set termcap" */ void ! add_termcode(name, string, use_8bit) ! char_u *name; ! char_u *string; ! int use_8bit; /* replace 7-bit control by 8-bit one */ { struct termcode *new_tc; int i, j; *************** *** 3079,3084 **** --- 3149,3161 ---- if (s == NULL) return; + /* Change leading [ to CSI, change O to . */ + if (use_8bit && term_7to8bit(string) != 0) + { + mch_memmove(s, s + 1, STRLEN(s)); + s[0] = term_7to8bit(string); + } + need_gather = TRUE; /* need to fill termleader[] */ /* *************** *** 3369,3390 **** { /* Check for xterm version string: "[>;;c". Also * eat other possible responses to t_RV, rxvt returns ! * "[?1;2c" */ ! if (tp[0] == ESC && tp[1] == '[' && len >= 3 && *T_CRV != NUL) { j = 0; extra = 0; ! for (i = 3; i < len && (isdigit(tp[i]) || tp[i] == ';'); ++i) if (tp[i] == ';' && ++j == 1) extra = atoi((char *)tp + i + 1); if (i == len) return -1; /* not enough characters */ /* eat it when at least one digit and ending in 'c' */ ! if (i > 3 && tp[i] == 'c') { /* If xterm version is >= 95, we can use mouse dragging */ ! if (tp[2] == '>' && j == 2 && extra >= 95) set_option_value((char_u *)"ttymouse", 0L, (char_u *)"xterm2"); key_name[0] = (int)KS_EXTRA; --- 3446,3469 ---- { /* Check for xterm version string: "[>;;c". Also * eat other possible responses to t_RV, rxvt returns ! * "[?1;2c". Also accept CSI instead of [. */ ! if (*T_CRV != NUL && ((tp[0] == ESC && tp[1] == '[' && len >= 3) ! || (tp[0] == CSI && len >= 2))) { j = 0; extra = 0; ! for (i = 2 + (tp[0] != CSI); ! i < len && (isdigit(tp[i]) || tp[i] == ';'); ++i) if (tp[i] == ';' && ++j == 1) extra = atoi((char *)tp + i + 1); if (i == len) return -1; /* not enough characters */ /* eat it when at least one digit and ending in 'c' */ ! if (i > 2 + (tp[0] != CSI) && tp[i] == 'c') { /* If xterm version is >= 95, we can use mouse dragging */ ! if (tp[1 + (tp[0] != CSI)] == '>' && j == 2 && extra >= 95) set_option_value((char_u *)"ttymouse", 0L, (char_u *)"xterm2"); key_name[0] = (int)KS_EXTRA; *** ../vim-5.6.60/src/os_unix.c Thu Mar 30 16:58:04 2000 --- src/os_unix.c Thu Apr 6 21:20:53 2000 *************** *** 1857,1863 **** intr_char = keys.sg_kill; #endif buf[1] = NUL; ! add_termcode((char_u *)"kb", buf); /* * If and are now the same, redefine . --- 1857,1863 ---- intr_char = keys.sg_kill; #endif buf[1] = NUL; ! add_termcode((char_u *)"kb", buf, FALSE); /* * If and are now the same, redefine . *************** *** 1922,1928 **** # ifdef XTERM_MOUSE if (use_xterm_mouse()) { ! set_mouse_termcode(KS_MOUSE, (char_u *)"\033[M"); if (*p_mouse != NUL) { /* force mouse off and maybe on to send possibly new mouse --- 1922,1929 ---- # ifdef XTERM_MOUSE if (use_xterm_mouse()) { ! set_mouse_termcode(KS_MOUSE, (char_u *)(term_is_8bit(T_NAME) ! ? "\233M" : "\033[M")); if (*p_mouse != NUL) { /* force mouse off and maybe on to send possibly new mouse *** ../vim-5.6.60/src/proto/option.pro Sun Jan 16 14:22:48 2000 --- src/proto/option.pro Fri Apr 7 10:05:40 2000 *************** *** 13,18 **** --- 13,19 ---- void check_options __ARGS((void)); void check_buf_options __ARGS((BUF *buf)); void free_string_option __ARGS((char_u *p)); + void set_term_option_alloced __ARGS((char_u **p)); void set_string_option_direct __ARGS((char_u *name, int opt_idx, char_u *val, int dofree)); char_u *check_stl_option __ARGS((char_u *s)); int get_option_value __ARGS((char_u *name, long *numval, char_u **stringval)); *** ../vim-5.6.60/src/proto/term.pro Sun Jan 16 14:23:00 2000 --- src/proto/term.pro Thu Apr 6 21:49:27 2000 *************** *** 4,9 **** --- 4,10 ---- void del_mouse_termcode __ARGS((int n)); void getlinecol __ARGS((void)); int add_termcap_entry __ARGS((char_u *name, int force)); + int term_is_8bit __ARGS((char_u *name)); int term_is_gui __ARGS((char_u *name)); char_u *tltoa __ARGS((unsigned long i)); void termcapinit __ARGS((char_u *name)); *************** *** 39,45 **** void scroll_region_set __ARGS((WIN *wp, int off)); void scroll_region_reset __ARGS((void)); void clear_termcodes __ARGS((void)); ! void add_termcode __ARGS((char_u *name, char_u *string)); char_u *find_termcode __ARGS((char_u *name)); char_u *get_termcode __ARGS((int i)); void del_termcode __ARGS((char_u *name)); --- 40,46 ---- void scroll_region_set __ARGS((WIN *wp, int off)); void scroll_region_reset __ARGS((void)); void clear_termcodes __ARGS((void)); ! void add_termcode __ARGS((char_u *name, char_u *string, int use_8bit)); char_u *find_termcode __ARGS((char_u *name)); char_u *get_termcode __ARGS((int i)); void del_termcode __ARGS((char_u *name)); *** ../vim-5.6.60/src/version.c Wed Apr 5 16:30:51 2000 --- src/version.c Fri Apr 7 09:51:49 2000 *************** *** 420,421 **** --- 420,423 ---- { /* Add new patch number below this line */ + /**/ + 61, /**/ -- I once paid $12 to peer at the box that held King Tutankhamen's little bandage-covered midget corpse at the De Young Museum in San Francisco. I remember thinking how pleased he'd be about the way things turned out in his afterlife. (Scott Adams - The Dilbert principle) /-/-- Bram Moolenaar --- Bram@moolenaar.net --- http://www.moolenaar.net --\-\ \-\-- Vim: http://www.vim.org ---- ICCF Holland: http://www.vim.org/iccf --/-/