304 lines
5.8 KiB
C
304 lines
5.8 KiB
C
#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 = strtol(args[2], 0, 0);
|
|
if(n == '\033') /* Escape exits */
|
|
break;
|
|
if(n <= Runemax){
|
|
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);
|
|
}
|