Implement xterm 256-colour mode.
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 28 Nov 2004 15:13:34 +0000 (15:13 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 28 Nov 2004 15:13:34 +0000 (15:13 +0000)
git-svn-id: svn://svn.tartarus.org/sgt/putty@4917 cda61777-01e9-0310-a592-d414129be87e

config.c
doc/config.but
putty.h
settings.c
terminal.c
unix/pterm.c
windows/window.c
windows/winhelp.h

index 99882a1..2c0c3b9 100644 (file)
--- 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)));
index e7e5db2..db0369b 100644 (file)
@@ -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 d880dbe..b50058c 100644 (file)
--- 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;
index 4f65fc5..749760a 100644 (file)
@@ -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++) {
index 0f0c9d8..aa23196 100644 (file)
@@ -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);
     }
 }
 
index 59a99c1..5254bf3 100644 (file)
 #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);
                }
index 4d581d7..fe90483 100644 (file)
@@ -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);
index ea6d028..6701b6c 100644 (file)
@@ -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"