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" <[email protected]>
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" <[email protected]>
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" <[email protected]>
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" <[email protected]>
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