311 lines
7.3 KiB
C
311 lines
7.3 KiB
C
#include <stdio.h>
|
|
#include <libtsm.h>
|
|
#include <string.h>
|
|
|
|
#define READ_BUF_SIZE 16 * 1024
|
|
|
|
static int RGB_LEVELS[6] = { 0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff };
|
|
|
|
struct tsm_screen_attr last_attr;
|
|
struct tsm_screen_attr *last_attr_ptr = &last_attr;
|
|
|
|
|
|
static int u8_wc_to_utf8(char *dest, uint32_t ch) {
|
|
if (ch < 0x80) {
|
|
dest[0] = (char)ch;
|
|
return 1;
|
|
}
|
|
|
|
if (ch < 0x800) {
|
|
dest[0] = (ch >> 6) | 0xC0;
|
|
dest[1] = (ch & 0x3F) | 0x80;
|
|
return 2;
|
|
}
|
|
|
|
if (ch < 0x10000) {
|
|
dest[0] = (ch >> 12) | 0xE0;
|
|
dest[1] = ((ch >> 6) & 0x3F) | 0x80;
|
|
dest[2] = (ch & 0x3F) | 0x80;
|
|
return 3;
|
|
}
|
|
|
|
if (ch < 0x110000) {
|
|
dest[0] = (ch >> 18) | 0xF0;
|
|
dest[1] = ((ch >> 12) & 0x3F) | 0x80;
|
|
dest[2] = ((ch >> 6) & 0x3F) | 0x80;
|
|
dest[3] = (ch & 0x3F) | 0x80;
|
|
return 4;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void check_err(int err, const char *message) {
|
|
if (err) {
|
|
printf("%s\n", message);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
void write_cb(struct tsm_vte *vte, const char *u8, size_t len, void *data) {}
|
|
|
|
int prepare_cb(struct tsm_screen *con, void *data) {
|
|
int *line = (int *)data;
|
|
|
|
*line = -1;
|
|
printf("[");
|
|
|
|
return 0;
|
|
}
|
|
|
|
void print_char(const uint32_t *ch) {
|
|
char str[5];
|
|
int size;
|
|
|
|
if (*ch == 0) {
|
|
printf(" ");
|
|
} else if (*ch == '"') {
|
|
printf("\\\"");
|
|
} else if (*ch == '\\') {
|
|
printf("\\\\");
|
|
} else {
|
|
size = u8_wc_to_utf8(str, *ch);
|
|
if (size > 0) {
|
|
str[size] = 0;
|
|
printf("%s", str);
|
|
} else {
|
|
printf("?");
|
|
}
|
|
}
|
|
}
|
|
|
|
int get_rgb_index(int value) {
|
|
int i;
|
|
|
|
for (i=0; i<6; i++) {
|
|
if (RGB_LEVELS[i] == value) return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int get_rgb_color(int r, int g, int b) {
|
|
if (r == g && g == b && (r - 8) % 10 == 0) {
|
|
return 232 + (r - 8) / 10;
|
|
} else {
|
|
return 16 + get_rgb_index(r) * 36 + get_rgb_index(g) * 6 + get_rgb_index(b);
|
|
}
|
|
}
|
|
|
|
int get_fg(const struct tsm_screen_attr *attr) {
|
|
if (attr->fccode == -1) {
|
|
return get_rgb_color(attr->fr, attr->fg, attr->fb);
|
|
} else if (attr->fccode >= 0 && attr->fccode < 16) {
|
|
return attr->fccode;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int get_bg(const struct tsm_screen_attr *attr) {
|
|
if (attr->bccode == -1) {
|
|
return get_rgb_color(attr->br, attr->bg, attr->bb);
|
|
} else if (attr->bccode >= 0 && attr->bccode < 16) {
|
|
return attr->bccode;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
void print_attr(const struct tsm_screen_attr *attr) {
|
|
bool comma_needed = false;
|
|
int color_code;
|
|
|
|
printf("{");
|
|
|
|
color_code = get_fg(attr);
|
|
if (color_code != -1) {
|
|
printf("\"fg\":%d", color_code);
|
|
comma_needed = true;
|
|
}
|
|
|
|
color_code = get_bg(attr);
|
|
if (color_code != -1) {
|
|
if (comma_needed) printf(",");
|
|
printf("\"bg\":%d", color_code);
|
|
comma_needed = true;
|
|
}
|
|
|
|
if (attr->bold) {
|
|
if (comma_needed) printf(",");
|
|
printf("\"bold\":true");
|
|
comma_needed = true;
|
|
}
|
|
|
|
if (attr->underline) {
|
|
if (comma_needed) printf(",");
|
|
printf("\"underline\":true");
|
|
comma_needed = true;
|
|
}
|
|
|
|
if (attr->inverse) {
|
|
if (comma_needed) printf(",");
|
|
printf("\"inverse\":true");
|
|
comma_needed = true;
|
|
}
|
|
|
|
if (attr->blink) {
|
|
if (comma_needed) printf(",");
|
|
printf("\"blink\":true");
|
|
comma_needed = true;
|
|
}
|
|
|
|
printf("}");
|
|
}
|
|
|
|
bool attr_eq(struct tsm_screen_attr *attr1, const struct tsm_screen_attr *attr2) {
|
|
return attr1->fccode == attr2->fccode &&
|
|
attr1->bccode == attr2->bccode &&
|
|
attr1->fr == attr2->fr &&
|
|
attr1->fg == attr2->fg &&
|
|
attr1->fb == attr2->fb &&
|
|
attr1->br == attr2->br &&
|
|
attr1->bg == attr2->bg &&
|
|
attr1->bb == attr2->bb &&
|
|
attr1->bold == attr2->bold &&
|
|
attr1->underline == attr2->underline &&
|
|
attr1->inverse == attr2->inverse &&
|
|
attr1->blink == attr2->blink;
|
|
}
|
|
|
|
void attr_cp(const struct tsm_screen_attr *src, struct tsm_screen_attr *dst) {
|
|
memcpy((void *)dst, (const void *)src, sizeof(last_attr));
|
|
}
|
|
|
|
void close_cell() {
|
|
printf("\",");
|
|
print_attr(last_attr_ptr);
|
|
printf("]");
|
|
}
|
|
|
|
void open_cell(const struct tsm_screen_attr *attr) {
|
|
printf("[\"");
|
|
attr_cp(attr, last_attr_ptr);
|
|
}
|
|
|
|
int draw_cb(struct tsm_screen *con, uint32_t id, const uint32_t *ch, size_t len,
|
|
unsigned int width, unsigned int posx, unsigned int posy,
|
|
const struct tsm_screen_attr *attr, tsm_age_t age, void *data) {
|
|
|
|
int *line = (int *)data;
|
|
|
|
if (((signed int)posy) > *line) {
|
|
if (*line >= 0) {
|
|
close_cell();
|
|
printf("],"); // close line
|
|
}
|
|
printf("["); // open line
|
|
open_cell(attr);
|
|
}
|
|
|
|
*line = posy;
|
|
|
|
if (width == 0) return 0;
|
|
|
|
if (!(attr_eq(last_attr_ptr, attr))) {
|
|
close_cell();
|
|
printf(",");
|
|
open_cell(attr);
|
|
}
|
|
|
|
print_char(ch);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int render_cb(struct tsm_screen *con, void *data) {
|
|
int *line = (int *)data;
|
|
|
|
if (*line >= 0) {
|
|
close_cell();
|
|
printf("]"); // close line
|
|
}
|
|
|
|
printf("]\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
int err;
|
|
int i;
|
|
struct tsm_screen *screen;
|
|
struct tsm_vte *vte;
|
|
int width, height;
|
|
char *line = NULL;
|
|
size_t size;
|
|
unsigned int n;
|
|
char *buffer = (char *) malloc(READ_BUF_SIZE);
|
|
int line_n, cursor_x, cursor_y;
|
|
char *cursor_visible;
|
|
unsigned int flags;
|
|
int m, read;
|
|
|
|
width = atoi(argv[1]);
|
|
height = atoi(argv[2]);
|
|
|
|
err = tsm_screen_new(&screen, NULL, NULL);
|
|
check_err(err, "can't create screen");
|
|
|
|
err = tsm_screen_resize(screen, width, height);
|
|
check_err(err, "can't resize screen");
|
|
|
|
err = tsm_vte_new(&vte, screen, write_cb, NULL, NULL, NULL);
|
|
check_err(err, "can't create vte");
|
|
|
|
for (;;) {
|
|
if (getline(&line, &size, stdin) == -1) break;
|
|
|
|
char action = line[0];
|
|
|
|
switch(action) {
|
|
case 'd':
|
|
if (getline(&line, &size, stdin) == -1) break;
|
|
n = atoi(line);
|
|
while (n > 0) {
|
|
if (n > READ_BUF_SIZE) {
|
|
m = READ_BUF_SIZE;
|
|
} else {
|
|
m = n;
|
|
}
|
|
read = fread(buffer, 1, m, stdin);
|
|
tsm_vte_input(vte, buffer, read);
|
|
n = n - read;
|
|
}
|
|
break;
|
|
case 'p':
|
|
//tsm_screen_draw(screen, prepare_cb, draw_cb, render_cb, &line_n);
|
|
prepare_cb(screen, &line_n);
|
|
tsm_screen_draw(screen, draw_cb, &line_n);
|
|
render_cb(screen, &line_n);
|
|
break;
|
|
case 'c':
|
|
cursor_x = tsm_screen_get_cursor_x(screen);
|
|
cursor_y = tsm_screen_get_cursor_y(screen);
|
|
flags = tsm_screen_get_flags(screen);
|
|
if (!(flags & TSM_SCREEN_HIDE_CURSOR)) {
|
|
cursor_visible = "true";
|
|
} else {
|
|
cursor_visible = "false";
|
|
}
|
|
printf("{\"x\":%d,\"y\":%d,\"visible\":%s}\n", cursor_x, cursor_y, cursor_visible);
|
|
|
|
break;
|
|
}
|
|
|
|
fflush(stdout);
|
|
}
|
|
|
|
return 0;
|
|
}
|