AnalogTerm2: Add input control flow for smooth scrolling.
authorMatthew Mondor <mmondor@pulsar-zone.net>
Thu, 20 Apr 2023 03:46:49 +0000 (03:46 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Thu, 20 Apr 2023 03:46:49 +0000 (03:46 +0000)
mmsoftware/analogterm2/TODO.txt
mmsoftware/analogterm2/src/main.c

index fe540c5..458de18 100644 (file)
   simplicity.  Also look at tcflow(3).  Currently, for smooth scrolling to
   work with screen(1)/tmux(1), the status bar must be disabled or configured
   to be at the top.
+  An early test used input flow control by temporarily stopping to read.  This
+  was not kept, but it may be necessary in some circumstances to avoid sudden
+  jumps.  Was restored in a different way, may need improvement.
 - Check termios(4) IMAXBEL and queue size, also reported by stty(1).
   This may allow to tweak interactive performance when a lot of application
   output happens.
index eeb28b6..156db48 100644 (file)
@@ -38,6 +38,8 @@ static const char     *progname = "";
 static Time            lastexpose = -1;
 
 static int             inputsleepskip = 0;
+static bool            scrollblocked = false;
+static int             blockedchar = '\0';
 
 
 
@@ -610,6 +612,27 @@ endopt:
                        if (state->cursor_disabled_ticks != 0)
                                rbufsize = 1;
 
+                       /*
+                        * If we stopped reading to control flow because of
+                        * scroll in progress while detecting another
+                        * character causing scrolling, simulate its
+                        * reception and unblock once scrolling stopped.
+                        */
+                       if (scrollblocked &&
+                           state->smoothscroll_offset == 0) {
+                               scrollblocked = false;
+                               *ttys->rbuf = blockedchar;
+                               size = 1;
+                               goto process;
+                       }
+
+                       /*
+                        * Avoid reading more data if blocked because of
+                        * scrolling.
+                        */
+                       if (scrollblocked)
+                               continue;
+
                        /* Finally read from the application tty(4) */
                        if ((size = read(ttys->ptyfd, ttys->rbuf, rbufsize))
                            == -1 && errno != EAGAIN && errno != EINTR) {
@@ -623,6 +646,22 @@ endopt:
                                break;
                        }
 
+                       /*
+                        * If scrolling is in progress and we receive another
+                        * character necessitating imminent scrolling,
+                        * temporarily stop input until scrolling ends.
+                        * Remember the character to simulate reading when
+                        * resuming.
+                        */
+                       if ((state->smoothscroll_offset > 0 && size == 1) &&
+                           (*ttys->rbuf == '\n' ||
+                            state->cursor_x == cfg_text_width - 1)) {
+                               scrollblocked = true;
+                               blockedchar = *ttys->rbuf;
+                               continue;
+                       }
+
+process:
                        /* Emulate terminal and update screen */
                        for (i = 0; i < size; i++)
                                state_emul_printc(state, ttys->rbuf[i]);