#include "../../print.h" #include #include #include #include #include int z__b_stream_is_tty(FILE *fp) { return isatty(fileno(fp)); } int z__b_stream_dimensions(FILE *fp, unsigned int *w, unsigned int *h) { if (!isatty(fileno(fp))) { return -1; } struct winsize ws; if (ioctl(fileno(fp), TIOCGWINSZ, &ws) == -1) { return -1; } if (w) { *w = ws.ws_col; } if (h) { *h = ws.ws_row; } return 0; } int z__b_stream_cursorpos(FILE *in, FILE *out, unsigned int *x, unsigned int *y) { if (!isatty(fileno(in)) || !isatty(fileno(out))) { return -1; } struct termios term, restore; tcgetattr(fileno(in), &term); tcgetattr(fileno(in), &restore); term.c_lflag &= ~(ICANON | ECHO); tcsetattr(fileno(in), TCSANOW, &term); const char *cmd = "\033[6n"; write(fileno(out), cmd, strlen(cmd)); char buf[64]; read(fileno(in), buf, sizeof buf); tcsetattr(fileno(in), TCSANOW, &restore); unsigned int row, col; int r = sscanf(buf, "\033[%u;%uR", &row, &col); if (r != 2) { return -1; } *x = col - 1; *y = row - 1; return 0; } int z__b_stream_set_modifier(FILE *fp, enum z__b_stream_modifier mod) { char buf[128]; int buf_i = 0; int nr_codes = 0; buf[buf_i++] = '\033'; buf[buf_i++] = '['; if (mod & Z__B_STREAM_MOD_RESET) { buf[buf_i++] = '0'; buf[buf_i++] = 'm'; buf[buf_i++] = '\0'; fputs(buf, fp); return 0; } if (mod & Z__B_STREAM_MOD_BOLD) { if (nr_codes > 0) { buf[buf_i++] = ';'; } buf[buf_i++] = '1'; nr_codes++; } if (mod & Z__B_STREAM_MOD_ITALIC) { if (nr_codes > 0) { buf[buf_i++] = ';'; } buf[buf_i++] = '3'; nr_codes++; } if (mod & Z__B_STREAM_MOD_ULINE) { if (nr_codes > 0) { buf[buf_i++] = ';'; } buf[buf_i++] = '4'; nr_codes++; } if (mod & Z__B_STREAM_MOD_INVERT) { if (nr_codes > 0) { buf[buf_i++] = ';'; } buf[buf_i++] = '7'; nr_codes++; } if (Z__B_STREAM_MOD_GET_FG_COLOUR(mod) != 0) { if (nr_codes > 0) { buf[buf_i++] = ';'; } buf[buf_i++] = mod & Z__B_STREAM_MOD_BRIGHT ? '9' : '3'; } switch (Z__B_STREAM_MOD_GET_FG_COLOUR(mod)) { case Z__B_STREAM_MOD_BLACK: buf[buf_i++] = '0'; nr_codes++; break; case Z__B_STREAM_MOD_RED: buf[buf_i++] = '1'; nr_codes++; break; case Z__B_STREAM_MOD_GREEN: buf[buf_i++] = '2'; nr_codes++; break; case Z__B_STREAM_MOD_BLUE: nr_codes++; break; case Z__B_STREAM_MOD_RED | Z__B_STREAM_MOD_GREEN: buf[buf_i++] = '3'; nr_codes++; break; case Z__B_STREAM_MOD_RED | Z__B_STREAM_MOD_BLUE: buf[buf_i++] = '5'; nr_codes++; break; case Z__B_STREAM_MOD_GREEN | Z__B_STREAM_MOD_BLUE: buf[buf_i++] = '6'; nr_codes++; break; case Z__B_STREAM_MOD_RED | Z__B_STREAM_MOD_GREEN | Z__B_STREAM_MOD_BLUE: buf[buf_i++] = '7'; nr_codes++; break; default: break; } if (Z__B_STREAM_MOD_GET_BG_COLOUR(mod) != 0) { if (nr_codes > 0) { buf[buf_i++] = ';'; } if (mod & Z__B_STREAM_MOD_BG_BRIGHT) { buf[buf_i++] = '1'; buf[buf_i++] = '0'; } else { buf[buf_i++] = '9'; } } switch (Z__B_STREAM_MOD_GET_BG_COLOUR(mod)) { case Z__B_STREAM_MOD_BG_BLACK: buf[buf_i++] = '0'; nr_codes++; break; case Z__B_STREAM_MOD_BG_RED: buf[buf_i++] = '1'; nr_codes++; break; case Z__B_STREAM_MOD_BG_GREEN: buf[buf_i++] = '2'; nr_codes++; break; case Z__B_STREAM_MOD_BG_BLUE: nr_codes++; break; case Z__B_STREAM_MOD_BG_RED | Z__B_STREAM_MOD_BG_GREEN: buf[buf_i++] = '3'; nr_codes++; break; case Z__B_STREAM_MOD_BG_RED | Z__B_STREAM_MOD_BG_BLUE: buf[buf_i++] = '5'; nr_codes++; break; case Z__B_STREAM_MOD_BG_GREEN | Z__B_STREAM_MOD_BG_BLUE: buf[buf_i++] = '6'; nr_codes++; break; case Z__B_STREAM_MOD_BG_RED | Z__B_STREAM_MOD_BG_GREEN | Z__B_STREAM_MOD_BG_BLUE: buf[buf_i++] = '7'; nr_codes++; break; default: break; } buf[buf_i++] = 'm'; buf[buf_i++] = '\0'; fputs(buf, fp); return 0; }