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;