Browse Source

Rudimentary (incomplete) alternate screen support

K. Lange 3 years ago
parent
commit
d5aab96199
4 changed files with 76 additions and 29 deletions
  1. 1 0
      apps/terminal-vga.c
  2. 72 26
      apps/terminal.c
  3. 1 0
      base/usr/include/toaru/termemu.h
  4. 2 3
      lib/termemu.c

+ 1 - 0
apps/terminal-vga.c

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

+ 72 - 26
apps/terminal.c

@@ -91,7 +91,14 @@ static uint32_t current_fg     = 7;    /* Current foreground 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_a = NULL;
+static term_cell_t * term_buffer_b = NULL;
 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 _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();
 }
 
+
+#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 */
 term_callbacks_t term_callbacks = {
 	term_write,
@@ -1295,6 +1322,7 @@ term_callbacks_t term_callbacks = {
 	term_get_cell_width,
 	term_get_cell_height,
 	term_set_csr_show,
+	term_switch_buffer,
 };
 
 /* Write data into the PTY */
@@ -1536,6 +1564,33 @@ static void check_for_exit(void) {
 	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. */
 static void reinit(int send_sig) {
 
@@ -1561,34 +1616,25 @@ static void reinit(int send_sig) {
 	term_width  = window_width  / char_width;
 	term_height = window_height / char_height;
 	if (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;
+		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);
+		free(term_buffer_a);
+		term_buffer_a = new_a;
+		free(term_buffer_b);
+		term_buffer_b = new_b;
+		if (active_buffer == 0) {
+			term_buffer = new_a;
+		} else {
+			term_buffer = new_b;
 		}
-		free(term_buffer);
-
-		term_buffer = new_term_buffer;
 	} else {
-		term_buffer = malloc(sizeof(term_cell_t) * term_width * term_height);
-		memset(term_buffer, 0x0, sizeof(term_cell_t) * term_width * term_height);
+		term_buffer_a = malloc(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 */

+ 1 - 0
base/usr/include/toaru/termemu.h

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

+ 2 - 3
lib/termemu.c

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