commit 61e69b96fdf101a2381367490c2c5b82800a5021 from: Stefan Sperling date: Sun May 20 17:08:05 2018 UTC better trimming of lines to the right length in tog diff commit - d56caa55a3f3b7d8102515dbdbb6490ee850aab4 commit + 61e69b96fdf101a2381367490c2c5b82800a5021 blob - 4fd5ba17802dd70e7c1323e8e2676299a6f2573b blob + cb1a8b9ad8c0cdfaa8e2935293dc642426e29740 --- tog/Makefile +++ tog/Makefile @@ -6,7 +6,7 @@ SRCS= tog.c delta.c diff.c diffreg.c error.c fileinde sha1.c worktree.c zbuf.c CPPFLAGS = -I${.CURDIR}/../include -I${.CURDIR}/../lib -LDADD = -lpanel -lcurses -lutil -lz +LDADD = -lpanel -lncursesw -lutil -lz DPADD = ${LIBZ} ${LIBUTIL} .if defined(PROFILE) CC = gcc blob - 3e8076c50f4fc3c2afaed784ffa805d6b56b043b blob + 651a1622c2286d54a2484467dde5dbd4c08e4678 --- tog/tog.c +++ tog/tog.c @@ -17,7 +17,9 @@ #include #include +#define _XOPEN_SOURCE_EXTENDED #include +#undef _XOPEN_SOURCE_EXTENDED #include #include #include @@ -28,6 +30,7 @@ #include #include #include +#include #include "got_error.h" #include "got_object.h" @@ -773,13 +776,70 @@ parse_next_line(FILE *f, size_t *len) return line; } +/* Format a line for display, ensuring that it won't overflow COLS columns. */ static const struct got_error * +format_line(wchar_t **wlinep, char *line) +{ + const struct got_error *err = NULL; + int cols = 0; + wchar_t *wline = NULL; + size_t wlen; + int i; + + *wlinep = NULL; + + wlen = mbstowcs(NULL, line, 0); + if (wlen == (size_t)-1) + return got_error_from_errno(); + + wline = calloc(wlen + 1, sizeof(wchar_t)); + if (wline == NULL) + return got_error_from_errno(); + + if (mbstowcs(wline, line, wlen) != wlen) { + err = got_error_from_errno(); + goto done; + } + + i = 0; + while (i < wlen && cols <= COLS) { + int width = wcwidth(wline[i]); + switch (width) { + case 0: + break; + case 1: + case 2: + cols += width; + break; + case -1: + if (wline[i] == L'\t') + cols += TABSIZE; + break; + default: + err = got_error_from_errno(); + goto done; + } + if (cols <= COLS) + i++; + } + wline[i] = L'\0'; +done: + if (err) + free(wline); + else + *wlinep = wline; + return err; +} + +static const struct got_error * draw_diff(FILE *f, int *first_displayed_line, int *last_displayed_line, int *eof, int max_lines) { + const struct got_error *err; int nlines = 0, nprinted = 0; char *line; size_t len; + wchar_t *wline; rewind(f); werase(tog_diff_view.window); @@ -796,9 +856,12 @@ draw_diff(FILE *f, int *first_displayed_line, int *las continue; } - if (len > COLS - 1) - line[COLS - 1] = '\0'; - waddstr(tog_diff_view.window, line); + err = format_line(&wline, line); + if (err) { + free(line); + return err; + } + waddwstr(tog_diff_view.window, wline); waddch(tog_diff_view.window, '\n'); if (++nprinted == 1) *first_displayed_line = nlines;