From: Mark Jamsek Subject: Re: switch printing newline on exit to To: Christian Weisgerber Cc: gameoftrees@openbsd.org Date: Sat, 21 Jan 2023 23:59:24 +1100 On 23-01-20 09:33PM, Christian Weisgerber wrote: > Tracey Emery: > > > Then what about this. It seems to just work in both cases. > > > --- tog/tog.c > > +++ tog/tog.c > > @@ -9438,7 +9438,6 @@ main(int argc, char *argv[]) > > } > > > > endwin(); > > - putchar('\n'); > > if (cmd_argv) { > > int i; > > for (i = 0; i < argc; i++) > > No, this brings us full circle to the original state of affairs > where you quit tog and then there is leftover stuff on the bottom > line to the right of your shell prompt (if alternate screen switching > is disabled). > > I tried to steal what vi(1) does, comment and all, see below, but > that doesn't work as expected. As soon as I call refresh() before > endwin(), the screen is cleared. I don't understand why this > happens. Maybe it's related to tog's use of panels, which vi doesn't > have? I believe this happens because when we refresh() in main, it is after having deallocated our windows. As such, there is no output to be redrawn. It looks like the vi code performs this line deletion to move all lines up and insert a blank line at the bottom before releasing window resources, so the final refresh() still has output to send to the screen. A solution is to do this in the view_loop() once we know the user is quitting tog (Q), or killing the current window (q) when it's the last one remaining. In the first case, we need to check if there are other windows and do the line deletion on them too. In the second case, we also need to then make sure tog doesn't redraw the full window (i.e., restore the line we deleted), so we set the done flag and bypass a redraw. As a small optimisation, in case there is more than one window (i.e., the user has input Q from a nested child window), use wnoutrefresh() and then call doupdate(); this saves repeated screen updates. Does the below diff produce the desired behaviour? An alternative solution would be to move to the bottom line and clear it, but I like the vi approach. diffstat /home/mark/src/got M tog/tog.c | 25+ 2- 1 file changed, 25 insertions(+), 2 deletions(-) diff /home/mark/src/got commit - 96afb0d62311dd459395b8eba2216094c18dfb67 path + /home/mark/src/got blob - 35282ce50aa4dec0745aa6402cd0b50d87b7416b file + tog/tog.c --- tog/tog.c +++ tog/tog.c @@ -1745,6 +1745,30 @@ view_loop(struct tog_view *view) err = view_input(&new_view, &done, view, &views); if (err) break; + + if (view->dying && view == TAILQ_FIRST(&views) && + TAILQ_NEXT(view, entry) == NULL) + done = 1; + if (done) { + struct tog_view *v; + + /* + * When we quit, scroll the screen up a single line + * so we don't lose any information. + */ + TAILQ_FOREACH(v, &views, entry) { + wmove(v->window, 0, 0); + wdeleteln(v->window); + wnoutrefresh(v->window); + if (v->child && !view_is_fullscreen(v)) { + wmove(v->child->window, 0, 0); + wdeleteln(v->child->window); + wnoutrefresh(v->child->window); + } + } + doupdate(); + } + if (view->dying) { struct tog_view *v, *prev = NULL; @@ -1808,7 +1832,7 @@ view_loop(struct tog_view *view) TAILQ_INSERT_TAIL(&views, new_view, entry); view = new_view; } - if (view) { + if (view && !done) { if (view_is_parent_view(view)) { if (view->child && view->child->focussed) view = view->child; @@ -9438,7 +9462,6 @@ main(int argc, char *argv[]) } endwin(); - putchar('\n'); if (cmd_argv) { int i; for (i = 0; i < argc; i++) -- Mark Jamsek GPG: F2FF 13DE 6A06 C471 CA80 E6E2 2930 DC66 86EE CF68