AnalogTerm2: Terminal emulation improvements
authorMatthew Mondor <mmondor@pulsar-zone.net>
Thu, 20 Apr 2023 15:29:11 +0000 (15:29 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Thu, 20 Apr 2023 15:29:11 +0000 (15:29 +0000)
- Fixes some cursor update bugs that were most noticeable when
  enabling slow bps simulation.
- 'E' handling was erroneous.

mmsoftware/analogterm2/TODO.txt
mmsoftware/analogterm2/src/state.c

index 458de18..de8c363 100644 (file)
@@ -1,5 +1,6 @@
-- There is a cursor related refresh issue that is noticeable when enabling
-  the slow bandwidth feature.  It may be more noticeable in slow scroll mode.
+- Many operations are the equivalent of newline or scroll if the end of the
+  scrolling buffer or bottom are reached.  Unify those in a function or two as
+  possible.
 - Maybe provide the option to have text blinking settings independent from
   cursor blinking ones.  Text blinking usually doesn't need to be asymmetric
   and it may be too slow when used with rarely blinking cursors.
index d8d17d1..3bf4c67 100644 (file)
@@ -426,14 +426,14 @@ state_printc_1(state_t *st, uint32_t c, uint32_t m, bool scroll)
 
        switch (c) {
        case '\n':      /* ^J, NL, Newline */
-               st->text_updated[st->cursor_y] = true;
+               state_update_cursor(st);
                if (st->cursor_y < st->scroll_bottom &&
                    st->cursor_y < cfg_text_height - 1)
                        st->cursor_y++;
                else
                        state_scroll(st);
                st->cursor_x = 0;
-               st->text_updated[st->cursor_y] = true;
+               state_update_cursor(st);
                break;
        case '\r':      /* ^M, CR, CarriageReturn */
                st->cursor_x = 0;
@@ -467,9 +467,9 @@ state_printc_1(state_t *st, uint32_t c, uint32_t m, bool scroll)
                if (++st->cursor_x == cfg_text_width) {
                        if (st->cursor_y < st->scroll_bottom &&
                            st->cursor_y < cfg_text_height - 1) {
-                               st->text_updated[st->cursor_y] = true; /* XXX */
+                               state_update_cursor(st); /* XXX */
                                st->cursor_y++;
-                               st->text_updated[st->cursor_y] = true; /* XXX */
+                               state_update_cursor(st); /* XXX */
                        } else {
                                if (scroll)
                                        state_scroll(st);
@@ -608,14 +608,17 @@ state_emul_printc(state_t *st, uint8_t c)
                                state->cursor_x--;
                        break;
                case 9: /* HT XXX May be bogus */
-                       if (state->cursor_x < cfg_text_width - 8)
+                       if (state->cursor_x < cfg_text_width - 8) {
                                state->cursor_x = (state->cursor_x & ~7) + 8;
-                       else {
+                               state_updated(st, state->cursor_y);
+                       } else {
                                state->cursor_x = 0;
                                if (state->cursor_y < st->scroll_bottom &&
-                                   state->cursor_y < cfg_text_height - 1)
+                                   state->cursor_y < cfg_text_height - 1) {
+                                       state_updated(st, state->cursor_y);
                                        state->cursor_y++;
-                               else
+                                       state_updated(st, state->cursor_y);
+                               } else
                                        state_scroll(st);
                        }
                        break;
@@ -624,9 +627,12 @@ state_emul_printc(state_t *st, uint8_t c)
                case 12: /* FF */ /* FALLTHROUGH */
                        state->lastcol = false;
                        if (state->cursor_y < st->scroll_bottom &&
-                           state->cursor_y < cfg_text_height - 1)
+                           state->cursor_y < cfg_text_height - 1) {
+                               /* XXX */
+                               state_updated(st, state->cursor_y);
                                state->cursor_y++;
-                       else
+                               state_updated(st, state->cursor_y);
+                       } else
                                state_scroll(st);
                        break;
                case 13: /* CR */
@@ -720,9 +726,11 @@ state_emul_printc(state_t *st, uint8_t c)
                                state->lastcol = false;
                                state->cursor_x = 0;
                                if (state->cursor_y < st->scroll_bottom &&
-                                   state->cursor_y < cfg_text_height - 1)
+                                   state->cursor_y < cfg_text_height - 1) {
+                                       state_updated(st, state->cursor_y);
                                        state->cursor_y++;
-                               else
+                                       state_updated(st, state->cursor_y);
+                               } else
                                        state_scroll(st);
                        }
                        state_goto(st, state->cursor_y, state->cursor_x);
@@ -736,6 +744,8 @@ state_emul_printc(state_t *st, uint8_t c)
                        else
                                state->lastcol = false;
                        st->cursor_x = state->cursor_x;
+                       state_updated(st, st->cursor_y);
+                       state_updated(st, state->cursor_y);
                        break;
                }
                break;
@@ -756,13 +766,22 @@ state_emul_printc(state_t *st, uint8_t c)
                        break;
                case 'D': /* Linefeed */
                        if (state->cursor_y < st->scroll_bottom &&
-                           state->cursor_y < cfg_text_height - 1)
+                           state->cursor_y < cfg_text_height - 1) {
+                               state_updated(st, state->cursor_y);
                                state->cursor_y++;
-                       else
+                               state_updated(st, state->cursor_y);
+                       } else
                                state_scroll(st);
                        state->escstate = 0;
                        break;
                case 'E': /* Newline */
+                       if (state->cursor_y < st->scroll_bottom &&
+                           state->cursor_y < cfg_text_height - 1) {
+                               state_updated(st, state->cursor_y);
+                               state->cursor_y++;
+                               state_updated(st, state->cursor_y);
+                       } else
+                               state_scroll(st);
                        state->cursor_x = 0;
                        state->escstate = 0;
                        break;
@@ -775,9 +794,11 @@ state_emul_printc(state_t *st, uint8_t c)
                         * Takes scrolling range in consideration.
                         */
                        if (state->cursor_y > st->scroll_top &&
-                           state->cursor_y > 0)
+                           state->cursor_y > 0) {
+                               state_updated(st, state->cursor_y);
                                state->cursor_y--;
-                       else
+                               state_updated(st, state->cursor_y);
+                       } else
                                state_scroll_range(st, 1);
                        state->escstate = 0;
                        break;
@@ -787,8 +808,10 @@ state_emul_printc(state_t *st, uint8_t c)
                        state->escstate = 0;
                        break;
                case '8': /* Restore cursor state (rc) */
+                       state_updated(st, st->cursor_y);
                        state->cursor_x = st->saved_cursor_x;
                        state->cursor_y = st->saved_cursor_y;
+                       state_updated(st, st->cursor_y);
                        state->escstate = 0;
                        break;
                case '[': /* CSI, reset params and switch to state 2 */
@@ -899,15 +922,17 @@ state_emul_printc(state_t *st, uint8_t c)
                        state->escstate = 0;
                        break;
 
-               case 'E': /* Cursor next line (cnl) */
-                       state->cursor_x = 0;
-               case 'e': /* FALLTHROUGH */
+               case 'e': /* Non-scrolling Linefeed */
                case 'B': /* Cursor down (cud)  FALLTHROUGH */
+               case 'E': /* Cursor next line (cnl) FALLTHROUGH */
                        if ((i = (state->curparam == -1) ? 1 :
                            state->csiparam[0]) > 0) {
                                if ((state->cursor_y += i) >= cfg_text_height)
                                        state->cursor_y = cfg_text_height - 1;
                        }
+                       /* E is non-scrolling Newline+CR. */
+                       if (c == 'E')
+                               state->cursor_x = 0;
                        state->escstate = 0;
                        break;
 
@@ -917,9 +942,11 @@ state_emul_printc(state_t *st, uint8_t c)
                                many = 1;
                        if (st->lastchar != (uint32_t)-1 &&
                            isprint((int)st->lastchar)) {
+                               state_updated(st, st->cursor_y);
                                for (i = 0; i < many; i++)
                                        state_printc(st, st->lastchar,
                                            state->mode);
+                               state_updated(st, st->cursor_y);
                                /* Double state requires this */
                                state_limit(&st->cursor_x, &st->cursor_y);
                                state->cursor_x = st->cursor_x;
@@ -977,9 +1004,11 @@ state_emul_printc(state_t *st, uint8_t c)
                        break;
                case 'f':
                case 'H': /* Cursor address h/v position (cup)  FALLTHROUGH */
+                       state_updated(st, state->cursor_y);
                        state->cursor_y = state->csiparam[0] - 1;
                        state->cursor_x = state->csiparam[1] - 1;
                        state_limit(&state->cursor_x, &state->cursor_y);
+                       state_updated(st, state->cursor_y);
                        state->escstate = 0;
                        break;
                case 'h': /* DEC Private Mode Set (DECSET) */
@@ -1619,8 +1648,10 @@ endh:
                        state->escstate = 0;
                        break;
                case 'u': /* Restore cursor position (rc) */
+                       state_updated(st, state->cursor_y);
                        state->cursor_x = st->saved_cursor_x;
                        state->cursor_y = st->saved_cursor_y;
+                       state_updated(st, state->cursor_y);
                        state->escstate = 0;
                        break;
                case 'X': /* Erase characters (ech) */