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

From:
Omar Polo <op@omarpolo.com>
Subject:
Re: fix hscrolling in split view
To:
Omar Polo <op@omarpolo.com>
Cc:
gameoftrees@openbsd.org
Date:
Fri, 17 Jun 2022 09:45:26 +0200

Download raw body.

Thread
Omar Polo <op@omarpolo.com> wrote:
> Stefan noticed that the horizontal scrolling in the split view (log +
> diff) in tog had a glitch when drawing double-width character.  To
> reproduce, open the ja.git repo provided by Stefan in a large enough
> xterm, press ret to see the diff in a split view, then tab to focus the
> log view and scroll horizontally and see the kanjis being rendered on
> top of the vertical line.
> 
> tog uses a trick for the split view: it renders the child view on top of
> the main view.  the main view always thinks of being as large as the
> terminal.  This confuses ncurses when you add double-width character to
> the equation.
> 
> The issue is that we end up in a situation like this
> 
>          |
>  log... xx
>          |
> 
> where "xx" is a double-width kanji and the | is the vertical line.  The
> vertical line should hide half of the character, but it can't.
> 
> diff below is an attempt at fixing this.  It properly resizes the main
> window when creating / destroying the split screen and accounts for the
> border when drawing the commit.
> 
> (the diff was generated on top of my previous diff that simplifies
> format_line and scroll_line, it should apply thought.)
> 
> ok?

The diff worked, but lacked some error checking.  In addressing that,
I've found that we failed to account correctly the size of the parent
window in view_resize.

new diff handles wresize failures, fixes the fallback from split screen
-> full screen when resizing and fixes the computation of the parent
window width (ncols) in view_resize.

diff c74541a34e628aa7d0d42da084a6f66045315aed /home/op/w/got
blob - 183c31a912c364ea95baef1534e1f5908d1fb8fe
file + tog/tog.c
--- tog/tog.c
+++ tog/tog.c
@@ -763,31 +763,39 @@ view_resize(struct tog_view *view)
 	else
 		ncols = view->ncols + (COLS - view->cols);
 
-	if (wresize(view->window, nlines, ncols) == ERR)
-		return got_error_from_errno("wresize");
-	if (replace_panel(view->panel, view->window) == ERR)
-		return got_error_from_errno("replace_panel");
-	wclear(view->window);
-
-	view->nlines = nlines;
-	view->ncols = ncols;
-	view->lines = LINES;
-	view->cols = COLS;
-
 	if (view->child) {
 		view->child->begin_x = view_split_begin_x(view->begin_x);
 		if (view->child->begin_x == 0) {
+			/*
+			 * Resize parent to full screen when not in
+			 * split screen.
+			 */
+			ncols = COLS;
+
 			view_fullscreen(view->child);
 			if (view->child->focussed)
 				show_panel(view->child->panel);
 			else
 				show_panel(view->panel);
 		} else {
+			ncols = view->child->begin_x;
+
 			view_splitscreen(view->child);
 			show_panel(view->child->panel);
 		}
 	}
 
+	if (wresize(view->window, nlines, ncols) == ERR)
+		return got_error_from_errno("wresize");
+	if (replace_panel(view->panel, view->window) == ERR)
+		return got_error_from_errno("replace_panel");
+	wclear(view->window);
+
+	view->nlines = nlines;
+	view->ncols = ncols;
+	view->lines = LINES;
+	view->cols = COLS;
+
 	return NULL;
 }
 
@@ -804,11 +812,13 @@ view_close_child(struct tog_view *view)
 	return err;
 }
 
-static void
+static const struct got_error *
 view_set_child(struct tog_view *view, struct tog_view *child)
 {
 	view->child = child;
 	child->parent = view;
+
+	return view_resize(view);
 }
 
 static int
@@ -1085,6 +1095,13 @@ view_loop(struct tog_view *view)
 			if (view->parent) {
 				view->parent->child = NULL;
 				view->parent->focus_child = 0;
+
+				prev->ncols = COLS;
+				if (wresize(prev->window, prev->lines,
+				    prev->ncols) == ERR)
+					err = got_error_from_errno("wresize");
+				if (err)
+					break;
 			} else
 				TAILQ_REMOVE(&views, view, entry);
 
@@ -1529,6 +1546,8 @@ draw_commit(struct tog_view *view, struct got_commit_o
 	if (newline)
 		*newline = '\0';
 	limit = avail - col;
+	if (view->child)
+		limit--;	/* for the border */
 	err = format_line(&wlogmsg, &logmsg_width, &scrollx, logmsg, view->x,
 	    limit, col, 1);
 	if (err)
@@ -2695,7 +2714,9 @@ input_log_view(struct tog_view **new_view, struct tog_
 			err = view_close_child(view);
 			if (err)
 				return err;
-			view_set_child(view, diff_view);
+			err = view_set_child(view, diff_view);
+			if (err)
+				return err;
 			view->focus_child = 1;
 		} else
 			*new_view = diff_view;
@@ -2716,7 +2737,9 @@ input_log_view(struct tog_view **new_view, struct tog_
 			err = view_close_child(view);
 			if (err)
 				return err;
-			view_set_child(view, tree_view);
+			err = view_set_child(view, tree_view);
+			if (err)
+				return err;
 			view->focus_child = 1;
 		} else
 			*new_view = tree_view;
@@ -2800,7 +2823,9 @@ input_log_view(struct tog_view **new_view, struct tog_
 			err = view_close_child(view);
 			if (err)
 				return err;
-			view_set_child(view, ref_view);
+			err = view_set_child(view, ref_view);
+			if (err)
+				return err;
 			view->focus_child = 1;
 		} else
 			*new_view = ref_view;
@@ -5101,7 +5126,9 @@ input_blame_view(struct tog_view **new_view, struct to
 			err = view_close_child(view);
 			if (err)
 				break;
-			view_set_child(view, diff_view);
+			err = view_set_child(view, diff_view);
+			if (err)
+				break;
 			view->focus_child = 1;
 		} else
 			*new_view = diff_view;
@@ -5845,7 +5872,9 @@ input_tree_view(struct tog_view **new_view, struct tog
 			err = view_close_child(view);
 			if (err)
 				return err;
-			view_set_child(view, log_view);
+			err = view_set_child(view, log_view);
+			if (err)
+				return err;
 			view->focus_child = 1;
 		} else
 			*new_view = log_view;
@@ -5868,7 +5897,9 @@ input_tree_view(struct tog_view **new_view, struct tog
 			err = view_close_child(view);
 			if (err)
 				return err;
-			view_set_child(view, ref_view);
+			err = view_set_child(view, ref_view);
+			if (err)
+				return err;
 			view->focus_child = 1;
 		} else
 			*new_view = ref_view;
@@ -6002,7 +6033,9 @@ input_tree_view(struct tog_view **new_view, struct tog
 				err = view_close_child(view);
 				if (err)
 					return err;
-				view_set_child(view, blame_view);
+				err = view_set_child(view, blame_view);
+				if (err)
+					return err;
 				view->focus_child = 1;
 			} else
 				*new_view = blame_view;
@@ -6728,7 +6761,9 @@ input_ref_view(struct tog_view **new_view, struct tog_
 			err = view_close_child(view);
 			if (err)
 				return err;
-			view_set_child(view, log_view);
+			err = view_set_child(view, log_view);
+			if (err)
+				return err;
 			view->focus_child = 1;
 		} else
 			*new_view = log_view;
@@ -6748,7 +6783,9 @@ input_ref_view(struct tog_view **new_view, struct tog_
 			err = view_close_child(view);
 			if (err)
 				return err;
-			view_set_child(view, tree_view);
+			err = view_set_child(view, tree_view);
+			if (err)
+				return err;
 			view->focus_child = 1;
 		} else
 			*new_view = tree_view;