diff options
author | C. McEnroe | 2020-09-02 01:55:44 -0400 |
---|---|---|
committer | C. McEnroe | 2020-09-02 01:57:51 -0400 |
commit | a84c9cdda7f6a4115d22983124bb70327ffbe785 (patch) | |
tree | 94b46d0ac8137c0e41f110aa712268531645d8a8 | |
parent | 149cafc5abe7f8a7709d8d100a5e6c547eab0b52 (diff) |
Fix line wrapping in various ways
Never split a codepoint, don't set wrapping point unless we're not already wrapping, wrap on any unicode whitespace, only clear rest of line if still on the same line...
-rw-r--r-- | buffer.c | 42 | ||||
-rw-r--r-- | ui.c | 4 |
2 files changed, 27 insertions, 19 deletions
diff --git a/buffer.c b/buffer.c index 8c6d6b3..9fee0b0 100644 --- a/buffer.c +++ b/buffer.c @@ -26,6 +26,7 @@ */ #include <err.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -111,18 +112,17 @@ static int flow(struct Lines *hard, int cols, const struct Line *soft) { struct Style style = StyleDefault; for (char *str = line->str; *str;) { size_t len = styleParse(&style, (const char **)&str); - if (*str == '\t' && !align) { - align = width + 1; - *str = ' '; - } - if (isspace(*str) || *str == '-') { - wrap = str; - } + if (!len) continue; + + bool tab = (*str == '\t' && !align); + if (tab) *str = ' '; - wchar_t wc; + wchar_t wc = L'\0'; int n = mbtowc(&wc, str, len); - if (n <= 0) continue; - if (wc == ZWS || wc == ZWNJ) { + if (n < 0) { + n = 1; + width++; + } else if (wc == ZWS || wc == ZWNJ) { // XXX: ncurses likes to render these as spaces when they should be // zero-width, so just remove them entirely. memmove(str, &str[n], strlen(&str[n]) + 1); @@ -134,32 +134,38 @@ static int flow(struct Lines *hard, int cols, const struct Line *soft) { width += wcwidth(wc); } - if (width < cols) { + if (width <= cols) { + if (tab && width < cols) align = width; + if (iswspace(wc)) wrap = str; + if (*str == '-') wrap = &str[1]; str += n; continue; } + if (!wrap) wrap = str; + n = mbtowc(&wc, wrap, strlen(wrap)); + if (n < 0) { + n = 1; + } else if (!iswspace(wc)) { + n = 0; + } flowed++; line = linesNext(hard); line->heat = soft->heat; line->time = soft->time; - size_t cap = StyleCap + align + strlen(&wrap[1]) + 1; + size_t cap = StyleCap + align + strlen(&wrap[n]) + 1; line->str = malloc(cap); if (!line->str) err(EX_OSERR, "malloc"); struct Cat cat = { line->str, cap, 0 }; styleCat(&cat, style); str = &line->str[cat.len]; - catf(&cat, "%*s%n%s", align, "", &width, &wrap[1]); + catf(&cat, "%*s%n%s", align, "", &width, &wrap[n]); str += width; - if (isspace(*wrap)) { - wrap[0] = '\0'; - } else { - wrap[1] = '\0'; - } + *wrap = '\0'; wrap = NULL; } diff --git a/ui.c b/ui.c index 3ecea9f..89dd4da 100644 --- a/ui.c +++ b/ui.c @@ -457,7 +457,9 @@ static void windowUpdate(void) { if (line->heat < Cold && window->ignore) continue; wmove(main, y, 0); styleAdd(main, line->str); - wclrtoeol(main); + int ny, nx; + getyx(main, ny, nx); + if (ny == y) wclrtoeol(main); if (!y--) break; } |