Hello, This is a new serie of patches for st related to control codes. In the case of 0003-Add-SI-and-SO-control-codes.patch code does the same that linux virtual terminal and my real vt520, but xterm and uxterm have other behaviour, so if someone could give some aditional information about this issue then please say it. In the patch 0004-Print-control-codes-only-in-graphic-mode.patch I have changed the priority of checks:
1: If we are in a STR sequence then handle it and return. 2: If ascii is a control code then handle it and continue. 3: Else if we are in a ESC sequence handle it and return. 4: Print the character. Control codes are printed only in graphic mode. After checked some strange sequences in xterm and uxterm this seems the correct order, but I can not be sure about str sequences because I can not find documentation about them (I think they were added by xterm). It is possible these patches can help with the problem of KarlOskar Rikås with sandy, because maybe the lost glyph were some control codes, but I can not be sure because I can not reproduce the problem in my computer. Roberto Vargas,
>From ea7f1156689131e069cfb302d7d97a68f6169565 Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" <k...@shike2.com> Date: Thu, 27 Sep 2012 18:34:07 +0200 Subject: Add documentation to control codes Add the documentation from the vt100 manual programmer: Control Octal Action Taken Character Code ------------------------------------------- NUL 000 Ignored on input (not stored in input buffer; see full duplex protocol). ENQ 005 Transmit answerback message. BEL 007 Sound bell tone from keyboard. BS 010 Move the cursor to the left one character position, unless it is at the left margin, in which case no action occurs. HT 011 Move the cursor to the next tab stop, or to the right margin if no further tab stops are present on the line. LF 012 This code causes a line feed or a new line operation. (See new line mode). VT 013 Interpreted as LF. FF 014 Interpreted as LF. CR 015 Move cursor to the left margin on the current line. SO 016 Invoke G1 character set, as designated by SCS control sequence. SI 017 Select G0 character set, as selected by ESC ( sequence. XON 021 Causes terminal to resume transmission. XOFF 023 Causes terminal to stop transmitted all codes except XOFF and XON. CAN 030 If sent during a control sequence, the sequence is immediately terminated and not executed. It also causes the error character to be displayed. SUB 032 Interpreted as CAN. ESC 033 Invokes a control sequence. DEL 177 Ignored on input (not stored in input buffer). -------------------------------------------- --- st.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/st.c b/st.c index 64e0aff..aa5f085 100644 --- a/st.c +++ b/st.c @@ -1789,32 +1789,42 @@ tputc(char *c, int len) { write(iofd, c, len); switch(ascii) { - case '\t': + case '\t': /* HT */ tputtab(1); return; - case '\b': + case '\b': /* BS */ tmoveto(term.c.x-1, term.c.y); return; - case '\r': + case '\r': /* CR */ tmoveto(0, term.c.y); return; - case '\f': - case '\v': - case '\n': + 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': + case '\a': /* BEL */ if(term.esc & ESC_STR) break; - if(!(xw.state & WIN_FOCUSED)) xseturgency(1); return; - case '\033': + case '\033': /* ESC */ csireset(); term.esc = ESC_START; return; + case '\016': /* XXX: SO */ + case '\017': /* XXX: SI */ + case '\032': /* XXX: SUB */ + case '\030': /* XXX: CAN */ + 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) { -- 1.7.10.4
>From 58b67250da632d4213f0dcf82eee5ce0585e5dfb Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" <k...@shike2.com> Date: Fri, 28 Sep 2012 22:04:17 +0200 Subject: Add SUB and CAN control codes These control codes reset any escape sequence already initialised. --- st.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/st.c b/st.c index aa5f085..8e25d23 100644 --- a/st.c +++ b/st.c @@ -1816,8 +1816,11 @@ tputc(char *c, int len) { return; case '\016': /* XXX: SO */ case '\017': /* XXX: SI */ - case '\032': /* XXX: SUB */ - case '\030': /* XXX: CAN */ + break; + case '\032': /* SUB */ + case '\030': /* CAN */ + csireset(); + return; default: /* case '\005': ENQ (IGNORED) */ /* case '\000': NUL (IGNORED) */ -- 1.7.10.4
>From a3a3ce413ffad5110640444e70685b37787e8bc5 Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" <k...@shike2.com> Date: Fri, 28 Sep 2012 22:06:02 +0200 Subject: Add SI and SO control codes SI and SO allows change the G0 and G1 selection. This implementation is not full vt100 compatible, but it is complatible with linux virtual terminal implementation. For full vt100 compatibility we need remake a lot of stuff relate to the different charmaps. --- st.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/st.c b/st.c index 8e25d23..ba6973a 100644 --- a/st.c +++ b/st.c @@ -1814,9 +1814,12 @@ tputc(char *c, int len) { csireset(); term.esc = ESC_START; return; - case '\016': /* XXX: SO */ - case '\017': /* XXX: SI */ + 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(); -- 1.7.10.4
>From 9faf80a2ea740222653f10fe6a4532a874737aa4 Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" <k...@shike2.com> Date: Sat, 6 Oct 2012 18:21:33 +0200 Subject: Print control codes only in graphic mode 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(-) diff --git a/st.c b/st.c index ba6973a..23ed213 100644 --- 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 -- 1.7.10.4