t* sacc + cursorline and uri preview
       
   URI git clone git://git.codevoid.de/sacc-sdk
   DIR Log
   DIR Files
   DIR Refs
   DIR LICENSE
       ---
   DIR commit 13dd0464fab6950cbeee18b8ae6549d0f48723c7
   DIR parent f5d039f7156956e52161605fa71715a2d1d7c3c8
   URI Author: Hiltjo Posthuma <hiltjo@codemadness.org>
       Date:   Fri,  9 Feb 2018 17:43:53 +0100
       
       Process glyph width for line length when truncating output
       
       Diffstat:
         M common.h                            |       1 +
         M sacc.c                              |      31 +++++++++++++++++++++++++++++++
         M ui_ti.c                             |      20 ++++++++++----------
         M ui_txt.c                            |      13 +++++++------
       
       4 files changed, 49 insertions(+), 16 deletions(-)
       ---
   DIR diff --git a/common.h b/common.h
       t@@ -23,6 +23,7 @@ struct dir {
        };
        
        void die(const char *fmt, ...);
       +size_t mbsprint(const char *s, size_t len);
        const char *typedisplay(char t);
        void uidisplay(Item *item);
        Item *uiselectitem(Item *entry);
   DIR diff --git a/sacc.c b/sacc.c
       t@@ -1,6 +1,7 @@
        /* See LICENSE file for copyright and license details. */
        #include <errno.h>
        #include <fcntl.h>
       +#include <locale.h>
        #include <netdb.h>
        #include <netinet/in.h>
        #include <signal.h>
       t@@ -9,6 +10,7 @@
        #include <stdlib.h>
        #include <string.h>
        #include <unistd.h>
       +#include <wchar.h>
        #include <sys/socket.h>
        #include <sys/stat.h>
        #include <sys/types.h>
       t@@ -37,6 +39,34 @@ die(const char *fmt, ...)
                exit(1);
        }
        
       +/* print `len' columns of characters. */
       +size_t
       +mbsprint(const char *s, size_t len)
       +{
       +        wchar_t wc;
       +        size_t col = 0, i, slen;
       +        int rl, w;
       +
       +        if (!len)
       +                return col;
       +
       +        slen = strlen(s);
       +        for (i = 0; i < slen; i += rl) {
       +                if ((rl = mbtowc(&wc, s + i, slen - i < 4 ? slen - i : 4)) <= 0)
       +                        break;
       +                if ((w = wcwidth(wc)) == -1)
       +                        continue;
       +                if (col + w > len || (col + w == len && s[i + rl])) {
       +                        fputs("\xe2\x80\xa6", stdout);
       +                        col++;
       +                        break;
       +                }
       +                fwrite(s + i, 1, rl, stdout);
       +                col += w;
       +        }
       +        return col;
       +}
       +
        static void *
        xreallocarray(void *m, const size_t n, const size_t s)
        {
       t@@ -779,6 +809,7 @@ setup(void)
                struct sigaction sa;
                int fd;
        
       +        setlocale(LC_CTYPE, "");
                setenv("PAGER", "more", 0);
                atexit(cleanup);
                /* reopen stdin in case we're reading from a pipe */
   DIR diff --git a/ui_ti.c b/ui_ti.c
       t@@ -65,11 +65,10 @@ uiprompt(char *fmt, ...)
                if (vsnprintf(bufout, sizeof(bufout), fmt, ap) >= sizeof(bufout))
                        bufout[sizeof(bufout)-1] = '\0';
                va_end(ap);
       -        printf("%.*s", columns, bufout);
       +        n = mbsprint(bufout, columns);
        
                putp(tparm(exit_standout_mode));
       -
       -        if ((n = strlen(bufout)) < columns)
       +        if (n < columns)
                        printf("%*s", columns - n, " ");
        
                putp(tparm(cursor_address, lines-1, n));
       t@@ -102,7 +101,8 @@ printitem(Item *item)
                if (snprintf(bufout, sizeof(bufout), "%s %s", typedisplay(item->type),
                    item->username) >= sizeof(bufout))
                        bufout[sizeof(bufout)-1] = '\0';
       -        printf("%.*s\r", columns, bufout);
       +        mbsprint(bufout, columns);
       +        putchar('\r');
        }
        
        static Item *
       t@@ -154,9 +154,9 @@ uistatus(char *fmt, ...)
                if (n >= sizeof(bufout))
                        bufout[sizeof(bufout)-1] = '\0';
        
       -        printf("%.*s", columns, bufout);
       +        n = mbsprint(bufout, columns);
                putp(tparm(exit_standout_mode));
       -        if ((n = strlen(bufout)) < columns)
       +        if (n < columns)
                        printf("%*s", columns - n, " ");
        
                putp(tparm(restore_cursor));
       t@@ -185,9 +185,9 @@ displaystatus(Item *item)
                             item->host, item->type, item->selector, item->port)
                    >= sizeof(bufout))
                        bufout[sizeof(bufout)-1] = '\0';
       -        printf("%.*s", columns, bufout);
       +        n = mbsprint(bufout, columns);
                putp(tparm(exit_standout_mode));
       -        if ((n = strlen(bufout)) < columns)
       +        if (n < columns)
                        printf("%*s", columns - n, " ");
        
                putp(tparm(restore_cursor));
       t@@ -225,9 +225,9 @@ displayuri(Item *item)
                if (n >= sizeof(bufout))
                        bufout[sizeof(bufout)-1] = '\0';
        
       -        printf("%.*s", columns, bufout);
       +        n = mbsprint(bufout, columns);
                putp(tparm(exit_standout_mode));
       -        if ((n = strlen(bufout)) < columns)
       +        if (n < columns)
                        printf("%*s", columns - n, " ");
        
                putp(tparm(restore_cursor));
   DIR diff --git a/ui_txt.c b/ui_txt.c
       t@@ -83,7 +83,7 @@ uistatus(char *fmt, ...)
                if (n >= sizeof(bufout))
                        bufout[sizeof(bufout)-1] = '\0';
        
       -        printf("%.*s", columns, bufout);
       +        mbsprint(bufout, columns);
                fflush(stdout);
        
                getchar();
       t@@ -106,7 +106,7 @@ printstatus(Item *item, char c)
                             item->host, item->type, item->selector, c, item->port)
                    >= sizeof(bufout))
                        bufout[sizeof(bufout)-1] = '\0';
       -        printf("%.*s", columns, bufout);
       +        mbsprint(bufout, columns);
        }
        
        char *
       t@@ -122,8 +122,7 @@ uiprompt(char *fmt, ...)
                        bufout[sizeof(bufout)-1] = '\0';
                va_end(ap);
        
       -        printf("%.*s", columns, bufout);
       -
       +        mbsprint(bufout, columns);
                fflush(stdout);
        
                if ((r = getline(&input, &n, stdin)) < 0) {
       t@@ -163,7 +162,8 @@ uidisplay(Item *entry)
                                     items[i].username)
                            >= sizeof(bufout))
                                bufout[sizeof(bufout)-1] = '\0';
       -                printf("%.*s\n", columns, bufout);
       +                mbsprint(bufout, columns);
       +                putchar('\n');
                }
        
                fflush(stdout);
       t@@ -201,7 +201,8 @@ printuri(Item *item, size_t i)
                if (n >= sizeof(bufout))
                        bufout[sizeof(bufout)-1] = '\0';
        
       -        printf("%.*s\n", columns, bufout);
       +        mbsprint(bufout, columns);
       +        putchar('\n');
        }
        
        void