diff options
Diffstat (limited to 'appl/spree/clients/gather.b')
| -rw-r--r-- | appl/spree/clients/gather.b | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/appl/spree/clients/gather.b b/appl/spree/clients/gather.b new file mode 100644 index 00000000..113985b3 --- /dev/null +++ b/appl/spree/clients/gather.b @@ -0,0 +1,178 @@ +implement Gather; + +include "sys.m"; + sys: Sys; +include "draw.m"; + draw: Draw; + Point, Rect, Display, Image, Font: import draw; +include "tk.m"; + tk: Tk; +include "tkclient.m"; + tkclient: Tkclient; +include "commandline.m"; + commandline: Commandline; + Cmdline: import commandline; +include "sh.m"; + +Gather: module { + init: fn(ctxt: ref Draw->Context, argv: list of string); +}; + +CLIENTDIR: con "/dis/spree/clients"; + +drawctxt: ref Draw->Context; +cliquefd: ref Sys->FD; +stderr: ref Sys->FD; + +mnt, dir: string; + +init(ctxt: ref Draw->Context, argv: list of string) +{ + sys = load Sys Sys->PATH; + stderr = sys->fildes(2); + draw = load Draw Draw->PATH; + tk = load Tk Tk->PATH; + tkclient = load Tkclient Tkclient->PATH; + if (tkclient == nil) { + sys->fprint(stderr, "gather: cannot load %s: %r\n", Tkclient->PATH); + raise "fail:bad module"; + } + tkclient->init(); + commandline = load Commandline Commandline->PATH; + if(commandline == nil) { + sys->fprint(stderr, "gather: cannot load %s: %r\n", Commandline->PATH); + raise "fail:bad module"; + } + commandline->init(); + drawctxt = ctxt; + cliquefd = sys->fildes(0); + + if (len argv >= 3) { + mnt = hd tl argv; + dir = hd tl tl argv; + } else + sys->fprint(stderr, "gather: expected mnt, dir args\n"); + client1(); +} + +client1() +{ + (win, winctl) := tkclient->toplevel(drawctxt, nil, "Gathering", Tkclient->Appl); + ech := chan of string; + tk->namechan(win, ech, "e"); + (chat, chatevent) := Cmdline.new(win, ".chat", nil); + updatech := chan of string; + spawn readproc(updatech); + + cmd(win, "button .b -text Start -command {send e start}"); + cmd(win, "pack .b -side top -anchor w"); + cmd(win, "pack .chat -fill both -expand 1"); + cmd(win, "pack propagate . 0"); + cmd(win, "update"); + tkclient->onscreen(win, nil); + tkclient->startinput(win, "kbd"::"ptr"::nil); + for (;;) alt { + s := <-win.ctxt.kbd => + tk->keyboard(win, s); + s := <-win.ctxt.ptr => + tk->pointer(win, *s); + s := <-win.ctxt.ctl or + s = <-win.wreq or + s = <-winctl => + tkclient->wmctl(win, s); + line := <-updatech => + (n, toks) := sys->tokenize(line, " "); + if (toks == nil) + continue; + case hd toks { + "clienttype" => + chat.addtext("starting " + hd tl toks + " session...\n"); + cmd(win, "update"); + path := CLIENTDIR + "/" + hd tl toks + ".dis"; + mod := load Command path; + if (mod == nil) { + chat.addtext(sys->sprint("could not load %s: %r\n", path)); + chat.addtext("bye bye\n"); + cliquefd = nil; + } else { + win = nil; + chat = nil; + startclient(mod, hd tl toks :: mnt :: dir :: tl tl toks); + exit; + } + "chat" => + chat.addtext(hd tl toks + ": " + concat(tl tl toks) + "\n"); + "title" => + tkclient->settitle(win, "Gather " + concat(tl toks)); + "join" or + "leave" or + "watch" or + "unwatch" => + chat.addtext(line + "\n"); + * => + chat.addtext("unknown update: " + line + "\n"); + } + cmd(win, "update"); + c := <-chatevent => + lines := chat.event(c); + for (; lines != nil; lines = tl lines) + cliquecmd("chat " + hd lines, chat); + c := <-ech => + cliquecmd(c, chat); + } +} + +cliquecmd(s: string, chat: ref Cmdline) +{ + if (sys->fprint(cliquefd, "%s", s) == -1) { + chat.addtext(sys->sprint("command failed: %r\n")); + cmd(chat.top, "update"); + } +} + +prefixed(s: string, prefix: string): int +{ + return len s >= len prefix && s[0:len prefix] == prefix; +} + +readproc(updatech: chan of string) +{ + buf := array[Sys->ATOMICIO] of byte; + while ((n := sys->read(cliquefd, buf, Sys->ATOMICIO)) > 0) { + (nil, lines) := sys->tokenize(string buf[0:n], "\n"); + for (; lines != nil; lines = tl lines) { + updatech <-= hd lines; + if (prefixed(hd lines, "clienttype")) + exit; + } + } + updatech <-= nil; +} + +startclient(mod: Command, argv: list of string) +{ + { + mod->init(drawctxt, argv); + } exception e { + "*" => + sys->print("client %s broken: %s\n", hd argv, e); + } +} + +cmd(win: ref Tk->Toplevel, s: string): string +{ + r := tk->cmd(win, s); + if(len r > 0 && r[0] == '!') + sys->print("error executing '%s': %s\n", s, r[1:]); + return r; +} + +concat(l: list of string): string +{ + if (l == nil) + return nil; + s := hd l; + for (l = tl l; l != nil; l = tl l) + s += " " + hd l; + return s; +} |
