Rudimentary (incomplete) alternate screen support

This commit is contained in:
K. Lange 2018-08-28 20:08:58 +09:00
parent fcbcb51ec2
commit d5aab96199
4 changed files with 76 additions and 29 deletions

View File

@ -900,6 +900,7 @@ term_callbacks_t term_callbacks = {
unsupported_int, unsupported_int,
unsupported_int, unsupported_int,
term_set_csr_show, term_set_csr_show,
NULL,
}; };
void reinit(int send_sig) { void reinit(int send_sig) {

View File

@ -91,7 +91,14 @@ static uint32_t current_fg = 7; /* Current foreground color */
static uint32_t current_bg = 0; /* Current background color */ static uint32_t current_bg = 0; /* Current background color */
static term_cell_t * term_buffer = NULL; /* The terminal cell buffer */ static term_cell_t * term_buffer = NULL; /* The terminal cell buffer */
static term_cell_t * term_buffer_a = NULL;
static term_cell_t * term_buffer_b = NULL;
static term_state_t * ansi_state = NULL; /* ANSI parser library state */ static term_state_t * ansi_state = NULL; /* ANSI parser library state */
static int active_buffer = 0;
static int _orig_x = 0;
static int _orig_y = 0;
static uint32_t _orig_fg = 7;
static uint32_t _orig_bg = 0;
static bool cursor_on = 1; /* Whether or not the cursor should be rendered */ static bool cursor_on = 1; /* Whether or not the cursor should be rendered */
static bool _fullscreen = 0; /* Whether or not we are running in fullscreen mode (GUI only) */ static bool _fullscreen = 0; /* Whether or not we are running in fullscreen mode (GUI only) */
@ -1278,6 +1285,26 @@ static void term_clear(int i) {
flush_unused_images(); flush_unused_images();
} }
#define SWAP(T,a,b) do { T _a = a; a = b; b = _a; } while(0);
static void term_switch_buffer(int buffer) {
if (buffer != 0 && buffer != 1) return;
if (buffer != active_buffer) {
active_buffer = buffer;
term_buffer = active_buffer == 0 ? term_buffer_a : term_buffer_b;
SWAP(int, csr_x, _orig_x);
SWAP(int, csr_y, _orig_y);
SWAP(uint32_t, current_fg, _orig_fg);
SWAP(uint32_t, current_bg, _orig_bg);
term_redraw_all();
display_flip();
}
}
/* ANSI callbacks */ /* ANSI callbacks */
term_callbacks_t term_callbacks = { term_callbacks_t term_callbacks = {
term_write, term_write,
@ -1295,6 +1322,7 @@ term_callbacks_t term_callbacks = {
term_get_cell_width, term_get_cell_width,
term_get_cell_height, term_get_cell_height,
term_set_csr_show, term_set_csr_show,
term_switch_buffer,
}; };
/* Write data into the PTY */ /* Write data into the PTY */
@ -1536,6 +1564,33 @@ static void check_for_exit(void) {
write(fd_slave, exit_message, sizeof(exit_message)); write(fd_slave, exit_message, sizeof(exit_message));
} }
static term_cell_t * copy_terminal(int old_width, int old_height, term_cell_t * term_buffer) {
term_cell_t * new_term_buffer = malloc(sizeof(term_cell_t) * term_width * term_height);
memset(new_term_buffer, 0x0, sizeof(term_cell_t) * term_width * term_height);
int offset = 0;
if (term_height < old_height) {
while (csr_y >= term_height) {
offset++;
old_height--;
csr_y--;
}
}
for (int row = 0; row < min(old_height, term_height); ++row) {
for (int col = 0; col < min(old_width, term_width); ++col) {
term_cell_t * old_cell = (term_cell_t *)((uintptr_t)term_buffer + ((row + offset) * old_width + col) * sizeof(term_cell_t));
term_cell_t * new_cell = (term_cell_t *)((uintptr_t)new_term_buffer + (row * term_width + col) * sizeof(term_cell_t));
*new_cell = *old_cell;
}
}
if (csr_x >= term_width) {
csr_x = term_width-1;
}
return new_term_buffer;
}
/* Reinitialize the terminal after a resize. */ /* Reinitialize the terminal after a resize. */
static void reinit(int send_sig) { static void reinit(int send_sig) {
@ -1561,34 +1616,25 @@ static void reinit(int send_sig) {
term_width = window_width / char_width; term_width = window_width / char_width;
term_height = window_height / char_height; term_height = window_height / char_height;
if (term_buffer) { if (term_buffer) {
term_cell_t * new_term_buffer = malloc(sizeof(term_cell_t) * term_width * term_height); term_cell_t * new_a = copy_terminal(old_width, old_height, term_buffer_a);
term_cell_t * new_b = copy_terminal(old_width, old_height, term_buffer_b);
memset(new_term_buffer, 0x0, sizeof(term_cell_t) * term_width * term_height); free(term_buffer_a);
term_buffer_a = new_a;
int offset = 0; free(term_buffer_b);
if (term_height < old_height) { term_buffer_b = new_b;
while (csr_y >= term_height) { if (active_buffer == 0) {
offset++; term_buffer = new_a;
old_height--; } else {
csr_y--; term_buffer = new_b;
}
} }
for (int row = 0; row < min(old_height, term_height); ++row) {
for (int col = 0; col < min(old_width, term_width); ++col) {
term_cell_t * old_cell = (term_cell_t *)((uintptr_t)term_buffer + ((row + offset) * old_width + col) * sizeof(term_cell_t));
term_cell_t * new_cell = (term_cell_t *)((uintptr_t)new_term_buffer + (row * term_width + col) * sizeof(term_cell_t));
*new_cell = *old_cell;
}
}
if (csr_x >= term_width) {
csr_x = term_width-1;
}
free(term_buffer);
term_buffer = new_term_buffer;
} else { } else {
term_buffer = malloc(sizeof(term_cell_t) * term_width * term_height); term_buffer_a = malloc(sizeof(term_cell_t) * term_width * term_height);
memset(term_buffer, 0x0, sizeof(term_cell_t) * term_width * term_height); memset(term_buffer_a, 0x0, sizeof(term_cell_t) * term_width * term_height);
term_buffer_b = malloc(sizeof(term_cell_t) * term_width * term_height);
memset(term_buffer_b, 0x0, sizeof(term_cell_t) * term_width * term_height);
term_buffer = term_buffer_a;
} }
/* Reset the ANSI library, ensuring we keep certain values */ /* Reset the ANSI library, ensuring we keep certain values */

View File

@ -32,6 +32,7 @@ typedef struct {
int (*get_cell_width)(void); int (*get_cell_width)(void);
int (*get_cell_height)(void); int (*get_cell_height)(void);
void (*set_csr_on)(int); void (*set_csr_on)(int);
void (*switch_buffer)(int);
} term_callbacks_t; } term_callbacks_t;
typedef struct { typedef struct {

View File

@ -311,8 +311,7 @@ static void _ansi_put(term_state_t * s, char c) {
case ANSI_SHOW: case ANSI_SHOW:
if (argc > 0) { if (argc > 0) {
if (!strcmp(argv[0], "?1049")) { if (!strcmp(argv[0], "?1049")) {
callbacks->cls(2); if (callbacks->switch_buffer) callbacks->switch_buffer(1);
callbacks->set_csr(0,0);
} else if (!strcmp(argv[0], "?1000")) { } else if (!strcmp(argv[0], "?1000")) {
s->mouse_on = 1; s->mouse_on = 1;
} else if (!strcmp(argv[0], "?1002")) { } else if (!strcmp(argv[0], "?1002")) {
@ -325,7 +324,7 @@ static void _ansi_put(term_state_t * s, char c) {
case ANSI_HIDE: case ANSI_HIDE:
if (argc > 0) { if (argc > 0) {
if (!strcmp(argv[0], "?1049")) { if (!strcmp(argv[0], "?1049")) {
/* TODO: Unimplemented */ if (callbacks->switch_buffer) callbacks->switch_buffer(0);
} else if (!strcmp(argv[0], "?1000")) { } else if (!strcmp(argv[0], "?1000")) {
s->mouse_on = 0; s->mouse_on = 0;
} else if (!strcmp(argv[0], "?1002")) { } else if (!strcmp(argv[0], "?1002")) {