diff --git a/input.c b/input.c index 4c0195b7..6009d35d 100644 --- a/input.c +++ b/input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: input.c,v 1.6 2009/06/04 14:42:14 nicm Exp $ */ +/* $OpenBSD: input.c,v 1.7 2009/06/04 18:48:24 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -74,6 +74,7 @@ void input_handle_sequence_vpa(struct input_ctx *); void input_handle_sequence_hpa(struct input_ctx *); void input_handle_sequence_cup(struct input_ctx *); void input_handle_sequence_cup(struct input_ctx *); +void input_handle_sequence_tbc(struct input_ctx *); void input_handle_sequence_ed(struct input_ctx *); void input_handle_sequence_el(struct input_ctx *); void input_handle_sequence_sm(struct input_ctx *); @@ -103,6 +104,7 @@ const struct input_sequence_entry input_sequence_table[] = { { 'P', input_handle_sequence_dch }, { 'd', input_handle_sequence_vpa }, { 'f', input_handle_sequence_cup }, + { 'g', input_handle_sequence_tbc }, { 'h', input_handle_sequence_sm }, { 'l', input_handle_sequence_rm }, { 'm', input_handle_sequence_sgr }, @@ -645,12 +647,16 @@ input_handle_c0_control(u_char ch, struct input_ctx *ictx) screen_write_cursorleft(&ictx->ctx, 1); break; case '\011': /* TAB */ - s->cx = ((s->cx / 8) * 8) + 8; - if (s->cx > screen_size_x(s) - 1) { - s->cx = 0; - screen_write_cursordown(&ictx->ctx, 1); - } - screen_write_cursormove(&ictx->ctx, s->cx, s->cy); + /* Don't tab beyond the end of the line. */ + if (s->cx >= screen_size_x(s) - 1) + break; + + /* Find the next tab point, or use the last column if none. */ + do { + s->cx++; + if (bit_test(s->tabs, s->cx)) + break; + } while (s->cx < screen_size_x(s) - 1); break; case '\013': /* VT */ screen_write_linefeed(&ictx->ctx); @@ -670,6 +676,8 @@ input_handle_c0_control(u_char ch, struct input_ctx *ictx) void input_handle_c1_control(u_char ch, struct input_ctx *ictx) { + struct screen *s = ictx->ctx.s; + log_debug2("-- c1 %zu: %hhu (%c)", ictx->off, ch, ch); switch (ch) { @@ -680,6 +688,10 @@ input_handle_c1_control(u_char ch, struct input_ctx *ictx) screen_write_carriagereturn(&ictx->ctx); screen_write_linefeed(&ictx->ctx); break; + case 'H': /* HTS */ + if (s->cx < screen_size_x(s)) + bit_set(s->tabs, s->cx); + break; case 'M': /* RI */ screen_write_reverseindex(&ictx->ctx); break; @@ -755,7 +767,7 @@ input_handle_standard_two(u_char ch, struct input_ctx *ictx) "-- s2 %zu: %hhu (%c) %hhu", ictx->off, ch, ch, ictx->intermediate); switch (ch) { - case 'B': /* Dscs (ASCII) */ + case 'B': /* SCS */ /* * Not really supported, but fake it up enough for those that * use it to switch character sets (by redefining G0 to @@ -774,6 +786,8 @@ input_handle_standard_two(u_char ch, struct input_ctx *ictx) ictx->saved_cx = 0; ictx->saved_cy = 0; + screen_reset_tabs(ictx->ctx.s); + screen_write_scrollregion( &ictx->ctx, 0, screen_size_y(ictx->ctx.s) - 1); @@ -1027,6 +1041,31 @@ input_handle_sequence_cup(struct input_ctx *ictx) screen_write_cursormove(&ictx->ctx, m - 1, n - 1); } +void +input_handle_sequence_tbc(struct input_ctx *ictx) +{ + struct screen *s = ictx->ctx.s; + uint16_t n; + + if (ictx->private != '\0') + return; + + if (ARRAY_LENGTH(&ictx->args) > 1) + return; + if (input_get_argument(ictx, 0, &n, 1) != 0) + return; + + switch (n) { + case 0: + if (s->cx < screen_size_x(s)) + bit_clear(s->tabs, s->cx); + break; + case 3: + bit_nclear(s->tabs, 0, screen_size_x(s) - 1); + break; + } +} + void input_handle_sequence_ed(struct input_ctx *ictx) { diff --git a/screen.c b/screen.c index da7763a8..e21cb642 100644 --- a/screen.c +++ b/screen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: screen.c,v 1.2 2009/06/03 19:33:04 nicm Exp $ */ +/* $OpenBSD: screen.c,v 1.3 2009/06/04 18:48:24 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -18,6 +18,7 @@ #include +#include #include #include @@ -34,6 +35,8 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit) s->title = xstrdup(""); + s->tabs = NULL; + screen_reinit(s); } @@ -48,6 +51,8 @@ screen_reinit(struct screen *s) s->rlower = screen_size_y(s) - 1; s->mode = MODE_CURSOR; + + screen_reset_tabs(s); grid_clear_lines(s->grid, s->grid->hsize, s->grid->sy - 1); @@ -62,6 +67,21 @@ screen_free(struct screen *s) grid_destroy(s->grid); } +/* Reset tabs to default, eight spaces apart. */ +void +screen_reset_tabs(struct screen *s) +{ + u_int i; + + if (s->tabs != NULL) + xfree(s->tabs); + + if ((s->tabs = bit_alloc(screen_size_x(s))) == NULL) + fatal("bit_alloc failed"); + for (i = 8; i < screen_size_x(s); i += 8) + bit_set(s->tabs, i); +} + /* Set screen title. */ void screen_set_title(struct screen *s, const char *title) @@ -83,8 +103,17 @@ screen_resize(struct screen *s, u_int sx, u_int sy) if (sy < 1) sy = 1; - if (sx != screen_size_x(s)) + if (sx != screen_size_x(s)) { screen_resize_x(s, sx); + + /* + * It is unclear what should happen to tabs on resize. xterm + * seems to try and maintain them, rxvt resets them. Resetting + * is simpler and more reliable so let's do that. + */ + screen_reset_tabs(s); + } + if (sy != screen_size_y(s)) screen_resize_y(s, sy); } diff --git a/tmux.h b/tmux.h index 7842c5ae..06756001 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.5 2009/06/03 23:30:40 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.6 2009/06/04 18:48:24 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -48,6 +48,7 @@ #include #endif +#include #include #include #include @@ -576,6 +577,8 @@ struct screen { int mode; + bitstr_t *tabs; + struct screen_sel sel; }; @@ -1518,6 +1521,7 @@ void screen_redraw_status(struct client *); void screen_init(struct screen *, u_int, u_int, u_int); void screen_reinit(struct screen *); void screen_free(struct screen *); +void screen_reset_tabs(struct screen *); void screen_set_title(struct screen *, const char *); void screen_resize(struct screen *, u_int, u_int); void screen_set_selection(