182 lines
4.3 KiB
C
182 lines
4.3 KiB
C
#include "term.h"
|
|
|
|
#include <gint/display.h>
|
|
#include <gint/rtc.h>
|
|
|
|
#include <ctype.h>
|
|
#include <printf.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
|
|
#include "utf8.h"
|
|
|
|
extern font_t uf5x7;
|
|
|
|
struct tcell {
|
|
char chr[4];
|
|
int fg;
|
|
int bg;
|
|
};
|
|
|
|
static struct tcell tgrid[UNS_TERM_ROWS][UNS_TERM_COLS];
|
|
|
|
static void tgrid_set(int row, int col, int fg, int bg, char c[4]) {
|
|
tgrid[row][col].chr[0] = c[0];
|
|
tgrid[row][col].chr[1] = c[1];
|
|
tgrid[row][col].chr[2] = c[2];
|
|
tgrid[row][col].chr[3] = c[3];
|
|
tgrid[row][col].fg = fg;
|
|
tgrid[row][col].bg = bg;
|
|
}
|
|
|
|
static int tgrid_sets(int *row, int *col, int fg, int bg, const char *s) {
|
|
int i = 0;
|
|
while (s[i] != '\0') {
|
|
// boundary check
|
|
if (*row >= UNS_TERM_ROWS)
|
|
return i;
|
|
if (*col >= UNS_TERM_COLS)
|
|
return i;
|
|
|
|
int charlen = charlen_utf8(s[i]);
|
|
|
|
char unichar[4];
|
|
int j;
|
|
for (j = 0; j < charlen; j++)
|
|
unichar[j] = s[i + j];
|
|
for (; j < 4; j++)
|
|
unichar[j] = '\0';
|
|
|
|
i += charlen;
|
|
|
|
const int char_is_newline = (strncmp(unichar, "\n", 4) == 0);
|
|
if (char_is_newline) {
|
|
// clear line end
|
|
for (; *col < UNS_TERM_COLS; *col = *col + 1)
|
|
tgrid_set(*row, *col, C_WHITE, C_BLACK, " \0\0");
|
|
} else {
|
|
tgrid_set(*row, *col, fg, bg, unichar);
|
|
*col = *col + 1;
|
|
}
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
int term_writeat(int row, int col, int fg, int bg, const char *s) { return tgrid_sets(&row, &col, fg, bg, s); }
|
|
|
|
void tgrid_display(void) {
|
|
dfont(&uf5x7);
|
|
|
|
int y = 3;
|
|
for (int row = 0; row < UNS_TERM_ROWS; row++) {
|
|
int x = 2;
|
|
for (int col = 0; col < UNS_TERM_COLS; col++) {
|
|
const struct tcell cell = tgrid[row][col];
|
|
|
|
// unpack unicode
|
|
char buf[5];
|
|
buf[0] = cell.chr[0];
|
|
buf[1] = cell.chr[1];
|
|
buf[2] = cell.chr[2];
|
|
buf[3] = cell.chr[3];
|
|
buf[4] = '\0';
|
|
|
|
drect(x - 1, y - 1, x + 6, y + 8, cell.bg);
|
|
dtext_opt(x, y, cell.fg, C_NONE, DTEXT_LEFT, DTEXT_TOP, (char *)&buf, -1);
|
|
|
|
x += 1 + 5;
|
|
}
|
|
|
|
y += 1 + 7 + 2;
|
|
}
|
|
}
|
|
|
|
void term_scroll_down(void) {
|
|
// clear last line
|
|
for (int i = 0; i < UNS_TERM_COLS; i++) {
|
|
tgrid[UNS_TERM_ROWS - 1][i].chr[0] = ' ';
|
|
tgrid[UNS_TERM_ROWS - 1][i].chr[1] = '\0';
|
|
tgrid[UNS_TERM_ROWS - 1][i].chr[2] = '\0';
|
|
tgrid[UNS_TERM_ROWS - 1][i].chr[3] = '\0';
|
|
tgrid[UNS_TERM_ROWS - 1][i].fg = C_WHITE;
|
|
tgrid[UNS_TERM_ROWS - 1][i].bg = C_BLACK;
|
|
}
|
|
|
|
for (int i = 1; i < UNS_TERM_ROWS - 1; i++) {
|
|
memcpy(tgrid[i], tgrid[i + 1], UNS_TERM_COLS * sizeof(struct tcell));
|
|
}
|
|
}
|
|
|
|
static int term_print_opt(const char *str, int fg, int bg) {
|
|
static int row = 1;
|
|
static int col = 0;
|
|
|
|
int i = 0;
|
|
|
|
while (str[i] != '\0') {
|
|
// handle cursor overflow (column)
|
|
if (col >= UNS_TERM_COLS) {
|
|
col = 0;
|
|
row++;
|
|
}
|
|
|
|
// handle cursor overflow (row)
|
|
if (row >= UNS_TERM_ROWS - 1) {
|
|
term_scroll_down();
|
|
row = UNS_TERM_ROWS - 2;
|
|
}
|
|
|
|
i += tgrid_sets(&row, &col, fg, bg, str + i);
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
int term_print(const char *str) { return term_print_opt(str, C_WHITE, C_BLACK); }
|
|
int term_printf(const char *restrict format, ...) {
|
|
va_list argp;
|
|
va_start(argp, format);
|
|
|
|
char buf[256];
|
|
const int n = vsnprintf(buf, sizeof(buf), format, argp);
|
|
term_print(buf);
|
|
|
|
va_end(argp);
|
|
return n;
|
|
}
|
|
|
|
int term_eprint(const char *str) { return term_print_opt(str, C_RED, C_BLACK); }
|
|
int term_eprintf(const char *restrict format, ...) {
|
|
va_list argp;
|
|
va_start(argp, format);
|
|
|
|
char buf[256];
|
|
const int n = vsnprintf(buf, sizeof(buf), format, argp);
|
|
term_eprint(buf);
|
|
|
|
va_end(argp);
|
|
return n;
|
|
}
|
|
|
|
int term_kprint(const char *str) {
|
|
int t = rtc_ticks();
|
|
|
|
char kstr[256];
|
|
sprintf(kstr, "[%5d.%03d] %s\n", t / 128, (t % 128) * 100 / 128, str);
|
|
|
|
const int ret = term_print_opt(kstr, C_RED | C_GREEN, C_BLACK);
|
|
|
|
return ret;
|
|
}
|
|
int term_kprintf(const char *restrict format, ...) {
|
|
va_list argp;
|
|
va_start(argp, format);
|
|
|
|
char buf[256];
|
|
const int n = vsnprintf(buf, sizeof(buf), format, argp);
|
|
term_kprint(buf);
|
|
|
|
va_end(argp);
|
|
return n;
|
|
} |