From 8ead06c97e16165208fd9d02ada73d63aeca11f2 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sat, 11 Nov 2006 01:15:19 +0100 Subject: [PATCH] reindent Signed-off-by: Pierre Habouzit --- am/footer.mk | 1 + madtty/inject.c | 426 ++++++++++++++++++----------------- madtty/inject_csi.c | 515 ++++++++++++++++++++++--------------------- madtty/inject_csi.h | 15 +- madtty/madtty.c | 437 ++++++++++++++++++------------------ madtty/madtty.h | 76 +++---- madtty/roteprivate.h | 28 +-- 7 files changed, 768 insertions(+), 730 deletions(-) diff --git a/am/footer.mk b/am/footer.mk index 0acffb8..0d680c6 100644 --- a/am/footer.mk +++ b/am/footer.mk @@ -148,6 +148,7 @@ clean:: clobber distclean:: CLEAN_RECURSE= clobber distclean:: clean $(RM) -r .objs* $(DISTCLEANFILES) + @[ -f Makefile.in ] && $(RM) Makefile ifeq (".","$(DEPTH)") clobber distclean:: diff --git a/madtty/inject.c b/madtty/inject.c index d4b05da..7334921 100644 --- a/madtty/inject.c +++ b/madtty/inject.c @@ -26,251 +26,261 @@ #include "roteprivate.h" #include "inject_csi.h" -static void cursor_line_down(RoteTerm *rt) { - int i; - rt->crow++; - rt->curpos_dirty = true; - if (rt->crow <= rt->pd->scrollbottom) return; - - /* must scroll the scrolling region up by 1 line, and put cursor on - * last line of it */ - rt->crow = rt->pd->scrollbottom; - - for (i = rt->pd->scrolltop; i < rt->pd->scrollbottom; i++) { - rt->line_dirty[i] = true; - memcpy(rt->cells[i], rt->cells[i+1], sizeof(RoteCell) * rt->cols); - } - - rt->line_dirty[rt->pd->scrollbottom] = true; - - /* clear last row of the scrolling region */ - for (i = 0; i < rt->cols; i++) { - rt->cells[rt->pd->scrollbottom][i].ch = 0x20; - rt->cells[rt->pd->scrollbottom][i].attr = 0x70; - } +static void cursor_line_down(RoteTerm *rt) +{ + int i; + rt->crow++; + rt->curpos_dirty = true; + if (rt->crow <= rt->pd->scrollbottom) return; + + /* must scroll the scrolling region up by 1 line, and put cursor on + * last line of it */ + rt->crow = rt->pd->scrollbottom; + + for (i = rt->pd->scrolltop; i < rt->pd->scrollbottom; i++) { + rt->line_dirty[i] = true; + memcpy(rt->cells[i], rt->cells[i+1], sizeof(RoteCell) * rt->cols); + } + + rt->line_dirty[rt->pd->scrollbottom] = true; + + /* clear last row of the scrolling region */ + for (i = 0; i < rt->cols; i++) { + rt->cells[rt->pd->scrollbottom][i].ch = 0x20; + rt->cells[rt->pd->scrollbottom][i].attr = 0x70; + } } -static void cursor_line_up(RoteTerm *rt) { - int i; - rt->crow--; - rt->curpos_dirty = true; - if (rt->crow >= rt->pd->scrolltop) return; - - /* must scroll the scrolling region up by 1 line, and put cursor on - * first line of it */ - rt->crow = rt->pd->scrolltop; - - for (i = rt->pd->scrollbottom; i > rt->pd->scrolltop; i--) { - rt->line_dirty[i] = true; - memcpy(rt->cells[i], rt->cells[i-1], sizeof(RoteCell) * rt->cols); - } - - rt->line_dirty[rt->pd->scrolltop] = true; - - /* clear first row of the scrolling region */ - for (i = 0; i < rt->cols; i++) { - rt->cells[rt->pd->scrolltop][i].ch = 0x20; - rt->cells[rt->pd->scrolltop][i].attr = 0x70; - } +static void cursor_line_up(RoteTerm *rt) +{ + int i; + rt->crow--; + rt->curpos_dirty = true; + if (rt->crow >= rt->pd->scrolltop) return; + + /* must scroll the scrolling region up by 1 line, and put cursor on + * first line of it */ + rt->crow = rt->pd->scrolltop; + + for (i = rt->pd->scrollbottom; i > rt->pd->scrolltop; i--) { + rt->line_dirty[i] = true; + memcpy(rt->cells[i], rt->cells[i-1], sizeof(RoteCell) * rt->cols); + } + + rt->line_dirty[rt->pd->scrolltop] = true; + + /* clear first row of the scrolling region */ + for (i = 0; i < rt->cols; i++) { + rt->cells[rt->pd->scrolltop][i].ch = 0x20; + rt->cells[rt->pd->scrolltop][i].attr = 0x70; + } } -static inline void put_normal_char(RoteTerm *rt, char c) { - if (rt->ccol >= rt->cols) { - rt->ccol = 0; - cursor_line_down(rt); - } +static inline void put_normal_char(RoteTerm *rt, char c) +{ + if (rt->ccol >= rt->cols) { + rt->ccol = 0; + cursor_line_down(rt); + } - if (rt->insert) { - int i; + if (rt->insert) { + int i; - for(i = rt->cols - 1; i >= rt->ccol+1; i--) - rt->cells[rt->crow][i] = rt->cells[rt->crow][i-1]; - } + for(i = rt->cols - 1; i >= rt->ccol+1; i--) + rt->cells[rt->crow][i] = rt->cells[rt->crow][i-1]; + } - rt->cells[rt->crow][rt->ccol].ch = c; - rt->cells[rt->crow][rt->ccol].attr = rt->curattr; - rt->ccol++; + rt->cells[rt->crow][rt->ccol].ch = c; + rt->cells[rt->crow][rt->ccol].attr = rt->curattr; + rt->ccol++; - rt->line_dirty[rt->crow] = true; - rt->curpos_dirty = true; + rt->line_dirty[rt->crow] = true; + rt->curpos_dirty = true; } -static inline void put_graphmode_char(RoteTerm *rt, char c) { - char nc; - /* do some very pitiful translation to regular ascii chars */ - switch (c) { +static inline void put_graphmode_char(RoteTerm *rt, char c) +{ + char nc; + /* do some very pitiful translation to regular ascii chars */ + switch (c) { case 'j': case 'k': case 'l': case 'm': case 'n': case 't': - case 'u': case 'v': case 'w': - nc = '+'; break; + case 'u': case 'v': case 'w': + nc = '+'; break; case 'x': - nc = '|'; break; + nc = '|'; break; default: - nc = '%'; - } + nc = '%'; + } - put_normal_char(rt, nc); + put_normal_char(rt, nc); } -static inline void new_escape_sequence(RoteTerm *rt) { - rt->pd->escaped = true; - rt->pd->esbuf_len = 0; - rt->pd->esbuf[0] = '\0'; +static inline void new_escape_sequence(RoteTerm *rt) +{ + rt->pd->escaped = true; + rt->pd->esbuf_len = 0; + rt->pd->esbuf[0] = '\0'; } -static inline void cancel_escape_sequence(RoteTerm *rt) { - rt->pd->escaped = false; - rt->pd->esbuf_len = 0; - rt->pd->esbuf[0] = '\0'; +static inline void cancel_escape_sequence(RoteTerm *rt) +{ + rt->pd->escaped = false; + rt->pd->esbuf_len = 0; + rt->pd->esbuf[0] = '\0'; } -static void handle_control_char(RoteTerm *rt, char c) { - switch (c) { +static void handle_control_char(RoteTerm *rt, char c) +{ + switch (c) { case '\r': rt->ccol = 0; break; /* carriage return */ case '\n': /* line feed */ - rt->ccol = 0; cursor_line_down(rt); - rt->curpos_dirty = true; - break; + rt->ccol = 0; cursor_line_down(rt); + rt->curpos_dirty = true; + break; case '\b': /* backspace */ - if (rt->ccol > 0) rt->ccol--; - rt->curpos_dirty = true; - break; + if (rt->ccol > 0) rt->ccol--; + rt->curpos_dirty = true; + break; case '\t': /* tab */ - rt->ccol += 8 - (rt->ccol % 8); - clamp_cursor_to_bounds(rt); - break; + rt->ccol += 8 - (rt->ccol % 8); + clamp_cursor_to_bounds(rt); + break; case '\x1B': /* begin escape sequence (aborting previous one if any) */ - new_escape_sequence(rt); - break; + new_escape_sequence(rt); + break; case '\x0E': /* enter graphical character mode */ - rt->pd->graphmode = true; - break; + rt->pd->graphmode = true; + break; case '\x0F': /* exit graphical character mode */ - rt->pd->graphmode = false; - break; + rt->pd->graphmode = false; + break; case '\x9B': /* CSI character. Equivalent to ESC [ */ - new_escape_sequence(rt); - rt->pd->esbuf[rt->pd->esbuf_len++] = '['; - break; + new_escape_sequence(rt); + rt->pd->esbuf[rt->pd->esbuf_len++] = '['; + break; case '\x18': case '\x1A': /* these interrupt escape sequences */ - cancel_escape_sequence(rt); - break; + cancel_escape_sequence(rt); + break; case '\a': /* bell */ - /* do nothing for now... maybe a visual bell would be nice? */ - break; - #ifdef DEBUG + /* do nothing for now... maybe a visual bell would be nice? */ + break; +#ifdef DEBUG default: - fprintf(stderr, "Unrecognized control char: %d (^%c)\n", c, c + '@'); - break; - #endif - } + fprintf(stderr, "Unrecognized control char: %d (^%c)\n", c, c + '@'); + break; +#endif + } } -static inline bool is_valid_csi_ender(char c) { - return (c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || - c == '@' || c == '`'; +static inline bool is_valid_csi_ender(char c) +{ + return (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + c == '@' || c == '`'; } -static void try_interpret_escape_seq(RoteTerm *rt) { - char firstchar = rt->pd->esbuf[0]; - char lastchar = rt->pd->esbuf[rt->pd->esbuf_len-1]; - - if (!firstchar) return; /* too early to do anything */ - - if (rt->pd->handler) { - /* call custom handler */ - #ifdef DEBUG - fprintf(stderr, "Calling custom handler for ES <%s>.\n", rt->pd->esbuf); - #endif - - int answer = (*(rt->pd->handler))(rt, rt->pd->esbuf); - if (answer == ROTE_HANDLERESULT_OK) { - /* successfully handled */ - #ifdef DEBUG - fprintf(stderr, "Handler returned OK. Done with escape sequence.\n"); - #endif - - cancel_escape_sequence(rt); - return; - } - else if (answer == ROTE_HANDLERESULT_NOTYET) { - /* handler might handle it when more characters are appended to - * it. So for now we don't interpret it */ - #ifdef DEBUG - fprintf(stderr, "Handler returned NOTYET. Waiting for more chars.\n"); - #endif - - return; - } - - /* If we got here then answer == ROTE_HANDLERESULT_NOWAY */ - /* handler said it can't handle that escape sequence, - * but we can still try handling it ourselves, so - * we proceed normally. */ - #ifdef DEBUG - fprintf(stderr, "Handler returned NOWAY. Trying our handlers.\n"); - #endif - } - - /* interpret ESC-M as reverse line-feed */ - if (firstchar == 'M') { - cursor_line_up(rt); - cancel_escape_sequence(rt); - return; - } - - if (firstchar != '[' && firstchar != ']') { - /* unrecognized escape sequence. Let's forget about it. */ - #ifdef DEBUG - fprintf(stderr, "Unrecognized ES: <%s>\n", rt->pd->esbuf); - #endif - - cancel_escape_sequence(rt); - return; - } - - if (firstchar == '[' && is_valid_csi_ender(lastchar)) { - /* we have a csi escape sequence: interpret it */ - rote_es_interpret_csi(rt); - cancel_escape_sequence(rt); - } - else if (firstchar == ']' && lastchar == '\a') { - /* we have an xterm escape sequence: interpret it */ - - /* rote_es_interpret_xterm_es(rt); -- TODO!*/ - #ifdef DEBUG - fprintf(stderr, "Ignored XTerm ES.\n"); - #endif - cancel_escape_sequence(rt); - } - - /* if the escape sequence took up all available space and could - * not yet be parsed, abort it */ - if (rt->pd->esbuf_len + 1 >= ESEQ_BUF_SIZE) cancel_escape_sequence(rt); +static void try_interpret_escape_seq(RoteTerm *rt) +{ + char firstchar = rt->pd->esbuf[0]; + char lastchar = rt->pd->esbuf[rt->pd->esbuf_len-1]; + + if (!firstchar) return; /* too early to do anything */ + + if (rt->pd->handler) { + /* call custom handler */ +#ifdef DEBUG + fprintf(stderr, "Calling custom handler for ES <%s>.\n", rt->pd->esbuf); +#endif + + int answer = (*(rt->pd->handler))(rt, rt->pd->esbuf); + if (answer == ROTE_HANDLERESULT_OK) { + /* successfully handled */ +#ifdef DEBUG + fprintf(stderr, "Handler returned OK. Done with escape sequence.\n"); +#endif + + cancel_escape_sequence(rt); + return; + } + else if (answer == ROTE_HANDLERESULT_NOTYET) { + /* handler might handle it when more characters are appended to + * it. So for now we don't interpret it */ +#ifdef DEBUG + fprintf(stderr, "Handler returned NOTYET. Waiting for more chars.\n"); +#endif + + return; + } + + /* If we got here then answer == ROTE_HANDLERESULT_NOWAY */ + /* handler said it can't handle that escape sequence, + * but we can still try handling it ourselves, so + * we proceed normally. */ +#ifdef DEBUG + fprintf(stderr, "Handler returned NOWAY. Trying our handlers.\n"); +#endif + } + + /* interpret ESC-M as reverse line-feed */ + if (firstchar == 'M') { + cursor_line_up(rt); + cancel_escape_sequence(rt); + return; + } + + if (firstchar != '[' && firstchar != ']') { + /* unrecognized escape sequence. Let's forget about it. */ +#ifdef DEBUG + fprintf(stderr, "Unrecognized ES: <%s>\n", rt->pd->esbuf); +#endif + + cancel_escape_sequence(rt); + return; + } + + if (firstchar == '[' && is_valid_csi_ender(lastchar)) { + /* we have a csi escape sequence: interpret it */ + rote_es_interpret_csi(rt); + cancel_escape_sequence(rt); + } + else if (firstchar == ']' && lastchar == '\a') { + /* we have an xterm escape sequence: interpret it */ + + /* rote_es_interpret_xterm_es(rt); -- TODO!*/ +#ifdef DEBUG + fprintf(stderr, "Ignored XTerm ES.\n"); +#endif + cancel_escape_sequence(rt); + } + + /* if the escape sequence took up all available space and could + * not yet be parsed, abort it */ + if (rt->pd->esbuf_len + 1 >= ESEQ_BUF_SIZE) cancel_escape_sequence(rt); } - -void rote_vt_inject(RoteTerm *rt, const char *data, int len) { - int i; - for (i = 0; i < len; i++, data++) { - if (*data == 0) continue; /* completely ignore NUL */ - if (*data >= 1 && *data <= 31) { - handle_control_char(rt, *data); - continue; - } - - if (rt->pd->escaped && rt->pd->esbuf_len < ESEQ_BUF_SIZE) { - /* append character to ongoing escape sequence */ - rt->pd->esbuf[rt->pd->esbuf_len] = *data; - rt->pd->esbuf[++rt->pd->esbuf_len] = 0; - - try_interpret_escape_seq(rt); - } - else if (rt->pd->graphmode) - put_graphmode_char(rt, *data); - else - put_normal_char(rt, *data); - } + +void rote_vt_inject(RoteTerm *rt, const char *data, int len) +{ + int i; + for (i = 0; i < len; i++, data++) { + if (*data == 0) continue; /* completely ignore NUL */ + if (*data >= 1 && *data <= 31) { + handle_control_char(rt, *data); + continue; + } + + if (rt->pd->escaped && rt->pd->esbuf_len < ESEQ_BUF_SIZE) { + /* append character to ongoing escape sequence */ + rt->pd->esbuf[rt->pd->esbuf_len] = *data; + rt->pd->esbuf[++rt->pd->esbuf_len] = 0; + + try_interpret_escape_seq(rt); + } + else if (rt->pd->graphmode) + put_graphmode_char(rt, *data); + else + put_normal_char(rt, *data); + } } diff --git a/madtty/inject_csi.c b/madtty/inject_csi.c index 4c3a52e..193f1f4 100644 --- a/madtty/inject_csi.c +++ b/madtty/inject_csi.c @@ -27,123 +27,126 @@ #include "roteprivate.h" #define MAX_CSI_ES_PARAMS 32 - + /* interprets a 'set attribute' (SGR) CSI escape sequence */ -static void interpret_csi_SGR(RoteTerm *rt, int param[], int pcount) { - int i; - - if (pcount == 0) { - /* special case: reset attributes */ - rt->curattr = 0x70; - return; - } - - for (i = 0; i < pcount; i++) { - -// From http://vt100.net/docs/vt510-rm/SGR table 5-16 -// 0 All attributes off -// 1 Bold -// 4 Underline -// 5 Blinking -// 7 Negative image -// 8 Invisible image -// 10 The ASCII character set is the current 7-bit -// display character set (default) - SCO Console only. -// 11 Map Hex 00-7F of the PC character set codes -// to the current 7-bit display character set -// - SCO Console only. -// 12 Map Hex 80-FF of the current character set to -// the current 7-bit display character set - SCO -// Console only. -// 22 Bold off -// 24 Underline off -// 25 Blinking off -// 27 Negative image off -// 28 Invisible image off - - if (param[i] == 0) rt->curattr = 0x70; - else if (param[i] == 1 || param[i] == 2 || param[i] == 4) /* set bold */ - ROTE_ATTR_MOD_BOLD(rt->curattr,1); - else if (param[i] == 5) /* set blink */ - ROTE_ATTR_MOD_BLINK(rt->curattr,1); - else if (param[i] == 7 || param[i] == 27) { /* reverse video */ - int fg = ROTE_ATTR_FG(rt->curattr); - int bg = ROTE_ATTR_BG(rt->curattr); - ROTE_ATTR_MOD_FG(rt->curattr, bg); - ROTE_ATTR_MOD_BG(rt->curattr, fg); - } - else if (param[i] == 8) rt->curattr = 0x0; /* invisible */ - else if (param[i] == 22 || param[i] == 24) /* bold off */ - ROTE_ATTR_MOD_BOLD(rt->curattr,0); - else if (param[i] == 25) /* blink off */ - ROTE_ATTR_MOD_BLINK(rt->curattr,0); - else if (param[i] == 28) /* invisible off */ +static void interpret_csi_SGR(RoteTerm *rt, int param[], int pcount) +{ + int i; + + if (pcount == 0) { + /* special case: reset attributes */ rt->curattr = 0x70; - else if (param[i] >= 30 && param[i] <= 37) /* set fg */ - ROTE_ATTR_MOD_FG(rt->curattr, param[i] - 30); - else if (param[i] >= 40 && param[i] <= 47) /* set bg */ - ROTE_ATTR_MOD_BG(rt->curattr, param[i] - 40); - else if (param[i] == 39) /* reset foreground to default */ - ROTE_ATTR_MOD_FG(rt->curattr, 7); - else if (param[i] == 49) /* reset background to default */ - ROTE_ATTR_MOD_BG(rt->curattr, 0); - } + return; + } + + for (i = 0; i < pcount; i++) { + + // From http://vt100.net/docs/vt510-rm/SGR table 5-16 + // 0 All attributes off + // 1 Bold + // 4 Underline + // 5 Blinking + // 7 Negative image + // 8 Invisible image + // 10 The ASCII character set is the current 7-bit + // display character set (default) - SCO Console only. + // 11 Map Hex 00-7F of the PC character set codes + // to the current 7-bit display character set + // - SCO Console only. + // 12 Map Hex 80-FF of the current character set to + // the current 7-bit display character set - SCO + // Console only. + // 22 Bold off + // 24 Underline off + // 25 Blinking off + // 27 Negative image off + // 28 Invisible image off + + if (param[i] == 0) rt->curattr = 0x70; + else if (param[i] == 1 || param[i] == 2 || param[i] == 4) /* set bold */ + ROTE_ATTR_MOD_BOLD(rt->curattr,1); + else if (param[i] == 5) /* set blink */ + ROTE_ATTR_MOD_BLINK(rt->curattr,1); + else if (param[i] == 7 || param[i] == 27) { /* reverse video */ + int fg = ROTE_ATTR_FG(rt->curattr); + int bg = ROTE_ATTR_BG(rt->curattr); + ROTE_ATTR_MOD_FG(rt->curattr, bg); + ROTE_ATTR_MOD_BG(rt->curattr, fg); + } + else if (param[i] == 8) rt->curattr = 0x0; /* invisible */ + else if (param[i] == 22 || param[i] == 24) /* bold off */ + ROTE_ATTR_MOD_BOLD(rt->curattr,0); + else if (param[i] == 25) /* blink off */ + ROTE_ATTR_MOD_BLINK(rt->curattr,0); + else if (param[i] == 28) /* invisible off */ + rt->curattr = 0x70; + else if (param[i] >= 30 && param[i] <= 37) /* set fg */ + ROTE_ATTR_MOD_FG(rt->curattr, param[i] - 30); + else if (param[i] >= 40 && param[i] <= 47) /* set bg */ + ROTE_ATTR_MOD_BG(rt->curattr, param[i] - 40); + else if (param[i] == 39) /* reset foreground to default */ + ROTE_ATTR_MOD_FG(rt->curattr, 7); + else if (param[i] == 49) /* reset background to default */ + ROTE_ATTR_MOD_BG(rt->curattr, 0); + } } /* interprets an 'erase display' (ED) escape sequence */ -static void interpret_csi_ED(RoteTerm *rt, int param[], int pcount) { - int r, c; - int start_row, start_col, end_row, end_col; +static void interpret_csi_ED(RoteTerm *rt, int param[], int pcount) +{ + int r, c; + int start_row, start_col, end_row, end_col; - /* decide range */ - if (pcount && param[0] == 2) - start_row = 0, start_col = 0, end_row = rt->rows - 1, - end_col = rt->cols - 1; + /* decide range */ + if (pcount && param[0] == 2) + start_row = 0, start_col = 0, end_row = rt->rows - 1, + end_col = rt->cols - 1; - else if (pcount && param[0] == 1) - start_row = 0, start_col = 0, end_row = rt->crow, - end_col = rt->ccol; + else if (pcount && param[0] == 1) + start_row = 0, start_col = 0, end_row = rt->crow, + end_col = rt->ccol; - else start_row = rt->crow, start_col = rt->ccol, + else start_row = rt->crow, start_col = rt->ccol, end_row = rt->rows - 1, end_col = rt->cols - 1; - /* clean range */ - for (r = start_row; r <= end_row; r++) { - rt->line_dirty[r] = true; - - for (c = (r == start_row ? start_col : 0); - c <= (r == end_row ? end_col : rt->cols - 1); - c++) { - rt->cells[r][c].ch = 0x20; - rt->cells[r][c].attr = rt->curattr; - } - } + /* clean range */ + for (r = start_row; r <= end_row; r++) { + rt->line_dirty[r] = true; + + for (c = (r == start_row ? start_col : 0); + c <= (r == end_row ? end_col : rt->cols - 1); + c++) { + rt->cells[r][c].ch = 0x20; + rt->cells[r][c].attr = rt->curattr; + } + } } /* interprets a 'move cursor' (CUP) escape sequence */ -static void interpret_csi_CUP(RoteTerm *rt, int param[], int pcount) { - if (pcount == 0) { - /* special case */ - rt->crow = rt->ccol = 0; - return; - } - else if (pcount < 2) return; /* malformed */ +static void interpret_csi_CUP(RoteTerm *rt, int param[], int pcount) +{ + if (pcount == 0) { + /* special case */ + rt->crow = rt->ccol = 0; + return; + } + else if (pcount < 2) return; /* malformed */ - rt->crow = param[0] - 1; /* convert from 1-based to 0-based */ - rt->ccol = param[1] - 1; /* convert from 1-based to 0-based */ + rt->crow = param[0] - 1; /* convert from 1-based to 0-based */ + rt->ccol = param[1] - 1; /* convert from 1-based to 0-based */ - rt->curpos_dirty = true; + rt->curpos_dirty = true; - clamp_cursor_to_bounds(rt); + clamp_cursor_to_bounds(rt); } /* Interpret the 'relative mode' sequences: CUU, CUD, CUF, CUB, CNL, * CPL, CHA, HPR, VPA, VPR, HPA */ static void interpret_csi_C(RoteTerm *rt, char verb, - int param[], int pcount) { - int n = (pcount && param[0] > 0) ? param[0] : 1; + int param[], int pcount) { + int n = (pcount && param[0] > 0) ? param[0] : 1; - switch (verb) { + switch (verb) { case 'A': rt->crow -= n; break; case 'B': case 'e': rt->crow += n; break; case 'C': case 'a': rt->ccol += n; break; @@ -152,215 +155,225 @@ static void interpret_csi_C(RoteTerm *rt, char verb, case 'F': rt->crow -= n; rt->ccol = 0; break; case 'G': case '`': rt->ccol = param[0] - 1; break; case 'd': rt->crow = param[0] - 1; break; - } + } - rt->curpos_dirty = true; - clamp_cursor_to_bounds(rt); + rt->curpos_dirty = true; + clamp_cursor_to_bounds(rt); } /* Interpret the 'erase line' escape sequence */ -static void interpret_csi_EL(RoteTerm *rt, int param[], int pcount) { - int erase_start, erase_end, i; - int cmd = pcount ? param[0] : 0; +static void interpret_csi_EL(RoteTerm *rt, int param[], int pcount) +{ + int erase_start, erase_end, i; + int cmd = pcount ? param[0] : 0; - switch (cmd) { + switch (cmd) { case 1: erase_start = 0; erase_end = rt->ccol; break; case 2: erase_start = 0; erase_end = rt->cols - 1; break; default: erase_start = rt->ccol; erase_end = rt->cols - 1; break; - } + } - for (i = erase_start; i <= erase_end; i++) { - rt->cells[rt->crow][i].ch = 0x20; - rt->cells[rt->crow][i].attr = rt->curattr; - } + for (i = erase_start; i <= erase_end; i++) { + rt->cells[rt->crow][i].ch = 0x20; + rt->cells[rt->crow][i].attr = rt->curattr; + } - rt->line_dirty[rt->crow] = true; + rt->line_dirty[rt->crow] = true; } /* Interpret the 'insert blanks' sequence (ICH) */ -static void interpret_csi_ICH(RoteTerm *rt, int param[], int pcount) { - int n = (pcount && param[0] > 0) ? param[0] : 1; - int i; - for (i = rt->cols - 1; i >= rt->ccol + n; i--) - rt->cells[rt->crow][i] = rt->cells[rt->crow][i - n]; - for (i = rt->ccol; i < rt->ccol + n; i++) { - rt->cells[rt->crow][i].ch = 0x20; - rt->cells[rt->crow][i].attr = rt->curattr; - } - - rt->line_dirty[rt->crow] = true; +static void interpret_csi_ICH(RoteTerm *rt, int param[], int pcount) +{ + int n = (pcount && param[0] > 0) ? param[0] : 1; + int i; + for (i = rt->cols - 1; i >= rt->ccol + n; i--) + rt->cells[rt->crow][i] = rt->cells[rt->crow][i - n]; + for (i = rt->ccol; i < rt->ccol + n; i++) { + rt->cells[rt->crow][i].ch = 0x20; + rt->cells[rt->crow][i].attr = rt->curattr; + } + + rt->line_dirty[rt->crow] = true; } /* Interpret the 'delete chars' sequence (DCH) */ -static void interpret_csi_DCH(RoteTerm *rt, int param[], int pcount) { - int n = (pcount && param[0] > 0) ? param[0] : 1; - int i; - for (i = rt->ccol; i < rt->cols; i++) { - if (i + n < rt->cols) - rt->cells[rt->crow][i] = rt->cells[rt->crow][i + n]; - else { - rt->cells[rt->crow][i].ch = 0x20; - rt->cells[rt->crow][i].attr = rt->curattr; - } - } - - rt->line_dirty[rt->crow] = true; +static void interpret_csi_DCH(RoteTerm *rt, int param[], int pcount) +{ + int n = (pcount && param[0] > 0) ? param[0] : 1; + int i; + for (i = rt->ccol; i < rt->cols; i++) { + if (i + n < rt->cols) + rt->cells[rt->crow][i] = rt->cells[rt->crow][i + n]; + else { + rt->cells[rt->crow][i].ch = 0x20; + rt->cells[rt->crow][i].attr = rt->curattr; + } + } + + rt->line_dirty[rt->crow] = true; } /* Interpret an 'insert line' sequence (IL) */ -static void interpret_csi_IL(RoteTerm *rt, int param[], int pcount) { - int n = (pcount && param[0] > 0) ? param[0] : 1; - int i, j; +static void interpret_csi_IL(RoteTerm *rt, int param[], int pcount) +{ + int n = (pcount && param[0] > 0) ? param[0] : 1; + int i, j; - for (i = rt->pd->scrollbottom; i >= rt->crow + n; i--) - memcpy(rt->cells[i], rt->cells[i - n], sizeof(RoteCell) * rt->cols); + for (i = rt->pd->scrollbottom; i >= rt->crow + n; i--) + memcpy(rt->cells[i], rt->cells[i - n], sizeof(RoteCell) * rt->cols); - for (i = rt->crow; i < rt->crow + n && i <= rt->pd->scrollbottom; i++) { - rt->line_dirty[i] = true; - for (j = 0; j < rt->cols; j++) - rt->cells[i][j].ch = 0x20, rt->cells[i][j].attr = rt->curattr; - } + for (i = rt->crow; i < rt->crow + n && i <= rt->pd->scrollbottom; i++) { + rt->line_dirty[i] = true; + for (j = 0; j < rt->cols; j++) + rt->cells[i][j].ch = 0x20, rt->cells[i][j].attr = rt->curattr; + } } /* Interpret a 'delete line' sequence (DL) */ -static void interpret_csi_DL(RoteTerm *rt, int param[], int pcount) { - int n = (pcount && param[0] > 0) ? param[0] : 1; - int i, j; - - for (i = rt->crow; i <= rt->pd->scrollbottom; i++) { - rt->line_dirty[i] = true; - if (i + n <= rt->pd->scrollbottom) - memcpy(rt->cells[i], rt->cells[i+n], sizeof(RoteCell) * rt->cols); - else { - for (j = 0; j < rt->cols; j++) - rt->cells[i][j].ch = 0x20, rt->cells[i][j].attr = rt->curattr; - } - } +static void interpret_csi_DL(RoteTerm *rt, int param[], int pcount) +{ + int n = (pcount && param[0] > 0) ? param[0] : 1; + int i, j; + + for (i = rt->crow; i <= rt->pd->scrollbottom; i++) { + rt->line_dirty[i] = true; + if (i + n <= rt->pd->scrollbottom) + memcpy(rt->cells[i], rt->cells[i+n], sizeof(RoteCell) * rt->cols); + else { + for (j = 0; j < rt->cols; j++) + rt->cells[i][j].ch = 0x20, rt->cells[i][j].attr = rt->curattr; + } + } } /* Interpret an 'erase characters' (ECH) sequence */ -static void interpret_csi_ECH(RoteTerm *rt, int param[], int pcount) { - int n = (pcount && param[0] > 0) ? param[0] : 1; - int i; +static void interpret_csi_ECH(RoteTerm *rt, int param[], int pcount) +{ + int n = (pcount && param[0] > 0) ? param[0] : 1; + int i; - for (i = rt->ccol; i < rt->ccol + n && i < rt->cols; i++) { - rt->cells[rt->crow][i].ch = 0x20; - rt->cells[rt->crow][i].attr = rt->curattr; - } + for (i = rt->ccol; i < rt->ccol + n && i < rt->cols; i++) { + rt->cells[rt->crow][i].ch = 0x20; + rt->cells[rt->crow][i].attr = rt->curattr; + } - rt->line_dirty[rt->crow] = true; + rt->line_dirty[rt->crow] = true; } - + /* Interpret a 'set scrolling region' (DECSTBM) sequence */ -static void interpret_csi_DECSTBM(RoteTerm *rt, int param[], int pcount) { - int newtop, newbottom; - - if (!pcount) { - newtop = 0; - newbottom = rt->rows - 1; - } - else if (pcount < 2) return; /* malformed */ - else { - newtop = param[0] - 1; - newbottom = param[1] - 1; - } - - /* clamp to bounds */ - if (newtop < 0) newtop = 0; - if (newtop >= rt->rows) newtop = rt->rows - 1; - if (newbottom < 0) newbottom = 0; - if (newbottom >= rt->rows) newbottom = rt->rows - 1; - - /* check for range validity */ - if (newtop > newbottom) return; - rt->pd->scrolltop = newtop; - rt->pd->scrollbottom = newbottom; +static void interpret_csi_DECSTBM(RoteTerm *rt, int param[], int pcount) +{ + int newtop, newbottom; + + if (!pcount) { + newtop = 0; + newbottom = rt->rows - 1; + } + else if (pcount < 2) return; /* malformed */ + else { + newtop = param[0] - 1; + newbottom = param[1] - 1; + } + + /* clamp to bounds */ + if (newtop < 0) newtop = 0; + if (newtop >= rt->rows) newtop = rt->rows - 1; + if (newbottom < 0) newbottom = 0; + if (newbottom >= rt->rows) newbottom = rt->rows - 1; + + /* check for range validity */ + if (newtop > newbottom) return; + rt->pd->scrolltop = newtop; + rt->pd->scrollbottom = newbottom; } - -static void interpret_csi_SAVECUR(RoteTerm *rt, int param[], int pcount) { - rt->pd->saved_x = rt->ccol; - rt->pd->saved_y = rt->crow; + +static void interpret_csi_SAVECUR(RoteTerm *rt, int param[], int pcount) +{ + rt->pd->saved_x = rt->ccol; + rt->pd->saved_y = rt->crow; } -static void interpret_csi_RESTORECUR(RoteTerm *rt, int param[], int pcount) { - rt->ccol = rt->pd->saved_x; - rt->crow = rt->pd->saved_y; - rt->curpos_dirty = true; +static void interpret_csi_RESTORECUR(RoteTerm *rt, int param[], int pcount) +{ + rt->ccol = rt->pd->saved_x; + rt->crow = rt->pd->saved_y; + rt->curpos_dirty = true; } -void rote_es_interpret_csi(RoteTerm *rt) { - static int csiparam[MAX_CSI_ES_PARAMS]; - int param_count = 0; - const char *p = rt->pd->esbuf + 1; - char verb = rt->pd->esbuf[rt->pd->esbuf_len - 1]; - - if (!strncmp(rt->pd->esbuf, "[?", 2)) { /* private-mode CSI, ignore */ - #ifdef DEBUG - fprintf(stderr, "Ignoring private-mode CSI: <%s>\n", rt->pd->esbuf); - #endif - return; - } - - /* parse numeric parameters */ - while ((*p >= '0' && *p <= '9') || *p == ';') { - if (*p == ';') { - if (param_count >= MAX_CSI_ES_PARAMS) return; /* too long! */ - csiparam[param_count++] = 0; - } - else { - if (param_count == 0) csiparam[param_count++] = 0; - csiparam[param_count - 1] *= 10; - csiparam[param_count - 1] += *p - '0'; - } - - p++; - } - - /* delegate handling depending on command character (verb) */ - switch (verb) { +void rote_es_interpret_csi(RoteTerm *rt) +{ + static int csiparam[MAX_CSI_ES_PARAMS]; + int param_count = 0; + const char *p = rt->pd->esbuf + 1; + char verb = rt->pd->esbuf[rt->pd->esbuf_len - 1]; + + if (!strncmp(rt->pd->esbuf, "[?", 2)) { /* private-mode CSI, ignore */ +#ifdef DEBUG + fprintf(stderr, "Ignoring private-mode CSI: <%s>\n", rt->pd->esbuf); +#endif + return; + } + + /* parse numeric parameters */ + while ((*p >= '0' && *p <= '9') || *p == ';') { + if (*p == ';') { + if (param_count >= MAX_CSI_ES_PARAMS) return; /* too long! */ + csiparam[param_count++] = 0; + } + else { + if (param_count == 0) csiparam[param_count++] = 0; + csiparam[param_count - 1] *= 10; + csiparam[param_count - 1] += *p - '0'; + } + + p++; + } + + /* delegate handling depending on command character (verb) */ + switch (verb) { case 'h': - if (param_count == 1 && csiparam[0] == 4) /* insert mode */ - rt->insert = true; - break; + if (param_count == 1 && csiparam[0] == 4) /* insert mode */ + rt->insert = true; + break; case 'l': - if (param_count == 1 && csiparam[0] == 4) /* replace mode */ - rt->insert = false; - break; + if (param_count == 1 && csiparam[0] == 4) /* replace mode */ + rt->insert = false; + break; case 'm': /* it's a 'set attribute' sequence */ - interpret_csi_SGR(rt, csiparam, param_count); break; + interpret_csi_SGR(rt, csiparam, param_count); break; case 'J': /* it's an 'erase display' sequence */ - interpret_csi_ED(rt, csiparam, param_count); break; + interpret_csi_ED(rt, csiparam, param_count); break; case 'H': case 'f': /* it's a 'move cursor' sequence */ - interpret_csi_CUP(rt, csiparam, param_count); break; + interpret_csi_CUP(rt, csiparam, param_count); break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'e': case 'a': case 'd': case '`': - /* it is a 'relative move' */ - interpret_csi_C(rt, verb, csiparam, param_count); break; + /* it is a 'relative move' */ + interpret_csi_C(rt, verb, csiparam, param_count); break; case 'K': /* erase line */ - interpret_csi_EL(rt, csiparam, param_count); break; + interpret_csi_EL(rt, csiparam, param_count); break; case '@': /* insert characters */ - interpret_csi_ICH(rt, csiparam, param_count); break; + interpret_csi_ICH(rt, csiparam, param_count); break; case 'P': /* delete characters */ - interpret_csi_DCH(rt, csiparam, param_count); break; + interpret_csi_DCH(rt, csiparam, param_count); break; case 'L': /* insert lines */ - interpret_csi_IL(rt, csiparam, param_count); break; + interpret_csi_IL(rt, csiparam, param_count); break; case 'M': /* delete lines */ - interpret_csi_DL(rt, csiparam, param_count); break; + interpret_csi_DL(rt, csiparam, param_count); break; case 'X': /* erase chars */ - interpret_csi_ECH(rt, csiparam, param_count); break; + interpret_csi_ECH(rt, csiparam, param_count); break; case 'r': /* set scrolling region */ - interpret_csi_DECSTBM(rt, csiparam, param_count); break; + interpret_csi_DECSTBM(rt, csiparam, param_count); break; case 's': /* save cursor location */ - interpret_csi_SAVECUR(rt, csiparam, param_count); break; + interpret_csi_SAVECUR(rt, csiparam, param_count); break; case 'u': /* restore cursor location */ - interpret_csi_RESTORECUR(rt, csiparam, param_count); break; + interpret_csi_RESTORECUR(rt, csiparam, param_count); break; default: - #ifdef DEBUG - fprintf(stderr, "Unrecogized CSI: verb=%c <%s>\n", - verb, rt->pd->esbuf); - #endif - break; - } +#ifdef DEBUG + fprintf(stderr, "Unrecogized CSI: verb=%c <%s>\n", + verb, rt->pd->esbuf); +#endif + break; + } } diff --git a/madtty/inject_csi.h b/madtty/inject_csi.h index 3759934..5c47efb 100644 --- a/madtty/inject_csi.h +++ b/madtty/inject_csi.h @@ -30,15 +30,16 @@ * related fields in it */ void rote_es_interpret_csi(RoteTerm *rt); -static inline void clamp_cursor_to_bounds(RoteTerm *rt) { - if (rt->crow < 0) rt->curpos_dirty = true, rt->crow = 0; - if (rt->ccol < 0) rt->curpos_dirty = true, rt->ccol = 0; +static inline void clamp_cursor_to_bounds(RoteTerm *rt) +{ + if (rt->crow < 0) rt->curpos_dirty = true, rt->crow = 0; + if (rt->ccol < 0) rt->curpos_dirty = true, rt->ccol = 0; - if (rt->crow >= rt->rows) - rt->curpos_dirty = true, rt->crow = rt->rows - 1; + if (rt->crow >= rt->rows) + rt->curpos_dirty = true, rt->crow = rt->rows - 1; - if (rt->ccol >= rt->cols) - rt->curpos_dirty = true, rt->ccol = rt->cols - 1; + if (rt->ccol >= rt->cols) + rt->curpos_dirty = true, rt->ccol = rt->cols - 1; } #endif diff --git a/madtty/madtty.c b/madtty/madtty.c index 0d1eba6..3121367 100644 --- a/madtty/madtty.c +++ b/madtty/madtty.c @@ -31,232 +31,243 @@ #define ROTE_VT_UPDATE_ITERATIONS 5 -RoteTerm *rote_vt_create(int rows, int cols) { - RoteTerm *rt; - int i, j; - - if (rows <= 0 || cols <= 0) return NULL; - - if (! (rt = (RoteTerm*) malloc(sizeof(RoteTerm))) ) return NULL; - memset(rt, 0, sizeof(RoteTerm)); - - /* record dimensions */ - rt->rows = rows; - rt->cols = cols; - - /* default mode is replace */ - rt->insert = false; - - /* create the cell matrix */ - rt->cells = (RoteCell**) malloc(sizeof(RoteCell*) * rt->rows); - for (i = 0; i < rt->rows; i++) { - /* create row */ - rt->cells[i] = (RoteCell*) malloc(sizeof(RoteCell) * rt->cols); - - /* fill row with spaces */ - for (j = 0; j < rt->cols; j++) { - rt->cells[i][j].ch = 0x20; /* a space */ - rt->cells[i][j].attr = 0x70; /* white text, black background */ - } - } - - /* allocate dirtiness array */ - rt->line_dirty = (bool*) malloc(sizeof(bool) * rt->rows); - - /* initialization of other public fields */ - rt->crow = rt->ccol = 0; - rt->curattr = 0x70; /* white text over black background */ - - /* allocate private data */ - rt->pd = (RoteTermPrivate*) malloc(sizeof(RoteTermPrivate)); - memset(rt->pd, 0, sizeof(RoteTermPrivate)); - - rt->pd->pty = -1; /* no pty for now */ - - /* initial scrolling area is the whole window */ - rt->pd->scrolltop = 0; - rt->pd->scrollbottom = rt->rows - 1; - - #ifdef DEBUG - fprintf(stderr, "Created a %d x %d terminal.\n", rt->rows, rt->cols); - #endif - - return rt; +RoteTerm *rote_vt_create(int rows, int cols) +{ + RoteTerm *rt; + int i, j; + + if (rows <= 0 || cols <= 0) return NULL; + + if (! (rt = (RoteTerm*) malloc(sizeof(RoteTerm))) ) return NULL; + memset(rt, 0, sizeof(RoteTerm)); + + /* record dimensions */ + rt->rows = rows; + rt->cols = cols; + + /* default mode is replace */ + rt->insert = false; + + /* create the cell matrix */ + rt->cells = (RoteCell**) malloc(sizeof(RoteCell*) * rt->rows); + for (i = 0; i < rt->rows; i++) { + /* create row */ + rt->cells[i] = (RoteCell*) malloc(sizeof(RoteCell) * rt->cols); + + /* fill row with spaces */ + for (j = 0; j < rt->cols; j++) { + rt->cells[i][j].ch = 0x20; /* a space */ + rt->cells[i][j].attr = 0x70; /* white text, black background */ + } + } + + /* allocate dirtiness array */ + rt->line_dirty = (bool*) malloc(sizeof(bool) * rt->rows); + + /* initialization of other public fields */ + rt->crow = rt->ccol = 0; + rt->curattr = 0x70; /* white text over black background */ + + /* allocate private data */ + rt->pd = (RoteTermPrivate*) malloc(sizeof(RoteTermPrivate)); + memset(rt->pd, 0, sizeof(RoteTermPrivate)); + + rt->pd->pty = -1; /* no pty for now */ + + /* initial scrolling area is the whole window */ + rt->pd->scrolltop = 0; + rt->pd->scrollbottom = rt->rows - 1; + +#ifdef DEBUG + fprintf(stderr, "Created a %d x %d terminal.\n", rt->rows, rt->cols); +#endif + + return rt; } -void rote_vt_destroy(RoteTerm *rt) { - int i; - if (!rt) return; +void rote_vt_destroy(RoteTerm *rt) +{ + int i; + if (!rt) return; - free(rt->pd); - free(rt->line_dirty); - for (i = 0; i < rt->rows; i++) free(rt->cells[i]); - free(rt->cells); - free(rt); + free(rt->pd); + free(rt->line_dirty); + for (i = 0; i < rt->rows; i++) free(rt->cells[i]); + free(rt->cells); + free(rt); } #ifdef USE_NCURSES -static void default_cur_set_attr(WINDOW *win, unsigned char attr) { - int cp = ROTE_ATTR_BG(attr) * 8 + 7 - ROTE_ATTR_FG(attr); - if (!cp) wattrset(win, A_NORMAL); - else wattrset(win, COLOR_PAIR(cp)); +static void default_cur_set_attr(WINDOW *win, unsigned char attr) +{ + int cp = ROTE_ATTR_BG(attr) * 8 + 7 - ROTE_ATTR_FG(attr); + if (!cp) wattrset(win, A_NORMAL); + else wattrset(win, COLOR_PAIR(cp)); - if (ROTE_ATTR_BOLD(attr)) wattron(win, A_BOLD); - if (ROTE_ATTR_BLINK(attr)) wattron(win, A_BLINK); + if (ROTE_ATTR_BOLD(attr)) wattron(win, A_BOLD); + if (ROTE_ATTR_BLINK(attr)) wattron(win, A_BLINK); } #endif static inline unsigned char ensure_printable(unsigned char ch) - { return ch >= 32 ? ch : 32; } +{ return ch >= 32 ? ch : 32; } #ifdef USE_NCURSES void rote_vt_draw(RoteTerm *rt, WINDOW *win, int srow, int scol, - void (*cur_set_attr)(WINDOW*,unsigned char)) { - - int i, j; - rote_vt_update(rt); - - if (!cur_set_attr) cur_set_attr = default_cur_set_attr; - for (i = 0; i < rt->rows; i++) { - wmove(win, srow + i, scol); - for (j = 0; j < rt->cols; j++) { - (*cur_set_attr)(win, rt->cells[i][j].attr); - waddch(win, ensure_printable(rt->cells[i][j].ch)); - } - } - - wmove(win, srow + rt->crow, scol + rt->ccol); + void (*cur_set_attr)(WINDOW*,unsigned char)) { + + int i, j; + rote_vt_update(rt); + + if (!cur_set_attr) cur_set_attr = default_cur_set_attr; + for (i = 0; i < rt->rows; i++) { + wmove(win, srow + i, scol); + for (j = 0; j < rt->cols; j++) { + (*cur_set_attr)(win, rt->cells[i][j].attr); + waddch(win, ensure_printable(rt->cells[i][j].ch)); + } + } + + wmove(win, srow + rt->crow, scol + rt->ccol); } #endif #ifdef USE_PTY -pid_t rote_vt_forkpty(RoteTerm *rt, const char *command) { - struct winsize ws; - pid_t childpid; - - ws.ws_row = rt->rows; - ws.ws_col = rt->cols; - ws.ws_xpixel = ws.ws_ypixel = 0; +pid_t rote_vt_forkpty(RoteTerm *rt, const char *command) +{ + struct winsize ws; + pid_t childpid; + + ws.ws_row = rt->rows; + ws.ws_col = rt->cols; + ws.ws_xpixel = ws.ws_ypixel = 0; - childpid = forkpty(&rt->pd->pty, NULL, NULL, &ws); - if (childpid < 0) return -1; + childpid = forkpty(&rt->pd->pty, NULL, NULL, &ws); + if (childpid < 0) return -1; - if (childpid == 0) { - /* we are the child, running under the slave side of the pty. */ + if (childpid == 0) { + /* we are the child, running under the slave side of the pty. */ - /* Cajole application into using linux-console-compatible escape - * sequences (which is what we are prepared to interpret) */ - setenv("TERM", "linux", 1); + /* Cajole application into using linux-console-compatible escape + * sequences (which is what we are prepared to interpret) */ + setenv("TERM", "linux", 1); - /* Now we will exec /bin/sh -c command. */ - execl("/bin/sh", "/bin/sh", "-c", command, NULL); + /* Now we will exec /bin/sh -c command. */ + execl("/bin/sh", "/bin/sh", "-c", command, NULL); - fprintf(stderr, "\nexecl() failed.\nCommand: '%s'\n", command); - exit(127); /* error exec'ing */ - } + fprintf(stderr, "\nexecl() failed.\nCommand: '%s'\n", command); + exit(127); /* error exec'ing */ + } - /* if we got here we are the parent process */ - rt->childpid = childpid; - return childpid; + /* if we got here we are the parent process */ + rt->childpid = childpid; + return childpid; } -void rote_vt_forsake_child(RoteTerm *rt) { - if (rt->pd->pty >= 0) close(rt->pd->pty); - rt->pd->pty = -1; - rt->childpid = 0; +void rote_vt_forsake_child(RoteTerm *rt) +{ + if (rt->pd->pty >= 0) close(rt->pd->pty); + rt->pd->pty = -1; + rt->childpid = 0; } #endif -void rote_vt_update(RoteTerm *rt) { - fd_set ifs; - struct timeval tvzero; - char buf[512]; - int bytesread; - int n = ROTE_VT_UPDATE_ITERATIONS; - if (rt->pd->pty < 0) return; /* nothing to pump */ - - while (n--) { /* iterate at most ROVE_VT_UPDATE_ITERATIONS times. - * As Phil Endecott pointed out, if we don't restrict this, - * a program that floods the terminal with output - * could cause this loop to iterate forever, never - * being able to catch up. So we'll rely on the client - * calling rote_vt_update often, as the documentation - * recommends :-) */ - - /* check if pty has something to say */ - FD_ZERO(&ifs); FD_SET(rt->pd->pty, &ifs); - tvzero.tv_sec = 0; tvzero.tv_usec = 0; - - if (select(rt->pd->pty + 1, &ifs, NULL, NULL, &tvzero) <= 0) - return; /* nothing to read, or select() failed */ - - /* read what we can. This is guaranteed not to block, since - * select() told us there was something to read. */ - bytesread = read(rt->pd->pty, buf, 512); - if (bytesread <= 0) return; - - /* inject the data into the terminal */ - rote_vt_inject(rt, buf, bytesread); - } +void rote_vt_update(RoteTerm *rt) +{ + fd_set ifs; + struct timeval tvzero; + char buf[512]; + int bytesread; + int n = ROTE_VT_UPDATE_ITERATIONS; + if (rt->pd->pty < 0) return; /* nothing to pump */ + + while (n--) { /* iterate at most ROVE_VT_UPDATE_ITERATIONS times. + * As Phil Endecott pointed out, if we don't restrict this, + * a program that floods the terminal with output + * could cause this loop to iterate forever, never + * being able to catch up. So we'll rely on the client + * calling rote_vt_update often, as the documentation + * recommends :-) */ + + /* check if pty has something to say */ + FD_ZERO(&ifs); FD_SET(rt->pd->pty, &ifs); + tvzero.tv_sec = 0; tvzero.tv_usec = 0; + + if (select(rt->pd->pty + 1, &ifs, NULL, NULL, &tvzero) <= 0) + return; /* nothing to read, or select() failed */ + + /* read what we can. This is guaranteed not to block, since + * select() told us there was something to read. */ + bytesread = read(rt->pd->pty, buf, 512); + if (bytesread <= 0) return; + + /* inject the data into the terminal */ + rote_vt_inject(rt, buf, bytesread); + } } -void rote_vt_write(RoteTerm *rt, const char *data, int len) { - if (rt->pd->pty < 0) { - /* no pty, so just inject the data plain and simple */ - rote_vt_inject(rt, data, len); - return; - } - - /* write data to pty. Keep calling write() until we have written - * everything. */ - while (len > 0) { - int byteswritten = write(rt->pd->pty, data, len); - if (byteswritten < 0) { - /* very ugly way to inform the error. Improvements welcome! */ - static char errormsg[] = "\n(ROTE: pty write() error)\n"; - rote_vt_inject(rt, errormsg, strlen(errormsg)); - return; - } - - data += byteswritten; - len -= byteswritten; - } +void rote_vt_write(RoteTerm *rt, const char *data, int len) +{ + if (rt->pd->pty < 0) { + /* no pty, so just inject the data plain and simple */ + rote_vt_inject(rt, data, len); + return; + } + + /* write data to pty. Keep calling write() until we have written + * everything. */ + while (len > 0) { + int byteswritten = write(rt->pd->pty, data, len); + if (byteswritten < 0) { + /* very ugly way to inform the error. Improvements welcome! */ + static char errormsg[] = "\n(ROTE: pty write() error)\n"; + rote_vt_inject(rt, errormsg, strlen(errormsg)); + return; + } + + data += byteswritten; + len -= byteswritten; + } } -void rote_vt_install_handler(RoteTerm *rt, rote_es_handler_t handler) { - rt->pd->handler = handler; +void rote_vt_install_handler(RoteTerm *rt, rote_es_handler_t handler) +{ + rt->pd->handler = handler; } -void *rote_vt_take_snapshot(RoteTerm *rt) { - int i; - int bytes_per_row = sizeof(RoteCell) * rt->cols; - void *buf = malloc(bytes_per_row * rt->rows); - void *ptr = buf; +void *rote_vt_take_snapshot(RoteTerm *rt) +{ + int i; + int bytes_per_row = sizeof(RoteCell) * rt->cols; + void *buf = malloc(bytes_per_row * rt->rows); + void *ptr = buf; - for (i = 0; i < rt->rows; i++, ptr += bytes_per_row) - memcpy(ptr, rt->cells[i], bytes_per_row); + for (i = 0; i < rt->rows; i++, ptr += bytes_per_row) + memcpy(ptr, rt->cells[i], bytes_per_row); - return buf; + return buf; } -void rote_vt_restore_snapshot(RoteTerm *rt, void *snapbuf) { - int i; - int bytes_per_row = sizeof(RoteCell) * rt->cols; +void rote_vt_restore_snapshot(RoteTerm *rt, void *snapbuf) +{ + int i; + int bytes_per_row = sizeof(RoteCell) * rt->cols; - for (i = 0; i < rt->rows; i++, snapbuf += bytes_per_row) { - rt->line_dirty[i] = true; - memcpy(rt->cells[i], snapbuf, bytes_per_row); - } + for (i = 0; i < rt->rows; i++, snapbuf += bytes_per_row) { + rt->line_dirty[i] = true; + memcpy(rt->cells[i], snapbuf, bytes_per_row); + } } -int rote_vt_get_pty_fd(RoteTerm *rt) { - return rt->pd->pty; +int rote_vt_get_pty_fd(RoteTerm *rt) +{ + return rt->pd->pty; } static const char *keytable[KEY_MAX+1]; @@ -264,44 +275,46 @@ static int initialized = 0; static void keytable_init(); -void rote_vt_keypress(RoteTerm *rt, int keycode) { - char c = (char) keycode; +void rote_vt_keypress(RoteTerm *rt, int keycode) +{ + char c = (char) keycode; - if (!initialized) keytable_init(); + if (!initialized) keytable_init(); - if (keycode >= 0 && keycode < KEY_MAX && keytable[keycode]) - rote_vt_write(rt, keytable[keycode], strlen(keytable[keycode])); - else - rote_vt_write(rt, &c, 1); /* not special, just write it */ + if (keycode >= 0 && keycode < KEY_MAX && keytable[keycode]) + rote_vt_write(rt, keytable[keycode], strlen(keytable[keycode])); + else + rote_vt_write(rt, &c, 1); /* not special, just write it */ } -static void keytable_init() { - initialized = 1; - memset(keytable, 0, KEY_MAX+1 * sizeof(const char*)); - - keytable['\n'] = "\r"; - keytable[KEY_UP] = "\e[A"; - keytable[KEY_DOWN] = "\e[B"; - keytable[KEY_RIGHT] = "\e[C"; - keytable[KEY_LEFT] = "\e[D"; - keytable[KEY_BACKSPACE] = "\b"; - keytable[KEY_HOME] = "\e[1~"; - keytable[KEY_IC] = "\e[2~"; - keytable[KEY_DC] = "\e[3~"; - keytable[KEY_END] = "\e[4~"; - keytable[KEY_PPAGE] = "\e[5~"; - keytable[KEY_NPAGE] = "\e[6~"; - keytable[KEY_SUSPEND] = "\x1A"; /* Ctrl+Z gets mapped to this */ - keytable[KEY_F(1)] = "\e[[A"; - keytable[KEY_F(2)] = "\e[[B"; - keytable[KEY_F(3)] = "\e[[C"; - keytable[KEY_F(4)] = "\e[[D"; - keytable[KEY_F(5)] = "\e[[E"; - keytable[KEY_F(6)] = "\e[17~"; - keytable[KEY_F(7)] = "\e[18~"; - keytable[KEY_F(8)] = "\e[19~"; - keytable[KEY_F(9)] = "\e[20~"; - keytable[KEY_F(10)] = "\e[21~"; +static void keytable_init() +{ + initialized = 1; + memset(keytable, 0, KEY_MAX+1 * sizeof(const char*)); + + keytable['\n'] = "\r"; + keytable[KEY_UP] = "\e[A"; + keytable[KEY_DOWN] = "\e[B"; + keytable[KEY_RIGHT] = "\e[C"; + keytable[KEY_LEFT] = "\e[D"; + keytable[KEY_BACKSPACE] = "\b"; + keytable[KEY_HOME] = "\e[1~"; + keytable[KEY_IC] = "\e[2~"; + keytable[KEY_DC] = "\e[3~"; + keytable[KEY_END] = "\e[4~"; + keytable[KEY_PPAGE] = "\e[5~"; + keytable[KEY_NPAGE] = "\e[6~"; + keytable[KEY_SUSPEND] = "\x1A"; /* Ctrl+Z gets mapped to this */ + keytable[KEY_F(1)] = "\e[[A"; + keytable[KEY_F(2)] = "\e[[B"; + keytable[KEY_F(3)] = "\e[[C"; + keytable[KEY_F(4)] = "\e[[D"; + keytable[KEY_F(5)] = "\e[[E"; + keytable[KEY_F(6)] = "\e[17~"; + keytable[KEY_F(7)] = "\e[18~"; + keytable[KEY_F(8)] = "\e[19~"; + keytable[KEY_F(9)] = "\e[20~"; + keytable[KEY_F(10)] = "\e[21~"; } diff --git a/madtty/madtty.h b/madtty/madtty.h index cd51378..d14c09e 100644 --- a/madtty/madtty.h +++ b/madtty/madtty.h @@ -74,9 +74,9 @@ #define ROTE_ATTR_MOD_XBG(attr, newxbg) attr &= 0xF0, attr |= (newxbg) #define ROTE_ATTR_MOD_XFG(attr, newxfg) attr &= 0x0F, attr |= ((newxfg) << 4) #define ROTE_ATTR_MOD_BOLD(attr, boldbit) \ - attr &= 0x7F, attr |= (boldbit)?0x80:0x00 + attr &= 0x7F, attr |= (boldbit)?0x80:0x00 #define ROTE_ATTR_MOD_BLINK(attr, blinkbit) \ - attr &= 0xF7, attr |= (blinkbit)?0x08:0x00 + attr &= 0xF7, attr |= (blinkbit)?0x08:0x00 /* these return non-zero for 'yes', zero for 'no'. Don't rely on them being * any more specific than that (e.g. being exactly 1 for 'yes' or whatever). */ @@ -85,10 +85,10 @@ /* Represents each of the text cells in the terminal screen */ typedef struct RoteCell_ { - unsigned char ch; /* >= 32, that is, control characters are not - * allowed to be on the virtual screen */ + unsigned char ch; /* >= 32, that is, control characters are not + * allowed to be on the virtual screen */ - unsigned char attr; /* a color attribute, as described previously */ + unsigned char attr; /* a color attribute, as described previously */ } RoteCell; /* Declaration of opaque rote_Term_Private structure */ @@ -98,38 +98,38 @@ typedef struct RoteTermPrivate_ RoteTermPrivate; * of this structure, but please pay close attention to the fields * marked read-only or with special usage notes. */ typedef struct RoteTerm_ { - int rows, cols; /* terminal dimensions, READ-ONLY. You - * can't resize the terminal by changing - * this (a segfault is about all you will - * accomplish). */ - - RoteCell **cells; /* matrix of cells. This - * matrix is indexed as cell[row][column] - * where 0 <= row < rows and - * 0 <= col < cols - * - * You may freely modify the contents of - * the cells. - */ - - int crow, ccol; /* cursor coordinates. READ-ONLY. */ - - unsigned char curattr; /* current attribute, that is the attribute - * that will be used for newly inserted - * characters */ - - pid_t childpid; /* pid of the child process running in the - * terminal; 0 for none. This is READ-ONLY. */ - - RoteTermPrivate *pd; /* private state data */ - - bool insert; /* insert or replace mode */ - /* --- dirtiness flags: the following flags will be raised when the - * corresponding items are modified. They can only be unset by YOU - * (when, for example, you redraw the term or something) --- */ - bool curpos_dirty; /* whether cursor location has changed */ - bool *line_dirty; /* whether each row is dirty */ - /* --- end dirtiness flags */ + int rows, cols; /* terminal dimensions, READ-ONLY. You + * can't resize the terminal by changing + * this (a segfault is about all you will + * accomplish). */ + + RoteCell **cells; /* matrix of cells. This + * matrix is indexed as cell[row][column] + * where 0 <= row < rows and + * 0 <= col < cols + * + * You may freely modify the contents of + * the cells. + */ + + int crow, ccol; /* cursor coordinates. READ-ONLY. */ + + unsigned char curattr; /* current attribute, that is the attribute + * that will be used for newly inserted + * characters */ + + pid_t childpid; /* pid of the child process running in the + * terminal; 0 for none. This is READ-ONLY. */ + + RoteTermPrivate *pd; /* private state data */ + + bool insert; /* insert or replace mode */ + /* --- dirtiness flags: the following flags will be raised when the + * corresponding items are modified. They can only be unset by YOU + * (when, for example, you redraw the term or something) --- */ + bool curpos_dirty; /* whether cursor location has changed */ + bool *line_dirty; /* whether each row is dirty */ + /* --- end dirtiness flags */ } RoteTerm; /* Creates a new virtual terminal with the given dimensions. You @@ -279,7 +279,7 @@ typedef int (*rote_es_handler_t)(RoteTerm *rt, const char *es); * changed). */ void rote_vt_install_handler(RoteTerm *rt, rote_es_handler_t handler); - + /* Possible return values for the custom handler function and their * meanings: */ #define ROTE_HANDLERESULT_OK 0 /* means escape sequence was handled */ diff --git a/madtty/roteprivate.h b/madtty/roteprivate.h index 90a490d..ab45baf 100644 --- a/madtty/roteprivate.h +++ b/madtty/roteprivate.h @@ -27,25 +27,25 @@ /* Terminal private data */ struct RoteTermPrivate_ { - bool escaped; /* whether we are currently reading an - * escape sequence */ + bool escaped; /* whether we are currently reading an + * escape sequence */ - bool graphmode; /* whether terminal is in graphical - * character mode or not */ + bool graphmode; /* whether terminal is in graphical + * character mode or not */ - int scrolltop, scrollbottom; /* current scrolling region of terminal */ - int saved_x, saved_y; /* saved cursor position */ + int scrolltop, scrollbottom; /* current scrolling region of terminal */ + int saved_x, saved_y; /* saved cursor position */ - char esbuf[ESEQ_BUF_SIZE]; /* 0-terminated string. Does NOT include - * the initial escape (\x1B) character. */ - int esbuf_len; /* length of buffer. The following property - * is always kept: esbuf[esbuf_len] == '\0' */ + char esbuf[ESEQ_BUF_SIZE]; /* 0-terminated string. Does NOT include + * the initial escape (\x1B) character. */ + int esbuf_len; /* length of buffer. The following property + * is always kept: esbuf[esbuf_len] == '\0' */ - int pty; /* file descriptor for the pty attached to - * this terminal. -1 if none. */ + int pty; /* file descriptor for the pty attached to + * this terminal. -1 if none. */ - /* custom escape sequence handler */ - rote_es_handler_t handler; + /* custom escape sequence handler */ + rote_es_handler_t handler; }; #endif -- 2.20.1