Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: PATCH: isearch match highlighting



On Mon, 28 Apr 2008 10:20:01 +0100
Peter Stephenson <pws@xxxxxxx> wrote:
> On Sun, 27 Apr 2008 21:49:01 -0400
> "Matt Wozniski" <godlygeek@xxxxxxxxx> 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 <pws@xxxxxxx>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070



Messages sorted by: Reverse Date, Date, Thread, Author