Browse Source

terminal: implement IL/DL in vga terminal; experiment with scrollable regions

K. Lange 2 years ago
parent
commit
1abba60e76
4 changed files with 115 additions and 33 deletions
  1. 46 11
      apps/bim.c
  2. 48 22
      apps/terminal-vga.c
  3. 3 0
      base/usr/include/toaru/termemu.h
  4. 18 0
      lib/termemu.c

+ 46 - 11
apps/bim.c

@@ -1,9 +1,9 @@
 /**
  * This is a baked, single-file version of bim.
- * It was built Tue Dec 17 13:18:29 2019
- * It is based on git commit 2f4da2036745c3f1b7d532988f346abcca0e59eb
+ * It was built Thu Dec 19 13:41:35 2019
+ * It is based on git commit 8860761a4e0906246a38f41939551fe7ed050c5b
  */
-#define GIT_TAG "2f4da20-baked"
+#define GIT_TAG "8860761-baked"
 /* Bim - A Text Editor
  *
  * Copyright (C) 2012-2019 K. Lange
@@ -197,6 +197,7 @@ typedef struct {
 	unsigned int can_24bit:1;
 	unsigned int can_256color:1;
 	unsigned int can_italic:1;
+	unsigned int can_insert:1;
 	unsigned int history_enabled:1;
 	unsigned int highlight_parens:1;
 	unsigned int smart_case:1;
@@ -639,6 +640,7 @@ global_config_t global_config = {
 	.can_24bit = 1, /* can use 24-bit color */
 	.can_256color = 1, /* can use 265 colors */
 	.can_italic = 1, /* can use italics (without inverting) */
+	.can_insert = 0, /* ^[[L */
 	/* Configuration options */
 	.history_enabled = 1,
 	.highlight_parens = 1, /* highlight parens/braces when cursor moves */
@@ -2396,6 +2398,16 @@ void shift_down(int amount) {
 	printf("\033[%dT", amount);
 }
 
+void insert_lines_at(int line, int count) {
+	place_cursor(1, line);
+	printf("\033[%dL", count);
+}
+
+void delete_lines_at(int line, int count) {
+	place_cursor(1, line);
+	printf("\033[%dM", count);
+}
+
 /**
  * Switch to the alternate terminal screen.
  */
@@ -4507,7 +4519,12 @@ BIM_ACTION(cursor_down, 0,
 
 			/* Tell terminal to scroll */
 			if (global_config.can_scroll && !left_buffer) {
-				shift_up(1);
+				if (!global_config.can_insert) {
+					shift_up(1);
+					redraw_tabbar();
+				} else {
+					delete_lines_at(global_config.tabs_visible ? 2 : 1, 1);
+				}
 
 				/* A new line appears on screen at the bottom, draw it */
 				int l = global_config.term_height - global_config.bottom_size - global_config.tabs_visible;
@@ -4519,7 +4536,6 @@ BIM_ACTION(cursor_down, 0,
 			} else {
 				redraw_text();
 			}
-			redraw_tabbar();
 			redraw_statusbar();
 			redraw_commandline();
 			place_cursor_actual();
@@ -4593,7 +4609,12 @@ BIM_ACTION(cursor_up, 0,
 
 			/* Tell terminal to scroll */
 			if (global_config.can_scroll && !left_buffer) {
-				shift_down(1);
+				if (!global_config.can_insert) {
+					shift_down(1);
+					redraw_tabbar();
+				} else {
+					insert_lines_at(global_config.tabs_visible ? 2 : 1, 1);
+				}
 
 				/*
 				 * The line at the top of the screen should always be real
@@ -4601,9 +4622,9 @@ BIM_ACTION(cursor_up, 0,
 				 */
 				redraw_line(env->offset);
 			} else {
+				redraw_tabbar();
 				redraw_text();
 			}
-			redraw_tabbar();
 			redraw_statusbar();
 			redraw_commandline();
 			place_cursor_actual();
@@ -7058,14 +7079,19 @@ void handle_common_mouse(int buttons, int x, int y) {
 			env->loading = 0;
 			if (!shifted) return;
 			if (global_config.can_scroll && !left_buffer) {
-				shift_down(shifted);
+				if (!global_config.can_insert) {
+					shift_down(shifted);
+					redraw_tabbar();
+				} else {
+					insert_lines_at(global_config.tabs_visible ? 2 : 1, shifted);
+				}
 				for (int i = 0; i < shifted; ++i) {
 					redraw_line(env->offset+i);
 				}
 			} else {
+				redraw_tabbar();
 				redraw_text();
 			}
-			redraw_tabbar();
 			redraw_statusbar();
 			redraw_commandline();
 			place_cursor_actual();
@@ -7093,7 +7119,12 @@ void handle_common_mouse(int buttons, int x, int y) {
 			env->loading = 0;
 			if (!shifted) return;
 			if (global_config.can_scroll && !left_buffer) {
-				shift_up(shifted);
+				if (!global_config.can_insert) {
+					shift_up(shifted);
+					redraw_tabbar();
+				} else {
+					delete_lines_at(global_config.tabs_visible ? 2 : 1, shifted);
+				}
 				int l = global_config.term_height - global_config.bottom_size - global_config.tabs_visible;
 				for (int i = 0; i < shifted; ++i) {
 					if (env->offset + l - i < env->line_count + 1) {
@@ -7103,9 +7134,9 @@ void handle_common_mouse(int buttons, int x, int y) {
 					}
 				}
 			} else {
+				redraw_tabbar();
 				redraw_text();
 			}
-			redraw_tabbar();
 			redraw_statusbar();
 			redraw_commandline();
 			place_cursor_actual();
@@ -10258,6 +10289,10 @@ void detect_weird_terminals(void) {
 	if (term && strstr(term,"toaru-vga") == term) {
 		global_config.can_24bit = 0; /* Also not strictly true */
 		global_config.can_256color = 0; /* Not strictly true */
+		global_config.can_insert = 1;
+	}
+	if (term && strstr(term,"xterm-256color") == term) {
+		global_config.can_insert = 1;
 	}
 
 	if (!global_config.can_unicode) {

+ 48 - 22
apps/terminal-vga.c

@@ -503,32 +503,57 @@ void term_redraw_all() {
 	}
 }
 
-void term_scroll(int how_much) {
-	if (how_much >= term_height || -how_much >= term_height) {
-		term_clear();
-		return;
+void term_shift_region(int top, int height, int how_much) {
+	if (how_much == 0) return;
+
+	void * destination, * source;
+	int count, new_top, new_bottom;
+	if (how_much > height) {
+		count = 0;
+		new_top = top;
+		new_bottom = top + height;
+	} else if (how_much > 0) {
+		destination = term_buffer + term_width * top;
+		source = term_buffer + term_width * (top + how_much);
+		count = height - how_much;
+		new_top = top + height - how_much;
+		new_bottom = top + height;
+	} else if (how_much < 0) {
+		destination = term_buffer + term_width * (top - how_much);
+		source = term_buffer + term_width * top;
+		count = height + how_much;
+		new_top = top;
+		new_bottom = top - how_much;
 	}
-	if (how_much == 0) {
-		return;
+
+	/* Move from top+how_much to top */
+	if (count) {
+		memmove(destination, source, count * term_width * sizeof(term_cell_t));
+		
 	}
-	if (how_much > 0) {
-		/* Shift terminal cells one row up */
-		memmove(term_buffer, (void *)((uintptr_t)term_buffer + sizeof(term_cell_t) * term_width * how_much), sizeof(term_cell_t) * term_width * (term_height - how_much));
-		/* Reset the "new" row to clean cells */
-		memset((void *)((uintptr_t)term_buffer + sizeof(term_cell_t) * term_width * (term_height - how_much)), 0x0, sizeof(term_cell_t) * term_width * how_much);
-		for (int i = 0; i < how_much; ++i) {
-			for (uint16_t x = 0; x < term_width; ++x) {
-				cell_set(x,term_height - how_much,' ', current_fg, current_bg, ansi_state->flags);
-			}
+
+	/* Clear new lines at bottom */
+	for (int i = new_top; i < new_bottom; ++i) {
+		for (uint16_t x = 0; x < term_width; ++x) {
+			cell_set(x, i, ' ', current_fg, current_bg, ansi_state->flags);
 		}
-		term_redraw_all();
+	}
+
+	term_redraw_all();
+}
+
+void term_scroll(int how_much) {
+	term_shift_region(0,term_height,how_much);
+}
+
+void insert_delete_lines(int how_many) {
+	if (how_many == 0) return;
+
+	if (how_many > 0) {
+		/* Insert lines is equivalent to scrolling from the current line */
+		term_shift_region(csr_y,term_height-csr_y,-how_many);
 	} else {
-		how_much = -how_much;
-		/* Shift terminal cells one row up */
-		memmove((void *)((uintptr_t)term_buffer + sizeof(term_cell_t) * term_width * how_much), term_buffer, sizeof(term_cell_t) * term_width * (term_height - how_much));
-		/* Reset the "new" row to clean cells */
-		memset(term_buffer, 0x0, sizeof(term_cell_t) * term_width * how_much);
-		term_redraw_all();
+		term_shift_region(csr_y,term_height-csr_y,-how_many);
 	}
 }
 
@@ -910,6 +935,7 @@ term_callbacks_t term_callbacks = {
 	unsupported_int,
 	term_set_csr_show,
 	term_switch_buffer,
+	insert_delete_lines,
 };
 
 void reinit(void) {

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

@@ -37,6 +37,7 @@ typedef struct {
 	int  (*get_cell_height)(void);
 	void (*set_csr_on)(int);
 	void (*switch_buffer)(int);
+	void (*insert_delete_lines)(int);
 } term_callbacks_t;
 
 typedef struct {
@@ -90,6 +91,8 @@ typedef struct {
 #define ANSI_RCP    'u' /* Restore Cursor Position    */
 #define ANSI_HIDE   'l' /* DECTCEM - Hide Cursor      */
 #define ANSI_SHOW   'h' /* DECTCEM - Show Cursor      */
+#define ANSI_IL     'L' /* Insert Line(s)             */
+#define ANSI_DL     'M' /* Delete Line(s)             */
 /* Display flags */
 #define ANSI_BOLD      0x01
 #define ANSI_UNDERLINE 0x02

+ 18 - 0
lib/termemu.c

@@ -450,6 +450,24 @@ static void _ansi_put(term_state_t * s, char c) {
 							callbacks->scroll(-how_many);
 						}
 						break;
+					case ANSI_IL:
+						{
+							int how_many = 1;
+							if (argc > 0) {
+								how_many = atoi(argv[0]);
+							}
+							callbacks->insert_delete_lines(how_many);
+						}
+						break;
+					case ANSI_DL:
+						{
+							int how_many = 1;
+							if (argc > 0) {
+								how_many = atoi(argv[0]);
+							}
+							callbacks->insert_delete_lines(-how_many);
+						}
+						break;
 					case 'X':
 						{
 							int how_many = 1;