From: Omar Polo Subject: Re: fix hscrolling in split view To: Omar Polo Cc: gameoftrees@openbsd.org Date: Fri, 17 Jun 2022 09:45:26 +0200 Omar Polo 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;