"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
tog: fix horizontal scrolling of unicode in the diff view
To:
gameoftrees@openbsd.org
Date:
Thu, 16 Jun 2022 16:32:33 +0200

Download raw body.

Thread
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?
 
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;