X-Git-Url: http://git.madism.org/?a=blobdiff_plain;f=madtty%2Finject.c;h=7334921b0995bbc9efc92d29d7af010959697205;hb=8ead06c97e16165208fd9d02ada73d63aeca11f2;hp=d4b05da0f09dd6710b098fbc6d76e21e7f29db01;hpb=7bbe8b9e43d79660594f369b25a1640799e9612d;p=apps%2Fmadtty.git 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); + } }