Commit Diff


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);
 	}