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.
This commit is contained in:
Roberto E. Vargas Caballero 2016-09-14 08:27:32 +02:00
parent f0e2d28732
commit f7398434b8

70
st.c
View File

@ -138,6 +138,7 @@ enum term_mode {
MODE_BRCKTPASTE = 1 << 19, MODE_BRCKTPASTE = 1 << 19,
MODE_PRINT = 1 << 20, MODE_PRINT = 1 << 20,
MODE_UTF8 = 1 << 21, MODE_UTF8 = 1 << 21,
MODE_SIXEL = 1 << 22,
MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\
|MODE_MOUSEMANY, |MODE_MOUSEMANY,
}; };
@ -155,11 +156,12 @@ enum charset {
enum escape_state { enum escape_state {
ESC_START = 1, ESC_START = 1,
ESC_CSI = 2, ESC_CSI = 2,
ESC_STR = 4, /* DCS, OSC, PM, APC */ ESC_STR = 4, /* OSC, PM, APC */
ESC_ALTCHARSET = 8, ESC_ALTCHARSET = 8,
ESC_STR_END = 16, /* a final string was encountered */ ESC_STR_END = 16, /* a final string was encountered */
ESC_TEST = 32, /* Enter in test mode */ ESC_TEST = 32, /* Enter in test mode */
ESC_UTF8 = 64, ESC_UTF8 = 64,
ESC_DCS =128,
}; };
enum window_state { enum window_state {
@ -1485,7 +1487,7 @@ ttyread(void)
ptr = buf; ptr = buf;
for (;;) { for (;;) {
if (IS_SET(MODE_UTF8)) { if (IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) {
/* process a complete utf8 char */ /* process a complete utf8 char */
charsize = utf8decode(ptr, &unicodep, buflen); charsize = utf8decode(ptr, &unicodep, buflen);
if (charsize == 0) if (charsize == 0)
@ -1578,7 +1580,7 @@ ttysend(char *s, size_t n)
lim = &s[n]; lim = &s[n];
for (t = s; t < lim; t += len) { 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); len = utf8decode(t, &u, n);
} else { } else {
u = *t & 0xFF; u = *t & 0xFF;
@ -2548,6 +2550,7 @@ strhandle(void)
xsettitle(strescseq.args[0]); xsettitle(strescseq.args[0]);
return; return;
case 'P': /* DCS -- Device Control String */ case 'P': /* DCS -- Device Control String */
term.mode |= ESC_DCS;
case '_': /* APC -- Application Program Command */ case '_': /* APC -- Application Program Command */
case '^': /* PM -- Privacy Message */ case '^': /* PM -- Privacy Message */
return; return;
@ -2754,9 +2757,12 @@ tdectest(char c)
void void
tstrsequence(uchar c) tstrsequence(uchar c)
{ {
strreset();
switch (c) { switch (c) {
case 0x90: /* DCS -- Device Control String */ case 0x90: /* DCS -- Device Control String */
c = 'P'; c = 'P';
term.esc |= ESC_DCS;
break; break;
case 0x9f: /* APC -- Application Program Command */ case 0x9f: /* APC -- Application Program Command */
c = '_'; c = '_';
@ -2768,7 +2774,6 @@ tstrsequence(uchar c)
c = ']'; c = ']';
break; break;
} }
strreset();
strescseq.type = c; strescseq.type = c;
term.esc |= ESC_STR; term.esc |= ESC_STR;
} }
@ -2968,7 +2973,7 @@ tputc(Rune u)
Glyph *gp; Glyph *gp;
control = ISCONTROL(u); control = ISCONTROL(u);
if (!IS_SET(MODE_UTF8)) { if (!IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) {
c[0] = u; c[0] = u;
width = len = 1; width = len = 1;
} else { } else {
@ -2991,30 +2996,47 @@ tputc(Rune u)
if (term.esc & ESC_STR) { if (term.esc & ESC_STR) {
if (u == '\a' || u == 030 || u == 032 || u == 033 || if (u == '\a' || u == 030 || u == 032 || u == 033 ||
ISCONTROLC1(u)) { 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; term.esc |= ESC_STR_END;
} else if (strescseq.len + len < sizeof(strescseq.buf) - 1) { goto check_control_code;
memmove(&strescseq.buf[strescseq.len], c, len); }
strescseq.len += len;
return;
} else { if (IS_SET(MODE_SIXEL)) {
/* /* TODO: implement sixel mode */
* 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; return;
} }
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 * Actions of control codes must be performed as soon they arrive
* because they can be embedded inside a control sequence, and * because they can be embedded inside a control sequence, and