MIRROR: javascript for 馃悳's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 173 lines 4.4 kB view raw
1#include <compat.h> // IWYU pragma: keep 2 3#include <errno.h> 4#include <limits.h> 5#include <math.h> 6#include <stdio.h> 7#include <string.h> 8 9#ifdef _WIN32 10#include <io.h> 11#define ANT_WRITE_FD _write 12#else 13#include <unistd.h> 14#define ANT_WRITE_FD write 15#endif 16 17#include "tty_ctrl.h" 18#include "internal.h" 19 20bool tty_ctrl_write_fd(int fd, const char *data, size_t len) { 21 if (fd < 0 || !data) return false; 22 if (len == 0) return true; 23 24 size_t off = 0; 25 while (off < len) { 26#ifdef _WIN32 27 size_t rem = len - off; 28 unsigned int chunk = (rem > (size_t)INT_MAX) ? (unsigned int)INT_MAX : (unsigned int)rem; 29 int wrote = ANT_WRITE_FD(fd, data + off, chunk); 30 if (wrote <= 0) return false; 31 off += (size_t)wrote; 32#else 33 ssize_t wrote = ANT_WRITE_FD(fd, data + off, len - off); 34 if (wrote < 0) { 35 if (errno == EINTR) continue; 36 return false; 37 } 38 if (wrote == 0) return false; 39 off += (size_t)wrote; 40#endif 41 } 42 43 return true; 44} 45 46bool tty_ctrl_write_stream(FILE *stream, const char *data, size_t len, bool flush) { 47 if (!stream || !data) return false; 48 if (len > 0 && fwrite(data, 1, len, stream) != len) return false; 49 if (flush && fflush(stream) != 0) return false; 50 return true; 51} 52 53bool tty_ctrl_parse_int_value(ant_value_t value, int *out) { 54 if (vtype(value) != T_NUM) return false; 55 double d = js_getnum(value); 56 if (!isfinite(d)) return false; 57 if (d < (double)INT_MIN || d > (double)INT_MAX) return false; 58 int i = (int)d; 59 if ((double)i != d) return false; 60 *out = i; 61 return true; 62} 63 64int tty_ctrl_normalize_clear_line_dir(int dir) { 65 if (dir < 0) return -1; 66 if (dir > 0) return 1; 67 return 0; 68} 69 70int tty_ctrl_normalize_coord(int value) { 71 return value < 0 ? 0 : value; 72} 73 74bool tty_ctrl_parse_clear_line_dir(ant_value_t *args, int nargs, int dir_index, int *dir_out) { 75 int dir = 0; 76 if (nargs > dir_index && vtype(args[dir_index]) != T_UNDEF) { 77 if (!tty_ctrl_parse_int_value(args[dir_index], &dir)) return false; 78 } 79 *dir_out = tty_ctrl_normalize_clear_line_dir(dir); 80 return true; 81} 82 83bool tty_ctrl_parse_cursor_to_args( 84 ant_value_t *args, 85 int nargs, 86 int x_index, 87 int y_index, 88 tty_ctrl_cursor_to_args_t *out 89) { 90 if (!out || nargs <= x_index) return false; 91 92 int x = 0; 93 if (!tty_ctrl_parse_int_value(args[x_index], &x)) return false; 94 out->x = tty_ctrl_normalize_coord(x); 95 out->has_y = false; 96 out->y = 0; 97 98 if (nargs > y_index && vtype(args[y_index]) != T_UNDEF) { 99 int y = 0; 100 if (!tty_ctrl_parse_int_value(args[y_index], &y)) return false; 101 out->has_y = true; 102 out->y = tty_ctrl_normalize_coord(y); 103 } 104 105 return true; 106} 107 108bool tty_ctrl_parse_move_cursor_args( 109 ant_value_t *args, 110 int nargs, 111 int dx_index, 112 int dy_index, 113 int *dx, 114 int *dy 115) { 116 if (!dx || !dy) return false; 117 if (nargs <= dy_index) return false; 118 if (!tty_ctrl_parse_int_value(args[dx_index], dx)) return false; 119 if (!tty_ctrl_parse_int_value(args[dy_index], dy)) return false; 120 return true; 121} 122 123const char *tty_ctrl_clear_line_seq(int dir, size_t *len_out) { 124 dir = tty_ctrl_normalize_clear_line_dir(dir); 125 const char *seq = "\033[2K\r"; 126 if (dir < 0) seq = "\033[1K"; 127 else if (dir > 0) seq = "\033[0K"; 128 129 if (len_out) *len_out = strlen(seq); 130 return seq; 131} 132 133const char *tty_ctrl_clear_screen_down_seq(size_t *len_out) { 134 static const char seq[] = "\033[0J"; 135 if (len_out) *len_out = sizeof(seq) - 1; 136 return seq; 137} 138 139bool tty_ctrl_build_cursor_to(char *buf, size_t buf_size, int x, bool has_y, int y, size_t *len_out) { 140 if (!buf || buf_size == 0) return false; 141 142 int n = 0; 143 if (has_y) n = snprintf(buf, buf_size, "\033[%d;%dH", y + 1, x + 1); 144 else n = snprintf(buf, buf_size, "\033[%dG", x + 1); 145 146 if (n < 0 || (size_t)n >= buf_size) return false; 147 if (len_out) *len_out = (size_t)n; 148 return true; 149} 150 151bool tty_ctrl_build_move_cursor_axis(char *buf, size_t buf_size, int delta, bool horizontal, size_t *len_out) { 152 if (!buf || buf_size == 0) return false; 153 154 if (delta == 0) { 155 if (len_out) *len_out = 0; 156 return true; 157 } 158 159 int amount = (delta < 0) ? -delta : delta; 160 char cmd = 0; 161 if (horizontal) cmd = (delta > 0) ? 'C' : 'D'; 162 else cmd = (delta > 0) ? 'B' : 'A'; 163 164 int n = snprintf(buf, buf_size, "\033[%d%c", amount, cmd); 165 if (n < 0 || (size_t)n >= buf_size) return false; 166 167 if (len_out) *len_out = (size_t)n; 168 return true; 169} 170 171ant_value_t tty_ctrl_bool_result(ant_t *js, bool ok) { 172 return js_bool(ok); 173}