shithub: orca

Download patch

ref: 655c657d070ebf46a869a90b1bc79a3601692247
parent: 37d24eaeea5017212d9fcad84619089603f6b64f
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Sat Feb 15 13:03:03 EST 2020

plan9: redraw only parts of the field that were changed, helps with huge fields

--- a/plan9.c
+++ b/plan9.c
@@ -52,6 +52,9 @@
 	Dblow,
 	Dbinv,
 	Numcolors,
+
+	/* this might become a bad idea in the future */
+	Mark_flag_selected = 1<<7,
 };
 
 struct Key {
@@ -68,11 +71,11 @@
 static int selw = 1, selh = 1;
 static int charw, charh;
 static Field field;
-static Mbuf_reusable mbuf;
+static Mbuf_reusable mbuf, mscr;
 static Oevent_list events;
 static char filename[256];
 static Channel *cchan;
-static Field copyfield;
+static Field copyfield, selfield;
 static int altdown;
 static int mode = Minsert;
 static long framedev; /* frame deviation >= 1ms */
@@ -312,7 +315,7 @@
 	Rectangle r;
 	Point p, top, bot;
 	int x, y, rx, ry, i;
-	int oldbg, oldfg, bg, fg, attr, selected;
+	int oldbg, oldfg, bg, fg, attr, selected, off;
 	char s[32];
 	Rune c;
 
@@ -336,20 +339,38 @@
 	bg = -1;
 	fg = -1;
 	for (y = 0; y < field.height && p.y < bot.y-charh; y++) {
+		p.x = top.x;
 		for (x = i = 0; x < field.width && x < screen->r.max.x-Txtoff; x++) {
 			oldbg = bg;
 			oldfg = fg;
+			off = field.width*y + x;
 
-			c = field.buffer[field.width*y + x];
-			attr = mbuf.buffer[field.width*y + x];
+			c = field.buffer[off];
+			attr = mbuf.buffer[off];
+			selected = x >= curx && y >= cury && x < curx+selw && y < cury+selh;
+			if (selected)
+				attr |= Mark_flag_selected;
+			else
+				attr &= ~Mark_flag_selected;
 
-			if (c == '.')
-				c = dot[dotstyle];
+			if (!complete && c == copyfield.buffer[off] && attr == mscr.buffer[off]) {
+				if (i > 0) {
+					p = runestringnbg(screen, p, color[oldfg], ZP, font, linebuf, i, color[oldbg], ZP);
+					i = 0;
+				}
+				p.x += charw;
+				continue;
+			}
 
-			selected = x >= curx && y >= cury && x < curx+selw && y < cury+selh;
+			copyfield.buffer[off] = c;
+			mscr.buffer[off] = attr;
+
 			bg = selected ? Dbinv : Dback;
 			fg = selected ? Dfinv : Dfhigh;
 
+			if (c == '.')
+				c = dot[dotstyle];
+
 			if (c == dot[dotstyle] && attr == 0) {
 				if ((x % gridw) == 0 && (y % gridh) == 0) {
 					rx = !!x + (x + 1) / field.width;
@@ -391,7 +412,6 @@
 		}
 		runestringnbg(screen, p, color[fg], ZP, font, linebuf, i, color[bg], ZP);
 		p.y += charh;
-		p.x = top.x;
 	}
 
 	r = screen->r;
@@ -510,31 +530,28 @@
 static void
 selmove(int x, int y)
 {
-	int i;
+	int i, n;
 
 	if (curx+x < 0 || cury+y < 0)
 		return;
 
-	field_resize_raw(&copyfield, selh, selw);
+	field_resize_raw(&selfield, selh, selw);
 	gbuffer_copy_subrect(
-		field.buffer,
-		copyfield.buffer,
-		field.height, field.width,
-		copyfield.height, copyfield.width,
-		cury, curx, 0, 0,
-		selh, selw
+		field.buffer, selfield.buffer,
+		field.height, field.width, selh, selw,
+		cury, curx, 0, 0, selh, selw
 	);
 
-	for (i = cury; i < cury+selh && i < field.height; i++)
-		memset(&field.buffer[curx + field.width*i], '.', MIN(selw, field.width-curx));
+	n = MIN(selw, field.width-curx);
+	for (i = cury; i < cury+selh && i < field.height; i++) {
+		memset(&field.buffer[curx + field.width*i], '.', n);
+		memset(&mbuf.buffer[curx + field.width*i], 0, n);
+	}
 
 	gbuffer_copy_subrect(
-		copyfield.buffer,
-		field.buffer,
-		copyfield.height, copyfield.width,
-		field.height, field.width,
-		0, 0, cury+y, curx+x,
-		selh, selw
+		selfield.buffer, field.buffer,
+		selh, selw, field.height, field.width,
+		0, 0, cury+y, curx+x, selh, selw
 	);
 }
 
@@ -688,12 +705,19 @@
 
 	screensize(&w, &h);
 	field_init_fill(&field, h, w, '.');
-	field_init(&copyfield);
+	field_init_fill(&copyfield, h, w, '.');
+	field_init(&selfield);
 
 	linebuf = malloc(sizeof(Rune)*MAX(w+1, 64));
 	memset(noteoff, 0, sizeof(noteoff));
+
 	mbuf_reusable_init(&mbuf);
 	mbuf_reusable_ensure_size(&mbuf, h, w);
+	memset(mbuf.buffer, 0, w*h);
+	mbuf_reusable_init(&mscr);
+	mbuf_reusable_ensure_size(&mscr, h, w);
+	memset(mscr.buffer, 0, w*h);
+
 	oevent_list_init(&events);
 
 	proccreate(orcathread, a[Credraw].c, mainstacksize);
@@ -721,10 +745,8 @@
 							w = field.width;
 							h = field.height;
 							strncpy(filename, tmp, sizeof(filename));
-							complete = 1;
 						} else if (n == Menu3save && fieldsave(tmp) == 0) {
 							strncpy(filename, tmp, sizeof(filename));
-							complete = 1;
 						}
 					}
 				} else if (n == Menu3dotstyle) {
@@ -734,6 +756,7 @@
 				} else if (n == Menu3exit) {
 					goto end;
 				}
+				complete = 1;
 			}
 			break;
 
@@ -904,34 +927,40 @@
 //					fprint(2, "unhandled key %04x\n", key.rune);
 				break;
 			}
-
-			if (w != oldw || h != oldh) {
-				field_copy(&field, &copyfield);
-				field_resize_raw(&field, h, w);
-				memset(field.buffer, '.', w*h);
-				gbuffer_copy_subrect(
-					copyfield.buffer,
-					field.buffer,
-					copyfield.height, copyfield.width,
-					field.height, field.width,
-					0, 0, 0, 0,
-					MIN(field.height, copyfield.height), MIN(field.width, copyfield.width)
-				);
-			}
 		}
 
 		if (w != oldw || h != oldh) {
+			mbuf_reusable_ensure_size(&mscr, h, w);
+			memset(mscr.buffer, 0, w*h);
+			for (n = 0; n < oldh; n++)
+				memmove(&mscr.buffer[n*w], &mbuf.buffer[n*oldw], oldw);
 			mbuf_reusable_ensure_size(&mbuf, h, w);
+			memmove(mbuf.buffer, mscr.buffer, w*h);
 			linebuf = realloc(linebuf, sizeof(Rune)*MAX(w+1, 64));
+
+			field_resize_raw(&copyfield, h, w);
+			field_copy(&field, &copyfield);
+			field_resize_raw(&field, h, w);
+			memset(field.buffer, '.', w*h);
+			gbuffer_copy_subrect(
+				copyfield.buffer, field.buffer,
+				copyfield.height, copyfield.width, h, w,
+				0, 0, 0, 0, MIN(h, copyfield.height), MIN(w, copyfield.width)
+			);
+			field_resize_raw(&copyfield, h, w);
+
 			complete = 1;
 		}
 	}
 
 end:
+	mbuf_reusable_deinit(&mscr);
 	mbuf_reusable_deinit(&mbuf);
 	oevent_list_deinit(&events);
 	field_deinit(&field);
 	field_deinit(&copyfield);
+	field_deinit(&selfield);
+	free(linebuf);
 
 	threadexitsall(nil);
 }