diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/bitsy |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/bitsy')
-rwxr-xr-x | sys/src/cmd/bitsy/bitsyload.c | 130 | ||||
-rwxr-xr-x | sys/src/cmd/bitsy/keyboard.c | 437 | ||||
-rwxr-xr-x | sys/src/cmd/bitsy/light.rc | 14 | ||||
-rwxr-xr-x | sys/src/cmd/bitsy/mkfile | 21 | ||||
-rwxr-xr-x | sys/src/cmd/bitsy/params.c | 83 | ||||
-rwxr-xr-x | sys/src/cmd/bitsy/pencal.c | 188 | ||||
-rwxr-xr-x | sys/src/cmd/bitsy/prompter.c | 303 |
7 files changed, 1176 insertions, 0 deletions
diff --git a/sys/src/cmd/bitsy/bitsyload.c b/sys/src/cmd/bitsy/bitsyload.c new file mode 100755 index 000000000..a7c6d5801 --- /dev/null +++ b/sys/src/cmd/bitsy/bitsyload.c @@ -0,0 +1,130 @@ +#include <u.h> +#include <libc.h> + +enum +{ + Magic= 0x5a5abeef, +}; + +typedef struct Method Method; +struct Method { + char *verb; + char *part; + char *file; +}; + +Method method[] = +{ + { "k", "/dev/flash/kernel", "/sys/src/9/bitsy/9bitsy" }, + { "r", "/dev/flash/ramdisk", "/sys/src/9/bitsy/paqdisk" }, + { "u", "/dev/flash/user", "/sys/src/9/bitsy/user" }, +}; + +void +leputl(uchar *p, ulong x) +{ + *p++ = x; + *p++ = x>>8; + *p++ = x>>16; + *p = x>>24; +} + +void +usage(void) +{ + fprint(2, "usage: %s k|r [file]\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char *file; + int ctl, in, out; + int i, n; + uchar *buf; + char ctlfile[64]; + char ctldata[1024]; + char *args[10]; + Dir *d; + ulong nsects, sectsize; + Method *m; + + ARGBEGIN { + } ARGEND; + + if(argc == 0) + usage(); + + for(m = method; m < method + nelem(method); m++) + if(strcmp(argv[0], m->verb) == 0) + break; + if(m == method + nelem(method)) + usage(); + + if(argc < 2) + file = m->file; + else + file = argv[1]; + + in = open(file, OREAD); + if(in < 0) + sysfatal("%s: %r", file); + d = dirfstat(in); + if(d == nil) + sysfatal("stating %s: %r", file); + + out = open(m->part, OWRITE); + if(out < 0) + sysfatal("%s: %r", m->part); + sprint(ctlfile, "%sctl", m->part); + ctl = open(ctlfile, ORDWR); + if(ctl < 0) + sysfatal("%s: %r", ctlfile); + + i = read(ctl, ctldata, sizeof(ctldata) - 1); + if (i <= 0) + sysfatal("%s: %r", ctlfile); + ctldata[i] = '\0'; + i = tokenize(ctldata, args, nelem(args)); + if(i < 7) + sysfatal("bad flash geometry"); + + nsects = atoi(args[5]); + sectsize = atoi(args[6]); + if(nsects < 3) + sysfatal("unreasonable value for nsects: %lud", nsects); + if(sectsize < 512) + sysfatal("unreasonable value for sectsize: %lud", sectsize); + + /* allocate a buffer and read in the whole file */ + n = d->length; + buf = malloc(n + sectsize); + if(buf == nil) + sysfatal("not enough room to read in file: %r"); + + print("reading %d bytes of %s\n", n, file); + if(readn(in, buf, n) != n) + sysfatal("error reading file: %r"); + close(in); + + memset(buf + n, 0, sectsize); + n = ((n+sectsize-1)/sectsize)*sectsize; + + if (nsects * sectsize < n) + sysfatal("file too large (%d) for partition (%lud)", n, nsects * sectsize); + + print("erasing %s\n", m->part); + if(fprint(ctl, "erase") < 0) + sysfatal("erase %s: %r", ctlfile); + close(ctl); + print("writing %s\n", m->part); + + for (i = 0; i < n; i += sectsize) + if(write(out, buf + i, sectsize) != sectsize) + sysfatal("writing %s at %d: %r", file, i); + + print("write done\n"); + close(in); + close(out); +} diff --git a/sys/src/cmd/bitsy/keyboard.c b/sys/src/cmd/bitsy/keyboard.c new file mode 100755 index 000000000..0972bcd75 --- /dev/null +++ b/sys/src/cmd/bitsy/keyboard.c @@ -0,0 +1,437 @@ +#include <u.h> +#include <libc.h> +#include <thread.h> +#include <draw.h> +#include <mouse.h> +#include <keyboard.h> +#include <control.h> +#include <scribble.h> + +int debug = 0; +typedef struct Win Win; +struct Win { + int n; + int dirty; + char *label; + Control *button; +}; + +Win *win; +int nwin; +int mwin; +int onwin; +int rows, cols; +int kbdonly; +int scribbleleft; +int winshow; + +Channel *kc; +Channel *ec; +Channel *tc; +Rectangle r, rk, rs, rw; +Font *keyfont, *keyctlfont; + +enum{ + Back, + Shade, + Light, + Mask, + Ncol +}; + +enum { + kbdheight = 2 + 5*13, +}; + +enum { + Keyback = 0xeeee9eff, + Keyshade = 0xaaaa55ff, + Keylight = DWhite, + Keymask = 0x0C0C0C0C, +}; + +Image *colors[Ncol]; + +Control *kbd; +Control *scrib; +Control *boxbox; +Controlset *cs; + +int ctldeletequits = 1; +int wctl; + +int +hidden(void) +{ + char buf[128]; + int n; + + close(wctl); + if ((wctl = open("/dev/wctl", ORDWR)) < 0) + return 0; + n = read(wctl, buf, sizeof buf-1); + if (n <= 0) + sysfatal("wctl read: %r"); + buf[n] = 0; + return strstr(buf, "visible") == nil; +} + +void +mousemux(void *v) +{ + Mouse m; + Channel *c; + int ob; + + c = v; + + for(ob = 0;;ob = m.buttons){ + if(recv(c, &m) < 0) + break; + if ((m.buttons & 0x20) == 0) { + if (ob & 0x20) { + /* hide button just came up */ + if (hidden()) { + if (debug) fprint(2, "unhide"); + if (fprint(wctl, "unhide") <= 0) + fprint(2, "unhide failed: %r\n"); + } else { + if (debug) fprint(2, "hide"); + if (fprint(wctl, "hide") <= 0) + fprint(2, "hide failed: %r\n"); + } + } else + send(cs->mousec, &m); + } + } +} + +void +refreshwin(void) +{ + char label[128]; + int i, fd, lfd, n, nr, nw, m; + Dir *pd; + + if((fd = open("/dev/wsys", OREAD)) < 0) + return; + + nw = 0; +/* i'd rather read one at a time but rio won't let me */ + while((nr=dirread(fd, &pd)) > 0){ + for(i=0; i<nr; i++){ + n = atoi(pd[i].name); + sprint(label, "/dev/wsys/%d/label", n); + if((lfd = open(label, OREAD)) < 0) + continue; + m = read(lfd, label, sizeof(label)-1); + close(lfd); + if(m < 0) + continue; + label[m] = '\0'; + if(nw < nwin && win[nw].n == n && strcmp(win[nw].label, label)==0){ + nw++; + continue; + } + + if(nw < nwin){ + free(win[nw].label); + win[nw].label = nil; + } + if(nw >= mwin){ + mwin += 8; + win = ctlrealloc(win, mwin*sizeof(win[0])); + memset(&win[mwin-8], 0, 8*sizeof(win[0])); + } + win[nw].n = n; + win[nw].label = ctlstrdup(label); + win[nw].dirty = 1; + sprint(label, "%d", nw); + if (win[nw].button == nil){ + win[nw].button = createtextbutton(cs, label); + chanprint(cs->ctl, "%q font keyfont", label); + chanprint(cs->ctl, "%q image keyback", label); + chanprint(cs->ctl, "%q pressedtextcolor red", label); + chanprint(cs->ctl, "%q mask transparent", label); + chanprint(cs->ctl, "%q border 1", label); + chanprint(cs->ctl, "%q bordercolor black", label); + chanprint(cs->ctl, "%q align centerleft", label); + chanprint(cs->ctl, "%q size 16 %d 512 %d", label, keyfont->height+2, keyfont->height+2); + controlwire(win[nw].button, "event", ec); + } + if (nw >= nwin){ + activate(win[nw].button); + chanprint(cs->ctl, "cols add %q", label); + } + chanprint(cs->ctl, "%q text %q", win[nw].button->name, win[nw].label); + nw++; + } + } + for(i = nw; i < nwin; i++){ + free(win[i].label); + win[i].label = nil; + deactivate(win[i].button); + chanprint(cs->ctl, "cols remove %q", win[i].button->name); + } + nwin = nw; + close(fd); + if (rw.max.x) + chanprint(cs->ctl, "cols rect %R\ncols show", rw); +} + +void +resizecontrolset(Controlset*) +{ + int fd; + char buf[61]; + + + if(getwindow(display, Refnone) < 0) + ctlerror("resize failed: %r"); + + if (hidden()) { + if (debug) fprint(2, "resizecontrolset: hidden\n"); + return; + } + + fd = open("/dev/screen", OREAD); + if (fd < 0) { + r = display->image->r; + if (debug) fprint(2, "display->imgae->r: %R\n", r); + } else { + if (read(fd, buf, 60) != 60) + sysfatal("resizecontrolset: read: /dev/screen: %r"); + close(fd); + buf[60] = '\0'; + r.min.x = atoi(buf+1+1*12); + r.min.y = atoi(buf+1+2*12); + r.max.x = atoi(buf+1+3*12); + r.max.y = atoi(buf+1+4*12); + if (debug) fprint(2, "/dev/screen: %R\n", r); + } + r = insetrect(r, 4); + r.min.y = r.max.y - kbdheight - 2*Borderwidth; + if (debug) fprint(2, "before eqrect: %R\n", r); + if (eqrect(r, screen->r) == 0) { + if (debug) fprint(2, "resizecontrolset: resize %R\n", r); + if (fprint(wctl, "resize -r %R", insetrect(r, -4)) <= 0) { + fprint(2, "resizecontrolset: resize failed\n"); + } + return; + } + + if (debug) fprint(2, "after eqrect: %R\n", r); + rk = r; + if (winshow){ + rw = rk; + rw.min.x = (3*rk.max.x + rk.min.x)/4; + rk.max.x = rw.min.x; + if (debug) fprint(2, "rw: rect %R\n", rw); + chanprint(cs->ctl, "cols rect %R\ncols show", rw); + } + if (kbdonly) { + chanprint(cs->ctl, "keyboard rect %R\nkeyboard show", rk); + } else { + rs = rk; + if (scribbleleft){ + rk.min.x = (rk.max.x + 3*rk.min.x)/4; + rs.max.x = rk.min.x; + }else{ + rk.max.x = (3*rk.max.x + rk.min.x)/4; + rs.min.x = rk.max.x; + } + chanprint(cs->ctl, "keyboard rect %R\nkeyboard show", rk); + if (debug) fprint(2, "rk: rect %R\nkeyboard show\n", rk); + chanprint(cs->ctl, "scribble rect %R\nscribble show", rs); + if (debug) fprint(2, "rs: rect %R\nscribble show\n", rs); + } +} + +void +usage(void) +{ + fprint(2, "usage: keyboard\n"); + threadexitsall("usage"); +} + +void +timerproc(void*v) +{ + Channel *c; + + c = v; + for(;;){ + sleep(5000); + sendul(c, 1); + } +} + +void +watchproc(void*) +{ + + for(;;){} +} + +void +threadmain(int argc, char *argv[]) +{ + int i, n, kbdfd; + char str[UTFmax+1]; + Rune r; + Mousectl *mousectl; + Channel *mtok; + char *e, buf[128], *args[8]; + int fd; + + ARGBEGIN{ + case 'w': + winshow++; + break; + case 'l': + scribbleleft++; + break; + case 'n': + kbdonly++; + break; + case 'd': + ScribbleDebug++; + debug++; + break; + default: + usage(); + }ARGEND + + if(argc != 0) + usage(); + + kbdfd = open("/dev/kbdin", OWRITE); + if (kbdfd < 0 && (kbdfd = open("#r/kbdin", OWRITE)) < 0) { + if (debug) fprint(2, "open %s: %r\n", "#r/kbdin"); + kbdfd = 1; + } + + initdraw(0, 0, "keyboard"); + mousectl = initmouse(nil, screen); + + wctl = open("/dev/wctl", ORDWR); + if (wctl < 0) { + fprint(2, "open %s: %r\n", "/dev/wctl"); + wctl = 2; /* for debugging */ + } + + mtok = chancreate(sizeof(Mouse), 0); + + initcontrols(); + + cs = newcontrolset(screen, nil, mtok, mousectl->resizec); + + threadcreate(mousemux, mousectl->c, 4096); + + kc = chancreate(sizeof(char*), 0); + tc = chancreate(sizeof(int), 1); + ec = chancreate(sizeof(char*), 1); + + colors[Back] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keyback); + namectlimage(colors[Back], "keyback"); + colors[Light] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keylight); + namectlimage(colors[Light], "keylight"); + colors[Shade] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keyshade); + namectlimage(colors[Shade], "keyshade"); + colors[Mask] = allocimage(display, Rect(0,0,1,1), RGBA32, 1, Keymask); + namectlimage(colors[Shade], "keymask"); + keyfont = openfont(display, "/lib/font/bit/lucidasans/boldlatin1.6.font"); + namectlfont(keyfont, "keyfont"); + keyctlfont = openfont(display, "/lib/font/bit/lucidasans/unicode.6.font"); + namectlfont(keyctlfont, "keyctlfont"); + + kbd = createkeyboard(cs, "keyboard"); + chanprint(cs->ctl, "keyboard font keyfont keyctlfont"); + chanprint(cs->ctl, "keyboard image keyback"); + chanprint(cs->ctl, "keyboard light keylight"); + chanprint(cs->ctl, "keyboard mask keymask"); + chanprint(cs->ctl, "keyboard border 1"); + chanprint(cs->ctl, "keyboard size %d %d %d %d", 246, 2 + 5 * (keyfont->height + 1), 512, 256); + controlwire(kbd, "event", kc); + + if (kbdonly == 0){ + scrib = createscribble(cs, "scribble"); + if (scrib == nil) + sysfatal("createscribble"); + chanprint(cs->ctl, "scribble font keyfont"); + chanprint(cs->ctl, "scribble image keyback"); + chanprint(cs->ctl, "scribble border 1"); + controlwire(scrib, "event", kc); + } + + if (winshow){ + boxbox = createboxbox(cs, "cols"); + + chanprint(cs->ctl, "cols border 2"); + chanprint(cs->ctl, "cols bordercolor keyback"); + } + + resizecontrolset(nil); + + activate(kbd); + if (kbdonly == 0) + activate(scrib); + if (winshow){ + refreshwin(); + proccreate(timerproc, tc, 2048); + } + + for(;;){ + Alt a[] = { + { kc, &e, CHANRCV }, + { ec, &e, CHANRCV }, + { tc, &n, CHANRCV }, + { nil, nil, CHANEND } + }; + switch(alt(a)){ + case 0: /* Keyboard */ + n = tokenize(e, args, nelem(args)); + if(n == 3) + if(strcmp(args[0], "keyboard:")==0 || strcmp(args[0], "scribble:")==0) + if(strcmp(args[1], "value") == 0){ + n = atoi(args[2]); + if(n <= 0xFFFF){ + r = n; + i = runetochar(str, &r); + write(kbdfd, str, i); + } + } + break; + case 1: /* Button event */ + n = tokenize(e, args, nelem(args)); + if (n != 3 || strcmp(args[1], "value")) + sysfatal("event string"); + i = atoi(args[0]); + if (i < 0 || i >= nwin) + sysfatal("win out of range: %d of %d", i, nwin); + n = atoi(args[2]); + if (n){ + sprint(buf, "/dev/wsys/%d/wctl", win[i].n); + if((fd = open(buf, OWRITE)) >= 0){ + while (write(fd, "top\n", 4) < 0) { + /* wait until mouse comes up */ + rerrstr(buf, sizeof buf); + if (strncmp(buf, "action disallowed when mouse active", sizeof buf)){ + fprint(2, "write top: %s\n", buf); + break; + } + sleep(100); + } + if (write(fd, "current\n", 8) < 0) + fprint(2, "write current: %r\n"); + close(fd); + } + chanprint(cs->ctl, "%q value 0", win[i].button->name); + } + break; + case 2: + refreshwin(); + break; + } + } +} diff --git a/sys/src/cmd/bitsy/light.rc b/sys/src/cmd/bitsy/light.rc new file mode 100755 index 000000000..d17cd8212 --- /dev/null +++ b/sys/src/cmd/bitsy/light.rc @@ -0,0 +1,14 @@ +#!/bin/rc + +#master file is /sys/src/cmd/bitsy/light.rc + +switch($1){ +case on + echo -n 2 1 0x80 > /dev/backlight +case off + echo -n 2 0 0x80 > /dev/backlight +case auto + echo -n 1 1 0x80 > /dev/backlight +case * + echo -n 2 1 $1 > /dev/backlight +} diff --git a/sys/src/cmd/bitsy/mkfile b/sys/src/cmd/bitsy/mkfile new file mode 100755 index 000000000..806683d80 --- /dev/null +++ b/sys/src/cmd/bitsy/mkfile @@ -0,0 +1,21 @@ +</$objtype/mkfile + +TARG=\ + bitsyload\ + pencal\ + prompter\ + keyboard\ + light\ + params\ + +BIN=/$objtype/bin/bitsy +</sys/src/cmd/mkmany + +light.$O:V: + # nothing + +$O.light: light.rc + cp light.rc $target + +light.install: + cp light.rc $BIN/light diff --git a/sys/src/cmd/bitsy/params.c b/sys/src/cmd/bitsy/params.c new file mode 100755 index 000000000..4d27930e9 --- /dev/null +++ b/sys/src/cmd/bitsy/params.c @@ -0,0 +1,83 @@ +#include <u.h> +#include <libc.h> + +void +erase(char *part) +{ + char file[256]; + int fd; + + snprint(file, sizeof file, "%sctl", part); + fd = open(file, ORDWR); + if(fd < 0) + return; + fprint(fd, "erase"); + close(fd); +} + +char* +readfile(char *file) +{ + char buf[512]; + int n, fd; + uchar *p; + + fd = open(file, OREAD); + if(fd < 0) + sysfatal("opening %s: %r", file); + n = read(fd, buf, sizeof(buf)-1); + close(fd); + if(n < 0) + return ""; + buf[n] = 0; + for(p = (uchar*)buf; *p; p++) + if(*p == 0xff){ + *p = 0; + break; + } + return strdup(buf); +} + +void +writefile(char *file, char *data) +{ + int fd; + + fd = open(file, OWRITE); + if(fd < 0) + fd = create(file, OWRITE, 0664); + if(fd < 0) + return; + write(fd, data, strlen(data)); + close(fd); +} + +void +main(int argc, char **argv) +{ + int from = 0; + char *params; + char *file = "/tmp/tmpparams"; + char *part; + + ARGBEGIN { + case 'f': + from++; + break; + } ARGEND; + + if(argc) + part = argv[0]; + else + part = "/dev/flash/user"; + + if(from){ + params = readfile(part); + writefile(file, params); + } else { + params = readfile(file); + erase(part); + writefile(part, params); + free(params); + } +} diff --git a/sys/src/cmd/bitsy/pencal.c b/sys/src/cmd/bitsy/pencal.c new file mode 100755 index 000000000..4ce830010 --- /dev/null +++ b/sys/src/cmd/bitsy/pencal.c @@ -0,0 +1,188 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> + +int debug = 0; + +struct Cal { + double scalex; + double transx; + double scaley; + double transy; +} cal; + +/* Calibrate the pen */ + +Point pts[5]; + +Point pens[5]; + +Point up = { 0, -10}; +Point down = { 0, 10}; +Point left = {-10, 0}; +Point right = { 10, 0}; + +Point +pen2scr(Point p) +{ + return Pt(p.x * cal.scalex / 65536.0 + cal.transx, + p.y * cal.scaley / 65536.0 + cal.transy); +} + +Point +scr2pen(Point p) +{ + return Pt((p.x - cal.transx) * 65536.0 / cal.scalex, + (p.y + cal.transy) * 65536.0 / cal.scaley); +} + +void +cross(Point p) { + draw(screen, screen->r, display->white, nil, ZP); + line(screen, addpt(p, up), addpt(p, down), Endsquare, Endsquare, 0, display->black, ZP); + line(screen, addpt(p, left), addpt(p, right), Endsquare, Endsquare, 0, display->black, ZP); + flushimage(display, 1); +} + +Point +getmouse(int mouse) { + static char buf[50]; + int x, y, b, n; + Point p; + + n = 0; + p.x = p.y = 0; + do{ + if (read(mouse, buf, 48) != 48) + sysfatal("read: %r"); + if (debug > 1) fprint(2, "%s\n", buf); + if (buf[0] == 'r') { + b = 1; + continue; + } + if (buf[0] != 'm') + sysfatal("mouse message: %s", buf); + x = strtol(buf+1, nil, 10); + y = strtol(buf+13, nil, 10); + b = strtol(buf+25, nil, 10); + p.x = (n * p.x + x)/(n+1); + p.y = (n * p.y + y)/(n+1); + n++; + }while (b & 0x7); + return p; +} + +void +main(int argc, char **argv) { + int i, mouse, mousectl, wctl, ntries; + Rectangle r, oldsize; + + ARGBEGIN{ + case 'd': + debug = 1; + break; + }ARGEND; + + if((mouse = open("/dev/mouse", OREAD)) < 0 + && (mouse = open("#m/mouse", OREAD)) < 0) + sysfatal("#m/mouse: %r"); + + mousectl = open("#m/mousectl", ORDWR); + if(mousectl < 0) + sysfatal("#m/mousectl: %r"); + + if(initdraw(nil, nil, "calibrate") < 0) + sysfatal("initdraw: %r"); + + wctl = -1; + for(ntries = 0; ntries < 3; ntries++){ + r = insetrect(display->image->r, 2); + + if(wctl < 0) + wctl = open("/dev/wctl", ORDWR); + if(wctl >= 0){ + char buf[4*12+1]; + + buf[48] = 0; + oldsize = screen->r; + if(fprint(wctl, "resize -r %R", r) <= 0) + sysfatal("write /dev/wctl, %r"); + if(getwindow(display, Refbackup) < 0) + sysfatal("getwindow"); + if(debug) fprint(2, "resize: %R\n", screen->r); + + if(read(mousectl, buf, 48) != 48) + sysfatal("read mousectl: %r"); + if(debug > 1) fprint(2, "mousectl %s\n", buf); + if(buf[0] != 'c') + sysfatal("mousectl message: %s", buf); + cal.scalex = strtol(buf+ 1, nil, 10); + cal.scaley = strtol(buf+13, nil, 10); + cal.transx = strtol(buf+25, nil, 10); + cal.transy = strtol(buf+37, nil, 10); + }else{ + fprint(mousectl, "calibrate"); + cal.scalex = 1<<16; + cal.scaley = 1<<16; + cal.transx = 0; + cal.transy = 0; + } + + fprint(2, "calibrate %ld %ld %ld %ld (old)\n", + (long)cal.scalex, (long)cal.scaley, (long)cal.transx, (long)cal.transy); + + if(debug) + fprint(2, "screen coords %R\n", screen->r); + pts[0] = addpt(Pt( 16, 16), screen->r.min); + pts[1] = addpt(Pt( 16, -16), Pt(screen->r.min.x, screen->r.max.y)); + pts[2] = addpt(Pt(-16, 16), Pt(screen->r.max.x, screen->r.min.y)); + pts[3] = addpt(Pt(-16, -16), screen->r.max); + pts[4] = Pt((screen->r.max.x + screen->r.min.x)/2, + (screen->r.max.y + screen->r.min.y)/2);; + + for(i = 0; i < 4; i++){ + cross(pts[i]); + pens[i] = scr2pen(getmouse(mouse)); + if (debug) fprint(2, "%P\n", pens[i]); + } + + cal.scalex = (pts[2].x + pts[3].x - pts[0].x - pts[1].x) * 65536.0 / + (pens[2].x + pens[3].x - pens[0].x - pens[1].x); + cal.scaley = (pts[1].y + pts[3].y - pts[0].y - pts[2].y) * 65536.0 / + (pens[1].y + pens[3].y - pens[0].y - pens[2].y); + cal.transx = pts[0].x - (pens[0].x*cal.scalex) / 65536.0; + cal.transy = pts[0].y - (pens[0].y*cal.scaley) / 65536.0; + + if(debug) + fprint(2, "scale [%f, %f], trans [%f, %f]\n", + cal.scalex, cal.scaley, cal.transx, cal.transy); + + fprint(mousectl, "calibrate %ld %ld %ld %ld", + (long)cal.scalex, (long)cal.scaley, (long)cal.transx, (long)cal.transy); + + cross(pts[4]); + pens[4] = getmouse(mouse); + + draw(screen, screen->r, display->white, nil, ZP); + flushimage(display, 1); + + if(abs(pts[4].x-pens[4].x) <= 4 && abs(pts[4].y-pens[4].y) <= 4){ + fprint(2, "Calibration ok: %P -> %P\n", pts[4], pens[4]); + break; + } + fprint(2, "Calibration inaccurate: %P -> %P\n", pts[4], pens[4]); + } + print("calibrate='%ld %ld %ld %ld'\n", + (long)cal.scalex, (long)cal.scaley, (long)cal.transx, (long)cal.transy); + + if(debug) + for(i = 0; i < 4; i++){ + cross(pts[i]); + pens[i] = getmouse(mouse); + if (debug) fprint(2, "%P\n", pens[i]); + } + + if(wctl >= 0) + fprint(wctl, "resize -r %R", oldsize); + +} diff --git a/sys/src/cmd/bitsy/prompter.c b/sys/src/cmd/bitsy/prompter.c new file mode 100755 index 000000000..9a76a0d0e --- /dev/null +++ b/sys/src/cmd/bitsy/prompter.c @@ -0,0 +1,303 @@ +#include <u.h> +#include <libc.h> +#include <thread.h> +#include <draw.h> +#include <mouse.h> +#include <keyboard.h> +#include <control.h> + +int Nline; + +enum{ + Back, + Shade, + Light, + Mask, + Ncol +}; + +enum { + Keyback = 0xeeee9eff, + Keyshade = 0xaaaa55ff, + Keylight = DWhite, + Keymask = 0x0C0C0C0C, +}; + +Image *cols[Ncol]; + +int nline; + +char *lines[24]; /* plus one so last line gets terminated by getfields */ +Control *entry[24]; +Control *kbd; +Control *scrib; +Controlset *keyboard; +Controlset *text; +int kbdy; + +int resizeready; + +int ctldeletequits = 1; + +Channel *eventchan; + +void +resizecontrolset(Controlset *cs) +{ + int i; + Rectangle r, r1; + + if(cs != keyboard) + return; + if (!resizeready) + return; + if(getwindow(display, Refnone) < 0) + ctlerror("resize failed: %r"); + draw(screen, screen->r, cols[Back], nil, ZP); + r = insetrect(screen->r, 4); + for(i=0; i<Nline; i++){ + r.max.y = r.min.y + font->height; + ctlprint(entry[i], "rect %R", r); + ctlprint(entry[i], "show"); + r.min.y = r.max.y; + } + kbdy = r.min.y; + + r = screen->r; + r.min.y = kbdy; + r.max.y = screen->r.max.y; + r.min.y = r.max.y - 2*2 - 5*13; + if(r.min.y >= r.max.y) + r.min.y = r.max.y; + r1 = r; + if(scrib) + r.max.x = (3*r.max.x + r.min.x)/4; + ctlprint(kbd, "rect %R", r); + ctlprint(kbd, "show"); + if(scrib){ + r1.min.x = (3*r1.max.x + r1.min.x)/4; + ctlprint(scrib, "rect %R", r1); + ctlprint(scrib, "show"); + } +} + +void +readall(char *s) +{ + char *buf; + int fd; + Dir *d; + + fd = open(s, OREAD); + if(fd < 0){ + fprint(2, "prompter: can't open %s: %r\n", s); + exits("open"); + } + d = dirfstat(fd); + if(d == nil){ + fprint(2, "prompter: can't stat %s: %r\n", s); + exits("stat"); + } + buf = ctlmalloc(d->length+1); /* +1 for NUL on end */ + if(read(fd, buf, d->length) != d->length){ + fprint(2, "prompter: can't read %s: %r\n", s); + exits("stat"); + } + nline = getfields(buf, lines, nelem(lines), 0, "\n"); + free(d); + close(fd); +} + +void +mousemux(void *v) +{ + Mouse m; + Channel *c; + + c = v; + + for(;;){ + if(recv(c, &m) < 0) + break; + if(m.buttons & 0x20) { + sendp(eventchan, "mouse: exit"); + break; + } + if(m.xy.y >= kbdy) + send(keyboard->mousec, &m); + else + send(text->mousec, &m); + } +} + +void +resizemux(void *v) +{ + Channel *c; + + c = v; + + for(;;){ + if(recv(c, nil) < 0) + break; + send(keyboard->resizec, nil); + send(text->resizec, nil); + } +} + +void +writeall(char *s) +{ + int fd; + int i, n; + + fd = create(s, OWRITE, 0666); + if(fd < 0){ + fprint(2, "prompter: can't create %s: %r\n", s); + exits("open"); + } + + for(n=Nline; --n>=0; ) + if(lines[n][0] != '\0') + break; + + for(i=0; i<=n; i++) + fprint(fd, "%s\n", lines[i]); + close(fd); +} + +void +usage(void) +{ + fprint(2, "usage: prompter file\n"); + threadexitsall("usage"); +} + +void +threadmain(int argc, char *argv[]) +{ + char *s; + Font *f; + int i, n; + char buf[32], *args[3]; + Keyboardctl *kbdctl; + Mousectl *mousectl; + Rune r; + Channel *mtok, *mtot, *ktok, *rtok, *rtot; + int noscrib; + + noscrib = 0; + ARGBEGIN{ + case 'n': + noscrib++; + break; + default: + usage(); + }ARGEND + + if(argc != 1) + usage(); + + readall(argv[0]); + + initdraw(0, 0, "prompter"); + mousectl = initmouse(nil, screen); + kbdctl = initkeyboard(nil); + + mtok = chancreate(sizeof(Mouse), 0); + mtot = chancreate(sizeof(Mouse), 0); + ktok = chancreate(sizeof(Rune), 20); + rtok = chancreate(sizeof(int), 2); + rtot = chancreate(sizeof(int), 2); + + initcontrols(); + + keyboard = newcontrolset(screen, ktok, mtok, rtok); + text = newcontrolset(screen, kbdctl->c, mtot, rtot); + text->clicktotype = 1; + + threadcreate(mousemux, mousectl->c, 4096); + threadcreate(resizemux, mousectl->resizec, 4096); + + eventchan = chancreate(sizeof(char*), 0); + + cols[Back] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keyback); + namectlimage(cols[Back], "keyback"); + cols[Light] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keylight); + namectlimage(cols[Light], "keylight"); + cols[Shade] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, Keyshade); + namectlimage(cols[Shade], "keyshade"); + cols[Mask] = allocimage(display, Rect(0,0,1,1), RGBA32, 1, Keymask); + namectlimage(cols[Shade], "keymask"); + f = openfont(display, "/lib/font/bit/lucidasans/boldlatin1.6.font"); + namectlfont(f, "bold"); + f = openfont(display, "/lib/font/bit/lucidasans/unicode.6.font"); + namectlfont(f, "roman"); + font = f; + + Nline = (screen->r.max.y - 2*2 - 5*13 - 8)/font->height; + if (Nline > nelem(entry)) Nline = nelem(entry); + + for(i=0; i<Nline; i++){ + snprint(buf, sizeof buf, "line.%.2d", i); + entry[i] = createentry(text, buf); + ctlprint(entry[i], "font roman"); + ctlprint(entry[i], "image keyback"); + if(i < nline) + ctlprint(entry[i], "value %q", lines[i]); + controlwire(entry[i], "event", eventchan); + activate(entry[i]); + } + + kbd = createkeyboard(keyboard, "keyboard"); + ctlprint(kbd, "font bold roman"); + ctlprint(kbd, "image keyback"); + ctlprint(kbd, "light keylight"); + ctlprint(kbd, "mask keymask"); + ctlprint(kbd, "border 1"); + controlwire(kbd, "event", eventchan); + + scrib = nil; + if(!noscrib){ + scrib = createscribble(keyboard, "scribble"); + ctlprint(scrib, "font bold"); + ctlprint(scrib, "image keyback"); + ctlprint(scrib, "border 1"); + controlwire(scrib, "event", eventchan); + activate(scrib); + } + + activate(kbd); + resizeready = 1; + resizecontrolset(keyboard); + + for(;;){ + s = recvp(eventchan); + n = tokenize(s, args, nelem(args)); + if(n == 2 && strcmp(args[0], "mouse:")==0 && strcmp(args[1], "exit")==0) + break; + if(n == 3) + if(strcmp(args[0], "keyboard:")==0 || strcmp(args[0], "scribble:")==0) + if(strcmp(args[1], "value") == 0){ + n = atoi(args[2]); + if(n == '\033') /* Escape exits */ + break; + if(n <= 0xFFFF){ + r = n; + send(kbdctl->c, &r); + } + } + } + + for(i=0; i<Nline; i++){ + ctlprint(entry[i], "data"); + lines[i] = ctlstrdup(recvp(entry[i]->data)); + } + + writeall(argv[0]); + + draw(screen, screen->r, display->white, nil, ZP); + flushimage(display, 1); + + threadexitsall(nil); +} |