Alien-libhisto
view release on metacpan or search on metacpan
bundled/tools/src/tui_term.c view on Meta::CPAN
switch (seq[2]) {
case '1': ev.type = TUI_KEY_HOME; break;
case '3': ev.type = TUI_KEY_BACKSPACE; break;
case '4': ev.type = TUI_KEY_END; break;
case '5': ev.type = TUI_KEY_PAGE_UP; break;
case '6': ev.type = TUI_KEY_PAGE_DOWN; break;
case '7': ev.type = TUI_KEY_HOME; break;
case '8': ev.type = TUI_KEY_END; break;
default: break;
}
}
} else {
switch (seq[2]) {
case 'A': ev.type = TUI_KEY_UP; break;
case 'B': ev.type = TUI_KEY_DOWN; break;
case 'C': ev.type = TUI_KEY_RIGHT; break;
case 'D': ev.type = TUI_KEY_LEFT; break;
case 'H': ev.type = TUI_KEY_HOME; break;
case 'F': ev.type = TUI_KEY_END; break;
default: break;
}
}
} else if (seq[1] == 'O') {
switch (seq[2]) {
case 'H': ev.type = TUI_KEY_HOME; break;
case 'F': ev.type = TUI_KEY_END; break;
default: break;
}
}
return ev;
}
if (c == 3) {
ev.type = TUI_KEY_CTRL_C;
ev.ch = 3;
return ev;
}
if (c == 13 || c == 10) {
ev.type = TUI_KEY_ENTER;
ev.ch = '\n';
return ev;
}
if (c == 9) {
ev.type = TUI_KEY_TAB;
ev.ch = '\t';
return ev;
}
if (c == 127 || c == 8) {
ev.type = TUI_KEY_BACKSPACE;
ev.ch = '\b';
return ev;
}
ev.type = TUI_KEY_CHAR;
ev.ch = (unsigned char)c;
#endif
return ev;
}
/* Frame buffer methods */
void tui_frame_init(tui_frame_t *f, size_t initial_cap) {
if (!f) return;
if (initial_cap < 4096) initial_cap = 65536;
f->buf = (char *)malloc(initial_cap);
f->len = 0;
f->cap = initial_cap;
if (f->buf) f->buf[0] = '\0';
}
void tui_frame_clear(tui_frame_t *f) {
if (!f) return;
f->len = 0;
if (f->buf) f->buf[0] = '\0';
}
void tui_frame_append(tui_frame_t *f, const char *str, size_t len) {
if (!f || !str || len == 0) return;
if (f->len + len + 1 > f->cap) {
size_t new_cap = (f->cap * 2 > f->len + len + 1) ? f->cap * 2 : f->len + len + 4096;
char *new_buf = (char *)realloc(f->buf, new_cap);
if (!new_buf) return;
f->buf = new_buf;
f->cap = new_cap;
}
memcpy(f->buf + f->len, str, len);
f->len += len;
f->buf[f->len] = '\0';
}
void tui_frame_puts(tui_frame_t *f, const char *str) {
if (!f || !str) return;
tui_frame_append(f, str, strlen(str));
}
void tui_frame_printf(tui_frame_t *f, const char *fmt, ...) {
if (!f || !fmt) return;
char stack_buf[1024];
va_list args;
va_start(args, fmt);
int written = vsnprintf(stack_buf, sizeof(stack_buf), fmt, args);
va_end(args);
if (written < 0) return;
if ((size_t)written < sizeof(stack_buf)) {
tui_frame_append(f, stack_buf, (size_t)written);
} else {
char *heap_buf = (char *)malloc((size_t)written + 1);
if (heap_buf) {
va_start(args, fmt);
vsnprintf(heap_buf, (size_t)written + 1, fmt, args);
va_end(args);
tui_frame_append(f, heap_buf, (size_t)written);
free(heap_buf);
}
}
}
void tui_frame_flush(tui_frame_t *f, FILE *out_fp) {
if (!f || !f->buf || f->len == 0) return;
if (!out_fp) out_fp = stdout;
fwrite(f->buf, 1, f->len, out_fp);
fflush(out_fp);
tui_frame_clear(f);
}
void tui_frame_free(tui_frame_t *f) {
if (!f) return;
if (f->buf) {
free(f->buf);
f->buf = NULL;
}
f->len = 0;
f->cap = 0;
}
void tui_term_get_color(double fraction, bool monochrome, char *out_ansi, size_t max_len) {
if (!out_ansi || max_len == 0) return;
out_ansi[0] = '\0';
if (monochrome) return;
if (fraction < 0.0) fraction = 0.0;
if (fraction > 1.0) fraction = 1.0;
int r = 0, g = 0, b = 0;
if (fraction < 0.25) {
double t = fraction / 0.25;
r = 0;
g = (int)(t * 255.0);
b = 255;
} else if (fraction < 0.5) {
double t = (fraction - 0.25) / 0.25;
r = 0;
g = 255;
b = (int)((1.0 - t) * 255.0);
} else if (fraction < 0.75) {
double t = (fraction - 0.5) / 0.25;
r = (int)(t * 255.0);
g = 255;
b = 0;
} else {
double t = (fraction - 0.75) / 0.25;
r = 255;
g = (int)((1.0 - t) * 255.0);
b = 0;
}
snprintf(out_ansi, max_len, "\033[38;2;%d;%d;%dm", r, g, b);
}
int tui_visual_width(const char *str) {
if (!str) return 0;
int cols = 0;
const unsigned char *p = (const unsigned char *)str;
while (*p) {
if (*p == '\033') {
p++;
if (*p == '[') {
p++;
while (*p && (*p < 0x40 || *p > 0x7E)) p++;
if (*p) p++;
}
} else if (*p < 0x80) {
if (*p >= 32 && *p <= 126) cols++;
p++;
} else if ((*p & 0xE0) == 0xC0) {
cols++;
p += (*(p + 1)) ? 2 : 1;
} else if ((*p & 0xF0) == 0xE0) {
cols++;
p += (*(p + 1) && *(p + 2)) ? 3 : 1;
} else if ((*p & 0xF8) == 0xF0) {
cols += 2;
p += (*(p + 1) && *(p + 2) && *(p + 3)) ? 4 : 1;
} else {
p++;
}
}
return cols;
}
void tui_render_row(tui_frame_t *f, const char *content, int width, bool newline) {
if (!f) return;
tui_frame_puts(f, "â ");
int vis = tui_visual_width(content);
int inner_width = width - 4;
if (inner_width < 1) inner_width = 1;
if (vis <= inner_width) {
tui_frame_puts(f, content ? content : "");
int pad = inner_width - vis;
for (int i = 0; i < pad; ++i) tui_frame_puts(f, " ");
} else {
const unsigned char *p = (const unsigned char *)(content ? content : "");
int cur_cols = 0;
while (*p && cur_cols < inner_width) {
if (*p == '\033') {
const unsigned char *start = p++;
if (*p == '[') {
p++;
while (*p && (*p < 0x40 || *p > 0x7E)) p++;
if (*p) p++;
}
tui_frame_append(f, (const char *)start, (size_t)(p - start));
} else if (*p < 0x80) {
if (*p >= 32 && *p <= 126) cur_cols++;
tui_frame_append(f, (const char *)p, 1);
p++;
} else if ((*p & 0xE0) == 0xC0) {
cur_cols++;
size_t len = (*(p + 1)) ? 2 : 1;
tui_frame_append(f, (const char *)p, len);
p += len;
} else if ((*p & 0xF0) == 0xE0) {
cur_cols++;
size_t len = (*(p + 1) && *(p + 2)) ? 3 : 1;
tui_frame_append(f, (const char *)p, len);
p += len;
} else if ((*p & 0xF8) == 0xF0) {
if (cur_cols + 2 <= inner_width) {
cur_cols += 2;
size_t len = (*(p + 1) && *(p + 2) && *(p + 3)) ? 4 : 1;
tui_frame_append(f, (const char *)p, len);
p += len;
} else break;
} else {
p++;
}
}
int pad = inner_width - cur_cols;
for (int i = 0; i < pad; ++i) tui_frame_puts(f, " ");
}
tui_frame_puts(f, "\033[0m â");
if (newline) tui_frame_puts(f, "\r\n");
}
( run in 0.451 second using v1.01-cache-2.11-cpan-2e0ccfb7a10 )