From d155009ded353e840f1f1480bb55fde9230b866c Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Wed, 6 Jul 2022 19:01:15 +0100 Subject: [PATCH] Utility function to do terminal word wrapping. I'm planning to use this to replace some of the manually wrapped lines in console messages. --- misc.h | 2 ++ utils/CMakeLists.txt | 1 + utils/wordwrap.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 utils/wordwrap.c diff --git a/misc.h b/misc.h index bdfa8c2e..f9e59b50 100644 --- a/misc.h +++ b/misc.h @@ -232,6 +232,8 @@ int string_length_for_printf(size_t); /* Make a ptrlen out of a constant byte array. */ #define PTRLEN_FROM_CONST_BYTES(a) make_ptrlen(a, sizeof(a)) +void wordwrap(BinarySink *bs, ptrlen input, size_t maxwid); + /* Wipe sensitive data out of memory that's about to be freed. Simpler * than memset because we don't need the fill char parameter; also * attempts (by fiddly use of volatile) to inhibit the compiler from diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 4f5479a6..34644cbd 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -70,6 +70,7 @@ add_sources_from_current_dir(utils version.c wcwidth.c wildcard.c + wordwrap.c write_c_string_literal.c x11authfile.c x11authnames.c diff --git a/utils/wordwrap.c b/utils/wordwrap.c new file mode 100644 index 00000000..330b6a03 --- /dev/null +++ b/utils/wordwrap.c @@ -0,0 +1,36 @@ +/* + * Function to wrap text to a fixed number of columns. + * + * Currently, assumes the text is in a single-byte character set, + * because it's only used to display host key prompt messages. + * Extending to Unicode and using wcwidth() could be an extension. + */ + +#include "misc.h" + +void wordwrap(BinarySink *bs, ptrlen input, size_t maxwid) +{ + size_t col = 0; + while (true) { + ptrlen word = ptrlen_get_word(&input, " "); + if (!word.len) + break; + + /* At the start of a line, any word is legal, even if it's + * overlong, because we have to display it _somehow_ and + * wrapping to the next line won't make it any better. */ + if (col > 0) { + size_t newcol = col + 1 + word.len; + if (newcol <= maxwid) { + put_byte(bs, ' '); + col++; + } else { + put_byte(bs, '\n'); + col = 0; + } + } + + put_datapl(bs, word); + col += word.len; + } +}