implement Olive;
include "mods.m";
mods, debug, win, tree: import dat;
Menu: import menus;
setcursor, Waiting, Arrow,
getfont, Cpointer, cols, panelback, maxpt, cookclick, drawtag,
BACK,TEXT, readsnarf, CMdouble, terminate : import gui;
Ptag, Pline, Pedit, Psync, Pdead, Pdirty,
intag, Panel: import wpanel;
panelctl, panelkbd, panelmouse, tagmouse, Tree: import wtree;
usage: import arg;
#
# Viewer for o/mero. This program is in charge
# of user I/O, and behaves as a write-through cache regarding
# the o/mero provided file tree.
# Events are handled by o/ports, and the snarf/selection info is
# kept outside as well.
# See the comment at ../mero/mero.b for details.
Olive: module {
init: fn(nil: ref Draw->Context, argv: list of string);
};
ioproc(kbdc: chan of int, mousec: chan of ref Cpointer, resizec: chan of int)
{
for(;;){
alt{
r := <-kbdc =>
if (debug['K'])
fprint(stderr, "kbd: '%c' 16r%x\n", r, r);
tree.kbd(r);
# consume keys repeated while we're busy
ir := r;
do {
r = -1;
alt {
r = <-kbdc => ;
* => ;
}
} while (r == ir);
if (r != -1)
tree.kbd(r);
m := <-mousec =>
if (m == nil)
terminate();
if (debug['M'])
fprint(stderr, "m [%d %d] %x f%x\n", m.xy.x, m.xy.y, m.buttons, m.flags);
tree.mouse(m, mousec);
<-resizec =>
tree.layout(nil);
}
}
}
# Events received from o/mero:
# "o/mero: /widget/path update|sync|ins|del"
updateproc(n: string)
{
fd := create("/mnt/ports/win." + n, ORDWR|ORCLOSE, 8r664);
if (fd == nil)
error(sprint("o/live: /mnt/ports/win.%s: %r", n));
expr := array of byte sprint("o/mero: /%s[ /].*\n", n);
prefix := "/" + n;
write(fd, expr, len expr);
setcursor(Waiting);
tree.update("/");
tree.layout("/");
setcursor(Arrow);
if (debug['P'])
tree.dump("/");
for(;;){
buf := array[4096] of byte;
nr := read(fd, buf, len buf);
if (nr <= 0)
break;
if (nr == len buf)
fprint(stderr, "o/live: event too big. fix me.\n");
buf = buf[0:nr];
event := string buf;
if (debug['E'])
fprint(stderr, "o/live: event: '%s'\n", event);
(na, a) := tokenize(event, " \t\n");
if (na > 2){
ea := hd tl a; # "/s9/row:wins/..."
ea = ea[len prefix:];
if (ea == "")
ea = "/";
ev := hd tl tl a;
case ev {
"update" =>
setcursor(Waiting);
tree.update(ea);
tree.layout(nil);
setcursor(Arrow);
"image" =>
setcursor(Waiting);
tree.image(ea);
setcursor(Arrow);
"top" =>
tree.layout(ea);
"ins" or "del" =>
p := tree.walk(ea);
if (p == nil)
fprint(stderr, "o/live: %s: %s: no panel\n", ev, ea);
p.event(event);
tree.tags("/");
* =>
fprint(stderr, "o/live: bad event: %s\n", ev);
}
} else
fprint(stderr, "o/live: short event: [%s]\n", string buf);
}
}
nullflags := array[256] of int;
init(ctx: ref Draw->Context, args: list of string)
{
sys = load Sys Sys->PATH;
dat = load Livedat Livedat->PATH;
if (dat == nil){
fprint(fildes(2), "o/live: can't load %s: %r\n", Livedat->PATH);
raise "fail: loads";
}
dat->loads();
initmods();
wmcli->init();
menus->init(dat);
arg->init(args);
arg->setusage("o/live [-dEFKLMPTW] dir scr");
debug = nullflags;
while((opt := arg->opt()) != 0) {
case opt{
'd' =>
debug['P'] = 1;
'P' or 'W' or 'L' or 'M' or 'E' or 'T' or 'K' or 'F' =>
# panel, win, layout, mouse, events, text, kbd, frame
debug[opt]++;
* =>
usage();
}
}
args = arg->argv();
if (len args != 2)
usage();
omero := hd args;
if (omero == "t")
omero = "/usr/nemo/om/mero/ui";
sys->pctl(NEWPGRP, nil);
layoutm->init(dat);
wpanel->init(dat, "/dis/o");
wtree->init(dat);
tree = Tree.start(omero, hd tl args);
if (tree == nil)
error(sprint("can't create tree: %r"));
(kbdc, mousec, resizec) := gui->init(dat, ctx);
setcursor(Arrow);
stderr=fildes(2);
spawn updateproc(hd tl args);
spawn ioproc(kbdc, mousec, resizec);
}
|