diff --git a/fx.term/include/fx/term/tty.h b/fx.term/include/fx/term/tty.h index de88307..594c431 100644 --- a/fx.term/include/fx/term/tty.h +++ b/fx.term/include/fx/term/tty.h @@ -50,6 +50,11 @@ enum { FX_KEY_BACKSPACE, FX_KEY_RETURN, + /* within this range, we further reserve a sub-range. applications can + * define their own special keycode values within this range */ + FX_KEY_RESERVED_START = 0xFFF00, + FX_KEY_RESERVED_END = 0xFFFFD, + FX_MOD_CTRL = 0x10000000, FX_KEY_EOF = 0xFFFFFFFF, @@ -153,6 +158,7 @@ FX_API void fx_tty_set_vmode( struct fx_tty *tty, const struct fx_tty_vmode *vmode); FX_API void fx_tty_reset_vmode(struct fx_tty *tty); +FX_API void fx_tty_flush(struct fx_tty *tty); FX_API enum fx_status fx_tty_get_dimensions( struct fx_tty *tty, diff --git a/fx.term/sys/linux/tty.c b/fx.term/sys/linux/tty.c index 2b08f74..a070bee 100644 --- a/fx.term/sys/linux/tty.c +++ b/fx.term/sys/linux/tty.c @@ -2,6 +2,7 @@ #include "../../tty.h" +#include #include #include #include @@ -103,6 +104,7 @@ static void init_tty(struct fx_tty *tty, FILE *in, FILE *out) tcgetattr(fd, &tty->t_ios_default); memcpy(&tty->t_ios_raw, &tty->t_ios_default, sizeof tty->t_ios_raw); + setvbuf(out, NULL, _IOLBF, 4096); tty->t_ios_raw.c_iflag &= ~(ICRNL | IXON); tty->t_ios_raw.c_oflag &= ~(OPOST); @@ -207,8 +209,14 @@ void fx_tty_reset_vmode(struct fx_tty *tty) tty->t_vmode.v_attrib = FX_TTY_ATTRIB_NORMAL; } +void fx_tty_flush(struct fx_tty *tty) +{ + fflush(tty->t_out); +} + static int compare_colour( - const struct fx_tty_colour *a, const struct fx_tty_colour *b) + const struct fx_tty_colour *a, + const struct fx_tty_colour *b) { if (a->c_mode != b->c_mode) { return -1; @@ -245,7 +253,9 @@ static int compare_colour( return 0; } -static int compare_vmode(const struct fx_tty_vmode *a, const struct fx_tty_vmode *b) +static int compare_vmode( + const struct fx_tty_vmode *a, + const struct fx_tty_vmode *b) { if (a->v_attrib != b->v_attrib) { return -1; @@ -273,45 +283,48 @@ static void put_ansi_attrib(struct fx_tty *tty, const char *s) } static void set_attrib( - struct fx_tty *tty, enum fx_tty_attrib old, enum fx_tty_attrib new) + struct fx_tty *tty, + enum fx_tty_attrib old, + enum fx_tty_attrib new) { if (old == new) { return; } /* Bold ON */ - if (!(old & FX_TTY_ATTRIB_BOLD) && new &FX_TTY_ATTRIB_BOLD) { + if (!(old & FX_TTY_ATTRIB_BOLD) && new & FX_TTY_ATTRIB_BOLD) { put_ansi_attrib(tty, ANSI_BOLD_ON); } /* Bold OFF */ - if (old & FX_TTY_ATTRIB_BOLD && !(new &FX_TTY_ATTRIB_BOLD)) { + if (old & FX_TTY_ATTRIB_BOLD && !(new & FX_TTY_ATTRIB_BOLD)) { put_ansi_attrib(tty, ANSI_BOLD_OFF); } /* Underline ON */ - if (!(old & FX_TTY_ATTRIB_UNDERLINE) && new &FX_TTY_ATTRIB_UNDERLINE) { + if (!(old & FX_TTY_ATTRIB_UNDERLINE) && new & FX_TTY_ATTRIB_UNDERLINE) { put_ansi_attrib(tty, ANSI_UNDERLINE_ON); } /* Underline OFF */ - if (old & FX_TTY_ATTRIB_UNDERLINE && !(new &FX_TTY_ATTRIB_UNDERLINE)) { + if (old & FX_TTY_ATTRIB_UNDERLINE && !(new & FX_TTY_ATTRIB_UNDERLINE)) { put_ansi_attrib(tty, ANSI_UNDERLINE_OFF); } /* Italic ON */ - if (!(old & FX_TTY_ATTRIB_ITALIC) && new &FX_TTY_ATTRIB_ITALIC) { + if (!(old & FX_TTY_ATTRIB_ITALIC) && new & FX_TTY_ATTRIB_ITALIC) { put_ansi_attrib(tty, ANSI_ITALIC_ON); } /* Italic OFF */ - if (old & FX_TTY_ATTRIB_ITALIC && !(new &FX_TTY_ATTRIB_ITALIC)) { + if (old & FX_TTY_ATTRIB_ITALIC && !(new & FX_TTY_ATTRIB_ITALIC)) { put_ansi_attrib(tty, ANSI_ITALIC_OFF); } } static void set_fg( - struct fx_tty *tty, const struct fx_tty_colour *old, + struct fx_tty *tty, + const struct fx_tty_colour *old, const struct fx_tty_colour *new) { if (compare_colour(old, new) == 0) { @@ -347,7 +360,8 @@ static void set_fg( } static void set_bg( - struct fx_tty *tty, const struct fx_tty_colour *old, + struct fx_tty *tty, + const struct fx_tty_colour *old, const struct fx_tty_colour *new) { if (compare_colour(old, new) == 0) { @@ -460,7 +474,10 @@ fx_keycode fx_tty_read_key(struct fx_tty *tty) return c; } -void fx_tty_move_cursor_x(struct fx_tty *tty, enum fx_tty_position_base base, int pos) +void fx_tty_move_cursor_x( + struct fx_tty *tty, + enum fx_tty_position_base base, + int pos) { if (base == FX_TTY_POS_CURSOR && pos < 0 && pos >= -4) { for (int i = 0; i > pos; i--) { @@ -489,7 +506,10 @@ void fx_tty_move_cursor_x(struct fx_tty *tty, enum fx_tty_position_base base, in } } -void fx_tty_move_cursor_y(struct fx_tty *tty, enum fx_tty_position_base base, int pos) +void fx_tty_move_cursor_y( + struct fx_tty *tty, + enum fx_tty_position_base base, + int pos) { if (base == FX_TTY_POS_START) { /* we don't need this functionality right now */ @@ -530,7 +550,9 @@ void fx_tty_clear(struct fx_tty *tty, enum fx_tty_clear_mode mode) } enum fx_status fx_tty_get_dimensions( - struct fx_tty *tty, unsigned int *w, unsigned int *h) + struct fx_tty *tty, + unsigned int *w, + unsigned int *h) { if (!(tty->t_flags & FX_TTY_INTERACTIVE)) { return -1; @@ -552,3 +574,62 @@ enum fx_status fx_tty_get_dimensions( return 0; } + +enum fx_status fx_tty_get_cursor_position( + struct fx_tty *tty, + unsigned int *w, + unsigned int *h) +{ + if (!(tty->t_flags & FX_TTY_INTERACTIVE)) { + return -1; + } + + int in_fd = fileno(tty->t_in); + int out_fd = fileno(tty->t_out); + + write(out_fd, "\x1b[6n", 4); + + char c; + read(in_fd, &c, 1); + read(in_fd, &c, 1); + + char s[16] = {0}; + for (int i = 0; i < sizeof s - 1; i++) { + read(in_fd, &c, 1); + if (!isdigit(c)) { + break; + } + + s[i] = c; + s[i + 1] = 0; + } + + if (w) { + if (s[0]) { + *w = atoi(s); + } else { + *w = 0; + } + } + + s[0] = 0; + for (int i = 0; i < sizeof s - 1; i++) { + read(in_fd, &c, 1); + if (!isdigit(c)) { + break; + } + + s[i] = c; + s[i + 1] = 0; + } + + if (h) { + if (s[0]) { + *h = atoi(s); + } else { + *h = 0; + } + } + + return 0; +}