Print control codes only in graphic mode
authorRoberto E. Vargas Caballero <k0ga@shike2.com>
Sat, 6 Oct 2012 17:15:30 +0000 (19:15 +0200)
committerRoberto E. Vargas Caballero <k0ga@shike2.com>
Sat, 6 Oct 2012 17:15:30 +0000 (19:15 +0200)
Non handled codes must be ignored, except in graphic mode. Also STR
sequences have higher priority than control codes, so they must be handled
before of them.
---
 st.c |  160 ++++++++++++++++++++++++++++++++++++------------------------------
 1 file changed, 87 insertions(+), 73 deletions(-)

st.c

diff --git a/st.c b/st.c
index ba6973a..23ed213 100644 (file)
--- a/st.c
+++ b/st.c
@@ -1784,56 +1784,80 @@ tputtab(bool forward) {
 void
 tputc(char *c, int len) {
        uchar ascii = *c;
+       bool control = ascii < '\x20' || ascii == 0177;
 
        if(iofd != -1)
                write(iofd, c, len);
-
-       switch(ascii) {
-       case '\t':      /* HT */
-               tputtab(1);
-               return;
-       case '\b':      /* BS */
-               tmoveto(term.c.x-1, term.c.y);
-               return;
-       case '\r':      /* CR */
-               tmoveto(0, term.c.y);
-               return;
-       case '\f':      /* LF */
-       case '\v':      /* VT */
-       case '\n':      /* LF */
-               /* go to first col if the mode is set */
-               tnewline(IS_SET(MODE_CRLF));
-               return;
-       case '\a':      /* BEL */
-               if(term.esc & ESC_STR)
+       /*
+        * STR sequences must be checked before of anything
+        * because it can use some control codes as part of the sequence
+        */
+       if(term.esc & ESC_STR) {
+               switch(ascii) {
+               case '\033':
+                       term.esc = ESC_START | ESC_STR_END;
                        break;
-               if(!(xw.state & WIN_FOCUSED))
-                       xseturgency(1);
-               return;
-       case '\033':    /* ESC */
-               csireset();
-               term.esc = ESC_START;
-               return;
-       case '\016':    /* SO */
-               term.c.attr.mode |= ATTR_GFX;
-               break;
-       case '\017':    /* SI */
-               term.c.attr.mode &= ~ATTR_GFX;
-               return;
-       case '\032':    /* SUB */
-       case '\030':    /* CAN */
-               csireset();
+               case '\a': /* backwards compatibility to xterm */
+                       term.esc = 0;
+                       strhandle();
+                       break;
+               default:
+                       strescseq.buf[strescseq.len++] = ascii;
+                       if(strescseq.len+1 >= STR_BUF_SIZ) {
+                               term.esc = 0;
+                               strhandle();
+                       }
+               }
                return;
-       default:
-       /* case '\005': ENQ (IGNORED) */
-       /* case '\000': NUL (IGNORED) */
-       /* case '\021': XON (IGNORED) */
-       /* case '\023': XOFF (IGNORED) */
-       /* case 0177:   DEL (IGNORED) */
-               break;
        }
-
-       if(term.esc & ESC_START) {
+       /*
+        * Actions of control codes must be performed as soon they arrive
+        * because they can be embedded inside a control sequence, and
+        * they must not cause conflicts with sequences.
+        */
+       if(control) {
+               switch(ascii) {
+               case '\t':      /* HT */
+                       tputtab(1);
+                       return;
+               case '\b':      /* BS */
+                       tmoveto(term.c.x-1, term.c.y);
+                       return;
+               case '\r':      /* CR */
+                       tmoveto(0, term.c.y);
+                       return;
+               case '\f':      /* LF */
+               case '\v':      /* VT */
+               case '\n':      /* LF */
+                       /* go to first col if the mode is set */
+                       tnewline(IS_SET(MODE_CRLF));
+                       return;
+               case '\a':      /* BEL */
+                       if(!(xw.state & WIN_FOCUSED))
+                               xseturgency(1);
+                       return;
+               case '\033':    /* ESC */
+                       csireset();
+                       term.esc = ESC_START;
+                       return;
+               case '\016':    /* SO */
+                       term.c.attr.mode |= ATTR_GFX;
+                       return;
+               case '\017':    /* SI */
+                       term.c.attr.mode &= ~ATTR_GFX;
+                       return;
+               case '\032':    /* SUB */
+               case '\030':    /* CAN */
+                       csireset();
+                       return;
+                case '\005':   /* ENQ (IGNORED) */
+                case '\000':   /* NUL (IGNORED) */
+                case '\021':   /* XON (IGNORED) */
+                case '\023':   /* XOFF (IGNORED) */
+                case 0177:     /* DEL (IGNORED) */
+                       return;
+               }
+       } else if(term.esc & ESC_START) {
                if(term.esc & ESC_CSI) {
                        csiescseq.buf[csiescseq.len++] = ascii;
                        if(BETWEEN(ascii, 0x40, 0x7E)
@@ -1841,22 +1865,6 @@ tputc(char *c, int len) {
                                term.esc = 0;
                                csiparse(), csihandle();
                        }
-               } else if(term.esc & ESC_STR) {
-                       switch(ascii) {
-                       case '\033':
-                               term.esc = ESC_START | ESC_STR_END;
-                               break;
-                       case '\a': /* backwards compatibility to xterm */
-                               term.esc = 0;
-                               strhandle();
-                               break;
-                       default:
-                               strescseq.buf[strescseq.len++] = ascii;
-                               if(strescseq.len+1 >= STR_BUF_SIZ) {
-                                       term.esc = 0;
-                                       strhandle();
-                               }
-                       }
                } else if(term.esc & ESC_STR_END) {
                        term.esc = 0;
                        if(ascii == '\\')
@@ -1955,20 +1963,26 @@ tputc(char *c, int len) {
                                term.esc = 0;
                        }
                }
-       } else {
-               if(sel.bx != -1 && BETWEEN(term.c.y, sel.by, sel.ey))
-                       sel.bx = -1;
-               if(ascii >= '\020' || term.c.attr.mode & ATTR_GFX) {
-                       if(IS_SET(MODE_WRAP) && term.c.state & CURSOR_WRAPNEXT)
-                               tnewline(1); /* always go to first col */
-                       tsetchar(c);
-                       if(term.c.x+1 < term.col) {
-                               tmoveto(term.c.x+1, term.c.y);
-                       } else {
-                               term.c.state |= CURSOR_WRAPNEXT;
-                       }
-               }
+               /*
+                * All characters which forms part of a sequence are not
+                * printed
+                */
+               return;
        }
+       /*
+        * Display control codes only if we are in graphic mode
+        */
+       if(control && !(term.c.attr.mode & ATTR_GFX))
+               return;
+       if(sel.bx != -1 && BETWEEN(term.c.y, sel.by, sel.ey))
+               sel.bx = -1;
+       if(IS_SET(MODE_WRAP) && term.c.state & CURSOR_WRAPNEXT)
+               tnewline(1); /* always go to first col */
+       tsetchar(c);
+       if(term.c.x+1 < term.col)
+               tmoveto(term.c.x+1, term.c.y);
+       else
+               term.c.state |= CURSOR_WRAPNEXT;
 }
 
 int