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); }