Skip to content

Commit dae2868

Browse files
author
nicm
committed
Add support for underscore colours with Setulc capability, mostly from
Kai Moschcau.
1 parent 3a6d90a commit dae2868

9 files changed

+184
-21
lines changed

colour.c

+79-5
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,85 @@ colour_fromstring(const char *s)
230230
return (-1);
231231
}
232232

233-
/* Convert 256 colour palette to 16. */
234-
u_char
235-
colour_256to16(u_char c)
233+
/* Convert 256 colour to RGB colour. */
234+
int
235+
colour_256toRGB(int c)
236+
{
237+
static const int table[256] = {
238+
0x000000, 0x800000, 0x008000, 0x808000,
239+
0x000080, 0x800080, 0x008080, 0xc0c0c0,
240+
0x808080, 0xff0000, 0x00ff00, 0xffff00,
241+
0x0000ff, 0xff00ff, 0x00ffff, 0xffffff,
242+
0x000000, 0x00005f, 0x000087, 0x0000af,
243+
0x0000d7, 0x0000ff, 0x005f00, 0x005f5f,
244+
0x005f87, 0x005faf, 0x005fd7, 0x005fff,
245+
0x008700, 0x00875f, 0x008787, 0x0087af,
246+
0x0087d7, 0x0087ff, 0x00af00, 0x00af5f,
247+
0x00af87, 0x00afaf, 0x00afd7, 0x00afff,
248+
0x00d700, 0x00d75f, 0x00d787, 0x00d7af,
249+
0x00d7d7, 0x00d7ff, 0x00ff00, 0x00ff5f,
250+
0x00ff87, 0x00ffaf, 0x00ffd7, 0x00ffff,
251+
0x5f0000, 0x5f005f, 0x5f0087, 0x5f00af,
252+
0x5f00d7, 0x5f00ff, 0x5f5f00, 0x5f5f5f,
253+
0x5f5f87, 0x5f5faf, 0x5f5fd7, 0x5f5fff,
254+
0x5f8700, 0x5f875f, 0x5f8787, 0x5f87af,
255+
0x5f87d7, 0x5f87ff, 0x5faf00, 0x5faf5f,
256+
0x5faf87, 0x5fafaf, 0x5fafd7, 0x5fafff,
257+
0x5fd700, 0x5fd75f, 0x5fd787, 0x5fd7af,
258+
0x5fd7d7, 0x5fd7ff, 0x5fff00, 0x5fff5f,
259+
0x5fff87, 0x5fffaf, 0x5fffd7, 0x5fffff,
260+
0x870000, 0x87005f, 0x870087, 0x8700af,
261+
0x8700d7, 0x8700ff, 0x875f00, 0x875f5f,
262+
0x875f87, 0x875faf, 0x875fd7, 0x875fff,
263+
0x878700, 0x87875f, 0x878787, 0x8787af,
264+
0x8787d7, 0x8787ff, 0x87af00, 0x87af5f,
265+
0x87af87, 0x87afaf, 0x87afd7, 0x87afff,
266+
0x87d700, 0x87d75f, 0x87d787, 0x87d7af,
267+
0x87d7d7, 0x87d7ff, 0x87ff00, 0x87ff5f,
268+
0x87ff87, 0x87ffaf, 0x87ffd7, 0x87ffff,
269+
0xaf0000, 0xaf005f, 0xaf0087, 0xaf00af,
270+
0xaf00d7, 0xaf00ff, 0xaf5f00, 0xaf5f5f,
271+
0xaf5f87, 0xaf5faf, 0xaf5fd7, 0xaf5fff,
272+
0xaf8700, 0xaf875f, 0xaf8787, 0xaf87af,
273+
0xaf87d7, 0xaf87ff, 0xafaf00, 0xafaf5f,
274+
0xafaf87, 0xafafaf, 0xafafd7, 0xafafff,
275+
0xafd700, 0xafd75f, 0xafd787, 0xafd7af,
276+
0xafd7d7, 0xafd7ff, 0xafff00, 0xafff5f,
277+
0xafff87, 0xafffaf, 0xafffd7, 0xafffff,
278+
0xd70000, 0xd7005f, 0xd70087, 0xd700af,
279+
0xd700d7, 0xd700ff, 0xd75f00, 0xd75f5f,
280+
0xd75f87, 0xd75faf, 0xd75fd7, 0xd75fff,
281+
0xd78700, 0xd7875f, 0xd78787, 0xd787af,
282+
0xd787d7, 0xd787ff, 0xd7af00, 0xd7af5f,
283+
0xd7af87, 0xd7afaf, 0xd7afd7, 0xd7afff,
284+
0xd7d700, 0xd7d75f, 0xd7d787, 0xd7d7af,
285+
0xd7d7d7, 0xd7d7ff, 0xd7ff00, 0xd7ff5f,
286+
0xd7ff87, 0xd7ffaf, 0xd7ffd7, 0xd7ffff,
287+
0xff0000, 0xff005f, 0xff0087, 0xff00af,
288+
0xff00d7, 0xff00ff, 0xff5f00, 0xff5f5f,
289+
0xff5f87, 0xff5faf, 0xff5fd7, 0xff5fff,
290+
0xff8700, 0xff875f, 0xff8787, 0xff87af,
291+
0xff87d7, 0xff87ff, 0xffaf00, 0xffaf5f,
292+
0xffaf87, 0xffafaf, 0xffafd7, 0xffafff,
293+
0xffd700, 0xffd75f, 0xffd787, 0xffd7af,
294+
0xffd7d7, 0xffd7ff, 0xffff00, 0xffff5f,
295+
0xffff87, 0xffffaf, 0xffffd7, 0xffffff,
296+
0x080808, 0x121212, 0x1c1c1c, 0x262626,
297+
0x303030, 0x3a3a3a, 0x444444, 0x4e4e4e,
298+
0x585858, 0x626262, 0x6c6c6c, 0x767676,
299+
0x808080, 0x8a8a8a, 0x949494, 0x9e9e9e,
300+
0xa8a8a8, 0xb2b2b2, 0xbcbcbc, 0xc6c6c6,
301+
0xd0d0d0, 0xdadada, 0xe4e4e4, 0xeeeeee
302+
};
303+
304+
return (table[c & 0xff] | COLOUR_FLAG_RGB);
305+
}
306+
307+
/* Convert 256 colour to 16 colour. */
308+
int
309+
colour_256to16(int c)
236310
{
237-
static const u_char table[256] = {
311+
static const char table[256] = {
238312
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
239313
0, 4, 4, 4, 12, 12, 2, 6, 4, 4, 12, 12, 2, 2, 6, 4,
240314
12, 12, 2, 2, 2, 6, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10,
@@ -253,5 +327,5 @@ colour_256to16(u_char c)
253327
8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15
254328
};
255329

256-
return (table[c]);
330+
return (table[c & 0xff]);
257331
}

grid.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@
3737

3838
/* Default grid cell data. */
3939
const struct grid_cell grid_default_cell = {
40-
0, 0, 8, 8, { { ' ' }, 0, 1, 1 }
40+
0, 0, 8, 8, 0, { { ' ' }, 0, 1, 1 }
4141
};
4242

4343
/* Cleared grid cell data. */
4444
const struct grid_cell grid_cleared_cell = {
45-
GRID_FLAG_CLEARED, 0, 8, 8, { { ' ' }, 0, 1, 1 }
45+
GRID_FLAG_CLEARED, 0, 8, 8, 0, { { ' ' }, 0, 1, 1 }
4646
};
4747
static const struct grid_cell_entry grid_cleared_entry = {
4848
GRID_FLAG_CLEARED, { .data = { 0, 8, 8, ' ' } }
@@ -82,6 +82,8 @@ grid_need_extended_cell(const struct grid_cell_entry *gce,
8282
return (1);
8383
if ((gc->fg & COLOUR_FLAG_RGB) || (gc->bg & COLOUR_FLAG_RGB))
8484
return (1);
85+
if (gc->us != 0) /* only supports 256 or RGB */
86+
return (1);
8587
return (0);
8688
}
8789

input.c

+9-2
Original file line numberDiff line numberDiff line change
@@ -1829,6 +1829,8 @@ input_csi_dispatch_sgr_256_do(struct input_ctx *ictx, int fgbg, int c)
18291829
gc->fg = c | COLOUR_FLAG_256;
18301830
else if (fgbg == 48)
18311831
gc->bg = c | COLOUR_FLAG_256;
1832+
else if (fgbg == 58)
1833+
gc->us = c | COLOUR_FLAG_256;
18321834
}
18331835
return (1);
18341836
}
@@ -1862,6 +1864,8 @@ input_csi_dispatch_sgr_rgb_do(struct input_ctx *ictx, int fgbg, int r, int g,
18621864
gc->fg = colour_join_rgb(r, g, b);
18631865
else if (fgbg == 48)
18641866
gc->bg = colour_join_rgb(r, g, b);
1867+
else if (fgbg == 58)
1868+
gc->us = colour_join_rgb(r, g, b);
18651869
return (1);
18661870
}
18671871

@@ -1938,7 +1942,7 @@ input_csi_dispatch_sgr_colon(struct input_ctx *ictx, u_int i)
19381942
}
19391943
return;
19401944
}
1941-
if (n < 2 || (p[0] != 38 && p[0] != 48))
1945+
if (n < 2 || (p[0] != 38 && p[0] != 48 && p[0] != 58))
19421946
return;
19431947
switch (p[1]) {
19441948
case 2:
@@ -1983,7 +1987,7 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
19831987
if (n == -1)
19841988
continue;
19851989

1986-
if (n == 38 || n == 48) {
1990+
if (n == 38 || n == 48 || n == 58) {
19871991
i++;
19881992
switch (input_get(ictx, i, 0, -1)) {
19891993
case 2:
@@ -2078,6 +2082,9 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
20782082
case 55:
20792083
gc->attr &= ~GRID_ATTR_OVERLINE;
20802084
break;
2085+
case 59:
2086+
gc->us = 0;
2087+
break;
20812088
case 90:
20822089
case 91:
20832090
case 92:

screen-write.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ static const struct grid_cell *screen_write_combine(struct screen_write_ctx *,
3636
const struct utf8_data *, u_int *);
3737

3838
static const struct grid_cell screen_write_pad_cell = {
39-
GRID_FLAG_PADDING, 0, 8, 8, { { 0 }, 0, 0, 0 }
39+
GRID_FLAG_PADDING, 0, 8, 8, 0, { { 0 }, 0, 0, 0 }
4040
};
4141

4242
struct screen_write_collect_item {

style.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
/* Default style. */
3232
static struct style style_default = {
33-
{ 0, 0, 8, 8, { { ' ' }, 0, 1, 1 } },
33+
{ 0, 0, 8, 8, 0, { { ' ' }, 0, 1, 1 } },
3434

3535
STYLE_ALIGN_DEFAULT,
3636
STYLE_LIST_OFF,

tmux.1

+26-4
Original file line numberDiff line numberDiff line change
@@ -5044,11 +5044,33 @@ $ printf '\e033]12;red\e033\e\e'
50445044
.Ed
50455045
.It Em \&Smol
50465046
Enable the overline attribute.
5047+
The capability is usually SGR 53 and can be added to
5048+
.Ic terminal-overrides
5049+
as:
5050+
.Bd -literal -offset indent
5051+
Smol=\eE[53m
5052+
.Ed
50475053
.It Em \&Smulx
5048-
Set a styled underline.
5049-
The single parameter is one of: 0 for no underline, 1 for normal
5050-
underline, 2 for double underline, 3 for curly underline, 4 for dotted
5051-
underline and 5 for dashed underline.
5054+
Set a styled underscore.
5055+
The single parameter is one of: 0 for no underscore, 1 for normal
5056+
underscore, 2 for double underscore, 3 for curly underscore, 4 for dotted
5057+
underscore and 5 for dashed underscore.
5058+
The capability can typically be added to
5059+
.Ic terminal-overrides
5060+
as:
5061+
.Bd -literal -offset indent
5062+
Smulx=\eE[4::%p1%dm
5063+
.Ed
5064+
.It Em \&Setulc
5065+
Set the underscore colour.
5066+
The argument is (red * 65536) + (green * 256) + blue where each is between 0
5067+
and 255.
5068+
The capability can typically be added to
5069+
.Ic terminal-overrides
5070+
as:
5071+
.Bd -literal -offset indent
5072+
Setulc=\eE[58::2::%p1%{65536}%/%d::%p1%{256}%/%{255}%&%d::%p1%{255}%&%d%;m
5073+
.Ed
50525074
.It Em \&Ss , Se
50535075
Set or reset the cursor style.
50545076
If set, a sequence such as this may be used

tmux.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,7 @@ enum tty_code_code {
427427
TTYC_SETAF,
428428
TTYC_SETRGBB,
429429
TTYC_SETRGBF,
430+
TTYC_SETULC,
430431
TTYC_SGR0,
431432
TTYC_SITM,
432433
TTYC_SMACS,
@@ -599,6 +600,7 @@ struct grid_cell {
599600
u_short attr;
600601
int fg;
601602
int bg;
603+
int us;
602604
struct utf8_data data;
603605
};
604606
struct grid_cell_entry {
@@ -2194,7 +2196,8 @@ int colour_join_rgb(u_char, u_char, u_char);
21942196
void colour_split_rgb(int, u_char *, u_char *, u_char *);
21952197
const char *colour_tostring(int);
21962198
int colour_fromstring(const char *s);
2197-
u_char colour_256to16(u_char);
2199+
int colour_256toRGB(int);
2200+
int colour_256to16(int);
21982201

21992202
/* attributes.c */
22002203
const char *attributes_tostring(int);

tty-term.c

+1
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ static const struct tty_term_code_entry tty_term_codes[] = {
246246
[TTYC_SETAF] = { TTYCODE_STRING, "setaf" },
247247
[TTYC_SETRGBB] = { TTYCODE_STRING, "setrgbb" },
248248
[TTYC_SETRGBF] = { TTYCODE_STRING, "setrgbf" },
249+
[TTYC_SETULC] = { TTYCODE_STRING, "Setulc" },
249250
[TTYC_SE] = { TTYCODE_STRING, "Se" },
250251
[TTYC_SGR0] = { TTYCODE_STRING, "sgr0" },
251252
[TTYC_SITM] = { TTYCODE_STRING, "sitm" },

tty.c

+59-5
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,11 @@ static void tty_check_fg(struct tty *, struct window_pane *,
4949
struct grid_cell *);
5050
static void tty_check_bg(struct tty *, struct window_pane *,
5151
struct grid_cell *);
52+
static void tty_check_us(struct tty *, struct window_pane *,
53+
struct grid_cell *);
5254
static void tty_colours_fg(struct tty *, const struct grid_cell *);
5355
static void tty_colours_bg(struct tty *, const struct grid_cell *);
56+
static void tty_colours_us(struct tty *, const struct grid_cell *);
5457

5558
static void tty_region_pane(struct tty *, const struct tty_ctx *, u_int,
5659
u_int);
@@ -1287,6 +1290,7 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
12871290
gcp->attr != last.attr ||
12881291
gcp->fg != last.fg ||
12891292
gcp->bg != last.bg ||
1293+
gcp->us != last.us ||
12901294
ux + width + gcp->data.width > nx ||
12911295
(sizeof buf) - len < gcp->data.size)) {
12921296
tty_attributes(tty, &last, wp);
@@ -2135,7 +2139,8 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
21352139
~(wp->flags & PANE_STYLECHANGED) &&
21362140
gc->attr == tty->last_cell.attr &&
21372141
gc->fg == tty->last_cell.fg &&
2138-
gc->bg == tty->last_cell.bg)
2142+
gc->bg == tty->last_cell.bg &&
2143+
gc->us == tty->last_cell.us)
21392144
return;
21402145
tty->last_wp = (wp != NULL ? (int)wp->id : -1);
21412146
memcpy(&tty->last_cell, gc, sizeof tty->last_cell);
@@ -2163,14 +2168,18 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
21632168
/* Fix up the colours if necessary. */
21642169
tty_check_fg(tty, wp, &gc2);
21652170
tty_check_bg(tty, wp, &gc2);
2171+
tty_check_us(tty, wp, &gc2);
21662172

2167-
/* If any bits are being cleared, reset everything. */
2168-
if (tc->attr & ~gc2.attr)
2173+
/*
2174+
* If any bits are being cleared or the underline colour is now default,
2175+
* reset everything.
2176+
*/
2177+
if ((tc->attr & ~gc2.attr) || (tc->us != gc2.us && gc2.us == 0))
21692178
tty_reset(tty);
21702179

21712180
/*
21722181
* Set the colours. This may call tty_reset() (so it comes next) and
2173-
* may add to (NOT remove) the desired attributes by changing new_attr.
2182+
* may add to (NOT remove) the desired attributes.
21742183
*/
21752184
tty_colours(tty, &gc2);
21762185

@@ -2223,7 +2232,7 @@ tty_colours(struct tty *tty, const struct grid_cell *gc)
22232232
int have_ax;
22242233

22252234
/* No changes? Nothing is necessary. */
2226-
if (gc->fg == tc->fg && gc->bg == tc->bg)
2235+
if (gc->fg == tc->fg && gc->bg == tc->bg && gc->us == tc->us)
22272236
return;
22282237

22292238
/*
@@ -2271,6 +2280,10 @@ tty_colours(struct tty *tty, const struct grid_cell *gc)
22712280
*/
22722281
if (!COLOUR_DEFAULT(gc->bg) && gc->bg != tc->bg)
22732282
tty_colours_bg(tty, gc);
2283+
2284+
/* Set the underscore color. */
2285+
if (gc->us != tc->us)
2286+
tty_colours_us(tty, gc);
22742287
}
22752288

22762289
static void
@@ -2385,6 +2398,22 @@ tty_check_bg(struct tty *tty, struct window_pane *wp, struct grid_cell *gc)
23852398
gc->bg -= 90;
23862399
}
23872400

2401+
static void
2402+
tty_check_us(__unused struct tty *tty, struct window_pane *wp, struct grid_cell *gc)
2403+
{
2404+
int c;
2405+
2406+
/* Perform substitution if this pane has a palette. */
2407+
if (~gc->flags & GRID_FLAG_NOPALETTE) {
2408+
if ((c = window_pane_get_palette(wp, gc->us)) != -1)
2409+
gc->us = c;
2410+
}
2411+
2412+
/* Underscore colour is set as RGB so convert a 256 colour to RGB. */
2413+
if (gc->us & COLOUR_FLAG_256)
2414+
gc->us = colour_256toRGB (gc->us);
2415+
}
2416+
23882417
static void
23892418
tty_colours_fg(struct tty *tty, const struct grid_cell *gc)
23902419
{
@@ -2449,6 +2478,31 @@ tty_colours_bg(struct tty *tty, const struct grid_cell *gc)
24492478
tc->bg = gc->bg;
24502479
}
24512480

2481+
static void
2482+
tty_colours_us(struct tty *tty, const struct grid_cell *gc)
2483+
{
2484+
struct grid_cell *tc = &tty->cell;
2485+
u_int c;
2486+
u_char r, g, b;
2487+
2488+
/* Must be an RGB colour - this should never happen. */
2489+
if (~gc->us & COLOUR_FLAG_RGB)
2490+
return;
2491+
2492+
/*
2493+
* Setulc follows the ncurses(3) one argument "direct colour"
2494+
* capability format. Calculate the colour value.
2495+
*/
2496+
colour_split_rgb(gc->us, &r, &g, &b);
2497+
c = (65536 * r) + (256 * g) + b;
2498+
2499+
/* Write the colour. */
2500+
tty_putcode1(tty, TTYC_SETULC, c);
2501+
2502+
/* Save the new values in the terminal current cell. */
2503+
tc->us = gc->us;
2504+
}
2505+
24522506
static int
24532507
tty_try_colour(struct tty *tty, int colour, const char *type)
24542508
{

0 commit comments

Comments
 (0)