Oh, I guess the mailing list manager swallowed the subscribe message --- Hello
The render- patches are independent of each other, but depend on the first reorder-and-extend. Move default-rows-cols to config is completely independent, and makes sense on its own. The fast-blink support involves a bit of mucking about in the main loop, and is a bit more debatable. I'm not entirely happy with it, but it does separate things a bit. It also makes independent windows blink synchronously, which makes me slightly less crazy. cheers aes
From 313012a5e28bedd9aa8c7e23fa0b8f09c4f3a3ab Mon Sep 17 00:00:00 2001 From: Anders Eurenius <a...@spotify.com> Date: Sat, 21 Jun 2014 20:29:36 +0200 Subject: [PATCH 1/6] Reorder and extend glyph attributes --- st.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/st.c b/st.c index 26053b0..4ffb3df 100644 --- a/st.c +++ b/st.c @@ -90,15 +90,19 @@ char *argv0; #define VT102ID "\033[?6c" enum glyph_attribute { - ATTR_NULL = 0, - ATTR_REVERSE = 1, - ATTR_UNDERLINE = 2, - ATTR_BOLD = 4, - ATTR_ITALIC = 8, + ATTR_NULL = 0, + ATTR_BOLD = 1, + ATTR_FAINT = 2, + ATTR_ITALIC = 4, + ATTR_UNDERLINE = 8, ATTR_BLINK = 16, - ATTR_WRAP = 32, - ATTR_WIDE = 64, - ATTR_WDUMMY = 128, + ATTR_FASTBLINK = 32, + ATTR_REVERSE = 64, + ATTR_INVISIBLE = 128, + ATTR_STRUCK = 256, + ATTR_WRAP = 512, + ATTR_WIDE = 1024, + ATTR_WDUMMY = 2048, }; enum cursor_movement { @@ -1682,15 +1686,25 @@ tsetattr(int *attr, int l) { for(i = 0; i < l; i++) { switch(attr[i]) { case 0: - term.c.attr.mode &= ~(ATTR_REVERSE | ATTR_UNDERLINE \ - | ATTR_BOLD | ATTR_ITALIC \ - | ATTR_BLINK); + term.c.attr.mode &= ~( + ATTR_BOLD | + ATTR_FAINT | + ATTR_ITALIC | + ATTR_UNDERLINE | + ATTR_BLINK | + ATTR_FASTBLINK | + ATTR_REVERSE | + ATTR_INVISIBLE | + ATTR_STRUCK ); term.c.attr.fg = defaultfg; term.c.attr.bg = defaultbg; break; case 1: term.c.attr.mode |= ATTR_BOLD; break; + case 2: + term.c.attr.mode |= ATTR_FAINT; + break; case 3: term.c.attr.mode |= ATTR_ITALIC; break; @@ -1698,16 +1712,26 @@ tsetattr(int *attr, int l) { term.c.attr.mode |= ATTR_UNDERLINE; break; case 5: /* slow blink */ - case 6: /* rapid blink */ term.c.attr.mode |= ATTR_BLINK; break; + case 6: /* rapid blink */ + term.c.attr.mode |= ATTR_FASTBLINK; + break; case 7: term.c.attr.mode |= ATTR_REVERSE; break; + case 8: + term.c.attr.mode |= ATTR_INVISIBLE; + break; + case 9: + term.c.attr.mode |= ATTR_STRUCK; + break; case 21: - case 22: term.c.attr.mode &= ~ATTR_BOLD; break; + case 22: + term.c.attr.mode &= ~ATTR_FAINT; + break; case 23: term.c.attr.mode &= ~ATTR_ITALIC; break; @@ -1715,12 +1739,20 @@ tsetattr(int *attr, int l) { term.c.attr.mode &= ~ATTR_UNDERLINE; break; case 25: - case 26: term.c.attr.mode &= ~ATTR_BLINK; break; + case 26: + term.c.attr.mode &= ~ATTR_FASTBLINK; + break; case 27: term.c.attr.mode &= ~ATTR_REVERSE; break; + case 28: + term.c.attr.mode &= ~ATTR_INVISIBLE; + break; + case 29: + term.c.attr.mode &= ~ATTR_STRUCK; + break; case 38: if ((idx = tdefcolor(attr, &i, l)) >= 0) term.c.attr.fg = idx; -- 2.0.0
From 06d67617e79ec6e4a63635c65654a76658136973 Mon Sep 17 00:00:00 2001 From: Anders Eurenius <a...@spotify.com> Date: Sat, 21 Jun 2014 20:30:22 +0200 Subject: [PATCH 2/6] Render invisible attribute --- st.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/st.c b/st.c index 4ffb3df..2083d42 100644 --- a/st.c +++ b/st.c @@ -3236,6 +3236,9 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { if(base.mode & ATTR_BLINK && term.mode & MODE_BLINK) fg = bg; + if(base.mode & ATTR_INVISIBLE) + fg = bg; + /* Intelligent cleaning up of the borders. */ if(x == 0) { xclear(0, (y == 0)? 0 : winy, borderpx, -- 2.0.0
From 47feca0fe1e719dabd67a4e8691372493d38074b Mon Sep 17 00:00:00 2001 From: Anders Eurenius <a...@spotify.com> Date: Sat, 21 Jun 2014 20:32:34 +0200 Subject: [PATCH 3/6] Render struck-out attribute --- st.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/st.c b/st.c index 2083d42..dcbc4cb 100644 --- a/st.c +++ b/st.c @@ -3383,6 +3383,11 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { width, 1); } + if(base.mode & ATTR_STRUCK) { + XftDrawRect(xw.draw, fg, winx, winy + 2 * font->ascent / 3, + width, 1); + } + /* Reset clip to none. */ XftDrawSetClip(xw.draw, 0); } -- 2.0.0
From 0caf4828c9ecace69322ebf87b37c91310b27f43 Mon Sep 17 00:00:00 2001 From: Anders Eurenius <a...@spotify.com> Date: Sun, 22 Jun 2014 00:10:59 +0200 Subject: [PATCH 4/6] Render faint attribute --- st.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/st.c b/st.c index dcbc4cb..40dcdf3 100644 --- a/st.c +++ b/st.c @@ -3189,7 +3189,7 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { * change basic system colors [0-7] * to bright system colors [8-15] */ - if(BETWEEN(base.fg, 0, 7)) + if(BETWEEN(base.fg, 0, 7) && !(base.mode & ATTR_FAINT)) fg = &dc.col[base.fg + 8]; if(base.mode & ATTR_ITALIC) { @@ -3233,6 +3233,14 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { bg = temp; } + if(base.mode & ATTR_FAINT && !(base.mode & ATTR_BOLD)) { + colfg.red = fg->color.red / 2; + colfg.green = fg->color.green / 2; + colfg.blue = fg->color.blue / 2; + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); + fg = &revfg; + } + if(base.mode & ATTR_BLINK && term.mode & MODE_BLINK) fg = bg; -- 2.0.0
From 8192b6f0f6f68dff2016022003406ba2f0d69aeb Mon Sep 17 00:00:00 2001 From: Anders Eurenius <a...@spotify.com> Date: Sat, 21 Jun 2014 20:34:11 +0200 Subject: [PATCH 5/6] Move default rows, cols to config.def.h --- config.def.h | 2 ++ st.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index fadcfa0..68c2051 100644 --- a/config.def.h +++ b/config.def.h @@ -6,6 +6,8 @@ * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ static char font[] = "Liberation Mono:pixelsize=12:antialias=false:autohint=false"; +static int default_cols = 80; +static int default_rows = 24; static int borderpx = 2; static char shell[] = "/bin/sh"; diff --git a/st.c b/st.c index 40dcdf3..1621352 100644 --- a/st.c +++ b/st.c @@ -3862,7 +3862,8 @@ usage(void) { int main(int argc, char *argv[]) { char *titles; - uint cols = 80, rows = 24; + uint cols = default_cols; + uint rows = default_rows; xw.l = xw.t = 0; xw.isfixed = False; -- 2.0.0
From 7482a4bf5f58274f7f0c032b91c18c673375b277 Mon Sep 17 00:00:00 2001 From: Anders Eurenius <a...@spotify.com> Date: Sun, 22 Jun 2014 16:02:06 +0200 Subject: [PATCH 6/6] Refactor mainloop, add fast blink support --- st.c | 136 ++++++++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 86 insertions(+), 50 deletions(-) diff --git a/st.c b/st.c index 1621352..f256528 100644 --- a/st.c +++ b/st.c @@ -3244,6 +3244,9 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { if(base.mode & ATTR_BLINK && term.mode & MODE_BLINK) fg = bg; + if(base.mode & ATTR_FASTBLINK && term.mode & MODE_FBLINK) + fg = bg; + if(base.mode & ATTR_INVISIBLE) fg = bg; @@ -3752,12 +3755,10 @@ resize(XEvent *e) { } void -run(void) { +init(void) +{ XEvent ev; int w = xw.w, h = xw.h; - fd_set rfd; - int xfd = XConnectionNumber(xw.dpy), xev, blinkset = 0, dodraw = 0; - struct timeval drawtimeout, *tv = NULL, now, last, lastblink; /* Waiting for window mapping */ while(1) { @@ -3772,32 +3773,75 @@ run(void) { ttynew(); cresize(w, h); +} + +const int xev_activity = 1; +const int cmd_activity = 2; + +int do_select(struct timeval *tv) +{ + int xfd = XConnectionNumber(xw.dpy); + fd_set rfd; + + FD_ZERO(&rfd); + FD_SET(cmdfd, &rfd); + FD_SET(xfd, &rfd); + + while(select(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, tv) < 0) { + if(errno == EINTR) + continue; + die("select failed: %s\n", strerror(errno)); + } + + return (FD_ISSET(xfd, &rfd)? xev_activity: 0) | + (FD_ISSET(cmdfd, &rfd)? cmd_activity: 0); +} + +int +setblinks(struct timeval *now) +{ + unsigned long long int t = now->tv_sec * 1000 + now->tv_usec / 1000; + int blink, fblink, change = 0; + + blink = (t / blinktimeout) & 1; + if(!!(term.mode & MODE_BLINK) != blink) + change = 1; + + fblink = (t / (blinktimeout / 4)) & 1; + if(!!(term.mode & MODE_FBLINK) != fblink) + change = 1; + + MODBIT(term.mode, blink, MODE_BLINK); + MODBIT(term.mode, fblink, MODE_FBLINK); + + return change; +} + +void +run(void) { + XEvent ev; + int s, xev, blinkset = 0, dodraw = 0; + struct timeval drawtimeout, *tv = NULL, now, last; + + init(); gettimeofday(&last, NULL); - lastblink = last; + xev = actionfps; - for(xev = actionfps;;) { + for(;;) { long deltatime; - FD_ZERO(&rfd); - FD_SET(cmdfd, &rfd); - FD_SET(xfd, &rfd); + s = do_select(tv); - if(select(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, tv) < 0) { - if(errno == EINTR) - continue; - die("select failed: %s\n", strerror(errno)); - } - if(FD_ISSET(cmdfd, &rfd)) { + if(s & cmd_activity) { ttyread(); if(blinktimeout) { - blinkset = tattrset(ATTR_BLINK); - if(!blinkset) - MODBIT(term.mode, 0, MODE_BLINK); + blinkset = tattrset(ATTR_BLINK) | + tattrset(ATTR_FASTBLINK); } } - if(FD_ISSET(xfd, &rfd)) + if(s & xev_activity) xev = actionfps; gettimeofday(&now, NULL); @@ -3806,10 +3850,9 @@ run(void) { tv = &drawtimeout; dodraw = 0; - if(blinktimeout && TIMEDIFF(now, lastblink) > blinktimeout) { + if(blinktimeout && blinkset && setblinks(&now)) { tsetdirtattr(ATTR_BLINK); - term.mode ^= MODE_BLINK; - lastblink = now; + tsetdirtattr(ATTR_FASTBLINK); dodraw = 1; } deltatime = TIMEDIFF(now, last); @@ -3819,35 +3862,28 @@ run(void) { last = now; } - if(dodraw) { - while(XPending(xw.dpy)) { - XNextEvent(xw.dpy, &ev); - if(XFilterEvent(&ev, None)) - continue; - if(handler[ev.type]) - (handler[ev.type])(&ev); - } + if(!dodraw) + continue; - draw(); - XFlush(xw.dpy); - - if(xev && !FD_ISSET(xfd, &rfd)) - xev--; - if(!FD_ISSET(cmdfd, &rfd) && !FD_ISSET(xfd, &rfd)) { - if(blinkset) { - if(TIMEDIFF(now, lastblink) \ - > blinktimeout) { - drawtimeout.tv_usec = 1; - } else { - drawtimeout.tv_usec = (1000 * \ - (blinktimeout - \ - TIMEDIFF(now, - lastblink))); - } - } else { - tv = NULL; - } - } + while(XPending(xw.dpy)) { + XNextEvent(xw.dpy, &ev); + if(XFilterEvent(&ev, None)) + continue; + if(handler[ev.type]) + (handler[ev.type])(&ev); + } + + draw(); + XFlush(xw.dpy); + + if(xev && !(s & xev_activity)) + xev--; + if(blinkset) { + drawtimeout.tv_sec = 0; + drawtimeout.tv_usec = blinktimeout / 2; + tv = &drawtimeout; + } else { + tv = NULL; } } } -- 2.0.0