- if(iofd != -1) {
- if (xwrite(iofd, c, len) < 0) {
- fprintf(stderr, "Error writting in %s:%s\n",
- opt_io, strerror(errno));
- close(iofd);
- iofd = -1;
- }
- }
- /*
- * STR sequences must be checked before anything else
- * 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;
- 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;
- }
-
- /*
- * 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)
- || csiescseq.len >= ESC_BUF_SIZ) {
- term.esc = 0;
- csiparse(), csihandle();
- }
- } else if(term.esc & ESC_STR_END) {
- term.esc = 0;
- if(ascii == '\\')
- strhandle();
- } else if(term.esc & ESC_ALTCHARSET) {
- switch(ascii) {
- case '0': /* Line drawing set */
- term.c.attr.mode |= ATTR_GFX;
- break;
- case 'B': /* USASCII */
- term.c.attr.mode &= ~ATTR_GFX;
- break;
- case 'A': /* UK (IGNORED) */
- case '<': /* multinational charset (IGNORED) */
- case '5': /* Finnish (IGNORED) */
- case 'C': /* Finnish (IGNORED) */
- case 'K': /* German (IGNORED) */
- break;
- default:
- fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii);
- }
- term.esc = 0;
- } else if(term.esc & ESC_TEST) {
- if(ascii == '8') { /* DEC screen alignment test. */
- char E[UTF_SIZ] = "E";
- int x, y;
-
- for(x = 0; x < term.col; ++x) {
- for(y = 0; y < term.row; ++y)
- tsetchar(E, &term.c.attr, x, y);
- }
- }
- term.esc = 0;
- } else {
- switch(ascii) {
- case '[':
- term.esc |= ESC_CSI;
- break;
- case '#':
- term.esc |= ESC_TEST;
- 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 'Z': /* DECID -- Identify Terminal */
- ttywrite(VT102ID, sizeof(VT102ID) - 1);
- term.esc = 0;
- break;
- case 'c': /* RIS -- Reset to inital state */
- treset();
- term.esc = 0;
- 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:'.');
- term.esc = 0;
- }
- }
- /*
- * 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, &term.c.attr, term.c.x, term.c.y);
- if(term.c.x+1 < term.col)
- tmoveto(term.c.x+1, term.c.y);
- else
- term.c.state |= CURSOR_WRAPNEXT;
-}
-
-int
-tresize(int col, int row) {
- int i, x;
- int minrow = MIN(row, term.row);
- int mincol = MIN(col, term.col);
- int slide = term.c.y - row + 1;
- bool *bp;
-
- if(col < 1 || row < 1)
- return 0;
-
- /* free unneeded rows */
- i = 0;
- if(slide > 0) {
- /* slide screen to keep cursor where we expect it -
- * tscrollup would work here, but we can optimize to
- * memmove because we're freeing the earlier lines */
- for(/* i = 0 */; i < slide; i++) {
- free(term.line[i]);
- free(term.alt[i]);
- }
- memmove(term.line, term.line + slide, row * sizeof(Line));
- memmove(term.alt, term.alt + slide, row * sizeof(Line));
- }
- for(i += row; i < term.row; i++) {
- free(term.line[i]);
- free(term.alt[i]);
- }
-
- /* resize to new height */
- term.line = xrealloc(term.line, row * sizeof(Line));
- term.alt = xrealloc(term.alt, row * sizeof(Line));
- term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
- term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
-
- /* resize each row to new width, zero-pad if needed */
- for(i = 0; i < minrow; i++) {
- term.dirty[i] = 1;
- term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph));
- term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph));
- for(x = mincol; x < col; x++) {
- term.line[i][x].state = 0;
- term.alt[i][x].state = 0;
- }
- }
-
- /* allocate any new rows */
- for(/* i == minrow */; i < row; i++) {
- term.dirty[i] = 1;
- term.line[i] = xcalloc(col, sizeof(Glyph));
- term.alt [i] = xcalloc(col, sizeof(Glyph));
- }
- if(col > term.col) {
- bp = term.tabs + term.col;
-
- memset(bp, 0, sizeof(*term.tabs) * (col - term.col));
- while(--bp > term.tabs && !*bp)
- /* nothing */ ;
- for(bp += tabspaces; bp < term.tabs + col; bp += tabspaces)
- *bp = 1;
- }
- /* update terminal size */
- term.col = col;
- term.row = row;
- /* make use of the LIMIT in tmoveto */
- tmoveto(term.c.x, term.c.y);
- /* reset scrolling region */
- tsetscroll(0, row-1);
-
- return (slide > 0);