- switch(ascii) {
- case '[':
- term.esc |= ESC_CSI;
- break;
- case 'P': /* DCS -- Device Control String */
- case '_': /* APC -- Application Program Command */
- case '^': /* PM -- Privacy Message */
- case ']': /* OSC -- Operating System Command */
- case 'k': /* old title set compatibility */
- strreset();
- strescseq.type = ascii;
- term.esc |= ESC_STR;
- break;
- case '(': /* set primary charset G0 */
- term.esc |= ESC_ALTCHARSET;
- break;
- case ')': /* set secondary charset G1 (IGNORED) */
- case '*': /* set tertiary charset G2 (IGNORED) */
- case '+': /* set quaternary charset G3 (IGNORED) */
- term.esc = 0;
- break;
- case 'D': /* IND -- Linefeed */
- if(term.c.y == term.bot)
- tscrollup(term.top, 1);
- else
- tmoveto(term.c.x, term.c.y+1);
- term.esc = 0;
- break;
- case 'E': /* NEL -- Next line */
- tnewline(1); /* always go to first col */
- term.esc = 0;
- break;
- case 'H': /* HTS -- Horizontal tab stop */
- term.tabs[term.c.x] = 1;
- term.esc = 0;
- break;
- case 'M': /* RI -- Reverse index */
- if(term.c.y == term.top)
- tscrolldown(term.top, 1);
- else
- tmoveto(term.c.x, term.c.y-1);
- term.esc = 0;
- break;
- case 'c': /* RIS -- Reset to inital state */
- treset();
- term.esc = 0;
- xclearborders();
- xresettitle();
- break;
- case '=': /* DECPAM -- Application keypad */
- term.mode |= MODE_APPKEYPAD;
- term.esc = 0;
- break;
- case '>': /* DECPNM -- Normal keypad */
- term.mode &= ~MODE_APPKEYPAD;
- term.esc = 0;
- break;
- case '7': /* DECSC -- Save Cursor */
- tcursor(CURSOR_SAVE);
- term.esc = 0;
- break;
- case '8': /* DECRC -- Restore Cursor */
- tcursor(CURSOR_LOAD);
- term.esc = 0;
- break;
- case '\\': /* ST -- Stop */
- term.esc = 0;
- break;
- default:
- fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n",
- (uchar) ascii, isprint(ascii)?ascii:'.');
+ tmoveto(term.c.x, term.c.y+1);
+ }
+ break;
+ case 'E': /* NEL -- Next line */
+ tnewline(1); /* always go to first col */
+ break;
+ case 'H': /* HTS -- Horizontal tab stop */
+ term.tabs[term.c.x] = 1;
+ break;
+ case 'M': /* RI -- Reverse index */
+ if(term.c.y == term.top) {
+ tscrolldown(term.top, 1);
+ } else {
+ tmoveto(term.c.x, term.c.y-1);
+ }
+ break;
+ case 'Z': /* DECID -- Identify Terminal */
+ ttywrite(vtiden, sizeof(vtiden) - 1);
+ break;
+ case 'c': /* RIS -- Reset to inital state */
+ treset();
+ xresettitle();
+ xloadcols();
+ break;
+ case '=': /* DECPAM -- Application keypad */
+ term.mode |= MODE_APPKEYPAD;
+ break;
+ case '>': /* DECPNM -- Normal keypad */
+ term.mode &= ~MODE_APPKEYPAD;
+ break;
+ case '7': /* DECSC -- Save Cursor */
+ tcursor(CURSOR_SAVE);
+ break;
+ case '8': /* DECRC -- Restore Cursor */
+ tcursor(CURSOR_LOAD);
+ break;
+ case '\\': /* ST -- String Terminator */
+ if(term.esc & ESC_STR_END)
+ strhandle();
+ break;
+ default:
+ fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n",
+ (uchar) ascii, isprint(ascii)? ascii:'.');
+ break;
+ }
+ return 1;
+}
+
+void
+tputc(char *c, int len) {
+ uchar ascii;
+ bool control;
+ long unicodep;
+ int width;
+ Glyph *gp;
+
+ if(len == 1) {
+ width = 1;
+ unicodep = ascii = *c;
+ } else {
+ utf8decode(c, &unicodep, UTF_SIZ);
+ if ((width = wcwidth(unicodep)) == -1) {
+ c = "\357\277\275"; /* UTF_INVALID */
+ width = 1;
+ }
+ ascii = unicodep;
+ }
+
+ if(IS_SET(MODE_PRINT))
+ tprinter(c, len);
+ control = ISCONTROL(unicodep);
+
+ /*
+ * STR sequence must be checked before anything else
+ * because it uses all following characters until it
+ * receives a ESC, a SUB, a ST or any other C1 control
+ * character.
+ */
+ if(term.esc & ESC_STR) {
+ if(len == 1 &&
+ (ascii == '\a' || ascii == 030 ||
+ ascii == 032 || ascii == 033 ||
+ ISCONTROLC1(unicodep))) {
+ term.esc &= ~(ESC_START|ESC_STR);
+ term.esc |= ESC_STR_END;
+ } else if(strescseq.len + len < sizeof(strescseq.buf) - 1) {
+ memmove(&strescseq.buf[strescseq.len], c, len);
+ strescseq.len += len;
+ 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();
+ */
+ return;
+ }
+ }
+
+ /*
+ * 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) {
+ tcontrolcode(ascii);
+ /*
+ * control codes are not shown ever
+ */
+ return;
+ } else if(term.esc & ESC_START) {
+ if(term.esc & ESC_CSI) {
+ csiescseq.buf[csiescseq.len++] = ascii;
+ if(BETWEEN(ascii, 0x40, 0x7E)
+ || csiescseq.len >= \
+ sizeof(csiescseq.buf)-1) {