From cecb13f6928246c1fc9f49c5613938b97b86da3d Mon Sep 17 00:00:00 2001 From: simon Date: Sun, 28 Nov 2004 15:13:34 +0000 Subject: [PATCH] Implement xterm 256-colour mode. git-svn-id: svn://svn.tartarus.org/sgt/putty@4917 cda61777-01e9-0310-a592-d414129be87e --- config.c | 3 ++ doc/config.but | 8 ++++ putty.h | 49 ++++++++++++++------- settings.c | 2 + terminal.c | 124 ++++++++++++++++++++++++++++++++++++++++-------------- unix/pterm.c | 106 +++++++++++++++++++++++++++------------------- windows/window.c | 97 +++++++++++++++++++++++++----------------- windows/winhelp.h | 1 + 8 files changed, 260 insertions(+), 130 deletions(-) diff --git a/config.c b/config.c index 99882a17..2c0c3b95 100644 --- a/config.c +++ b/config.c @@ -1237,6 +1237,9 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist, ctrl_checkbox(s, "Allow terminal to specify ANSI colours", 'i', HELPCTX(colours_ansi), dlg_stdcheckbox_handler, I(offsetof(Config,ansi_colour))); + ctrl_checkbox(s, "Allow terminal to use xterm 256-colour mode", '2', + HELPCTX(colours_xterm256), dlg_stdcheckbox_handler, + I(offsetof(Config,xterm_256_colour))); ctrl_checkbox(s, "Bolded text is a different colour", 'b', HELPCTX(colours_bold), dlg_stdcheckbox_handler, I(offsetof(Config,bold_colour))); diff --git a/doc/config.but b/doc/config.but index e7e5db2c..db0369b6 100644 --- a/doc/config.but +++ b/doc/config.but @@ -1401,6 +1401,14 @@ If you have a particularly garish application, you might want to turn this option off and make PuTTY only use the default foreground and background colours. +\S{config-xtermcolour} \q{Allow terminal to use xterm 256-colour mode} + +\cfg{winhelp-topic}{colours.xterm256} + +This option is enabled by default. If it is disabled, PuTTY will +ignore any control sequences sent by the server which use the +extended 256-colour mode supported by recent versions of \cw{xterm}. + \S{config-boldcolour} \q{Bolded text is a different colour} \cfg{winhelp-topic}{colours.bold} diff --git a/putty.h b/putty.h index d880dbe2..b50058c3 100644 --- a/putty.h +++ b/putty.h @@ -80,24 +80,40 @@ typedef struct terminal_tag Terminal; */ #define UCSWIDE 0xDFFF -#define ATTR_NARROW 0x8000U -#define ATTR_WIDE 0x4000U -#define ATTR_BOLD 0x0400U -#define ATTR_UNDER 0x0800U -#define ATTR_REVERSE 0x1000U -#define ATTR_BLINK 0x2000U -#define ATTR_FGMASK 0x001FU -#define ATTR_BGMASK 0x03E0U -#define ATTR_COLOURS 0x03FFU +#define ATTR_NARROW 0x800000U +#define ATTR_WIDE 0x400000U +#define ATTR_BOLD 0x040000U +#define ATTR_UNDER 0x080000U +#define ATTR_REVERSE 0x100000U +#define ATTR_BLINK 0x200000U +#define ATTR_FGMASK 0x0001FFU +#define ATTR_BGMASK 0x03FE00U +#define ATTR_COLOURS 0x03FFFFU #define ATTR_FGSHIFT 0 -#define ATTR_BGSHIFT 5 +#define ATTR_BGSHIFT 9 -#define ATTR_DEFAULT 0x0128U /* bg 9, fg 8 */ -#define ATTR_DEFFG 0x0008U -#define ATTR_DEFBG 0x0120U - -#define ATTR_CUR_AND (~(ATTR_BOLD|ATTR_REVERSE|ATTR_BLINK|ATTR_COLOURS)) -#define ATTR_CUR_XOR 0x016AU +/* + * The definitive list of colour numbers stored in terminal + * attribute words is kept here. It is: + * + * - 0-7 are ANSI colours (KRGYBMCW). + * - 8-15 are the bold versions of those colours. + * - 16-255 are the remains of the xterm 256-colour mode (a + * 216-colour cube with R at most significant and B at least, + * followed by a uniform series of grey shades running between + * black and white but not including either on grounds of + * redundancy). + * - 256 is default foreground + * - 257 is default bold foreground + * - 258 is default background + * - 259 is default bold background + * - 260 is cursor foreground + * - 261 is cursor background + */ + +#define ATTR_DEFFG (256 << ATTR_FGSHIFT) +#define ATTR_DEFBG (258 << ATTR_BGSHIFT) +#define ATTR_DEFAULT (ATTR_DEFFG | ATTR_DEFBG) struct sesslist { int nsessions; @@ -447,6 +463,7 @@ struct config_tag { int bidi; /* Colour options */ int ansi_colour; + int xterm_256_colour; int system_colour; int try_palette; int bold_colour; diff --git a/settings.c b/settings.c index 4f65fc5d..749760a8 100644 --- a/settings.c +++ b/settings.c @@ -289,6 +289,7 @@ void save_open_settings(void *sesskey, int do_host, Config *cfg) write_setting_i(sesskey, "UseSystemColours", cfg->system_colour); write_setting_i(sesskey, "TryPalette", cfg->try_palette); write_setting_i(sesskey, "ANSIColour", cfg->ansi_colour); + write_setting_i(sesskey, "Xterm256Colour", cfg->xterm_256_colour); write_setting_i(sesskey, "BoldAsColour", cfg->bold_colour); for (i = 0; i < 22; i++) { @@ -555,6 +556,7 @@ void load_open_settings(void *sesskey, int do_host, Config *cfg) gppi(sesskey, "UseSystemColours", 0, &cfg->system_colour); gppi(sesskey, "TryPalette", 0, &cfg->try_palette); gppi(sesskey, "ANSIColour", 1, &cfg->ansi_colour); + gppi(sesskey, "Xterm256Colour", 1, &cfg->xterm_256_colour); gppi(sesskey, "BoldAsColour", 1, &cfg->bold_colour); for (i = 0; i < 22; i++) { diff --git a/terminal.c b/terminal.c index 0f0c9d83..aa231962 100644 --- a/terminal.c +++ b/terminal.c @@ -554,15 +554,39 @@ static void makeliteral_attr(struct buf *b, termchar *c, unsigned long *state) * store a two-byte value with the top bit clear (indicating * just that value), or a four-byte value with the top bit set * (indicating the same value with its top bit clear). + * + * However, first I permute the bits of the attribute value, so + * that the eight bits of colour (four in each of fg and bg) + * which are never non-zero unless xterm 256-colour mode is in + * use are placed higher up the word than everything else. This + * ensures that attribute values remain 16-bit _unless_ the + * user uses extended colour. */ - if (c->attr < 0x8000) { - add(b, (unsigned char)((c->attr >> 8) & 0xFF)); - add(b, (unsigned char)(c->attr & 0xFF)); + unsigned attr, colourbits; + + attr = c->attr; + + assert(ATTR_BGSHIFT > ATTR_FGSHIFT); + + colourbits = (attr >> (ATTR_BGSHIFT + 4)) & 0xF; + colourbits <<= 4; + colourbits |= (attr >> (ATTR_FGSHIFT + 4)) & 0xF; + + attr = (((attr >> (ATTR_BGSHIFT + 8)) << (ATTR_BGSHIFT + 4)) | + (attr & ((1 << (ATTR_BGSHIFT + 4))-1))); + attr = (((attr >> (ATTR_FGSHIFT + 8)) << (ATTR_FGSHIFT + 4)) | + (attr & ((1 << (ATTR_FGSHIFT + 4))-1))); + + attr |= (colourbits << (32-9)); + + if (attr < 0x8000) { + add(b, (unsigned char)((attr >> 8) & 0xFF)); + add(b, (unsigned char)(attr & 0xFF)); } else { - add(b, (unsigned char)(((c->attr >> 24) & 0x7F) | 0x80)); - add(b, (unsigned char)((c->attr >> 16) & 0xFF)); - add(b, (unsigned char)((c->attr >> 8) & 0xFF)); - add(b, (unsigned char)(c->attr & 0xFF)); + add(b, (unsigned char)(((attr >> 24) & 0x7F) | 0x80)); + add(b, (unsigned char)((attr >> 16) & 0xFF)); + add(b, (unsigned char)((attr >> 8) & 0xFF)); + add(b, (unsigned char)(attr & 0xFF)); } } static void makeliteral_cc(struct buf *b, termchar *c, unsigned long *state) @@ -758,18 +782,30 @@ static void readliteral_chr(struct buf *b, termchar *c, termline *ldata, static void readliteral_attr(struct buf *b, termchar *c, termline *ldata, unsigned long *state) { - int val; + unsigned val, attr, colourbits; val = get(b) << 8; val |= get(b); if (val >= 0x8000) { + val &= ~0x8000; val <<= 16; val |= get(b) << 8; val |= get(b); } - c->attr = val; + colourbits = (val >> (32-9)) & 0xFF; + attr = (val & ((1<<(32-9))-1)); + + attr = (((attr >> (ATTR_FGSHIFT + 4)) << (ATTR_FGSHIFT + 8)) | + (attr & ((1 << (ATTR_FGSHIFT + 4))-1))); + attr = (((attr >> (ATTR_BGSHIFT + 4)) << (ATTR_BGSHIFT + 8)) | + (attr & ((1 << (ATTR_BGSHIFT + 4))-1))); + + attr |= (colourbits >> 4) << (ATTR_BGSHIFT + 4); + attr |= (colourbits & 0xF) << (ATTR_FGSHIFT + 4); + + c->attr = attr; } static void readliteral_cc(struct buf *b, termchar *c, termline *ldata, unsigned long *state) @@ -1024,6 +1060,14 @@ static void term_timer(void *ctx, long now) term_update(term); } +static void term_schedule_update(Terminal *term) +{ + if (!term->window_update_pending) { + term->window_update_pending = TRUE; + term->next_update = schedule_timer(UPDATE_DELAY, term_timer, term); + } +} + /* * Call this whenever the terminal window state changes, to queue * an update. @@ -1031,10 +1075,7 @@ static void term_timer(void *ctx, long now) static void seen_disp_event(Terminal *term) { term->seen_disp_event = TRUE; /* for scrollback-reset-on-activity */ - if (!term->window_update_pending) { - term->window_update_pending = TRUE; - term->next_update = schedule_timer(UPDATE_DELAY, term_timer, term); - } + term_schedule_update(term); } /* @@ -3471,7 +3512,7 @@ static void term_out(Terminal *term) /* xterm-style bright foreground */ term->curr_attr &= ~ATTR_FGMASK; term->curr_attr |= - ((term->esc_args[i] - 90 + 16) + ((term->esc_args[i] - 90 + 8) << ATTR_FGSHIFT); break; case 39: /* default-foreground */ @@ -3502,13 +3543,33 @@ static void term_out(Terminal *term) /* xterm-style bright background */ term->curr_attr &= ~ATTR_BGMASK; term->curr_attr |= - ((term->esc_args[i] - 100 + 16) + ((term->esc_args[i] - 100 + 8) << ATTR_BGSHIFT); break; case 49: /* default-background */ term->curr_attr &= ~ATTR_BGMASK; term->curr_attr |= ATTR_DEFBG; break; + case 38: /* xterm 256-colour mode */ + if (i+2 < term->esc_nargs && + term->esc_args[i+1] == 5) { + term->curr_attr &= ~ATTR_FGMASK; + term->curr_attr |= + ((term->esc_args[i+2] & 0xFF) + << ATTR_FGSHIFT); + i += 2; + } + break; + case 48: /* xterm 256-colour mode */ + if (i+2 < term->esc_nargs && + term->esc_args[i+1] == 5) { + term->curr_attr &= ~ATTR_BGMASK; + term->curr_attr |= + ((term->esc_args[i+2] & 0xFF) + << ATTR_BGSHIFT); + i += 2; + } + break; } } set_erase_char(term); @@ -3801,7 +3862,7 @@ static void term_out(Terminal *term) if (term->esc_args[0] >= 0 && term->esc_args[0] < 16) { long colour = (sco2ansicolour[term->esc_args[0] & 0x7] | - ((term->esc_args[0] & 0x8) << 1)) << + (term->esc_args[0] & 0x8)) << ATTR_FGSHIFT; term->curr_attr &= ~ATTR_FGMASK; term->curr_attr |= colour; @@ -3814,7 +3875,7 @@ static void term_out(Terminal *term) if (term->esc_args[0] >= 0 && term->esc_args[0] < 16) { long colour = (sco2ansicolour[term->esc_args[0] & 0x7] | - ((term->esc_args[0] & 0x8) << 1)) << + (term->esc_args[0] & 0x8)) << ATTR_BGSHIFT; term->curr_attr &= ~ATTR_BGMASK; term->curr_attr |= colour; @@ -4255,22 +4316,14 @@ static void term_out(Terminal *term) term->termstate = TOPLEVEL; term->curr_attr &= ~ATTR_FGMASK; term->curr_attr &= ~ATTR_BOLD; - term->curr_attr |= (c & 0x7) << ATTR_FGSHIFT; - if ((c & 0x8) || term->vt52_bold) - term->curr_attr |= ATTR_BOLD; - + term->curr_attr |= (c & 0xF) << ATTR_FGSHIFT; set_erase_char(term); break; case VT52_BG: term->termstate = TOPLEVEL; term->curr_attr &= ~ATTR_BGMASK; term->curr_attr &= ~ATTR_BLINK; - term->curr_attr |= (c & 0x7) << ATTR_BGSHIFT; - - /* Note: bold background */ - if (c & 0x8) - term->curr_attr |= ATTR_BLINK; - + term->curr_attr |= (c & 0xF) << ATTR_BGSHIFT; set_erase_char(term); break; #endif @@ -4612,6 +4665,16 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise) tattr = (tattr & ~(ATTR_FGMASK | ATTR_BGMASK)) | ATTR_DEFFG | ATTR_DEFBG; + if (!term->cfg.xterm_256_colour) { + int colour; + colour = (tattr & ATTR_FGMASK) >> ATTR_FGSHIFT; + if (colour >= 16 && colour < 256) + tattr = (tattr &~ ATTR_FGMASK) | ATTR_DEFFG; + colour = (tattr & ATTR_BGMASK) >> ATTR_BGSHIFT; + if (colour >= 16 && colour < 256) + tattr = (tattr &~ ATTR_BGMASK) | ATTR_DEFBG; + } + switch (tchar & CSET_MASK) { case CSET_ASCII: tchar = term->ucsdata->unitab_line[tchar & 0xFF]; @@ -4849,6 +4912,8 @@ void term_invalidate(Terminal *term) for (i = 0; i < term->rows; i++) for (j = 0; j < term->cols; j++) term->disptext[i]->chars[j].attr = ATTR_INVALID; + + term_schedule_update(term); } /* @@ -4875,10 +4940,7 @@ void term_paint(Terminal *term, Context ctx, if (immediately) { do_paint (term, ctx, FALSE); } else { - if (!term->window_update_pending) { - term->window_update_pending = TRUE; - term->next_update = schedule_timer(UPDATE_DELAY, term_timer, term); - } + term_schedule_update(term); } } diff --git a/unix/pterm.c b/unix/pterm.c index 59a99c1e..5254bf37 100644 --- a/unix/pterm.c +++ b/unix/pterm.c @@ -33,7 +33,10 @@ #define CAT(x,y) CAT2(x,y) #define ASSERT(x) enum {CAT(assertion_,__LINE__) = 1 / (x)} -#define NCOLOURS (lenof(((Config *)0)->colours)) +/* Colours come in two flavours: configurable, and xterm-extended. */ +#define NCFGCOLOURS (lenof(((Config *)0)->colours)) +#define NEXTCOLOURS 240 /* 216 colour-cube plus 24 shades of grey */ +#define NALLCOLOURS (NCFGCOLOURS + NEXTCOLOURS) GdkAtom compound_text_atom, utf8_string_atom; @@ -62,7 +65,7 @@ struct gui_data { } fontinfo[4]; int xpos, ypos, gotpos, gravity; GdkCursor *rawcursor, *textcursor, *blankcursor, *currcursor; - GdkColor cols[NCOLOURS]; + GdkColor cols[NALLCOLOURS]; GdkColormap *colmap; wchar_t *pastein_data; int direct_to_font; @@ -1336,15 +1339,12 @@ void set_window_background(struct gui_data *inst) void palette_set(void *frontend, int n, int r, int g, int b) { struct gui_data *inst = (struct gui_data *)frontend; - static const int first[21] = { - 0, 2, 4, 6, 8, 10, 12, 14, - 1, 3, 5, 7, 9, 11, 13, 15, - 16, 17, 18, 20, 22 - }; - real_palette_set(inst, first[n], r, g, b); - if (first[n] >= 18) - real_palette_set(inst, first[n] + 1, r, g, b); - if (first[n] == 18) + if (n >= 16) + n += 256 - 16; + if (n > NALLCOLOURS) + return; + real_palette_set(inst, n, r, g, b); + if (n == 258) set_window_background(inst); } @@ -1353,30 +1353,44 @@ void palette_reset(void *frontend) struct gui_data *inst = (struct gui_data *)frontend; /* This maps colour indices in inst->cfg to those used in inst->cols. */ static const int ww[] = { - 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, - 0, 1, 2, 3, 4, 5 + 256, 257, 258, 259, 260, 261, + 0, 8, 1, 9, 2, 10, 3, 11, + 4, 12, 5, 13, 6, 14, 7, 15 }; - gboolean success[NCOLOURS]; + gboolean success[NALLCOLOURS]; int i; - assert(lenof(ww) == NCOLOURS); + assert(lenof(ww) == NCFGCOLOURS); if (!inst->colmap) { inst->colmap = gdk_colormap_get_system(); } else { - gdk_colormap_free_colors(inst->colmap, inst->cols, NCOLOURS); + gdk_colormap_free_colors(inst->colmap, inst->cols, NALLCOLOURS); } - for (i = 0; i < NCOLOURS; i++) { - inst->cols[i].red = inst->cfg.colours[ww[i]][0] * 0x0101; - inst->cols[i].green = inst->cfg.colours[ww[i]][1] * 0x0101; - inst->cols[i].blue = inst->cfg.colours[ww[i]][2] * 0x0101; + for (i = 0; i < NCFGCOLOURS; i++) { + inst->cols[ww[i]].red = inst->cfg.colours[i][0] * 0x0101; + inst->cols[ww[i]].green = inst->cfg.colours[i][1] * 0x0101; + inst->cols[ww[i]].blue = inst->cfg.colours[i][2] * 0x0101; } - gdk_colormap_alloc_colors(inst->colmap, inst->cols, NCOLOURS, + for (i = 0; i < NEXTCOLOURS; i++) { + if (i < 216) { + int r = i / 36, g = (i / 6) % 6, b = i % 6; + inst->cols[i+16].red = r * 0x3333; + inst->cols[i+16].green = g * 0x3333; + inst->cols[i+16].blue = b * 0x3333; + } else { + int shade = i - 216; + shade = (shade + 1) * 0xFFFF / (NEXTCOLOURS - 216 + 1); + inst->cols[i+16].red = inst->cols[i+16].green = + inst->cols[i+16].blue = shade; + } + } + + gdk_colormap_alloc_colors(inst->colmap, inst->cols, NALLCOLOURS, FALSE, FALSE, success); - for (i = 0; i < NCOLOURS; i++) { + for (i = 0; i < NALLCOLOURS; i++) { if (!success[i]) g_error("%s: couldn't allocate colour %d (#%02x%02x%02x)\n", appname, i, inst->cfg.colours[i][0], @@ -1849,21 +1863,23 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len, ncombining = 1; nfg = ((attr & ATTR_FGMASK) >> ATTR_FGSHIFT); - nfg = 2 * (nfg & 0xF) + (nfg & 0x10 ? 1 : 0); nbg = ((attr & ATTR_BGMASK) >> ATTR_BGSHIFT); - nbg = 2 * (nbg & 0xF) + (nbg & 0x10 ? 1 : 0); if (attr & ATTR_REVERSE) { t = nfg; nfg = nbg; nbg = t; } - if (inst->cfg.bold_colour && (attr & ATTR_BOLD)) - nfg |= 1; - if (inst->cfg.bold_colour && (attr & ATTR_BLINK)) - nbg |= 1; + if (inst->cfg.bold_colour && (attr & ATTR_BOLD)) { + if (nfg < 16) nfg |= 8; + else if (nfg >= 256) nfg |= 1; + } + if (inst->cfg.bold_colour && (attr & ATTR_BLINK)) { + if (nbg < 16) nbg |= 8; + else if (nbg >= 256) nbg |= 1; + } if (attr & TATTR_ACTCURS) { - nfg = NCOLOURS-2; - nbg = NCOLOURS-1; + nfg = 260; + nbg = 261; } fontid = shadow = 0; @@ -2109,7 +2125,7 @@ void do_cursor(Context ctx, int x, int y, wchar_t *text, int len, * if it's passive. */ if (passive) { - gdk_gc_set_foreground(gc, &inst->cols[NCOLOURS-1]); + gdk_gc_set_foreground(gc, &inst->cols[261]); gdk_draw_rectangle(inst->pixmap, gc, 0, x*inst->font_width+inst->cfg.window_border, y*inst->font_height+inst->cfg.window_border, @@ -2147,7 +2163,7 @@ void do_cursor(Context ctx, int x, int y, wchar_t *text, int len, length = inst->font_height; } - gdk_gc_set_foreground(gc, &inst->cols[NCOLOURS-1]); + gdk_gc_set_foreground(gc, &inst->cols[NCFGCOLOURS-1]); if (passive) { for (i = 0; i < length; i++) { if (i % 2 == 0) { @@ -2839,15 +2855,17 @@ void change_settings_menuitem(GtkMenuItem *item, gpointer data) { /* This maps colour indices in inst->cfg to those used in inst->cols. */ static const int ww[] = { - 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, - 0, 1, 2, 3, 4, 5 + 256, 257, 258, 259, 260, 261, + 0, 8, 1, 9, 2, 10, 3, 11, + 4, 12, 5, 13, 6, 14, 7, 15 }; struct gui_data *inst = (struct gui_data *)data; char *title = dupcat(appname, " Reconfiguration", NULL); Config cfg2, oldcfg; int i, need_size; + assert(lenof(ww) == NCFGCOLOURS); + cfg2 = inst->cfg; /* structure copy */ if (do_config_box(title, &cfg2, 1)) { @@ -2877,20 +2895,20 @@ void change_settings_menuitem(GtkMenuItem *item, gpointer data) * have to the new default, on the assumption that the user * is most likely to want an immediate update. */ - for (i = 0; i < NCOLOURS; i++) { - if (oldcfg.colours[ww[i]][0] != cfg2.colours[ww[i]][0] || - oldcfg.colours[ww[i]][1] != cfg2.colours[ww[i]][1] || - oldcfg.colours[ww[i]][2] != cfg2.colours[ww[i]][2]) { - real_palette_set(inst, i, cfg2.colours[ww[i]][0], - cfg2.colours[ww[i]][1], - cfg2.colours[ww[i]][2]); + for (i = 0; i < NCFGCOLOURS; i++) { + if (oldcfg.colours[i][0] != cfg2.colours[i][0] || + oldcfg.colours[i][1] != cfg2.colours[i][1] || + oldcfg.colours[i][2] != cfg2.colours[i][2]) { + real_palette_set(inst, ww[i], cfg2.colours[i][0], + cfg2.colours[i][1], + cfg2.colours[i][2]); /* * If the default background has changed, we must * repaint the space in between the window border * and the text area. */ - if (i == 18) { + if (i == 258) { set_window_background(inst); draw_backing_rect(inst); } diff --git a/windows/window.c b/windows/window.c index 4d581d70..fe90483e 100644 --- a/windows/window.c +++ b/windows/window.c @@ -158,11 +158,13 @@ static enum { } und_mode; static int descent; -#define NCOLOURS 24 -static COLORREF colours[NCOLOURS]; +#define NCFGCOLOURS 24 +#define NEXTCOLOURS 240 +#define NALLCOLOURS (NCFGCOLOURS + NEXTCOLOURS) +static COLORREF colours[NALLCOLOURS]; static HPALETTE pal; static LPLOGPALETTE logpal; -static RGBTRIPLE defpal[NCOLOURS]; +static RGBTRIPLE defpal[NALLCOLOURS]; static HWND hwnd; @@ -1023,16 +1025,29 @@ static void cfgtopalette(void) { int i; static const int ww[] = { - 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, - 0, 1, 2, 3, 4, 4, 5, 5 + 256, 257, 258, 259, 260, 261, + 0, 8, 1, 9, 2, 10, 3, 11, + 4, 12, 5, 13, 6, 14, 7, 15 }; - for (i = 0; i < 24; i++) { + for (i = 0; i < 22; i++) { int w = ww[i]; - defpal[i].rgbtRed = cfg.colours[w][0]; - defpal[i].rgbtGreen = cfg.colours[w][1]; - defpal[i].rgbtBlue = cfg.colours[w][2]; + defpal[w].rgbtRed = cfg.colours[i][0]; + defpal[w].rgbtGreen = cfg.colours[i][1]; + defpal[w].rgbtBlue = cfg.colours[i][2]; + } + for (i = 0; i < NEXTCOLOURS; i++) { + if (i < 216) { + int r = i / 36, g = (i / 6) % 6, b = i % 6; + defpal[i+16].rgbtRed = r * 0x33; + defpal[i+16].rgbtGreen = g * 0x33; + defpal[i+16].rgbtBlue = b * 0x33; + } else { + int shade = i - 216; + shade = (shade + 1) * 0xFF / (NEXTCOLOURS - 216 + 1); + defpal[i+16].rgbtRed = defpal[i+16].rgbtGreen = + defpal[i+16].rgbtBlue = shade; + } } /* Override with system colours if appropriate */ @@ -1051,10 +1066,10 @@ static void systopalette(void) int i; static const struct { int nIndex; int norm; int bold; } or[] = { - { COLOR_WINDOWTEXT, 16, 17 }, /* Default Foreground */ - { COLOR_WINDOW, 18, 19 }, /* Default Background */ - { COLOR_HIGHLIGHTTEXT, 20, 21 }, /* Cursor Text */ - { COLOR_HIGHLIGHT, 22, 23 }, /* Cursor Colour */ + { COLOR_WINDOWTEXT, 256, 257 }, /* Default Foreground */ + { COLOR_WINDOW, 258, 259 }, /* Default Background */ + { COLOR_HIGHLIGHTTEXT, 260, 260 }, /* Cursor Text */ + { COLOR_HIGHLIGHT, 261, 261 }, /* Cursor Colour */ }; for (i = 0; i < (sizeof(or)/sizeof(or[0])); i++) { @@ -1083,10 +1098,10 @@ static void init_palette(void) */ logpal = smalloc(sizeof(*logpal) - sizeof(logpal->palPalEntry) - + NCOLOURS * sizeof(PALETTEENTRY)); + + NALLCOLOURS * sizeof(PALETTEENTRY)); logpal->palVersion = 0x300; - logpal->palNumEntries = NCOLOURS; - for (i = 0; i < NCOLOURS; i++) { + logpal->palNumEntries = NALLCOLOURS; + for (i = 0; i < NALLCOLOURS; i++) { logpal->palPalEntry[i].peRed = defpal[i].rgbtRed; logpal->palPalEntry[i].peGreen = defpal[i].rgbtGreen; logpal->palPalEntry[i].peBlue = defpal[i].rgbtBlue; @@ -1102,12 +1117,12 @@ static void init_palette(void) ReleaseDC(hwnd, hdc); } if (pal) - for (i = 0; i < NCOLOURS; i++) + for (i = 0; i < NALLCOLOURS; i++) colours[i] = PALETTERGB(defpal[i].rgbtRed, defpal[i].rgbtGreen, defpal[i].rgbtBlue); else - for (i = 0; i < NCOLOURS; i++) + for (i = 0; i < NALLCOLOURS; i++) colours[i] = RGB(defpal[i].rgbtRed, defpal[i].rgbtGreen, defpal[i].rgbtBlue); } @@ -2905,8 +2920,12 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len, y += offset_height; if ((attr & TATTR_ACTCURS) && (cfg.cursor_type == 0 || term->big_cursor)) { - attr &= ATTR_CUR_AND | (bold_mode != BOLD_COLOURS ? ATTR_BOLD : 0); - attr ^= ATTR_CUR_XOR; + attr &= ~(ATTR_REVERSE|ATTR_BLINK|ATTR_COLOURS); + if (bold_mode == BOLD_COLOURS) + attr &= ~ATTR_BOLD; + + /* cursor fg and bg */ + attr |= (260 << ATTR_FGSHIFT) | (261 << ATTR_BGSHIFT); } nfont = 0; @@ -2964,9 +2983,7 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len, nfont |= FONT_OEM; nfg = ((attr & ATTR_FGMASK) >> ATTR_FGSHIFT); - nfg = 2 * (nfg & 0xF) + (nfg & 0x10 ? 1 : 0); nbg = ((attr & ATTR_BGMASK) >> ATTR_BGSHIFT); - nbg = 2 * (nbg & 0xF) + (nbg & 0x10 ? 1 : 0); if (bold_mode == BOLD_FONT && (attr & ATTR_BOLD)) nfont |= FONT_BOLD; if (und_mode == UND_FONT && (attr & ATTR_UNDER)) @@ -2987,10 +3004,14 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len, nfg = nbg; nbg = t; } - if (bold_mode == BOLD_COLOURS && (attr & ATTR_BOLD)) - nfg |= 1; - if (bold_mode == BOLD_COLOURS && (attr & ATTR_BLINK)) - nbg |= 1; + if (bold_mode == BOLD_COLOURS && (attr & ATTR_BOLD)) { + if (nfg < 16) nfg |= 8; + else if (nfg >= 256) nfg |= 1; + } + if (bold_mode == BOLD_COLOURS && (attr & ATTR_BLINK)) { + if (nbg < 16) nbg |= 8; + else if (nbg >= 256) nbg |= 1; + } fg = colours[nfg]; bg = colours[nbg]; SelectObject(hdc, fonts[nfont]); @@ -3188,7 +3209,7 @@ void do_cursor(Context ctx, int x, int y, wchar_t *text, int len, pts[2].x = pts[3].x = x + char_width - 1; pts[0].y = pts[3].y = pts[4].y = y; pts[1].y = pts[2].y = y + font_height - 1; - oldpen = SelectObject(hdc, CreatePen(PS_SOLID, 0, colours[23])); + oldpen = SelectObject(hdc, CreatePen(PS_SOLID, 0, colours[261])); Polyline(hdc, pts, 5); oldpen = SelectObject(hdc, oldpen); DeleteObject(oldpen); @@ -4221,21 +4242,18 @@ static void real_palette_set(int n, int r, int g, int b) logpal->palPalEntry[n].peBlue = b; logpal->palPalEntry[n].peFlags = PC_NOCOLLAPSE; colours[n] = PALETTERGB(r, g, b); - SetPaletteEntries(pal, 0, NCOLOURS, logpal->palPalEntry); + SetPaletteEntries(pal, 0, NALLCOLOURS, logpal->palPalEntry); } else colours[n] = RGB(r, g, b); } void palette_set(void *frontend, int n, int r, int g, int b) { - static const int first[21] = { - 0, 2, 4, 6, 8, 10, 12, 14, - 1, 3, 5, 7, 9, 11, 13, 15, - 16, 17, 18, 20, 22 - }; - real_palette_set(first[n], r, g, b); - if (first[n] >= 18) - real_palette_set(first[n] + 1, r, g, b); + if (n >= 16) + n += 256 - 16; + if (n > NALLCOLOURS) + return; + real_palette_set(n, r, g, b); if (pal) { HDC hdc = get_ctx(frontend); UnrealizeObject(pal); @@ -4248,7 +4266,8 @@ void palette_reset(void *frontend) { int i; - for (i = 0; i < NCOLOURS; i++) { + /* And this */ + for (i = 0; i < NALLCOLOURS; i++) { if (pal) { logpal->palPalEntry[i].peRed = defpal[i].rgbtRed; logpal->palPalEntry[i].peGreen = defpal[i].rgbtGreen; @@ -4264,7 +4283,7 @@ void palette_reset(void *frontend) if (pal) { HDC hdc; - SetPaletteEntries(pal, 0, NCOLOURS, logpal->palPalEntry); + SetPaletteEntries(pal, 0, NALLCOLOURS, logpal->palPalEntry); hdc = get_ctx(frontend); RealizePalette(hdc); free_ctx(hdc); diff --git a/windows/winhelp.h b/windows/winhelp.h index ea6d0286..6701b6c3 100644 --- a/windows/winhelp.h +++ b/windows/winhelp.h @@ -97,6 +97,7 @@ #define WINHELP_CTX_selection_linedraw "selection.linedraw" #define WINHELP_CTX_selection_rtf "selection.rtf" #define WINHELP_CTX_colours_ansi "colours.ansi" +#define WINHELP_CTX_colours_xterm256 "colours.xterm256" #define WINHELP_CTX_colours_bold "colours.bold" #define WINHELP_CTX_colours_system "colours.system" #define WINHELP_CTX_colours_logpal "colours.logpal" -- 2.11.0