commit 29688b02fe263635f239dd48dd3715577def8352 from: Stefan Sperling date: Thu Jun 16 11:33:48 2022 UTC fix horizontal scrolling of unicode in tog log view ok jamsek commit - a75b3e2dd76c9392eb52ae19ef339a13f32eb821 commit + 29688b02fe263635f239dd48dd3715577def8352 blob - 8a28476cd4abc2585e93d816ed8368b82925038b blob + a973c4a5aef87ce408322a2aedaa71ee09f7b82d --- tog/tog.c +++ tog/tog.c @@ -1332,6 +1332,51 @@ done: else *wlinep = wline; return err; +} + +/* Skip the leading nscroll columns of a wide character string. */ +const struct got_error * +scroll_wline(wchar_t **wlinep, wchar_t *wline, int nscroll, + int col_tab_align) +{ + int cols = 0; + size_t wlen = wcslen(wline); + int i = 0, j = 0; + + *wlinep = wline; + + while (i < wlen && cols < nscroll) { + int width = wcwidth(wline[i]); + + if (width == 0) { + i++; + continue; + } + + if (width == 1 || width == 2) { + if (cols + width > nscroll) + break; + cols += width; + i++; + } else if (width == -1) { + if (wline[i] == L'\t') { + width = TABSIZE - + ((cols + col_tab_align) % TABSIZE); + } else { + width = 1; + wline[i] = L'.'; + } + if (cols + width > nscroll) + break; + cols += width; + i++; + } else + return got_error_from_errno("wcwidth"); + j++; + } + + *wlinep = &wline[j]; + return NULL; } static const struct got_error* @@ -1426,7 +1471,7 @@ draw_commit(struct tog_view *view, struct got_commit_o char datebuf[12]; /* YYYY-MM-DD + SPACE + NUL */ char *logmsg0 = NULL, *logmsg = NULL; char *author = NULL; - wchar_t *wlogmsg = NULL, *wauthor = NULL; + wchar_t *wlogmsg = NULL, *wauthor = NULL, *scrolled_wline; int author_width, logmsg_width; char *newline, *line = NULL; int col, limit; @@ -1514,11 +1559,12 @@ draw_commit(struct tog_view *view, struct got_commit_o err = format_line(&wlogmsg, &logmsg_width, logmsg, limit, col, 1); if (err) goto done; - if (view->x < logmsg_width - 1) - waddwstr(view->window, wlogmsg + view->x); - else - logmsg_width = 0; - col += MAX(logmsg_width - view->x, 0); + err = scroll_wline(&scrolled_wline, wlogmsg, view->x, col); + if (err) + goto done; + waddwstr(view->window, scrolled_wline); + logmsg_width = wcswidth(scrolled_wline, wcslen(scrolled_wline)); + col += MAX(logmsg_width, 0); while (col < avail) { waddch(view->window, ' '); col++; @@ -1781,13 +1827,13 @@ draw_commits(struct tog_view *view) if (limit <= 1) goto done; - /* Grow author column size if necessary. */ + /* Grow author column size if necessary, and set view->maxx. */ entry = s->first_displayed_entry; ncommits = 0; view->maxx = 0; while (entry) { char *author, *eol, *msg, *msg0; - wchar_t *wauthor; + wchar_t *wauthor, *wmsg; int width; if (ncommits >= limit - 1) break; @@ -1809,10 +1855,14 @@ draw_commits(struct tog_view *view) while (*msg == '\n') ++msg; if ((eol = strchr(msg, '\n'))) - view->maxx = MAX(view->maxx, eol - msg); - else - view->maxx = MAX(view->maxx, strlen(msg)); + *eol = '\0'; + err = format_line(&wmsg, &width, msg, INT_MAX, + date_display_cols + author_cols, 0); + if (err) + goto done; + view->maxx = MAX(view->maxx, width); free(msg0); + free(wmsg); ncommits++; entry = TAILQ_NEXT(entry, entry); }