From: Omar Polo Subject: Re: tog: fix horizontal scrolling of unicode in the diff view To: Stefan Sperling Cc: gameoftrees@openbsd.org Date: Thu, 16 Jun 2022 16:49:03 +0200 Stefan Sperling wrote: > Fix horizontal scrolling of unicode in the diff view. This makes > the diff in my ja.git test repo scroll properly. > > Turns out we need another output parameter in format_line() for > this case. draw_file() needs to know the width of the unscrolled > version of each line in order to set view->maxx correctly. > > ok? yep, it reads fine. > diff 3a8eb03e7089a4869bb33afa6dc90d2b9d4c2c70 7c4eb5ef2ddd2fc6b8127a6b4746081efcb1411c > blob - 285021accb225e5cc858097d09e1a68d4b32e1ca > blob + 4b3a42b896e6f4177b004831b046fa812308b489 > --- tog/tog.c > +++ tog/tog.c > @@ -1262,7 +1262,7 @@ expand_tab(char **ptr, const char *src) > * Returns the index to the first character of the scrolled string. > */ > static const struct got_error * > -scroll_wline(int *scrollx , wchar_t *wline, int nscroll, > +scroll_wline(int *scrollx, int *widthp, wchar_t *wline, int nscroll, > int col_tab_align) > { > int cols = 0; > @@ -1301,27 +1301,34 @@ scroll_wline(int *scrollx , wchar_t *wline, int nscrol > } > > *scrollx = i; > + *widthp = cols; > return NULL; > } > > /* > * Format a line for display, ensuring that it won't overflow a width limit. > - * With scrolling, the width returned refers to the scrolled version of the > - * line, which starts at (*wlinep)[*scrollxp]. The caller must free *wlinep. > + * With scrolling, the width returned in *scrolled_widthp refers to the > + * scrolled version of the line, which starts at (*wlinep)[*scrollxp]. > + * The caller must free *wlinep. > */ > static const struct got_error * > -format_line(wchar_t **wlinep, int *widthp, int *scrollxp, > +format_line(wchar_t **wlinep, int *widthp, int *scrollxp, int *scrolled_widthp, > const char *line, int nscroll, int wlimit, int col_tab_align, int expand) > { > const struct got_error *err = NULL; > - int cols = 0; > + int cols = 0, skipped_cols = 0; > wchar_t *wline = NULL; > char *exstr = NULL; > size_t wlen; > int i, scrollx = 0; > > *wlinep = NULL; > - *widthp = 0; > + if (widthp) > + *widthp = 0; > + if (scrollxp) > + *scrollxp = 0; > + if (scrolled_widthp) > + *scrolled_widthp = 0; > > if (expand) { > err = expand_tab(&exstr, line); > @@ -1334,7 +1341,8 @@ format_line(wchar_t **wlinep, int *widthp, int *scroll > if (err) > return err; > > - err = scroll_wline(&scrollx, wline, nscroll, col_tab_align); > + err = scroll_wline(&scrollx, &skipped_cols, wline, nscroll, > + col_tab_align); > if (err) > goto done; > > @@ -1380,9 +1388,11 @@ format_line(wchar_t **wlinep, int *widthp, int *scroll > } > wline[i] = L'\0'; > if (widthp) > - *widthp = cols; > + *widthp = skipped_cols + cols; > if (scrollxp) > *scrollxp = scrollx; > + if (scrolled_widthp) > + *scrolled_widthp = cols; > done: > if (err) > free(wline); > @@ -1469,7 +1479,7 @@ format_author(wchar_t **wauthor, int *author_width, ch > if (smallerthan && smallerthan[1] != '\0') > author = smallerthan + 1; > author[strcspn(author, "@>")] = '\0'; > - return format_line(wauthor, author_width, NULL, author, 0, limit, > + return format_line(wauthor, author_width, NULL, NULL, author, 0, limit, > col_tab_align, 0); > } > > @@ -1568,8 +1578,8 @@ draw_commit(struct tog_view *view, struct got_commit_o > if (newline) > *newline = '\0'; > limit = avail - col; > - err = format_line(&wlogmsg, &logmsg_width, &scrollx, logmsg, view->x, > - limit, col, 1); > + err = format_line(&wlogmsg, NULL, &scrollx, &logmsg_width, > + logmsg, view->x, limit, col, 1); > if (err) > goto done; > waddwstr(view->window, &wlogmsg[scrollx]); > @@ -1810,7 +1820,8 @@ draw_commits(struct tog_view *view) > header = NULL; > goto done; > } > - err = format_line(&wline, &width, NULL, header, 0, view->ncols, 0, 0); > + err = format_line(&wline, &width, NULL, NULL, header, 0, view->ncols, > + 0, 0); > if (err) > goto done; > > @@ -1865,7 +1876,7 @@ draw_commits(struct tog_view *view) > ++msg; > if ((eol = strchr(msg, '\n'))) > *eol = '\0'; > - err = format_line(&wmsg, &width, NULL, msg, 0, INT_MAX, > + err = format_line(&wmsg, &width, NULL, NULL, msg, 0, INT_MAX, > date_display_cols + author_cols, 0); > if (err) > goto done; > @@ -3126,7 +3137,7 @@ add_matched_line(int *wtotal, const char *line, int wl > rms = regmatch->rm_so; > rme = regmatch->rm_eo; > > - err = format_line(&wline, &width, NULL, line, 0, wlimit + skip, > + err = format_line(&wline, &width, NULL, NULL, line, 0, wlimit + skip, > col_tab_align, 1); > if (err) > return err; > @@ -3196,8 +3207,8 @@ draw_file(struct tog_view *view, const char *header) > s->first_displayed_line - 1 + s->selected_line, nlines, > header) == -1) > return got_error_from_errno("asprintf"); > - err = format_line(&wline, &width, NULL, line, 0, view->ncols, > - 0, 0); > + err = format_line(&wline, &width, NULL, NULL, line, 0, > + view->ncols, 0, 0); > free(line); > if (err) > return err; > @@ -3231,8 +3242,6 @@ draw_file(struct tog_view *view, const char *header) > return got_ferror(s->f, GOT_ERR_IO); > } > > - view->maxx = MAX(view->maxx, linelen); > - > tc = match_color(&s->colors, line); > if (tc) > wattr_on(view->window, > @@ -3246,23 +3255,25 @@ draw_file(struct tog_view *view, const char *header) > return err; > } > } else { > - err = format_line(&wline, &width, NULL, line, 0, > - view->x + view->ncols, 0, view->x ? 1 : 0); > + int skip, fullwidth; > + err = format_line(&wline, &fullwidth, &skip, &width, > + line, view->x, view->ncols, 0, view->x ? 1 : 0); > if (err) { > free(line); > return err; > } > - if (view->x < width) > - waddwstr(view->window, wline + view->x); > + view->maxx = MAX(view->maxx, fullwidth); > + waddwstr(view->window, &wline[skip]); > free(wline); > wline = NULL; > } > if (tc) > wattr_off(view->window, > COLOR_PAIR(tc->colorpair), NULL); > - if (width - view->x <= view->ncols - 1) > + if (width <= view->ncols - 1) > waddch(view->window, '\n'); > nprinted++; > + > } > free(line); > if (nprinted >= 1) > @@ -3279,7 +3290,7 @@ draw_file(struct tog_view *view, const char *header) > nprinted++; > } > > - err = format_line(&wline, &width, NULL, TOG_EOF_STRING, 0, > + err = format_line(&wline, &width, NULL, NULL, TOG_EOF_STRING, 0, > view->ncols, 0, 0); > if (err) { > return err; > @@ -4279,7 +4290,8 @@ draw_blame(struct tog_view *view) > return err; > } > > - err = format_line(&wline, &width, NULL, line, 0, view->ncols, 0, 0); > + err = format_line(&wline, &width, NULL, NULL, line, 0, view->ncols, > + 0, 0); > free(line); > line = NULL; > if (err) > @@ -4308,7 +4320,8 @@ draw_blame(struct tog_view *view) > return got_error_from_errno("asprintf"); > } > free(id_str); > - err = format_line(&wline, &width, NULL, line, 0, view->ncols, 0, 0); > + err = format_line(&wline, &width, NULL, NULL, line, 0, view->ncols, > + 0, 0); > free(line); > line = NULL; > if (err) > @@ -4395,7 +4408,7 @@ draw_blame(struct tog_view *view) > } > width += 9; > } else { > - err = format_line(&wline, &width, NULL, line, 0, > + err = format_line(&wline, &width, NULL, NULL, line, 0, > view->x + view->ncols - 9, 9, 1); > if (err) { > free(line); > @@ -5273,8 +5286,8 @@ draw_tree_entries(struct tog_view *view, const char *p > if (limit == 0) > return NULL; > > - err = format_line(&wline, &width, NULL, s->tree_label, 0, view->ncols, > - 0, 0); > + err = format_line(&wline, &width, NULL, NULL, s->tree_label, 0, > + view->ncols, 0, 0); > if (err) > return err; > if (view_needs_focus_indication(view)) > @@ -5295,8 +5308,8 @@ draw_tree_entries(struct tog_view *view, const char *p > waddch(view->window, '\n'); > if (--limit <= 0) > return NULL; > - err = format_line(&wline, &width, NULL, parent_path, 0, view->ncols, > - 0, 0); > + err = format_line(&wline, &width, NULL, NULL, parent_path, 0, > + view->ncols, 0, 0); > if (err) > return err; > waddwstr(view->window, wline); > @@ -5376,8 +5389,8 @@ draw_tree_entries(struct tog_view *view, const char *p > } > free(id_str); > free(link_target); > - err = format_line(&wline, &width, NULL, line, 0, view->ncols, > - 0, 0); > + err = format_line(&wline, &width, NULL, NULL, line, 0, > + view->ncols, 0, 0); > if (err) { > free(line); > break; > @@ -6488,7 +6501,8 @@ show_ref_view(struct tog_view *view) > s->nrefs) == -1) > return got_error_from_errno("asprintf"); > > - err = format_line(&wline, &width, NULL, line, 0, view->ncols, 0, 0); > + err = format_line(&wline, &width, NULL, NULL, line, 0, view->ncols, > + 0, 0); > if (err) { > free(line); > return err; > @@ -6575,8 +6589,8 @@ show_ref_view(struct tog_view *view) > got_ref_get_name(re->ref)) == -1) > return got_error_from_errno("asprintf"); > > - err = format_line(&wline, &width, NULL, line, 0, view->ncols, > - 0, 0); > + err = format_line(&wline, &width, NULL, NULL, line, 0, > + view->ncols, 0, 0); > if (err) { > free(line); > return err;