ref: 91d13854e587eae5f4928a042055cb471fc091a5
parent: 083ddca1a35977eaa9bb8c227a0d5c41cf237342
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Wed Feb 12 18:35:33 EST 2020
plan9: selection
--- a/plan9.c
+++ b/plan9.c
@@ -12,20 +12,27 @@
enum {
Txtoff = 16,
-
Msgredraw = 0,
};
+typedef struct Key Key;
+
static struct {
u8int u[4];
Usz at;
}noteoff[16*128]; /* 16 channels, 128 notes each */
+struct Key {
+ int down;
+ Rune rune;
+};
+
static Rune *linebuf;
static Usz tick;
static int gridw = 8, gridh = 8;
static int bpm = 120, insert = 1, pause;
static int curx, cury;
+static int selw = 1, selh = 1;
static Image *curbg;
static int charw, charh;
static Field field;
@@ -32,6 +39,7 @@
static Mbuf_reusable mbuf;
static Oevent_list events;
static char filename[256];
+static Channel *cchan;
static char *menu3i[] = {
"load",
@@ -186,8 +194,8 @@
static void
redraw(void)
{
+ Rectangle r;
Point p, top;
- Rune cursor;
int x, y, len;
draw(screen, screen->r, display->black, nil, ZP);
@@ -195,6 +203,7 @@
p.x += Txtoff;
p.y += Txtoff;
top = p;
+
for (y = 0; y < field.height; y++) {
for (x = 0; x < field.width; x++) {
Rune c = field.buffer[field.width*y + x];
@@ -201,8 +210,6 @@
if (c == L'.')
c = L'·';
linebuf[x] = c;
- if (y == cury && x == curx)
- cursor = c;
}
linebuf[x] = 0;
runestring(screen, p, display->white, ZP, font, linebuf);
@@ -249,9 +256,13 @@
/* cursor bg */
p = top;
- p.x += curx*stringwidth(font, " ");
- p.y += cury*font->height;
- runestringnbgop(screen, p, display->black, ZP, font, &cursor, 1, curbg, ZP, SoverD);
+ p.x += curx * charw;
+ p.y += cury * charh;
+ r.min = p;
+ r.max = p;
+ r.max.x += selw * charw;
+ r.max.y += selh * charh;
+ draw(screen, r, curbg, nil, ZP);
flushimage(display, 1);
}
@@ -286,9 +297,16 @@
static void
fieldset(Rune key)
{
- field.buffer[curx + field.width*cury] = key;
- if (!insert && curx < field.width-1)
- curx++;
+ int y;
+
+ if (insert) {
+ for (y = cury; y < cury+selh; y++)
+ memset(&field.buffer[curx + field.width*y], key, selw);
+ } else {
+ if (curx < field.width-1)
+ curx++;
+ field.buffer[curx + field.width*cury] = key;
+ }
}
static void
@@ -303,26 +321,98 @@
{
}
+static void
+kbdproc(void *k)
+{
+ char buf[128], buf2[128], *s;
+ Channel *kchan;
+ int kfd, n;
+ Key key;
+ Rune r;
+
+ threadsetname("orca/kbd");
+ if ((kfd = open("/dev/kbd", OREAD)) < 0)
+ sysfatal("can't open kbd: %r");
+
+ kchan = k;
+ buf2[0] = 0;
+ buf2[1] = 0;
+ buf[0] = 0;
+ for(;;){
+ if (buf[0] != 0) {
+ n = strlen(buf)+1;
+ memmove(buf, buf+n, sizeof(buf)-n);
+ }
+ if (buf[0] == 0) {
+ n = read(kfd, buf, sizeof(buf)-1);
+ if (n <= 0)
+ break;
+ buf[n-1] = 0;
+ buf[n] = 0;
+ }
+
+ switch (buf[0]) {
+ case 'c':
+ if (chartorune(&r, buf+1) > 0 && r != Runeerror)
+ send(cchan, &r);
+ /* no break */
+ default:
+ continue;
+
+ case 'k':
+ s = buf+1;
+ while (*s){
+ s += chartorune(&r, s);
+ if (utfrune(buf2+1, r) == nil) {
+ key.down = 1;
+ key.rune = r;
+ send(kchan, &key);
+ }
+ }
+ break;
+
+ case 'K':
+ s = buf2+1;
+ while (*s) {
+ s += chartorune(&r, s);
+ if(utfrune(buf+1, r) == nil) {
+ key.down = 0;
+ key.rune = r;
+ send(kchan, &key);
+ }
+ }
+ break;
+ }
+ strcpy(buf2, buf);
+ }
+}
+
void
threadmain(int argc, char **argv)
{
Mousectl *mctl;
- Keyboardctl *kctl;
Field copyfield;
- Rune key;
+ Key key;
+ Keyboardctl kctl;
Mouse m;
char tmp[256];
- int oldw, oldh, w, h, n;
+ Channel *kchan;
+ int oldw, oldh, w, h, n, shiftdown, altdown;
Alt a[] = {
{ nil, &m, CHANRCV },
{ nil, nil, CHANRCV },
{ nil, &key, CHANRCV },
{ nil, nil, CHANRCV },
+ { nil, &key.rune, CHANRCV },
{ nil, nil, CHANEND },
};
USED(argc, argv);
+ kchan = chancreate(sizeof(Key), 20);
+ cchan = chancreate(sizeof(Rune), 20);
+ proccreate(kbdproc, kchan, mainstacksize);
+
srand(time(0));
threadsetname("orca/draw");
@@ -330,15 +420,17 @@
sysfatal("initdraw: %r");
if ((mctl = initmouse(nil, screen)) == nil)
sysfatal("initmouse: %r");
- if ((kctl = initkeyboard(nil)) == nil)
- sysfatal("initkeyboard: %r");
+ kctl.c = cchan;
+ kctl.file = "/dev/null";
+ kctl.consfd = kctl.pid = kctl.ctlfd = -1;
a[0].c = mctl->c;
a[1].c = mctl->resizec;
- a[2].c = kctl->c;
+ a[2].c = kchan;
a[3].c = chancreate(sizeof(ulong), 0); /* FIXME should it be buffered instead? */
+ a[4].c = cchan;
- curbg = allocimage(display, Rect(0, 0, 1, 1), RGBA32, 1, DYellow);
+ curbg = allocimage(display, Rect(0, 0, 1, 1), RGBA32, 1, setalpha(DYellow, 128));
charw = stringwidth(font, "X");
charh = font->height;
@@ -353,6 +445,8 @@
oevent_list_init(&events);
threadcreate(orcathread, a[3].c, mainstacksize);
+ shiftdown = 0;
+ altdown = 0;
for (;;) {
redraw();
@@ -371,7 +465,7 @@
n = menuhit(3, mctl, &menu3, nil);
if (n == 0 || n == 1) {
strncpy(tmp, filename, sizeof(tmp));
- if (enter("file path:", tmp, sizeof(tmp), mctl, kctl, nil) > 0) {
+ if (enter("file path:", tmp, sizeof(tmp), mctl, &kctl, nil) > 0) {
if (n == 0 && fieldload(tmp) == 0) {
w = field.width;
h = field.height;
@@ -389,23 +483,49 @@
getwindow(display, Refnone);
break;
- case 2: /* keyboard */
- switch (key) {
+ case 2: /* key up/down */
+ switch (key.rune) {
+ case Kshift:
+ shiftdown = key.down;
+ break;
+ case Kalt:
+ altdown = key.down;
+ break;
+ }
+ break;
+
+ case 3: /* redraw */
+ break;
+
+ case 4: /* key */
+ switch (key.rune) {
case 0x0b: /* C-k */
case Kup:
- cury = MAX(0, cury-1);
+ if (shiftdown)
+ selh = MAX(1, selh-1);
+ else if (!altdown)
+ cury = MAX(0, cury-1);
break;
case '\n': /* C-j */
case Kdown:
- cury = MIN(h-1, cury+1);
+ if (shiftdown)
+ selh++;
+ else if (!altdown)
+ cury = MIN(h-1, cury+1);
break;
case Kbs: /* C-h */
case Kleft:
- curx = MAX(0, curx-1);
+ if (shiftdown)
+ selw = MAX(1, selw-1);
+ else if (!altdown)
+ curx = MAX(0, curx-1);
break;
case 0x0c: /* C-l */
case Kright:
- curx = MIN(w-1, curx+1);
+ if (shiftdown)
+ selw++;
+ else if (!altdown)
+ curx = MIN(w-1, curx+1);
break;
case Khome:
curx = 0;
@@ -448,6 +568,8 @@
case Kesc:
if (!insert)
insert = 1;
+ else
+ selw = selh = 1;
/* FIXME else remove selection */
break;
case ' ':
@@ -456,12 +578,12 @@
break;
}
default:
- if (key == Kdel || key == ' ')
- key = '.';
- if (orca_is_valid_glyph(key))
- fieldset(key);
+ if (key.rune == Kdel || key.rune == ' ')
+ key.rune = '.';
+ if (orca_is_valid_glyph(key.rune))
+ fieldset(key.rune);
else
- fprint(2, "unhandled key %04x\n", key);
+ fprint(2, "unhandled key %04x\n", key.rune);
break;
}
@@ -478,9 +600,6 @@
MIN(field.height, copyfield.height), MIN(field.width, copyfield.width)
);
}
-
- case 3: /* redraw */
- break;
}
if (w != oldw || h != oldh) {