From 8e310303903792c010d03c046ba75f8b18f7d3a7 Mon Sep 17 00:00:00 2001 From: Raheman Vaiya Date: Sun, 26 Dec 2021 18:57:04 +0100 Subject: [PATCH 01/15] Add support for OSC color sequences --- config.def.h | 8 ++++-- st.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++- st.h | 3 ++ x.c | 13 +++++++++ 4 files changed, 100 insertions(+), 4 deletions(-) diff --git a/config.def.h b/config.def.h index 6f05dce..91ab8ca 100644 --- a/config.def.h +++ b/config.def.h @@ -120,6 +120,8 @@ static const char *colorname[] = { /* more colors can be added after 255 to use with DefaultXX */ "#cccccc", "#555555", + "gray90", /* default foreground colour */ + "black", /* default background colour */ }; @@ -127,9 +129,9 @@ static const char *colorname[] = { * Default colors (colorname index) * foreground, background, cursor, reverse cursor */ -unsigned int defaultfg = 7; -unsigned int defaultbg = 0; -static unsigned int defaultcs = 256; +unsigned int defaultfg = 258; +unsigned int defaultbg = 259; +unsigned int defaultcs = 256; static unsigned int defaultrcs = 257; /* diff --git a/st.c b/st.c index a9338e1..781dbf2 100644 --- a/st.c +++ b/st.c @@ -1842,6 +1842,42 @@ csireset(void) memset(&csiescseq, 0, sizeof(csiescseq)); } +void +osc4_color_response(int num) +{ + int n; + char buf[32]; + unsigned char r, g, b; + + if (xgetcolor(num, &r, &g, &b)) { + fprintf(stderr, "erresc: failed to fetch osc4 color %d\n", num); + return; + } + + n = snprintf(buf, sizeof buf, "\033]4;%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + num, r, r, g, g, b, b); + + ttywrite(buf, n, 1); +} + +void +osc_color_response(int index, int num) +{ + int n; + char buf[32]; + unsigned char r, g, b; + + if (xgetcolor(index, &r, &g, &b)) { + fprintf(stderr, "erresc: failed to fetch osc color %d\n", index); + return; + } + + n = snprintf(buf, sizeof buf, "\033]%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + num, r, r, g, g, b, b); + + ttywrite(buf, n, 1); +} + void strhandle(void) { @@ -1880,6 +1916,45 @@ strhandle(void) } } return; + case 10: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultfg, 10); + else if (xsetcolorname(defaultfg, p)) + fprintf(stderr, "erresc: invalid foreground color: %s\n", p); + else + redraw(); + break; + case 11: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultbg, 11); + else if (xsetcolorname(defaultbg, p)) + fprintf(stderr, "erresc: invalid background color: %s\n", p); + else + redraw(); + break; + case 12: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultcs, 12); + else if (xsetcolorname(defaultcs, p)) + fprintf(stderr, "erresc: invalid cursor color: %s\n", p); + else + redraw(); + break; case 4: /* color set */ if (narg < 3) break; @@ -1887,7 +1962,10 @@ strhandle(void) /* FALLTHROUGH */ case 104: /* color reset, here p = NULL */ j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - if (xsetcolorname(j, p)) { + + if (!strcmp(p, "?")) + osc4_color_response(j); + else if (xsetcolorname(j, p)) { if (par == 104 && narg <= 1) return; /* color reset without parameter */ fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", diff --git a/st.h b/st.h index fa2eddf..519b9bd 100644 --- a/st.h +++ b/st.h @@ -111,6 +111,8 @@ void *xmalloc(size_t); void *xrealloc(void *, size_t); char *xstrdup(const char *); +int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b); + /* config.h globals */ extern char *utmp; extern char *scroll; @@ -123,3 +125,4 @@ extern char *termname; extern unsigned int tabspaces; extern unsigned int defaultfg; extern unsigned int defaultbg; +extern unsigned int defaultcs; diff --git a/x.c b/x.c index 89786b8..8a16faa 100644 --- a/x.c +++ b/x.c @@ -799,6 +799,19 @@ xloadcols(void) loaded = 1; } +int +xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b) +{ + if (!BETWEEN(x, 0, dc.collen)) + return 1; + + *r = dc.col[x].color.red >> 8; + *g = dc.col[x].color.green >> 8; + *b = dc.col[x].color.blue >> 8; + + return 0; +} + int xsetcolorname(int x, const char *name) { From 273db5ceaf392e68c2faf8f7dec14ea2e25e980d Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sun, 26 Dec 2021 19:00:41 +0100 Subject: [PATCH 02/15] follow-up fix for OSC color sequences, return Otherwise the message "erresc: unknown str" is printed. --- st.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/st.c b/st.c index 781dbf2..6783c2b 100644 --- a/st.c +++ b/st.c @@ -1928,7 +1928,7 @@ strhandle(void) fprintf(stderr, "erresc: invalid foreground color: %s\n", p); else redraw(); - break; + return; case 11: if (narg < 2) break; @@ -1941,7 +1941,7 @@ strhandle(void) fprintf(stderr, "erresc: invalid background color: %s\n", p); else redraw(); - break; + return; case 12: if (narg < 2) break; @@ -1954,7 +1954,7 @@ strhandle(void) fprintf(stderr, "erresc: invalid cursor color: %s\n", p); else redraw(); - break; + return; case 4: /* color set */ if (narg < 3) break; From a0467c802d4f86ed162486e3453dd61181423902 Mon Sep 17 00:00:00 2001 From: Jochen Sprickerhof Date: Mon, 27 Dec 2021 11:41:42 +0100 Subject: [PATCH 03/15] Fix null pointer access in strhandle According to the spec the argument is optional for 104, so p can be NULL as can be tested with printf '\x1b]104\x07'. This is a regression of 8e31030. --- st.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/st.c b/st.c index 6783c2b..de2dd0e 100644 --- a/st.c +++ b/st.c @@ -1960,10 +1960,10 @@ strhandle(void) break; p = strescseq.args[2]; /* FALLTHROUGH */ - case 104: /* color reset, here p = NULL */ + case 104: /* color reset */ j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - if (!strcmp(p, "?")) + if (p && !strcmp(p, "?")) osc4_color_response(j); else if (xsetcolorname(j, p)) { if (par == 104 && narg <= 1) From 65f1dc428315ae9d7f362e10c668557c1379e7af Mon Sep 17 00:00:00 2001 From: jamin Date: Wed, 29 Dec 2021 09:07:17 -0800 Subject: [PATCH 04/15] Fix overtyping wide characters. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Overtyping the first half of a wide character with the second half of a wide character results in display garbage. This is because the trailing dummy is not cleaned up. i.e. ATTR_WIDE, ATTR_WDUMMY, ATTR_WDUMMY Here is a short script for demonstrating the behavior: #!/bin/sh alias printf=/usr/bin/printf printf こんにちは!; sleep 2 printf '\x1b[5D'; sleep 2 printf へ; sleep 2 printf ' '; sleep 2 echo --- st.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/st.c b/st.c index de2dd0e..51049ba 100644 --- a/st.c +++ b/st.c @@ -2507,6 +2507,10 @@ check_control_code: if (width == 2) { gp->mode |= ATTR_WIDE; if (term.c.x+1 < term.col) { + if (gp[1].mode == ATTR_WIDE && term.c.x+2 < term.col) { + gp[2].u = ' '; + gp[2].mode &= ~ATTR_WDUMMY; + } gp[1].u = '\0'; gp[1].mode = ATTR_WDUMMY; } From 7e1c68f25d9f08687a94eeef8d7f8ffd0d14b911 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sun, 2 Jan 2022 12:15:45 +0100 Subject: [PATCH 05/15] FAQ: fix a typo, patch -> path --- FAQ | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FAQ b/FAQ index 0f9609d..969b195 100644 --- a/FAQ +++ b/FAQ @@ -29,8 +29,8 @@ you can manually run `tic -sx st.info`. ## I would like to have utmp and/or scroll functionality by default -You can add the absolute patch of both programs in your config.h -file. You only have to modify the value of utmp and scroll variables. +You can add the absolute path of both programs in your config.h file. You only +have to modify the value of utmp and scroll variables. ## Why doesn't the Del key work in some programs? From 7fb0c0cc681f36be2ad12091ef93a41671f32738 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 7 Jan 2022 12:39:57 +0100 Subject: [PATCH 06/15] bump version to 0.8.5 --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index c070a4a..4c4c5d5 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # st version -VERSION = 0.8.4 +VERSION = 0.8.5 # Customize below to fit your system From ea7cd7b62fdfa6a1fbd882d1565d557577f2cf32 Mon Sep 17 00:00:00 2001 From: robert Date: Sat, 8 Jan 2022 11:40:34 -0800 Subject: [PATCH 07/15] Fix mousereport This patch replaces the previous one I sent. The following changes are made in this patch: - Fix tracking of pressed buttons. Previously, pressing two buttons and then releasing one would make st think no buttons are pressed, which in particular broke MODE_MOUSEMOTION. - Always send the lowest-numbered pressed button on motion events; when no button is pressed for a motion event in MODE_MOUSEMANY, then send a release. This matches the behaviour of xterm. (Previously, st sent the most recently pressed button in the motion report.) - Remove UB (?) access to potentially inactive struct member e->xbutton.button of XEvent union. - Fix (unlikely) possibility of overflow for large button numbers. The one discrepancy I found between st and xterm is that xterm sometimes encodes buttons with large numbers (>5) strangely. E.g., xterm reports presses of buttons 8 and 9 as releases, whereas st properly (?) encodes them as presses. --- x.c | 86 ++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 51 insertions(+), 35 deletions(-) diff --git a/x.c b/x.c index 8a16faa..5f4ea73 100644 --- a/x.c +++ b/x.c @@ -252,7 +252,7 @@ static char *opt_line = NULL; static char *opt_name = NULL; static char *opt_title = NULL; -static int oldbutton = 3; /* button event on startup: 3 = release */ +static uint buttons; /* bit field of pressed buttons */ void clipcopy(const Arg *dummy) @@ -364,61 +364,68 @@ mousesel(XEvent *e, int done) void mousereport(XEvent *e) { - int len, x = evcol(e), y = evrow(e), - button = e->xbutton.button, state = e->xbutton.state; + int len, btn, code; + int x = evcol(e), y = evrow(e); + int state = e->xbutton.state; char buf[40]; static int ox, oy; - /* from urxvt */ - if (e->xbutton.type == MotionNotify) { + if (e->type == MotionNotify) { if (x == ox && y == oy) return; if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) return; - /* MOUSE_MOTION: no reporting if no button is pressed */ - if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3) + /* MODE_MOUSEMOTION: no reporting if no button is pressed */ + if (IS_SET(MODE_MOUSEMOTION) && buttons == 0) return; - - button = oldbutton + 32; - ox = x; - oy = y; + /* Set btn to lowest-numbered pressed button, or 12 if no + * buttons are pressed. */ + for (btn = 1; btn <= 11 && !(buttons & (1<<(btn-1))); btn++) + ; + code = 32; } else { - if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) { - button = 3; - } else { - button -= Button1; - if (button >= 7) - button += 128 - 7; - else if (button >= 3) - button += 64 - 3; - } - if (e->xbutton.type == ButtonPress) { - oldbutton = button; - ox = x; - oy = y; - } else if (e->xbutton.type == ButtonRelease) { - oldbutton = 3; + btn = e->xbutton.button; + /* Only buttons 1 through 11 can be encoded */ + if (btn < 1 || btn > 11) + return; + if (e->type == ButtonRelease) { /* MODE_MOUSEX10: no button release reporting */ if (IS_SET(MODE_MOUSEX10)) return; - if (button == 64 || button == 65) + /* Don't send release events for the scroll wheel */ + if (btn == 4 || btn == 5) return; } + code = 0; } + ox = x; + oy = y; + + /* Encode btn into code. If no button is pressed for a motion event in + * MODE_MOUSEMANY, then encode it as a release. */ + if ((!IS_SET(MODE_MOUSESGR) && e->type == ButtonRelease) || btn == 12) + code += 3; + else if (btn >= 8) + code += 128 + btn - 8; + else if (btn >= 4) + code += 64 + btn - 4; + else + code += btn - 1; + if (!IS_SET(MODE_MOUSEX10)) { - button += ((state & ShiftMask ) ? 4 : 0) - + ((state & Mod4Mask ) ? 8 : 0) - + ((state & ControlMask) ? 16 : 0); + code += ((state & ShiftMask ) ? 4 : 0) + + ((state & Mod4Mask ) ? 8 : 0) + + ((state & ControlMask) ? 16 : 0); } if (IS_SET(MODE_MOUSESGR)) { len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", - button, x+1, y+1, - e->xbutton.type == ButtonRelease ? 'm' : 'M'); + code, x+1, y+1, + e->type == ButtonRelease ? 'm' : 'M'); } else if (x < 223 && y < 223) { len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", - 32+button, 32+x+1, 32+y+1); + 32+code, 32+x+1, 32+y+1); } else { return; } @@ -461,9 +468,13 @@ mouseaction(XEvent *e, uint release) void bpress(XEvent *e) { + int btn = e->xbutton.button; struct timespec now; int snap; + if (1 <= btn && btn <= 11) + buttons |= 1 << (btn-1); + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { mousereport(e); return; @@ -472,7 +483,7 @@ bpress(XEvent *e) if (mouseaction(e, 0)) return; - if (e->xbutton.button == Button1) { + if (btn == Button1) { /* * If the user clicks below predefined timeouts specific * snapping behaviour is exposed. @@ -686,6 +697,11 @@ xsetsel(char *str) void brelease(XEvent *e) { + int btn = e->xbutton.button; + + if (1 <= btn && btn <= 11) + buttons &= ~(1 << (btn-1)); + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { mousereport(e); return; @@ -693,7 +709,7 @@ brelease(XEvent *e) if (mouseaction(e, 1)) return; - if (e->xbutton.button == Button1) + if (btn == Button1) mousesel(e, 1); } From b1d97fec47b0d6633addb848131388ec40154ebc Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Mon, 10 Jan 2022 17:11:17 +0100 Subject: [PATCH 08/15] LICENSE: bump year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index d80eb47..3cbf420 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT/X Consortium License -© 2014-2020 Hiltjo Posthuma +© 2014-2022 Hiltjo Posthuma © 2018 Devin J. Pohly © 2014-2017 Quentin Rameau © 2009-2012 Aurélien APTEL From 2c5edf28ec851907305d73c6218ce75d39f1767f Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Wed, 12 Jan 2022 09:44:27 +0100 Subject: [PATCH 09/15] X10/SGR mouse: use alt as meta key instead of super/windows key --- x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x.c b/x.c index 5f4ea73..cd96575 100644 --- a/x.c +++ b/x.c @@ -415,7 +415,7 @@ mousereport(XEvent *e) if (!IS_SET(MODE_MOUSEX10)) { code += ((state & ShiftMask ) ? 4 : 0) - + ((state & Mod4Mask ) ? 8 : 0) + + ((state & Mod1Mask ) ? 8 : 0) /* meta key: alt */ + ((state & ControlMask) ? 16 : 0); } From e823e2308f2a99023032a3966ebb7036a31d305f Mon Sep 17 00:00:00 2001 From: Santtu Lakkala Date: Thu, 17 Feb 2022 16:00:47 +0200 Subject: [PATCH 10/15] Delay redrawals on palette changes Build on auto-sync and only mark window dirty on palette changes and let the event handler do the actual draw. --- st.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/st.c b/st.c index 51049ba..c71fa06 100644 --- a/st.c +++ b/st.c @@ -1927,7 +1927,7 @@ strhandle(void) else if (xsetcolorname(defaultfg, p)) fprintf(stderr, "erresc: invalid foreground color: %s\n", p); else - redraw(); + tfulldirt(); return; case 11: if (narg < 2) @@ -1940,7 +1940,7 @@ strhandle(void) else if (xsetcolorname(defaultbg, p)) fprintf(stderr, "erresc: invalid background color: %s\n", p); else - redraw(); + tfulldirt(); return; case 12: if (narg < 2) @@ -1953,7 +1953,7 @@ strhandle(void) else if (xsetcolorname(defaultcs, p)) fprintf(stderr, "erresc: invalid cursor color: %s\n", p); else - redraw(); + tfulldirt(); return; case 4: /* color set */ if (narg < 3) @@ -1975,7 +1975,7 @@ strhandle(void) * TODO if defaultbg color is changed, borders * are dirty */ - redraw(); + tfulldirt(); } return; } From 2aefa348baf4b702fdce98eb105bcba175d8283f Mon Sep 17 00:00:00 2001 From: Zacchary Dempsey-Plante Date: Sun, 13 Mar 2022 10:44:08 +0100 Subject: [PATCH 11/15] make underlines and strikethroughs respect `chscale` --- x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x.c b/x.c index cd96575..2a3bd38 100644 --- a/x.c +++ b/x.c @@ -1493,12 +1493,12 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i /* Render underline and strikethrough. */ if (base.mode & ATTR_UNDERLINE) { - XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, + XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1, width, 1); } if (base.mode & ATTR_STRUCK) { - XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, + XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3, width, 1); } From af3bb68add1c40d19d0dee382009e21b0870a38f Mon Sep 17 00:00:00 2001 From: NRK Date: Fri, 18 Mar 2022 16:20:54 +0600 Subject: [PATCH 12/15] avoid potential UB when using isprint() all the ctype.h functions' argument must be representable as an unsigned char or as EOF, otherwise the behavior is undefined. --- st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/st.c b/st.c index c71fa06..1307fdf 100644 --- a/st.c +++ b/st.c @@ -367,7 +367,7 @@ static const char base64_digits[] = { char base64dec_getc(const char **src) { - while (**src && !isprint(**src)) + while (**src && !isprint((unsigned char)**src)) (*src)++; return **src ? *((*src)++) : '='; /* emulate padding if string ends */ } From ef0551932fb162f907b40185d2f48c3b497708ee Mon Sep 17 00:00:00 2001 From: NRK Date: Fri, 18 Mar 2022 17:03:34 +0600 Subject: [PATCH 13/15] base64_digits: reduce scope, implicit zero, +1 size the array is not accessed outside of base64dec() so it makes sense to limit it's scope to the related function. the static-storage duration of the array is kept intact. this also removes unnecessary explicit zeroing from the start and end of the array. anything that wasn't explicitly zero-ed will now be implicitly zero-ed instead. the validity of the new array can be easily confirmed via running this trivial loop: for (int i = 0; i < 255; ++i) assert(base64_digits[i] == base64_digits_old[i]); lastly, as pointed out by Roberto, the array needs to have 256 elements in order to able access it as any unsigned char as an index; the previous array had 255. however, this array will only be accessed at indexes which are isprint() || '=' (see `base64dec_getc()`), so reducing the size of the array to the highest printable ascii char (127 AFAIK) + 1 might also be a valid strategy. --- st.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/st.c b/st.c index 1307fdf..f43cfd3 100644 --- a/st.c +++ b/st.c @@ -349,21 +349,6 @@ utf8validate(Rune *u, size_t i) return i; } -static const char base64_digits[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, - 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, -1, 0, 0, 0, 0, 1, - 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - char base64dec_getc(const char **src) { @@ -377,6 +362,13 @@ base64dec(const char *src) { size_t in_len = strlen(src); char *result, *dst; + static const char base64_digits[256] = { + [43] = 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, + 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 + }; if (in_len % 4) in_len += 4 - (in_len % 4); From 8629d9a1da72cc18568a8f146307b0e939b77ebf Mon Sep 17 00:00:00 2001 From: NRK Date: Fri, 7 Jan 2022 23:21:04 +0600 Subject: [PATCH 14/15] code-golfing: cleanup osc color related code * adds missing function prototype * move xgetcolor() prototype to win.h (that's where all the other x.c func prototype seems to be declared at) * check for snprintf error/truncation * reduces code duplication for osc 10/11/12 * unify osc_color_response() and osc4_color_response() into a single function the latter two was suggested by Quentin Rameau in his patch review on the hackers list. --- st.c | 88 +++++++++++++++++++++-------------------------------------- st.h | 2 -- win.h | 1 + 3 files changed, 32 insertions(+), 59 deletions(-) diff --git a/st.c b/st.c index f43cfd3..6ba467d 100644 --- a/st.c +++ b/st.c @@ -161,6 +161,7 @@ static void csidump(void); static void csihandle(void); static void csiparse(void); static void csireset(void); +static void osc_color_response(int, int, int); static int eschandle(uchar); static void strdump(void); static void strhandle(void); @@ -1835,39 +1836,28 @@ csireset(void) } void -osc4_color_response(int num) +osc_color_response(int num, int index, int is_osc4) { int n; char buf[32]; unsigned char r, g, b; - if (xgetcolor(num, &r, &g, &b)) { - fprintf(stderr, "erresc: failed to fetch osc4 color %d\n", num); + if (xgetcolor(is_osc4 ? num : index, &r, &g, &b)) { + fprintf(stderr, "erresc: failed to fetch %s color %d\n", + is_osc4 ? "osc4" : "osc", + is_osc4 ? num : index); return; } - n = snprintf(buf, sizeof buf, "\033]4;%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", - num, r, r, g, g, b, b); - - ttywrite(buf, n, 1); -} - -void -osc_color_response(int index, int num) -{ - int n; - char buf[32]; - unsigned char r, g, b; - - if (xgetcolor(index, &r, &g, &b)) { - fprintf(stderr, "erresc: failed to fetch osc color %d\n", index); - return; + n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + is_osc4 ? "4;" : "", num, r, r, g, g, b, b); + if (n < 0 || n >= sizeof(buf)) { + fprintf(stderr, "error: %s while printing %s response\n", + n < 0 ? "snprintf failed" : "truncation occurred", + is_osc4 ? "osc4" : "osc"); + } else { + ttywrite(buf, n, 1); } - - n = snprintf(buf, sizeof buf, "\033]%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", - num, r, r, g, g, b, b); - - ttywrite(buf, n, 1); } void @@ -1875,6 +1865,11 @@ strhandle(void) { char *p = NULL, *dec; int j, narg, par; + const struct { int idx; char *str; } osc_table[] = { + { defaultfg, "foreground" }, + { defaultbg, "background" }, + { defaultcs, "cursor" } + }; term.esc &= ~(ESC_STR_END|ESC_STR); strparse(); @@ -1909,43 +1904,22 @@ strhandle(void) } return; case 10: - if (narg < 2) - break; - - p = strescseq.args[1]; - - if (!strcmp(p, "?")) - osc_color_response(defaultfg, 10); - else if (xsetcolorname(defaultfg, p)) - fprintf(stderr, "erresc: invalid foreground color: %s\n", p); - else - tfulldirt(); - return; case 11: - if (narg < 2) - break; - - p = strescseq.args[1]; - - if (!strcmp(p, "?")) - osc_color_response(defaultbg, 11); - else if (xsetcolorname(defaultbg, p)) - fprintf(stderr, "erresc: invalid background color: %s\n", p); - else - tfulldirt(); - return; case 12: if (narg < 2) break; - p = strescseq.args[1]; + if ((j = par - 10) < 0 || j >= LEN(osc_table)) + break; /* shouldn't be possible */ - if (!strcmp(p, "?")) - osc_color_response(defaultcs, 12); - else if (xsetcolorname(defaultcs, p)) - fprintf(stderr, "erresc: invalid cursor color: %s\n", p); - else + if (!strcmp(p, "?")) { + osc_color_response(par, osc_table[j].idx, 0); + } else if (xsetcolorname(osc_table[j].idx, p)) { + fprintf(stderr, "erresc: invalid %s color: %s\n", + osc_table[j].str, p); + } else { tfulldirt(); + } return; case 4: /* color set */ if (narg < 3) @@ -1955,9 +1929,9 @@ strhandle(void) case 104: /* color reset */ j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - if (p && !strcmp(p, "?")) - osc4_color_response(j); - else if (xsetcolorname(j, p)) { + if (p && !strcmp(p, "?")) { + osc_color_response(j, 0, 1); + } else if (xsetcolorname(j, p)) { if (par == 104 && narg <= 1) return; /* color reset without parameter */ fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", diff --git a/st.h b/st.h index 519b9bd..fd3b0d8 100644 --- a/st.h +++ b/st.h @@ -111,8 +111,6 @@ void *xmalloc(size_t); void *xrealloc(void *, size_t); char *xstrdup(const char *); -int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b); - /* config.h globals */ extern char *utmp; extern char *scroll; diff --git a/win.h b/win.h index e6e4369..6de960d 100644 --- a/win.h +++ b/win.h @@ -30,6 +30,7 @@ void xdrawline(Line, int, int, int); void xfinishdraw(void); void xloadcols(void); int xsetcolorname(int, const char *); +int xgetcolor(int, unsigned char *, unsigned char *, unsigned char *); void xseticontitle(char *); void xsettitle(char *); int xsetcursor(int); From baa9357e96d2478baa52a3301e70ac80a229b726 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sun, 1 May 2022 18:38:40 +0200 Subject: [PATCH 15/15] Makefile: add manual path for OpenBSD --- config.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/config.mk b/config.mk index 4c4c5d5..ddf278a 100644 --- a/config.mk +++ b/config.mk @@ -30,6 +30,7 @@ STLDFLAGS = $(LIBS) $(LDFLAGS) #LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ # `$(PKG_CONFIG) --libs fontconfig` \ # `$(PKG_CONFIG) --libs freetype2` +#MANPREFIX = ${PREFIX}/man # compiler and linker # CC = c99