tTruncate output to the terminal size - sacc - sacc (saccomys): simple gopher client.
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit 2e31e44ffa614c5202edfe2abcc05a7880902640
 (DIR) parent d90036de3c72730ae2797844b36eb5ae9fd3843f
 (HTM) Author: Quentin Rameau <quinq@fifth.space>
       Date:   Fri, 29 Dec 2017 10:52:39 +0100
       
       Truncate output to the terminal size
       
       Thanks to Hiltjo for his input, making this patch a little better.
       
       Diffstat:
         ui_ti.c                             |      71 +++++++++++++++++++++----------
         ui_txt.c                            |      58 +++++++++++++++++++++++--------
       
       2 files changed, 92 insertions(+), 37 deletions(-)
       ---
 (DIR) diff --git a/ui_ti.c b/ui_ti.c
       t@@ -13,6 +13,7 @@
        #define C(c) #c
        #define S(c) C(c)
        
       +static char bufout[256];
        static struct termios tsave;
        static struct termios tsacc;
        #if defined(__NetBSD__)
       t@@ -50,8 +51,8 @@ uiprompt(char *fmt, ...)
        {
                va_list ap;
                char *input = NULL;
       -        size_t n = 0;
       -        ssize_t r = 0;
       +        size_t n;
       +        ssize_t r;
        
                putp(tparm(save_cursor));
        
       t@@ -60,19 +61,23 @@ uiprompt(char *fmt, ...)
                putp(tparm(enter_standout_mode));
        
                va_start(ap, fmt);
       -        r += vprintf(fmt, ap);
       +        if (vsnprintf(bufout, sizeof(bufout), fmt, ap) >= sizeof(bufout))
       +                bufout[sizeof(bufout)-1] = '\0';
                va_end(ap);
       +        printf("%.*s", columns, bufout);
        
                putp(tparm(exit_standout_mode));
        
       -        printf("%*s", columns-r, " ");
       +        if ((n = strlen(bufout)) < columns)
       +                printf("%*s", columns - n, " ");
        
       -        putp(tparm(cursor_address, lines-1, r));
       +        putp(tparm(cursor_address, lines-1, n));
        
                tsacc.c_lflag |= (ECHO|ICANON);
                tcsetattr(0, TCSANOW, &tsacc);
                fflush(stdout);
        
       +        n = 0;
                r = getline(&input, &n, stdin);
        
                tsacc.c_lflag &= ~(ECHO|ICANON);
       t@@ -93,7 +98,10 @@ uiprompt(char *fmt, ...)
        static void
        printitem(Item *item)
        {
       -        printf("%s %s\r", typedisplay(item->type), item->username);
       +        if (snprintf(bufout, sizeof(bufout), "%s %s", typedisplay(item->type),
       +            item->username) >= sizeof(bufout))
       +                bufout[sizeof(bufout)-1] = '\0';
       +        printf("%.*s\r", columns, bufout);
        }
        
        static Item *
       t@@ -127,7 +135,7 @@ void
        uistatus(char *fmt, ...)
        {
                va_list ap;
       -        int n = 0;
       +        size_t n;
        
                putp(tparm(save_cursor));
        
       t@@ -135,12 +143,20 @@ uistatus(char *fmt, ...)
                putp(tparm(enter_standout_mode));
        
                va_start(ap, fmt);
       -        n += vprintf(fmt, ap);
       +        n = vsnprintf(bufout + n, sizeof(bufout) - n, fmt, ap);
                va_end(ap);
        
       -        n += printf(" [Press a key to continue ☃]");
       +        if (n < sizeof(bufout)-1) {
       +                n += snprintf(bufout + n, sizeof(bufout) - n,
       +                              " [Press a key to continue ☃]");
       +        }
       +        if (n >= sizeof(bufout))
       +                bufout[sizeof(bufout)-1] = '\0';
       +
       +        printf("%.*s", columns, bufout);
                putp(tparm(exit_standout_mode));
       -        printf("%*s", columns-n, " ");
       +        if ((n = strlen(bufout)) < columns)
       +                printf("%*s", columns - n, " ");
        
                putp(tparm(restore_cursor));
                fflush(stdout);
       t@@ -153,9 +169,8 @@ displaystatus(Item *item)
        {
                Dir *dir = item->dat;
                char *fmt;
       -        size_t nitems = dir ? dir->nitems : 0;
       +        size_t n, nitems = dir ? dir->nitems : 0;
                unsigned long long printoff = dir ? dir->printoff : 0;
       -        int n;
        
                putp(tparm(save_cursor));
        
       t@@ -163,12 +178,16 @@ displaystatus(Item *item)
                putp(tparm(enter_standout_mode));
                fmt = (strcmp(item->port, "70") && strcmp(item->port, "gopher")) ?
                      "%1$3lld%%| %2$s:%5$s/%3$c%4$s" : "%3lld%%| %s/%c%s";
       -        n = printf(fmt,
       -                   (printoff + lines-1 >= nitems) ? 100 :
       -                   (printoff + lines-1) * 100 / nitems,
       -                   item->host, item->type, item->selector, item->port);
       +        if (snprintf(bufout, sizeof(bufout), fmt,
       +                     (printoff + lines-1 >= nitems) ? 100 :
       +                     (printoff + lines-1) * 100 / nitems,
       +                     item->host, item->type, item->selector, item->port)
       +            >= sizeof(bufout))
       +                bufout[sizeof(bufout)-1] = '\0';
       +        printf("%.*s", columns, bufout);
                putp(tparm(exit_standout_mode));
       -        printf("%*s", columns-n, " ");
       +        if ((n = strlen(bufout)) < columns)
       +                printf("%*s", columns - n, " ");
        
                putp(tparm(restore_cursor));
                fflush(stdout);
       t@@ -178,7 +197,7 @@ static void
        displayuri(Item *item)
        {
                char *fmt;
       -        int n;
       +        size_t n;
        
                if (item->type == 0 || item->type == 'i')
                        return;
       t@@ -189,18 +208,26 @@ displayuri(Item *item)
                putp(tparm(enter_standout_mode));
                switch (item->type) {
                case 'h':
       -                n = printf("%s: %s", item->username, item->selector);
       +                n = snprintf(bufout, sizeof(bufout), "%s: %s",
       +                             item->username, item->selector);
                        break;
                default:
                        fmt = strcmp(item->port, "70") ?
                              "%1$s: gopher://%2$s:%5$s/%3$c%4$s" :
                              "%s: gopher://%s/%c%s";
       -                n = printf(fmt, item->username,
       -                           item->host, item->type, item->selector, item->port);
       +                n = snprintf(bufout, sizeof(bufout), fmt,
       +                             item->username, item->host, item->type,
       +                             item->selector, item->port);
                        break;
                }
       +
       +        if (n >= sizeof(bufout))
       +                bufout[sizeof(bufout)-1] = '\0';
       +
       +        printf("%.*s", columns, bufout);
                putp(tparm(exit_standout_mode));
       -        printf("%*s", columns-n, " ");
       +        if ((n = strlen(bufout)) < columns)
       +                printf("%*s", columns - n, " ");
        
                putp(tparm(restore_cursor));
                fflush(stdout);
 (DIR) diff --git a/ui_txt.c b/ui_txt.c
       t@@ -10,6 +10,7 @@
        
        #include "common.h"
        
       +static char bufout[256];
        int lines, columns;
        
        static void
       t@@ -67,12 +68,20 @@ void
        uistatus(char *fmt, ...)
        {
                va_list arg;
       +        int n;
        
                va_start(arg, fmt);
       -        vprintf(fmt, arg);
       +        n = vsnprintf(bufout, sizeof(bufout), fmt, arg);
                va_end(arg);
        
       -        printf(" [Press Enter to continue ☃]");
       +        if (n < sizeof(bufout)-1) {
       +                n += snprintf(bufout + n, sizeof(bufout) - n,
       +                              " [Press Enter to continue ☃]");
       +        }
       +        if (n >= sizeof(bufout))
       +                bufout[sizeof(bufout)-1] = '\0';
       +
       +        printf("%.*s", columns, bufout);
                fflush(stdout);
        
                getchar();
       t@@ -89,9 +98,13 @@ printstatus(Item *item, char c)
                fmt = (strcmp(item->port, "70") && strcmp(item->port, "gopher")) ?
                      "%1$3lld%%%*2$3$c %4$s:%8$s/%5$c%6$s [%7$c]: " :
                      "%3lld%%%*c %s/%c%s [%c]: ";
       -        printf(fmt, (printoff + lines-1 >= nitems) ? 100 :
       -               (printoff + lines) * 100 / nitems, ndigits(nitems)+2, '|',
       -               item->host, item->type, item->selector, c, item->port);
       +        if (snprintf(bufout, sizeof(bufout), fmt,
       +                     (printoff + lines-1 >= nitems) ? 100 :
       +                     (printoff + lines) * 100 / nitems, ndigits(nitems)+2, '|',
       +                     item->host, item->type, item->selector, c, item->port)
       +            >= sizeof(bufout))
       +                bufout[sizeof(bufout)-1] = '\0';
       +        printf("%.*s", columns, bufout);
        }
        
        char *
       t@@ -103,9 +116,12 @@ uiprompt(char *fmt, ...)
                ssize_t r;
        
                va_start(ap, fmt);
       -        vprintf(fmt, ap);
       +        if (vsnprintf(bufout, sizeof(bufout), fmt, ap) >= sizeof(bufout))
       +                bufout[sizeof(bufout)-1] = '\0';
                va_end(ap);
        
       +        printf("%.*s", columns, bufout);
       +
                fflush(stdout);
        
                if ((r = getline(&input, &n, stdin)) < 0) {
       t@@ -138,8 +154,12 @@ uidisplay(Item *entry)
                nd = ndigits(nitems);
        
                for (i = dir->printoff; i < nitems && i < nlines; ++i) {
       -                printf("%*zu %s %s\n",
       -                       nd, i+1, typedisplay(items[i].type), items[i].username);
       +                if (snprintf(bufout, sizeof(bufout), "%*zu %s %s",
       +                             nd, i+1, typedisplay(items[i].type),
       +                             items[i].username)
       +                    >= sizeof(bufout))
       +                        bufout[sizeof(bufout)-1] = '\0';
       +                printf("%.*s\n", columns, bufout);
                }
        
                fflush(stdout);
       t@@ -149,27 +169,35 @@ void
        printuri(Item *item, size_t i)
        {
                char *fmt;
       +        int n;
        
                if (!item)
                        return;
        
                switch (item->type) {
                case 0:
       -                break;
       +                return;
                case 'i':
       -                printf("%zu: %s\n", i, item->username);
       +                n = snprintf(bufout, sizeof(bufout), "%zu: %s",
       +                             i, item->username);
                        break;
                case 'h':
       -                printf("%zu: %s: %s\n", i, item->username, item->selector);
       +                n = snprintf(bufout, sizeof(bufout), "%zu: %s: %s",
       +                         i, item->username, item->selector);
                        break;
                default:
                        fmt = strcmp(item->port, "70") ?
       -                      "%1$zu: %2$s: gopher://%3$s:%6$s/%4$c%5$s\n" :
       -                      "%zu: %s: gopher://%s/%c%s\n";
       -                printf(fmt, i, item->username,
       -                       item->host, item->type, item->selector, item->port);
       +                      "%1$zu: %2$s: gopher://%3$s:%6$s/%4$c%5$s" :
       +                      "%zu: %s: gopher://%s/%c%s";
       +                n = snprintf(bufout, sizeof(bufout), fmt, i, item->username,
       +                             item->host, item->type, item->selector, item->port);
                        break;
                }
       +        
       +        if (n >= sizeof(bufout))
       +                bufout[sizeof(bufout)-1] = '\0';
       +
       +        printf("%.*s\n", columns, bufout);
        }
        
        void