# st

Unnamed repository; edit this file 'description' to name the repository.

| Log | Files | Refs | README | LICENSE

    commit 8ca60ffb089547db4ba2c1a60663ecadf659f53a
    parent 96385952322575090822ef20329b690a55611cb1
    Author: c0dev0id <sh+github@codevoid.de>
    Date:   Sun,  1 Aug 2021 12:33:38 +0200

    sdk-appsync-tmux

    Diffstat:
    Mconfig.def.h | 6++++++
    Mconfig.h | 13+++++++++----
    Mst.c | 48++++++++++++++++++++++++++++++++++++++++++++++--
    Mst.info | 1+
    Mx.c | 22+++++++++++++++++++---

    5 files changed, 81 insertions(+), 9 deletions(-)
    diff --git a/config.def.h b/config.def.h
    @@ -63,6 +63,12 @@ static double minlatency = 8;
     static double maxlatency = 33;

     /*
    + * Synchronized-Update timeout in ms
    + * https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec
    + */
    +static uint su_timeout = 200;
    +
    +/*
      * blinking timeout (set to 0 to disable blinking) for the terminal blinking
      * attribute.
      */
    diff --git a/config.h b/config.h
    @@ -8,8 +8,7 @@
     static char *font = "-misc-termsynu-medium-r-normal--14-101-100-100-c-70-iso10646-1";
     /* Spare fonts */
     static char *font2[] = {
    -/*	"Inconsolata for Powerline:pixelsize=12:antialias=true:autohint=true", */
    -/*	"Hack Nerd Font Mono:pixelsize=11:antialias=true:autohint=true", */
    +	"Noto Emoji"
     };

     static int borderpx = 2;
    @@ -62,6 +61,12 @@ static double minlatency = 8;
     static double maxlatency = 33;

     /*
    + * Synchronized-Update timeout in ms
    + * https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec
    + */
    +static uint su_timeout = 200;
    +
    +/*
      * blinking timeout (set to 0 to disable blinking) for the terminal blinking
      * attribute.
      */
    @@ -218,8 +223,8 @@ static Shortcut shortcuts[] = {
     	{ TERMMOD,              XK_Num_Lock,    numlock,        {.i =  0} },
     	{ ShiftMask,            XK_Page_Up,     kscrollup,      {.i = -1} },
     	{ ShiftMask,            XK_Page_Down,   kscrolldown,    {.i = -1} },
    -	{ ShiftMask,            XK_l,           copyurl,        {.i =  0} },
    -	{ ShiftMask,            XK_o,           opencopied,     {.v = "luakit"} },
    +	{ ControlMask,          XK_i,           copyurl,        {.i =  0} },
    +	{ ControlMask,          XK_o,           opencopied,     {.v = "luakit"} }
     };

     /*
    diff --git a/st.c b/st.c
    @@ -243,6 +243,33 @@ static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
     static const Rune utfmin[UTF_SIZ + 1] = {       0,    0,  0x80,  0x800,  0x10000};
     static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};

    +#include <time.h>
    +static int su = 0;
    +struct timespec sutv;
    +
    +static void
    +tsync_begin()
    +{
    +	clock_gettime(CLOCK_MONOTONIC, &sutv);
    +	su = 1;
    +}
    +
    +static void
    +tsync_end()
    +{
    +	su = 0;
    +}
    +
    +int
    +tinsync(uint timeout)
    +{
    +	struct timespec now;
    +	if (su && !clock_gettime(CLOCK_MONOTONIC, &now)
    +	       && TIMEDIFF(now, sutv) >= timeout)
    +		su = 0;
    +	return su;
    +}
    +
     ssize_t
     xwrite(int fd, const char *s, size_t len)
     {
    @@ -833,6 +860,9 @@ ttynew(const char *line, char *cmd, const char *out, char **args)
     	return cmdfd;
     }

    +static int twrite_aborted = 0;
    +int ttyread_pending() { return twrite_aborted; }
    +
     size_t
     ttyread(void)
     {
    @@ -841,7 +871,7 @@ ttyread(void)
     	int ret, written;

     	/* append read bytes to unprocessed bytes */
    -	ret = read(cmdfd, buf+buflen, LEN(buf)-buflen);
    +	ret = twrite_aborted ? 1 : read(cmdfd, buf+buflen, LEN(buf)-buflen);

     	switch (ret) {
     	case 0:
    @@ -849,7 +879,7 @@ ttyread(void)
     	case -1:
     		die("couldn't read from shell: %s\n", strerror(errno));
     	default:
    -		buflen += ret;
    +		buflen += twrite_aborted ? 0 : ret;
     		written = twrite(buf, buflen, 0);
     		buflen -= written;
     		/* keep any incomplete UTF-8 byte sequence for the next call */
    @@ -1012,6 +1042,7 @@ tsetdirtattr(int attr)
     void
     tfulldirt(void)
     {
    +	tsync_end();
     	tsetdirt(0, term.row-1);
     }

    @@ -2020,6 +2051,12 @@ strhandle(void)
     		xsettitle(strescseq.args[0]);
     		return;
     	case 'P': /* DCS -- Device Control String */
    +		/* https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec */
    +		if (strstr(strescseq.buf, "=1s") == strescseq.buf)
    +			tsync_begin();  /* BSU */
    +		else if (strstr(strescseq.buf, "=2s") == strescseq.buf)
    +			tsync_end();  /* ESU */
    +		return;
     	case '_': /* APC -- Application Program Command */
     	case '^': /* PM -- Privacy Message */
     		return;
    @@ -2561,6 +2598,9 @@ twrite(const char *buf, int buflen, int show_ctrl)
     	Rune u;
     	int n;

    +	int su0 = su;
    +	twrite_aborted = 0;
    +
     	for (n = 0; n < buflen; n += charsize) {
     		if (IS_SET(MODE_UTF8)) {
     			/* process a complete utf8 char */
    @@ -2571,6 +2611,10 @@ twrite(const char *buf, int buflen, int show_ctrl)
     			u = buf[n] & 0xFF;
     			charsize = 1;
     		}
    +		if (su0 && !su) {
    +			twrite_aborted = 1;
    +			break;  // ESU - allow rendering before a new BSU
    +		}
     		if (show_ctrl && ISCONTROL(u)) {
     			if (u & 0x80) {
     				u &= 0x7f;
    diff --git a/st.info b/st.info
    @@ -192,6 +192,7 @@ st-mono| simpleterm monocolor,
     	Ms=\E]52;%p1%s;%p2%s\007,
     	Se=\E[2 q,
     	Ss=\E[%p1%d q,
    +	Sync=\EP=%p1%ds\E\\,

     st| simpleterm,
     	use=st-mono,
    diff --git a/x.c b/x.c
    @@ -2090,6 +2090,9 @@ resize(XEvent *e)
     	cresize(e->xconfigure.width, e->xconfigure.height);
     }

    +int tinsync(uint);
    +int ttyread_pending();
    +
     void
     run(void)
     {
    @@ -2124,7 +2127,7 @@ run(void)
     		FD_SET(ttyfd, &rfd);
     		FD_SET(xfd, &rfd);

    -		if (XPending(xw.dpy))
    +		if (XPending(xw.dpy) || ttyread_pending())
     			timeout = 0;  /* existing events might not set xfd */

     		seltv.tv_sec = timeout / 1E3;
    @@ -2138,7 +2141,8 @@ run(void)
     		}
     		clock_gettime(CLOCK_MONOTONIC, &now);

    -		if (FD_ISSET(ttyfd, &rfd))
    +		int ttyin = FD_ISSET(ttyfd, &rfd) || ttyread_pending();
    +		if (ttyin)
     			ttyread();

     		xev = 0;
    @@ -2162,7 +2166,7 @@ run(void)
     		 * maximum latency intervals during `cat huge.txt`, and perfect
     		 * sync with periodic updates from animations/key-repeats/etc.
     		 */
    -		if (FD_ISSET(ttyfd, &rfd) || xev) {
    +		if (ttyin || xev) {
     			if (!drawing) {
     				trigger = now;
     				drawing = 1;
    @@ -2173,6 +2177,18 @@ run(void)
     				continue;  /* we have time, try to find idle */
     		}

    +		if (tinsync(su_timeout)) {
    +			/*
    +			 * on synchronized-update draw-suspension: don't reset
    +			 * drawing so that we draw ASAP once we can (just after
    +			 * ESU). it won't be too soon because we already can
    +			 * draw now but we skip. we set timeout > 0 to draw on
    +			 * SU-timeout even without new content.
    +			 */
    +			timeout = minlatency;
    +			continue;
    +		}
    +
     		/* idle detected or maxlatency exhausted -> draw */
     		timeout = -1;
     		if (blinktimeout && tattrset(ATTR_BLINK)) {