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

From:
Stefan Sperling <stsp@stsp.name>
Subject:
Re: [rfc] tog horizontal scroll (diff & blame view)
To:
Mark Jamsek <mark@jamsek.com>, gameoftrees@openbsd.org
Date:
Thu, 16 Jun 2022 14:21:41 +0200

Download raw body.

Thread
On Thu, Jun 16, 2022 at 01:38:16PM +0200, Stefan Sperling wrote:
> On Thu, Jun 16, 2022 at 09:16:05PM +1000, Mark Jamsek wrote:
> > On 22-06-16 12:33pm, Stefan Sperling wrote:
> > > This new helper could be part of format_line(), but for now I wanted
> > > to keep it seperate. Otherwise I would need to update all existing
> > > callers of format_line() in the same patch.
> > > 
> > 
> > I think that's a good idea too; it makes sense doing this in
> > format_line().
> 
> Yes, I'll try to this later once things have settled a bit.

Well, why not do it now.

Having this functionality built into format_line() should make it
easier to fix the other views for unicode.

ok?

diff c05b27d80ffca42064176ccd557158bf67877943 0a40cff8c4fcef71b9eaf004224753b94cd426b0
blob - 61e731b74f838cf2b8072f3655e745a29b6c673f
blob + 8f9d4366f97c12983f70c237ca107a52f835a2d9
--- tog/tog.c
+++ tog/tog.c
@@ -1257,17 +1257,69 @@ expand_tab(char **ptr, const char *src)
 	return NULL;
 }
 
-/* Format a line for display, ensuring that it won't overflow a width limit. */
+/* 
+ * Skip leading nscroll columns of a wide character string.
+ * Returns the index to the first character of the scrolled string.
+ */
 static const struct got_error *
-format_line(wchar_t **wlinep, int *widthp, const char *line, int wlimit,
-    int col_tab_align, int expand)
+scroll_wline(int *scrollx , wchar_t *wline, int nscroll,
+    int col_tab_align)
 {
+	int cols = 0;
+	size_t wlen = wcslen(wline);
+	int i = 0;
+
+	*scrollx = 0;
+
+	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");
+	}
+
+	*scrollx = i;
+	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.
+ */
+static const struct got_error *
+format_line(wchar_t **wlinep, int *widthp, int *scrollxp,
+    const char *line, int nscroll, int wlimit, int col_tab_align, int expand)
+{
 	const struct got_error *err = NULL;
 	int cols = 0;
 	wchar_t *wline = NULL;
 	char *exstr = NULL;
 	size_t wlen;
-	int i;
+	int i, scrollx = 0;
 
 	*wlinep = NULL;
 	*widthp = 0;
@@ -1283,6 +1335,10 @@ format_line(wchar_t **wlinep, int *widthp, const char 
 	if (err)
 		return err;
 
+	err = scroll_wline(&scrollx, wline, nscroll, col_tab_align);
+	if (err)
+		goto done;
+
 	if (wlen > 0 && wline[wlen - 1] == L'\n') {
 		wline[wlen - 1] = L'\0';
 		wlen--;
@@ -1292,7 +1348,7 @@ format_line(wchar_t **wlinep, int *widthp, const char 
 		wlen--;
 	}
 
-	i = 0;
+	i = scrollx;
 	while (i < wlen) {
 		int width = wcwidth(wline[i]);
 
@@ -1326,6 +1382,8 @@ format_line(wchar_t **wlinep, int *widthp, const char 
 	wline[i] = L'\0';
 	if (widthp)
 		*widthp = cols;
+	if (scrollxp)
+		*scrollxp = scrollx;
 done:
 	if (err)
 		free(wline);
@@ -1334,51 +1392,6 @@ done:
 	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*
 build_refs_str(char **refs_str, struct got_reflist_head *refs,
     struct got_object_id *id, struct got_repository *repo)
@@ -1457,8 +1470,8 @@ 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, author, limit, col_tab_align,
-	    0);
+	return format_line(wauthor, author_width, NULL, author, 0, limit,
+	    col_tab_align, 0);
 }
 
 static const struct got_error *
@@ -1471,10 +1484,10 @@ 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, *scrolled_wline;
+	wchar_t *wlogmsg = NULL, *wauthor = NULL;
 	int author_width, logmsg_width;
 	char *newline, *line = NULL;
-	int col, limit;
+	int col, limit, scrollx;
 	const int avail = view->ncols;
 	struct tm tm;
 	time_t committer_time;
@@ -1555,15 +1568,12 @@ draw_commit(struct tog_view *view, struct got_commit_o
 	newline = strchr(logmsg, '\n');
 	if (newline)
 		*newline = '\0';
-	limit = view->x + avail - col;
-	err = format_line(&wlogmsg, &logmsg_width, logmsg, limit, col, 1);
+	limit = avail - col;
+	err = format_line(&wlogmsg, &logmsg_width, &scrollx, logmsg, view->x,
+	    limit, col, 1);
 	if (err)
 		goto done;
-	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));
+	waddwstr(view->window, &wlogmsg[scrollx]);
 	col += MAX(logmsg_width, 0);
 	while (col < avail) {
 		waddch(view->window, ' ');
@@ -1801,7 +1811,7 @@ draw_commits(struct tog_view *view)
 		header = NULL;
 		goto done;
 	}
-	err = format_line(&wline, &width, header, view->ncols, 0, 0);
+	err = format_line(&wline, &width, NULL, header, 0, view->ncols, 0, 0);
 	if (err)
 		goto done;
 
@@ -1856,7 +1866,7 @@ draw_commits(struct tog_view *view)
 			++msg;
 		if ((eol = strchr(msg, '\n')))
 			*eol = '\0';
-		err = format_line(&wmsg, &width, msg, INT_MAX,
+		err = format_line(&wmsg, &width, NULL, msg, 0, INT_MAX,
 		    date_display_cols + author_cols, 0);
 		if (err)
 			goto done;
@@ -3117,7 +3127,7 @@ add_matched_line(int *wtotal, const char *line, int wl
 	rms = regmatch->rm_so;
 	rme = regmatch->rm_eo;
 
-	err = format_line(&wline, &width, line, wlimit + skip,
+	err = format_line(&wline, &width, NULL, line, 0, wlimit + skip,
 	    col_tab_align, 1);
 	if (err)
 		return err;
@@ -3187,7 +3197,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, line, view->ncols, 0, 0);
+		err = format_line(&wline, &width, NULL, line, 0, view->ncols,
+		    0, 0);
 		free(line);
 		if (err)
 			return err;
@@ -3236,7 +3247,7 @@ draw_file(struct tog_view *view, const char *header)
 				return err;
 			}
 		} else {
-			err = format_line(&wline, &width, line,
+			err = format_line(&wline, &width, NULL, line, 0,
 			    view->x + view->ncols, 0, view->x ? 1 : 0);
 			if (err) {
 				free(line);
@@ -3269,8 +3280,8 @@ draw_file(struct tog_view *view, const char *header)
 			nprinted++;
 		}
 
-		err = format_line(&wline, &width, TOG_EOF_STRING, view->ncols,
-		    0, 0);
+		err = format_line(&wline, &width, NULL, TOG_EOF_STRING, 0,
+		    view->ncols, 0, 0);
 		if (err) {
 			return err;
 		}
@@ -4269,7 +4280,7 @@ draw_blame(struct tog_view *view)
 		return err;
 	}
 
-	err = format_line(&wline, &width, line, view->ncols, 0, 0);
+	err = format_line(&wline, &width, NULL, line, 0, view->ncols, 0, 0);
 	free(line);
 	line = NULL;
 	if (err)
@@ -4298,7 +4309,7 @@ draw_blame(struct tog_view *view)
 		return got_error_from_errno("asprintf");
 	}
 	free(id_str);
-	err = format_line(&wline, &width, line, view->ncols, 0, 0);
+	err = format_line(&wline, &width, NULL, line, 0, view->ncols, 0, 0);
 	free(line);
 	line = NULL;
 	if (err)
@@ -4385,7 +4396,7 @@ draw_blame(struct tog_view *view)
 			}
 			width += 9;
 		} else {
-			err = format_line(&wline, &width, line,
+			err = format_line(&wline, &width, NULL, line, 0,
 			    view->x + view->ncols - 9, 9, 1);
 			if (err) {
 				free(line);
@@ -5263,7 +5274,8 @@ draw_tree_entries(struct tog_view *view, const char *p
 	if (limit == 0)
 		return NULL;
 
-	err = format_line(&wline, &width, s->tree_label, view->ncols, 0, 0);
+	err = format_line(&wline, &width, NULL, s->tree_label, 0, view->ncols,
+	    0, 0);
 	if (err)
 		return err;
 	if (view_needs_focus_indication(view))
@@ -5284,7 +5296,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, parent_path, view->ncols, 0, 0);
+	err = format_line(&wline, &width, NULL, parent_path, 0, view->ncols,
+	    0, 0);
 	if (err)
 		return err;
 	waddwstr(view->window, wline);
@@ -5364,7 +5377,8 @@ draw_tree_entries(struct tog_view *view, const char *p
 		}
 		free(id_str);
 		free(link_target);
-		err = format_line(&wline, &width, line, view->ncols, 0, 0);
+		err = format_line(&wline, &width, NULL, line, 0, view->ncols,
+		    0, 0);
 		if (err) {
 			free(line);
 			break;
@@ -6475,7 +6489,7 @@ show_ref_view(struct tog_view *view)
 	    s->nrefs) == -1)
 		return got_error_from_errno("asprintf");
 
-	err = format_line(&wline, &width, line, view->ncols, 0, 0);
+	err = format_line(&wline, &width, NULL, line, 0, view->ncols, 0, 0);
 	if (err) {
 		free(line);
 		return err;
@@ -6562,7 +6576,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, line, view->ncols, 0, 0);
+		err = format_line(&wline, &width, NULL, line, 0, view->ncols,
+		    0, 0);
 		if (err) {
 			free(line);
 			return err;