summaryrefslogtreecommitdiff
path: root/appl/spree/clients/gather.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/spree/clients/gather.b')
-rw-r--r--appl/spree/clients/gather.b178
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;
+}