Browse Source

terminal: support IL/DL in graphical terminal; update bim

K. Lange 1 year ago
parent
commit
89495ef22e
3 changed files with 81 additions and 70 deletions
  1. 2 0
      apps/bim.c
  2. 6 7
      apps/terminal-vga.c
  3. 73 63
      apps/terminal.c

+ 2 - 0
apps/bim.c

@@ -10289,6 +10289,8 @@ 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 */
+	}
+	if (term && strstr(term,"toaru") == term) {
 		global_config.can_insert = 1;
 	}
 	if (term && strstr(term,"xterm-256color") == term) {

+ 6 - 7
apps/terminal-vga.c

@@ -506,21 +506,21 @@ void term_redraw_all() {
 void term_shift_region(int top, int height, int how_much) {
 	if (how_much == 0) return;
 
-	void * destination, * source;
+	int 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);
+		destination = term_width * top;
+		source = 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;
+		destination = term_width * (top - how_much);
+		source = term_width * top;
 		count = height + how_much;
 		new_top = top;
 		new_bottom = top - how_much;
@@ -528,8 +528,7 @@ void term_shift_region(int top, int height, int how_much) {
 
 	/* Move from top+how_much to top */
 	if (count) {
-		memmove(destination, source, count * term_width * sizeof(term_cell_t));
-		
+		memmove(term_buffer + destination, term_buffer + source, count * term_width * sizeof(term_cell_t));
 	}
 
 	/* Clear new lines at bottom */

+ 73 - 63
apps/terminal.c

@@ -1007,6 +1007,10 @@ static void term_redraw_all() {
 	}
 }
 
+static void _menu_action_redraw(struct MenuEntry * self) {
+	term_redraw_all();
+}
+
 /* Remove no-longer-visible image cell data. */
 static void flush_unused_images(void) {
 	list_t * tmp = list_create();
@@ -1028,79 +1032,82 @@ static void flush_unused_images(void) {
 	images_list = tmp;
 }
 
-/* Scroll the terminal up or down. */
-static void term_scroll(int how_much) {
-
-	/* A large scroll request should just clear the screen. */
-	if (how_much >= term_height || -how_much >= term_height) {
-		term_clear();
-		return;
+static void term_shift_region(int top, int height, int how_much) {
+	if (how_much == 0) return;
+
+	int 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_width * top;
+		source = 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_width * (top - how_much);
+		source = term_width * top;
+		count = height + how_much;
+		new_top = top;
+		new_bottom = top - how_much;
+	}
+
+	/* Move from top+how_much to top */
+	if (count) {
+		memmove(term_buffer + destination, term_buffer + source, count * term_width * sizeof(term_cell_t));
+		/* Move displayed as well */
+		cell_redraw(csr_x, csr_y); /* Otherwise we may copy the inverted cursor */
+		uintptr_t dst = (uintptr_t)ctx->backbuffer + GFX_W(ctx) * (destination / term_width * char_height) * GFX_B(ctx);
+		uintptr_t src = (uintptr_t)ctx->backbuffer + GFX_W(ctx) * (source / term_width * char_height) * GFX_B(ctx);
+		size_t siz = count * char_height * GFX_W(ctx) * GFX_B(ctx);
+		if (!_no_frame) {
+			/*
+			 * Adjust for decorations; note that since we're copying everything, that includes the decorations!
+			 * we'll redraw them later which should account for anything we broke by doing this.
+			 */
+			dst += GFX_W(ctx) * GFX_B(ctx) * (decor_top_height + menu_bar_height);
+			src += GFX_W(ctx) * GFX_B(ctx) * (decor_top_height + menu_bar_height);
+		}
+		memmove((void*)dst, (void*)src, siz);
 	}
 
-	/* A request to scroll 0... is a request not to scroll. */
-	if (how_much == 0) {
-		return;
+	/* 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);
+			cell_redraw(x, i);
+		}
 	}
+}
 
-	/* Redraw the cursor before continuing. */
-	cell_redraw(csr_x, csr_y);
+/* Scroll the terminal up or down. */
+static void term_scroll(int how_much) {
 
-	if (how_much > 0) {
-		/* Scroll 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);
-		/* In graphical modes, we will shift the graphics buffer up as necessary */
-		uintptr_t dst, src;
-		size_t    siz = char_height * (term_height - how_much) * GFX_W(ctx) * GFX_B(ctx);
-		if (!_no_frame) {
-			/* Must include decorations */
-			dst = (uintptr_t)ctx->backbuffer + (GFX_W(ctx) * (decor_top_height+menu_bar_height)) * GFX_B(ctx);
-			src = (uintptr_t)ctx->backbuffer + (GFX_W(ctx) * (decor_top_height+menu_bar_height + char_height * how_much)) * GFX_B(ctx);
-		} else {
-			/* Can skip decorations */
-			dst = (uintptr_t)ctx->backbuffer;
-			src = (uintptr_t)ctx->backbuffer + (GFX_W(ctx) *  char_height * how_much) * GFX_B(ctx);
-		}
-		/* Perform the shift */
-		memmove((void *)dst, (void *)src, siz);
-		/* And redraw the new rows */
-		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);
-				cell_redraw(x, term_height - how_much);
-			}
-		}
-	} else {
-		how_much = -how_much;
-		/* Scroll down */
-		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);
-		uintptr_t dst, src;
-		size_t    siz = char_height * (term_height - how_much) * GFX_W(ctx) * GFX_B(ctx);
-		if (!_no_frame) {
-			src = (uintptr_t)ctx->backbuffer + (GFX_W(ctx) * (decor_top_height+menu_bar_height)) * GFX_B(ctx);
-			dst = (uintptr_t)ctx->backbuffer + (GFX_W(ctx) * (decor_top_height+menu_bar_height + char_height * how_much)) * GFX_B(ctx);
-		} else {
-			src = (uintptr_t)ctx->backbuffer;
-			dst = (uintptr_t)ctx->backbuffer + (GFX_W(ctx) *  char_height * how_much) * GFX_B(ctx);
-		}
-		/* Perform the shift */
-		memmove((void *)dst, (void *)src, siz);
-		/* And redraw the new rows */
-		for (int i = 0; i < how_much; ++i) {
-			for (uint16_t x = 0; x < term_width; ++x) {
-				cell_redraw(x, i);
-			}
-		}
-	}
+	term_shift_region(0, term_height, how_much);
 
 	/* Remove image data for image cells that are no longer on screen. */
 	flush_unused_images();
 
 	/* Flip the entire window. */
-	yutani_flip(yctx, window);
+	if (!_fullscreen) {
+		render_decors();
+	} else {
+		yutani_flip(yctx, window);
+	}
+}
+
+static 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 {
+		term_shift_region(csr_y,term_height-csr_y,-how_many);
+	}
 }
 
 /* Is this a wide character? (does wcwidth == 2) */
@@ -1420,6 +1427,7 @@ term_callbacks_t term_callbacks = {
 	term_get_cell_height,
 	term_set_csr_show,
 	term_switch_buffer,
+	insert_delete_lines,
 };
 
 /* Write data into the PTY */
@@ -2299,6 +2307,8 @@ int main(int argc, char ** argv) {
 	menu_insert(m, menu_create_submenu(NULL,"zoom","Set zoom..."));
 	menu_insert(m, menu_create_normal(NULL, NULL, _use_aa ? "Bitmap font" : "Anti-aliased font", _menu_action_toggle_sdf));
 	menu_insert(m, menu_create_normal(NULL, NULL, _free_size ? "Snap to Cell Size" : "Freely Resize", _menu_action_toggle_free_size));
+	menu_insert(menu_right_click, menu_create_separator());
+	menu_insert(m, menu_create_normal(NULL, NULL, "Redraw", _menu_action_redraw));
 	menu_set_insert(terminal_menu_bar.set, "view", m);
 
 	m = menu_create();