mirror of
https://github.com/limine-bootloader/limine
synced 2025-01-05 20:34:33 +03:00
term: Support for reverse scroll, save/restore, and bug fixes
This commit is contained in:
parent
58a3954c51
commit
4d6e1b801a
@ -23,7 +23,10 @@ bool text_scroll_disable(void);
|
||||
void text_scroll_enable(void);
|
||||
void text_move_character(size_t new_x, size_t new_y, size_t old_x, size_t old_y);
|
||||
void text_scroll(void);
|
||||
void text_revscroll(void);
|
||||
void text_swap_palette(void);
|
||||
void text_save_state(void);
|
||||
void text_restore_state(void);
|
||||
|
||||
void text_double_buffer(bool state);
|
||||
void text_double_buffer_flush(void);
|
||||
|
@ -29,6 +29,11 @@ static struct context {
|
||||
#define text_palette context.text_palette
|
||||
bool scroll_enabled;
|
||||
#define scroll_enabled context.scroll_enabled
|
||||
|
||||
uint8_t saved_state_text_palette;
|
||||
#define saved_state_text_palette context.saved_state_text_palette
|
||||
size_t saved_state_cursor_offset;
|
||||
#define saved_state_cursor_offset context.saved_state_cursor_offset
|
||||
} context;
|
||||
|
||||
static size_t old_cursor_offset = 0;
|
||||
@ -38,6 +43,16 @@ static void draw_cursor(void) {
|
||||
video_mem[cursor_offset + 1] = ((pal & 0xf0) >> 4) | ((pal & 0x0f) << 4);
|
||||
}
|
||||
|
||||
void text_save_state(void) {
|
||||
saved_state_text_palette = text_palette;
|
||||
saved_state_cursor_offset = cursor_offset;
|
||||
}
|
||||
|
||||
void text_restore_state(void) {
|
||||
text_palette = saved_state_text_palette;
|
||||
cursor_offset = saved_state_cursor_offset;
|
||||
}
|
||||
|
||||
void text_swap_palette(void) {
|
||||
text_palette = (text_palette << 4) | (text_palette >> 4);
|
||||
}
|
||||
@ -66,6 +81,22 @@ void text_scroll(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void text_revscroll(void) {
|
||||
// move the text up by one row
|
||||
for (size_t i = (term_context.scroll_bottom_margin - 1) * VD_COLS - 2; ; i--) {
|
||||
back_buffer[i + VD_COLS] = back_buffer[i];
|
||||
if (i == term_context.scroll_top_margin * VD_COLS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// clear the first line of the screen
|
||||
for (size_t i = term_context.scroll_top_margin * VD_COLS;
|
||||
i < (term_context.scroll_top_margin + 1) * VD_COLS; i += 2) {
|
||||
back_buffer[i] = ' ';
|
||||
back_buffer[i + 1] = text_palette;
|
||||
}
|
||||
}
|
||||
|
||||
void text_clear(bool move) {
|
||||
for (size_t i = 0; i < VIDEO_BOTTOM; i += 2) {
|
||||
back_buffer[i] = ' ';
|
||||
|
@ -89,19 +89,40 @@ static struct context {
|
||||
#define cursor_x context.cursor_x
|
||||
size_t cursor_y;
|
||||
#define cursor_y context.cursor_y
|
||||
bool scroll_enabled;
|
||||
#define scroll_enabled context.scroll_enabled
|
||||
|
||||
uint32_t saved_state_text_fg;
|
||||
#define saved_state_text_fg context.saved_state_text_fg
|
||||
uint32_t saved_state_text_bg;
|
||||
#define saved_state_text_bg context.saved_state_text_bg
|
||||
size_t saved_state_cursor_x;
|
||||
#define saved_state_cursor_x context.saved_state_cursor_x
|
||||
size_t saved_state_cursor_y;
|
||||
#define saved_state_cursor_y context.saved_state_cursor_y
|
||||
} context;
|
||||
|
||||
static size_t old_cursor_x = 0;
|
||||
static size_t old_cursor_y = 0;
|
||||
|
||||
void gterm_save_state(void) {
|
||||
saved_state_text_fg = text_fg;
|
||||
saved_state_text_bg = text_bg;
|
||||
saved_state_cursor_x = cursor_x;
|
||||
saved_state_cursor_y = cursor_y;
|
||||
}
|
||||
|
||||
void gterm_restore_state(void) {
|
||||
text_fg = saved_state_text_fg;
|
||||
text_bg = saved_state_text_bg;
|
||||
cursor_x = saved_state_cursor_x;
|
||||
cursor_y = saved_state_cursor_y;
|
||||
}
|
||||
|
||||
void gterm_swap_palette(void) {
|
||||
uint32_t tmp = text_bg;
|
||||
text_bg = text_fg;
|
||||
if (tmp == 0xffffffff) {
|
||||
text_fg = default_bg;
|
||||
} else {
|
||||
text_fg = tmp;
|
||||
}
|
||||
text_fg = tmp;
|
||||
}
|
||||
|
||||
#define A(rgb) (uint8_t)(rgb >> 24)
|
||||
@ -353,8 +374,6 @@ static void push_to_queue(struct gterm_char *c, size_t x, size_t y) {
|
||||
q->c = *c;
|
||||
}
|
||||
|
||||
static bool scroll_enabled = true;
|
||||
|
||||
bool gterm_scroll_disable(void) {
|
||||
bool ret = scroll_enabled;
|
||||
scroll_enabled = false;
|
||||
@ -365,6 +384,32 @@ void gterm_scroll_enable(void) {
|
||||
scroll_enabled = true;
|
||||
}
|
||||
|
||||
void gterm_revscroll(void) {
|
||||
for (size_t i = (term_context.scroll_bottom_margin - 1) * cols - 1; ; i--) {
|
||||
struct gterm_char *c;
|
||||
struct queue_item *q = map[i];
|
||||
if (q != NULL) {
|
||||
c = &q->c;
|
||||
} else {
|
||||
c = &grid[i];
|
||||
}
|
||||
push_to_queue(c, (i + cols) % cols, (i + cols) / cols);
|
||||
if (i == term_context.scroll_top_margin * cols) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the first line of the screen.
|
||||
struct gterm_char empty;
|
||||
empty.c = ' ';
|
||||
empty.fg = text_fg;
|
||||
empty.bg = text_bg;
|
||||
for (size_t i = term_context.scroll_top_margin * cols;
|
||||
i < (term_context.scroll_top_margin + 1) * cols; i++) {
|
||||
push_to_queue(&empty, i % cols, i / cols);
|
||||
}
|
||||
}
|
||||
|
||||
void gterm_scroll(void) {
|
||||
for (size_t i = (term_context.scroll_top_margin + 1) * cols;
|
||||
i < term_context.scroll_bottom_margin * cols; i++) {
|
||||
@ -578,6 +623,7 @@ bool gterm_init(size_t *_rows, size_t *_cols, size_t width, size_t height) {
|
||||
return false;
|
||||
|
||||
cursor_status = true;
|
||||
scroll_enabled = true;
|
||||
|
||||
// default scheme
|
||||
margin = 64;
|
||||
|
@ -27,7 +27,10 @@ bool gterm_scroll_disable(void);
|
||||
void gterm_scroll_enable(void);
|
||||
void gterm_move_character(size_t new_x, size_t new_y, size_t old_x, size_t old_y);
|
||||
void gterm_scroll(void);
|
||||
void gterm_revscroll(void);
|
||||
void gterm_swap_palette(void);
|
||||
void gterm_save_state(void);
|
||||
void gterm_restore_state(void);
|
||||
|
||||
void gterm_double_buffer_flush(void);
|
||||
|
||||
|
@ -51,7 +51,10 @@ void term_vbe(size_t width, size_t height) {
|
||||
scroll_enable = gterm_scroll_enable;
|
||||
term_move_character = gterm_move_character;
|
||||
term_scroll = gterm_scroll;
|
||||
term_revscroll = gterm_revscroll;
|
||||
term_swap_palette = gterm_swap_palette;
|
||||
term_save_state = gterm_save_state;
|
||||
term_restore_state = gterm_restore_state;
|
||||
|
||||
term_double_buffer_flush = gterm_double_buffer_flush;
|
||||
|
||||
|
@ -30,6 +30,11 @@ extern struct term_context {
|
||||
size_t scroll_top_margin;
|
||||
size_t scroll_bottom_margin;
|
||||
uint32_t esc_values[MAX_ESC_VALUES];
|
||||
|
||||
bool saved_state_bold;
|
||||
bool saved_state_reverse_video;
|
||||
size_t saved_state_current_charset;
|
||||
size_t saved_state_current_primary;
|
||||
} term_context;
|
||||
|
||||
enum {
|
||||
@ -71,7 +76,10 @@ extern bool (*scroll_disable)(void);
|
||||
extern void (*scroll_enable)(void);
|
||||
extern void (*term_move_character)(size_t new_x, size_t new_y, size_t old_x, size_t old_y);
|
||||
extern void (*term_scroll)(void);
|
||||
extern void (*term_revscroll)(void);
|
||||
extern void (*term_swap_palette)(void);
|
||||
extern void (*term_save_state)(void);
|
||||
extern void (*term_restore_state)(void);
|
||||
|
||||
extern void (*term_double_buffer_flush)(void);
|
||||
|
||||
|
@ -66,7 +66,10 @@ void term_notready(void) {
|
||||
scroll_enable = notready_void;
|
||||
term_move_character = notready_move_character;
|
||||
term_scroll = notready_void;
|
||||
term_revscroll = notready_void;
|
||||
term_swap_palette = notready_void;
|
||||
term_save_state = notready_void;
|
||||
term_restore_state = notready_void;
|
||||
term_double_buffer_flush = notready_void;
|
||||
term_context_size = notready_context_size;
|
||||
term_context_save = notready_uint64_t;
|
||||
@ -207,7 +210,10 @@ bool (*scroll_disable)(void);
|
||||
void (*scroll_enable)(void);
|
||||
void (*term_move_character)(size_t new_x, size_t new_y, size_t old_x, size_t old_y);
|
||||
void (*term_scroll)(void);
|
||||
void (*term_revscroll)(void);
|
||||
void (*term_swap_palette)(void);
|
||||
void (*term_save_state)(void);
|
||||
void (*term_restore_state)(void);
|
||||
|
||||
void (*term_double_buffer_flush)(void);
|
||||
|
||||
@ -241,6 +247,11 @@ struct term_context term_context;
|
||||
#define charsets term_context.charsets
|
||||
#define g_select term_context.g_select
|
||||
|
||||
#define saved_state_bold term_context.saved_state_bold
|
||||
#define saved_state_reverse_video term_context.saved_state_reverse_video
|
||||
#define saved_state_current_charset term_context.saved_state_current_charset
|
||||
#define saved_state_current_primary term_context.saved_state_current_primary
|
||||
|
||||
#define CHARSET_DEFAULT 0
|
||||
#define CHARSET_DEC_SPECIAL 1
|
||||
|
||||
@ -296,7 +307,10 @@ void term_textmode(void) {
|
||||
scroll_enable = text_scroll_enable;
|
||||
term_move_character = text_move_character;
|
||||
term_scroll = text_scroll;
|
||||
term_revscroll = text_revscroll;
|
||||
term_swap_palette = text_swap_palette;
|
||||
term_save_state = text_save_state;
|
||||
term_restore_state = text_restore_state;
|
||||
|
||||
term_double_buffer_flush = text_double_buffer_flush;
|
||||
|
||||
@ -897,6 +911,24 @@ cleanup:
|
||||
escape = false;
|
||||
}
|
||||
|
||||
static void restore_state(void) {
|
||||
bold = saved_state_bold;
|
||||
reverse_video = saved_state_reverse_video;
|
||||
current_charset = saved_state_current_charset;
|
||||
current_primary = saved_state_current_primary;
|
||||
|
||||
term_restore_state();
|
||||
}
|
||||
|
||||
static void save_state(void) {
|
||||
term_save_state();
|
||||
|
||||
saved_state_bold = bold;
|
||||
saved_state_reverse_video = reverse_video;
|
||||
saved_state_current_charset = current_charset;
|
||||
saved_state_current_primary = current_primary;
|
||||
}
|
||||
|
||||
static void escape_parse(uint8_t c) {
|
||||
escape_offset++;
|
||||
|
||||
@ -922,6 +954,12 @@ is_csi:
|
||||
rrr = false;
|
||||
control_sequence = true;
|
||||
return;
|
||||
case '7':
|
||||
save_state();
|
||||
break;
|
||||
case '8':
|
||||
restore_state();
|
||||
break;
|
||||
case 'c':
|
||||
term_reinit();
|
||||
clear(true);
|
||||
@ -944,7 +982,12 @@ is_csi:
|
||||
break;
|
||||
case 'M':
|
||||
// "Reverse linefeed"
|
||||
set_cursor_pos(x, y - 1);
|
||||
if (y == scroll_top_margin) {
|
||||
term_revscroll();
|
||||
set_cursor_pos(0, y);
|
||||
} else {
|
||||
set_cursor_pos(0, y - 1);
|
||||
}
|
||||
break;
|
||||
case 'Z':
|
||||
if (term_callback != NULL) {
|
||||
|
Loading…
Reference in New Issue
Block a user