diff --git a/.github/workflows/build-os.yml b/.github/workflows/build-os.yml index 9123791..3209ce2 100644 --- a/.github/workflows/build-os.yml +++ b/.github/workflows/build-os.yml @@ -26,6 +26,7 @@ jobs: git \ tar \ xorriso \ + mtools \ clang \ lld \ llvm \ diff --git a/clks/drivers/video/framebuffer.c b/clks/drivers/video/framebuffer.c index 8227f29..4279f54 100644 --- a/clks/drivers/video/framebuffer.c +++ b/clks/drivers/video/framebuffer.c @@ -197,7 +197,7 @@ void clks_fb_scroll_up(u32 pixel_rows, u32 fill_rgb) { } } -void clks_fb_draw_char(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb) { +void clks_fb_draw_char_styled(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb, u32 style_flags) { const u8 *glyph; u32 row; u32 col; @@ -206,6 +206,9 @@ void clks_fb_draw_char(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb) { u32 row_stride; u32 draw_cols; u32 draw_rows; + clks_bool style_bold; + clks_bool style_underline; + u32 underline_row; if (clks_fb.ready == CLKS_FALSE || clks_fb.font == CLKS_NULL) { return; @@ -256,6 +259,10 @@ void clks_fb_draw_char(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb) { draw_rows = clks_fb.info.height - y; } + style_bold = ((style_flags & CLKS_FB_STYLE_BOLD) != 0U) ? CLKS_TRUE : CLKS_FALSE; + style_underline = ((style_flags & CLKS_FB_STYLE_UNDERLINE) != 0U) ? CLKS_TRUE : CLKS_FALSE; + underline_row = (rows > 1U) ? (rows - 2U) : 0U; + for (row = 0U; row < draw_rows; row++) { const u8 *row_bits = glyph + ((usize)row * (usize)row_stride); volatile u32 *dst_row = (volatile u32 *)( @@ -265,11 +272,31 @@ void clks_fb_draw_char(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb) { for (col = 0U; col < draw_cols; col++) { u8 bits = row_bits[col >> 3U]; u8 mask = (u8)(0x80U >> (col & 7U)); - dst_row[col] = (bits & mask) != 0U ? fg_rgb : bg_rgb; + clks_bool pixel_on = ((bits & mask) != 0U) ? CLKS_TRUE : CLKS_FALSE; + + if (style_bold == CLKS_TRUE && pixel_on == CLKS_FALSE && col > 0U) { + u32 left_col = col - 1U; + u8 left_bits = row_bits[left_col >> 3U]; + u8 left_mask = (u8)(0x80U >> (left_col & 7U)); + + if ((left_bits & left_mask) != 0U) { + pixel_on = CLKS_TRUE; + } + } + + if (style_underline == CLKS_TRUE && row == underline_row) { + pixel_on = CLKS_TRUE; + } + + dst_row[col] = (pixel_on == CLKS_TRUE) ? fg_rgb : bg_rgb; } } } +void clks_fb_draw_char(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb) { + clks_fb_draw_char_styled(x, y, ch, fg_rgb, bg_rgb, 0U); +} + clks_bool clks_fb_load_psf_font(const void *blob, u64 blob_size) { struct clks_psf_font parsed = {0, 0, 0, 0, 0, CLKS_NULL}; diff --git a/clks/include/clks/framebuffer.h b/clks/include/clks/framebuffer.h index 5d963a0..8e6d874 100644 --- a/clks/include/clks/framebuffer.h +++ b/clks/include/clks/framebuffer.h @@ -19,7 +19,11 @@ void clks_fb_scroll_up(u32 pixel_rows, u32 fill_rgb); void clks_fb_draw_pixel(u32 x, u32 y, u32 rgb); clks_bool clks_fb_read_pixel(u32 x, u32 y, u32 *out_rgb); void clks_fb_fill_rect(u32 x, u32 y, u32 width, u32 height, u32 rgb); +#define CLKS_FB_STYLE_BOLD 0x1U +#define CLKS_FB_STYLE_UNDERLINE 0x2U + void clks_fb_draw_char(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb); +void clks_fb_draw_char_styled(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb, u32 style_flags); clks_bool clks_fb_load_psf_font(const void *blob, u64 blob_size); u32 clks_fb_cell_width(void); u32 clks_fb_cell_height(void); diff --git a/clks/kernel/tty.c b/clks/kernel/tty.c index f4c38f7..c1fcb9d 100644 --- a/clks/kernel/tty.c +++ b/clks/kernel/tty.c @@ -14,11 +14,15 @@ #define CLKS_TTY_DESKTOP_INDEX 1U #define CLKS_TTY_ANSI_MAX_LEN 95U #define CLKS_TTY_SCROLLBACK_LINES 256U +#define CLKS_TTY_STYLE_NONE 0U +#define CLKS_TTY_STYLE_BOLD ((u8)CLKS_FB_STYLE_BOLD) +#define CLKS_TTY_STYLE_UNDERLINE ((u8)CLKS_FB_STYLE_UNDERLINE) typedef struct clks_tty_ansi_state { clks_bool in_escape; clks_bool saw_csi; clks_bool bold; + clks_bool underline; clks_bool inverse; u32 saved_row; u32 saved_col; @@ -29,6 +33,7 @@ typedef struct clks_tty_ansi_state { static char clks_tty_cells[CLKS_TTY_COUNT][CLKS_TTY_MAX_ROWS][CLKS_TTY_MAX_COLS]; static u32 clks_tty_cell_fg[CLKS_TTY_COUNT][CLKS_TTY_MAX_ROWS][CLKS_TTY_MAX_COLS]; static u32 clks_tty_cell_bg[CLKS_TTY_COUNT][CLKS_TTY_MAX_ROWS][CLKS_TTY_MAX_COLS]; +static u8 clks_tty_cell_style[CLKS_TTY_COUNT][CLKS_TTY_MAX_ROWS][CLKS_TTY_MAX_COLS]; static u32 clks_tty_cursor_row[CLKS_TTY_COUNT]; static u32 clks_tty_cursor_col[CLKS_TTY_COUNT]; static u32 clks_tty_current_fg[CLKS_TTY_COUNT]; @@ -37,6 +42,7 @@ static clks_tty_ansi_state clks_tty_ansi[CLKS_TTY_COUNT]; static char clks_tty_scrollback_cells[CLKS_TTY_COUNT][CLKS_TTY_SCROLLBACK_LINES][CLKS_TTY_MAX_COLS]; static u32 clks_tty_scrollback_fg[CLKS_TTY_COUNT][CLKS_TTY_SCROLLBACK_LINES][CLKS_TTY_MAX_COLS]; static u32 clks_tty_scrollback_bg[CLKS_TTY_COUNT][CLKS_TTY_SCROLLBACK_LINES][CLKS_TTY_MAX_COLS]; +static u8 clks_tty_scrollback_style[CLKS_TTY_COUNT][CLKS_TTY_SCROLLBACK_LINES][CLKS_TTY_MAX_COLS]; static u32 clks_tty_scrollback_head[CLKS_TTY_COUNT]; static u32 clks_tty_scrollback_count[CLKS_TTY_COUNT]; static u32 clks_tty_scrollback_offset[CLKS_TTY_COUNT]; @@ -70,8 +76,15 @@ static void clks_tty_reset_blink_timer(void) { clks_tty_blink_last_tick = CLKS_TTY_BLINK_TICK_UNSET; } -static void clks_tty_draw_cell_with_colors(u32 row, u32 col, char ch, u32 fg, u32 bg) { - clks_fb_draw_char(col * clks_tty_cell_width, row * clks_tty_cell_height, ch, fg, bg); +static void clks_tty_draw_cell_with_colors(u32 row, u32 col, char ch, u32 fg, u32 bg, u8 style) { + clks_fb_draw_char_styled( + col * clks_tty_cell_width, + row * clks_tty_cell_height, + ch, + fg, + bg, + (u32)style + ); } static void clks_tty_draw_cell(u32 tty_index, u32 row, u32 col) { @@ -80,7 +93,8 @@ static void clks_tty_draw_cell(u32 tty_index, u32 row, u32 col) { col, clks_tty_cells[tty_index][row][col], clks_tty_cell_fg[tty_index][row][col], - clks_tty_cell_bg[tty_index][row][col] + clks_tty_cell_bg[tty_index][row][col], + clks_tty_cell_style[tty_index][row][col] ); } @@ -122,6 +136,11 @@ static void clks_tty_scrollback_push_row(u32 tty_index, u32 row) { clks_tty_cell_bg[tty_index][row], (usize)clks_tty_cols * sizeof(u32) ); + clks_memcpy( + clks_tty_scrollback_style[tty_index][slot], + clks_tty_cell_style[tty_index][row], + clks_tty_cols + ); clks_tty_scrollback_head[tty_index] = (slot + 1U) % CLKS_TTY_SCROLLBACK_LINES; @@ -143,6 +162,7 @@ static void clks_tty_reset_color_state(u32 tty_index) { clks_tty_current_fg[tty_index] = CLKS_TTY_FG; clks_tty_current_bg[tty_index] = CLKS_TTY_BG; clks_tty_ansi[tty_index].bold = CLKS_FALSE; + clks_tty_ansi[tty_index].underline = CLKS_FALSE; clks_tty_ansi[tty_index].inverse = CLKS_FALSE; } @@ -160,6 +180,7 @@ static void clks_tty_fill_row(u32 tty_index, u32 row, char ch) { clks_tty_cells[tty_index][row][col] = ch; clks_tty_cell_fg[tty_index][row][col] = CLKS_TTY_FG; clks_tty_cell_bg[tty_index][row][col] = CLKS_TTY_BG; + clks_tty_cell_style[tty_index][row][col] = CLKS_TTY_STYLE_NONE; } } @@ -205,6 +226,7 @@ static void clks_tty_draw_cursor(void) { u32 col; u32 fg; u32 bg; + u8 style; char ch; if (clks_tty_is_ready == CLKS_FALSE) { @@ -232,8 +254,9 @@ static void clks_tty_draw_cursor(void) { ch = clks_tty_cells[clks_tty_active_index][row][col]; fg = clks_tty_cell_fg[clks_tty_active_index][row][col]; bg = clks_tty_cell_bg[clks_tty_active_index][row][col]; + style = clks_tty_cell_style[clks_tty_active_index][row][col]; - clks_tty_draw_cell_with_colors(row, col, ch, bg, fg); + clks_tty_draw_cell_with_colors(row, col, ch, bg, fg, style); clks_tty_cursor_visible = CLKS_TRUE; } @@ -260,7 +283,8 @@ static void clks_tty_redraw_active(void) { col, clks_tty_scrollback_cells[tty_index][phys][col], clks_tty_scrollback_fg[tty_index][phys][col], - clks_tty_scrollback_bg[tty_index][phys][col] + clks_tty_scrollback_bg[tty_index][phys][col], + clks_tty_scrollback_style[tty_index][phys][col] ); } @@ -280,7 +304,8 @@ static void clks_tty_redraw_active(void) { col, clks_tty_cells[tty_index][src_row][col], clks_tty_cell_fg[tty_index][src_row][col], - clks_tty_cell_bg[tty_index][src_row][col] + clks_tty_cell_bg[tty_index][src_row][col], + clks_tty_cell_style[tty_index][src_row][col] ); } } @@ -307,6 +332,11 @@ static void clks_tty_scroll_up(u32 tty_index) { clks_tty_cell_bg[tty_index][row], (usize)clks_tty_cols * sizeof(u32) ); + clks_memcpy( + clks_tty_cell_style[tty_index][row - 1U], + clks_tty_cell_style[tty_index][row], + clks_tty_cols + ); } clks_tty_fill_row(tty_index, clks_tty_rows - 1U, ' '); @@ -328,6 +358,7 @@ static void clks_tty_scroll_up(u32 tty_index) { static void clks_tty_put_visible(u32 tty_index, u32 row, u32 col, char ch) { u32 fg = clks_tty_current_fg[tty_index]; u32 bg = clks_tty_current_bg[tty_index]; + u8 style = CLKS_TTY_STYLE_NONE; if (clks_tty_ansi[tty_index].inverse == CLKS_TRUE) { u32 swap = fg; @@ -335,9 +366,18 @@ static void clks_tty_put_visible(u32 tty_index, u32 row, u32 col, char ch) { bg = swap; } + if (clks_tty_ansi[tty_index].bold == CLKS_TRUE) { + style = (u8)(style | CLKS_TTY_STYLE_BOLD); + } + + if (clks_tty_ansi[tty_index].underline == CLKS_TRUE) { + style = (u8)(style | CLKS_TTY_STYLE_UNDERLINE); + } + clks_tty_cells[tty_index][row][col] = ch; clks_tty_cell_fg[tty_index][row][col] = fg; clks_tty_cell_bg[tty_index][row][col] = bg; + clks_tty_cell_style[tty_index][row][col] = style; if (tty_index == clks_tty_active_index) { clks_tty_draw_cell(tty_index, row, col); @@ -516,6 +556,7 @@ static void clks_tty_ansi_clear_line_mode(u32 tty_index, u32 mode) { clks_tty_cells[tty_index][row][col] = ' '; clks_tty_cell_fg[tty_index][row][col] = CLKS_TTY_FG; clks_tty_cell_bg[tty_index][row][col] = CLKS_TTY_BG; + clks_tty_cell_style[tty_index][row][col] = CLKS_TTY_STYLE_NONE; } if (tty_index == clks_tty_active_index) { @@ -547,6 +588,7 @@ static void clks_tty_ansi_clear_screen_mode(u32 tty_index, u32 mode) { clks_tty_cells[tty_index][row][col] = ' '; clks_tty_cell_fg[tty_index][row][col] = CLKS_TTY_FG; clks_tty_cell_bg[tty_index][row][col] = CLKS_TTY_BG; + clks_tty_cell_style[tty_index][row][col] = CLKS_TTY_STYLE_NONE; } } } else if (mode == 1U) { @@ -557,6 +599,7 @@ static void clks_tty_ansi_clear_screen_mode(u32 tty_index, u32 mode) { clks_tty_cells[tty_index][row][col] = ' '; clks_tty_cell_fg[tty_index][row][col] = CLKS_TTY_FG; clks_tty_cell_bg[tty_index][row][col] = CLKS_TTY_BG; + clks_tty_cell_style[tty_index][row][col] = CLKS_TTY_STYLE_NONE; } } } else { @@ -565,6 +608,7 @@ static void clks_tty_ansi_clear_screen_mode(u32 tty_index, u32 mode) { clks_tty_cells[tty_index][row][col] = ' '; clks_tty_cell_fg[tty_index][row][col] = CLKS_TTY_FG; clks_tty_cell_bg[tty_index][row][col] = CLKS_TTY_BG; + clks_tty_cell_style[tty_index][row][col] = CLKS_TTY_STYLE_NONE; } } } @@ -602,6 +646,11 @@ static void clks_tty_ansi_apply_sgr_params(u32 tty_index, const char *params, u3 continue; } + if (code == 4U) { + clks_tty_ansi[tty_index].underline = CLKS_TRUE; + continue; + } + if (code == 7U) { clks_tty_ansi[tty_index].inverse = CLKS_TRUE; continue; @@ -612,6 +661,11 @@ static void clks_tty_ansi_apply_sgr_params(u32 tty_index, const char *params, u3 continue; } + if (code == 24U) { + clks_tty_ansi[tty_index].underline = CLKS_FALSE; + continue; + } + if (code == 27U) { clks_tty_ansi[tty_index].inverse = CLKS_FALSE; continue; @@ -1196,3 +1250,5 @@ clks_bool clks_tty_ready(void) { return clks_tty_is_ready; } + +