aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/tui
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2018-12-27 22:49:44 +0100
committerJustin M. Keyes <justinkz@gmail.com>2018-12-27 22:49:44 +0100
commitc1015121ec626cab6cb384f544bc0be1a1760c0e (patch)
tree6cc9a5d1899a4486a24c491e07d17a7dd01f9503 /src/nvim/tui
parent4f030ec24e0e148bbb83aedaef7dd629e5fef130 (diff)
parente1876c7ad1b5e30c0a9919e2c4587d11550c8507 (diff)
downloadrneovim-c1015121ec626cab6cb384f544bc0be1a1760c0e.tar.gz
rneovim-c1015121ec626cab6cb384f544bc0be1a1760c0e.tar.bz2
rneovim-c1015121ec626cab6cb384f544bc0be1a1760c0e.zip
Merge 'upstream/master' into pr-win-erw7
Diffstat (limited to 'src/nvim/tui')
-rw-r--r--src/nvim/tui/terminfo.c19
-rw-r--r--src/nvim/tui/tui.c288
2 files changed, 173 insertions, 134 deletions
diff --git a/src/nvim/tui/terminfo.c b/src/nvim/tui/terminfo.c
index 42237903ea..27792655c9 100644
--- a/src/nvim/tui/terminfo.c
+++ b/src/nvim/tui/terminfo.c
@@ -13,6 +13,7 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option.h"
+#include "nvim/os/os.h"
#include "nvim/tui/terminfo.h"
#include "nvim/tui/terminfo_defs.h"
@@ -33,6 +34,24 @@ bool terminfo_is_term_family(const char *term, const char *family)
&& ('\0' == term[flen] || '-' == term[flen]);
}
+bool terminfo_is_bsd_console(const char *term)
+{
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \
+ || defined(__DragonFly__)
+ if (strequal(term, "vt220") // OpenBSD
+ || strequal(term, "vt100")) { // NetBSD
+ return true;
+ }
+# if defined(__FreeBSD__)
+ // FreeBSD console sets TERM=xterm, but it does not support xterm features
+ // like cursor-shaping. Assume that TERM=xterm is degraded. #8644
+ return strequal(term, "xterm") && !!os_getenv("XTERM_VERSION");
+# endif
+#else
+ return false;
+#endif
+}
+
/// Loads a built-in terminfo db when we (unibilium) failed to load a terminfo
/// record from the environment (termcap systems, unrecognized $TERM, …).
/// We do not attempt to detect xterm pretenders here.
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index f444d1ec84..c73de1049c 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -99,6 +99,7 @@ typedef struct {
bool can_set_lr_margin;
bool can_set_left_right_margin;
bool can_scroll;
+ bool can_erase_chars;
bool immediate_wrap_after_last_column;
bool bce;
bool mouse_enabled;
@@ -108,8 +109,9 @@ typedef struct {
cursorentry_T cursor_shapes[SHAPE_IDX_COUNT];
HlAttrs clear_attrs;
kvec_t(HlAttrs) attrs;
- HlAttrs print_attrs;
+ int print_attr_id;
bool default_attr;
+ bool can_clear_attr;
ModeShape showing_mode;
struct {
int enable_mouse, disable_mouse;
@@ -124,6 +126,7 @@ typedef struct {
int set_cursor_style, reset_cursor_style;
int enter_undercurl_mode, exit_undercurl_mode, set_underline_color;
} unibi_ext;
+ char *space_buf;
} TUIData;
static bool volatile got_winch = false;
@@ -189,6 +192,7 @@ static void terminfo_start(UI *ui)
data->scroll_region_is_full_screen = true;
data->bufpos = 0;
data->default_attr = false;
+ data->can_clear_attr = false;
data->is_invisible = true;
data->busy = false;
data->cork = false;
@@ -281,14 +285,17 @@ static void terminfo_start(UI *ui)
const char *colorterm = os_getenv("COLORTERM");
const char *termprg = os_getenv("TERM_PROGRAM");
const char *vte_version_env = os_getenv("VTE_VERSION");
- long vte_version = vte_version_env ? strtol(vte_version_env, NULL, 10) : 0;
+ long vtev = vte_version_env ? strtol(vte_version_env, NULL, 10) : 0;
bool iterm_env = termprg && strstr(termprg, "iTerm.app");
bool konsole = terminfo_is_term_family(term, "konsole")
|| os_getenv("KONSOLE_PROFILE_NAME")
|| os_getenv("KONSOLE_DBUS_SESSION");
+ const char *konsolev_env = os_getenv("KONSOLE_VERSION");
+ long konsolev = konsolev_env ? strtol(konsolev_env, NULL, 10)
+ : (konsole ? 1 : 0);
- patch_terminfo_bugs(data, term, colorterm, vte_version, konsole, iterm_env);
- augment_terminfo(data, term, colorterm, vte_version, konsole, iterm_env);
+ patch_terminfo_bugs(data, term, colorterm, vtev, konsolev, iterm_env);
+ augment_terminfo(data, term, colorterm, vtev, konsolev, iterm_env);
data->can_change_scroll_region =
!!unibi_get_str(data->ut, unibi_change_scroll_region);
data->can_set_lr_margin =
@@ -301,6 +308,7 @@ static void terminfo_start(UI *ui)
&& !!unibi_get_str(data->ut, unibi_parm_delete_line)
&& !!unibi_get_str(data->ut, unibi_insert_line)
&& !!unibi_get_str(data->ut, unibi_parm_insert_line);
+ data->can_erase_chars = !!unibi_get_str(data->ut, unibi_erase_chars);
data->immediate_wrap_after_last_column =
conemu_ansi
|| terminfo_is_term_family(term, "cygwin")
@@ -366,7 +374,7 @@ static void terminfo_stop(UI *ui)
static void tui_terminal_start(UI *ui)
{
TUIData *data = ui->data;
- data->print_attrs = HLATTRS_INVALID;
+ data->print_attr_id = -1;
ugrid_init(&data->grid);
terminfo_start(ui);
update_size(ui);
@@ -465,6 +473,7 @@ static void tui_main(UIBridgeData *bridge, UI *ui)
loop_close(&tui_loop, false);
kv_destroy(data->invalid_regions);
kv_destroy(data->attrs);
+ xfree(data->space_buf);
xfree(data);
}
@@ -499,8 +508,17 @@ static void sigwinch_cb(SignalWatcher *watcher, int signum, void *data)
ui_schedule_refresh();
}
-static bool attrs_differ(HlAttrs a1, HlAttrs a2, bool rgb)
+static bool attrs_differ(UI *ui, int id1, int id2, bool rgb)
{
+ TUIData *data = ui->data;
+ if (id1 == id2) {
+ return false;
+ } else if (id1 < 0 || id2 < 0) {
+ return true;
+ }
+ HlAttrs a1 = kv_A(data->attrs, (size_t)id1);
+ HlAttrs a2 = kv_A(data->attrs, (size_t)id2);
+
if (rgb) {
return a1.rgb_fg_color != a2.rgb_fg_color
|| a1.rgb_bg_color != a2.rgb_bg_color
@@ -515,21 +533,16 @@ static bool attrs_differ(HlAttrs a1, HlAttrs a2, bool rgb)
}
}
-static bool no_bg(UI *ui, HlAttrs attrs)
-{
- return ui->rgb ? attrs.rgb_bg_color == -1
- : attrs.cterm_bg_color == 0;
-}
-
-static void update_attrs(UI *ui, HlAttrs attrs)
+static void update_attrs(UI *ui, int attr_id)
{
TUIData *data = ui->data;
- if (!attrs_differ(attrs, data->print_attrs, ui->rgb)) {
+ if (!attrs_differ(ui, attr_id, data->print_attr_id, ui->rgb)) {
+ data->print_attr_id = attr_id;
return;
}
-
- data->print_attrs = attrs;
+ data->print_attr_id = attr_id;
+ HlAttrs attrs = kv_A(data->attrs, (size_t)attr_id);
int fg = ui->rgb ? attrs.rgb_fg_color : (attrs.cterm_fg_color - 1);
if (fg == -1) {
@@ -634,6 +647,12 @@ static void update_attrs(UI *ui, HlAttrs attrs)
data->default_attr = fg == -1 && bg == -1
&& !bold && !italic && !underline && !undercurl && !reverse && !standout;
+
+ // Non-BCE terminals can't clear with non-default background color. Some BCE
+ // terminals don't support attributes either, so don't rely on it. But assume
+ // italic and bold has no effect if there is no text.
+ data->can_clear_attr = !reverse && !standout && !underline && !undercurl
+ && (data->bce || bg == -1);
}
static void final_column_wrap(UI *ui)
@@ -659,7 +678,7 @@ static void print_cell(UI *ui, UCell *ptr)
// Printing the next character finally advances the cursor.
final_column_wrap(ui);
}
- update_attrs(ui, kv_A(data->attrs, ptr->attr));
+ update_attrs(ui, ptr->attr);
out(ui, ptr->data, strlen(ptr->data));
grid->col++;
if (data->immediate_wrap_after_last_column) {
@@ -675,8 +694,8 @@ static bool cheap_to_print(UI *ui, int row, int col, int next)
UCell *cell = grid->cells[row] + col;
while (next) {
next--;
- if (attrs_differ(kv_A(data->attrs, cell->attr),
- data->print_attrs, ui->rgb)) {
+ if (attrs_differ(ui, cell->attr,
+ data->print_attr_id, ui->rgb)) {
if (data->default_attr) {
return false;
}
@@ -726,7 +745,7 @@ static void cursor_goto(UI *ui, int row, int col)
int n = col - grid->col;
if (n <= (row == grid->row ? 4 : 2)
&& cheap_to_print(ui, grid->row, grid->col, n)) {
- UGRID_FOREACH_CELL(grid, grid->row, grid->row, grid->col, col - 1, {
+ UGRID_FOREACH_CELL(grid, grid->row, grid->col, col, {
print_cell(ui, cell);
});
}
@@ -798,50 +817,45 @@ safe_move:
}
static void clear_region(UI *ui, int top, int bot, int left, int right,
- HlAttrs attrs)
+ int attr_id)
{
TUIData *data = ui->data;
UGrid *grid = &data->grid;
- bool cleared = false;
-
- // non-BCE terminals can't clear with non-default background color
- bool can_clear = data->bce || no_bg(ui, attrs);
-
- if (can_clear && right == ui->width -1) {
- // Background is set to the default color and the right edge matches the
- // screen end, try to use terminal codes for clearing the requested area.
- update_attrs(ui, attrs);
- if (left == 0) {
- if (bot == ui->height - 1) {
- if (top == 0) {
- unibi_out(ui, unibi_clear_screen);
- ugrid_goto(&data->grid, top, left);
- } else {
- cursor_goto(ui, top, 0);
- unibi_out(ui, unibi_clr_eos);
- }
- cleared = true;
- }
+ update_attrs(ui, attr_id);
+
+ // Background is set to the default color and the right edge matches the
+ // screen end, try to use terminal codes for clearing the requested area.
+ if (data->can_clear_attr
+ && left == 0 && right == ui->width && bot == ui->height) {
+ if (top == 0) {
+ unibi_out(ui, unibi_clear_screen);
+ ugrid_goto(&data->grid, top, left);
+ } else {
+ cursor_goto(ui, top, 0);
+ unibi_out(ui, unibi_clr_eos);
}
+ } else {
+ int width = right-left;
- if (!cleared) {
- // iterate through each line and clear with clr_eol
- for (int row = top; row <= bot; row++) {
- cursor_goto(ui, row, left);
+ // iterate through each line and clear
+ for (int row = top; row < bot; row++) {
+ cursor_goto(ui, row, left);
+ if (data->can_clear_attr && right == ui->width) {
unibi_out(ui, unibi_clr_eol);
+ } else if (data->can_erase_chars && data->can_clear_attr && width >= 5) {
+ UNIBI_SET_NUM_VAR(data->params[0], width);
+ unibi_out(ui, unibi_erase_chars);
+ } else {
+ out(ui, data->space_buf, (size_t)width);
+ grid->col += width;
+ if (data->immediate_wrap_after_last_column) {
+ // Printing at the right margin immediately advances the cursor.
+ final_column_wrap(ui);
+ }
}
- cleared = true;
}
}
-
- if (!cleared) {
- // could not clear using faster terminal codes, refresh the whole region
- UGRID_FOREACH_CELL(grid, top, bot, left, right, {
- cursor_goto(ui, row, col);
- print_cell(ui, cell);
- });
- }
}
static void set_scroll_region(UI *ui, int top, int bot, int left, int right)
@@ -902,12 +916,16 @@ static void tui_grid_resize(UI *ui, Integer g, Integer width, Integer height)
UGrid *grid = &data->grid;
ugrid_resize(grid, (int)width, (int)height);
+ xfree(data->space_buf);
+ data->space_buf = xmalloc((size_t)width * sizeof(*data->space_buf));
+ memset(data->space_buf, ' ', (size_t)width);
+
// resize might not always be followed by a clear before flush
// so clip the invalid region
for (size_t i = 0; i < kv_size(data->invalid_regions); i++) {
Rect *r = &kv_A(data->invalid_regions, i);
- r->bot = MIN(r->bot, grid->height-1);
- r->right = MIN(r->right, grid->width-1);
+ r->bot = MIN(r->bot, grid->height);
+ r->right = MIN(r->right, grid->width);
}
if (!got_winch) { // Try to resize the terminal window.
@@ -930,8 +948,7 @@ static void tui_grid_clear(UI *ui, Integer g)
UGrid *grid = &data->grid;
ugrid_clear(grid);
kv_size(data->invalid_regions) = 0;
- clear_region(ui, 0, grid->height-1, 0, grid->width-1,
- data->clear_attrs);
+ clear_region(ui, 0, grid->height, 0, grid->width, 0);
}
static void tui_grid_cursor_goto(UI *ui, Integer grid, Integer row, Integer col)
@@ -1089,9 +1106,7 @@ static void tui_grid_scroll(UI *ui, Integer g, Integer startrow, Integer endrow,
data->scroll_region_is_full_screen = fullwidth
&& top == 0 && bot == ui->height-1;
- int clear_top, clear_bot;
- ugrid_scroll(grid, top, bot, left, right, (int)rows,
- &clear_top, &clear_bot);
+ ugrid_scroll(grid, top, bot, left, right, (int)rows);
bool can_scroll = data->can_scroll
&& (data->scroll_region_is_full_screen
@@ -1106,8 +1121,6 @@ static void tui_grid_scroll(UI *ui, Integer g, Integer startrow, Integer endrow,
set_scroll_region(ui, top, bot, left, right);
}
cursor_goto(ui, top, left);
- // also set default color attributes or some terminals can become funny
- update_attrs(ui, data->clear_attrs);
if (rows > 0) {
if (rows == 1) {
@@ -1129,16 +1142,14 @@ static void tui_grid_scroll(UI *ui, Integer g, Integer startrow, Integer endrow,
if (!data->scroll_region_is_full_screen) {
reset_scroll_region(ui, fullwidth);
}
-
- if (!(data->bce || no_bg(ui, data->clear_attrs))) {
- // Scrolling will leave wrong background in the cleared area on non-BCE
- // terminals. Update the cleared area.
- clear_region(ui, clear_top, clear_bot, left, right,
- data->clear_attrs);
- }
} else {
- // Mark the entire scroll region as invalid for redrawing later
- invalidate(ui, top, bot, left, right);
+ // Mark the moved region as invalid for redrawing later
+ if (rows > 0) {
+ endrow = endrow - rows;
+ } else {
+ startrow = startrow - rows;
+ }
+ invalidate(ui, (int)startrow, (int)endrow, (int)startcol, (int)endcol);
}
}
@@ -1171,8 +1182,8 @@ static void tui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg,
data->clear_attrs.cterm_fg_color = (int)cterm_fg;
data->clear_attrs.cterm_bg_color = (int)cterm_bg;
- data->print_attrs = HLATTRS_INVALID;
- invalidate(ui, 0, data->grid.height-1, 0, data->grid.width-1);
+ data->print_attr_id = -1;
+ invalidate(ui, 0, data->grid.height, 0, data->grid.width);
}
static void tui_flush(UI *ui)
@@ -1194,11 +1205,27 @@ static void tui_flush(UI *ui)
while (kv_size(data->invalid_regions)) {
Rect r = kv_pop(data->invalid_regions);
- assert(r.bot < grid->height && r.right < grid->width);
- UGRID_FOREACH_CELL(grid, r.top, r.bot, r.left, r.right, {
- cursor_goto(ui, row, col);
- print_cell(ui, cell);
- });
+ assert(r.bot <= grid->height && r.right <= grid->width);
+
+ for (int row = r.top; row < r.bot; row++) {
+ int clear_attr = grid->cells[row][r.right-1].attr;
+ int clear_col;
+ for (clear_col = r.right; clear_col > 0; clear_col--) {
+ UCell *cell = &grid->cells[row][clear_col-1];
+ if (!(cell->data[0] == ' ' && cell->data[1] == NUL
+ && cell->attr == clear_attr)) {
+ break;
+ }
+ }
+
+ UGRID_FOREACH_CELL(grid, row, r.left, clear_col, {
+ cursor_goto(ui, row, col);
+ print_cell(ui, cell);
+ });
+ if (clear_col < r.right) {
+ clear_region(ui, row, row+1, clear_col, r.right, clear_attr);
+ }
+ }
}
cursor_goto(ui, data->row, data->col);
@@ -1283,8 +1310,8 @@ static void tui_option_set(UI *ui, String name, Object value)
if (strequal(name.data, "termguicolors")) {
ui->rgb = value.data.boolean;
- data->print_attrs = HLATTRS_INVALID;
- invalidate(ui, 0, data->grid.height-1, 0, data->grid.width-1);
+ data->print_attr_id = -1;
+ invalidate(ui, 0, data->grid.height, 0, data->grid.width);
}
}
@@ -1300,18 +1327,16 @@ static void tui_raw_line(UI *ui, Integer g, Integer linerow, Integer startcol,
assert((size_t)attrs[c-startcol] < kv_size(data->attrs));
grid->cells[linerow][c].attr = attrs[c-startcol];
}
- UGRID_FOREACH_CELL(grid, (int)linerow, (int)linerow, (int)startcol,
- (int)endcol-1, {
- cursor_goto(ui, row, col);
+ UGRID_FOREACH_CELL(grid, (int)linerow, (int)startcol, (int)endcol, {
+ cursor_goto(ui, (int)linerow, col);
print_cell(ui, cell);
});
if (clearcol > endcol) {
- HlAttrs cl_attrs = kv_A(data->attrs, (size_t)clearattr);
ugrid_clear_chunk(grid, (int)linerow, (int)endcol, (int)clearcol,
(sattr_T)clearattr);
- clear_region(ui, (int)linerow, (int)linerow, (int)endcol, (int)clearcol-1,
- cl_attrs);
+ clear_region(ui, (int)linerow, (int)linerow+1, (int)endcol, (int)clearcol,
+ (int)clearattr);
}
if (wrap && ui->width == grid->width && linerow + 1 < grid->height) {
@@ -1319,9 +1344,10 @@ static void tui_raw_line(UI *ui, Integer g, Integer linerow, Integer startcol,
// width and the line continuation is within the grid.
if (endcol != grid->width) {
- // Print the last cell of the row, if we haven't already done so.
- cursor_goto(ui, (int)linerow, grid->width - 1);
- print_cell(ui, &grid->cells[linerow][grid->width - 1]);
+ // Print the last char of the row, if we haven't already done so.
+ int size = grid->cells[linerow][grid->width - 1].data[0] == NUL ? 2 : 1;
+ cursor_goto(ui, (int)linerow, grid->width - size);
+ print_cell(ui, &grid->cells[linerow][grid->width - size]);
}
// Wrap the cursor over to the next line. The next line will be
@@ -1334,27 +1360,17 @@ static void invalidate(UI *ui, int top, int bot, int left, int right)
{
TUIData *data = ui->data;
Rect *intersects = NULL;
- // Increase dimensions before comparing to ensure adjacent regions are
- // treated as intersecting
- --top;
- ++bot;
- --left;
- ++right;
for (size_t i = 0; i < kv_size(data->invalid_regions); i++) {
Rect *r = &kv_A(data->invalid_regions, i);
- if (!(top > r->bot || bot < r->top
- || left > r->right || right < r->left)) {
+ // adjacent regions are treated as overlapping
+ if (!(top > r->bot || bot < r->top)
+ && !(left > r->right || right < r->left)) {
intersects = r;
break;
}
}
- ++top;
- --bot;
- ++left;
- --right;
-
if (intersects) {
// If top/bot/left/right intersects with a invalid rect, we replace it
// by the union
@@ -1514,16 +1530,19 @@ static int unibi_find_ext_bool(unibi_term *ut, const char *name)
/// and several terminal emulators falsely announce incorrect terminal types.
static void patch_terminfo_bugs(TUIData *data, const char *term,
const char *colorterm, long vte_version,
- bool konsole, bool iterm_env)
+ long konsolev, bool iterm_env)
{
unibi_term *ut = data->ut;
- const char * xterm_version = os_getenv("XTERM_VERSION");
+ const char *xterm_version = os_getenv("XTERM_VERSION");
#if 0 // We don't need to identify this specifically, for now.
bool roxterm = !!os_getenv("ROXTERM_ID");
#endif
- bool xterm = terminfo_is_term_family(term, "xterm");
+ bool xterm = terminfo_is_term_family(term, "xterm")
+ // Treat Terminal.app as generic xterm-like, for now.
+ || terminfo_is_term_family(term, "nsterm");
bool kitty = terminfo_is_term_family(term, "xterm-kitty");
bool linuxvt = terminfo_is_term_family(term, "linux");
+ bool bsdvt = terminfo_is_bsd_console(term);
bool rxvt = terminfo_is_term_family(term, "rxvt");
bool teraterm = terminfo_is_term_family(term, "teraterm");
bool putty = terminfo_is_term_family(term, "putty");
@@ -1539,12 +1558,12 @@ static void patch_terminfo_bugs(TUIData *data, const char *term,
bool alacritty = terminfo_is_term_family(term, "alacritty");
// None of the following work over SSH; see :help TERM .
bool iterm_pretending_xterm = xterm && iterm_env;
- bool konsole_pretending_xterm = xterm && konsole;
+ bool konsole_pretending_xterm = xterm && konsolev;
bool gnome_pretending_xterm = xterm && colorterm
&& strstr(colorterm, "gnome-terminal");
bool mate_pretending_xterm = xterm && colorterm
&& strstr(colorterm, "mate-terminal");
- bool true_xterm = xterm && !!xterm_version;
+ bool true_xterm = xterm && !!xterm_version && !bsdvt;
bool cygwin = terminfo_is_term_family(term, "cygwin");
bool conemu = terminfo_is_term_family(term, "conemu");
@@ -1689,7 +1708,7 @@ static void patch_terminfo_bugs(TUIData *data, const char *term,
unibi_set_num(ut, unibi_max_colors, 256);
unibi_set_str(ut, unibi_set_a_foreground, XTERM_SETAF_256_COLON);
unibi_set_str(ut, unibi_set_a_background, XTERM_SETAB_256_COLON);
- } else if (konsole || xterm || gnome || rxvt || st || putty
+ } else if (konsolev || xterm || gnome || rxvt || st || putty
|| linuxvt // Linux 4.8+ supports 256-colour SGR.
|| mate_pretending_xterm || gnome_pretending_xterm
|| tmux
@@ -1710,7 +1729,8 @@ static void patch_terminfo_bugs(TUIData *data, const char *term,
}
// Blacklist of terminals that cannot be trusted to report DECSCUSR support.
- if (!(st || (vte_version != 0 && vte_version < 3900) || konsole)) {
+ if (!(st || (vte_version != 0 && vte_version < 3900)
+ || (konsolev > 0 && konsolev < 180770))) {
data->unibi_ext.reset_cursor_style = unibi_find_ext_str(ut, "Se");
data->unibi_ext.set_cursor_style = unibi_find_ext_str(ut, "Ss");
}
@@ -1719,15 +1739,15 @@ static void patch_terminfo_bugs(TUIData *data, const char *term,
// adding them to terminal types, that have such control sequences but lack
// the correct terminfo entries, is a fixup, not an augmentation.
if (-1 == data->unibi_ext.set_cursor_style) {
- // DECSCUSR (cursor shape) sequence is widely supported by several terminal
- // types. https://github.com/gnachman/iTerm2/pull/92
- // xterm extension: vertical bar
- if (!konsole
+ // DECSCUSR (cursor shape) is widely supported.
+ // https://github.com/gnachman/iTerm2/pull/92
+ if ((!bsdvt && (!konsolev || konsolev >= 180770))
&& ((xterm && !vte_version) // anything claiming xterm compat
// per MinTTY 0.4.3-1 release notes from 2009
|| putty
// per https://bugzilla.gnome.org/show_bug.cgi?id=720821
|| (vte_version >= 3900)
+ || (konsolev >= 180770) // #9364
|| tmux // per tmux manual page
// https://lists.gnu.org/archive/html/screen-devel/2013-03/msg00000.html
|| screen
@@ -1735,7 +1755,7 @@ static void patch_terminfo_bugs(TUIData *data, const char *term,
|| rxvt // per command.C
// per analysis of VT100Terminal.m
|| iterm || iterm_pretending_xterm
- || teraterm // per TeraTerm "Supported Control Functions" doco
+ || teraterm // per TeraTerm "Supported Control Functions" doco
|| alacritty // https://github.com/jwilm/alacritty/pull/608
|| cygwin
// Some linux-type terminals implement the xterm extension.
@@ -1776,12 +1796,10 @@ static void patch_terminfo_bugs(TUIData *data, const char *term,
"");
}
unibi_set_ext_str(ut, (size_t)data->unibi_ext.reset_cursor_style,
- "\x1b[?c");
- } else if (konsole) {
- // Konsole uses an idiosyncratic escape code to set the cursor shape and
- // does not support DECSCUSR. This makes Konsole set up and apply a
- // nonce profile, which has side-effects on temporary font resizing.
- // In an ideal world, Konsole would just support DECSCUSR.
+ "\x1b[?c");
+ } else if (konsolev > 0 && konsolev < 180770) {
+ // Konsole before version 18.07.70: set up a nonce profile. This has
+ // side-effects on temporary font resizing. #6798
data->unibi_ext.set_cursor_style = (int)unibi_add_ext_str(ut, "Ss",
TMUX_WRAP(tmux, "\x1b]50;CursorShape=%?"
"%p1%{3}%<" "%t%{0}" // block
@@ -1804,10 +1822,14 @@ static void patch_terminfo_bugs(TUIData *data, const char *term,
/// This adds stuff that is not in standard terminfo as extended unibilium
/// capabilities.
static void augment_terminfo(TUIData *data, const char *term,
- const char *colorterm, long vte_version, bool konsole, bool iterm_env)
+ const char *colorterm, long vte_version,
+ long konsolev, bool iterm_env)
{
unibi_term *ut = data->ut;
- bool xterm = terminfo_is_term_family(term, "xterm");
+ bool xterm = terminfo_is_term_family(term, "xterm")
+ // Treat Terminal.app as generic xterm-like, for now.
+ || terminfo_is_term_family(term, "nsterm");
+ bool bsdvt = terminfo_is_bsd_console(term);
bool dtterm = terminfo_is_term_family(term, "dtterm");
bool rxvt = terminfo_is_term_family(term, "rxvt");
bool teraterm = terminfo_is_term_family(term, "teraterm");
@@ -1818,16 +1840,17 @@ static void augment_terminfo(TUIData *data, const char *term,
|| terminfo_is_term_family(term, "iterm2")
|| terminfo_is_term_family(term, "iTerm.app")
|| terminfo_is_term_family(term, "iTerm2.app");
+ bool alacritty = terminfo_is_term_family(term, "alacritty");
// None of the following work over SSH; see :help TERM .
bool iterm_pretending_xterm = xterm && iterm_env;
- const char * xterm_version = os_getenv("XTERM_VERSION");
- bool true_xterm = xterm && !!xterm_version;
+ const char *xterm_version = os_getenv("XTERM_VERSION");
+ bool true_xterm = xterm && !!xterm_version && !bsdvt;
// Only define this capability for terminal types that we know understand it.
if (dtterm // originated this extension
|| xterm // per xterm ctlseqs doco
- || konsole // per commentary in VT102Emulation.cpp
+ || konsolev // per commentary in VT102Emulation.cpp
|| teraterm // per TeraTerm "Supported Control Functions" doco
|| rxvt) { // per command.C
data->unibi_ext.resize_screen = (int)unibi_add_ext_str(ut,
@@ -1885,7 +1908,8 @@ static void augment_terminfo(TUIData *data, const char *term,
// would use a tmux control sequence and an extra if(screen) test.
data->unibi_ext.set_cursor_color = (int)unibi_add_ext_str(
ut, NULL, TMUX_WRAP(tmux, "\033]Pl%p1%06x\033\\"));
- } else if ((xterm || rxvt) && (vte_version == 0 || vte_version >= 3900)) {
+ } else if ((xterm || rxvt || alacritty)
+ && (vte_version == 0 || vte_version >= 3900)) {
// Supported in urxvt, newer VTE.
data->unibi_ext.set_cursor_color = (int)unibi_add_ext_str(
ut, "ext.set_cursor_color", "\033]12;#%p1%06x\007");
@@ -1925,13 +1949,9 @@ static void augment_terminfo(TUIData *data, const char *term,
ut, "ext.enter_undercurl_mode", "\x1b[4:3m");
data->unibi_ext.exit_undercurl_mode = (int)unibi_add_ext_str(
ut, "ext.exit_undercurl_mode", "\x1b[4:0m");
- if (has_colon_rgb) {
- data->unibi_ext.set_underline_color = (int)unibi_add_ext_str(
- ut, "ext.set_underline_color", "\x1b[58:2:%p1%d:%p2%d:%p3%dm");
- } else {
- data->unibi_ext.set_underline_color = (int)unibi_add_ext_str(
- ut, "ext.set_underline_color", "\x1b[58;2;%p1%d;%p2%d;%p3%dm");
- }
+ // Only support colon syntax. #9270
+ data->unibi_ext.set_underline_color = (int)unibi_add_ext_str(
+ ut, "ext.set_underline_color", "\x1b[58:2::%p1%d:%p2%d:%p3%dm");
}
}