137da2899SCharles.Forsythimplement Srvbrowse; 237da2899SCharles.Forsyth 337da2899SCharles.Forsyth# 437da2899SCharles.Forsyth# Copyright © 2003 Vita Nuova Holdings Limited. All rights reserved. 537da2899SCharles.Forsyth# 637da2899SCharles.Forsyth 737da2899SCharles.Forsyth 837da2899SCharles.Forsythinclude "sys.m"; 937da2899SCharles.Forsyth sys : Sys; 1037da2899SCharles.Forsythinclude "draw.m"; 1137da2899SCharles.Forsyth draw: Draw; 1237da2899SCharles.Forsyth Rect: import draw; 1337da2899SCharles.Forsythinclude "tk.m"; 1437da2899SCharles.Forsyth tk: Tk; 1537da2899SCharles.Forsythinclude "tkclient.m"; 1637da2899SCharles.Forsyth tkclient: Tkclient; 1737da2899SCharles.Forsythinclude "grid/srvbrowse.m"; 1837da2899SCharles.Forsythinclude "registries.m"; 1937da2899SCharles.Forsyth registries: Registries; 2037da2899SCharles.Forsyth Registry, Attributes, Service: import registries; 2137da2899SCharles.Forsyth 2237da2899SCharles.Forsythinit() 2337da2899SCharles.Forsyth{ 2437da2899SCharles.Forsyth sys = load Sys Sys->PATH; 2537da2899SCharles.Forsyth if (sys == nil) 2637da2899SCharles.Forsyth badmod(Sys->PATH); 2737da2899SCharles.Forsyth draw = load Draw Draw->PATH; 2837da2899SCharles.Forsyth if (draw == nil) 2937da2899SCharles.Forsyth badmod(Draw->PATH); 3037da2899SCharles.Forsyth tk = load Tk Tk->PATH; 3137da2899SCharles.Forsyth if (tk == nil) 3237da2899SCharles.Forsyth badmod(Tk->PATH); 3337da2899SCharles.Forsyth tkclient = load Tkclient Tkclient->PATH; 3437da2899SCharles.Forsyth if (tkclient == nil) 3537da2899SCharles.Forsyth badmod(Tkclient->PATH); 3637da2899SCharles.Forsyth tkclient->init(); 3737da2899SCharles.Forsyth registries = load Registries Registries->PATH; 3837da2899SCharles.Forsyth if (registries == nil) 3937da2899SCharles.Forsyth badmod(Registries->PATH); 4037da2899SCharles.Forsyth registries->init(); 4137da2899SCharles.Forsyth reg = Registry.new("/mnt/registry"); 4237da2899SCharles.Forsyth if (reg == nil) { 4337da2899SCharles.Forsyth reg = Registry.connect(nil, nil, nil); 4437da2899SCharles.Forsyth if (reg == nil) 4537da2899SCharles.Forsyth error("Could not find registry"); 4637da2899SCharles.Forsyth } 4737da2899SCharles.Forsyth qids = array[511] of { * => "" }; 4837da2899SCharles.Forsyth} 4937da2899SCharles.Forsyth 5037da2899SCharles.Forsythreg : ref Registry; 5137da2899SCharles.Forsythqids : array of string; 5237da2899SCharles.Forsyth 5337da2899SCharles.Forsyth# Qid stuff is a bit rubbish at the mo but waiting for registries to change: 5437da2899SCharles.Forsyth# currently address is unique but will not be in the future so waiting 5537da2899SCharles.Forsyth# for another id to uniquely identify a resource 5637da2899SCharles.Forsyth 5737da2899SCharles.Forsythaddqid(srvc: ref Service): int 5837da2899SCharles.Forsyth{ 5937da2899SCharles.Forsyth addr := srvc.addr; 6037da2899SCharles.Forsyth qid := addr2qid(addr); 6137da2899SCharles.Forsyth for (;;) { 6237da2899SCharles.Forsyth if (qids[qid] == nil) 6337da2899SCharles.Forsyth break; 6437da2899SCharles.Forsyth else if (qids[qid] == addr) 6537da2899SCharles.Forsyth return qid; 6637da2899SCharles.Forsyth qid++; 6737da2899SCharles.Forsyth if (qid >= len qids) 6837da2899SCharles.Forsyth qid = 0; 6937da2899SCharles.Forsyth } 7037da2899SCharles.Forsyth qids[qid] = addr; 7137da2899SCharles.Forsyth# sys->print("adding %s (%s) to %d\n",srvc.attrs.get("resource"), addr, qid); 7237da2899SCharles.Forsyth return qid; 7337da2899SCharles.Forsyth} 7437da2899SCharles.Forsyth 7537da2899SCharles.Forsythgetqid(srvc: ref Service): string 7637da2899SCharles.Forsyth{ 7737da2899SCharles.Forsyth addr := srvc.addr; 7837da2899SCharles.Forsyth qid := addr2qid(addr); 7937da2899SCharles.Forsyth startqid := qid; 8037da2899SCharles.Forsyth for (;;) { 8137da2899SCharles.Forsyth if (qids[qid] == addr) 8237da2899SCharles.Forsyth return string qid; 8337da2899SCharles.Forsyth qid++; 8437da2899SCharles.Forsyth if (qid == startqid) 8537da2899SCharles.Forsyth break; 8637da2899SCharles.Forsyth if (qid >= len qids) 8737da2899SCharles.Forsyth qid = 0; 8837da2899SCharles.Forsyth } 8937da2899SCharles.Forsyth return nil; 9037da2899SCharles.Forsyth} 9137da2899SCharles.Forsyth 9237da2899SCharles.Forsythaddr2qid(addr: string): int 9337da2899SCharles.Forsyth{ 9437da2899SCharles.Forsyth qid := 0; 9537da2899SCharles.Forsyth # assume addr starts 'tcp!...' 9637da2899SCharles.Forsyth for (i := 4; i < len addr; i++) { 9737da2899SCharles.Forsyth qid += addr[i] * 2**(i%10); 9837da2899SCharles.Forsyth qid = qid % len qids; 9937da2899SCharles.Forsyth } 10037da2899SCharles.Forsyth return qid; 10137da2899SCharles.Forsyth} 10237da2899SCharles.Forsyth 10337da2899SCharles.Forsythaddservice(srvc: ref Service) 10437da2899SCharles.Forsyth{ 10537da2899SCharles.Forsyth services = srvc :: services; 10637da2899SCharles.Forsyth addqid(srvc); 10737da2899SCharles.Forsyth} 10837da2899SCharles.Forsyth 10937da2899SCharles.Forsythfind(filter: list of list of (string, string)): list of ref Service 11037da2899SCharles.Forsyth{ 11137da2899SCharles.Forsyth lsrv : list of ref Service = nil; 11237da2899SCharles.Forsyth if (filter == nil) 11337da2899SCharles.Forsyth (lsrv, nil) = reg.services(); 11437da2899SCharles.Forsyth else { 11537da2899SCharles.Forsyth for (; filter != nil; filter = tl filter) { 11637da2899SCharles.Forsyth attr := hd filter; 117*170ff9d4SCharles Forsyth (s, nil) := reg.find(attr); 11837da2899SCharles.Forsyth for (; s != nil; s = tl s) 11937da2899SCharles.Forsyth lsrv = hd s :: lsrv; 12037da2899SCharles.Forsyth } 12137da2899SCharles.Forsyth } 12237da2899SCharles.Forsyth return sortservices(lsrv); 12337da2899SCharles.Forsyth} 12437da2899SCharles.Forsyth 12537da2899SCharles.Forsythrefreshservices(filter: list of list of (string, string)) 12637da2899SCharles.Forsyth{ 12737da2899SCharles.Forsyth services = find(filter); 12837da2899SCharles.Forsyth} 12937da2899SCharles.Forsyth 13037da2899SCharles.Forsythservicepath2Service(path, qid: string): list of ref Service 13137da2899SCharles.Forsyth{ 13237da2899SCharles.Forsyth srvl : list of ref Service = nil; 13337da2899SCharles.Forsyth (nil, lst) := sys->tokenize(path, "/"); 13437da2899SCharles.Forsyth pname: string; 13537da2899SCharles.Forsyth l := len lst; 13637da2899SCharles.Forsyth if (l < 2 || l > 3) 13737da2899SCharles.Forsyth return nil; 13837da2899SCharles.Forsyth presource := hd tl lst; 13937da2899SCharles.Forsyth if (l == 3) 14037da2899SCharles.Forsyth pname = hd tl tl lst; 14137da2899SCharles.Forsyth 14237da2899SCharles.Forsyth for (tmpl := services; tmpl != nil; tmpl = tl tmpl) { 14337da2899SCharles.Forsyth srvc := hd tmpl; 14437da2899SCharles.Forsyth (resource, name) := getresname(srvc); 14537da2899SCharles.Forsyth if (l == 2) { 14637da2899SCharles.Forsyth if (resource == presource) 14737da2899SCharles.Forsyth srvl = srvc :: srvl; 14837da2899SCharles.Forsyth } 14937da2899SCharles.Forsyth else if (l == 3) { 15037da2899SCharles.Forsyth if (resource == presource) { 15137da2899SCharles.Forsyth if (name == pname && qid == getqid(srvc)) { 15237da2899SCharles.Forsyth srvl = srvc :: srvl; 15337da2899SCharles.Forsyth break; 15437da2899SCharles.Forsyth } 15537da2899SCharles.Forsyth } 15637da2899SCharles.Forsyth } 15737da2899SCharles.Forsyth } 15837da2899SCharles.Forsyth return srvl; 15937da2899SCharles.Forsyth} 16037da2899SCharles.Forsyth 16137da2899SCharles.Forsythservicepath2Dir(path: string, qid: int): (array of ref sys->Dir, int) 16237da2899SCharles.Forsyth{ 16337da2899SCharles.Forsyth # sys->print("srvcPath2Dir: '%s' %d\n",path, qid); 16437da2899SCharles.Forsyth res : list of (string, string) = nil; 16537da2899SCharles.Forsyth (nil, lst) := sys->tokenize(path, "/"); 16637da2899SCharles.Forsyth presource, pname: string; 16737da2899SCharles.Forsyth pattrib := 0; 16837da2899SCharles.Forsyth l := len lst; 16937da2899SCharles.Forsyth if (l > 1) 17037da2899SCharles.Forsyth presource = hd tl lst; 17137da2899SCharles.Forsyth if (l > 2) 17237da2899SCharles.Forsyth pname = hd tl tl lst; 17337da2899SCharles.Forsyth if (l == 4 && hd tl tl tl lst == "attributes") 17437da2899SCharles.Forsyth pattrib = 1; 17537da2899SCharles.Forsyth for (tmpl := services; tmpl != nil; tmpl = tl tmpl) { 17637da2899SCharles.Forsyth srvc := hd tmpl; 17737da2899SCharles.Forsyth (resource, name) := getresname(srvc); 17837da2899SCharles.Forsyth if (l == 1) { 17937da2899SCharles.Forsyth if (!isin(res, resource)) 18037da2899SCharles.Forsyth res = (resource, nil) :: res; 18137da2899SCharles.Forsyth } 18237da2899SCharles.Forsyth else if (l == 2) { 18337da2899SCharles.Forsyth if (resource == presource) 18437da2899SCharles.Forsyth res = (name, string getqid(srvc)) :: res; 18537da2899SCharles.Forsyth } 18637da2899SCharles.Forsyth else if (l == 3) { 18737da2899SCharles.Forsyth if (resource == presource && name == pname) { 18837da2899SCharles.Forsyth if (qid == int getqid(srvc)) { 18937da2899SCharles.Forsyth if (srvc.addr[0] == '@') 19037da2899SCharles.Forsyth res = (srvc.addr[1:], string getqid(srvc)) :: res; 19137da2899SCharles.Forsyth else { 19237da2899SCharles.Forsyth if (srvc.attrs != nil) 19337da2899SCharles.Forsyth res = ("attributes", string getqid(srvc)) :: res; 19437da2899SCharles.Forsyth res = ("address:\0"+srvc.addr+"}", string getqid(srvc)) :: res; 19537da2899SCharles.Forsyth } 19637da2899SCharles.Forsyth break; 19737da2899SCharles.Forsyth } 19837da2899SCharles.Forsyth } 19937da2899SCharles.Forsyth } 20037da2899SCharles.Forsyth else if (l == 4) { 20137da2899SCharles.Forsyth if (resource == presource && name == pname && pattrib) { 20237da2899SCharles.Forsyth if (qid == int getqid(srvc)) { 20337da2899SCharles.Forsyth for (tmpl2 := srvc.attrs.attrs; tmpl2 != nil; tmpl2 = tl tmpl2) { 20437da2899SCharles.Forsyth (attrib, val) := hd tmpl2; 20537da2899SCharles.Forsyth if (attrib != "name" && attrib != "resource") 20637da2899SCharles.Forsyth res = (attrib+":\0"+val, string getqid(srvc)) :: res; 20737da2899SCharles.Forsyth } 20837da2899SCharles.Forsyth break; 20937da2899SCharles.Forsyth } 21037da2899SCharles.Forsyth } 21137da2899SCharles.Forsyth } 21237da2899SCharles.Forsyth } 21337da2899SCharles.Forsyth resa := array [len res] of ref sys->Dir; 21437da2899SCharles.Forsyth i := len resa - 1; 21537da2899SCharles.Forsyth for (; res != nil; res = tl res) { 21637da2899SCharles.Forsyth dir : sys->Dir; 21737da2899SCharles.Forsyth qid: string; 21837da2899SCharles.Forsyth (dir.name, qid) = hd res; 21937da2899SCharles.Forsyth if (l < 3 || dir.name == "attributes") 22037da2899SCharles.Forsyth dir.mode = 8r777 | sys->DMDIR; 22137da2899SCharles.Forsyth else 22237da2899SCharles.Forsyth dir.mode = 8r777; 22337da2899SCharles.Forsyth if (qid != nil) 22437da2899SCharles.Forsyth dir.qid.path = big qid; 22537da2899SCharles.Forsyth resa[i--] = ref dir; 22637da2899SCharles.Forsyth } 22737da2899SCharles.Forsyth dups := 0; 22837da2899SCharles.Forsyth if (l >= 2) 22937da2899SCharles.Forsyth dups = 1; 23037da2899SCharles.Forsyth return (resa, dups); 23137da2899SCharles.Forsyth} 23237da2899SCharles.Forsyth 23337da2899SCharles.Forsythisin(l: list of (string, string), s: string): int 23437da2899SCharles.Forsyth{ 23537da2899SCharles.Forsyth for (; l != nil; l = tl l) 23637da2899SCharles.Forsyth if ((hd l).t0 == s) 23737da2899SCharles.Forsyth return 1; 23837da2899SCharles.Forsyth return 0; 23937da2899SCharles.Forsyth} 24037da2899SCharles.Forsyth 24137da2899SCharles.Forsythgetresname(srvc: ref Service): (string, string) 24237da2899SCharles.Forsyth{ 24337da2899SCharles.Forsyth resource := srvc.attrs.get("resource"); 24437da2899SCharles.Forsyth if (resource == nil) 24537da2899SCharles.Forsyth resource = "Other"; 24637da2899SCharles.Forsyth name := srvc.attrs.get("name"); 24737da2899SCharles.Forsyth if (name == nil) 24837da2899SCharles.Forsyth name = "?????"; 24937da2899SCharles.Forsyth return (resource,name); 25037da2899SCharles.Forsyth} 25137da2899SCharles.Forsyth 25237da2899SCharles.Forsythbadmod(path: string) 25337da2899SCharles.Forsyth{ 25437da2899SCharles.Forsyth sys->print("Srvbrowse: failed to load: %s\n",path); 25537da2899SCharles.Forsyth exit; 25637da2899SCharles.Forsyth} 25737da2899SCharles.Forsyth 25837da2899SCharles.Forsythsortservices(lsrv: list of ref Service): list of ref Service 25937da2899SCharles.Forsyth{ 26037da2899SCharles.Forsyth a := array[len lsrv] of ref Service; 26137da2899SCharles.Forsyth i := 0; 26237da2899SCharles.Forsyth for (; lsrv != nil; lsrv = tl lsrv) { 26337da2899SCharles.Forsyth addqid(hd lsrv); 26437da2899SCharles.Forsyth a[i++] = hd lsrv; 26537da2899SCharles.Forsyth } 26637da2899SCharles.Forsyth heapsort(a); 26737da2899SCharles.Forsyth lsrvsorted: list of ref Service = nil; 26837da2899SCharles.Forsyth for (i = len a - 1; i >= 0; i--) 26937da2899SCharles.Forsyth lsrvsorted = a[i] :: lsrvsorted; 27037da2899SCharles.Forsyth return lsrvsorted; 27137da2899SCharles.Forsyth} 27237da2899SCharles.Forsyth 27337da2899SCharles.Forsyth 27437da2899SCharles.Forsythheapsort(a: array of ref Service) 27537da2899SCharles.Forsyth{ 27637da2899SCharles.Forsyth for (i := (len a / 2) - 1; i >= 0; i--) 27737da2899SCharles.Forsyth movedownheap(a, i, len a - 1); 27837da2899SCharles.Forsyth 27937da2899SCharles.Forsyth for (i = len a - 1; i > 0; i--) { 28037da2899SCharles.Forsyth tmp := a[0]; 28137da2899SCharles.Forsyth a[0] = a[i]; 28237da2899SCharles.Forsyth a[i] = tmp; 28337da2899SCharles.Forsyth movedownheap(a, 0, i - 1); 28437da2899SCharles.Forsyth } 28537da2899SCharles.Forsyth} 28637da2899SCharles.Forsyth 28737da2899SCharles.Forsythmovedownheap(a: array of ref Service, root, end: int) 28837da2899SCharles.Forsyth{ 28937da2899SCharles.Forsyth max: int; 29037da2899SCharles.Forsyth while (2*root <= end) { 29137da2899SCharles.Forsyth r2 := root * 2; 29237da2899SCharles.Forsyth if (2*root == end || comp(a[r2], a[r2+1]) == GT) 29337da2899SCharles.Forsyth max = r2; 29437da2899SCharles.Forsyth else 29537da2899SCharles.Forsyth max = r2 + 1; 29637da2899SCharles.Forsyth 29737da2899SCharles.Forsyth if (comp(a[root], a[max]) == LT) { 29837da2899SCharles.Forsyth tmp := a[root]; 29937da2899SCharles.Forsyth a[root] = a[max]; 30037da2899SCharles.Forsyth a[max] = tmp; 30137da2899SCharles.Forsyth root = max; 30237da2899SCharles.Forsyth } 30337da2899SCharles.Forsyth else 30437da2899SCharles.Forsyth break; 30537da2899SCharles.Forsyth } 30637da2899SCharles.Forsyth} 30737da2899SCharles.Forsyth 30837da2899SCharles.ForsythLT: con -1; 30937da2899SCharles.ForsythEQ: con 0; 31037da2899SCharles.ForsythGT: con 1; 31137da2899SCharles.Forsyth 31237da2899SCharles.Forsythcomp(a1, a2: ref Service): int 31337da2899SCharles.Forsyth{ 31437da2899SCharles.Forsyth (resource1, name1) := getresname(a1); 31537da2899SCharles.Forsyth (resource2, name2) := getresname(a2); 31637da2899SCharles.Forsyth if (resource1 < resource2) 31737da2899SCharles.Forsyth return LT; 31837da2899SCharles.Forsyth if (resource1 > resource2) 31937da2899SCharles.Forsyth return GT; 32037da2899SCharles.Forsyth if (name1 < name2) 32137da2899SCharles.Forsyth return LT; 32237da2899SCharles.Forsyth if (name1 > name2) 32337da2899SCharles.Forsyth return GT; 32437da2899SCharles.Forsyth return EQ; 32537da2899SCharles.Forsyth} 32637da2899SCharles.Forsyth 32737da2899SCharles.Forsytherror(e: string) 32837da2899SCharles.Forsyth{ 32937da2899SCharles.Forsyth sys->fprint(sys->fildes(2), "Srvbrowse: %s\n", e); 33037da2899SCharles.Forsyth raise "fail:error"; 33137da2899SCharles.Forsyth} 33237da2899SCharles.Forsyth 33337da2899SCharles.Forsythsearchscr := array[] of { 33437da2899SCharles.Forsyth "frame .f", 33537da2899SCharles.Forsyth "scrollbar .f.sy -command {.f.c yview}", 33637da2899SCharles.Forsyth "scrollbar .f.sx -command {.f.c xview} -orient horizontal", 33737da2899SCharles.Forsyth "canvas .f.c -yscrollcommand {.f.sy set} -xscrollcommand {.f.sx set} -bg white -width 414 -borderwidth 2 -relief sunken -height 180 -xscrollincrement 10 -yscrollincrement 19", 33837da2899SCharles.Forsyth "grid .f.sy -row 0 -column 0 -sticky ns -rowspan 2", 33937da2899SCharles.Forsyth "grid .f.sx -row 1 -column 1 -sticky ew", 34037da2899SCharles.Forsyth "grid .f.c -row 0 -column 1", 34137da2899SCharles.Forsyth "pack .f -fill both -expand 1 ; pack propagate . 0; update", 34237da2899SCharles.Forsyth}; 34337da2899SCharles.Forsyth 34437da2899SCharles.ForsythSEARCH, RESULTS: con iota; 34537da2899SCharles.Forsyth 34637da2899SCharles.Forsythsearchwin(ctxt: ref Draw->Context, chanout: chan of string, filter: list of list of (string, string)) 34737da2899SCharles.Forsyth{ 34837da2899SCharles.Forsyth (top, titlebar) := tkclient->toplevel(ctxt,"","Search", tkclient->Appl); 34937da2899SCharles.Forsyth butchan := chan of string; 35037da2899SCharles.Forsyth tk->namechan(top, butchan, "butchan"); 35137da2899SCharles.Forsyth tkcmds(top, searchscr); 35237da2899SCharles.Forsyth makesearchframe(top); 35337da2899SCharles.Forsyth flid := setframe(top, ".fsearch", nil); 35437da2899SCharles.Forsyth selected := ""; 35537da2899SCharles.Forsyth lresults : list of ref Service = nil; 35637da2899SCharles.Forsyth resultstart := 0; 35737da2899SCharles.Forsyth resize(top, 368,220); 35837da2899SCharles.Forsyth maxresults := getmaxresults(top); 35937da2899SCharles.Forsyth currmode := SEARCH; 36037da2899SCharles.Forsyth tkclient->onscreen(top, nil); 36137da2899SCharles.Forsyth tkclient->startinput(top, "kbd"::"ptr"::nil); 36237da2899SCharles.Forsyth 36337da2899SCharles.Forsyth main: for (;;) { 36437da2899SCharles.Forsyth alt { 36537da2899SCharles.Forsyth s := <-top.ctxt.kbd => 36637da2899SCharles.Forsyth tk->keyboard(top, s); 36737da2899SCharles.Forsyth s := <-top.ctxt.ptr => 36837da2899SCharles.Forsyth tk->pointer(top, *s); 36937da2899SCharles.Forsyth inp := <-butchan => 37037da2899SCharles.Forsyth (nil, lst) := sys->tokenize(inp, " "); 37137da2899SCharles.Forsyth case hd lst { 37237da2899SCharles.Forsyth "key" => 37337da2899SCharles.Forsyth s := " "; 37437da2899SCharles.Forsyth id := hd tl lst; 37537da2899SCharles.Forsyth nv := hd tl tl lst; 37637da2899SCharles.Forsyth tkp : string; 37737da2899SCharles.Forsyth if (id != "-1") 37837da2899SCharles.Forsyth tkp = ".fsearch.ea"+nv+id; 37937da2899SCharles.Forsyth else 38037da2899SCharles.Forsyth tkp = ".fsearch.e"+nv; 38137da2899SCharles.Forsyth char := int hd tl tl tl lst; 38237da2899SCharles.Forsyth s[0] = char; 38337da2899SCharles.Forsyth if (char == '\n' || char == '\t') { 38437da2899SCharles.Forsyth newtkp := ".fsearch"; 38537da2899SCharles.Forsyth if (nv == "n") 38637da2899SCharles.Forsyth newtkp += ".eav"+id; 38737da2899SCharles.Forsyth else if (nv == "v") { 38837da2899SCharles.Forsyth newid := string ((int id)+1); 38937da2899SCharles.Forsyth e := tk->cmd(top, ".fsearch.ean"+newid+" cget -width"); 39037da2899SCharles.Forsyth if (e == "" || e[0] == '!') { 39137da2899SCharles.Forsyth insertattribrow(top); 39237da2899SCharles.Forsyth newtkp += ".ean"+newid; 39337da2899SCharles.Forsyth } 39437da2899SCharles.Forsyth else 39537da2899SCharles.Forsyth newtkp += ".ean"+newid; 39637da2899SCharles.Forsyth } 39737da2899SCharles.Forsyth focus(top, newtkp); 39837da2899SCharles.Forsyth } 39937da2899SCharles.Forsyth else { 40037da2899SCharles.Forsyth tkcmd(top, tkp+" insert insert {"+s+"}"); 40137da2899SCharles.Forsyth tkcmd(top, tkp+" see "+tkcmd(top, tkp+" index insert")); 40237da2899SCharles.Forsyth } 40337da2899SCharles.Forsyth "go" => 40437da2899SCharles.Forsyth lresults = search(top, filter); 40537da2899SCharles.Forsyth resultstart = 0; 40637da2899SCharles.Forsyth makeresultsframe(top, lresults, 0, maxresults); 40737da2899SCharles.Forsyth selected = nil; 40837da2899SCharles.Forsyth flid = setframe(top, ".fresults", flid); 40937da2899SCharles.Forsyth currmode = RESULTS; 41037da2899SCharles.Forsyth if (chanout != nil) 41137da2899SCharles.Forsyth chanout <-= "search search"; 41237da2899SCharles.Forsyth "prev" => 41337da2899SCharles.Forsyth selected = nil; 41437da2899SCharles.Forsyth resultstart -= maxresults; 41537da2899SCharles.Forsyth if (resultstart < 0) 41637da2899SCharles.Forsyth resultstart = 0; 41737da2899SCharles.Forsyth makeresultsframe(top, lresults, resultstart, maxresults); 41837da2899SCharles.Forsyth flid = setframe(top, ".fresults", flid); 41937da2899SCharles.Forsyth "next" => 42037da2899SCharles.Forsyth selected = nil; 42137da2899SCharles.Forsyth if (resultstart < 0) 42237da2899SCharles.Forsyth resultstart = 0; 42337da2899SCharles.Forsyth resultstart += maxresults; 42437da2899SCharles.Forsyth if (resultstart >= len lresults) 42537da2899SCharles.Forsyth resultstart -= maxresults; 42637da2899SCharles.Forsyth makeresultsframe(top, lresults, resultstart, maxresults); 42737da2899SCharles.Forsyth flid = setframe(top, ".fresults", flid); 42837da2899SCharles.Forsyth "backto" => 42937da2899SCharles.Forsyth flid = setframe(top, ".fsearch", flid); 43037da2899SCharles.Forsyth tkcmd(top, ".f.c see 0 "+tkcmd(top, ".fsearch cget -height")); 43137da2899SCharles.Forsyth currmode = SEARCH; 43237da2899SCharles.Forsyth "new" => 43337da2899SCharles.Forsyth resetsearchscr(top); 43437da2899SCharles.Forsyth tkcmd(top, ".f.c see 0 0"); 43537da2899SCharles.Forsyth setscrollr(top, ".fsearch"); 43637da2899SCharles.Forsyth "select" => 43737da2899SCharles.Forsyth if (selected != nil) 43837da2899SCharles.Forsyth tkcmd(top, selected+" configure -bg white"); 43937da2899SCharles.Forsyth if (selected == hd tl lst) 44037da2899SCharles.Forsyth selected = nil; 44137da2899SCharles.Forsyth else { 44237da2899SCharles.Forsyth selected = hd tl lst; 44337da2899SCharles.Forsyth tkcmd(top, hd tl lst+" configure -bg #5555FF"); 44437da2899SCharles.Forsyth if (chanout != nil) 44537da2899SCharles.Forsyth chanout <-= "search select " + 44637da2899SCharles.Forsyth tkcmd(top, selected+" cget -text") + " " + hd tl tl lst; 44737da2899SCharles.Forsyth } 44837da2899SCharles.Forsyth } 44937da2899SCharles.Forsyth tkcmd(top, "update"); 45037da2899SCharles.Forsyth title := <-top.ctxt.ctl or 45137da2899SCharles.Forsyth title = <-top.wreq or 45237da2899SCharles.Forsyth title = <-titlebar => 45337da2899SCharles.Forsyth if (title == "exit" || title == "ok") 45437da2899SCharles.Forsyth break main; 45537da2899SCharles.Forsyth e := tkclient->wmctl(top, title); 45637da2899SCharles.Forsyth if (e == nil && title[0] == '!') { 45737da2899SCharles.Forsyth (nil, lst) := sys->tokenize(title, " \t\n"); 45837da2899SCharles.Forsyth if (len lst >= 2 && hd lst == "!size" && hd tl lst == ".") { 45937da2899SCharles.Forsyth resize(top, -1,-1); 46037da2899SCharles.Forsyth maxresults = getmaxresults(top); 46137da2899SCharles.Forsyth if (currmode == RESULTS) { 46237da2899SCharles.Forsyth makeresultsframe(top, lresults, resultstart, maxresults); 46337da2899SCharles.Forsyth flid = setframe(top, ".fresults", flid); 46437da2899SCharles.Forsyth tkcmd(top, "update"); 46537da2899SCharles.Forsyth } 46637da2899SCharles.Forsyth } 46737da2899SCharles.Forsyth } 46837da2899SCharles.Forsyth } 46937da2899SCharles.Forsyth } 47037da2899SCharles.Forsyth 47137da2899SCharles.Forsyth} 47237da2899SCharles.Forsyth 47337da2899SCharles.Forsythgetmaxresults(top: ref Tk->Toplevel): int 47437da2899SCharles.Forsyth{ 47537da2899SCharles.Forsyth val := ((int tkcmd(top, ".f.c cget -height")) - 65)/17; 47637da2899SCharles.Forsyth if (val < 1) 47737da2899SCharles.Forsyth return 1; 47837da2899SCharles.Forsyth return val; 47937da2899SCharles.Forsyth} 48037da2899SCharles.Forsyth 48137da2899SCharles.Forsythsetframe(top: ref Tk->Toplevel, f, oldflid: string): string 48237da2899SCharles.Forsyth{ 48337da2899SCharles.Forsyth if (oldflid != nil) 48437da2899SCharles.Forsyth tkcmd(top, ".f.c delete " + oldflid); 48537da2899SCharles.Forsyth newflid := tkcmd(top, ".f.c create window 0 0 -window "+f+" -anchor nw"); 48637da2899SCharles.Forsyth setscrollr(top, f); 48737da2899SCharles.Forsyth return newflid; 48837da2899SCharles.Forsyth} 48937da2899SCharles.Forsyth 49037da2899SCharles.Forsythsetscrollr(top: ref Tk->Toplevel, f: string) 49137da2899SCharles.Forsyth{ 49237da2899SCharles.Forsyth h := tkcmd(top, f+" cget -height"); 49337da2899SCharles.Forsyth w := tkcmd(top, f+" cget -width"); 49437da2899SCharles.Forsyth tkcmd(top, ".f.c configure -scrollregion {0 0 "+w+" "+h+"}"); 49537da2899SCharles.Forsyth} 49637da2899SCharles.Forsyth 49737da2899SCharles.Forsythresize(top: ref Tk->Toplevel, width, height: int) 49837da2899SCharles.Forsyth{ 49937da2899SCharles.Forsyth if (width == -1) { 50037da2899SCharles.Forsyth width = int tkcmd(top, ". cget -width"); 50137da2899SCharles.Forsyth height = int tkcmd(top, ". cget -height"); 50237da2899SCharles.Forsyth } 50337da2899SCharles.Forsyth else 50437da2899SCharles.Forsyth tkcmd(top, sys->sprint(". configure -width %d -height %d", width, height)); 50537da2899SCharles.Forsyth htitle := int tkcmd(top, ".f cget -acty") - int tkcmd(top, ". cget -acty"); 50637da2899SCharles.Forsyth height -= htitle; 50737da2899SCharles.Forsyth ws := int tkcmd(top, ".f.sy cget -width"); 50837da2899SCharles.Forsyth hs := int tkcmd(top, ".f.sx cget -height"); 50937da2899SCharles.Forsyth 51037da2899SCharles.Forsyth tkcmd(top, ".f.c configure -width "+string (width - ws - 8)+ 51137da2899SCharles.Forsyth " -height "+string (height - hs - 8)); 51237da2899SCharles.Forsyth 51337da2899SCharles.Forsyth tkcmd(top, "update"); 51437da2899SCharles.Forsyth} 51537da2899SCharles.Forsyth 51637da2899SCharles.Forsythmakesearchframe(top: ref Tk->Toplevel) 51737da2899SCharles.Forsyth{ 51837da2899SCharles.Forsyth font := " -font /fonts/charon/plain.normal.font"; 51937da2899SCharles.Forsyth fontb := " -font /fonts/charon/bold.normal.font"; 52037da2899SCharles.Forsyth f := ".fsearch"; 52137da2899SCharles.Forsyth 52237da2899SCharles.Forsyth tkcmd(top, "frame "+f+" -bg white"); 52337da2899SCharles.Forsyth tkcmd(top, "label "+f+".l -text {Search for Resource Attributes} -bg white" + fontb); 52437da2899SCharles.Forsyth tkcmd(top, "grid "+f+".l -row 0 -column 0 -columnspan 3 -sticky nw"); 52537da2899SCharles.Forsyth 52637da2899SCharles.Forsyth tkcmd(top, "grid rowconfigure "+f+" 0 -minsize 30"); 52737da2899SCharles.Forsyth tkcmd(top, "frame "+f+".fgo -bg white"); 52837da2899SCharles.Forsyth tkcmd(top, "button "+f+".bs -text {Search} -command {send butchan go} "+font); 52937da2899SCharles.Forsyth tkcmd(top, "button "+f+".bc -text {Clear} -command {send butchan new} "+font); 53037da2899SCharles.Forsyth tkcmd(top, "grid "+f+".bs -row 3 -column 0 -sticky e -padx 2 -pady 5"); 53137da2899SCharles.Forsyth tkcmd(top, "grid "+f+".bc -row 3 -column 1 -sticky w -pady 5"); 53237da2899SCharles.Forsyth 53337da2899SCharles.Forsyth tkcmd(top, "label "+f+".la1 -text {name} -bg white "+fontb); 53437da2899SCharles.Forsyth tkcmd(top, "label "+f+".la2 -text {value} -bg white "+fontb); 53537da2899SCharles.Forsyth 53637da2899SCharles.Forsyth tkcmd(top, "grid "+f+".la1 "+f+".la2 -row 1"); 53737da2899SCharles.Forsyth 53837da2899SCharles.Forsyth insertattribrow(top); 53937da2899SCharles.Forsyth} 54037da2899SCharles.Forsyth 54137da2899SCharles.Forsythinsertattribrow(top: ref Tk->Toplevel) 54237da2899SCharles.Forsyth{ 54337da2899SCharles.Forsyth (n, nil) := sys->tokenize(tkcmd(top, "grid slaves .fsearch -column 1"), " \t\n"); 54437da2899SCharles.Forsyth row := string (n); 54537da2899SCharles.Forsyth sn := string (n - 2); 54637da2899SCharles.Forsyth fsn := ".fsearch.ean"+sn; 54737da2899SCharles.Forsyth fsv := ".fsearch.eav"+sn; 54837da2899SCharles.Forsyth font := " -font /fonts/charon/plain.normal.font"; 54937da2899SCharles.Forsyth tkcmd(top, "entry "+fsn+" -width 170 -borderwidth 0 "+font); 55037da2899SCharles.Forsyth tkcmd(top, "bind "+fsn+" <Key> {send butchan key "+sn+" n %s}"); 55137da2899SCharles.Forsyth tkcmd(top, "entry "+fsv+" -width 170 -borderwidth 0 "+font); 55237da2899SCharles.Forsyth tkcmd(top, "bind "+fsv+" <Key> {send butchan key "+sn+" v %s}"); 55337da2899SCharles.Forsyth tkcmd(top, "grid rowinsert .fsearch "+row); 55437da2899SCharles.Forsyth tkcmd(top, "grid "+fsn+" -column 0 -row "+row+" -sticky w -pady 1 -padx 2"); 55537da2899SCharles.Forsyth tkcmd(top, "grid "+fsv+" -column 1 -row "+row+" -sticky w -pady 1"); 55637da2899SCharles.Forsyth setscrollr(top, ".fsearch"); 55737da2899SCharles.Forsyth} 55837da2899SCharles.Forsyth 55937da2899SCharles.Forsythmin(a,b: int): int 56037da2899SCharles.Forsyth{ 56137da2899SCharles.Forsyth if (a < b) 56237da2899SCharles.Forsyth return a; 56337da2899SCharles.Forsyth return b; 56437da2899SCharles.Forsyth} 56537da2899SCharles.Forsyth 56637da2899SCharles.Forsythmax(a,b: int): int 56737da2899SCharles.Forsyth{ 56837da2899SCharles.Forsyth if (a > b) 56937da2899SCharles.Forsyth return a; 57037da2899SCharles.Forsyth return b; 57137da2899SCharles.Forsyth} 57237da2899SCharles.Forsyth 57337da2899SCharles.Forsythmakeresultsframe(top: ref Tk->Toplevel, lsrv: list of ref Service, resultstart, maxresults: int) 57437da2899SCharles.Forsyth{ 57537da2899SCharles.Forsyth font := " -font /fonts/charon/plain.normal.font"; 57637da2899SCharles.Forsyth fontb := " -font /fonts/charon/bold.normal.font"; 57737da2899SCharles.Forsyth f := ".fresults"; 57837da2899SCharles.Forsyth nresults := len lsrv; 57937da2899SCharles.Forsyth row := 0; 58037da2899SCharles.Forsyth n := 0; 58137da2899SCharles.Forsyth tk->cmd(top, "destroy "+f); 58237da2899SCharles.Forsyth tkcmd(top, "frame "+f+" -bg white"); 58337da2899SCharles.Forsyth title := "Search Results"; 58437da2899SCharles.Forsyth if (nresults > 0) { 58537da2899SCharles.Forsyth from := resultstart+1; 58637da2899SCharles.Forsyth too := min(resultstart+maxresults, nresults); 58737da2899SCharles.Forsyth if (from == too) 58837da2899SCharles.Forsyth title += sys->sprint(" (displaying match %d of %d)", from, nresults); 58937da2899SCharles.Forsyth else 59037da2899SCharles.Forsyth title += sys->sprint(" (displaying matches %d - %d of %d)", from, too, nresults); 59137da2899SCharles.Forsyth } 59237da2899SCharles.Forsyth tkcmd(top, "label "+f+".l -text {"+title+"} -bg white -anchor w" + fontb); 59337da2899SCharles.Forsyth w1 := int tkcmd(top, f+".l cget -width"); 59437da2899SCharles.Forsyth w2 := int tkcmd(top, ".f.c cget -width"); 59537da2899SCharles.Forsyth tkcmd(top, f+".l configure -width "+string max(w1,w2)); 59637da2899SCharles.Forsyth tkcmd(top, "grid "+f+".l -row 0 -column 0 -columnspan 3 -sticky nw"); 59737da2899SCharles.Forsyth 59837da2899SCharles.Forsyth tkcmd(top, "grid rowconfigure "+f+" 0 -minsize 30"); 59937da2899SCharles.Forsyth tkcmd(top, "frame "+f+".f -bg white"); 60037da2899SCharles.Forsyth for (; lsrv != nil; lsrv = tl lsrv) { 60137da2899SCharles.Forsyth if (n >= resultstart && n < resultstart + maxresults) { 60237da2899SCharles.Forsyth srvc := hd lsrv; 60337da2899SCharles.Forsyth (resource, name) := getresname(srvc); 60437da2899SCharles.Forsyth qid := getqid(srvc); 60537da2899SCharles.Forsyth if (qid == nil) 60637da2899SCharles.Forsyth qid = string addqid(srvc); 60737da2899SCharles.Forsyth label := f+".f.lQ"+qid; 60837da2899SCharles.Forsyth tkcmd(top, "label "+label+" -bg white -text {services/"+ 60937da2899SCharles.Forsyth resource+"/"+name+"/}"+font); 61037da2899SCharles.Forsyth tkcmd(top, "grid "+label+" -row "+string row+" -column 0 -sticky w"); 61137da2899SCharles.Forsyth tkcmd(top, "bind "+label+" <Button-1> {send butchan select "+label+" "+qid+"}"); 61237da2899SCharles.Forsyth row++; 61337da2899SCharles.Forsyth } 61437da2899SCharles.Forsyth n++; 61537da2899SCharles.Forsyth } 61637da2899SCharles.Forsyth if (nresults == 0) { 61737da2899SCharles.Forsyth tkcmd(top, "label "+f+".f.l0 -bg white -text {No matches found}"+font); 61837da2899SCharles.Forsyth tkcmd(top, "grid "+f+".f.l0 -row 0 -column 0 -columnspan 3 -sticky w"); 61937da2899SCharles.Forsyth } 62037da2899SCharles.Forsyth else { 62137da2899SCharles.Forsyth tkcmd(top, "button "+f+".bprev -text {<<} "+ 62237da2899SCharles.Forsyth "-command {send butchan prev}"+font); 62337da2899SCharles.Forsyth if (resultstart == 0) 62437da2899SCharles.Forsyth tkcmd(top, f+".bprev configure -state disabled"); 62537da2899SCharles.Forsyth tkcmd(top, "button "+f+".bnext -text {>>} "+ 62637da2899SCharles.Forsyth "-command {send butchan next}"+font); 62737da2899SCharles.Forsyth if (resultstart + maxresults >= nresults) 62837da2899SCharles.Forsyth tkcmd(top, f+".bnext configure -state disabled"); 62937da2899SCharles.Forsyth tkcmd(top, "grid "+f+".bprev -column 0 -row 2 -padx 5 -pady 5"); 63037da2899SCharles.Forsyth tkcmd(top, "grid "+f+".bnext -column 2 -row 2 -padx 5 -pady 5"); 63137da2899SCharles.Forsyth } 63237da2899SCharles.Forsyth tkcmd(top, "grid "+f+".f -row 1 -column 0 -columnspan 3 -sticky nw"); 63337da2899SCharles.Forsyth tkcmd(top, "grid rowconfigure "+f+" 1 -minsize "+string (maxresults*17)); 63437da2899SCharles.Forsyth tkcmd(top, "button "+f+".bsearch -text {Back to Search} "+ 63537da2899SCharles.Forsyth "-command {send butchan backto}"+font); 63637da2899SCharles.Forsyth tkcmd(top, "grid "+f+".bsearch -column 1 -row 2 -padx 5 -pady 5"); 63737da2899SCharles.Forsyth} 63837da2899SCharles.Forsyth 63937da2899SCharles.Forsythfocus(top: ref Tk->Toplevel, newtkp: string) 64037da2899SCharles.Forsyth{ 64137da2899SCharles.Forsyth tkcmd(top, "focus "+newtkp); 64237da2899SCharles.Forsyth x1 := int tkcmd(top, newtkp + " cget -actx") 64337da2899SCharles.Forsyth - int tkcmd(top, ".fsearch cget -actx"); 64437da2899SCharles.Forsyth y1 := int tkcmd(top, newtkp + " cget -acty") 64537da2899SCharles.Forsyth - int tkcmd(top, ".fsearch cget -acty"); 64637da2899SCharles.Forsyth x2 := x1 + int tkcmd(top, newtkp + " cget -width"); 64737da2899SCharles.Forsyth y2 := y1 + int tkcmd(top, newtkp + " cget -height") + 45; 64837da2899SCharles.Forsyth tkcmd(top, sys->sprint(".f.c see %d %d %d %d", x1,y1-30,x2,y2)); 64937da2899SCharles.Forsyth} 65037da2899SCharles.Forsyth 65137da2899SCharles.Forsythsearch(top: ref Tk->Toplevel, filter: list of list of (string, string)): list of ref Service 65237da2899SCharles.Forsyth{ 65337da2899SCharles.Forsyth searchattrib: list of (string, string) = nil; 65437da2899SCharles.Forsyth (n, nil) := sys->tokenize(tkcmd(top, "grid slaves .fsearch -column 0"), " \t\n"); 65537da2899SCharles.Forsyth for (i := 0; i < n - 3; i++) { 65637da2899SCharles.Forsyth attrib := tkcmd(top, ".fsearch.ean"+string i+" get"); 65737da2899SCharles.Forsyth val := tkcmd(top, ".fsearch.eav"+string i+" get"); 65837da2899SCharles.Forsyth if (val == nil) 65937da2899SCharles.Forsyth val = "*"; 66037da2899SCharles.Forsyth if (attrib != nil) 66137da2899SCharles.Forsyth searchattrib = (attrib, val) :: searchattrib; 66237da2899SCharles.Forsyth } 66337da2899SCharles.Forsyth tmp : list of list of (string, string) = nil; 66437da2899SCharles.Forsyth for (; filter != nil; filter = tl filter) { 66537da2899SCharles.Forsyth l := hd filter; 66637da2899SCharles.Forsyth for (tmp2 := searchattrib; tmp2 != nil; tmp2 = tl tmp2) 66737da2899SCharles.Forsyth l = hd tmp2 :: l; 66837da2899SCharles.Forsyth tmp = l :: tmp; 66937da2899SCharles.Forsyth } 67037da2899SCharles.Forsyth filter = tmp; 67137da2899SCharles.Forsyth if (filter == nil) 67237da2899SCharles.Forsyth filter = searchattrib :: nil; 67337da2899SCharles.Forsyth return find(filter); 67437da2899SCharles.Forsyth} 67537da2899SCharles.Forsyth 67637da2899SCharles.Forsythgetitem(l : list of (string, ref Service), testid: string): ref Service 67737da2899SCharles.Forsyth{ 67837da2899SCharles.Forsyth for (; l != nil; l = tl l) { 67937da2899SCharles.Forsyth (id, srvc) := hd l; 68037da2899SCharles.Forsyth if (testid == id) 68137da2899SCharles.Forsyth return srvc; 68237da2899SCharles.Forsyth } 68337da2899SCharles.Forsyth return nil; 68437da2899SCharles.Forsyth} 68537da2899SCharles.Forsyth 68637da2899SCharles.Forsythdelitem(l : list of (string, ref Service), testid: string): list of (string, ref Service) 68737da2899SCharles.Forsyth{ 68837da2899SCharles.Forsyth l2 : list of (string, ref Service) = nil; 68937da2899SCharles.Forsyth for (; l != nil; l = tl l) { 69037da2899SCharles.Forsyth (id, srvc) := hd l; 69137da2899SCharles.Forsyth if (testid != id) 69237da2899SCharles.Forsyth l2 = (id, srvc) :: l2; 69337da2899SCharles.Forsyth } 69437da2899SCharles.Forsyth return l2; 69537da2899SCharles.Forsyth} 69637da2899SCharles.Forsyth 69737da2899SCharles.Forsythresetsearchscr(top: ref Tk->Toplevel) 69837da2899SCharles.Forsyth{ 69937da2899SCharles.Forsyth (n, nil) := sys->tokenize(tkcmd(top, "grid slaves .fsearch -column 1"), " \t\n"); 70037da2899SCharles.Forsyth for (i := 1; i < n - 2; i++) 70137da2899SCharles.Forsyth tkcmd(top, "destroy .fsearch.ean"+string i+" .fsearch.eav"+string i); 70237da2899SCharles.Forsyth s := " delete 0 end"; 70337da2899SCharles.Forsyth tkcmd(top, ".fsearch.ean0"+s); 70437da2899SCharles.Forsyth tkcmd(top, ".fsearch.eav0"+s); 70537da2899SCharles.Forsyth} 70637da2899SCharles.Forsyth 70737da2899SCharles.Forsythtkcmd(top: ref Tk->Toplevel, cmd: string): string 70837da2899SCharles.Forsyth{ 70937da2899SCharles.Forsyth e := tk->cmd(top, cmd); 71037da2899SCharles.Forsyth if (e != "" && e[0] == '!') 71137da2899SCharles.Forsyth sys->print("Tk error: '%s': %s\n",cmd,e); 71237da2899SCharles.Forsyth return e; 71337da2899SCharles.Forsyth} 71437da2899SCharles.Forsyth 71537da2899SCharles.Forsythtkcmds(top: ref Tk->Toplevel, a: array of string) 71637da2899SCharles.Forsyth{ 71737da2899SCharles.Forsyth for (j := 0; j < len a; j++) 71837da2899SCharles.Forsyth tkcmd(top, a[j]); 71937da2899SCharles.Forsyth} 720