shithub: orca

Download patch

ref: 7f5bd9984baea651694f8bd32fa49a00d31297c2
parent: a92bffafd4ec2f8a22590249846ea376ea3e1011
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Sun Feb 16 19:47:37 EST 2020

plan9: selection to all 4 sides, draw cursor as @

--- a/plan9.c
+++ b/plan9.c
@@ -10,8 +10,8 @@
 
 typedef struct Key Key;
 
-#define MIN(x,y) ((x)<(y)?(x):(y))
-#define MAX(x,y) ((x)>(y)?(x):(y))
+#define MIN(x,y) ((x)<=(y)?(x):(y))
+#define MAX(x,y) ((x)>=(y)?(x):(y))
 #define is_movement(c) (c == 'W' || c == 'N' || c == 'E' || c == 'S')
 #define is_send(c) (c == ':' || c == '%' || c == '!' || c == '?' || c == ';' || c == ';' || c == '$')
 
@@ -70,8 +70,9 @@
 static int gridw = 8, gridh = 8;
 static int rulerstyle = Sfancy, dotstyle = Sfancy;
 static int bpm = 120, apm = 120;
-static int curx, cury;
-static int selw = 1, selh = 1;
+static Point cur;
+static Rectangle sel;
+static int selw, selh;
 static int charw, charh;
 static Field field;
 static Mbuf_reusable mbuf, mscr;
@@ -379,7 +380,7 @@
 		draw(screen, r, color[Dback], nil, ZP);
 	}
 
-	off = field.width*cury + curx;
+	off = field.width*cur.y + cur.x;
 	csel = field.buffer[off];
 
 	bg = -1;
@@ -393,7 +394,7 @@
 
 			c = field.buffer[off];
 			attr = mbuf.buffer[off];
-			selected = x >= curx && y >= cury && x < curx+selw && y < cury+selh;
+			selected = x >= sel.min.x && y >= sel.min.y && x <= sel.max.x && y <= sel.max.y;
 			if (selected)
 				attr |= Mark_flag_selected;
 			else
@@ -400,12 +401,15 @@
 				attr &= ~Mark_flag_selected;
 
 			/* highlight the same char */
-			grouphl = c != '.' && csel == c && (x != curx || y != cury) && (attr & (Mark_flag_input|Mark_flag_lock|Mark_flag_output)) == 0;
+			grouphl = c != '.' && csel == c && (x != cur.x || y != cur.y) && (attr & (Mark_flag_input|Mark_flag_lock|Mark_flag_output)) == 0;
 			if (grouphl)
 				attr |= Mark_flag_group_highlight;
 			else
 				attr &= ~Mark_flag_group_highlight;
 
+			if (c == '.' && eqpt(Pt(x, y), cur))
+				c = '@';
+
 			if (!grouphl && !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);
@@ -490,7 +494,7 @@
 	bot.y += charh;
 
 	i = 0;
-	sprint(s, "%ud,%ud", curx, cury);
+	sprint(s, "%ud,%ud", cur.x, cur.y);
 	i += runesprint(linebuf, "%-10s", s);
 	sprint(s, "%d:%d", selw, selh);
 	i += runesprint(linebuf+i, "%-9s", s);
@@ -510,8 +514,9 @@
 		werrstr(field_load_error_string(e));
 		return -1;
 	}
-	curx = MIN(curx, field.width-1);
-	cury = MIN(cury, field.height-1);
+	memset(&cur, 0, sizeof(cur));
+	memset(&sel, 0, sizeof(sel));
+	selw = selh = 0;
 
 	return 0;
 }
@@ -529,6 +534,31 @@
 }
 
 static void
+fieldset(int x, int y, Glyph c)
+{
+	if (x < field.width && y < field.height && x >= 0 && y >= 0)
+		field.buffer[x + field.width*y] = c;
+}
+
+static void
+fieldsetn(int x, int y, Glyph c, int n)
+{
+	if (y >= 0 && y < field.height) {
+		for (; n > 0 && x < field.width; n--, x++)
+			field.buffer[x + field.width*y] = c;
+	}
+}
+
+static Glyph
+fieldget(int x, int y)
+{
+	if (x < field.width && y < field.height && x >= 0 && y >= 0)
+		return field.buffer[x + field.width*y];
+
+	return 0;
+}
+
+static void
 selset(Rune key)
 {
 	int y;
@@ -536,11 +566,8 @@
 
 	if (key == '#') {
 		commented = true;
-		for (y = cury; y < cury+selh && y < field.height && commented; y++) {
-			commented =
-				field.buffer[curx + field.width*y] == key &&
-				field.buffer[MIN(field.width-1, curx + selw-1) + field.width*y] == key;
-		}
+		for (y = sel.min.y; y <= sel.max.y && commented; y++)
+			commented = fieldget(sel.min.x, y) == key && fieldget(sel.max.x, y) == key;
 		if (commented)
 			key = '.';
 	} else {
@@ -547,12 +574,12 @@
 		commented = false;
 	}
 
-	for (y = cury; y < cury+selh && y < field.height; y++) {
+	for (y = sel.min.y; y <= sel.max.y; y++) {
 		if (key == '#' || commented) {
-			field.buffer[curx + field.width*y] = key;
-			field.buffer[MIN(field.width-1, curx + selw-1) + field.width*y] = key;
+			fieldset(sel.min.x, y, key);
+			fieldset(sel.max.x, y, key);
 		} else {
-			memset(&field.buffer[curx + field.width*y], key, MIN(field.width-curx, selw));
+			fieldsetn(sel.min.x, y, key, Dx(sel)+1);
 		}
 	}
 }
@@ -564,8 +591,8 @@
 	int y;
 
 	if ((b = Bopen("/dev/snarf", OWRITE)) != nil) {
-		for (y = cury; y < cury+selh && y < field.height; y++) {
-			Bwrite(b, &field.buffer[curx + field.width*y], MIN(selw, field.width-curx));
+		for (y = sel.min.y; y <= sel.max.y; y++) {
+			Bwrite(b, &field.buffer[sel.min.x + field.width*y], Dx(sel)+1);
 			Bputc(b, '\n');
 		}
 		Bterm(b);
@@ -580,28 +607,52 @@
 	int cols, rows, n;
 
 	if ((b = Bopen("/dev/snarf", OREAD)) != nil) {
-		for (cols = rows = 0; (s = Brdstr(b, '\n', 1)) != nil; rows++) {
+		for (cols = rows = 0; (s = Brdstr(b, '\n', 1)) != nil;) {
 			if ((n = Blinelen(b)) > cols)
-				cols = n;
-			if (cury+rows < field.height)
-				memmove(&field.buffer[curx + field.width*(cury+rows)], s, MIN(n, field.width-curx));
+				cols = MIN(n, field.width-sel.min.x);
+			if (sel.min.y+rows < field.height) {
+				memmove(&field.buffer[sel.min.x + field.width*(sel.min.y+rows)], s, MIN(n, field.width-sel.min.x));
+				rows++;
+			}
 			free(s);
 		}
-		selw = MAX(1, cols);
-		selh = MAX(1, rows);
+		// FIXME - expand properly if .min if the cur is on the right/bottom
+		sel.max.x = sel.min.x + MAX(0, cols-1);
+		sel.max.y = sel.min.y + MAX(0, rows-1);
 		Bterm(b);
 	}
 }
 
+static Point
+ptfield(Point p)
+{
+	p.x = MAX(0, MIN((int)field.width-1, p.x));
+	p.y = MAX(0, MIN((int)field.height-1, p.y));
+	return p;
+}
+
 static void
-fieldset(Rune key)
+curmove(int x, int y)
 {
+	Point xy;
+
+	xy = Pt(x, y);
+	cur = ptfield(addpt(cur, xy));
+	sel.min = ptfield(addpt(sel.min, xy));
+	sel.max = ptfield(addpt(sel.max, xy));
+
+	selw = selw < 0 ? sel.min.x - sel.max.x : sel.max.x - sel.min.x;
+	selh = selh < 0 ? sel.min.y - sel.max.y : sel.max.y - sel.min.y;
+}
+
+static void
+fieldmodeset(Rune key)
+{
 	if (mode == Minsert) {
 		selset(key);
 	} else {
-		field.buffer[curx + field.width*cury] = key;
-		if (curx < field.width-1)
-			curx++;
+		fieldset(cur.x, cur.x, key);
+		curmove(1, 0);
 	}
 }
 
@@ -608,28 +659,27 @@
 static void
 selmove(int x, int y)
 {
-	int i, n;
+	int i;
 
-	if (curx+x < 0 || cury+y < 0)
+	if (sel.min.x+x < 0 || sel.min.x >= field.width || sel.min.y+y < 0 || sel.min.y+y >= field.height)
 		return;
 
-	field_resize_raw(&selfield, selh, selw);
+	field_resize_raw(&selfield, Dy(sel), Dx(sel));
 	gbuffer_copy_subrect(
 		field.buffer, selfield.buffer,
-		field.height, field.width, selh, selw,
-		cury, curx, 0, 0, selh, selw
+		field.height, field.width, Dy(sel), Dx(sel),
+		sel.min.x, sel.min.y, 0, 0, Dy(sel), Dx(sel)
 	);
 
-	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);
+	for (i = sel.min.y; i < sel.max.y; i++) {
+		fieldsetn(sel.min.x, i, '.', Dx(sel));
+		memset(&mbuf.buffer[sel.min.x + field.width*i], 0, Dx(sel));
 	}
 
 	gbuffer_copy_subrect(
 		selfield.buffer, field.buffer,
-		selh, selw, field.height, field.width,
-		0, 0, cury+y, curx+x, selh, selw
+		Dy(sel), Dx(sel), field.height, field.width,
+		0, 0, sel.min.y+y, sel.min.x+x, Dy(sel), Dx(sel)
 	);
 }
 
@@ -638,9 +688,9 @@
 {
 	int x, y;
 
-	for (y = cury; y < cury+selh && y < field.height; y++) {
-		for (x = curx; x < curx+selw && x < field.width; x++) {
-			field.buffer[x + field.width*y] = f(field.buffer[x + field.width*y]);
+	for (y = sel.min.y; y <= sel.max.y; y++) {
+		for (x = sel.min.x; x <= sel.max.x; x++) {
+			fieldset(x, y, f(fieldget(x, y)));
 		}
 	}
 }
@@ -734,6 +784,42 @@
 	}
 }
 
+static void
+selext(int xdt, int ydt)
+{
+	if (xdt > 0) {
+		if (sel.min.x < cur.x)
+			sel.min.x += xdt;
+		else
+			sel.max.x += xdt;
+	} else {
+		if (sel.max.x > cur.x)
+			sel.max.x += xdt;
+		else
+			sel.min.x += xdt;
+	}
+
+	if (ydt > 0) {
+		if (sel.min.y < cur.y)
+			sel.min.y += ydt;
+		else
+			sel.max.y += ydt;
+	} else {
+		if (sel.max.y > cur.y)
+			sel.max.y += ydt;
+		else
+			sel.min.y += ydt;
+	}
+
+	sel.min.x = MAX(0, MIN((int)field.width-1, sel.min.x));
+	sel.max.x = MAX(0, MIN((int)field.width-1, sel.max.x));
+	sel.min.y = MAX(0, MIN((int)field.height-1, sel.min.y));
+	sel.max.y = MAX(0, MIN((int)field.height-1, sel.max.y));
+
+	selw = selw < 0 ? sel.min.x - sel.max.x : sel.max.x - sel.min.x;
+	selh = selh < 0 ? sel.min.y - sel.max.y : sel.max.y - sel.min.y;
+}
+
 void
 threadmain(int argc, char **argv)
 {
@@ -881,11 +967,11 @@
 				movey = 1;
 			case Kup:
 				if (shiftdown || mode == Mselect)
-					selh = MAX(1, selh-movey);
+					selext(0, -movey);
 				else {
 					if (altdown || mode == Mslide)
 						selmove(0, -movey);
-					cury = MAX(0, cury-movey);
+					curmove(0, -movey);
 				}
 				break;
 			case '\n': /* C-j */
@@ -892,22 +978,22 @@
 				movey = 1;
 			case Kdown:
 				if (shiftdown || mode == Mselect)
-					selh += movey;
+					selext(0, movey);
 				else {
 					if (altdown || mode == Mslide)
 						selmove(0, movey);
-					cury = MIN(h-1, cury+movey);
+					curmove(0, movey);
 				}
 				break;
 			case Kbs: /* C-h */
 				movex = 1;
 			case Kleft:
-				if (shiftdown || mode == Mselect)
-					selw = MAX(1, selw-movex);
-				else {
+				if (shiftdown || mode == Mselect) {
+					selext(-movex, 0);
+				} else {
 					if (altdown || mode == Mslide)
 						selmove(-movex, 0);
-					curx = MAX(0, curx-movex);
+					curmove(-movex, 0);
 				}
 				break;
 			case 0x0c: /* C-l */
@@ -918,34 +1004,36 @@
 				}
 			case Kright:
 				if (shiftdown || mode == Mselect)
-					selw += movex;
+					selext(movex, 0);
 				else {
 					if (altdown || mode == Mslide)
 						selmove(movex, 0);
-					curx = MIN(w-1, curx+movex);
+					curmove(movex, 0);
 				}
 				break;
 			case Ksoh: /* C-a */
 				if (shiftdown || mode == Mselect)
-					selw = curx;
-				curx = 0;
+					selext(-ORCA_X_MAX, 0);
+				else
+					curmove(-ORCA_X_MAX, 0);
 				break;
 			case Kenq: /* C-e */
 				if (shiftdown || mode == Mselect)
-					selw = field.width - curx;
+					selext(ORCA_X_MAX, 0);
 				else
-					curx = field.width-1;
+					curmove(ORCA_X_MAX, 0);
 				break;
 			case Khome:
 				if (shiftdown || mode == Mselect)
-					selh = cury;
-				cury = 0;
+					selext(0, -ORCA_Y_MAX);
+				else
+					curmove(0, -ORCA_Y_MAX);
 				break;
 			case Kend:
 				if (shiftdown || mode == Mselect)
-					selh = field.height - cury;
+					selext(0, ORCA_Y_MAX);
 				else
-					cury = field.height-1;
+					curmove(0, ORCA_Y_MAX);
 				break;
 			case 0x12: /* C-r */
 				tick = -1;
@@ -1014,8 +1102,11 @@
 			case Kesc:
 				if (mode == Mslide || mode != Minsert)
 					mode = Minsert;
-				else
-					selw = selh = 1;
+				else {
+					sel.min = cur;
+					sel.max = cur;
+					selw = selh = 0;
+				}
 				break;
 			case Kack: /* C-f */
 				forward = true;
@@ -1041,7 +1132,7 @@
 				if (key.rune == Kdel || key.rune == ' ')
 					key.rune = '.';
 				if (orca_is_valid_glyph(key.rune) || key.rune == '$') {
-					fieldset(key.rune);
+					fieldmodeset(key.rune);
 				} else {
 //					fprint(2, "unhandled key %04x\n", key.rune);
 					goto noredraw;