From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16672 invoked from network); 29 Apr 2008 17:10:51 -0000 X-Spam-Checker-Version: SpamAssassin 3.2.4 (2008-01-01) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.4 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.2.4 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by ns1.primenet.com.au with SMTP; 29 Apr 2008 17:10:51 -0000 Received-SPF: none (ns1.primenet.com.au: domain at sunsite.dk does not designate permitted sender hosts) Received: (qmail 6724 invoked from network); 29 Apr 2008 17:10:46 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 29 Apr 2008 17:10:46 -0000 Received: (qmail 3740 invoked by alias); 29 Apr 2008 17:10:42 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 24894 Received: (qmail 3724 invoked from network); 29 Apr 2008 17:10:41 -0000 Received: from bifrost.dotsrc.org (130.225.254.106) by sunsite.dk with SMTP; 29 Apr 2008 17:10:41 -0000 Received: from cluster-g.mailcontrol.com (cluster-g.mailcontrol.com [85.115.41.190]) by bifrost.dotsrc.org (Postfix) with ESMTP id BAA48808A38A for ; Tue, 29 Apr 2008 19:10:35 +0200 (CEST) Received: from cameurexb01.EUROPE.ROOT.PRI ([62.189.241.200]) by rly22g.srv.mailcontrol.com (MailControl) with ESMTP id m3THASuv013230 for ; Tue, 29 Apr 2008 18:10:29 +0100 Received: from news01 ([10.103.143.38]) by cameurexb01.EUROPE.ROOT.PRI with Microsoft SMTPSVC(6.0.3790.3959); Tue, 29 Apr 2008 18:10:22 +0100 Date: Tue, 29 Apr 2008 18:10:22 +0100 From: Peter Stephenson To: zsh-workers@sunsite.dk Subject: Re: PATCH: isearch match highlighting Message-ID: <20080429181022.12809d23@news01> In-Reply-To: <20080428102001.7b55074e@news01> References: <17393e3e0804261727s560acff7sb6125d8f8b46b4b4@mail.gmail.com> <200804271957.m3RJvxiS004075@pws-pc.ntlworld.com> <17393e3e0804271849l30fe20bdp4008fc8247298d12@mail.gmail.com> <20080428102001.7b55074e@news01> Organization: CSR X-Mailer: Claws Mail 3.3.1 (GTK+ 2.12.5; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-OriginalArrivalTime: 29 Apr 2008 17:10:22.0152 (UTC) FILETIME=[E87EC480:01C8AA1B] X-Scanned-By: MailControl A-08-50-01 (www.mailcontrol.com) on 10.71.0.132 X-Virus-Scanned: ClamAV 0.91.2/6986/Tue Apr 29 18:57:31 2008 on bifrost X-Virus-Status: Clean On Mon, 28 Apr 2008 10:20:01 +0100 Peter Stephenson wrote: > On Sun, 27 Apr 2008 21:49:01 -0400 > "Matt Wozniski" wrote: > > Yep, works now - and looks very nice, though I wonder if we could set > > it up in a way that would let us change the fg or bg color of the > > text, rather than just reverse/standout/underline? > > I should get around to that before long. I don't think it should be too > hard. I'd like to use standard termcap AF/AB codes for this instead of the > hacked-in (surprise!) colors we currently use in completion, but it doesn't > seem to be that easy to set defaults etc. that way. Maybe Geoff knows > about this. This seems now to be Not Necessarily Completely Broken (TM). It is currently hardwired to use ANSI sequences at least for setting the default colour, though it will use termcap sequences where available for non-default colours above 7, which is the limit of the ANSI set. There is a facility at the lower level to force it to use termcap for all non-default colours including 0 to 7, but it's not wired to anything above it at the moment. I would like at the least to make the use of the ANSI escapes configurable. They are in completion listings, but unfortunately that's tied to the variable interface for GNU ls colouring which doesn't really fit the case here. I suppose special values in zle_highlight would be suitable (with bindkey escapes). You'll be glad to know you can use the system without ever having to worry about the spelling of colo[u]r. I will try to keep it that way. I've just remembered I haven't documented the fact that only colours 0 to 255 are allowed internally. I can't be bothered to remake the patch, so I'll alter that before committing. The numbers of supported colours reported by a few terminals I tried are: xterm: 8 rxvt-unicode: 88 konsole: 8 gnome-terminal: 8 Linux console: 8 so mostly just the ANSI set. I did try the extended colours on rxvt-unicode and they seemed to work. I have a vague feeling I saw a terminal claim to support 256. Index: Doc/Zsh/zle.yo =================================================================== RCS file: /cvsroot/zsh/zsh/Doc/Zsh/zle.yo,v retrieving revision 1.64 diff -u -r1.64 zle.yo --- Doc/Zsh/zle.yo 26 Apr 2008 22:52:51 -0000 1.64 +++ Doc/Zsh/zle.yo 29 Apr 2008 16:40:32 -0000 @@ -2097,6 +2097,24 @@ this to appear with other types of highlighting; it is used to override a default. ) +item(tt(fg=)var(colour))( +The foreground colour should be set to var(colour), an integer. Not all +terminals support this, and of those that do not all provide facilities to +test the support, hence the user should decide based on the terminal type. +Most terminals with colour support accept the numbers 0 to 7, and may +generate additional colours if the tt(bold) attributes is also present. On +recent terminals and on systems with an up-to-date terminal database the +number of colours supported may be tested by with the command `tt(echotc +Co)'; if this succeeds, it indicates a limit on the number of colours which +will be enforced by the line editor. + +Colour is also known as color. +) +item(tt(bg=)var(colour))( +The background colour should be set to var(colour), an integer. This +works similarly to the foreground colour, except the background is +not usually affected by the bold attribute. +) item(tt(bold))( The characters in the given context are shown in a bold font. ) Index: Src/init.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/init.c,v retrieving revision 1.82 diff -u -r1.82 init.c --- Src/init.c 26 Apr 2008 17:46:47 -0000 1.82 +++ Src/init.c 29 Apr 2008 16:40:33 -0000 @@ -79,6 +79,11 @@ /**/ mod_export int hasam, hasxn; +/* Value of the Co (max_colors) entry: may not be set */ + +/**/ +mod_export int tccolours; + /* Pointer to read-key function from zle */ /**/ @@ -531,7 +536,7 @@ "cl", "le", "LE", "nd", "RI", "up", "UP", "do", "DO", "dc", "DC", "ic", "IC", "cd", "ce", "al", "dl", "ta", "md", "so", "us", "me", "se", "ue", "ch", - "ku", "kd", "kl", "kr", "sc", "rc", "bc" + "ku", "kd", "kl", "kr", "sc", "rc", "bc", "AF", "AB" }; /* Initialise termcap */ @@ -590,6 +595,7 @@ tclines = tgetnum("li"); tccolumns = tgetnum("co"); + tccolours = tgetnum("Co"); /* if there's no termcap entry for cursor up, use single line mode: * * this is flagged by termflags which is examined in zle_refresh.c * Index: Src/zsh.h =================================================================== RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v retrieving revision 1.127 diff -u -r1.127 zsh.h --- Src/zsh.h 26 Apr 2008 19:51:09 -0000 1.127 +++ Src/zsh.h 29 Apr 2008 16:40:33 -0000 @@ -1949,7 +1949,9 @@ #define TCSAVECURSOR 29 #define TCRESTRCURSOR 30 #define TCBACKSPACE 31 -#define TC_COUNT 32 +#define TCFGCOLOUR 32 +#define TCBGCOLOUR 33 +#define TC_COUNT 34 #define tccan(X) (tclen[X]) @@ -1957,32 +1959,63 @@ * Text attributes for displaying in ZLE */ -#define TXTBOLDFACE 0x01 -#define TXTSTANDOUT 0x02 -#define TXTUNDERLINE 0x04 -#define TXTDIRTY 0x80 +#define TXTBOLDFACE 0x0001 +#define TXTSTANDOUT 0x0002 +#define TXTUNDERLINE 0x0004 +#define TXTFGCOLOUR 0x0008 +#define TXTBGCOLOUR 0x0010 +#define TXTDIRTY 0x0020 -#define TXT_ATTR_ON_MASK 0x07 +#define TXT_ATTR_ON_MASK 0x001F #define txtisset(X) (txtattrmask & (X)) #define txtset(X) (txtattrmask |= (X)) #define txtunset(X) (txtattrmask &= ~(X)) -#define TXTNOBOLDFACE 0x10 -#define TXTNOSTANDOUT 0x20 -#define TXTNOUNDERLINE 0x40 +#define TXTNOBOLDFACE 0x0040 +#define TXTNOSTANDOUT 0x0080 +#define TXTNOUNDERLINE 0x0100 +#define TXTNOFGCOLOUR 0x0200 +#define TXTNOBGCOLOUR 0x0400 -#define TXT_ATTR_OFF_MASK 0x70 +#define TXT_ATTR_OFF_MASK 0x07C0 /* Bits to shift off right to get on */ -#define TXT_ATTR_OFF_ON_SHIFT (4) - +#define TXT_ATTR_OFF_ON_SHIFT 6 +#define TXT_ATTR_OFF_FROM_ON(attr) \ + (((attr) & TXT_ATTR_ON_MASK) << TXT_ATTR_OFF_ON_SHIFT) /* * Indicates to zle_refresh.c that the character entry is an * index into the list of multiword symbols. */ -#define TXT_MULTIWORD_MASK 0x100 +#define TXT_MULTIWORD_MASK 0x0800 + +/* Mask for colour to use in foreground */ +#define TXT_ATTR_FG_COL_MASK 0x000FF000 +/* Bits to shift the foreground colour */ +#define TXT_ATTR_FG_COL_SHIFT (12) +/* Mask for colour to use in background */ +#define TXT_ATTR_BG_COL_MASK 0x0FF00000 +/* Bits to shift the background colour */ +#define TXT_ATTR_BG_COL_SHIFT (20) + +/* Flag to use termcap AF sequence to set colour, if available */ +#define TXT_ATTR_FG_TERMCAP 0x10000000 +/* Flag to use termcap AB sequence to set colour, if available */ +#define TXT_ATTR_BG_TERMCAP 0x20000000 + +/* Things to turn on, including values for the colour elements */ +#define TXT_ATTR_ON_VALUES_MASK \ + (TXT_ATTR_ON_MASK|TXT_ATTR_FG_COL_MASK|TXT_ATTR_BG_COL_MASK|\ + TXT_ATTR_FG_TERMCAP|TXT_ATTR_BG_TERMCAP) + +/* Mask out everything to do with activating colours */ +#define TXT_ATTR_COLOUR_ON_MASK \ + (TXTFGCOLOUR|TXTBGCOLOUR| \ + TXT_ATTR_FG_COL_MASK|TXT_ATTR_BG_COL_MASK| \ + TXT_ATTR_FG_TERMCAP|TXT_ATTR_BG_TERMCAP) #define txtchangeisset(T,X) ((T) & (X)) +#define txtchangeget(T,A) (((T) & A ## _MASK) >> A ## _SHIFT) #define txtchangeset(X, Y) (txtchange |= (X), txtchange &= ~(Y)) /****************************************/ Index: Src/Zle/zle_refresh.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_refresh.c,v retrieving revision 1.63 diff -u -r1.63 zle_refresh.c --- Src/Zle/zle_refresh.c 29 Apr 2008 08:43:39 -0000 1.63 +++ Src/Zle/zle_refresh.c 29 Apr 2008 16:40:34 -0000 @@ -207,7 +207,7 @@ * displayed on screen. */ -static int special_atr_on, special_atr_off; +static int special_atr_on; /* Flags for the region_highlight structure */ enum { @@ -357,19 +357,41 @@ const struct highlight *hl; found = 0; - for (hl = highlights; hl->name; hl++) { - if (strpfx(hl->name, teststr)) { - const char *val = teststr + strlen(hl->name); - - if (*val == ',') - val++; - else if (*val) - break; + if (strpfx("fg=", teststr) || strpfx("bg=", teststr)) { + int is_fg = (teststr[0] == 'f'); + int colour = (int)zstrtol(teststr+3, (char **)&teststr, 10); + int shft, on; + if (*teststr == ',') + teststr++; + else if (*teststr) + break; + found = 1; + /* skip out of range colours but keep scanning attributes */ + if (colour >= 256) + continue; + if (is_fg) { + shft = TXT_ATTR_FG_COL_SHIFT; + on = TXTFGCOLOUR; + } else { + shft = TXT_ATTR_BG_COL_SHIFT; + on = TXTBGCOLOUR; + } + *on_var |= on | (colour << shft); + } else { + for (hl = highlights; hl->name; hl++) { + if (strpfx(hl->name, teststr)) { + const char *val = teststr + strlen(hl->name); + + if (*val == ',') + val++; + else if (*val) + break; - *on_var |= hl->mask_on; - *on_var &= ~hl->mask_off; - teststr = val; - found = 1; + *on_var |= hl->mask_on; + *on_var &= ~hl->mask_off; + teststr = val; + found = 1; + } } } } @@ -431,7 +453,6 @@ region_highlights->atr = TXTSTANDOUT; if (!isearch_atr_on_set) region_highlights[1].atr = TXTUNDERLINE; - special_atr_off = special_atr_on << TXT_ATTR_OFF_ON_SHIFT; } @@ -610,19 +631,23 @@ if (lastatr & ~c->atr) { /* Stuff on we don't want, turn it off */ - settextattributes((lastatr & ~c->atr) << TXT_ATTR_OFF_ON_SHIFT); + settextattributes(TXT_ATTR_OFF_FROM_ON(lastatr & ~c->atr)); lastatr = 0; } /* * Don't output "on" attributes in a string of characters with - * the same attributes. + * the same attributes. Be careful in case a different colour + * needs setting. */ if ((c->atr & TXT_ATTR_ON_MASK) && (!curatrp || - ((*curatrp & TXT_ATTR_ON_MASK) != (c->atr & TXT_ATTR_ON_MASK)))) { + ((*curatrp & TXT_ATTR_ON_VALUES_MASK) != + (c->atr & TXT_ATTR_ON_VALUES_MASK)))) { + /* Record just the control flags we might need to turn off... */ lastatr = c->atr & TXT_ATTR_ON_MASK; - settextattributes(lastatr); + /* ...but set including the values for colour attributes */ + settextattributes(c->atr & TXT_ATTR_ON_VALUES_MASK); } #ifdef MULTIBYTE_SUPPORT @@ -656,9 +681,11 @@ if (curatrp) { /* * Remember the current attributes: those that are turned - * on, less those that are turned off again. + * on, less those that are turned off again. Include + * colour attributes here in case the colour changes to + * another non-default one. */ - *curatrp = (c->atr & TXT_ATTR_ON_MASK) & + *curatrp = (c->atr & TXT_ATTR_ON_VALUES_MASK) & ~((c->atr & TXT_ATTR_OFF_MASK) >> TXT_ATTR_OFF_ON_SHIFT); } } @@ -915,6 +942,54 @@ rpms->sen = rpms->s + winw; } +/* + * HERE: these need to be made configurable, somehow. + * Ideally we need to make the complist stuff use the + * same system, but that may be too much tied to the GNU ls + * interface to make that possible. + */ +/* Start of escape sequence for foreground colour */ +#define TC_COL_FG_START "\033[3" +/* Start of escape sequence for background colour */ +#define TC_COL_BG_START "\033[4" +/* End of either escape sequence */ +#define TC_COL_END "m" +/* Numeric code (to be turned into ASCII) to reset default colour */ +#define TC_COL_DEFAULT 9 + +static void +setcolourattribute(int colour, char *start, int tc, int def, + int use_termcap) +{ + char out[16], *ptr; + /* + * If we're not restoring the default, and either have a + * colour value that is too large for ANSI, or have been told + * to use the termcap sequence (which at the time of writing + * we never are), try to use the termcap sequence. + */ + if (!def && (colour > 7 || use_termcap)) { + /* + * We can if it's available, and either we couldn't get + * the maximum number of colours, or the colour is in range. + */ + if (tccan(tc) && (tccolours < 0 || colour < tccolours)) + tcoutarg(tc, colour); + /* for 0 to 7 assume standard ANSI works, otherwise it won't. */ + if (colour > 7) + return; + } + + strcpy(out, start); + if (def) + colour = TC_COL_DEFAULT; + + ptr = out + strlen(start); + *ptr++ = colour + '0'; + strcpy(ptr, TC_COL_END); + tputs(out, 1, putshout); +} + /**/ static void settextattributes(int atr) @@ -931,6 +1006,18 @@ tsetcap(TCSTANDOUTBEG, 0); if (txtchangeisset(atr, TXTUNDERLINE)) tsetcap(TCUNDERLINEBEG, 0); + if (txtchangeisset(atr, TXTFGCOLOUR|TXTNOFGCOLOUR)) { + setcolourattribute(txtchangeget(atr, TXT_ATTR_FG_COL), + TC_COL_FG_START, TCFGCOLOUR, + txtchangeisset(atr, TXTNOFGCOLOUR), + txtchangeisset(atr, TXT_ATTR_FG_TERMCAP)); + } + if (txtchangeisset(atr, TXTBGCOLOUR|TXTNOBGCOLOUR)) { + setcolourattribute(txtchangeget(atr, TXT_ATTR_BG_COL), + TC_COL_BG_START, TCBGCOLOUR, + txtchangeisset(atr, TXTNOBGCOLOUR), + txtchangeisset(atr, TXT_ATTR_BG_TERMCAP)); + } } #ifdef MULTIBYTE_SUPPORT @@ -1209,6 +1296,7 @@ rpms.sen = *nbuf + winw; for (t = tmpline, tmppos = 0; tmppos < tmpll; t++, tmppos++) { int base_atr_on = 0, base_atr_off = 0, ireg; + int all_atr_on, all_atr_off; struct region_highlight *rhp; /* * Calculate attribute based on region. @@ -1223,12 +1311,27 @@ offset = predisplaylen; /* increment over it */ if (rhp->start + offset <= tmppos && tmppos < rhp->end + offset) { - base_atr_on |= rhp->atr; + if (base_atr_on & (TXTFGCOLOUR|TXTBGCOLOUR)) { + /* keep colour already set */ + base_atr_on |= rhp->atr & ~TXT_ATTR_COLOUR_ON_MASK; + } else { + /* no colour set yet */ + base_atr_on |= rhp->atr; + } if (tmppos == rhp->end + offset - 1 || tmppos == tmpll - 1) - base_atr_off |= rhp->atr << TXT_ATTR_OFF_ON_SHIFT; + base_atr_off |= TXT_ATTR_OFF_FROM_ON(rhp->atr); } } + if (special_atr_on & (TXTFGCOLOUR|TXTBGCOLOUR)) { + /* keep colours from special attributes */ + all_atr_on = special_atr_on | + (base_atr_on & ~TXT_ATTR_COLOUR_ON_MASK); + } else { + /* keep colours from standard attributes */ + all_atr_on = special_atr_on | base_atr_on; + } + all_atr_off = TXT_ATTR_OFF_FROM_ON(all_atr_on); if (t == scs) /* if cursor is here, remember it */ rpms.nvcs = rpms.s - nbuf[rpms.nvln = rpms.ln]; @@ -1264,11 +1367,11 @@ rpms.s->chr = ZWC(' '); if (!started) started = 1; - rpms.s->atr = special_atr_on | base_atr_on; + rpms.s->atr = all_atr_on; rpms.s++; } while (rpms.s < rpms.sen); if (started) - rpms.s[-1].atr |= special_atr_off | base_atr_off; + rpms.s[-1].atr |= all_atr_off; if (nextline(&rpms, 1)) break; if (t == scs) { @@ -1292,8 +1395,7 @@ * occurrence. */ rpms.s->chr = ZWC('?'); - rpms.s->atr = special_atr_on | special_atr_off | - base_atr_on | base_atr_off; + rpms.s->atr = all_atr_on | all_atr_off; rpms.s++; } else { /* We can fit it without reaching the end of the line. */ @@ -1334,18 +1436,17 @@ #endif ) { /* other control character */ rpms.s->chr = ZWC('^'); - rpms.s->atr = special_atr_on | base_atr_on; + rpms.s->atr = all_atr_on; rpms.s++; if (rpms.s == rpms.sen) { /* text wrapped */ - rpms.s[-1].atr |= special_atr_off | base_atr_off; + rpms.s[-1].atr |= all_atr_off; if (nextline(&rpms, 1)) break; } rpms.s->chr = (((unsigned int)*t & ~0x80u) > 31) ? ZWC('?') : (*t | ZWC('@')); - rpms.s->atr = special_atr_on | special_atr_off | - base_atr_on | base_atr_off; + rpms.s->atr = all_atr_on | all_atr_off; rpms.s++; } #ifdef MULTIBYTE_SUPPORT @@ -1370,12 +1471,12 @@ rpms.s->chr = wc; if (!started) started = 1; - rpms.s->atr = special_atr_on | base_atr_on; + rpms.s->atr = all_atr_on; rpms.s++; if (rpms.s == rpms.sen) { /* text wrapped */ if (started) { - rpms.s[-1].atr |= special_atr_off | base_atr_off; + rpms.s[-1].atr |= all_atr_off; started = 0; } if (nextline(&rpms, 1)) @@ -1385,7 +1486,7 @@ dispptr++; } if (started) - rpms.s[-1].atr |= special_atr_off | base_atr_off; + rpms.s[-1].atr |= all_atr_off; if (*dispptr) /* nextline said stop processing */ break; } @@ -1417,11 +1518,14 @@ more_end = 1; if (statusline) { - int outll, outsz; + int outll, outsz, all_atr_on, all_atr_off; char *statusdup = ztrdup(statusline); ZLE_STRING_T outputline = stringaszleline(statusdup, 0, &outll, &outsz, NULL); + all_atr_on = special_atr_on; + all_atr_off = TXT_ATTR_OFF_FROM_ON(all_atr_on); + rpms.tosln = rpms.ln + 1; nbuf[rpms.ln][winw + 1] = zr_zr; /* text not wrapped */ snextline(&rpms); @@ -1440,7 +1544,7 @@ } if (width > rpms.sen - rpms.s) { rpms.s->chr = ZWC('?'); - rpms.s->atr = special_atr_on | special_atr_off; + rpms.s->atr = all_atr_on | all_atr_off; rpms.s++; } else { rpms.s->chr = *u; @@ -1457,7 +1561,7 @@ #endif if (ZC_icntrl(*u)) { /* simplified processing in the status line */ rpms.s->chr = ZWC('^'); - rpms.s->atr = special_atr_on; + rpms.s->atr = all_atr_on; rpms.s++; if (rpms.s == rpms.sen) { nbuf[rpms.ln][winw + 1] = zr_nl;/* text wrapped */ @@ -1465,7 +1569,7 @@ } rpms.s->chr = (((unsigned int)*u & ~0x80u) > 31) ? ZWC('?') : (*u | ZWC('@')); - rpms.s->atr = special_atr_on | special_atr_off; + rpms.s->atr = all_atr_on | all_atr_off; rpms.s++; } else { rpms.s->chr = *u; @@ -2037,7 +2141,7 @@ */ int now_off = ol->atr & ~nl->atr & TXT_ATTR_ON_MASK; if (now_off) - settextattributes(now_off << TXT_ATTR_OFF_ON_SHIFT); + settextattributes(TXT_ATTR_OFF_FROM_ON(now_off)); zputc(nl); nl++, ol++; @@ -2324,7 +2428,7 @@ if (tmpcs < 0) { #ifdef DEBUG fprintf(stderr, "BUG: negative cursor position\n"); - fflush(stderr); + fflush(stderr); #endif tmpcs = 0; } @@ -2336,6 +2440,7 @@ for (t0 = 0; t0 < tmpll; t0++) { int base_atr_on = 0, base_atr_off = 0, ireg; + int all_atr_on, all_atr_off; struct region_highlight *rhp; /* * Calculate attribute based on region. @@ -2350,12 +2455,27 @@ offset = predisplaylen; /* increment over it */ if (rhp->start + offset <= t0 && t0 < rhp->end + offset) { - base_atr_on |= rhp->atr; + if (base_atr_on & (TXTFGCOLOUR|TXTBGCOLOUR)) { + /* keep colour already set */ + base_atr_on |= rhp->atr & ~TXT_ATTR_COLOUR_ON_MASK; + } else { + /* no colour set yet */ + base_atr_on |= rhp->atr; + } if (t0 == rhp->end + offset - 1 || t0 == tmpll - 1) - base_atr_off |= rhp->atr << TXT_ATTR_OFF_ON_SHIFT; + base_atr_off |= TXT_ATTR_OFF_FROM_ON(rhp->atr); } } + if (special_atr_on & (TXTFGCOLOUR|TXTBGCOLOUR)) { + /* keep colours from special attributes */ + all_atr_on = special_atr_on | + (base_atr_on & ~TXT_ATTR_COLOUR_ON_MASK); + } else { + /* keep colours from standard attributes */ + all_atr_on = special_atr_on | base_atr_on; + } + all_atr_off = TXT_ATTR_OFF_FROM_ON(all_atr_on); if (tmpline[t0] == ZWC('\t')) { REFRESH_ELEMENT sp = zr_sp; @@ -2365,11 +2485,10 @@ vp[-1].atr |= base_atr_off; } else if (tmpline[t0] == ZWC('\n')) { vp->chr = ZWC('\\'); - vp->atr = special_atr_on | base_atr_on; + vp->atr = all_atr_on; vp++; vp->chr = ZWC('n'); - vp->atr = special_atr_on | special_atr_off | - base_atr_on | base_atr_off; + vp->atr = all_atr_on | all_atr_off; vp++; #ifdef MULTIBYTE_SUPPORT } else if (iswprint(tmpline[t0]) && @@ -2406,12 +2525,11 @@ ZLE_INT_T t = tmpline[++t0]; vp->chr = ZWC('^'); - vp->atr = special_atr_on | base_atr_on; + vp->atr = all_atr_on; vp++; vp->chr = (((unsigned int)t & ~0x80u) > 31) ? ZWC('?') : (t | ZWC('@')); - vp->atr = special_atr_on | special_atr_off | base_atr_on | - base_atr_off; + vp->atr = all_atr_on | all_atr_off; vp++; } #ifdef MULTIBYTE_SUPPORT @@ -2431,13 +2549,13 @@ vp->chr = wc; if (!started) started = 1; - vp->atr = special_atr_on | base_atr_on; + vp->atr = all_atr_on; vp++; } dispptr++; } if (started) - vp[-1].atr |= special_atr_off | base_atr_off; + vp[-1].atr |= all_atr_off; } #else else { -- Peter Stephenson Software Engineer CSR PLC, Churchill House, Cambridge Business Park, Cowley Road Cambridge, CB4 0WZ, UK Tel: +44 (0)1223 692070