mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-27 05:34:00 +00:00
terminal支持全ANSI
This commit is contained in:
@@ -31,6 +31,7 @@
|
|||||||
#define USH_BROWSER_CSS_TEXT_MAX 4096U
|
#define USH_BROWSER_CSS_TEXT_MAX 4096U
|
||||||
#define USH_BROWSER_CSS_RULE_MAX 96U
|
#define USH_BROWSER_CSS_RULE_MAX 96U
|
||||||
#define USH_BROWSER_CSS_IDENT_MAX 48U
|
#define USH_BROWSER_CSS_IDENT_MAX 48U
|
||||||
|
#define USH_BROWSER_OUTPUT_COLS 78U
|
||||||
#define USH_BROWSER_ANSI_RESET "\x1B[0m"
|
#define USH_BROWSER_ANSI_RESET "\x1B[0m"
|
||||||
#define USH_BROWSER_ANSI_BLUE "\x1B[34m"
|
#define USH_BROWSER_ANSI_BLUE "\x1B[34m"
|
||||||
#define USH_BROWSER_ANSI_UNDERLINE "\x1B[4m"
|
#define USH_BROWSER_ANSI_UNDERLINE "\x1B[4m"
|
||||||
@@ -2123,16 +2124,26 @@ static int ush_browser_is_block_tag(GumboTag tag) {
|
|||||||
case GUMBO_TAG_ARTICLE:
|
case GUMBO_TAG_ARTICLE:
|
||||||
case GUMBO_TAG_ASIDE:
|
case GUMBO_TAG_ASIDE:
|
||||||
case GUMBO_TAG_NAV:
|
case GUMBO_TAG_NAV:
|
||||||
|
case GUMBO_TAG_ADDRESS:
|
||||||
case GUMBO_TAG_P:
|
case GUMBO_TAG_P:
|
||||||
case GUMBO_TAG_UL:
|
case GUMBO_TAG_UL:
|
||||||
case GUMBO_TAG_OL:
|
case GUMBO_TAG_OL:
|
||||||
case GUMBO_TAG_LI:
|
case GUMBO_TAG_LI:
|
||||||
|
case GUMBO_TAG_DL:
|
||||||
|
case GUMBO_TAG_DT:
|
||||||
|
case GUMBO_TAG_DD:
|
||||||
case GUMBO_TAG_TABLE:
|
case GUMBO_TAG_TABLE:
|
||||||
|
case GUMBO_TAG_CAPTION:
|
||||||
|
case GUMBO_TAG_TBODY:
|
||||||
|
case GUMBO_TAG_THEAD:
|
||||||
|
case GUMBO_TAG_TFOOT:
|
||||||
case GUMBO_TAG_TR:
|
case GUMBO_TAG_TR:
|
||||||
case GUMBO_TAG_TD:
|
case GUMBO_TAG_TD:
|
||||||
case GUMBO_TAG_TH:
|
case GUMBO_TAG_TH:
|
||||||
case GUMBO_TAG_PRE:
|
case GUMBO_TAG_PRE:
|
||||||
case GUMBO_TAG_BLOCKQUOTE:
|
case GUMBO_TAG_BLOCKQUOTE:
|
||||||
|
case GUMBO_TAG_FIGURE:
|
||||||
|
case GUMBO_TAG_FIGCAPTION:
|
||||||
case GUMBO_TAG_H1:
|
case GUMBO_TAG_H1:
|
||||||
case GUMBO_TAG_H2:
|
case GUMBO_TAG_H2:
|
||||||
case GUMBO_TAG_H3:
|
case GUMBO_TAG_H3:
|
||||||
@@ -2142,6 +2153,19 @@ static int ush_browser_is_block_tag(GumboTag tag) {
|
|||||||
case GUMBO_TAG_FOOTER:
|
case GUMBO_TAG_FOOTER:
|
||||||
case GUMBO_TAG_HEADER:
|
case GUMBO_TAG_HEADER:
|
||||||
case GUMBO_TAG_MAIN:
|
case GUMBO_TAG_MAIN:
|
||||||
|
case GUMBO_TAG_HGROUP:
|
||||||
|
case GUMBO_TAG_FORM:
|
||||||
|
case GUMBO_TAG_FIELDSET:
|
||||||
|
case GUMBO_TAG_DETAILS:
|
||||||
|
case GUMBO_TAG_SUMMARY:
|
||||||
|
case GUMBO_TAG_MENU:
|
||||||
|
case GUMBO_TAG_DIR:
|
||||||
|
case GUMBO_TAG_LISTING:
|
||||||
|
case GUMBO_TAG_XMP:
|
||||||
|
case GUMBO_TAG_PLAINTEXT:
|
||||||
|
case GUMBO_TAG_CENTER:
|
||||||
|
case GUMBO_TAG_DIALOG:
|
||||||
|
case GUMBO_TAG_SEARCH:
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2494,6 +2518,109 @@ static int ush_browser_render_html(const char *html, u64 html_size) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ush_browser_ansi_csi_len(const char *text, u64 pos, u64 len, u64 *out_len) {
|
||||||
|
u64 i;
|
||||||
|
|
||||||
|
if (text == (const char *)0 || out_len == (u64 *)0 || pos + 1ULL >= len || text[pos] != '\x1B' ||
|
||||||
|
text[pos + 1ULL] != '[') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = pos + 2ULL;
|
||||||
|
while (i < len) {
|
||||||
|
unsigned char ch = (unsigned char)text[i];
|
||||||
|
i++;
|
||||||
|
if (ch >= 0x40U && ch <= 0x7EU) {
|
||||||
|
*out_len = i - pos;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ush_browser_write_span(const char *text, u64 start, u64 end) {
|
||||||
|
u64 i;
|
||||||
|
|
||||||
|
if (text == (const char *)0 || end <= start) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = start; i < end; i++) {
|
||||||
|
(void)fputc(text[i], 1);
|
||||||
|
}
|
||||||
|
(void)fputc('\n', 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ush_browser_print_wrapped_span(const char *text, u64 start, u64 end, u64 *io_line_count) {
|
||||||
|
u64 pos = start;
|
||||||
|
|
||||||
|
if (text == (const char *)0 || io_line_count == (u64 *)0 || end <= start) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (pos < end) {
|
||||||
|
u64 line_start;
|
||||||
|
u64 line_end;
|
||||||
|
u64 last_space = (u64)-1;
|
||||||
|
u64 col = 0ULL;
|
||||||
|
|
||||||
|
while (pos < end && text[pos] == ' ') {
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
if (pos >= end) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
line_start = pos;
|
||||||
|
line_end = pos;
|
||||||
|
|
||||||
|
while (pos < end) {
|
||||||
|
u64 ansi_len;
|
||||||
|
char ch = text[pos];
|
||||||
|
|
||||||
|
if (ush_browser_ansi_csi_len(text, pos, end, &ansi_len) != 0) {
|
||||||
|
pos += ansi_len;
|
||||||
|
line_end = pos;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch == ' ') {
|
||||||
|
last_space = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (col >= (u64)USH_BROWSER_OUTPUT_COLS) {
|
||||||
|
if (last_space != (u64)-1 && last_space > line_start) {
|
||||||
|
line_end = last_space;
|
||||||
|
pos = last_space + 1ULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
col++;
|
||||||
|
pos++;
|
||||||
|
line_end = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (line_end > line_start && text[line_end - 1ULL] == ' ') {
|
||||||
|
line_end--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line_end > line_start) {
|
||||||
|
ush_browser_write_span(text, line_start, line_end);
|
||||||
|
(*io_line_count)++;
|
||||||
|
if (*io_line_count >= 220ULL) {
|
||||||
|
ush_writeln("[browser] output truncated at 220 lines");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (pos < end) {
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void ush_browser_print_rendered(const char *source_desc) {
|
static void ush_browser_print_rendered(const char *source_desc) {
|
||||||
u64 i = 0ULL;
|
u64 i = 0ULL;
|
||||||
u64 line_count = 0ULL;
|
u64 line_count = 0ULL;
|
||||||
@@ -2511,28 +2638,23 @@ static void ush_browser_print_rendered(const char *source_desc) {
|
|||||||
ush_writeln("------------------------------------------------------------");
|
ush_writeln("------------------------------------------------------------");
|
||||||
|
|
||||||
while (ush_browser_text_buf[i] != '\0') {
|
while (ush_browser_text_buf[i] != '\0') {
|
||||||
char line[256];
|
u64 start = i;
|
||||||
u64 j = 0ULL;
|
|
||||||
|
|
||||||
while (ush_browser_text_buf[i] != '\0' && ush_browser_text_buf[i] != '\n' && j + 1ULL < (u64)sizeof(line)) {
|
while (ush_browser_text_buf[i] != '\0' && ush_browser_text_buf[i] != '\n') {
|
||||||
line[j++] = ush_browser_text_buf[i++];
|
|
||||||
}
|
|
||||||
line[j] = '\0';
|
|
||||||
|
|
||||||
if (ush_browser_text_buf[i] == '\n') {
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line[0] != '\0') {
|
if (i > start) {
|
||||||
ush_writeln(line);
|
if (ush_browser_print_wrapped_span(ush_browser_text_buf, start, i, &line_count) == 0) {
|
||||||
line_count++;
|
|
||||||
if (line_count >= 220ULL) {
|
|
||||||
ush_writeln("[browser] output truncated at 220 lines");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (line_count > 0ULL) {
|
} else if (line_count > 0ULL) {
|
||||||
ush_writeln("");
|
ush_writeln("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ush_browser_text_buf[i] == '\n') {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ush_browser_link_count > 0ULL) {
|
if (ush_browser_link_count > 0ULL) {
|
||||||
|
|||||||
@@ -15,9 +15,12 @@
|
|||||||
#define TERM_LINES 128U
|
#define TERM_LINES 128U
|
||||||
#define TERM_LINE_MAX 160U
|
#define TERM_LINE_MAX 160U
|
||||||
#define TERM_INPUT_MAX 160U
|
#define TERM_INPUT_MAX 160U
|
||||||
#define TERM_ANSI_MAX 24U
|
#define TERM_ANSI_MAX 95U
|
||||||
#define TERM_EVENT_BUDGET 128ULL
|
#define TERM_EVENT_BUDGET 128ULL
|
||||||
#define TERM_IDLE_SPINS 24
|
#define TERM_IDLE_SPINS 24
|
||||||
|
#define TERM_STYLE_NONE 0U
|
||||||
|
#define TERM_STYLE_BOLD 1U
|
||||||
|
#define TERM_STYLE_UNDERLINE 2U
|
||||||
|
|
||||||
#define TERM_COLOR_WHITE 0x00FFFFFFU
|
#define TERM_COLOR_WHITE 0x00FFFFFFU
|
||||||
#define TERM_COLOR_WIN_BLUE 0x000078D7U
|
#define TERM_COLOR_WIN_BLUE 0x000078D7U
|
||||||
@@ -38,6 +41,7 @@
|
|||||||
((u64)(r5) << 5U) | (u64)(r6))
|
((u64)(r5) << 5U) | (u64)(r6))
|
||||||
|
|
||||||
typedef unsigned int term_u32;
|
typedef unsigned int term_u32;
|
||||||
|
typedef unsigned char term_u8;
|
||||||
|
|
||||||
typedef struct term_app {
|
typedef struct term_app {
|
||||||
int screen_w;
|
int screen_w;
|
||||||
@@ -70,9 +74,20 @@ typedef struct term_app {
|
|||||||
char input[TERM_INPUT_MAX];
|
char input[TERM_INPUT_MAX];
|
||||||
u64 input_len;
|
u64 input_len;
|
||||||
char lines[TERM_LINES][TERM_LINE_MAX];
|
char lines[TERM_LINES][TERM_LINE_MAX];
|
||||||
term_u32 line_colors[TERM_LINES];
|
term_u32 cell_fg[TERM_LINES][TERM_LINE_MAX];
|
||||||
|
term_u32 cell_bg[TERM_LINES][TERM_LINE_MAX];
|
||||||
|
term_u8 cell_style[TERM_LINES][TERM_LINE_MAX];
|
||||||
u64 line_count;
|
u64 line_count;
|
||||||
term_u32 color;
|
u64 cursor_row;
|
||||||
|
u64 cursor_col;
|
||||||
|
u64 saved_row;
|
||||||
|
u64 saved_col;
|
||||||
|
term_u32 current_fg;
|
||||||
|
term_u32 current_bg;
|
||||||
|
term_u8 current_style;
|
||||||
|
int ansi_bold;
|
||||||
|
int ansi_underline;
|
||||||
|
int ansi_inverse;
|
||||||
int ansi_state;
|
int ansi_state;
|
||||||
char ansi_buf[TERM_ANSI_MAX];
|
char ansi_buf[TERM_ANSI_MAX];
|
||||||
u64 ansi_len;
|
u64 ansi_len;
|
||||||
@@ -309,6 +324,36 @@ static void term_draw_char(term_app *app, int x, int y, char ch, int scale, term
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void term_draw_char_styled(term_app *app, int x, int y, char ch, term_u32 fg, term_u32 bg, term_u8 style) {
|
||||||
|
u64 mask = term_glyph_mask(ch);
|
||||||
|
int row;
|
||||||
|
|
||||||
|
term_fill_rect(app, x, y, 6, 11, bg);
|
||||||
|
if (mask == 0ULL) {
|
||||||
|
if ((style & TERM_STYLE_UNDERLINE) != 0U) {
|
||||||
|
term_fill_rect(app, x, y + 8, 5, 1, fg);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (row = 0; row < 7; row++) {
|
||||||
|
int col;
|
||||||
|
for (col = 0; col < 5; col++) {
|
||||||
|
unsigned int bit_index = (unsigned int)((6 - row) * 5 + (4 - col));
|
||||||
|
if ((mask & (1ULL << bit_index)) != 0ULL) {
|
||||||
|
term_fill_rect(app, x + col, y + row, 1, 1, fg);
|
||||||
|
if ((style & TERM_STYLE_BOLD) != 0U && col < 4) {
|
||||||
|
term_fill_rect(app, x + col + 1, y + row, 1, 1, fg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((style & TERM_STYLE_UNDERLINE) != 0U) {
|
||||||
|
term_fill_rect(app, x, y + 8, 5, 1, fg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void term_draw_text_limit(term_app *app, int x, int y, const char *text, int scale, term_u32 color, int max_x) {
|
static void term_draw_text_limit(term_app *app, int x, int y, const char *text, int scale, term_u32 color, int max_x) {
|
||||||
int cursor_x = x;
|
int cursor_x = x;
|
||||||
|
|
||||||
@@ -358,93 +403,194 @@ static void term_draw_control_button(term_app *app, int x, int active, int kind)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static term_u32 term_ansi_color(int code) {
|
static term_u32 term_ansi_palette(u64 index) {
|
||||||
switch (code) {
|
static const term_u32 palette[16] = {0x00000000U, 0x00CD3131U, 0x000DBC79U, 0x00E5E510U, 0x002472C8U, 0x00BC3FBCU,
|
||||||
case 30:
|
0x0011A8CDU, 0x00E5E5E5U, 0x00666666U, 0x00F14C4CU, 0x0023D18BU, 0x00F5F543U,
|
||||||
return 0x00404040U;
|
0x003B8EEAU, 0x00D670D6U, 0x0029B8DBU, 0x00FFFFFFU};
|
||||||
case 31:
|
|
||||||
return 0x00F44747U;
|
return (index < 16ULL) ? palette[index] : TERM_COLOR_DEFAULT;
|
||||||
case 32:
|
}
|
||||||
return 0x0060D060U;
|
|
||||||
case 33:
|
static term_u32 term_ansi_clamp_255(u64 value) {
|
||||||
return 0x00DCDCAAU;
|
return (term_u32)((value > 255ULL) ? 255ULL : value);
|
||||||
case 34:
|
}
|
||||||
return 0x00569CD6U;
|
|
||||||
case 35:
|
static term_u32 term_ansi_color_from_256(u64 index) {
|
||||||
return 0x00C586C0U;
|
if (index < 16ULL) {
|
||||||
case 36:
|
return term_ansi_palette(index);
|
||||||
return 0x004EC9B0U;
|
}
|
||||||
case 37:
|
if (index <= 231ULL) {
|
||||||
return 0x00DCDCDCU;
|
static const term_u32 steps[6] = {0U, 95U, 135U, 175U, 215U, 255U};
|
||||||
case 90:
|
u64 n = index - 16ULL;
|
||||||
return 0x00808080U;
|
u64 r = n / 36ULL;
|
||||||
case 91:
|
u64 g = (n / 6ULL) % 6ULL;
|
||||||
return 0x00FF7070U;
|
u64 b = n % 6ULL;
|
||||||
case 92:
|
return (steps[r] << 16U) | (steps[g] << 8U) | steps[b];
|
||||||
return 0x0080FF80U;
|
}
|
||||||
case 93:
|
if (index <= 255ULL) {
|
||||||
return 0x00FFFF80U;
|
term_u32 gray = (term_u32)(8ULL + ((index - 232ULL) * 10ULL));
|
||||||
case 94:
|
return (gray << 16U) | (gray << 8U) | gray;
|
||||||
return 0x0080C0FFU;
|
}
|
||||||
case 95:
|
|
||||||
return 0x00FF80FFU;
|
|
||||||
case 96:
|
|
||||||
return 0x0080FFFFU;
|
|
||||||
case 97:
|
|
||||||
return 0x00FFFFFFU;
|
|
||||||
default:
|
|
||||||
return TERM_COLOR_DEFAULT;
|
return TERM_COLOR_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void term_reset_style(term_app *app) {
|
||||||
|
if (app == (term_app *)0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
app->current_fg = TERM_COLOR_DEFAULT;
|
||||||
|
app->current_bg = TERM_COLOR_BG;
|
||||||
|
app->current_style = TERM_STYLE_NONE;
|
||||||
|
app->ansi_bold = 0;
|
||||||
|
app->ansi_underline = 0;
|
||||||
|
app->ansi_inverse = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static term_u32 term_effective_fg(const term_app *app) {
|
||||||
|
if (app == (const term_app *)0) {
|
||||||
|
return TERM_COLOR_DEFAULT;
|
||||||
|
}
|
||||||
|
return (app->ansi_inverse != 0) ? app->current_bg : app->current_fg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static term_u32 term_effective_bg(const term_app *app) {
|
||||||
|
if (app == (const term_app *)0) {
|
||||||
|
return TERM_COLOR_BG;
|
||||||
|
}
|
||||||
|
return (app->ansi_inverse != 0) ? app->current_fg : app->current_bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static term_u8 term_effective_style(const term_app *app) {
|
||||||
|
term_u8 style = TERM_STYLE_NONE;
|
||||||
|
if (app == (const term_app *)0) {
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
if (app->ansi_bold != 0) {
|
||||||
|
style |= TERM_STYLE_BOLD;
|
||||||
|
}
|
||||||
|
if (app->ansi_underline != 0) {
|
||||||
|
style |= TERM_STYLE_UNDERLINE;
|
||||||
|
}
|
||||||
|
style |= app->current_style;
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void term_clear_cell(term_app *app, u64 row, u64 col) {
|
||||||
|
if (app == (term_app *)0 || row >= (u64)TERM_LINES || col >= (u64)TERM_LINE_MAX) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
app->lines[row][col] = ' ';
|
||||||
|
app->cell_fg[row][col] = term_effective_fg(app);
|
||||||
|
app->cell_bg[row][col] = term_effective_bg(app);
|
||||||
|
app->cell_style[row][col] = term_effective_style(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void term_trim_line(term_app *app, u64 row) {
|
||||||
|
i64 col;
|
||||||
|
|
||||||
|
if (app == (term_app *)0 || row >= (u64)TERM_LINES) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
app->lines[row][TERM_LINE_MAX - 1U] = '\0';
|
||||||
|
for (col = (i64)TERM_LINE_MAX - 2; col >= 0; col--) {
|
||||||
|
if (app->lines[row][(u64)col] != ' ' && app->lines[row][(u64)col] != '\0') {
|
||||||
|
app->lines[row][(u64)col + 1ULL] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
app->lines[row][(u64)col] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void term_clear_line_range(term_app *app, u64 row, u64 start_col, u64 end_col) {
|
||||||
|
u64 col;
|
||||||
|
|
||||||
|
if (app == (term_app *)0 || row >= (u64)TERM_LINES) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (end_col > (u64)TERM_LINE_MAX - 1ULL) {
|
||||||
|
end_col = (u64)TERM_LINE_MAX - 1ULL;
|
||||||
|
}
|
||||||
|
for (col = start_col; col < end_col; col++) {
|
||||||
|
term_clear_cell(app, row, col);
|
||||||
|
}
|
||||||
|
term_trim_line(app, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void term_clear(term_app *app) {
|
static void term_clear(term_app *app) {
|
||||||
|
u64 row;
|
||||||
|
u64 col;
|
||||||
|
|
||||||
|
if (app == (term_app *)0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (row = 0ULL; row < (u64)TERM_LINES; row++) {
|
||||||
|
for (col = 0ULL; col < (u64)TERM_LINE_MAX; col++) {
|
||||||
|
app->lines[row][col] = '\0';
|
||||||
|
app->cell_fg[row][col] = term_effective_fg(app);
|
||||||
|
app->cell_bg[row][col] = term_effective_bg(app);
|
||||||
|
app->cell_style[row][col] = term_effective_style(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
app->line_count = 0ULL;
|
||||||
|
app->cursor_row = 0ULL;
|
||||||
|
app->cursor_col = 0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void term_ensure_row(term_app *app, u64 row) {
|
||||||
u64 i;
|
u64 i;
|
||||||
|
|
||||||
if (app == (term_app *)0) {
|
if (app == (term_app *)0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (row >= (u64)TERM_LINES) {
|
||||||
ush_zero(app->lines, (u64)sizeof(app->lines));
|
row = (u64)TERM_LINES - 1ULL;
|
||||||
for (i = 0ULL; i < (u64)TERM_LINES; i++) {
|
|
||||||
app->line_colors[i] = app->color;
|
|
||||||
}
|
}
|
||||||
app->line_count = 0ULL;
|
while (app->line_count <= row) {
|
||||||
}
|
i = app->line_count;
|
||||||
|
app->lines[i][0] = '\0';
|
||||||
static void term_ensure_line(term_app *app) {
|
app->cell_fg[i][0] = term_effective_fg(app);
|
||||||
if (app != (term_app *)0 && app->line_count == 0ULL) {
|
app->cell_bg[i][0] = term_effective_bg(app);
|
||||||
app->line_count = 1ULL;
|
app->cell_style[i][0] = term_effective_style(app);
|
||||||
app->lines[0][0] = '\0';
|
app->line_count++;
|
||||||
app->line_colors[0] = app->color;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void term_shift_lines(term_app *app) {
|
static void term_shift_lines(term_app *app) {
|
||||||
u64 i;
|
u64 i;
|
||||||
|
u64 col;
|
||||||
|
|
||||||
|
if (app == (term_app *)0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (i = 1ULL; i < (u64)TERM_LINES; i++) {
|
for (i = 1ULL; i < (u64)TERM_LINES; i++) {
|
||||||
ush_copy(app->lines[i - 1ULL], (u64)TERM_LINE_MAX, app->lines[i]);
|
ush_copy(app->lines[i - 1ULL], (u64)TERM_LINE_MAX, app->lines[i]);
|
||||||
app->line_colors[i - 1ULL] = app->line_colors[i];
|
for (col = 0ULL; col < (u64)TERM_LINE_MAX; col++) {
|
||||||
|
app->cell_fg[i - 1ULL][col] = app->cell_fg[i][col];
|
||||||
|
app->cell_bg[i - 1ULL][col] = app->cell_bg[i][col];
|
||||||
|
app->cell_style[i - 1ULL][col] = app->cell_style[i][col];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
app->lines[TERM_LINES - 1U][0] = '\0';
|
app->lines[TERM_LINES - 1U][0] = '\0';
|
||||||
app->line_colors[TERM_LINES - 1U] = app->color;
|
for (col = 0ULL; col < (u64)TERM_LINE_MAX; col++) {
|
||||||
|
app->cell_fg[TERM_LINES - 1U][col] = term_effective_fg(app);
|
||||||
|
app->cell_bg[TERM_LINES - 1U][col] = term_effective_bg(app);
|
||||||
|
app->cell_style[TERM_LINES - 1U][col] = term_effective_style(app);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void term_newline(term_app *app) {
|
static void term_newline(term_app *app) {
|
||||||
if (app == (term_app *)0) {
|
if (app == (term_app *)0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (app->line_count == 0ULL) {
|
term_ensure_row(app, app->cursor_row);
|
||||||
term_ensure_line(app);
|
app->cursor_col = 0ULL;
|
||||||
return;
|
if (app->cursor_row + 1ULL >= (u64)TERM_LINES) {
|
||||||
}
|
|
||||||
if (app->line_count < (u64)TERM_LINES) {
|
|
||||||
app->lines[app->line_count][0] = '\0';
|
|
||||||
app->line_colors[app->line_count] = app->color;
|
|
||||||
app->line_count++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
term_shift_lines(app);
|
term_shift_lines(app);
|
||||||
|
app->line_count = (u64)TERM_LINES;
|
||||||
|
} else {
|
||||||
|
app->cursor_row++;
|
||||||
|
term_ensure_row(app, app->cursor_row);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void term_append_char(term_app *app, char ch) {
|
static void term_append_char(term_app *app, char ch) {
|
||||||
@@ -455,6 +601,7 @@ static void term_append_char(term_app *app, char ch) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ch == '\r') {
|
if (ch == '\r') {
|
||||||
|
app->cursor_col = 0ULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ch == '\n') {
|
if (ch == '\n') {
|
||||||
@@ -462,86 +609,257 @@ static void term_append_char(term_app *app, char ch) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ch == '\t') {
|
if (ch == '\t') {
|
||||||
ch = ' ';
|
term_append_char(app, ' ');
|
||||||
|
term_append_char(app, ' ');
|
||||||
|
term_append_char(app, ' ');
|
||||||
|
term_append_char(app, ' ');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (ch < ' ' || ch > '~') {
|
if (ch < ' ' || ch > '~') {
|
||||||
ch = '?';
|
ch = '?';
|
||||||
}
|
}
|
||||||
|
if (app->cursor_col + 1ULL >= (u64)TERM_LINE_MAX) {
|
||||||
term_ensure_line(app);
|
|
||||||
line = app->lines[app->line_count - 1ULL];
|
|
||||||
app->line_colors[app->line_count - 1ULL] = app->color;
|
|
||||||
len = ush_strlen(line);
|
|
||||||
if (len + 1ULL >= (u64)TERM_LINE_MAX) {
|
|
||||||
term_newline(app);
|
term_newline(app);
|
||||||
line = app->lines[app->line_count - 1ULL];
|
|
||||||
app->line_colors[app->line_count - 1ULL] = app->color;
|
|
||||||
len = 0ULL;
|
|
||||||
}
|
|
||||||
line[len] = ch;
|
|
||||||
line[len + 1ULL] = '\0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int term_ansi_number(const char *text, u64 *offset, int *out_value) {
|
term_ensure_row(app, app->cursor_row);
|
||||||
int value = 0;
|
line = app->lines[app->cursor_row];
|
||||||
int any = 0;
|
len = ush_strlen(line);
|
||||||
|
while (len < app->cursor_col && len + 1ULL < (u64)TERM_LINE_MAX) {
|
||||||
|
line[len] = ' ';
|
||||||
|
app->cell_fg[app->cursor_row][len] = term_effective_fg(app);
|
||||||
|
app->cell_bg[app->cursor_row][len] = term_effective_bg(app);
|
||||||
|
app->cell_style[app->cursor_row][len] = term_effective_style(app);
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
line[app->cursor_col] = ch;
|
||||||
|
app->cell_fg[app->cursor_row][app->cursor_col] = term_effective_fg(app);
|
||||||
|
app->cell_bg[app->cursor_row][app->cursor_col] = term_effective_bg(app);
|
||||||
|
app->cell_style[app->cursor_row][app->cursor_col] = term_effective_style(app);
|
||||||
|
if (line[app->cursor_col + 1ULL] == '\0') {
|
||||||
|
line[app->cursor_col + 1ULL] = '\0';
|
||||||
|
}
|
||||||
|
app->cursor_col++;
|
||||||
|
}
|
||||||
|
|
||||||
if (text == (const char *)0 || offset == (u64 *)0 || out_value == (int *)0) {
|
static u64 term_ansi_parse_params(const char *params, u64 *out_values, u64 max_values) {
|
||||||
return 0;
|
u64 count = 0ULL;
|
||||||
|
u64 value = 0ULL;
|
||||||
|
int has_digit = 0;
|
||||||
|
u64 i;
|
||||||
|
|
||||||
|
if (out_values == (u64 *)0 || max_values == 0ULL) {
|
||||||
|
return 0ULL;
|
||||||
}
|
}
|
||||||
while (text[*offset] >= '0' && text[*offset] <= '9') {
|
if (params == (const char *)0 || params[0] == '\0') {
|
||||||
value = (value * 10) + (text[*offset] - '0');
|
out_values[0] = 0ULL;
|
||||||
(*offset)++;
|
return 1ULL;
|
||||||
any = 1;
|
|
||||||
}
|
}
|
||||||
*out_value = value;
|
for (i = 0ULL;; i++) {
|
||||||
return any;
|
char ch = params[i];
|
||||||
|
if (ch >= '0' && ch <= '9') {
|
||||||
|
has_digit = 1;
|
||||||
|
value = (value * 10ULL) + (u64)(ch - '0');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ch == '?' && i == 0ULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ch == ';' || ch == '\0') {
|
||||||
|
if (count < max_values) {
|
||||||
|
out_values[count++] = (has_digit != 0) ? value : 0ULL;
|
||||||
|
}
|
||||||
|
value = 0ULL;
|
||||||
|
has_digit = 0;
|
||||||
|
if (ch == '\0') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (count == 0ULL) ? 1ULL : count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 term_ansi_param_or_default(const u64 *params, u64 count, u64 index, u64 default_value) {
|
||||||
|
if (params == (const u64 *)0 || index >= count || params[index] == 0ULL) {
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
return params[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void term_apply_sgr(term_app *app, const char *params) {
|
static void term_apply_sgr(term_app *app, const char *params) {
|
||||||
u64 pos = 0ULL;
|
u64 values[16];
|
||||||
|
u64 count = term_ansi_parse_params(params, values, 16ULL);
|
||||||
|
u64 i;
|
||||||
|
|
||||||
if (app == (term_app *)0 || params == (const char *)0 || params[0] == '\0') {
|
if (app == (term_app *)0) {
|
||||||
if (app != (term_app *)0) {
|
|
||||||
app->color = TERM_COLOR_DEFAULT;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
for (i = 0ULL; i < count; i++) {
|
||||||
|
u64 code = values[i];
|
||||||
|
|
||||||
while (params[pos] != '\0') {
|
if (code == 0ULL) {
|
||||||
int code = 0;
|
term_reset_style(app);
|
||||||
int has_number = term_ansi_number(params, &pos, &code);
|
} else if (code == 1ULL) {
|
||||||
|
app->ansi_bold = 1;
|
||||||
|
} else if (code == 4ULL) {
|
||||||
|
app->ansi_underline = 1;
|
||||||
|
} else if (code == 7ULL) {
|
||||||
|
app->ansi_inverse = 1;
|
||||||
|
} else if (code == 21ULL || code == 22ULL) {
|
||||||
|
app->ansi_bold = 0;
|
||||||
|
} else if (code == 24ULL) {
|
||||||
|
app->ansi_underline = 0;
|
||||||
|
} else if (code == 27ULL) {
|
||||||
|
app->ansi_inverse = 0;
|
||||||
|
} else if (code == 39ULL) {
|
||||||
|
app->current_fg = TERM_COLOR_DEFAULT;
|
||||||
|
} else if (code == 49ULL) {
|
||||||
|
app->current_bg = TERM_COLOR_BG;
|
||||||
|
} else if (code >= 30ULL && code <= 37ULL) {
|
||||||
|
u64 idx = code - 30ULL;
|
||||||
|
if (app->ansi_bold != 0) {
|
||||||
|
idx += 8ULL;
|
||||||
|
}
|
||||||
|
app->current_fg = term_ansi_palette(idx);
|
||||||
|
} else if (code >= 90ULL && code <= 97ULL) {
|
||||||
|
app->current_fg = term_ansi_palette((code - 90ULL) + 8ULL);
|
||||||
|
} else if (code >= 40ULL && code <= 47ULL) {
|
||||||
|
app->current_bg = term_ansi_palette(code - 40ULL);
|
||||||
|
} else if (code >= 100ULL && code <= 107ULL) {
|
||||||
|
app->current_bg = term_ansi_palette((code - 100ULL) + 8ULL);
|
||||||
|
} else if ((code == 38ULL || code == 48ULL) && i + 1ULL < count) {
|
||||||
|
u64 mode = values[i + 1ULL];
|
||||||
|
term_u32 color;
|
||||||
|
|
||||||
if (has_number == 0) {
|
if (mode == 5ULL && i + 2ULL < count) {
|
||||||
code = 0;
|
color = term_ansi_color_from_256(values[i + 2ULL]);
|
||||||
|
if (code == 38ULL) {
|
||||||
|
app->current_fg = color;
|
||||||
|
} else {
|
||||||
|
app->current_bg = color;
|
||||||
}
|
}
|
||||||
if (code == 0 || code == 39) {
|
i += 2ULL;
|
||||||
app->color = TERM_COLOR_DEFAULT;
|
} else if (mode == 2ULL && i + 4ULL < count) {
|
||||||
} else if ((code >= 30 && code <= 37) || (code >= 90 && code <= 97)) {
|
term_u32 r = term_ansi_clamp_255(values[i + 2ULL]);
|
||||||
app->color = term_ansi_color(code);
|
term_u32 g = term_ansi_clamp_255(values[i + 3ULL]);
|
||||||
|
term_u32 b = term_ansi_clamp_255(values[i + 4ULL]);
|
||||||
|
color = (r << 16U) | (g << 8U) | b;
|
||||||
|
if (code == 38ULL) {
|
||||||
|
app->current_fg = color;
|
||||||
|
} else {
|
||||||
|
app->current_bg = color;
|
||||||
|
}
|
||||||
|
i += 4ULL;
|
||||||
}
|
}
|
||||||
if (params[pos] == ';') {
|
|
||||||
pos++;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void term_apply_ansi(term_app *app, char final_ch) {
|
static void term_apply_ansi(term_app *app, char final_ch) {
|
||||||
|
u64 values[16];
|
||||||
|
u64 count;
|
||||||
|
int private_mode;
|
||||||
|
|
||||||
if (app == (term_app *)0) {
|
if (app == (term_app *)0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
app->ansi_buf[app->ansi_len] = '\0';
|
app->ansi_buf[app->ansi_len] = '\0';
|
||||||
|
count = term_ansi_parse_params(app->ansi_buf, values, 16ULL);
|
||||||
|
private_mode = (app->ansi_buf[0] == '?') ? 1 : 0;
|
||||||
|
|
||||||
if (final_ch == 'm') {
|
if (final_ch == 'm') {
|
||||||
term_apply_sgr(app, app->ansi_buf);
|
term_apply_sgr(app, app->ansi_buf);
|
||||||
} else if (final_ch == 'J') {
|
} else if (final_ch == 'J') {
|
||||||
u64 pos = 0ULL;
|
u64 mode = (count == 0ULL) ? 0ULL : values[0];
|
||||||
int code = 0;
|
if (mode == 0ULL) {
|
||||||
|
u64 row;
|
||||||
if (term_ansi_number(app->ansi_buf, &pos, &code) != 0 && (code == 2 || code == 3)) {
|
term_clear_line_range(app, app->cursor_row, app->cursor_col, (u64)TERM_LINE_MAX - 1ULL);
|
||||||
|
for (row = app->cursor_row + 1ULL; row < (u64)TERM_LINES; row++) {
|
||||||
|
term_clear_line_range(app, row, 0ULL, (u64)TERM_LINE_MAX - 1ULL);
|
||||||
|
}
|
||||||
|
} else if (mode == 1ULL) {
|
||||||
|
u64 row;
|
||||||
|
for (row = 0ULL; row < app->cursor_row && row < (u64)TERM_LINES; row++) {
|
||||||
|
term_clear_line_range(app, row, 0ULL, (u64)TERM_LINE_MAX - 1ULL);
|
||||||
|
}
|
||||||
|
term_clear_line_range(app, app->cursor_row, 0ULL, app->cursor_col + 1ULL);
|
||||||
|
} else if (mode == 2ULL || mode == 3ULL) {
|
||||||
term_clear(app);
|
term_clear(app);
|
||||||
}
|
}
|
||||||
|
} else if (final_ch == 'K') {
|
||||||
|
u64 mode = (count == 0ULL) ? 0ULL : values[0];
|
||||||
|
if (mode == 0ULL) {
|
||||||
|
term_clear_line_range(app, app->cursor_row, app->cursor_col, (u64)TERM_LINE_MAX - 1ULL);
|
||||||
|
} else if (mode == 1ULL) {
|
||||||
|
term_clear_line_range(app, app->cursor_row, 0ULL, app->cursor_col + 1ULL);
|
||||||
|
} else {
|
||||||
|
term_clear_line_range(app, app->cursor_row, 0ULL, (u64)TERM_LINE_MAX - 1ULL);
|
||||||
|
}
|
||||||
|
} else if (final_ch == 'H' || final_ch == 'f') {
|
||||||
|
u64 row = term_ansi_param_or_default(values, count, 0ULL, 1ULL);
|
||||||
|
u64 col = term_ansi_param_or_default(values, count, 1ULL, 1ULL);
|
||||||
|
app->cursor_row = (row > 0ULL) ? row - 1ULL : 0ULL;
|
||||||
|
app->cursor_col = (col > 0ULL) ? col - 1ULL : 0ULL;
|
||||||
|
if (app->cursor_row >= (u64)TERM_LINES) {
|
||||||
|
app->cursor_row = (u64)TERM_LINES - 1ULL;
|
||||||
|
}
|
||||||
|
if (app->cursor_col >= (u64)TERM_LINE_MAX - 1ULL) {
|
||||||
|
app->cursor_col = (u64)TERM_LINE_MAX - 2ULL;
|
||||||
|
}
|
||||||
|
term_ensure_row(app, app->cursor_row);
|
||||||
|
} else if (final_ch == 'A') {
|
||||||
|
u64 n = term_ansi_param_or_default(values, count, 0ULL, 1ULL);
|
||||||
|
app->cursor_row = (n > app->cursor_row) ? 0ULL : app->cursor_row - n;
|
||||||
|
} else if (final_ch == 'B') {
|
||||||
|
u64 n = term_ansi_param_or_default(values, count, 0ULL, 1ULL);
|
||||||
|
app->cursor_row += n;
|
||||||
|
if (app->cursor_row >= (u64)TERM_LINES) {
|
||||||
|
app->cursor_row = (u64)TERM_LINES - 1ULL;
|
||||||
|
}
|
||||||
|
term_ensure_row(app, app->cursor_row);
|
||||||
|
} else if (final_ch == 'C') {
|
||||||
|
u64 n = term_ansi_param_or_default(values, count, 0ULL, 1ULL);
|
||||||
|
app->cursor_col += n;
|
||||||
|
if (app->cursor_col >= (u64)TERM_LINE_MAX - 1ULL) {
|
||||||
|
app->cursor_col = (u64)TERM_LINE_MAX - 2ULL;
|
||||||
|
}
|
||||||
|
} else if (final_ch == 'D') {
|
||||||
|
u64 n = term_ansi_param_or_default(values, count, 0ULL, 1ULL);
|
||||||
|
app->cursor_col = (n > app->cursor_col) ? 0ULL : app->cursor_col - n;
|
||||||
|
} else if (final_ch == 'E' || final_ch == 'F') {
|
||||||
|
u64 n = term_ansi_param_or_default(values, count, 0ULL, 1ULL);
|
||||||
|
if (final_ch == 'E') {
|
||||||
|
app->cursor_row += n;
|
||||||
|
if (app->cursor_row >= (u64)TERM_LINES) {
|
||||||
|
app->cursor_row = (u64)TERM_LINES - 1ULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
app->cursor_row = (n > app->cursor_row) ? 0ULL : app->cursor_row - n;
|
||||||
|
}
|
||||||
|
app->cursor_col = 0ULL;
|
||||||
|
term_ensure_row(app, app->cursor_row);
|
||||||
|
} else if (final_ch == 'G') {
|
||||||
|
u64 col = term_ansi_param_or_default(values, count, 0ULL, 1ULL);
|
||||||
|
app->cursor_col = (col > 0ULL) ? col - 1ULL : 0ULL;
|
||||||
|
if (app->cursor_col >= (u64)TERM_LINE_MAX - 1ULL) {
|
||||||
|
app->cursor_col = (u64)TERM_LINE_MAX - 2ULL;
|
||||||
|
}
|
||||||
|
} else if (final_ch == 'd') {
|
||||||
|
u64 row = term_ansi_param_or_default(values, count, 0ULL, 1ULL);
|
||||||
|
app->cursor_row = (row > 0ULL) ? row - 1ULL : 0ULL;
|
||||||
|
if (app->cursor_row >= (u64)TERM_LINES) {
|
||||||
|
app->cursor_row = (u64)TERM_LINES - 1ULL;
|
||||||
|
}
|
||||||
|
term_ensure_row(app, app->cursor_row);
|
||||||
|
} else if (final_ch == 's') {
|
||||||
|
app->saved_row = app->cursor_row;
|
||||||
|
app->saved_col = app->cursor_col;
|
||||||
|
} else if (final_ch == 'u') {
|
||||||
|
app->cursor_row = (app->saved_row < (u64)TERM_LINES) ? app->saved_row : (u64)TERM_LINES - 1ULL;
|
||||||
|
app->cursor_col = (app->saved_col < (u64)TERM_LINE_MAX - 1ULL) ? app->saved_col : (u64)TERM_LINE_MAX - 2ULL;
|
||||||
|
term_ensure_row(app, app->cursor_row);
|
||||||
|
} else if ((final_ch == 'h' || final_ch == 'l') && private_mode != 0) {
|
||||||
|
/* Cursor visibility mode is accepted for compatibility; this terminal does not draw a PTY cursor. */
|
||||||
}
|
}
|
||||||
app->ansi_state = 0;
|
app->ansi_state = 0;
|
||||||
app->ansi_len = 0ULL;
|
app->ansi_len = 0ULL;
|
||||||
@@ -558,6 +876,21 @@ static void term_append_ansi_char(term_app *app, char ch) {
|
|||||||
app->ansi_len = 0ULL;
|
app->ansi_len = 0ULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (ch == '7') {
|
||||||
|
app->saved_row = app->cursor_row;
|
||||||
|
app->saved_col = app->cursor_col;
|
||||||
|
app->ansi_state = 0;
|
||||||
|
app->ansi_len = 0ULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ch == '8') {
|
||||||
|
app->cursor_row = (app->saved_row < (u64)TERM_LINES) ? app->saved_row : (u64)TERM_LINES - 1ULL;
|
||||||
|
app->cursor_col = (app->saved_col < (u64)TERM_LINE_MAX - 1ULL) ? app->saved_col : (u64)TERM_LINE_MAX - 2ULL;
|
||||||
|
term_ensure_row(app, app->cursor_row);
|
||||||
|
app->ansi_state = 0;
|
||||||
|
app->ansi_len = 0ULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
app->ansi_state = 0;
|
app->ansi_state = 0;
|
||||||
app->ansi_len = 0ULL;
|
app->ansi_len = 0ULL;
|
||||||
return;
|
return;
|
||||||
@@ -677,15 +1010,23 @@ static void term_render(term_app *app) {
|
|||||||
for (i = start; i < app->line_count; i++) {
|
for (i = start; i < app->line_count; i++) {
|
||||||
int row = (int)(i - start);
|
int row = (int)(i - start);
|
||||||
int y = TERM_TITLE_H + 50 + (row * line_h);
|
int y = TERM_TITLE_H + 50 + (row * line_h);
|
||||||
term_u32 color = app->line_colors[i];
|
u64 col;
|
||||||
|
const char *line = app->lines[i];
|
||||||
|
|
||||||
if (y + 8 >= app->h - TERM_BOTTOM_H) {
|
if (y + 8 >= app->h - TERM_BOTTOM_H) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (color == 0U) {
|
for (col = 0ULL; line[col] != '\0' && col + 1ULL < (u64)TERM_LINE_MAX; col++) {
|
||||||
color = TERM_COLOR_DEFAULT;
|
int x = 10 + ((int)col * 6);
|
||||||
|
term_u32 fg = app->cell_fg[i][col];
|
||||||
|
term_u32 bg = app->cell_bg[i][col];
|
||||||
|
term_u8 style = app->cell_style[i][col];
|
||||||
|
|
||||||
|
if (x + 5 >= app->w - 10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
term_draw_char_styled(app, x, y, line[col], fg, bg, style);
|
||||||
}
|
}
|
||||||
term_draw_text_limit(app, 10, y, app->lines[i], 1, color, app->w - 10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
term_fill_rect(app, 0, app->h - TERM_BOTTOM_H, app->w, TERM_BOTTOM_H, TERM_COLOR_BAR);
|
term_fill_rect(app, 0, app->h - TERM_BOTTOM_H, app->w, TERM_BOTTOM_H, TERM_COLOR_BAR);
|
||||||
@@ -1336,7 +1677,7 @@ int cleonos_terminal_run(void) {
|
|||||||
|
|
||||||
ush_zero(&app, (u64)sizeof(app));
|
ush_zero(&app, (u64)sizeof(app));
|
||||||
app.running = 1;
|
app.running = 1;
|
||||||
app.color = TERM_COLOR_DEFAULT;
|
term_reset_style(&app);
|
||||||
ush_copy(app.cwd, (u64)sizeof(app.cwd), "/");
|
ush_copy(app.cwd, (u64)sizeof(app.cwd), "/");
|
||||||
term_clear(&app);
|
term_clear(&app);
|
||||||
term_append_line(&app, "CLEONOS TERMINAL READY");
|
term_append_line(&app, "CLEONOS TERMINAL READY");
|
||||||
|
|||||||
Reference in New Issue
Block a user