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

From:
Mark Jamsek <mark@jamsek.com>
Subject:
Re: switch printing newline on exit to
To:
Christian Weisgerber <naddy@mips.inka.de>
Cc:
gameoftrees@openbsd.org
Date:
Sat, 21 Jan 2023 23:59:24 +1100

Download raw body.

Thread
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 <fnc.bsdbox.org>
GPG: F2FF 13DE 6A06 C471 CA80  E6E2 2930 DC66 86EE CF68