summaryrefslogtreecommitdiff
path: root/appl/grid/query.b
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /appl/grid/query.b
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'appl/grid/query.b')
-rw-r--r--appl/grid/query.b399
1 files changed, 399 insertions, 0 deletions
diff --git a/appl/grid/query.b b/appl/grid/query.b
new file mode 100644
index 00000000..b0e9c376
--- /dev/null
+++ b/appl/grid/query.b
@@ -0,0 +1,399 @@
+implement Query;
+
+#
+# Copyright © 2003 Vita Nuova Holdings Limited. All rights reserved.
+#
+
+
+include "sys.m";
+ sys : Sys;
+include "draw.m";
+ draw: Draw;
+ Display, Rect, Image: import draw;
+include "tk.m";
+ tk: Tk;
+include "tkclient.m";
+ tkclient: Tkclient;
+include "readdir.m";
+ readdir: Readdir;
+include "sh.m";
+include "workdir.m";
+include "registries.m";
+ registries: Registries;
+ Service: import registries;
+include "grid/pathreader.m";
+ reader: PathReader;
+include "grid/browser.m";
+ browser: Browser;
+ Browse, File: import browser;
+include "grid/srvbrowse.m";
+ srvbrowse: Srvbrowse;
+include "grid/fbrowse.m";
+include "grid/announce.m";
+ announce: Announce;
+
+srvfilter : list of list of (string, string);
+
+Query : module {
+ init : fn (context : ref Draw->Context, nil : list of string);
+ readpath: fn (dir: File): (array of ref sys->Dir, int);
+};
+
+realinit()
+{
+ sys = load Sys Sys->PATH;
+ if (sys == nil)
+ badmod(Sys->PATH);
+ readdir = load Readdir Readdir->PATH;
+ if (readdir == nil)
+ badmod(Readdir->PATH);
+ draw = load Draw Draw->PATH;
+ if (draw == nil)
+ badmod(Draw->PATH);
+ tk = load Tk Tk->PATH;
+ if (tk == nil)
+ badmod(Tk->PATH);
+ tkclient = load Tkclient Tkclient->PATH;
+ if (tkclient == nil)
+ badmod(Tkclient->PATH);
+ tkclient->init();
+ workdir := load Workdir Workdir->PATH;
+ if (workdir == nil)
+ badmod(Workdir->PATH);
+ registries = load Registries Registries->PATH;
+ if (registries == nil)
+ badmod(Registries->PATH);
+ registries->init();
+ browser = load Browser Browser->PATH;
+ if (browser == nil)
+ badmod(Browser->PATH);
+ browser->init();
+ srvbrowse = load Srvbrowse Srvbrowse->PATH;
+ if (srvbrowse == nil)
+ badmod(Srvbrowse->PATH);
+ srvbrowse->init();
+ announce = load Announce Announce->PATH;
+ if (announce == nil)
+ badmod(Announce->PATH);
+ announce->init();
+ reader = load PathReader "$self";
+ if (reader == nil)
+ badmod("PathReader");
+}
+
+init(ctxt : ref Draw->Context, nil: list of string)
+{
+ realinit();
+ spawn start(ctxt, 1);
+}
+
+start(ctxt: ref Draw->Context, standalone: int)
+{
+ sys->pctl(sys->FORKNS | sys->NEWPGRP, nil);
+ if (ctxt == nil)
+ ctxt = tkclient->makedrawcontext();
+
+ if (standalone)
+ sys->create("/tmp/query", sys->OREAD, sys->DMDIR | 8r777);
+ root := "/";
+ (top, titlebar) := tkclient->toplevel(ctxt,"","Query", tkclient->Appl);
+ butchan := chan of string;
+ tk->namechan(top, butchan, "butchan");
+ browsechan := chan of string;
+ tk->namechan(top, browsechan, "browsechan");
+ br := Browse.new(top, "browsechan", "services/", "Services", 1, reader);
+ br.addopened(File ("services/", nil), 1);
+ srvbrowse->refreshservices(srvfilter);
+ br.refresh();
+
+ for (ik := 0; ik < len mainscreen; ik++)
+ tkcmd(top,mainscreen[ik]);
+
+ tkcmd(top, "pack .f -fill both -expand 1; pack propagate . 0");
+ released := 1;
+ title := "";
+ resize(top, 400,400);
+ tkclient->onscreen(top, nil);
+ tkclient->startinput(top, "kbd"::"ptr"::nil);
+ tkpath: string;
+ main: for (;;) {
+ alt {
+ s := <-top.ctxt.kbd =>
+ tk->keyboard(top, s);
+ s := <-top.ctxt.ptr =>
+ tk->pointer(top, *s);
+ inp := <-browsechan =>
+ (nil, lst) := sys->tokenize(inp, " \n\t");
+ if (len lst > 1)
+ tkpath = hd tl lst;
+ selected := br.getselected(0);
+ br.defaultaction(lst, nil);
+ if (!File.eq(selected, br.getselected(0)))
+ actionbutton(top, br.selected[0].file.path, br.selected[0].tkpath);
+ tkcmd(top, "update");
+ inp := <-butchan =>
+ # sys->print("inp: %s\n",inp);
+ (nil, lst) := sys->tokenize(inp, " \n\t");
+ if (len lst > 1)
+ tkpath = hd tl lst;
+ case hd lst {
+ "search" =>
+ if (tl lst == nil)
+ spawn srvbrowse->searchwin(ctxt, butchan, nil);
+ else {
+ if (hd tl lst == "select") {
+ file := hd tl tl lst;
+ for (tmp := tl tl tl lst; tl tmp != nil; tmp = tl tmp)
+ file += " "+hd tmp;
+ qid := hd tmp;
+ br.gotoselectfile(File (file, qid));
+ actionbutton(top, br.selected[0].file.path, br.selected[0].tkpath);
+ }
+ else if (hd tl lst == "search") {
+ srvbrowse->refreshservices(srvfilter);
+ br.refresh();
+ }
+ }
+ "refresh" =>
+ # ! check to see if anything is mounted first
+ srvbrowse->refreshservices(srvfilter);
+ br.refresh();
+ "mount" =>
+ file := *br.getpath(tkpath);
+ (nsrv, lsrv) := sys->tokenize(file.path, "/");
+ if (nsrv == 3)
+ spawn mountsrv(ctxt, file, getcoords(top));
+ }
+ tkcmd(top, "update");
+
+ title = <-top.ctxt.ctl or
+ title = <-top.wreq or
+ title = <-titlebar =>
+ if (title == "exit")
+ break main;
+ e := tkclient->wmctl(top, title);
+ if (e == nil && title[0] == '!')
+ (nil, lst) := sys->tokenize(title, " \t\n");
+ }
+ }
+ killg(sys->pctl(0,nil));
+}
+
+resize(top: ref Tk->Toplevel, w, h: int)
+{
+ tkcmd(top, ". configure -x 0 -width "+string min(top.screenr.dx(), w));
+ tkcmd(top, ". configure -y 0 -height "+string min(top.screenr.dy(), h));
+}
+
+min(a, b: int): int
+{
+ if (a < b)
+ return a;
+ return b;
+}
+
+nactionbuttons := 0;
+actionbutton(top: ref Tk->Toplevel, path, tkpath: string)
+{
+ for (i := 0; i < nactionbuttons; i++) {
+ tkcmd(top, "grid forget .f.ftop.baction"+string i);
+ tkcmd(top, "destroy .f.ftop.baction"+string i);
+ }
+ if (path == nil) {
+ nactionbuttons = 0;
+ return;
+ }
+ (n, nil) := sys->tokenize(path, "/");
+ buttons : list of (string, string) = nil;
+ if (n == 3)
+ buttons = ("Mount", "mount "+tkpath) :: buttons;
+
+ nactionbuttons = len buttons;
+ for (i = 0; i < nactionbuttons; i++) {
+ name := ".f.ftop.baction"+string i+" ";
+ (text,cmd) := hd buttons;
+ tkcmd(top, "button "+name+"-text {"+text+"} "+
+ "-font /fonts/charon/bold.normal.font "+
+ "-command {send butchan "+cmd+"}");
+ tkcmd(top, "grid "+name+" -row 0 -column "+string (4+i));
+ buttons = tl buttons;
+ }
+}
+
+kill(pid: int)
+{
+ if ((fd := sys->open("/prog/" + string pid + "/ctl", Sys->OWRITE)) != nil)
+ sys->fprint(fd, "kill");
+}
+
+killg(pid: int)
+{
+ if ((fd := sys->open("/prog/" + string pid + "/ctl", Sys->OWRITE)) != nil)
+ sys->fprint(fd, "killgrp");
+}
+
+mainscreen := array[] of {
+ "frame .f",
+ "frame .f.ftop",
+ "variable opt command",
+ "button .f.ftop.br -text {Refresh} -command {send butchan refresh} -font /fonts/charon/bold.normal.font",
+ "button .f.ftop.bs -text {Search} -command {send butchan search} -font /fonts/charon/bold.normal.font",
+ "grid .f.ftop.br .f.ftop.bs -row 0",
+ "grid columnconfigure .f.ftop 3 -minsize 30",
+ "label .f.l -text { } -height 1 -bg red",
+ "grid .f.l -row 1 -column 0 -sticky ew",
+ "grid .f.ftop -row 0 -column 0 -pady 2 -sticky w",
+ "grid .fbrowse -in .f -row 2 -column 0 -sticky nsew",
+
+ "grid columnconfigure .f 0 -weight 1",
+ "grid rowconfigure .f 2 -weight 1",
+
+ "bind .Wm_t <Button-1> +{focus .Wm_t}",
+ "bind .Wm_t.title <Button-1> +{focus .Wm_t}",
+ "focus .Wm_t",
+};
+
+readpath(dir: File): (array of ref sys->Dir, int)
+{
+ return srvbrowse->servicepath2Dir(dir.path, int dir.qid);
+}
+
+badmod(path: string)
+{
+ sys->print("Query: failed to load %s: %r\n",path);
+ exit;
+}
+
+mountscr := array[] of {
+ "frame .f -borderwidth 2 -relief raised",
+ "text .f.t -width 200 -height 60 -borderwidth 1 -bg white -font /fonts/charon/plain.normal.font",
+ "button .f.b -text {Cancel} -command {send butchan cancel} -width 70 -font /fonts/charon/plain.normal.font",
+ "grid .f.t -row 0 -column 0 -padx 10 -pady 10",
+ "grid .f.b -row 1 -column 0 -sticky n",
+ "grid rowconfigure .f 1 -minsize 30",
+};
+
+mountsrv(ctxt: ref Draw->Context, srvfile: File, coords: draw->Rect)
+{
+ (top, nil) := tkclient->toplevel(ctxt, "", nil, tkclient->Plain);
+ ctlchan := chan of string;
+ butchan := chan of string;
+ tk->namechan(top, butchan, "butchan");
+ tkcmds(top, mountscr);
+ tkcmd(top, ". configure "+getcentre(top, coords)+"; pack .f; update");
+ spawn mountit(ctxt, srvfile, ctlchan);
+ pid := int <-ctlchan;
+ tkclient->onscreen(top, "exact");
+ tkclient->startinput(top, "kbd"::"ptr"::nil);
+ for (;;) {
+ alt {
+ s := <-top.ctxt.kbd =>
+ tk->keyboard(top, s);
+ s := <-top.ctxt.ptr =>
+ tk->pointer(top, *s);
+ e := <- ctlchan =>
+ if (e[0] == '!') {
+ tkcmd(top, ".f.t insert end {"+e[1:]+"}");
+ tkcmd(top, ".f.b configure -text {close}; update");
+ pid = -1;
+ }
+ else if (e == "ok")
+ return;
+ else
+ tkcmd(top, ".f.t insert end {"+e+"}; update");
+ <- butchan =>
+ if (pid != -1)
+ kill(pid);
+ return;
+ }
+ }
+}
+
+mountit(ctxt: ref Draw->Context, srvfile: File, ctlchan: chan of string)
+{
+ ctlchan <-= string sys->pctl(0,nil);
+
+ n := 0;
+ (nil, lst) := sys->tokenize(srvfile.path, "/");
+ stype := hd tl lst;
+ name := hd tl tl lst;
+ addr := "";
+ ctlchan <-= "Connecting...\n";
+ lsrv := srvbrowse->servicepath2Service(srvfile.path, srvfile.qid);
+ if (len lsrv < 1) {
+ ctlchan <-= "!could not find service";
+ return;
+ }
+ srvc := hd lsrv;
+
+ ctlchan <-= "Mounting...\n";
+
+ id := 0;
+ dir : string;
+ for (;;) {
+ dir = "/tmp/query/"+string id;
+ (n2, nil) := sys->stat(dir);
+ if (n2 == -1) {
+ fdtmp := sys->create(dir, sys->OREAD, sys->DMDIR | 8r777);
+ if (fdtmp != nil)
+ break;
+ }
+ else {
+ (dirs2, nil) := readdir->init(dir, readdir->NAME | readdir->COMPACT);
+ if (len dirs2 == 0)
+ break;
+ }
+ id++;
+ }
+ attached := srvc.attach(nil, nil);
+ if (attached == nil) {
+ ctlchan <-= sys->sprint("!could not connect: %r");
+ return;
+ }
+ if (sys->mount(attached.fd, nil, dir, sys->MREPL, nil) != -1) {
+ ctlchan <-= "ok";
+ fbrowse := load FBrowse FBrowse->PATH;
+ if (fbrowse == nil)
+ badmod(FBrowse->PATH);
+ fbrowse->init(ctxt, srvfile.path, dir, dir);
+ sys->unmount(nil, dir);
+ attached = nil;
+ }
+ else
+ ctlchan <-= sys->sprint("!mount failed: %r");
+}
+
+getcoords(top: ref Tk->Toplevel): draw->Rect
+{
+ h := int tkcmd(top, ". cget -height");
+ w := int tkcmd(top, ". cget -width");
+ x := int tkcmd(top, ". cget -actx");
+ y := int tkcmd(top, ". cget -acty");
+ r := draw->Rect((x,y),(x+w,y+h));
+ return r;
+}
+
+getcentre(top: ref Tk->Toplevel, winr: draw->Rect): string
+{
+ h := int tkcmd(top, ".f cget -height");
+ w := int tkcmd(top, ".f cget -width");
+ midx := winr.min.x + (winr.dx() / 2);
+ midy := winr.min.y + (winr.dy() / 2);
+ newx := midx - (w/2);
+ newy := midy - (h/2);
+ return "-x "+string newx+" -y "+string newy;
+}
+
+tkcmd(top: ref Tk->Toplevel, cmd: string): string
+{
+ e := tk->cmd(top, cmd);
+ if (e != "" && e[0] == '!')
+ sys->print("Tk error: '%s': %s\n",cmd,e);
+ return e;
+}
+
+tkcmds(top: ref Tk->Toplevel, a: array of string)
+{
+ for (j := 0; j < len a; j++)
+ tkcmd(top, a[j]);
+}