From 6674197e853ddec4ab1af04ede3ebabcdcc581c5 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Mon, 8 Sep 2008 22:03:56 +0000 Subject: [PATCH] Fix bold/non-bold mismatch in 256 colour mode by adding an extra 8 bits (ick) onto the attributes and using two of them to mark the fg and bg as 256 colours when necessary. If only it was 255 colours we would have one value for default and wouln't need this :-/. --- input.c | 25 ++++++------- screen-display.c | 21 +++++++---- screen-redraw.c | 11 +++--- screen-write.c | 4 +- screen.c | 40 ++++++++++++-------- status.c | 9 +++-- tmux.h | 26 +++++++------ tty.c | 95 +++++++++++++++++++++++++++++++----------------- 8 files changed, 136 insertions(+), 95 deletions(-) diff --git a/input.c b/input.c index 0ae1bc5c..475cf22a 100644 --- a/input.c +++ b/input.c @@ -1,4 +1,4 @@ -/* $Id: input.c,v 1.55 2008-09-08 21:05:41 nicm Exp $ */ +/* $Id: input.c,v 1.56 2008-09-08 22:03:54 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -493,7 +493,7 @@ void input_handle_c0_control(u_char ch, struct input_ctx *ictx) { struct screen *s = ictx->ctx.s; - u_char attr; + u_short attr; log_debug2("-- c0 %zu: %hhu", ictx->off, ch); @@ -1053,7 +1053,8 @@ input_handle_sequence_sgr(struct input_ctx *ictx) struct screen *s = ictx->ctx.s; u_int i, n; uint16_t m, o; - u_char attr, fg, bg; + u_short attr; + u_char fg, bg; attr = s->attr; fg = s->fg; @@ -1075,19 +1076,11 @@ input_handle_sequence_sgr(struct input_ctx *ictx) if (input_get_argument(ictx, 2, &m, 0) != 0) return; if (o == 38) { - if (m > 7 && m < 16) { - /* XXX this is not right; colours 8-15 are not the same as bold */ - attr |= ATTR_BRIGHT; - m -= 8; - } + attr |= ATTR_FG256; fg = m; break; } else if (o == 48) { - if (m > 7 && m < 16) { - /* XXX this is not right; colours 8-15 are not the same as bold */ - attr |= ATTR_BRIGHT; - m -= 8; - } + attr |= ATTR_BG256; bg = m; break; } @@ -1139,9 +1132,11 @@ input_handle_sequence_sgr(struct input_ctx *ictx) case 35: case 36: case 37: + attr &= ~ATTR_FG256; fg = m - 30; break; case 39: + attr &= ~ATTR_FG256; fg = 8; break; case 40: @@ -1151,10 +1146,12 @@ input_handle_sequence_sgr(struct input_ctx *ictx) case 44: case 45: case 46: - case 47: + case 47: + attr &= ~ATTR_BG256; bg = m - 40; break; case 49: + attr &= ~ATTR_BG256; bg = 8; break; } diff --git a/screen-display.c b/screen-display.c index 06ec6caf..be8c8e93 100644 --- a/screen-display.c +++ b/screen-display.c @@ -1,4 +1,4 @@ -/* $Id: screen-display.c,v 1.19 2008-09-08 17:40:50 nicm Exp $ */ +/* $Id: screen-display.c,v 1.20 2008-09-08 22:03:54 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -25,7 +25,7 @@ /* Set a cell. */ void screen_display_set_cell(struct screen *s, - u_int px, u_int py, u_char data, u_char attr, u_char fg, u_char bg) + u_int px, u_int py, u_char data, u_short attr, u_char fg, u_char bg) { screen_set_cell( s, screen_x(s, px), screen_y(s, py), data, attr, fg, bg); @@ -75,7 +75,7 @@ screen_display_move_lines(struct screen *s, u_int dy, u_int py, u_int ny) /* Fill a set of cells. */ void screen_display_fill_area(struct screen *s, u_int px, u_int py, - u_int nx, u_int ny, u_char data, u_char attr, u_char fg, u_char bg) + u_int nx, u_int ny, u_char data, u_short attr, u_char fg, u_char bg) { if (nx == 0 || ny == 0) { SCREEN_DEBUG4(s, px, py, nx, ny); @@ -378,10 +378,14 @@ screen_display_insert_characters(struct screen *s, u_int px, u_int py, u_int nx) if (px + nx != screen_last_x(s)) { mx = screen_last_x(s) - (px + nx); - memmove(&s->grid_data[py][px + nx], &s->grid_data[py][px], mx); - memmove(&s->grid_attr[py][px + nx], &s->grid_attr[py][px], mx); - memmove(&s->grid_fg[py][px + nx], &s->grid_fg[py][px], mx); - memmove(&s->grid_bg[py][px + nx], &s->grid_bg[py][px], mx); + memmove(&s->grid_data[py][px + nx], + &s->grid_data[py][px], mx * sizeof **s->grid_data); + memmove(&s->grid_attr[py][px + nx], + &s->grid_attr[py][px], mx * sizeof **s->grid_attr); + memmove(&s->grid_fg[py][px + nx], + &s->grid_fg[py][px], mx * sizeof **s->grid_fg); + memmove(&s->grid_bg[py][px + nx], + &s->grid_bg[py][px], mx * sizeof **s->grid_bg); } memset(&s->grid_data[py][px], ' ', nx); @@ -437,7 +441,8 @@ screen_display_copy_area(struct screen *dst, struct screen *src, u_int px, u_int py, u_int nx, u_int ny, u_int ox, u_int oy) { u_int i, j; - u_char data, attr, fg, bg; + u_short attr; + u_char data, fg, bg; if (nx == 0 || ny == 0) { SCREEN_DEBUG4(dst, px, py, nx, ny); diff --git a/screen-redraw.c b/screen-redraw.c index 39687664..a66aee45 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -1,4 +1,4 @@ -/* $Id: screen-redraw.c,v 1.10 2008-09-08 17:40:51 nicm Exp $ */ +/* $Id: screen-redraw.c,v 1.11 2008-09-08 22:03:54 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -23,7 +23,7 @@ #include "tmux.h" void screen_redraw_get_cell(struct screen_redraw_ctx *, - u_int, u_int, u_char *, u_char *, u_char *, u_char *); + u_int, u_int, u_char *, u_short *, u_char *, u_char *); /* Initialise redrawing with a window. */ void @@ -99,7 +99,7 @@ screen_redraw_stop(struct screen_redraw_ctx *ctx) /* Get cell data. */ void screen_redraw_get_cell(struct screen_redraw_ctx *ctx, - u_int px, u_int py, u_char *data, u_char *attr, u_char *fg, u_char *bg) + u_int px, u_int py, u_char *data, u_short *attr, u_char *fg, u_char *bg) { struct screen *s = ctx->s; @@ -121,7 +121,7 @@ screen_redraw_move_cursor(struct screen_redraw_ctx *ctx, u_int px, u_int py) /* Set attributes. */ void screen_redraw_set_attributes( - struct screen_redraw_ctx *ctx, u_char attr, u_char fg, u_char bg) + struct screen_redraw_ctx *ctx, u_short attr, u_char fg, u_char bg) { ctx->write(ctx->data, TTY_ATTRIBUTES, attr, fg, bg); } @@ -151,7 +151,8 @@ screen_redraw_write_string(struct screen_redraw_ctx *ctx, const char *fmt, ...) void screen_redraw_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py) { - u_char data, attr, fg, bg; + u_short attr; + u_char data, fg, bg; screen_redraw_move_cursor(ctx, px, py); screen_redraw_get_cell(ctx, px, py, &data, &attr, &fg, &bg); diff --git a/screen-write.c b/screen-write.c index ddcaff6c..c4f3fef1 100644 --- a/screen-write.c +++ b/screen-write.c @@ -1,4 +1,4 @@ -/* $Id: screen-write.c,v 1.11 2008-09-08 17:40:51 nicm Exp $ */ +/* $Id: screen-write.c,v 1.12 2008-09-08 22:03:54 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -172,7 +172,7 @@ screen_write_put_string(struct screen_write_ctx *ctx, const char *fmt, ...) /* Set screen attributes. */ void screen_write_set_attributes( - struct screen_write_ctx *ctx, u_char attr, u_char fg, u_char bg) + struct screen_write_ctx *ctx, u_short attr, u_char fg, u_char bg) { struct screen *s = ctx->s; diff --git a/screen.c b/screen.c index d20e04aa..06d34083 100644 --- a/screen.c +++ b/screen.c @@ -1,4 +1,4 @@ -/* $Id: screen.c,v 1.67 2008-09-08 17:40:51 nicm Exp $ */ +/* $Id: screen.c,v 1.68 2008-09-08 22:03:54 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -279,14 +279,18 @@ screen_expand_line(struct screen *s, u_int py, u_int nx) ox = s->grid_size[py]; s->grid_size[py] = nx; - s->grid_data[py] = xrealloc(s->grid_data[py], 1, nx); - memset(&s->grid_data[py][ox], ' ', nx - ox); - s->grid_attr[py] = xrealloc(s->grid_attr[py], 1, nx); - memset(&s->grid_attr[py][ox], 0, nx - ox); - s->grid_fg[py] = xrealloc(s->grid_fg[py], 1, nx); - memset(&s->grid_fg[py][ox], 8, nx - ox); - s->grid_bg[py] = xrealloc(s->grid_bg[py], 1, nx); - memset(&s->grid_bg[py][ox], 8, nx - ox); + s->grid_data[py] = xrealloc( + s->grid_data[py], sizeof **s->grid_data, nx); + memset(&s->grid_data[py][ox], ' ', (nx - ox) * sizeof **s->grid_data); + s->grid_attr[py] = xrealloc( + s->grid_attr[py], sizeof **s->grid_attr, nx); + memset(&s->grid_attr[py][ox], 0, (nx - ox) * sizeof **s->grid_attr); + s->grid_fg[py] = xrealloc( + s->grid_fg[py], sizeof **s->grid_fg, nx); + memset(&s->grid_fg[py][ox], 8, (nx - ox) * sizeof **s->grid_fg); + s->grid_bg[py] = xrealloc( + s->grid_bg[py], sizeof **s->grid_bg, nx); + memset(&s->grid_bg[py][ox], 8, (nx - ox) * sizeof **s->grid_bg); } /* Reduce line. */ @@ -295,16 +299,20 @@ screen_reduce_line(struct screen *s, u_int py, u_int nx) { s->grid_size[py] = nx; - s->grid_data[py] = xrealloc(s->grid_data[py], 1, nx); - s->grid_attr[py] = xrealloc(s->grid_attr[py], 1, nx); - s->grid_fg[py] = xrealloc(s->grid_fg[py], 1, nx); - s->grid_bg[py] = xrealloc(s->grid_bg[py], 1, nx); + s->grid_data[py] = xrealloc( + s->grid_data[py], sizeof **s->grid_data, nx); + s->grid_attr[py] = xrealloc( + s->grid_attr[py], sizeof **s->grid_attr, nx); + s->grid_fg[py] = xrealloc( + s->grid_fg[py], sizeof **s->grid_fg, nx); + s->grid_bg[py] = xrealloc( + s->grid_bg[py], sizeof **s->grid_bg, nx); } /* Get cell. */ void screen_get_cell(struct screen *s, - u_int cx, u_int cy, u_char *data, u_char *attr, u_char *fg, u_char *bg) + u_int cx, u_int cy, u_char *data, u_short *attr, u_char *fg, u_char *bg) { if (cx >= s->grid_size[cy]) { *data = ' '; @@ -325,7 +333,7 @@ screen_get_cell(struct screen *s, /* Set a cell. */ void screen_set_cell(struct screen *s, - u_int cx, u_int cy, u_char data, u_char attr, u_char fg, u_char bg) + u_int cx, u_int cy, u_char data, u_short attr, u_char fg, u_char bg) { if (cx >= s->grid_size[cy]) screen_expand_line(s, cy, cx + 1); @@ -406,7 +414,7 @@ screen_move_lines(struct screen *s, u_int dy, u_int py, u_int ny) /* Fill an area. */ void screen_fill_area(struct screen *s, u_int px, u_int py, - u_int nx, u_int ny, u_char data, u_char attr, u_char fg, u_char bg) + u_int nx, u_int ny, u_char data, u_short attr, u_char fg, u_char bg) { u_int i, j; diff --git a/status.c b/status.c index cca8a79a..6f2a534d 100644 --- a/status.c +++ b/status.c @@ -1,4 +1,4 @@ -/* $Id: status.c,v 1.44 2008-09-08 17:40:51 nicm Exp $ */ +/* $Id: status.c,v 1.45 2008-09-08 22:03:54 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -25,7 +25,7 @@ #include "tmux.h" size_t status_width(struct winlink *); -char *status_print(struct session *, struct winlink *, u_char *); +char *status_print(struct session *, struct winlink *, u_short *); /* Draw status for client on the last lines of given context. */ void @@ -38,7 +38,8 @@ status_redraw(struct client *c) char lbuf[BUFSIZ], rbuf[BUFSIZ]; size_t llen, rlen, offset, xx, yy; size_t size, start, width; - u_char attr, fg, bg; + u_short attr; + u_char fg, bg; struct tm *tm; time_t t; int larrow, rarrow; @@ -275,7 +276,7 @@ status_width(struct winlink *wl) } char * -status_print(struct session *s, struct winlink *wl, u_char *attr) +status_print(struct session *s, struct winlink *wl, u_short *attr) { char *text, flag; diff --git a/tmux.h b/tmux.h index fa2a1b5f..d9a19e89 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.183 2008-09-08 17:40:51 nicm Exp $ */ +/* $Id: tmux.h,v 1.184 2008-09-08 22:03:54 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -395,6 +395,8 @@ struct msg_resize_data { #define ATTR_HIDDEN 0x20 #define ATTR_ITALICS 0x40 #define ATTR_CHARSET 0x80 /* alternative character set */ +#define ATTR_FG256 0x100 +#define ATTR_BG256 0x200 /* Modes. */ #define MODE_CURSOR 0x01 @@ -420,7 +422,7 @@ struct screen { char *title; u_char **grid_data; - u_char **grid_attr; + u_short **grid_attr; u_char **grid_fg; u_char **grid_bg; u_int *grid_size; @@ -436,13 +438,13 @@ struct screen { u_int cx; /* cursor x */ u_int cy; /* cursor y */ - u_char attr; + u_short attr; u_char fg; u_char bg; u_int saved_cx; u_int saved_cy; - u_char saved_attr; + u_short saved_attr; u_char saved_fg; u_char saved_bg; @@ -692,7 +694,7 @@ struct tty { struct termios tio; - u_char attr; + u_short attr; u_char fg; u_char bg; @@ -1139,12 +1141,12 @@ void input_key(struct window *, int); /* screen-display.c */ void screen_display_set_cell( - struct screen *, u_int, u_int, u_char, u_char, u_char, u_char); + struct screen *, u_int, u_int, u_char, u_short, u_char, u_char); void screen_display_make_lines(struct screen *, u_int, u_int); void screen_display_free_lines(struct screen *, u_int, u_int); void screen_display_move_lines(struct screen *, u_int, u_int, u_int); void screen_display_fill_area(struct screen *, - u_int, u_int, u_int, u_int, u_char, u_char, u_char, u_char); + u_int, u_int, u_int, u_int, u_char, u_short, u_char, u_char); void screen_display_scroll_region_up(struct screen *); void screen_display_scroll_region_down(struct screen *); void screen_display_insert_lines(struct screen *, u_int, u_int); @@ -1171,7 +1173,7 @@ size_t printflike2 screen_write_put_string_rjust( void printflike2 screen_write_put_string( struct screen_write_ctx *, const char *, ...); void screen_write_set_attributes( - struct screen_write_ctx *, u_char, u_char, u_char); + struct screen_write_ctx *, u_short, u_char, u_char); void screen_write_set_region(struct screen_write_ctx *, u_int, u_int); void screen_write_cursor_up_scroll(struct screen_write_ctx *); void screen_write_cursor_down_scroll(struct screen_write_ctx *); @@ -1204,7 +1206,7 @@ void screen_redraw_start(struct screen_redraw_ctx *, void screen_redraw_stop(struct screen_redraw_ctx *); void screen_redraw_move_cursor(struct screen_redraw_ctx *, u_int, u_int); void screen_redraw_set_attributes( - struct screen_redraw_ctx *, u_char, u_char, u_char); + struct screen_redraw_ctx *, u_short, u_char, u_char); void printflike2 screen_redraw_write_string( struct screen_redraw_ctx *, const char *, ...); void screen_redraw_cell(struct screen_redraw_ctx *, u_int, u_int); @@ -1223,14 +1225,14 @@ void screen_resize(struct screen *, u_int, u_int); void screen_expand_line(struct screen *, u_int, u_int); void screen_reduce_line(struct screen *, u_int, u_int); void screen_get_cell(struct screen *, - u_int, u_int, u_char *, u_char *, u_char *, u_char *); + u_int, u_int, u_char *, u_short *, u_char *, u_char *); void screen_set_cell( - struct screen *, u_int, u_int, u_char, u_char, u_char, u_char); + struct screen *, u_int, u_int, u_char, u_short, u_char, u_char); void screen_make_lines(struct screen *, u_int, u_int); void screen_free_lines(struct screen *, u_int, u_int); void screen_move_lines(struct screen *, u_int, u_int, u_int); void screen_fill_area(struct screen *, - u_int, u_int, u_int, u_int, u_char, u_char, u_char, u_char); + u_int, u_int, u_int, u_int, u_char, u_short, u_char, u_char); void screen_set_selection(struct screen *, u_int, u_int, u_int, u_int); void screen_clear_selection(struct screen *); int screen_check_selection(struct screen *, u_int, u_int); diff --git a/tty.c b/tty.c index 955378ff..9f99cc61 100644 --- a/tty.c +++ b/tty.c @@ -1,4 +1,4 @@ -/* $Id: tty.c,v 1.39 2008-09-08 21:04:59 nicm Exp $ */ +/* $Id: tty.c,v 1.40 2008-09-08 22:03:56 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -39,7 +39,9 @@ void tty_raw(struct tty *, const char *); void tty_puts(struct tty *, const char *); void tty_putc(struct tty *, char); -void tty_attributes(struct tty *, u_char, u_char, u_char); +void tty_attributes(struct tty *, u_short, u_char, u_char); +u_char tty_attributes_fg(struct tty *, u_char); +u_char tty_attributes_bg(struct tty *, u_char); char tty_translate(char); TAILQ_HEAD(, tty_term) tty_terms = TAILQ_HEAD_INITIALIZER(tty_terms); @@ -602,17 +604,14 @@ tty_vwrite(struct tty *tty, struct screen *s, int cmd, va_list ap) } void -tty_attributes(struct tty *tty, u_char attr, u_char fg, u_char bg) +tty_attributes(struct tty *tty, u_short attr, u_char fg, u_char bg) { - char s[32]; - if (attr == tty->attr && fg == tty->fg && bg == tty->bg) return; /* If any bits are being cleared, reset everything. */ if (tty->attr & ~attr) { - if ((tty->attr & ATTR_CHARSET) && - exit_alt_charset_mode != NULL) + if ((tty->attr & ATTR_CHARSET) && exit_alt_charset_mode != NULL) tty_puts(tty, exit_alt_charset_mode); tty_puts(tty, exit_attribute_mode); tty->fg = 8; @@ -620,10 +619,11 @@ tty_attributes(struct tty *tty, u_char attr, u_char fg, u_char bg) tty->attr = 0; } - /* Filter out bits already set. */ + /* Filter out attribute bits already set. */ attr &= ~tty->attr; tty->attr |= attr; + /* Set the attributes. */ if ((attr & ATTR_BRIGHT) && enter_bold_mode != NULL) tty_puts(tty, enter_bold_mode); if ((attr & ATTR_DIM) && enter_dim_mode != NULL) @@ -641,38 +641,65 @@ tty_attributes(struct tty *tty, u_char attr, u_char fg, u_char bg) if ((attr & ATTR_CHARSET) && enter_alt_charset_mode != NULL) tty_puts(tty, enter_alt_charset_mode); - if (fg != tty->fg) { - if (fg > 15 && tty->term->flags & TERM_256COLOURS) { + /* Set foreground colour. */ + if (fg != tty->fg || attr & ATTR_FG256) + tty->fg = tty_attributes_fg(tty, fg); + + /* Set background colour. */ + if (bg != tty->bg || attr & ATTR_BG256) + tty->bg = tty_attributes_bg(tty, bg); +} + +u_char +tty_attributes_fg(struct tty *tty, u_char fg) +{ + char s[32]; + + if (tty->attr & ATTR_FG256) { + if (tty->term->flags & TERM_256COLOURS) { xsnprintf(s, sizeof s, "\033[38;5;%hhum", fg); tty_puts(tty, s); - } else { - if (fg > 7) - fg = 8; - if (fg == 8 && !(tty->term->flags & TERM_HASDEFAULTS)) - fg = 7; - if (fg == 8) - tty_puts(tty, "\033[39m"); - else if (set_a_foreground != NULL) - tty_puts(tty, tparm(set_a_foreground, fg)); + return (fg); } - } - if (bg != tty->bg) { - if (bg > 15 && tty->term->flags & TERM_256COLOURS) { + if (fg > 15) + fg = 8; + else if (fg > 7) + fg -= 8; + } + + if (fg == 8 && !(tty->term->flags & TERM_HASDEFAULTS)) + fg = 7; + if (fg == 8) + tty_puts(tty, "\033[39m"); + else if (set_a_foreground != NULL) + tty_puts(tty, tparm(set_a_foreground, fg)); + return (fg); +} + +u_char +tty_attributes_bg(struct tty *tty, u_char bg) +{ + char s[32]; + + if (tty->attr & ATTR_BG256) { + if (tty->term->flags & TERM_256COLOURS) { xsnprintf(s, sizeof s, "\033[48;5;%hhum", bg); tty_puts(tty, s); - } else { - if (bg > 7) - bg = 8; - if (bg == 8 && !(tty->term->flags & TERM_HASDEFAULTS)) - bg = 0; - if (bg == 8) - tty_puts(tty, "\033[49m"); - else if (set_a_background != NULL) - tty_puts(tty, tparm(set_a_background, bg)); + return (bg); } - } - tty->fg = fg; - tty->bg = bg; + if (bg > 15) + bg = 8; + else if (bg > 7) + bg -= 8; + } + + if (bg == 8 && !(tty->term->flags & TERM_HASDEFAULTS)) + bg = 0; + if (bg == 8) + tty_puts(tty, "\033[49m"); + else if (set_a_background != NULL) + tty_puts(tty, tparm(set_a_background, bg)); + return (bg); }