1
0
mirror of https://github.com/tmux/tmux.git synced 2025-04-01 21:41:44 +00:00

Flag tabs if possible in the grid cell so they can be preserved on

copying and capture-pane. From Alexander Arch in GitHub issue 4201.
This commit is contained in:
nicm 2024-10-25 15:00:18 +00:00
parent 63582c154c
commit fdbc6cdea5
6 changed files with 84 additions and 16 deletions

View File

@ -345,6 +345,8 @@ grid_reader_cell_equals_data(const struct grid_cell *gc,
{ {
if (gc->flags & GRID_FLAG_PADDING) if (gc->flags & GRID_FLAG_PADDING)
return (0); return (0);
if (gc->flags & GRID_FLAG_TAB && ud->size == 1 && *ud->data == '\t')
return (1);
if (gc->data.size != ud->size) if (gc->data.size != ud->size)
return (0); return (0);
return (memcmp(gc->data.data, ud->data, gc->data.size) == 0); return (memcmp(gc->data.data, ud->data, gc->data.size) == 0);

42
grid.c
View File

@ -92,6 +92,8 @@ grid_need_extended_cell(const struct grid_cell_entry *gce,
return (1); return (1);
if (gc->link != 0) if (gc->link != 0)
return (1); return (1);
if (gc->flags & GRID_FLAG_TAB)
return (1);
return (0); return (0);
} }
@ -124,7 +126,10 @@ grid_extended_cell(struct grid_line *gl, struct grid_cell_entry *gce,
fatalx("offset too big"); fatalx("offset too big");
gl->flags |= GRID_LINE_EXTENDED; gl->flags |= GRID_LINE_EXTENDED;
utf8_from_data(&gc->data, &uc); if (gc->flags & GRID_FLAG_TAB)
uc = gc->data.width;
else
utf8_from_data(&gc->data, &uc);
gee = &gl->extddata[gce->offset]; gee = &gl->extddata[gce->offset];
gee->data = uc; gee->data = uc;
@ -252,6 +257,16 @@ grid_cells_equal(const struct grid_cell *gc1, const struct grid_cell *gc2)
return (memcmp(gc1->data.data, gc2->data.data, gc1->data.size) == 0); return (memcmp(gc1->data.data, gc2->data.data, gc1->data.size) == 0);
} }
/* Set grid cell to a tab. */
void
grid_set_tab(struct grid_cell *gc, u_int width)
{
memset(&gc->data, 0, sizeof gc->data);
gc->flags |= GRID_FLAG_TAB;
gc->data.width = gc->data.size = gc->data.have = width;
memset(&gc->data, ' ', gc->data.size);
}
/* Free one line. */ /* Free one line. */
static void static void
grid_free_line(struct grid *gd, u_int py) grid_free_line(struct grid *gd, u_int py)
@ -515,7 +530,11 @@ grid_get_cell1(struct grid_line *gl, u_int px, struct grid_cell *gc)
gc->bg = gee->bg; gc->bg = gee->bg;
gc->us = gee->us; gc->us = gee->us;
gc->link = gee->link; gc->link = gee->link;
utf8_to_data(gee->data, &gc->data);
if (gc->flags & GRID_FLAG_TAB)
grid_set_tab(gc, gee->data);
else
utf8_to_data(gee->data, &gc->data);
} }
return; return;
} }
@ -1077,13 +1096,18 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
} else } else
codelen = 0; codelen = 0;
data = gc.data.data; if (gc.flags & GRID_FLAG_TAB) {
size = gc.data.size; data = "\t";
if ((flags & GRID_STRING_ESCAPE_SEQUENCES) && size = 1;
size == 1 && } else {
*data == '\\') { data = gc.data.data;
data = "\\\\"; size = gc.data.size;
size = 2; if ((flags & GRID_STRING_ESCAPE_SEQUENCES) &&
size == 1 &&
*data == '\\') {
data = "\\\\";
size = 2;
}
} }
while (len < off + size + codelen + 1) { while (len < off + size + codelen + 1) {

27
input.c
View File

@ -1213,6 +1213,10 @@ input_c0_dispatch(struct input_ctx *ictx)
struct screen_write_ctx *sctx = &ictx->ctx; struct screen_write_ctx *sctx = &ictx->ctx;
struct window_pane *wp = ictx->wp; struct window_pane *wp = ictx->wp;
struct screen *s = sctx->s; struct screen *s = sctx->s;
struct grid_cell gc, first_gc;
u_int cx = s->cx, line = s->cy + s->grid->hsize;
u_int width;
int has_content = 0;
ictx->utf8started = 0; /* can't be valid UTF-8 */ ictx->utf8started = 0; /* can't be valid UTF-8 */
@ -1234,11 +1238,28 @@ input_c0_dispatch(struct input_ctx *ictx)
break; break;
/* Find the next tab point, or use the last column if none. */ /* Find the next tab point, or use the last column if none. */
grid_get_cell(s->grid, s->cx, line, &first_gc);
do { do {
s->cx++; if (!has_content) {
if (bit_test(s->tabs, s->cx)) grid_get_cell(s->grid, cx, line, &gc);
if (gc.data.size != 1 ||
*gc.data.data != ' ' ||
!grid_cells_look_equal(&gc, &first_gc))
has_content = 1;
}
cx++;
if (bit_test(s->tabs, cx))
break; break;
} while (s->cx < screen_size_x(s) - 1); } while (cx < screen_size_x(s) - 1);
width = cx - s->cx;
if (has_content || width > sizeof gc.data.data)
s->cx = cx;
else {
grid_get_cell(s->grid, s->cx, line, &gc);
grid_set_tab(&gc, width);
screen_write_collect_add(sctx, &gc);
}
break; break;
case '\012': /* LF */ case '\012': /* LF */
case '\013': /* VT */ case '\013': /* VT */

View File

@ -1814,6 +1814,8 @@ screen_write_collect_add(struct screen_write_ctx *ctx,
collect = 1; collect = 1;
if (gc->data.width != 1 || gc->data.size != 1 || *gc->data.data >= 0x7f) if (gc->data.width != 1 || gc->data.size != 1 || *gc->data.data >= 0x7f)
collect = 0; collect = 0;
else if (gc->flags & GRID_FLAG_TAB)
collect = 0;
else if (gc->attr & GRID_ATTR_CHARSET) else if (gc->attr & GRID_ATTR_CHARSET)
collect = 0; collect = 0;
else if (~s->mode & MODE_WRAP) else if (~s->mode & MODE_WRAP)

2
tmux.h
View File

@ -709,6 +709,7 @@ struct colour_palette {
#define GRID_FLAG_SELECTED 0x10 #define GRID_FLAG_SELECTED 0x10
#define GRID_FLAG_NOPALETTE 0x20 #define GRID_FLAG_NOPALETTE 0x20
#define GRID_FLAG_CLEARED 0x40 #define GRID_FLAG_CLEARED 0x40
#define GRID_FLAG_TAB 0x80
/* Grid line flags. */ /* Grid line flags. */
#define GRID_LINE_WRAPPED 0x1 #define GRID_LINE_WRAPPED 0x1
@ -2861,6 +2862,7 @@ int attributes_fromstring(const char *);
/* grid.c */ /* grid.c */
extern const struct grid_cell grid_default_cell; extern const struct grid_cell grid_default_cell;
void grid_empty_line(struct grid *, u_int, u_int); void grid_empty_line(struct grid *, u_int, u_int);
void grid_set_tab(struct grid_cell *, u_int);
int grid_cells_equal(const struct grid_cell *, const struct grid_cell *); int grid_cells_equal(const struct grid_cell *, const struct grid_cell *);
int grid_cells_look_equal(const struct grid_cell *, int grid_cells_look_equal(const struct grid_cell *,
const struct grid_cell *); const struct grid_cell *);

View File

@ -3301,6 +3301,11 @@ window_copy_cellstring(const struct grid_line *gl, u_int px, size_t *size,
*allocated = 0; *allocated = 0;
return (&gce->data.data); return (&gce->data.data);
} }
if (gce->flags & GRID_FLAG_TAB) {
*size = 1;
*allocated = 0;
return ("\t");
}
utf8_to_data(gl->extddata[gce->offset].data, &ud); utf8_to_data(gl->extddata[gce->offset].data, &ud);
if (ud.size == 0) { if (ud.size == 0) {
@ -4083,9 +4088,15 @@ window_copy_match_at_cursor(struct window_copy_mode_data *data)
px = at - (py * sx); px = at - (py * sx);
grid_get_cell(gd, px, gd->hsize + py - data->oy, &gc); grid_get_cell(gd, px, gd->hsize + py - data->oy, &gc);
buf = xrealloc(buf, len + gc.data.size + 1); if (gc.flags & GRID_FLAG_TAB) {
memcpy(buf + len, gc.data.data, gc.data.size); buf = xrealloc(buf, len + 2);
len += gc.data.size; buf[len] = '\t';
len++;
} else {
buf = xrealloc(buf, len + gc.data.size + 1);
memcpy(buf + len, gc.data.data, gc.data.size);
len += gc.data.size;
}
} }
if (len != 0) if (len != 0)
buf[len] = '\0'; buf[len] = '\0';
@ -4812,7 +4823,13 @@ window_copy_copy_line(struct window_mode_entry *wme, char **buf, size_t *off,
grid_get_cell(gd, i, sy, &gc); grid_get_cell(gd, i, sy, &gc);
if (gc.flags & GRID_FLAG_PADDING) if (gc.flags & GRID_FLAG_PADDING)
continue; continue;
utf8_copy(&ud, &gc.data); if (gc.flags & GRID_FLAG_TAB) {
memset(ud.data, 0, sizeof ud.data);
*ud.data = '\t';
ud.have = ud.size = 1;
ud.width = gc.data.width;
} else
utf8_copy(&ud, &gc.data);
if (ud.size == 1 && (gc.attr & GRID_ATTR_CHARSET)) { if (ud.size == 1 && (gc.attr & GRID_ATTR_CHARSET)) {
s = tty_acs_get(NULL, ud.data[0]); s = tty_acs_get(NULL, ud.data[0]);
if (s != NULL && strlen(s) <= sizeof ud.data) { if (s != NULL && strlen(s) <= sizeof ud.data) {