diff --git a/term/include/blue/term/tty.h b/term/include/blue/term/tty.h index aa4b508..686cda1 100644 --- a/term/include/blue/term/tty.h +++ b/term/include/blue/term/tty.h @@ -1,37 +1,38 @@ #ifndef BLUELIB_TERM_TTY_H_ #define BLUELIB_TERM_TTY_H_ -#include #include -#include +#include +#include #include +#include -#define b_stdtty (z__b_tty_get_std()) -#define b_stderr (z__b_tty_get_err()) +#define b_stdtty (z__b_tty_get_std()) +#define b_stderr (z__b_tty_get_err()) #define B_TTY_CTRL_KEY(c) ((c) | B_MOD_CTRL) -#define B_MAKE_VMODE(fg, bg, a) \ +#define B_MAKE_VMODE(fg, bg, a) \ { \ .v_fg = fg, .v_bg = bg, .v_attrib = (a) \ } -#define B_MAKE_COLOUR_DEFAULT(v) \ +#define B_MAKE_COLOUR_DEFAULT(v) \ { \ .c_mode = TTY_COLOUR_NONE, \ } -#define B_MAKE_COLOUR_16(v) \ +#define B_MAKE_COLOUR_16(v) \ { \ .c_mode = TTY_COLOUR_16, .c_16 = {.value = (v) } \ } -#define B_MAKE_COLOUR_256(v) \ +#define B_MAKE_COLOUR_256(v) \ { \ .c_mode = TTY_COLOUR_256, .c_256 = {.value = (v) } \ } -#define B_MAKE_COLOUR_TRUE(cr, cg, cb) \ +#define B_MAKE_COLOUR_TRUE(cr, cg, cb) \ { \ .c_mode = TTY_COLOUR_TRUE, .c_true \ = {.r = (cr), \ @@ -167,13 +168,13 @@ BLUE_API void b_tty_move_cursor_y( struct b_tty *tty, enum b_tty_position_base base, int pos); BLUE_API void b_tty_clear(struct b_tty *tty, enum b_tty_clear_mode mode); -BLUE_API int b_tty_putc( - struct b_tty *tty, enum b_tty_print_flags flags, char c); +BLUE_API int b_tty_putc(struct b_tty *tty, enum b_tty_print_flags flags, char c); BLUE_API int b_tty_puts( struct b_tty *tty, enum b_tty_print_flags flags, const char *s); BLUE_API int b_tty_printf( struct b_tty *tty, enum b_tty_print_flags flags, const char *s, ...); BLUE_API int b_tty_vprintf( - struct b_tty *tty, enum b_tty_print_flags flags, const char *s, va_list args); + struct b_tty *tty, enum b_tty_print_flags flags, const char *s, + va_list args); -#endif \ No newline at end of file +#endif diff --git a/term/printf.c b/term/printf.c index 8baa9d1..dc18b40 100644 --- a/term/printf.c +++ b/term/printf.c @@ -122,8 +122,7 @@ struct out_tty_args { }; // output function type -typedef void (*out_fct_type)( - char character, struct out_tty_args *args); +typedef void (*out_fct_type)(char character, struct out_tty_args *args); // wrapper (used as buffer) for output function type typedef struct { @@ -149,17 +148,6 @@ static inline void _out_null(char character, void *buffer, size_t idx, size_t ma (void)maxlen; } -// internal _putchar wrapper -static inline void _out_char(char character, void *buffer, size_t idx, size_t maxlen) -{ - (void)buffer; - (void)idx; - (void)maxlen; - if (character) { - _putchar(character); - } -} - // internal output function wrapper static inline void _out_fct(char character, void *buffer, size_t idx, size_t maxlen) { @@ -201,8 +189,8 @@ static unsigned int _atoi(const char **str) // output the specified string in reverse, taking care of any zero-padding static size_t _out_rev( - out_fct_type out, struct out_tty_args *args, - const char *buf, size_t len, unsigned int width, unsigned int flags) + out_fct_type out, struct out_tty_args *args, const char *buf, + size_t len, unsigned int width, unsigned int flags) { size_t idx = 0; @@ -231,9 +219,9 @@ static size_t _out_rev( // internal itoa format static size_t _ntoa_format( - out_fct_type out, struct out_tty_args *args, char *buf, - size_t len, bool negative, unsigned int base, unsigned int prec, - unsigned int width, unsigned int flags) + out_fct_type out, struct out_tty_args *args, char *buf, size_t len, + bool negative, unsigned int base, unsigned int prec, unsigned int width, + unsigned int flags) { // pad leading zeros if (!(flags & FLAGS_LEFT)) { @@ -289,9 +277,9 @@ static size_t _ntoa_format( // internal itoa for 'long' type static size_t _ntoa_long( - out_fct_type out, struct out_tty_args *args, - unsigned long value, bool negative, unsigned long base, - unsigned int prec, unsigned int width, unsigned int flags) + out_fct_type out, struct out_tty_args *args, unsigned long value, + bool negative, unsigned long base, unsigned int prec, + unsigned int width, unsigned int flags) { char buf[PRINTF_NTOA_BUFFER_SIZE]; size_t len = 0U; @@ -314,16 +302,16 @@ static size_t _ntoa_long( } return _ntoa_format( - out, args, buf, len, negative, - (unsigned int)base, prec, width, flags); + out, args, buf, len, negative, (unsigned int)base, prec, width, + flags); } // internal itoa for 'long long' type #if defined(PRINTF_SUPPORT_LONG_LONG) static size_t _ntoa_long_long( - out_fct_type out, struct out_tty_args *args, - unsigned long long value, bool negative, unsigned long long base, - unsigned int prec, unsigned int width, unsigned int flags) + out_fct_type out, struct out_tty_args *args, unsigned long long value, + bool negative, unsigned long long base, unsigned int prec, + unsigned int width, unsigned int flags) { char buf[PRINTF_NTOA_BUFFER_SIZE]; size_t len = 0U; @@ -346,8 +334,8 @@ static size_t _ntoa_long_long( } return _ntoa_format( - out, args, buf, len, negative, - (unsigned int)base, prec, width, flags); + out, args, buf, len, negative, (unsigned int)base, prec, width, + flags); } #endif // PRINTF_SUPPORT_LONG_LONG @@ -381,8 +369,7 @@ static size_t _ftoa( return _out_rev(out, args, "fni-", 4, width, flags); if (value > DBL_MAX) return _out_rev( - out, args, - (flags & FLAGS_PLUS) ? "fni+" : "fni", + out, args, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags); // test for very large values @@ -582,7 +569,9 @@ static size_t _etoa( } // output the floating part - size_t idx = _ftoa(out, args, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP); + size_t idx + = _ftoa(out, args, negative ? -value : value, prec, fwidth, + flags & ~FLAGS_ADAPT_EXP); // output the exponent part if (minwidth) { @@ -590,9 +579,8 @@ static size_t _etoa( out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', args); // output the exponent value idx = _ntoa_long( - out, args, - (expval < 0) ? -expval : expval, expval < 0, 10, 0, - minwidth - 1, FLAGS_ZEROPAD | FLAGS_PLUS); + out, args, (expval < 0) ? -expval : expval, expval < 0, + 10, 0, minwidth - 1, FLAGS_ZEROPAD | FLAGS_PLUS); // might need to right-pad spaces if (flags & FLAGS_LEFT) { while (idx < width) { @@ -606,13 +594,12 @@ static size_t _etoa( #endif // PRINTF_SUPPORT_EXPONENTIAL #endif // PRINTF_SUPPORT_FLOAT -#define set_format_ch(args) ((args)->format_ch = true) +#define set_format_ch(args) ((args)->format_ch = true) #define unset_format_ch(args) ((args)->format_ch = false) // internal vsnprintf static int _vsnprintf( - out_fct_type out, struct out_tty_args *args, const char *format, - va_list va) + out_fct_type out, struct out_tty_args *args, const char *format, va_list va) { unsigned int flags, width, precision, n; size_t idx = 0U; @@ -831,15 +818,14 @@ static int _vsnprintf( const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg( - va, unsigned int) + va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg( - va, unsigned int) + va, unsigned int) : va_arg(va, unsigned int); idx = _ntoa_long( - out, args, value, - false, base, precision, width, - flags); + out, args, value, false, base, + precision, width, flags); } } format++; @@ -850,9 +836,9 @@ static int _vsnprintf( case 'F': if (*format == 'F') flags |= FLAGS_UPPERCASE; - idx = _ftoa( - out, args, va_arg(va, double), - precision, width, flags); + idx + = _ftoa(out, args, va_arg(va, double), + precision, width, flags); format++; break; #if defined(PRINTF_SUPPORT_EXPONENTIAL) @@ -864,9 +850,9 @@ static int _vsnprintf( flags |= FLAGS_ADAPT_EXP; if ((*format == 'E') || (*format == 'G')) flags |= FLAGS_UPPERCASE; - idx = _etoa( - out, args, va_arg(va, double), - precision, width, flags); + idx + = _etoa(out, args, va_arg(va, double), + precision, width, flags); format++; break; #endif // PRINTF_SUPPORT_EXPONENTIAL @@ -926,9 +912,8 @@ static int _vsnprintf( const bool is_ll = sizeof(uintptr_t) == sizeof(long long); if (is_ll) { idx = _ntoa_long_long( - out, args, - (uintptr_t)va_arg(va, void *), false, - 16U, precision, width, flags); + out, args, (uintptr_t)va_arg(va, void *), + false, 16U, precision, width, flags); } else { #endif idx = _ntoa_long( @@ -983,14 +968,15 @@ static void out_tty(char c, struct out_tty_args *args) b_tty_putc(args->tty, flags, c); } -int b_tty_vprintf(struct b_tty *tty, enum b_tty_print_flags flags, const char *format, va_list args) +int b_tty_vprintf( + struct b_tty *tty, enum b_tty_print_flags flags, const char *format, + va_list args) { struct out_tty_args tty_args = { .flags = flags, .tty = tty, }; - const int ret = _vsnprintf( - out_tty, &tty_args, format, args); + const int ret = _vsnprintf(out_tty, &tty_args, format, args); return ret; } diff --git a/term/sys/darwin/tty.c b/term/sys/darwin/tty.c index e2ca52f..b035f62 100644 --- a/term/sys/darwin/tty.c +++ b/term/sys/darwin/tty.c @@ -1,5 +1,6 @@ -#include "../../../line-ed/tty.h" +#include "../../tty.h" +#include #include #include #include @@ -24,67 +25,78 @@ #define ANSI_TRUECOLOUR_BG "48;2" enum tty_flags { - TTY_INIT = 0x01u, - TTY_INTERACTIVE = 0x02u, + B_TTY_INIT = 0x01u, + B_TTY_INTERACTIVE = 0x02u, }; -struct s_tty { +struct b_tty { FILE *t_in, *t_out; enum tty_flags t_flags; struct termios t_ios_raw, t_ios_default; - struct s_tty_vmode t_vmode; + struct b_tty_vmode t_vmode; unsigned char t_mcount; + struct tty_format_buf t_format_buf; }; -static struct s_tty tty = {}; +static struct b_tty std = {0}; +static struct b_tty err = {0}; static const char *ansi_colour16_fg[] = { - [TTY_COLOUR16_BLACK] = "30", - [TTY_COLOUR16_RED] = "31", - [TTY_COLOUR16_GREEN] = "32", - [TTY_COLOUR16_YELLOW] = "33", - [TTY_COLOUR16_BLUE] = "34", - [TTY_COLOUR16_MAGENTA] = "35", - [TTY_COLOUR16_CYAN] = "36", - [TTY_COLOUR16_WHITE] = "37", - [TTY_COLOUR16_GREY] = "90", - [TTY_COLOUR16_BRIGHT_RED] = "91", - [TTY_COLOUR16_BRIGHT_GREEN] = "92", - [TTY_COLOUR16_BRIGHT_YELLOW] = "93", - [TTY_COLOUR16_BRIGHT_BLUE] = "94", - [TTY_COLOUR16_BRIGHT_MAGENTA] = "95", - [TTY_COLOUR16_BRIGHT_CYAN] = "96", - [TTY_COLOUR16_BRIGHT_WHITE] = "97", + [B_TTY_COLOUR16_BLACK] = "30", + [B_TTY_COLOUR16_RED] = "31", + [B_TTY_COLOUR16_GREEN] = "32", + [B_TTY_COLOUR16_YELLOW] = "33", + [B_TTY_COLOUR16_BLUE] = "34", + [B_TTY_COLOUR16_MAGENTA] = "35", + [B_TTY_COLOUR16_CYAN] = "36", + [B_TTY_COLOUR16_WHITE] = "37", + [B_TTY_COLOUR16_BRIGHT_BLACK] = "90", + [B_TTY_COLOUR16_BRIGHT_RED] = "91", + [B_TTY_COLOUR16_BRIGHT_GREEN] = "92", + [B_TTY_COLOUR16_BRIGHT_YELLOW] = "93", + [B_TTY_COLOUR16_BRIGHT_BLUE] = "94", + [B_TTY_COLOUR16_BRIGHT_MAGENTA] = "95", + [B_TTY_COLOUR16_BRIGHT_CYAN] = "96", + [B_TTY_COLOUR16_BRIGHT_WHITE] = "97", }; static const char *ansi_colour16_bg[] = { - [TTY_COLOUR16_BLACK] = "40", - [TTY_COLOUR16_RED] = "41", - [TTY_COLOUR16_GREEN] = "42", - [TTY_COLOUR16_YELLOW] = "43", - [TTY_COLOUR16_BLUE] = "44", - [TTY_COLOUR16_MAGENTA] = "45", - [TTY_COLOUR16_CYAN] = "46", - [TTY_COLOUR16_WHITE] = "47", - [TTY_COLOUR16_GREY] = "100", - [TTY_COLOUR16_BRIGHT_RED] = "101", - [TTY_COLOUR16_BRIGHT_GREEN] = "102", - [TTY_COLOUR16_BRIGHT_YELLOW] = "103", - [TTY_COLOUR16_BRIGHT_BLUE] = "104", - [TTY_COLOUR16_BRIGHT_MAGENTA] = "105", - [TTY_COLOUR16_BRIGHT_CYAN] = "106", - [TTY_COLOUR16_BRIGHT_WHITE] = "107", + [B_TTY_COLOUR16_BLACK] = "40", + [B_TTY_COLOUR16_RED] = "41", + [B_TTY_COLOUR16_GREEN] = "42", + [B_TTY_COLOUR16_YELLOW] = "43", + [B_TTY_COLOUR16_BLUE] = "44", + [B_TTY_COLOUR16_MAGENTA] = "45", + [B_TTY_COLOUR16_CYAN] = "46", + [B_TTY_COLOUR16_WHITE] = "47", + [B_TTY_COLOUR16_BRIGHT_BLACK] = "100", + [B_TTY_COLOUR16_BRIGHT_RED] = "101", + [B_TTY_COLOUR16_BRIGHT_GREEN] = "102", + [B_TTY_COLOUR16_BRIGHT_YELLOW] = "103", + [B_TTY_COLOUR16_BRIGHT_BLUE] = "104", + [B_TTY_COLOUR16_BRIGHT_MAGENTA] = "105", + [B_TTY_COLOUR16_BRIGHT_CYAN] = "106", + [B_TTY_COLOUR16_BRIGHT_WHITE] = "107", }; -static void init_tty(struct s_tty *tty, FILE *in, FILE *out) +static void init_tty(struct b_tty *tty, FILE *in, FILE *out) { tty->t_in = in; tty->t_out = out; - int fd = fileno(in); + int fd = -1; + if (in) { + fd = fileno(in); + } else if (out) { + fd = fileno(out); + } + + if (fd == -1) { + return; + } if (isatty(fd)) { - tty->t_flags |= TTY_INTERACTIVE; + tty->t_flags |= B_TTY_INTERACTIVE; } tcgetattr(fd, &tty->t_ios_default); @@ -94,69 +106,124 @@ static void init_tty(struct s_tty *tty, FILE *in, FILE *out) tty->t_ios_raw.c_oflag &= ~(OPOST); tty->t_ios_raw.c_lflag &= ~(ECHO | ICANON | IEXTEN); - tty->t_flags |= TTY_INIT; + tty->t_flags |= B_TTY_INIT; } -struct s_tty *s_get_tty(void) +struct b_tty *z__b_tty_get_std(void) { - if (!(tty.t_flags & TTY_INIT)) { - init_tty(&tty, stdin, stdout); + if (!(std.t_flags & B_TTY_INIT)) { + init_tty(&std, stdin, stdout); } - return &tty; + return &std; } -bool s_tty_is_interactive(const struct s_tty *tty) +struct b_tty *z__b_tty_get_err(void) { - return (tty->t_flags & TTY_INTERACTIVE) == TTY_INTERACTIVE; + if (!(err.t_flags & B_TTY_INIT)) { + init_tty(&err, NULL, stderr); + } + + return &err; } -void s_tty_set_raw(struct s_tty *tty) +struct tty_format_buf *z__b_tty_get_format_buf(struct b_tty *tty) { - tcsetattr(STDIN_FILENO, TCSAFLUSH, &tty->t_ios_raw); + return &tty->t_format_buf; } -void s_tty_set_canon(struct s_tty *tty) +void z__b_tty_putc(struct b_tty *tty, char c) { - tcsetattr(STDIN_FILENO, TCSAFLUSH, &tty->t_ios_default); + fputc(c, tty->t_out); } -void s_tty_reset_vmode(struct s_tty *tty) +bool b_tty_is_interactive(const struct b_tty *tty) { - if (tty->t_vmode.v_fg.c_mode == TTY_COLOUR_NONE - && tty->t_vmode.v_bg.c_mode == TTY_COLOUR_NONE - && tty->t_vmode.v_attrib == TTY_ATTRIB_NORMAL) { + return (tty->t_flags & B_TTY_INTERACTIVE) == B_TTY_INTERACTIVE; +} + +static void set_raw(struct b_tty *tty) +{ + int fd = -1; + if (tty->t_in) { + fd = fileno(tty->t_in); + } else if (tty->t_out) { + fd = fileno(tty->t_out); + } + + if (fd == -1) { return; } - fprintf(tty->t_out, "\033[0;39;49m"); + tcsetattr(fd, TCSAFLUSH, &tty->t_ios_raw); +} + +static void set_canon(struct b_tty *tty) +{ + int fd = -1; + if (tty->t_in) { + fd = fileno(tty->t_in); + } else if (tty->t_out) { + fd = fileno(tty->t_out); + } + + if (fd == -1) { + return; + } + + tcsetattr(fd, TCSAFLUSH, &tty->t_ios_default); +} + +void b_tty_set_mode(struct b_tty *tty, enum b_tty_mode mode) +{ + switch (mode) { + case B_TTY_CANONICAL: + set_canon(tty); + break; + case B_TTY_RAW: + set_raw(tty); + break; + default: + break; + } +} + +void b_tty_reset_vmode(struct b_tty *tty) +{ + if (tty->t_vmode.v_fg.c_mode == B_TTY_COLOUR_NONE + && tty->t_vmode.v_bg.c_mode == B_TTY_COLOUR_NONE + && tty->t_vmode.v_attrib == B_TTY_ATTRIB_NORMAL) { + return; + } + + fprintf(tty->t_out, "\033[0m"); memset(&tty->t_vmode, 0x0, sizeof tty->t_vmode); - tty->t_vmode.v_fg.c_mode = TTY_COLOUR_NONE; - tty->t_vmode.v_bg.c_mode = TTY_COLOUR_NONE; - tty->t_vmode.v_attrib = TTY_ATTRIB_NORMAL; + tty->t_vmode.v_fg.c_mode = B_TTY_COLOUR_NONE; + tty->t_vmode.v_bg.c_mode = B_TTY_COLOUR_NONE; + tty->t_vmode.v_attrib = B_TTY_ATTRIB_NORMAL; } static int compare_colour( - const struct s_tty_colour *a, const struct s_tty_colour *b) + const struct b_tty_colour *a, const struct b_tty_colour *b) { if (a->c_mode != b->c_mode) { return -1; } switch (a->c_mode) { - case TTY_COLOUR_16: + case B_TTY_COLOUR_16: if (a->c_16.value != b->c_16.value) { return -1; } break; - case TTY_COLOUR_256: + case B_TTY_COLOUR_256: if (a->c_256.value != b->c_256.value) { return -1; } break; - case TTY_COLOUR_TRUE: + case B_TTY_COLOUR_TRUE: if (a->c_true.r != b->c_true.r) { return -1; } @@ -176,7 +243,7 @@ static int compare_colour( return 0; } -static int compare_vmode(const struct s_tty_vmode *a, const struct s_tty_vmode *b) +static int compare_vmode(const struct b_tty_vmode *a, const struct b_tty_vmode *b) { if (a->v_attrib != b->v_attrib) { return -1; @@ -193,7 +260,7 @@ static int compare_vmode(const struct s_tty_vmode *a, const struct s_tty_vmode * return 0; } -static void put_ansi_attrib(struct s_tty *tty, const char *s) +static void put_ansi_attrib(struct b_tty *tty, const char *s) { if (tty->t_mcount > 0) { fputs(";", tty->t_out); @@ -204,46 +271,46 @@ static void put_ansi_attrib(struct s_tty *tty, const char *s) } static void set_attrib( - struct s_tty *tty, enum s_tty_attrib old, enum s_tty_attrib new) + struct b_tty *tty, enum b_tty_attrib old, enum b_tty_attrib new) { if (old == new) { return; } /* Bold ON */ - if (!(old & TTY_ATTRIB_BOLD) && new &TTY_ATTRIB_BOLD) { + if (!(old & B_TTY_ATTRIB_BOLD) && new &B_TTY_ATTRIB_BOLD) { put_ansi_attrib(tty, ANSI_BOLD_ON); } /* Bold OFF */ - if (old & TTY_ATTRIB_BOLD && !(new &TTY_ATTRIB_BOLD)) { + if (old & B_TTY_ATTRIB_BOLD && !(new &B_TTY_ATTRIB_BOLD)) { put_ansi_attrib(tty, ANSI_BOLD_OFF); } /* Underline ON */ - if (!(old & TTY_ATTRIB_UNDERLINE) && new &TTY_ATTRIB_UNDERLINE) { + if (!(old & B_TTY_ATTRIB_UNDERLINE) && new &B_TTY_ATTRIB_UNDERLINE) { put_ansi_attrib(tty, ANSI_UNDERLINE_ON); } /* Underline OFF */ - if (old & TTY_ATTRIB_UNDERLINE && !(new &TTY_ATTRIB_UNDERLINE)) { + if (old & B_TTY_ATTRIB_UNDERLINE && !(new &B_TTY_ATTRIB_UNDERLINE)) { put_ansi_attrib(tty, ANSI_UNDERLINE_OFF); } /* Italic ON */ - if (!(old & TTY_ATTRIB_ITALIC) && new &TTY_ATTRIB_ITALIC) { + if (!(old & B_TTY_ATTRIB_ITALIC) && new &B_TTY_ATTRIB_ITALIC) { put_ansi_attrib(tty, ANSI_ITALIC_ON); } /* Italic OFF */ - if (old & TTY_ATTRIB_ITALIC && !(new &TTY_ATTRIB_ITALIC)) { + if (old & B_TTY_ATTRIB_ITALIC && !(new &B_TTY_ATTRIB_ITALIC)) { put_ansi_attrib(tty, ANSI_ITALIC_OFF); } } static void set_fg( - struct s_tty *tty, const struct s_tty_colour *old, - const struct s_tty_colour *new) + struct b_tty *tty, const struct b_tty_colour *old, + const struct b_tty_colour *new) { if (compare_colour(old, new) == 0) { return; @@ -252,18 +319,18 @@ static void set_fg( char buf[8]; switch (new->c_mode) { - case TTY_COLOUR_NONE: + case B_TTY_COLOUR_NONE: put_ansi_attrib(tty, ANSI_DEFAULTCOLOUR_FG); break; - case TTY_COLOUR_16: + case B_TTY_COLOUR_16: put_ansi_attrib(tty, ansi_colour16_fg[new->c_16.value]); break; - case TTY_COLOUR_256: + case B_TTY_COLOUR_256: put_ansi_attrib(tty, ANSI_256COLOUR_FG); snprintf(buf, sizeof buf, "%u", new->c_256.value); put_ansi_attrib(tty, buf); break; - case TTY_COLOUR_TRUE: + case B_TTY_COLOUR_TRUE: put_ansi_attrib(tty, ANSI_TRUECOLOUR_FG); snprintf(buf, sizeof buf, "%u", new->c_true.r); put_ansi_attrib(tty, buf); @@ -278,8 +345,8 @@ static void set_fg( } static void set_bg( - struct s_tty *tty, const struct s_tty_colour *old, - const struct s_tty_colour *new) + struct b_tty *tty, const struct b_tty_colour *old, + const struct b_tty_colour *new) { if (compare_colour(old, new) == 0) { return; @@ -288,18 +355,18 @@ static void set_bg( char buf[8]; switch (new->c_mode) { - case TTY_COLOUR_NONE: + case B_TTY_COLOUR_NONE: put_ansi_attrib(tty, ANSI_DEFAULTCOLOUR_BG); break; - case TTY_COLOUR_16: + case B_TTY_COLOUR_16: put_ansi_attrib(tty, ansi_colour16_bg[new->c_16.value]); break; - case TTY_COLOUR_256: + case B_TTY_COLOUR_256: put_ansi_attrib(tty, ANSI_256COLOUR_BG); snprintf(buf, sizeof buf, "%u", new->c_256.value); put_ansi_attrib(tty, buf); break; - case TTY_COLOUR_TRUE: + case B_TTY_COLOUR_TRUE: put_ansi_attrib(tty, ANSI_TRUECOLOUR_BG); snprintf(buf, sizeof buf, "%u", new->c_true.r); put_ansi_attrib(tty, buf); @@ -313,7 +380,7 @@ static void set_bg( } } -void s_tty_set_vmode(struct s_tty *tty, const struct s_tty_vmode *vmode) +void b_tty_set_vmode(struct b_tty *tty, const struct b_tty_vmode *vmode) { if (compare_vmode(&tty->t_vmode, vmode) == 0) { return; @@ -332,7 +399,7 @@ void s_tty_set_vmode(struct s_tty *tty, const struct s_tty_vmode *vmode) memcpy(&tty->t_vmode, vmode, sizeof *vmode); } -s_keycode s_tty_read_key(struct s_tty *tty) +b_keycode b_tty_read_key(struct b_tty *tty) { char c; int v; @@ -341,19 +408,19 @@ s_keycode s_tty_read_key(struct s_tty *tty) while (1) { v = read(fd, &c, 1); if (v < 1) { - return S_KEY_EOF; + return B_KEY_EOF; } if (c == '\r' || c == '\n') { - return S_KEY_RETURN; + return B_KEY_RETURN; } if (c == '\b' || c == 0x7F) { - return S_KEY_BACKSPACE; + return B_KEY_BACKSPACE; } if (c >= 1 && c <= 26) { - return S_TTY_CTRL_KEY(c + 'a' - 1); + return B_TTY_CTRL_KEY(c + 'a' - 1); } if (c != 0x1b) { @@ -362,7 +429,7 @@ s_keycode s_tty_read_key(struct s_tty *tty) v = read(fd, &c, 1); if (v < 1) { - return S_KEY_EOF; + return B_KEY_EOF; } if (c != '[') { @@ -371,18 +438,18 @@ s_keycode s_tty_read_key(struct s_tty *tty) v = read(fd, &c, 1); if (v < 1) { - return S_KEY_EOF; + return B_KEY_EOF; } switch (c) { case 'A': - return S_KEY_ARROW_UP; + return B_KEY_ARROW_UP; case 'B': - return S_KEY_ARROW_DOWN; + return B_KEY_ARROW_DOWN; case 'C': - return S_KEY_ARROW_RIGHT; + return B_KEY_ARROW_RIGHT; case 'D': - return S_KEY_ARROW_LEFT; + return B_KEY_ARROW_LEFT; default: continue; } @@ -391,9 +458,9 @@ s_keycode s_tty_read_key(struct s_tty *tty) return c; } -void s_tty_move_cursor_x(struct s_tty *tty, enum s_tty_position_base base, int pos) +void b_tty_move_cursor_x(struct b_tty *tty, enum b_tty_position_base base, int pos) { - if (base == TTY_POS_CURSOR && pos < 0 && pos >= -4) { + if (base == B_TTY_POS_CURSOR && pos < 0 && pos >= -4) { for (int i = 0; i > pos; i--) { fputc('\b', tty->t_out); } @@ -401,7 +468,7 @@ void s_tty_move_cursor_x(struct s_tty *tty, enum s_tty_position_base base, int p return; } - if (base == TTY_POS_START) { + if (base == B_TTY_POS_START) { if (pos == 0) { fputs("\033[G", tty->t_out); } else { @@ -420,9 +487,9 @@ void s_tty_move_cursor_x(struct s_tty *tty, enum s_tty_position_base base, int p } } -void s_tty_move_cursor_y(struct s_tty *tty, enum s_tty_position_base base, int pos) +void b_tty_move_cursor_y(struct b_tty *tty, enum b_tty_position_base base, int pos) { - if (base == TTY_POS_START) { + if (base == B_TTY_POS_START) { /* we don't need this functionality right now */ abort(); } @@ -438,24 +505,48 @@ void s_tty_move_cursor_y(struct s_tty *tty, enum s_tty_position_base base, int p } } -void s_tty_clear(struct s_tty *tty, enum s_tty_clear_mode mode) +void b_tty_clear(struct b_tty *tty, enum b_tty_clear_mode mode) { const char *arg; - if (mode & TTY_CLEAR_ALL) { + if (mode & B_TTY_CLEAR_ALL) { arg = "2"; - } else if (mode & TTY_CLEAR_TO_CURSOR) { + } else if (mode & B_TTY_CLEAR_TO_CURSOR) { arg = "1"; - } else if (mode & TTY_CLEAR_FROM_CURSOR) { + } else if (mode & B_TTY_CLEAR_FROM_CURSOR) { arg = ""; } else { abort(); } - if (mode & TTY_CLEAR_SCREEN) { + if (mode & B_TTY_CLEAR_SCREEN) { fprintf(tty->t_out, "\033[%sJ", arg); - } else if (mode & TTY_CLEAR_LINE) { + } else if (mode & B_TTY_CLEAR_LINE) { fprintf(tty->t_out, "\033[%sK", arg); } else { abort(); } } + +enum b_status b_tty_get_dimensions( + struct b_tty *tty, unsigned int *w, unsigned int *h) +{ + if (!(tty->t_flags & B_TTY_INTERACTIVE)) { + return -1; + } + + int fd = fileno(tty->t_out); + struct winsize ws; + if (ioctl(fd, TIOCGWINSZ, &ws) == -1) { + return -1; + } + + if (w) { + *w = ws.ws_col; + } + + if (h) { + *h = ws.ws_row; + } + + return 0; +} diff --git a/term/sys/linux/tty.c b/term/sys/linux/tty.c index e2ca52f..b035f62 100644 --- a/term/sys/linux/tty.c +++ b/term/sys/linux/tty.c @@ -1,5 +1,6 @@ -#include "../../../line-ed/tty.h" +#include "../../tty.h" +#include #include #include #include @@ -24,67 +25,78 @@ #define ANSI_TRUECOLOUR_BG "48;2" enum tty_flags { - TTY_INIT = 0x01u, - TTY_INTERACTIVE = 0x02u, + B_TTY_INIT = 0x01u, + B_TTY_INTERACTIVE = 0x02u, }; -struct s_tty { +struct b_tty { FILE *t_in, *t_out; enum tty_flags t_flags; struct termios t_ios_raw, t_ios_default; - struct s_tty_vmode t_vmode; + struct b_tty_vmode t_vmode; unsigned char t_mcount; + struct tty_format_buf t_format_buf; }; -static struct s_tty tty = {}; +static struct b_tty std = {0}; +static struct b_tty err = {0}; static const char *ansi_colour16_fg[] = { - [TTY_COLOUR16_BLACK] = "30", - [TTY_COLOUR16_RED] = "31", - [TTY_COLOUR16_GREEN] = "32", - [TTY_COLOUR16_YELLOW] = "33", - [TTY_COLOUR16_BLUE] = "34", - [TTY_COLOUR16_MAGENTA] = "35", - [TTY_COLOUR16_CYAN] = "36", - [TTY_COLOUR16_WHITE] = "37", - [TTY_COLOUR16_GREY] = "90", - [TTY_COLOUR16_BRIGHT_RED] = "91", - [TTY_COLOUR16_BRIGHT_GREEN] = "92", - [TTY_COLOUR16_BRIGHT_YELLOW] = "93", - [TTY_COLOUR16_BRIGHT_BLUE] = "94", - [TTY_COLOUR16_BRIGHT_MAGENTA] = "95", - [TTY_COLOUR16_BRIGHT_CYAN] = "96", - [TTY_COLOUR16_BRIGHT_WHITE] = "97", + [B_TTY_COLOUR16_BLACK] = "30", + [B_TTY_COLOUR16_RED] = "31", + [B_TTY_COLOUR16_GREEN] = "32", + [B_TTY_COLOUR16_YELLOW] = "33", + [B_TTY_COLOUR16_BLUE] = "34", + [B_TTY_COLOUR16_MAGENTA] = "35", + [B_TTY_COLOUR16_CYAN] = "36", + [B_TTY_COLOUR16_WHITE] = "37", + [B_TTY_COLOUR16_BRIGHT_BLACK] = "90", + [B_TTY_COLOUR16_BRIGHT_RED] = "91", + [B_TTY_COLOUR16_BRIGHT_GREEN] = "92", + [B_TTY_COLOUR16_BRIGHT_YELLOW] = "93", + [B_TTY_COLOUR16_BRIGHT_BLUE] = "94", + [B_TTY_COLOUR16_BRIGHT_MAGENTA] = "95", + [B_TTY_COLOUR16_BRIGHT_CYAN] = "96", + [B_TTY_COLOUR16_BRIGHT_WHITE] = "97", }; static const char *ansi_colour16_bg[] = { - [TTY_COLOUR16_BLACK] = "40", - [TTY_COLOUR16_RED] = "41", - [TTY_COLOUR16_GREEN] = "42", - [TTY_COLOUR16_YELLOW] = "43", - [TTY_COLOUR16_BLUE] = "44", - [TTY_COLOUR16_MAGENTA] = "45", - [TTY_COLOUR16_CYAN] = "46", - [TTY_COLOUR16_WHITE] = "47", - [TTY_COLOUR16_GREY] = "100", - [TTY_COLOUR16_BRIGHT_RED] = "101", - [TTY_COLOUR16_BRIGHT_GREEN] = "102", - [TTY_COLOUR16_BRIGHT_YELLOW] = "103", - [TTY_COLOUR16_BRIGHT_BLUE] = "104", - [TTY_COLOUR16_BRIGHT_MAGENTA] = "105", - [TTY_COLOUR16_BRIGHT_CYAN] = "106", - [TTY_COLOUR16_BRIGHT_WHITE] = "107", + [B_TTY_COLOUR16_BLACK] = "40", + [B_TTY_COLOUR16_RED] = "41", + [B_TTY_COLOUR16_GREEN] = "42", + [B_TTY_COLOUR16_YELLOW] = "43", + [B_TTY_COLOUR16_BLUE] = "44", + [B_TTY_COLOUR16_MAGENTA] = "45", + [B_TTY_COLOUR16_CYAN] = "46", + [B_TTY_COLOUR16_WHITE] = "47", + [B_TTY_COLOUR16_BRIGHT_BLACK] = "100", + [B_TTY_COLOUR16_BRIGHT_RED] = "101", + [B_TTY_COLOUR16_BRIGHT_GREEN] = "102", + [B_TTY_COLOUR16_BRIGHT_YELLOW] = "103", + [B_TTY_COLOUR16_BRIGHT_BLUE] = "104", + [B_TTY_COLOUR16_BRIGHT_MAGENTA] = "105", + [B_TTY_COLOUR16_BRIGHT_CYAN] = "106", + [B_TTY_COLOUR16_BRIGHT_WHITE] = "107", }; -static void init_tty(struct s_tty *tty, FILE *in, FILE *out) +static void init_tty(struct b_tty *tty, FILE *in, FILE *out) { tty->t_in = in; tty->t_out = out; - int fd = fileno(in); + int fd = -1; + if (in) { + fd = fileno(in); + } else if (out) { + fd = fileno(out); + } + + if (fd == -1) { + return; + } if (isatty(fd)) { - tty->t_flags |= TTY_INTERACTIVE; + tty->t_flags |= B_TTY_INTERACTIVE; } tcgetattr(fd, &tty->t_ios_default); @@ -94,69 +106,124 @@ static void init_tty(struct s_tty *tty, FILE *in, FILE *out) tty->t_ios_raw.c_oflag &= ~(OPOST); tty->t_ios_raw.c_lflag &= ~(ECHO | ICANON | IEXTEN); - tty->t_flags |= TTY_INIT; + tty->t_flags |= B_TTY_INIT; } -struct s_tty *s_get_tty(void) +struct b_tty *z__b_tty_get_std(void) { - if (!(tty.t_flags & TTY_INIT)) { - init_tty(&tty, stdin, stdout); + if (!(std.t_flags & B_TTY_INIT)) { + init_tty(&std, stdin, stdout); } - return &tty; + return &std; } -bool s_tty_is_interactive(const struct s_tty *tty) +struct b_tty *z__b_tty_get_err(void) { - return (tty->t_flags & TTY_INTERACTIVE) == TTY_INTERACTIVE; + if (!(err.t_flags & B_TTY_INIT)) { + init_tty(&err, NULL, stderr); + } + + return &err; } -void s_tty_set_raw(struct s_tty *tty) +struct tty_format_buf *z__b_tty_get_format_buf(struct b_tty *tty) { - tcsetattr(STDIN_FILENO, TCSAFLUSH, &tty->t_ios_raw); + return &tty->t_format_buf; } -void s_tty_set_canon(struct s_tty *tty) +void z__b_tty_putc(struct b_tty *tty, char c) { - tcsetattr(STDIN_FILENO, TCSAFLUSH, &tty->t_ios_default); + fputc(c, tty->t_out); } -void s_tty_reset_vmode(struct s_tty *tty) +bool b_tty_is_interactive(const struct b_tty *tty) { - if (tty->t_vmode.v_fg.c_mode == TTY_COLOUR_NONE - && tty->t_vmode.v_bg.c_mode == TTY_COLOUR_NONE - && tty->t_vmode.v_attrib == TTY_ATTRIB_NORMAL) { + return (tty->t_flags & B_TTY_INTERACTIVE) == B_TTY_INTERACTIVE; +} + +static void set_raw(struct b_tty *tty) +{ + int fd = -1; + if (tty->t_in) { + fd = fileno(tty->t_in); + } else if (tty->t_out) { + fd = fileno(tty->t_out); + } + + if (fd == -1) { return; } - fprintf(tty->t_out, "\033[0;39;49m"); + tcsetattr(fd, TCSAFLUSH, &tty->t_ios_raw); +} + +static void set_canon(struct b_tty *tty) +{ + int fd = -1; + if (tty->t_in) { + fd = fileno(tty->t_in); + } else if (tty->t_out) { + fd = fileno(tty->t_out); + } + + if (fd == -1) { + return; + } + + tcsetattr(fd, TCSAFLUSH, &tty->t_ios_default); +} + +void b_tty_set_mode(struct b_tty *tty, enum b_tty_mode mode) +{ + switch (mode) { + case B_TTY_CANONICAL: + set_canon(tty); + break; + case B_TTY_RAW: + set_raw(tty); + break; + default: + break; + } +} + +void b_tty_reset_vmode(struct b_tty *tty) +{ + if (tty->t_vmode.v_fg.c_mode == B_TTY_COLOUR_NONE + && tty->t_vmode.v_bg.c_mode == B_TTY_COLOUR_NONE + && tty->t_vmode.v_attrib == B_TTY_ATTRIB_NORMAL) { + return; + } + + fprintf(tty->t_out, "\033[0m"); memset(&tty->t_vmode, 0x0, sizeof tty->t_vmode); - tty->t_vmode.v_fg.c_mode = TTY_COLOUR_NONE; - tty->t_vmode.v_bg.c_mode = TTY_COLOUR_NONE; - tty->t_vmode.v_attrib = TTY_ATTRIB_NORMAL; + tty->t_vmode.v_fg.c_mode = B_TTY_COLOUR_NONE; + tty->t_vmode.v_bg.c_mode = B_TTY_COLOUR_NONE; + tty->t_vmode.v_attrib = B_TTY_ATTRIB_NORMAL; } static int compare_colour( - const struct s_tty_colour *a, const struct s_tty_colour *b) + const struct b_tty_colour *a, const struct b_tty_colour *b) { if (a->c_mode != b->c_mode) { return -1; } switch (a->c_mode) { - case TTY_COLOUR_16: + case B_TTY_COLOUR_16: if (a->c_16.value != b->c_16.value) { return -1; } break; - case TTY_COLOUR_256: + case B_TTY_COLOUR_256: if (a->c_256.value != b->c_256.value) { return -1; } break; - case TTY_COLOUR_TRUE: + case B_TTY_COLOUR_TRUE: if (a->c_true.r != b->c_true.r) { return -1; } @@ -176,7 +243,7 @@ static int compare_colour( return 0; } -static int compare_vmode(const struct s_tty_vmode *a, const struct s_tty_vmode *b) +static int compare_vmode(const struct b_tty_vmode *a, const struct b_tty_vmode *b) { if (a->v_attrib != b->v_attrib) { return -1; @@ -193,7 +260,7 @@ static int compare_vmode(const struct s_tty_vmode *a, const struct s_tty_vmode * return 0; } -static void put_ansi_attrib(struct s_tty *tty, const char *s) +static void put_ansi_attrib(struct b_tty *tty, const char *s) { if (tty->t_mcount > 0) { fputs(";", tty->t_out); @@ -204,46 +271,46 @@ static void put_ansi_attrib(struct s_tty *tty, const char *s) } static void set_attrib( - struct s_tty *tty, enum s_tty_attrib old, enum s_tty_attrib new) + struct b_tty *tty, enum b_tty_attrib old, enum b_tty_attrib new) { if (old == new) { return; } /* Bold ON */ - if (!(old & TTY_ATTRIB_BOLD) && new &TTY_ATTRIB_BOLD) { + if (!(old & B_TTY_ATTRIB_BOLD) && new &B_TTY_ATTRIB_BOLD) { put_ansi_attrib(tty, ANSI_BOLD_ON); } /* Bold OFF */ - if (old & TTY_ATTRIB_BOLD && !(new &TTY_ATTRIB_BOLD)) { + if (old & B_TTY_ATTRIB_BOLD && !(new &B_TTY_ATTRIB_BOLD)) { put_ansi_attrib(tty, ANSI_BOLD_OFF); } /* Underline ON */ - if (!(old & TTY_ATTRIB_UNDERLINE) && new &TTY_ATTRIB_UNDERLINE) { + if (!(old & B_TTY_ATTRIB_UNDERLINE) && new &B_TTY_ATTRIB_UNDERLINE) { put_ansi_attrib(tty, ANSI_UNDERLINE_ON); } /* Underline OFF */ - if (old & TTY_ATTRIB_UNDERLINE && !(new &TTY_ATTRIB_UNDERLINE)) { + if (old & B_TTY_ATTRIB_UNDERLINE && !(new &B_TTY_ATTRIB_UNDERLINE)) { put_ansi_attrib(tty, ANSI_UNDERLINE_OFF); } /* Italic ON */ - if (!(old & TTY_ATTRIB_ITALIC) && new &TTY_ATTRIB_ITALIC) { + if (!(old & B_TTY_ATTRIB_ITALIC) && new &B_TTY_ATTRIB_ITALIC) { put_ansi_attrib(tty, ANSI_ITALIC_ON); } /* Italic OFF */ - if (old & TTY_ATTRIB_ITALIC && !(new &TTY_ATTRIB_ITALIC)) { + if (old & B_TTY_ATTRIB_ITALIC && !(new &B_TTY_ATTRIB_ITALIC)) { put_ansi_attrib(tty, ANSI_ITALIC_OFF); } } static void set_fg( - struct s_tty *tty, const struct s_tty_colour *old, - const struct s_tty_colour *new) + struct b_tty *tty, const struct b_tty_colour *old, + const struct b_tty_colour *new) { if (compare_colour(old, new) == 0) { return; @@ -252,18 +319,18 @@ static void set_fg( char buf[8]; switch (new->c_mode) { - case TTY_COLOUR_NONE: + case B_TTY_COLOUR_NONE: put_ansi_attrib(tty, ANSI_DEFAULTCOLOUR_FG); break; - case TTY_COLOUR_16: + case B_TTY_COLOUR_16: put_ansi_attrib(tty, ansi_colour16_fg[new->c_16.value]); break; - case TTY_COLOUR_256: + case B_TTY_COLOUR_256: put_ansi_attrib(tty, ANSI_256COLOUR_FG); snprintf(buf, sizeof buf, "%u", new->c_256.value); put_ansi_attrib(tty, buf); break; - case TTY_COLOUR_TRUE: + case B_TTY_COLOUR_TRUE: put_ansi_attrib(tty, ANSI_TRUECOLOUR_FG); snprintf(buf, sizeof buf, "%u", new->c_true.r); put_ansi_attrib(tty, buf); @@ -278,8 +345,8 @@ static void set_fg( } static void set_bg( - struct s_tty *tty, const struct s_tty_colour *old, - const struct s_tty_colour *new) + struct b_tty *tty, const struct b_tty_colour *old, + const struct b_tty_colour *new) { if (compare_colour(old, new) == 0) { return; @@ -288,18 +355,18 @@ static void set_bg( char buf[8]; switch (new->c_mode) { - case TTY_COLOUR_NONE: + case B_TTY_COLOUR_NONE: put_ansi_attrib(tty, ANSI_DEFAULTCOLOUR_BG); break; - case TTY_COLOUR_16: + case B_TTY_COLOUR_16: put_ansi_attrib(tty, ansi_colour16_bg[new->c_16.value]); break; - case TTY_COLOUR_256: + case B_TTY_COLOUR_256: put_ansi_attrib(tty, ANSI_256COLOUR_BG); snprintf(buf, sizeof buf, "%u", new->c_256.value); put_ansi_attrib(tty, buf); break; - case TTY_COLOUR_TRUE: + case B_TTY_COLOUR_TRUE: put_ansi_attrib(tty, ANSI_TRUECOLOUR_BG); snprintf(buf, sizeof buf, "%u", new->c_true.r); put_ansi_attrib(tty, buf); @@ -313,7 +380,7 @@ static void set_bg( } } -void s_tty_set_vmode(struct s_tty *tty, const struct s_tty_vmode *vmode) +void b_tty_set_vmode(struct b_tty *tty, const struct b_tty_vmode *vmode) { if (compare_vmode(&tty->t_vmode, vmode) == 0) { return; @@ -332,7 +399,7 @@ void s_tty_set_vmode(struct s_tty *tty, const struct s_tty_vmode *vmode) memcpy(&tty->t_vmode, vmode, sizeof *vmode); } -s_keycode s_tty_read_key(struct s_tty *tty) +b_keycode b_tty_read_key(struct b_tty *tty) { char c; int v; @@ -341,19 +408,19 @@ s_keycode s_tty_read_key(struct s_tty *tty) while (1) { v = read(fd, &c, 1); if (v < 1) { - return S_KEY_EOF; + return B_KEY_EOF; } if (c == '\r' || c == '\n') { - return S_KEY_RETURN; + return B_KEY_RETURN; } if (c == '\b' || c == 0x7F) { - return S_KEY_BACKSPACE; + return B_KEY_BACKSPACE; } if (c >= 1 && c <= 26) { - return S_TTY_CTRL_KEY(c + 'a' - 1); + return B_TTY_CTRL_KEY(c + 'a' - 1); } if (c != 0x1b) { @@ -362,7 +429,7 @@ s_keycode s_tty_read_key(struct s_tty *tty) v = read(fd, &c, 1); if (v < 1) { - return S_KEY_EOF; + return B_KEY_EOF; } if (c != '[') { @@ -371,18 +438,18 @@ s_keycode s_tty_read_key(struct s_tty *tty) v = read(fd, &c, 1); if (v < 1) { - return S_KEY_EOF; + return B_KEY_EOF; } switch (c) { case 'A': - return S_KEY_ARROW_UP; + return B_KEY_ARROW_UP; case 'B': - return S_KEY_ARROW_DOWN; + return B_KEY_ARROW_DOWN; case 'C': - return S_KEY_ARROW_RIGHT; + return B_KEY_ARROW_RIGHT; case 'D': - return S_KEY_ARROW_LEFT; + return B_KEY_ARROW_LEFT; default: continue; } @@ -391,9 +458,9 @@ s_keycode s_tty_read_key(struct s_tty *tty) return c; } -void s_tty_move_cursor_x(struct s_tty *tty, enum s_tty_position_base base, int pos) +void b_tty_move_cursor_x(struct b_tty *tty, enum b_tty_position_base base, int pos) { - if (base == TTY_POS_CURSOR && pos < 0 && pos >= -4) { + if (base == B_TTY_POS_CURSOR && pos < 0 && pos >= -4) { for (int i = 0; i > pos; i--) { fputc('\b', tty->t_out); } @@ -401,7 +468,7 @@ void s_tty_move_cursor_x(struct s_tty *tty, enum s_tty_position_base base, int p return; } - if (base == TTY_POS_START) { + if (base == B_TTY_POS_START) { if (pos == 0) { fputs("\033[G", tty->t_out); } else { @@ -420,9 +487,9 @@ void s_tty_move_cursor_x(struct s_tty *tty, enum s_tty_position_base base, int p } } -void s_tty_move_cursor_y(struct s_tty *tty, enum s_tty_position_base base, int pos) +void b_tty_move_cursor_y(struct b_tty *tty, enum b_tty_position_base base, int pos) { - if (base == TTY_POS_START) { + if (base == B_TTY_POS_START) { /* we don't need this functionality right now */ abort(); } @@ -438,24 +505,48 @@ void s_tty_move_cursor_y(struct s_tty *tty, enum s_tty_position_base base, int p } } -void s_tty_clear(struct s_tty *tty, enum s_tty_clear_mode mode) +void b_tty_clear(struct b_tty *tty, enum b_tty_clear_mode mode) { const char *arg; - if (mode & TTY_CLEAR_ALL) { + if (mode & B_TTY_CLEAR_ALL) { arg = "2"; - } else if (mode & TTY_CLEAR_TO_CURSOR) { + } else if (mode & B_TTY_CLEAR_TO_CURSOR) { arg = "1"; - } else if (mode & TTY_CLEAR_FROM_CURSOR) { + } else if (mode & B_TTY_CLEAR_FROM_CURSOR) { arg = ""; } else { abort(); } - if (mode & TTY_CLEAR_SCREEN) { + if (mode & B_TTY_CLEAR_SCREEN) { fprintf(tty->t_out, "\033[%sJ", arg); - } else if (mode & TTY_CLEAR_LINE) { + } else if (mode & B_TTY_CLEAR_LINE) { fprintf(tty->t_out, "\033[%sK", arg); } else { abort(); } } + +enum b_status b_tty_get_dimensions( + struct b_tty *tty, unsigned int *w, unsigned int *h) +{ + if (!(tty->t_flags & B_TTY_INTERACTIVE)) { + return -1; + } + + int fd = fileno(tty->t_out); + struct winsize ws; + if (ioctl(fd, TIOCGWINSZ, &ws) == -1) { + return -1; + } + + if (w) { + *w = ws.ws_col; + } + + if (h) { + *h = ws.ws_row; + } + + return 0; +} diff --git a/term/tty.c b/term/tty.c index 98a4c90..d782d40 100644 --- a/term/tty.c +++ b/term/tty.c @@ -1,49 +1,50 @@ -#include -#include #include "tty.h" -#include "printf.h" -#define MOD_HASH_BLACK 0x4b5dd0abbc6fc1e4 -#define MOD_HASH_RED 0x89e9be1960f4c21c -#define MOD_HASH_GREEN 0x0f40f029637fecbc -#define MOD_HASH_YELLOW 0x8346a574925e75a9 -#define MOD_HASH_BLUE 0xc5ccd29bc2dda64d -#define MOD_HASH_MAGENTA 0x6c90e772edbc8708 -#define MOD_HASH_CYAN 0x70ae2e90c1bce27a -#define MOD_HASH_WHITE 0xced973885856e206 +#include +#include +#include -#define MOD_HASH_DARK_GREY 0x55a19de854654d99 -#define MOD_HASH_BRIGHT_RED 0xbad8e3fe841b9385 -#define MOD_HASH_BRIGHT_GREEN 0x11cc5e579bdd2fb9 -#define MOD_HASH_BRIGHT_YELLOW 0xfd579007fe8579f6 -#define MOD_HASH_BRIGHT_BLUE 0x57c76bf18badb6d6 -#define MOD_HASH_BRIGHT_MAGENTA 0xf6ecc6d3fdfec129 -#define MOD_HASH_BRIGHT_CYAN 0x03df73fd4e12ec6d -#define MOD_HASH_BRIGHT_WHITE 0xb5ebc3323f57d7fb +#define MOD_HASH_BLACK 0x4b5dd0abbc6fc1e4 +#define MOD_HASH_RED 0x89e9be1960f4c21c +#define MOD_HASH_GREEN 0x0f40f029637fecbc +#define MOD_HASH_YELLOW 0x8346a574925e75a9 +#define MOD_HASH_BLUE 0xc5ccd29bc2dda64d +#define MOD_HASH_MAGENTA 0x6c90e772edbc8708 +#define MOD_HASH_CYAN 0x70ae2e90c1bce27a +#define MOD_HASH_WHITE 0xced973885856e206 -#define MOD_HASH_BG_BLACK 0xd87a8f2d9d394432 -#define MOD_HASH_BG_RED 0x145b1e4366c7d7aa -#define MOD_HASH_BG_GREEN 0xa00b8541d3b1e55a -#define MOD_HASH_BG_YELLOW 0x98b030fd86e3b3cf -#define MOD_HASH_BG_BLUE 0xa15529109506b5df -#define MOD_HASH_BG_MAGENTA 0x86dbda99bcc86222 -#define MOD_HASH_BG_CYAN 0xf16a3104cf61a098 -#define MOD_HASH_BG_WHITE 0x3408c46ab5836674 +#define MOD_HASH_DARK_GREY 0x55a19de854654d99 +#define MOD_HASH_BRIGHT_RED 0xbad8e3fe841b9385 +#define MOD_HASH_BRIGHT_GREEN 0x11cc5e579bdd2fb9 +#define MOD_HASH_BRIGHT_YELLOW 0xfd579007fe8579f6 +#define MOD_HASH_BRIGHT_BLUE 0x57c76bf18badb6d6 +#define MOD_HASH_BRIGHT_MAGENTA 0xf6ecc6d3fdfec129 +#define MOD_HASH_BRIGHT_CYAN 0x03df73fd4e12ec6d +#define MOD_HASH_BRIGHT_WHITE 0xb5ebc3323f57d7fb -#define MOD_HASH_BG_DARK_GREY 0x820d2e77568eec47 -#define MOD_HASH_BRIGHT_BG_RED 0x144f5dc138087701 -#define MOD_HASH_BRIGHT_BG_GREEN 0xc4d88c6426ffe355 -#define MOD_HASH_BRIGHT_BG_YELLOW 0xf7bb000a4a792602 -#define MOD_HASH_BRIGHT_BG_BLUE 0x9b5c16d6807a1002 -#define MOD_HASH_BRIGHT_BG_MAGENTA 0xc59fb2196cdba3fd -#define MOD_HASH_BRIGHT_BG_CYAN 0x46feb6dc999a6f09 -#define MOD_HASH_BRIGHT_BG_WHITE 0xa3e7d1da08826f5f +#define MOD_HASH_BG_BLACK 0xd87a8f2d9d394432 +#define MOD_HASH_BG_RED 0x145b1e4366c7d7aa +#define MOD_HASH_BG_GREEN 0xa00b8541d3b1e55a +#define MOD_HASH_BG_YELLOW 0x98b030fd86e3b3cf +#define MOD_HASH_BG_BLUE 0xa15529109506b5df +#define MOD_HASH_BG_MAGENTA 0x86dbda99bcc86222 +#define MOD_HASH_BG_CYAN 0xf16a3104cf61a098 +#define MOD_HASH_BG_WHITE 0x3408c46ab5836674 -#define MOD_HASH_BOLD 0xcd32ea9bc6b26ff6 -#define MOD_HASH_ULINE 0x141fe741e9f8c22a -#define MOD_HASH_ITALIC 0x69d5e5f057d8992d -#define MOD_HASH_INVERT 0xab4ab85ddd6232e1 -#define MOD_HASH_RESET 0x0f136ff2c086b760 +#define MOD_HASH_BG_DARK_GREY 0x820d2e77568eec47 +#define MOD_HASH_BRIGHT_BG_RED 0x144f5dc138087701 +#define MOD_HASH_BRIGHT_BG_GREEN 0xc4d88c6426ffe355 +#define MOD_HASH_BRIGHT_BG_YELLOW 0xf7bb000a4a792602 +#define MOD_HASH_BRIGHT_BG_BLUE 0x9b5c16d6807a1002 +#define MOD_HASH_BRIGHT_BG_MAGENTA 0xc59fb2196cdba3fd +#define MOD_HASH_BRIGHT_BG_CYAN 0x46feb6dc999a6f09 +#define MOD_HASH_BRIGHT_BG_WHITE 0xa3e7d1da08826f5f + +#define MOD_HASH_BOLD 0xcd32ea9bc6b26ff6 +#define MOD_HASH_ULINE 0x141fe741e9f8c22a +#define MOD_HASH_ITALIC 0x69d5e5f057d8992d +#define MOD_HASH_INVERT 0xab4ab85ddd6232e1 +#define MOD_HASH_RESET 0x0f136ff2c086b760 #define COMPARE_MOD_NAME(ss, sd, hs, hd) ((hs) == (hd) && !strcmp(ss, sd)) @@ -102,32 +103,38 @@ static void apply_code_to_vmode(struct tty_format_buf *fmt) fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_BRIGHT_RED; } - if (COMPARE_MOD_NAME(modifier, "bright_green", mod_hash, MOD_HASH_BRIGHT_GREEN)) { + if (COMPARE_MOD_NAME( + modifier, "bright_green", mod_hash, MOD_HASH_BRIGHT_GREEN)) { fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16; fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_BRIGHT_GREEN; } - if (COMPARE_MOD_NAME(modifier, "bright_yellow", mod_hash, MOD_HASH_BRIGHT_YELLOW)) { + if (COMPARE_MOD_NAME( + modifier, "bright_yellow", mod_hash, MOD_HASH_BRIGHT_YELLOW)) { fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16; fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_BRIGHT_YELLOW; } - if (COMPARE_MOD_NAME(modifier, "bright_blue", mod_hash, MOD_HASH_BRIGHT_BLUE)) { + if (COMPARE_MOD_NAME( + modifier, "bright_blue", mod_hash, MOD_HASH_BRIGHT_BLUE)) { fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16; fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_BRIGHT_BLUE; } - if (COMPARE_MOD_NAME(modifier, "bright_magenta", mod_hash, MOD_HASH_BRIGHT_MAGENTA)) { + if (COMPARE_MOD_NAME( + modifier, "bright_magenta", mod_hash, MOD_HASH_BRIGHT_MAGENTA)) { fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16; fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_BRIGHT_MAGENTA; } - if (COMPARE_MOD_NAME(modifier, "bright_cyan", mod_hash, MOD_HASH_BRIGHT_CYAN)) { + if (COMPARE_MOD_NAME( + modifier, "bright_cyan", mod_hash, MOD_HASH_BRIGHT_CYAN)) { fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16; fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_BRIGHT_CYAN; } - if (COMPARE_MOD_NAME(modifier, "bright_white", mod_hash, MOD_HASH_BRIGHT_WHITE)) { + if (COMPARE_MOD_NAME( + modifier, "bright_white", mod_hash, MOD_HASH_BRIGHT_WHITE)) { fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16; fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_BRIGHT_WHITE; } @@ -172,42 +179,54 @@ static void apply_code_to_vmode(struct tty_format_buf *fmt) fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_WHITE; } - if (COMPARE_MOD_NAME(modifier, "bg_dark_grey", mod_hash, MOD_HASH_BG_DARK_GREY)) { + if (COMPARE_MOD_NAME( + modifier, "bg_dark_grey", mod_hash, MOD_HASH_BG_DARK_GREY)) { fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16; fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BRIGHT_BLACK; } - if (COMPARE_MOD_NAME(modifier, "bright_bg_red", mod_hash, MOD_HASH_BRIGHT_BG_RED)) { + if (COMPARE_MOD_NAME( + modifier, "bright_bg_red", mod_hash, MOD_HASH_BRIGHT_BG_RED)) { fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16; fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BRIGHT_RED; } - if (COMPARE_MOD_NAME(modifier, "bright_bg_green", mod_hash, MOD_HASH_BRIGHT_BG_GREEN)) { + if (COMPARE_MOD_NAME( + modifier, "bright_bg_green", mod_hash, + MOD_HASH_BRIGHT_BG_GREEN)) { fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16; fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BRIGHT_GREEN; } - if (COMPARE_MOD_NAME(modifier, "bright_bg_yellow", mod_hash, MOD_HASH_BRIGHT_BG_YELLOW)) { + if (COMPARE_MOD_NAME( + modifier, "bright_bg_yellow", mod_hash, + MOD_HASH_BRIGHT_BG_YELLOW)) { fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16; fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BRIGHT_YELLOW; } - if (COMPARE_MOD_NAME(modifier, "bright_bg_blue", mod_hash, MOD_HASH_BRIGHT_BG_BLUE)) { + if (COMPARE_MOD_NAME( + modifier, "bright_bg_blue", mod_hash, MOD_HASH_BRIGHT_BG_BLUE)) { fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16; fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BRIGHT_BLUE; } - if (COMPARE_MOD_NAME(modifier, "bright_bg_magenta", mod_hash, MOD_HASH_BRIGHT_BG_MAGENTA)) { + if (COMPARE_MOD_NAME( + modifier, "bright_bg_magenta", mod_hash, + MOD_HASH_BRIGHT_BG_MAGENTA)) { fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16; fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BRIGHT_MAGENTA; } - if (COMPARE_MOD_NAME(modifier, "bright_bg_cyan", mod_hash, MOD_HASH_BRIGHT_BG_CYAN)) { + if (COMPARE_MOD_NAME( + modifier, "bright_bg_cyan", mod_hash, MOD_HASH_BRIGHT_BG_CYAN)) { fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16; fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BRIGHT_CYAN; } - if (COMPARE_MOD_NAME(modifier, "bright_bg_white", mod_hash, MOD_HASH_BRIGHT_BG_WHITE)) { + if (COMPARE_MOD_NAME( + modifier, "bright_bg_white", mod_hash, + MOD_HASH_BRIGHT_BG_WHITE)) { fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16; fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BRIGHT_WHITE; } @@ -229,16 +248,14 @@ static void apply_code_to_vmode(struct tty_format_buf *fmt) } if (COMPARE_MOD_NAME(modifier, "reset", mod_hash, MOD_HASH_RESET)) { - fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16; - fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16; - - fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_WHITE; - fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BLACK; + fmt->reset_vmode = true; + fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_NONE; + fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_NONE; fmt->vmode.v_attrib = 0; } } -static void format_buffer_putc(struct tty_format_buf* fmt, int c) +static void format_buffer_putc(struct tty_format_buf *fmt, int c) { if (fmt->ptr < TTY_TMPBUF_SIZE - 1) { fmt->buf[fmt->ptr++] = c; @@ -246,15 +263,20 @@ static void format_buffer_putc(struct tty_format_buf* fmt, int c) } } -static void format_buffer_clear(struct tty_format_buf* fmt) +static void format_buffer_clear(struct tty_format_buf *fmt) { fmt->ptr = 0; fmt->buf[fmt->ptr] = '\0'; + fmt->reset_vmode = false; } -static void flush_vmode(struct b_tty* tty, struct tty_format_buf* fmt) +static void flush_vmode(struct b_tty *tty, struct tty_format_buf *fmt) { - b_tty_set_vmode(tty, &fmt->vmode); + if (fmt->reset_vmode) { + b_tty_reset_vmode(tty); + } else { + b_tty_set_vmode(tty, &fmt->vmode); + } } int b_tty_putc(struct b_tty *tty, enum b_tty_print_flags flags, char c) @@ -265,7 +287,7 @@ int b_tty_putc(struct b_tty *tty, enum b_tty_print_flags flags, char c) } struct tty_format_buf *fmt = z__b_tty_get_format_buf(tty); - + if (c == '[') { if (!fmt->in_format) { fmt->in_format = true; @@ -306,8 +328,7 @@ int b_tty_putc(struct b_tty *tty, enum b_tty_print_flags flags, char c) return c; } -int b_tty_puts( - struct b_tty* tty, enum b_tty_print_flags flags, const char* s) +int b_tty_puts(struct b_tty *tty, enum b_tty_print_flags flags, const char *s) { int r = 0; @@ -319,8 +340,7 @@ int b_tty_puts( return r; } -int b_tty_printf( - struct b_tty* tty, enum b_tty_print_flags flags, const char* s, ...) +int b_tty_printf(struct b_tty *tty, enum b_tty_print_flags flags, const char *s, ...) { va_list arg; va_start(arg, s); diff --git a/term/tty.h b/term/tty.h index 6a38e11..f84a067 100644 --- a/term/tty.h +++ b/term/tty.h @@ -1,12 +1,16 @@ #ifndef _TTY_H_ #define _TTY_H_ +#include +#include + #define TTY_TMPBUF_SIZE 128 struct b_tty; struct tty_format_buf { bool in_format; + bool reset_vmode; char buf[TTY_TMPBUF_SIZE]; unsigned int ptr; @@ -16,4 +20,4 @@ struct tty_format_buf { extern struct tty_format_buf *z__b_tty_get_format_buf(struct b_tty *tty); extern void z__b_tty_putc(struct b_tty *tty, char c); -#endif \ No newline at end of file +#endif