sacc

sacc (saccomys): simple gopher client.
Log | Files | Refs | LICENSE

commit 13dd0464fab6950cbeee18b8ae6549d0f48723c7
parent f5d039f7156956e52161605fa71715a2d1d7c3c8
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:
common.h | 1+
sacc.c | 31+++++++++++++++++++++++++++++++
ui_ti.c | 20++++++++++----------
ui_txt.c | 13+++++++------
4 files changed, 49 insertions(+), 16 deletions(-)

diff --git a/common.h b/common.h @@ -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); diff --git a/sacc.c b/sacc.c @@ -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> @@ -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> @@ -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) { @@ -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 */ diff --git a/ui_ti.c b/ui_ti.c @@ -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)); @@ -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 * @@ -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)); @@ -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)); @@ -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)); diff --git a/ui_txt.c b/ui_txt.c @@ -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(); @@ -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 * @@ -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) { @@ -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); @@ -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