Truncate output to the terminal size - sacc - sacc(omys), simple console gopher client
git clone git://bitreich.org/sacc/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/sacc/
Log
Files
Refs
Tags
LICENSE
---
commit 2e31e44ffa614c5202edfe2abcc05a7880902640
parent d90036de3c72730ae2797844b36eb5ae9fd3843f
Author: Quentin Rameau 
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:
  M ui_ti.c                             |      71 +++++++++++++++++++++----------
  M ui_txt.c                            |      58 +++++++++++++++++++++++--------

2 files changed, 92 insertions(+), 37 deletions(-)
---
diff --git a/ui_ti.c b/ui_ti.c
@@ -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__)
@@ -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));
 
@@ -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);
@@ -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 *
@@ -127,7 +135,7 @@ void
 uistatus(char *fmt, ...)
 {
         va_list ap;
-        int n = 0;
+        size_t n;
 
         putp(tparm(save_cursor));
 
@@ -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);
@@ -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));
 
@@ -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);
@@ -178,7 +197,7 @@ static void
 displayuri(Item *item)
 {
         char *fmt;
-        int n;
+        size_t n;
 
         if (item->type == 0 || item->type == 'i')
                 return;
@@ -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);
diff --git a/ui_txt.c b/ui_txt.c
@@ -10,6 +10,7 @@
 
 #include "common.h"
 
+static char bufout[256];
 int lines, columns;
 
 static void
@@ -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();
@@ -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 *
@@ -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) {
@@ -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);
@@ -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