Add parsing of DCS q sequences - st - Simple Terminal
       
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit f7398434b8fa949af7bf43472caaefdd97eed0f3
 (DIR) parent f0e2d28732549690466df995981698173daf39c0
 (HTM) Author: Roberto E. Vargas Caballero <roberto.vargas@igrid-td.com>
       Date:   Wed, 14 Sep 2016 08:27:32 +0200
       
       Add parsing of DCS q sequences
       
       These sequences are used to operate with sixels, but they are still
       str sequences, so they are finished with \a, ST or with a C1 control
       code. This patch also disables utf8 handling for the case of sixels.
       
       Diffstat:
         st.c                                |      68 ++++++++++++++++++++-----------
       
       1 file changed, 45 insertions(+), 23 deletions(-)
       ---
 (DIR) diff --git a/st.c b/st.c
       @@ -138,6 +138,7 @@ enum term_mode {
                MODE_BRCKTPASTE  = 1 << 19,
                MODE_PRINT       = 1 << 20,
                MODE_UTF8        = 1 << 21,
       +        MODE_SIXEL       = 1 << 22,
                MODE_MOUSE       = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\
                                  |MODE_MOUSEMANY,
        };
       @@ -155,11 +156,12 @@ enum charset {
        enum escape_state {
                ESC_START      = 1,
                ESC_CSI        = 2,
       -        ESC_STR        = 4,  /* DCS, OSC, PM, APC */
       +        ESC_STR        = 4,  /* OSC, PM, APC */
                ESC_ALTCHARSET = 8,
                ESC_STR_END    = 16, /* a final string was encountered */
                ESC_TEST       = 32, /* Enter in test mode */
                ESC_UTF8       = 64,
       +        ESC_DCS        =128,
        };
        
        enum window_state {
       @@ -1485,7 +1487,7 @@ ttyread(void)
                ptr = buf;
        
                for (;;) {
       -                if (IS_SET(MODE_UTF8)) {
       +                if (IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) {
                                /* process a complete utf8 char */
                                charsize = utf8decode(ptr, &unicodep, buflen);
                                if (charsize == 0)
       @@ -1578,7 +1580,7 @@ ttysend(char *s, size_t n)
        
                lim = &s[n];
                for (t = s; t < lim; t += len) {
       -                if (IS_SET(MODE_UTF8)) {
       +                if (IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) {
                                len = utf8decode(t, &u, n);
                        } else {
                                u = *t & 0xFF;
       @@ -2548,6 +2550,7 @@ strhandle(void)
                        xsettitle(strescseq.args[0]);
                        return;
                case 'P': /* DCS -- Device Control String */
       +                term.mode |= ESC_DCS;
                case '_': /* APC -- Application Program Command */
                case '^': /* PM -- Privacy Message */
                        return;
       @@ -2754,9 +2757,12 @@ tdectest(char c)
        void
        ttstrsequence(uchar c)
        {
       +        strreset();
       +
                switch (c) {
                case 0x90:   /* DCS -- Device Control String */
                        c = 'P';
       +                term.esc |= ESC_DCS;
                        break;
                case 0x9f:   /* APC -- Application Program Command */
                        c = '_';
       @@ -2768,7 +2774,6 @@ tstrsequence(uchar c)
                        c = ']';
                        break;
                }
       -        strreset();
                strescseq.type = c;
                term.esc |= ESC_STR;
        }
       @@ -2968,7 +2973,7 @@ tputc(Rune u)
                Glyph *gp;
        
                control = ISCONTROL(u);
       -        if (!IS_SET(MODE_UTF8)) {
       +        if (!IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) {
                        c[0] = u;
                        width = len = 1;
                } else {
       @@ -2991,30 +2996,47 @@ tputc(Rune u)
                if (term.esc & ESC_STR) {
                        if (u == '\a' || u == 030 || u == 032 || u == 033 ||
                           ISCONTROLC1(u)) {
       -                        term.esc &= ~(ESC_START|ESC_STR);
       +                        term.esc &= ~(ESC_START|ESC_STR|ESC_DCS);
       +                        if (IS_SET(MODE_SIXEL)) {
       +                                /* TODO: render sixel */;
       +                                term.mode &= ~MODE_SIXEL;
       +                                return;
       +                        }
                                term.esc |= ESC_STR_END;
       -                } else if (strescseq.len + len < sizeof(strescseq.buf) - 1) {
       -                        memmove(&strescseq.buf[strescseq.len], c, len);
       -                        strescseq.len += len;
       +                        goto check_control_code;
       +                }
       +
       +
       +                if (IS_SET(MODE_SIXEL)) {
       +                        /* TODO: implement sixel mode */
                                return;
       -                } else {
       -                /*
       -                 * Here is a bug in terminals. If the user never sends
       -                 * some code to stop the str or esc command, then st
       -                 * will stop responding. But this is better than
       -                 * silently failing with unknown characters. At least
       -                 * then users will report back.
       -                 *
       -                 * In the case users ever get fixed, here is the code:
       -                 */
       -                /*
       -                 * term.esc = 0;
       -                 * strhandle();
       -                 */
       +                }
       +                if (term.esc&ESC_DCS && strescseq.len == 0 && u == 'q')
       +                        term.mode |= MODE_SIXEL;
       +
       +                if (strescseq.len+len >= sizeof(strescseq.buf)-1) {
       +                        /*
       +                         * Here is a bug in terminals. If the user never sends
       +                         * some code to stop the str or esc command, then st
       +                         * will stop responding. But this is better than
       +                         * silently failing with unknown characters. At least
       +                         * then users will report back.
       +                         *
       +                         * In the case users ever get fixed, here is the code:
       +                         */
       +                        /*
       +                         * term.esc = 0;
       +                         * strhandle();
       +                         */
                                return;
                        }
       +
       +                memmove(&strescseq.buf[strescseq.len], c, len);
       +                strescseq.len += len;
       +                return;
                }
        
       +check_control_code:
                /*
                 * Actions of control codes must be performed as soon they arrive
                 * because they can be embedded inside a control sequence, and