term: Support for reverse scroll, save/restore, and bug fixes

This commit is contained in:
mintsuki 2022-01-18 23:46:25 +01:00
parent 58a3954c51
commit 4d6e1b801a
7 changed files with 145 additions and 8 deletions

View File

@ -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);

View File

@ -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] = ' ';

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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) {