xref: /inferno-os/appl/grid/blurdemo.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsythimplement Blurdemo;
2*37da2899SCharles.Forsyth
3*37da2899SCharles.Forsythinclude "sys.m";
4*37da2899SCharles.Forsyth	sys : Sys;
5*37da2899SCharles.Forsythinclude "draw.m";
6*37da2899SCharles.Forsyth	draw: Draw;
7*37da2899SCharles.Forsyth	Display, Rect, Image: import draw;
8*37da2899SCharles.Forsythinclude "tk.m";
9*37da2899SCharles.Forsyth	tk: Tk;
10*37da2899SCharles.Forsythinclude "tkclient.m";
11*37da2899SCharles.Forsyth	tkclient: Tkclient;
12*37da2899SCharles.Forsythinclude "readdir.m";
13*37da2899SCharles.Forsyth	readdir: Readdir;
14*37da2899SCharles.Forsythinclude "sh.m";
15*37da2899SCharles.Forsythinclude "registries.m";
16*37da2899SCharles.Forsyth	registries: Registries;
17*37da2899SCharles.Forsyth	Registry, Attributes, Service: import registries;
18*37da2899SCharles.Forsythinclude "grid/pathreader.m";
19*37da2899SCharles.Forsyth	reader: PathReader;
20*37da2899SCharles.Forsythinclude "grid/browser.m";
21*37da2899SCharles.Forsyth	browser: Browser;
22*37da2899SCharles.Forsyth	Browse, Select, File, Parameter,
23*37da2899SCharles.Forsyth	DESELECT, SELECT, TOGGLE: import browser;
24*37da2899SCharles.Forsythinclude "grid/srvbrowse.m";
25*37da2899SCharles.Forsyth	srvbrowse: Srvbrowse;
26*37da2899SCharles.Forsythinclude "grid/announce.m";
27*37da2899SCharles.Forsyth	announce: Announce;
28*37da2899SCharles.Forsythinclude "grid/readjpg.m";
29*37da2899SCharles.Forsyth	readjpg: Readjpg;
30*37da2899SCharles.Forsyth
31*37da2899SCharles.Forsythsrvfilter: list of list of (string, string);
32*37da2899SCharles.Forsythcurrstep: int;
33*37da2899SCharles.Forsyth
34*37da2899SCharles.Forsythcurrsrv: ref Service;
35*37da2899SCharles.Forsythcurrattach: ref Registries->Attached;
36*37da2899SCharles.Forsythctxt: ref Draw->Context;
37*37da2899SCharles.Forsythdisplay: ref Draw->Display;
38*37da2899SCharles.Forsythsysname : string;
39*37da2899SCharles.Forsyth
40*37da2899SCharles.ForsythIMAGE: con 0;
41*37da2899SCharles.ForsythMOUNT: con 4;
42*37da2899SCharles.Forsyth
43*37da2899SCharles.Forsythimgcache: ref Image;
44*37da2899SCharles.Forsythbr: ref Browse;
45*37da2899SCharles.Forsythsel: ref Select;
46*37da2899SCharles.Forsyth
47*37da2899SCharles.ForsythBlurdemo : module {
48*37da2899SCharles.Forsyth	init : fn (context : ref Draw->Context, argv : list of string);
49*37da2899SCharles.Forsyth	readpath: fn (dir: File): (array of ref sys->Dir, int);
50*37da2899SCharles.Forsyth};
51*37da2899SCharles.Forsyth
52*37da2899SCharles.Forsythinit(context : ref Draw->Context, argv: list of string)
53*37da2899SCharles.Forsyth{
54*37da2899SCharles.Forsyth	ctxt = context;
55*37da2899SCharles.Forsyth	display = ctxt.display;
56*37da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
57*37da2899SCharles.Forsyth	if (sys == nil)
58*37da2899SCharles.Forsyth		badmod(Sys->PATH);
59*37da2899SCharles.Forsyth	readdir = load Readdir Readdir->PATH;
60*37da2899SCharles.Forsyth	if (readdir == nil)
61*37da2899SCharles.Forsyth		badmod(Readdir->PATH);
62*37da2899SCharles.Forsyth	draw = load Draw Draw->PATH;
63*37da2899SCharles.Forsyth	if (draw == nil)
64*37da2899SCharles.Forsyth		badmod(Draw->PATH);
65*37da2899SCharles.Forsyth	tk = load Tk Tk->PATH;
66*37da2899SCharles.Forsyth	if (tk == nil)
67*37da2899SCharles.Forsyth		badmod(Tk->PATH);
68*37da2899SCharles.Forsyth	tkclient = load Tkclient Tkclient->PATH;
69*37da2899SCharles.Forsyth	if (tkclient == nil)
70*37da2899SCharles.Forsyth		badmod(Tkclient->PATH);
71*37da2899SCharles.Forsyth	tkclient->init();
72*37da2899SCharles.Forsyth	registries = load Registries Registries->PATH;
73*37da2899SCharles.Forsyth	if (registries == nil)
74*37da2899SCharles.Forsyth		badmod(Registries->PATH);
75*37da2899SCharles.Forsyth	registries->init();
76*37da2899SCharles.Forsyth	browser = load Browser Browser->PATH;
77*37da2899SCharles.Forsyth	if (browser == nil)
78*37da2899SCharles.Forsyth		badmod(Browser->PATH);
79*37da2899SCharles.Forsyth	browser->init();
80*37da2899SCharles.Forsyth	srvbrowse = load Srvbrowse Srvbrowse->PATH;
81*37da2899SCharles.Forsyth	if (srvbrowse == nil)
82*37da2899SCharles.Forsyth		badmod(Srvbrowse->PATH);
83*37da2899SCharles.Forsyth	srvbrowse->init();
84*37da2899SCharles.Forsyth	announce = load Announce Announce->PATH;
85*37da2899SCharles.Forsyth	if (announce == nil)
86*37da2899SCharles.Forsyth		badmod(Announce->PATH);
87*37da2899SCharles.Forsyth	announce->init();
88*37da2899SCharles.Forsyth	reader = load PathReader "$self";
89*37da2899SCharles.Forsyth	if (reader == nil)
90*37da2899SCharles.Forsyth		badmod("PathReader");
91*37da2899SCharles.Forsyth	readjpg = load Readjpg Readjpg->PATH;
92*37da2899SCharles.Forsyth	if (readjpg == nil)
93*37da2899SCharles.Forsyth		badmod(Readjpg->PATH);
94*37da2899SCharles.Forsyth	readjpg->init(display);
95*37da2899SCharles.Forsyth	sys->pctl(sys->FORKNS | sys->NEWPGRP, nil);
96*37da2899SCharles.Forsyth	if (ctxt == nil) {
97*37da2899SCharles.Forsyth		sys->print("no draw context found!\n");
98*37da2899SCharles.Forsyth		exit;
99*37da2899SCharles.Forsyth	}
100*37da2899SCharles.Forsyth	sysname = readfile("/dev/sysname");
101*37da2899SCharles.Forsyth	if (sysname == "")
102*37da2899SCharles.Forsyth		sysname = "Localhost";
103*37da2899SCharles.Forsyth	imgcache = nil;
104*37da2899SCharles.Forsyth	setsrvfilter();
105*37da2899SCharles.Forsyth	root := "/";
106*37da2899SCharles.Forsyth	currsrv = nil;
107*37da2899SCharles.Forsyth
108*37da2899SCharles.Forsyth	attribs := ("resource", "Cpu Pool") :: nil;
109*37da2899SCharles.Forsyth	lcpupool := srvbrowse->find(attribs :: nil);
110*37da2899SCharles.Forsyth	if (lcpupool == nil) {
111*37da2899SCharles.Forsyth		browser->dialog(ctxt, nil, "ok" :: nil, "Alert","Cannot find a Cpu Pool Resource");
112*37da2899SCharles.Forsyth		raise "fail: error cannot find a Cpu Pool resource";
113*37da2899SCharles.Forsyth	}
114*37da2899SCharles.Forsyth
115*37da2899SCharles.Forsyth	(top, titlebar) := tkclient->toplevel(ctxt,"","BlurDemo", tkclient->Appl);
116*37da2899SCharles.Forsyth	butchan := chan of string;
117*37da2899SCharles.Forsyth	tk->namechan(top, butchan, "butchan");
118*37da2899SCharles.Forsyth	browsechan := chan of string;
119*37da2899SCharles.Forsyth	tk->namechan(top, browsechan, "browsechan");
120*37da2899SCharles.Forsyth	selectchan := chan of string;
121*37da2899SCharles.Forsyth	tk->namechan(top, selectchan, "selectchan");
122*37da2899SCharles.Forsyth	br = Browse.new(top, "browsechan", "services/", "Services", 1, reader);
123*37da2899SCharles.Forsyth	bropened := array[] of {
124*37da2899SCharles.Forsyth		"services/",
125*37da2899SCharles.Forsyth		"services/Data source/",
126*37da2899SCharles.Forsyth		"services/Camera/",
127*37da2899SCharles.Forsyth		"/n/remote/",
128*37da2899SCharles.Forsyth		"/" ,
129*37da2899SCharles.Forsyth	};
130*37da2899SCharles.Forsyth	for (i := 0; i < len bropened; i++)
131*37da2899SCharles.Forsyth		br.addopened(File (bropened[i], nil), 1);
132*37da2899SCharles.Forsyth
133*37da2899SCharles.Forsyth	sel = Select.new(top, "selectchan");
134*37da2899SCharles.Forsyth
135*37da2899SCharles.Forsyth	for (ik := 0; ik < len mainscreen; ik++)
136*37da2899SCharles.Forsyth		tkcmd(top,mainscreen[ik]);
137*37da2899SCharles.Forsyth
138*37da2899SCharles.Forsyth	currstep = -1;
139*37da2899SCharles.Forsyth
140*37da2899SCharles.Forsyth	sel.addframe("image", "Select a '.bit' image");
141*37da2899SCharles.Forsyth
142*37da2899SCharles.Forsyth	changestep(top, IMAGE, nil);
143*37da2899SCharles.Forsyth
144*37da2899SCharles.Forsyth	tkcmd(top, "pack .f -fill both -expand 1; pack propagate . 0");
145*37da2899SCharles.Forsyth	released := 1;
146*37da2899SCharles.Forsyth	title := "";
147*37da2899SCharles.Forsyth	resize(top, ref Rect ((0,0), (400,400)));
148*37da2899SCharles.Forsyth	tkclient->onscreen(top, nil);
149*37da2899SCharles.Forsyth	tkclient->startinput(top, "kbd"::"ptr"::nil);
150*37da2899SCharles.Forsyth	tkpath: string;
151*37da2899SCharles.Forsyth	selected := array[2] of File;
152*37da2899SCharles.Forsyth	if (tl argv != nil)
153*37da2899SCharles.Forsyth		spawn initimg(butchan, hd tl argv);
154*37da2899SCharles.Forsyth
155*37da2899SCharles.Forsyth	main: for (;;) {
156*37da2899SCharles.Forsyth		alt {
157*37da2899SCharles.Forsyth		s := <-top.ctxt.kbd =>
158*37da2899SCharles.Forsyth			tk->keyboard(top, s);
159*37da2899SCharles.Forsyth		s := <-top.ctxt.ptr =>
160*37da2899SCharles.Forsyth			tk->pointer(top, *s);
161*37da2899SCharles.Forsyth		inp := <-browsechan =>
162*37da2899SCharles.Forsyth			(nil, lst) := sys->tokenize(inp, " \n\t");
163*37da2899SCharles.Forsyth			if (len lst > 1)
164*37da2899SCharles.Forsyth				tkpath = hd tl lst;
165*37da2899SCharles.Forsyth			selected[0] = br.getselected(0);
166*37da2899SCharles.Forsyth			selected[1] = br.getselected(1);
167*37da2899SCharles.Forsyth			br.defaultaction(lst, nil);
168*37da2899SCharles.Forsyth			i = -1;
169*37da2899SCharles.Forsyth			if (!File.eq(selected[0], br.getselected(0)))
170*37da2899SCharles.Forsyth				i = 0;
171*37da2899SCharles.Forsyth			if (!File.eq(selected[1], br.getselected(1)))
172*37da2899SCharles.Forsyth				i = 1;
173*37da2899SCharles.Forsyth			if (i != -1) {
174*37da2899SCharles.Forsyth				sel.select(sel.currfname,nil,DESELECT);
175*37da2899SCharles.Forsyth				actionbutton(top, br.selected[i].file.path, br.selected[i].tkpath);
176*37da2899SCharles.Forsyth			}
177*37da2899SCharles.Forsyth			tkcmd(top, "update");
178*37da2899SCharles.Forsyth		inp := <-selectchan =>
179*37da2899SCharles.Forsyth			(nil, lst) := sys->tokenize(inp, " \n\t");
180*37da2899SCharles.Forsyth			case hd lst {
181*37da2899SCharles.Forsyth				"but3" =>
182*37da2899SCharles.Forsyth					tkpath = hd tl lst;
183*37da2899SCharles.Forsyth					x := string (int hd tl tl lst - 5);
184*37da2899SCharles.Forsyth					y := string (int hd tl tl tl lst - 5);
185*37da2899SCharles.Forsyth
186*37da2899SCharles.Forsyth					path := tkcmd(top, tkpath+" cget -text");
187*37da2899SCharles.Forsyth					s := blursrvc.attrs.get("name") + " ("+blursrvc.addr+")";
188*37da2899SCharles.Forsyth					tk->cmd(top, "destroy .m2");
189*37da2899SCharles.Forsyth					tkcmd(top, "menu .m2 -font /fonts/charon/plain.normal.font");
190*37da2899SCharles.Forsyth					tkcmd(top, ".m2 add command -label {"+path+"}");
191*37da2899SCharles.Forsyth					tkcmd(top, ".m2 add separator");
192*37da2899SCharles.Forsyth					tkcmd(top, ".m2 add command -label {"+s+"}");
193*37da2899SCharles.Forsyth					tkcmd(top, ".m2 post "+x+" "+y);
194*37da2899SCharles.Forsyth				"double1" =>
195*37da2899SCharles.Forsyth					tkpath = hd tl lst;
196*37da2899SCharles.Forsyth					path := tkcmd(top, tkpath+" cget -text");
197*37da2899SCharles.Forsyth					qid := "";
198*37da2899SCharles.Forsyth					(n, nil) := sys->tokenize(path, "/");
199*37da2899SCharles.Forsyth					if (currstep == IMAGE) {
200*37da2899SCharles.Forsyth						qid = srvbrowse->getqid(blursrvc);
201*37da2899SCharles.Forsyth						(res,name) := srvbrowse->getresname(blursrvc);
202*37da2899SCharles.Forsyth						path = "services/"+res+"/"+name+"/";
203*37da2899SCharles.Forsyth					}
204*37da2899SCharles.Forsyth					else if (currsrv.addr != blursrvc.addr)
205*37da2899SCharles.Forsyth						break;
206*37da2899SCharles.Forsyth					else if (blursrvc.addr != "Local Machine")
207*37da2899SCharles.Forsyth						path = "/n/remote" + path;
208*37da2899SCharles.Forsyth					tkpath = br.gotoselectfile(File(path,qid));
209*37da2899SCharles.Forsyth					if (tkpath != nil) {
210*37da2899SCharles.Forsyth						sel.select(sel.currfname, nil, DESELECT);
211*37da2899SCharles.Forsyth						actionbutton(top, path, tkpath);
212*37da2899SCharles.Forsyth					}
213*37da2899SCharles.Forsyth				"but1" =>
214*37da2899SCharles.Forsyth					if (currstep == IMAGE)
215*37da2899SCharles.Forsyth						br.selectfile(0, DESELECT, File (nil, nil), nil);
216*37da2899SCharles.Forsyth					else
217*37da2899SCharles.Forsyth						br.selectfile(1, DESELECT, File (nil, nil), nil);
218*37da2899SCharles.Forsyth					sel.defaultaction(lst);
219*37da2899SCharles.Forsyth					actionbutton(top, sel.getselected(sel.currfname), hd tl lst);
220*37da2899SCharles.Forsyth				* =>
221*37da2899SCharles.Forsyth					sel.defaultaction(lst);
222*37da2899SCharles.Forsyth			}
223*37da2899SCharles.Forsyth			tkcmd(top, "update");
224*37da2899SCharles.Forsyth		inp := <-butchan =>
225*37da2899SCharles.Forsyth			# sys->print("inp: %s\n",inp);
226*37da2899SCharles.Forsyth			(nil, lst) := sys->tokenize(inp, " \n\t");
227*37da2899SCharles.Forsyth			if (len lst > 1)
228*37da2899SCharles.Forsyth				tkpath = hd tl lst;
229*37da2899SCharles.Forsyth			case hd lst {
230*37da2899SCharles.Forsyth				"refresh" =>
231*37da2899SCharles.Forsyth					# ! check to see if anything is mounted first
232*37da2899SCharles.Forsyth					if (currstep == IMAGE) {
233*37da2899SCharles.Forsyth						# addlocalservice();
234*37da2899SCharles.Forsyth						srvbrowse->refreshservices(srvfilter);
235*37da2899SCharles.Forsyth					}
236*37da2899SCharles.Forsyth					br.refresh();
237*37da2899SCharles.Forsyth				"back" =>
238*37da2899SCharles.Forsyth					changestep(top, IMAGE, nil);
239*37da2899SCharles.Forsyth				"run" =>
240*37da2899SCharles.Forsyth					spawn run(ctxt, getcoords(top));
241*37da2899SCharles.Forsyth				"preview" =>
242*37da2899SCharles.Forsyth					spawn previewwin(top, butchan, hd tl lst);
243*37da2899SCharles.Forsyth				"add" =>
244*37da2899SCharles.Forsyth					additem(top, hd tl lst, int hd tl tl lst);
245*37da2899SCharles.Forsyth				"del" =>
246*37da2899SCharles.Forsyth					sel.delselection("image", hd tl lst);
247*37da2899SCharles.Forsyth					tkcmd (top, ".f.ftop.bn configure -state disabled");
248*37da2899SCharles.Forsyth					blurimage = nil;
249*37da2899SCharles.Forsyth					blurtkpath = nil;
250*37da2899SCharles.Forsyth					blursrvc = nil;
251*37da2899SCharles.Forsyth					actionbutton(top, sel.getselected(sel.currfname), hd tl lst);
252*37da2899SCharles.Forsyth				"mount" =>
253*37da2899SCharles.Forsyth					file := br.getpath(tkpath);
254*37da2899SCharles.Forsyth					(nsrv, lsrv) := sys->tokenize(file.path, "/");
255*37da2899SCharles.Forsyth					if (currstep != IMAGE)
256*37da2899SCharles.Forsyth						break;
257*37da2899SCharles.Forsyth					if (nsrv != 3)
258*37da2899SCharles.Forsyth						break;
259*37da2899SCharles.Forsyth					if (hd tl tl lsrv != "Local Filestore") {
260*37da2899SCharles.Forsyth						ok := mountsrv(file.path, file.qid, getcoords(top));
261*37da2899SCharles.Forsyth						if (!ok)
262*37da2899SCharles.Forsyth							break;
263*37da2899SCharles.Forsyth						changestep(top, MOUNT, hd tl tl lsrv);
264*37da2899SCharles.Forsyth					}
265*37da2899SCharles.Forsyth					else {
266*37da2899SCharles.Forsyth						srv : Service;
267*37da2899SCharles.Forsyth						srv.attrs = Attributes.new(("name", sysname) :: nil);
268*37da2899SCharles.Forsyth						srv.addr = "Local Machine";
269*37da2899SCharles.Forsyth						currsrv = ref srv;
270*37da2899SCharles.Forsyth						changestep(top, MOUNT, hd tl tl lsrv);
271*37da2899SCharles.Forsyth					}
272*37da2899SCharles.Forsyth			}
273*37da2899SCharles.Forsyth			tkcmd(top, "update");
274*37da2899SCharles.Forsyth
275*37da2899SCharles.Forsyth		title = <-top.ctxt.ctl or
276*37da2899SCharles.Forsyth		title = <-top.wreq or
277*37da2899SCharles.Forsyth		title = <-titlebar =>
278*37da2899SCharles.Forsyth			if (title == "exit")
279*37da2899SCharles.Forsyth				break main;
280*37da2899SCharles.Forsyth			e := tkclient->wmctl(top, title);
281*37da2899SCharles.Forsyth			if (e == nil && title[0] == '!') {
282*37da2899SCharles.Forsyth				(nil, lst) := sys->tokenize(title, " \t\n");
283*37da2899SCharles.Forsyth				if (len lst >= 2 && hd lst == "!size" && hd tl lst == ".")
284*37da2899SCharles.Forsyth					resize(top, nil);
285*37da2899SCharles.Forsyth			}
286*37da2899SCharles.Forsyth		}
287*37da2899SCharles.Forsyth	}
288*37da2899SCharles.Forsyth	currattach = nil;
289*37da2899SCharles.Forsyth	killg(sys->pctl(0,nil));
290*37da2899SCharles.Forsyth}
291*37da2899SCharles.Forsyth
292*37da2899SCharles.Forsythresize(top: ref Tk->Toplevel, r: ref Draw->Rect)
293*37da2899SCharles.Forsyth{
294*37da2899SCharles.Forsyth	if (r != nil) {
295*37da2899SCharles.Forsyth		sw := (*r).dx();
296*37da2899SCharles.Forsyth		sh := (*r).dy();
297*37da2899SCharles.Forsyth		ww := int tkcmd(top, ". cget -actwidth");
298*37da2899SCharles.Forsyth		wh := int tkcmd(top, ". cget -actheight");
299*37da2899SCharles.Forsyth		if (ww > sw)
300*37da2899SCharles.Forsyth			tkcmd(top, ". configure -x 0 -width "+string sw);
301*37da2899SCharles.Forsyth		if (wh > sh)
302*37da2899SCharles.Forsyth			tkcmd(top, ". configure -y 0 -height "+string sh);
303*37da2899SCharles.Forsyth	}
304*37da2899SCharles.Forsyth	w := int tkcmd(top, ".fselect cget -actwidth");
305*37da2899SCharles.Forsyth	h := int tkcmd(top, ".fselect cget -actheight");
306*37da2899SCharles.Forsyth	sel.resize(w,h);
307*37da2899SCharles.Forsyth}
308*37da2899SCharles.Forsyth
309*37da2899SCharles.Forsythnactionbuttons := 0;
310*37da2899SCharles.Forsythactionbutton(top: ref Tk->Toplevel, path, tkpath: string)
311*37da2899SCharles.Forsyth{
312*37da2899SCharles.Forsyth	for (i := 0; i < nactionbuttons; i++) {
313*37da2899SCharles.Forsyth		tkcmd(top, "grid forget .f.ftop.baction"+string i);
314*37da2899SCharles.Forsyth		tkcmd(top, "destroy .f.ftop.baction"+string i);
315*37da2899SCharles.Forsyth	}
316*37da2899SCharles.Forsyth	if (path == nil) {
317*37da2899SCharles.Forsyth		nactionbuttons = 0;
318*37da2899SCharles.Forsyth		return;
319*37da2899SCharles.Forsyth	}
320*37da2899SCharles.Forsyth	buttons : list of (string,string) = nil;
321*37da2899SCharles.Forsyth	(n, nil) := sys->tokenize(path, "/");
322*37da2899SCharles.Forsyth	if (len tkpath > 8 && tkpath[:8] == ".fselect")
323*37da2899SCharles.Forsyth		buttons = ("Remove", "del "+tkpath) :: buttons;
324*37da2899SCharles.Forsyth	else {
325*37da2899SCharles.Forsyth		if (currstep == IMAGE) {
326*37da2899SCharles.Forsyth			if (n == 3)
327*37da2899SCharles.Forsyth				buttons = ("Mount", "mount "+tkpath) :: buttons;
328*37da2899SCharles.Forsyth		}
329*37da2899SCharles.Forsyth		else {
330*37da2899SCharles.Forsyth			if (len path > 4) {
331*37da2899SCharles.Forsyth				if (path[len path - 4:] == ".bit") {
332*37da2899SCharles.Forsyth					buttons = ("Select", "add "+path+" 0") ::
333*37da2899SCharles.Forsyth							("Preview", "preview "+path) :: buttons;
334*37da2899SCharles.Forsyth				}
335*37da2899SCharles.Forsyth				else if (path[len path - 4:] == ".jpg")
336*37da2899SCharles.Forsyth					buttons = ("Select", "add "+path+" 0") :: buttons;
337*37da2899SCharles.Forsyth			}
338*37da2899SCharles.Forsyth		}
339*37da2899SCharles.Forsyth	}
340*37da2899SCharles.Forsyth	nactionbuttons = len buttons;
341*37da2899SCharles.Forsyth	for (i = 0; i < nactionbuttons; i++) {
342*37da2899SCharles.Forsyth		name := ".f.ftop.baction"+string i+" ";
343*37da2899SCharles.Forsyth		(text,cmd) := hd buttons;
344*37da2899SCharles.Forsyth		tkcmd(top, "button "+name+"-text {"+text+"} "+
345*37da2899SCharles.Forsyth				"-font /fonts/charon/bold.normal.font "+
346*37da2899SCharles.Forsyth				"-command {send butchan "+cmd+"}");
347*37da2899SCharles.Forsyth		tkcmd(top, "grid "+name+" -row 0 -column "+string (4+i));
348*37da2899SCharles.Forsyth		buttons = tl buttons;
349*37da2899SCharles.Forsyth	}
350*37da2899SCharles.Forsyth}
351*37da2899SCharles.Forsyth
352*37da2899SCharles.Forsythinitimg(butchan: chan of string, imgpath: string)
353*37da2899SCharles.Forsyth{
354*37da2899SCharles.Forsyth	srv : Service;
355*37da2899SCharles.Forsyth	srv.attrs = Attributes.new(("name", sysname) :: nil);
356*37da2899SCharles.Forsyth	srv.addr = "Local Machine";
357*37da2899SCharles.Forsyth	currsrv = ref srv;
358*37da2899SCharles.Forsyth	butchan <-= "add "+imgpath+" 0";
359*37da2899SCharles.Forsyth	butchan <-= "back";
360*37da2899SCharles.Forsyth}
361*37da2899SCharles.Forsyth
362*37da2899SCharles.Forsythblurimage := "";
363*37da2899SCharles.Forsythblurtkpath := "";
364*37da2899SCharles.Forsythblursrvc: ref Service;
365*37da2899SCharles.Forsyth
366*37da2899SCharles.Forsythadditem(top: ref Tk->Toplevel, path: string, overwrite: int)
367*37da2899SCharles.Forsyth{
368*37da2899SCharles.Forsyth	if (blurimage != nil) {
369*37da2899SCharles.Forsyth		if (overwrite || browser->dialog(ctxt, top, "ok" :: "cancel" :: nil,
370*37da2899SCharles.Forsyth			"Alert","Replace existing image '"
371*37da2899SCharles.Forsyth			+nopath(blurimage)+"' with '"+nopath(path)+"'?") == 0) {
372*37da2899SCharles.Forsyth			sel.delselection("image", blurtkpath);
373*37da2899SCharles.Forsyth		}
374*37da2899SCharles.Forsyth		else
375*37da2899SCharles.Forsyth			return;
376*37da2899SCharles.Forsyth	}
377*37da2899SCharles.Forsyth	imgpath := path;
378*37da2899SCharles.Forsyth	if (currsrv.addr != "Local Machine")
379*37da2899SCharles.Forsyth		path = path[len "/n/remote":];
380*37da2899SCharles.Forsyth	blurtkpath = sel.addselection("image", path, nil, 0);
381*37da2899SCharles.Forsyth	tkcmd(top, "update");
382*37da2899SCharles.Forsyth	blurimage = path;
383*37da2899SCharles.Forsyth	blursrvc = currsrv;
384*37da2899SCharles.Forsyth	if (overwrite)
385*37da2899SCharles.Forsyth		spawn getpreview(blurtkpath, nil, imgcache);
386*37da2899SCharles.Forsyth	else
387*37da2899SCharles.Forsyth		spawn getpreview(blurtkpath, imgpath, nil);
388*37da2899SCharles.Forsyth}
389*37da2899SCharles.Forsyth
390*37da2899SCharles.Forsythnopath(file: string): string
391*37da2899SCharles.Forsyth{
392*37da2899SCharles.Forsyth	return file[len browser->prevpath(file):];
393*37da2899SCharles.Forsyth}
394*37da2899SCharles.Forsyth
395*37da2899SCharles.Forsythrunscr := array[] of {
396*37da2899SCharles.Forsyth	"frame .f",
397*37da2899SCharles.Forsyth	"frame .f.f1",
398*37da2899SCharles.Forsyth	"label .f.f1.l -text {Select no of CPUs} -font /fonts/charon/plain.normal.font",
399*37da2899SCharles.Forsyth	"scale .f.f1.s -orient horizontal -height 16 -showvalue 0 -from 1 -to 20 -command {.f.f1.ls configure -text}",
400*37da2899SCharles.Forsyth	"label .f.f1.ls -text {1} -font /fonts/charon/plain.normal.font -width 30",
401*37da2899SCharles.Forsyth	"button .f.f1.b -text {Run} -font /fonts/charon/plain.normal.font -command {send butchan go}",
402*37da2899SCharles.Forsyth	"pack .f.f1.l .f.f1.s .f.f1.ls .f.f1.b -side left",
403*37da2899SCharles.Forsyth	"frame .f.f2",
404*37da2899SCharles.Forsyth	"text .f.f2.t -width 250 -height 150 -borderwidth 1 -bg white -font /fonts/charon/plain.normal.font -yscrollcommand { .f.f2.sy set }",
405*37da2899SCharles.Forsyth	"scrollbar .f.f2.sy -command { .f.f2.t yview }",
406*37da2899SCharles.Forsyth	"pack .f.f2.sy -side left -fill y",
407*37da2899SCharles.Forsyth	"pack .f.f2.t -fill both -expand 1",
408*37da2899SCharles.Forsyth	"bind .Wm_t <Button-1> +{focus .Wm_t}",
409*37da2899SCharles.Forsyth	"bind .Wm_t.title <Button-1> +{focus .Wm_t}",
410*37da2899SCharles.Forsyth	"focus .Wm_t",
411*37da2899SCharles.Forsyth	"pack .f.f1 -side top",
412*37da2899SCharles.Forsyth	"pack .f.f2 -fill both -expand 1",
413*37da2899SCharles.Forsyth};
414*37da2899SCharles.Forsyth
415*37da2899SCharles.Forsythrun(ctxt: ref Draw->Context, coords: draw->Rect)
416*37da2899SCharles.Forsyth{
417*37da2899SCharles.Forsyth	(top, titlectl) := tkclient->toplevel(ctxt, "", nil, tkclient->Resize);
418*37da2899SCharles.Forsyth	butchan := chan of string;
419*37da2899SCharles.Forsyth	sync := chan of int;
420*37da2899SCharles.Forsyth	quit := chan of int;
421*37da2899SCharles.Forsyth	tk->namechan(top, butchan, "butchan");
422*37da2899SCharles.Forsyth	tkcmds(top, runscr);
423*37da2899SCharles.Forsyth	tkcmd(top, ". configure "+getcentre(top, coords));
424*37da2899SCharles.Forsyth	tkcmd(top, "pack .f -fill both -expand 1; pack propagate . 0; focus .; update");
425*37da2899SCharles.Forsyth	tkclient->onscreen(top, "exact");
426*37da2899SCharles.Forsyth	tkclient->startinput(top, "kbd"::"ptr"::nil);
427*37da2899SCharles.Forsyth	done := 1;
428*37da2899SCharles.Forsyth	loop: for (;;) {
429*37da2899SCharles.Forsyth		alt {
430*37da2899SCharles.Forsyth		s := <-top.ctxt.kbd =>
431*37da2899SCharles.Forsyth			tk->keyboard(top, s);
432*37da2899SCharles.Forsyth		s := <-top.ctxt.ptr =>
433*37da2899SCharles.Forsyth			tk->pointer(top, *s);
434*37da2899SCharles.Forsyth		<-sync =>
435*37da2899SCharles.Forsyth			tkcmd(top, ".f.f1.b configure -state normal; update");
436*37da2899SCharles.Forsyth			done = 1;
437*37da2899SCharles.Forsyth		inp := <-butchan =>
438*37da2899SCharles.Forsyth			(nil, lst) := sys->tokenize(inp, " \n\t");
439*37da2899SCharles.Forsyth			case hd lst {
440*37da2899SCharles.Forsyth				"go" =>
441*37da2899SCharles.Forsyth					tkcmd(top, ".f.f1.b configure -state disabled");
442*37da2899SCharles.Forsyth					ncpus := int tkcmd(top, ".f.f1.s get");
443*37da2899SCharles.Forsyth					done = 0;
444*37da2899SCharles.Forsyth					spawn startit(ncpus, butchan, sync, quit);
445*37da2899SCharles.Forsyth				"output" =>
446*37da2899SCharles.Forsyth					tkcmd(top, ".f.f2.t insert end {"+inp[len "output ":]+"}");
447*37da2899SCharles.Forsyth				"error" =>
448*37da2899SCharles.Forsyth					tkcmd(top, ".f.f2.t insert end {Error: "+inp[len "error ":]+"\n}");
449*37da2899SCharles.Forsyth					tkcmd(top, ".f.f1.b configure -state normal");
450*37da2899SCharles.Forsyth				"fewcpu" =>
451*37da2899SCharles.Forsyth					i := browser->dialog(ctxt, top, "ok" :: "cancel" :: nil, "Alert",
452*37da2899SCharles.Forsyth							"Only found "+hd tl lst+" cpus available. Continue?");
453*37da2899SCharles.Forsyth					quit <-= i;
454*37da2899SCharles.Forsyth					if (i == 1)
455*37da2899SCharles.Forsyth						return;
456*37da2899SCharles.Forsyth			}
457*37da2899SCharles.Forsyth			tkcmd(top, "update");
458*37da2899SCharles.Forsyth		s := <-top.ctxt.ctl or
459*37da2899SCharles.Forsyth		s = <-top.wreq or
460*37da2899SCharles.Forsyth		s = <- titlectl =>
461*37da2899SCharles.Forsyth			if (s == "exit") {
462*37da2899SCharles.Forsyth				if (done)
463*37da2899SCharles.Forsyth					return;
464*37da2899SCharles.Forsyth				break loop;
465*37da2899SCharles.Forsyth			}
466*37da2899SCharles.Forsyth			else
467*37da2899SCharles.Forsyth				tkclient->wmctl(top, s);
468*37da2899SCharles.Forsyth		}
469*37da2899SCharles.Forsyth	}
470*37da2899SCharles.Forsyth	top = nil;
471*37da2899SCharles.Forsyth	for (;;) alt {
472*37da2899SCharles.Forsyth		<- butchan =>
473*37da2899SCharles.Forsyth			;
474*37da2899SCharles.Forsyth		<-sync =>
475*37da2899SCharles.Forsyth			return;
476*37da2899SCharles.Forsyth	}
477*37da2899SCharles.Forsyth}
478*37da2899SCharles.Forsyth
479*37da2899SCharles.Forsythstartit(ncpus: int, butchan: chan of string, sync, quit: chan of int)
480*37da2899SCharles.Forsyth{
481*37da2899SCharles.Forsyth	imgattached : ref Registries->Attached;
482*37da2899SCharles.Forsyth	imgpath := blurimage;
483*37da2899SCharles.Forsyth	if (blursrvc.addr != "Local Machine") {
484*37da2899SCharles.Forsyth		imgattached = blursrvc.attach(nil, nil);
485*37da2899SCharles.Forsyth		if (imgattached == nil) {
486*37da2899SCharles.Forsyth			butchan <-= "error cannot connect to data source: "+blursrvc.attrs.get("name");
487*37da2899SCharles.Forsyth			return;
488*37da2899SCharles.Forsyth		}
489*37da2899SCharles.Forsyth		if (sys->mount(imgattached.fd, nil, "/n/local", sys->MREPL, nil) == -1) {
490*37da2899SCharles.Forsyth			butchan <-= sys->sprint("error img mount failed: %r");
491*37da2899SCharles.Forsyth			return;
492*37da2899SCharles.Forsyth		}
493*37da2899SCharles.Forsyth		imgpath = "/n/local" + imgpath;
494*37da2899SCharles.Forsyth		butchan <-= "output Found image namespace\n";
495*37da2899SCharles.Forsyth	}
496*37da2899SCharles.Forsyth	sys->pctl(sys->FORKNS, nil);
497*37da2899SCharles.Forsyth	attribs := ("resource", "Cpu Pool") :: nil;
498*37da2899SCharles.Forsyth	lsrv := srvbrowse->find(attribs :: nil);
499*37da2899SCharles.Forsyth	if (lsrv == nil) {
500*37da2899SCharles.Forsyth		butchan <-= "error cannot find Cpu Pool resource";
501*37da2899SCharles.Forsyth		return;
502*37da2899SCharles.Forsyth	}
503*37da2899SCharles.Forsyth	cpupoolsrvc := hd lsrv;
504*37da2899SCharles.Forsyth	attached := cpupoolsrvc.attach(nil, nil);
505*37da2899SCharles.Forsyth	if (attached == nil) {
506*37da2899SCharles.Forsyth		butchan <-= "error cannot connect to Cpu Pool resource";
507*37da2899SCharles.Forsyth		return;
508*37da2899SCharles.Forsyth	}
509*37da2899SCharles.Forsyth	if (sys->mount(attached.fd, nil, "/n/remote", sys->MREPL, nil) == -1) {
510*37da2899SCharles.Forsyth		butchan <-= sys->sprint("error Cpu Pool mount failed: %r");
511*37da2899SCharles.Forsyth		return;
512*37da2899SCharles.Forsyth	}
513*37da2899SCharles.Forsyth	butchan <-= "output Connected to Cpu Pool resource\n";
514*37da2899SCharles.Forsyth	if (blurimage[len blurimage - 4:] == ".jpg") {
515*37da2899SCharles.Forsyth		butchan <-= "output Converting jpg => bit image\n";
516*37da2899SCharles.Forsyth		chanin := chan of string;
517*37da2899SCharles.Forsyth		killchan := chan of int;
518*37da2899SCharles.Forsyth		spawn jpgprog(butchan, chanin, killchan);
519*37da2899SCharles.Forsyth		img := readjpg->jpg2img(imgpath, "", chan of string, chanin);
520*37da2899SCharles.Forsyth		killchan <-= 1;
521*37da2899SCharles.Forsyth		butchan <-= "output \n";
522*37da2899SCharles.Forsyth		if (img == nil) {
523*37da2899SCharles.Forsyth			butchan <-= "error Error converting jpg";
524*37da2899SCharles.Forsyth			return;
525*37da2899SCharles.Forsyth		}
526*37da2899SCharles.Forsyth		sys->remove("/n/remote/data/blurimage.bit");
527*37da2899SCharles.Forsyth		fd := sys->create("/n/remote/data/blurimage.bit", sys->OWRITE, 8r666);
528*37da2899SCharles.Forsyth		if (fd == nil || display.writeimage(fd, img) == -1) {
529*37da2899SCharles.Forsyth			butchan <-= sys->sprint("error Error saving bit: %r");
530*37da2899SCharles.Forsyth			return;
531*37da2899SCharles.Forsyth		}
532*37da2899SCharles.Forsyth		imgpath = "/n/remote/data/blurimage.bit";
533*37da2899SCharles.Forsyth	}
534*37da2899SCharles.Forsyth	afd := array[ncpus] of ref sys->FD;
535*37da2899SCharles.Forsyth	ngot := 0;
536*37da2899SCharles.Forsyth	for (i := 0; i < ncpus; i++) {
537*37da2899SCharles.Forsyth		afd[ngot] = sys->open("/n/remote/clone", sys->ORDWR);
538*37da2899SCharles.Forsyth		if (afd[ngot] == nil)
539*37da2899SCharles.Forsyth			break;
540*37da2899SCharles.Forsyth		ngot++;
541*37da2899SCharles.Forsyth	}
542*37da2899SCharles.Forsyth	if (ngot == 0) {
543*37da2899SCharles.Forsyth		butchan <-= "error no cpu resources available";
544*37da2899SCharles.Forsyth		return;
545*37da2899SCharles.Forsyth	}
546*37da2899SCharles.Forsyth	if (ngot < ncpus) {
547*37da2899SCharles.Forsyth		butchan <-= "fewcpu "+string ngot;
548*37da2899SCharles.Forsyth		q := <-quit;
549*37da2899SCharles.Forsyth		if (q)
550*37da2899SCharles.Forsyth			return;
551*37da2899SCharles.Forsyth	}
552*37da2899SCharles.Forsyth	butchan <-= "output Found "+string ngot+" Cpu resource(s)\n";
553*37da2899SCharles.Forsyth	sh := load Sh Sh->PATH;
554*37da2899SCharles.Forsyth	if (sh == nil)
555*37da2899SCharles.Forsyth		badmod(Sh->PATH);
556*37da2899SCharles.Forsyth	sys->create("/n/remote/data/blur", sys->OREAD, 8r777 | sys->DMDIR);
557*37da2899SCharles.Forsyth	done := chan of int;
558*37da2899SCharles.Forsyth	for (i = 0; i < ngot; i++)
559*37da2899SCharles.Forsyth		spawn go(afd[i], i, butchan, done);
560*37da2899SCharles.Forsyth	err := sh->run(ctxt, "/dis/grid/demo/blur.dis" :: "/n/remote/data" :: imgpath :: nil);
561*37da2899SCharles.Forsyth	if (err != nil)
562*37da2899SCharles.Forsyth		butchan <-= "error "+err;
563*37da2899SCharles.Forsyth	finished := 0;
564*37da2899SCharles.Forsyth	for (;;) {
565*37da2899SCharles.Forsyth		<-done;
566*37da2899SCharles.Forsyth		finished++;
567*37da2899SCharles.Forsyth		if (finished == ngot)
568*37da2899SCharles.Forsyth			break;
569*37da2899SCharles.Forsyth	}
570*37da2899SCharles.Forsyth	sys->unmount(nil, "/n/remote");
571*37da2899SCharles.Forsyth	butchan <-= "output Finished\n";
572*37da2899SCharles.Forsyth	sync <-= 1;
573*37da2899SCharles.Forsyth}
574*37da2899SCharles.Forsyth
575*37da2899SCharles.Forsythjpgprog(butchan, chanin: chan of string, killchan: chan of int)
576*37da2899SCharles.Forsyth{
577*37da2899SCharles.Forsyth	i := 0;
578*37da2899SCharles.Forsyth	for (;;) alt {
579*37da2899SCharles.Forsyth		<-killchan =>
580*37da2899SCharles.Forsyth			return;
581*37da2899SCharles.Forsyth		<-chanin =>
582*37da2899SCharles.Forsyth			i = (i+1) % 2;
583*37da2899SCharles.Forsyth			if (i)
584*37da2899SCharles.Forsyth				butchan <-= "output .";
585*37da2899SCharles.Forsyth	}
586*37da2899SCharles.Forsyth}
587*37da2899SCharles.Forsyth
588*37da2899SCharles.Forsythgo(fd: ref sys->FD, id: int, butchan: chan of string, done: chan of int)
589*37da2899SCharles.Forsyth{
590*37da2899SCharles.Forsyth	op := "output Cpu "+string id+": ";
591*37da2899SCharles.Forsyth	sys->fprint(fd, "/dis/grid/demo/blur.dis /data/");
592*37da2899SCharles.Forsyth	buf := array[sys->ATOMICIO] of byte;
593*37da2899SCharles.Forsyth	sys->seek(fd, big 0, sys->SEEKSTART);
594*37da2899SCharles.Forsyth	i := sys->read(fd, buf, len buf);
595*37da2899SCharles.Forsyth	if (i < 1)
596*37da2899SCharles.Forsyth		sys->print("Error reading dir name: %r\n");
597*37da2899SCharles.Forsyth	dir := string buf[:i];
598*37da2899SCharles.Forsyth	if (dir[len dir - 1] == '\n')
599*37da2899SCharles.Forsyth		dir = dir[:len dir -1];
600*37da2899SCharles.Forsyth	fdout := sys->open("/n/remote/"+dir+"/data", sys->OREAD);
601*37da2899SCharles.Forsyth	if (fdout == nil) {
602*37da2899SCharles.Forsyth		butchan <-= op+"Cannot read from stdout";
603*37da2899SCharles.Forsyth		done <-= 1;
604*37da2899SCharles.Forsyth		return;
605*37da2899SCharles.Forsyth	}
606*37da2899SCharles.Forsyth	for (;;) {
607*37da2899SCharles.Forsyth		i = sys->read(fdout, buf, len buf);
608*37da2899SCharles.Forsyth		if (i < 1)
609*37da2899SCharles.Forsyth			break;
610*37da2899SCharles.Forsyth		s := string buf[:i];
611*37da2899SCharles.Forsyth		if (s[len s - 1] != '\n')
612*37da2899SCharles.Forsyth			s[len s] = '\n';
613*37da2899SCharles.Forsyth		butchan <-= op+s;
614*37da2899SCharles.Forsyth	}
615*37da2899SCharles.Forsyth	done <-= 1;
616*37da2899SCharles.Forsyth}
617*37da2899SCharles.Forsyth
618*37da2899SCharles.Forsythkill(pid: int)
619*37da2899SCharles.Forsyth{
620*37da2899SCharles.Forsyth	if ((fd := sys->open("/prog/" + string pid + "/ctl", Sys->OWRITE)) != nil)
621*37da2899SCharles.Forsyth		sys->fprint(fd, "kill");
622*37da2899SCharles.Forsyth}
623*37da2899SCharles.Forsyth
624*37da2899SCharles.Forsythkillg(pid: int)
625*37da2899SCharles.Forsyth{
626*37da2899SCharles.Forsyth	if ((fd := sys->open("/prog/" + string pid + "/ctl", Sys->OWRITE)) != nil)
627*37da2899SCharles.Forsyth		sys->fprint(fd, "killgrp");
628*37da2899SCharles.Forsyth}
629*37da2899SCharles.Forsyth
630*37da2899SCharles.Forsythmainscreen := array[] of {
631*37da2899SCharles.Forsyth	"frame .f",
632*37da2899SCharles.Forsyth	"frame .f.ftop",
633*37da2899SCharles.Forsyth	"variable opt command",
634*37da2899SCharles.Forsyth	"button .f.ftop.bp -text {Services} -command {send butchan back} -font /fonts/charon/bold.normal.font -state disabled -state disabled",
635*37da2899SCharles.Forsyth	"button .f.ftop.bn -text {Run} -command {send butchan run} -font /fonts/charon/bold.normal.font -state disabled",
636*37da2899SCharles.Forsyth	"button .f.ftop.br -text {Refresh} -command {send butchan refresh} -font /fonts/charon/bold.normal.font",
637*37da2899SCharles.Forsyth 	"grid .f.ftop.br .f.ftop.bp .f.ftop.bn -row 0",
638*37da2899SCharles.Forsyth	"grid columnconfigure .f.ftop 3 -minsize 30",
639*37da2899SCharles.Forsyth	"label .f.l -text { } -height 1 -bg red",
640*37da2899SCharles.Forsyth	"grid .f.l -row 1 -column 0 -sticky ew",
641*37da2899SCharles.Forsyth	"grid .f.ftop -row 0 -column 0 -pady 2 -sticky w",
642*37da2899SCharles.Forsyth	"grid .fbrowse -in .f -row 2 -column 0 -sticky nsew",
643*37da2899SCharles.Forsyth	"grid .fselect -in .f -row 3 -column 0 -sticky nsew",
644*37da2899SCharles.Forsyth	"grid columnconfigure .f 0 -weight 1",
645*37da2899SCharles.Forsyth	"grid rowconfigure .f 2 -weight 1",
646*37da2899SCharles.Forsyth	"grid rowconfigure .f 3 -weight 1",
647*37da2899SCharles.Forsyth
648*37da2899SCharles.Forsyth	"bind .Wm_t <Button-1> +{focus .Wm_t}",
649*37da2899SCharles.Forsyth	"bind .Wm_t.title <Button-1> +{focus .Wm_t}",
650*37da2899SCharles.Forsyth	"focus .Wm_t",
651*37da2899SCharles.Forsyth};
652*37da2899SCharles.Forsyth
653*37da2899SCharles.Forsythreadpath(dir: File): (array of ref sys->Dir, int)
654*37da2899SCharles.Forsyth{
655*37da2899SCharles.Forsyth	if (currstep == MOUNT) {
656*37da2899SCharles.Forsyth		(dirs, nil) := readdir->init(dir.path, readdir->NAME | readdir->COMPACT);
657*37da2899SCharles.Forsyth		dirs2 := array[len dirs] of ref sys->Dir;
658*37da2899SCharles.Forsyth		num := 0;
659*37da2899SCharles.Forsyth		for (i := 0; i < len dirs; i++)
660*37da2899SCharles.Forsyth			if (dirs[i].mode & sys->DMDIR ||
661*37da2899SCharles.Forsyth				(len dirs[i].name > 4 && (
662*37da2899SCharles.Forsyth					dirs[i].name[len dirs[i].name - 4:] == ".bit" ||
663*37da2899SCharles.Forsyth					dirs[i].name[len dirs[i].name - 4:] == ".jpg")))
664*37da2899SCharles.Forsyth				dirs2[num++] = dirs[i];
665*37da2899SCharles.Forsyth		return (dirs2[:num], 0);
666*37da2899SCharles.Forsyth	}
667*37da2899SCharles.Forsyth	else
668*37da2899SCharles.Forsyth		return srvbrowse->servicepath2Dir(dir.path, int dir.qid);
669*37da2899SCharles.Forsyth	return (nil, 0);
670*37da2899SCharles.Forsyth}
671*37da2899SCharles.Forsyth
672*37da2899SCharles.Forsythbadmod(path: string)
673*37da2899SCharles.Forsyth{
674*37da2899SCharles.Forsyth	sys->print("Blurdemo: failed to load %s: %r\n",path);
675*37da2899SCharles.Forsyth	exit;
676*37da2899SCharles.Forsyth}
677*37da2899SCharles.Forsyth
678*37da2899SCharles.Forsythmountscr := array[] of {
679*37da2899SCharles.Forsyth	"frame .f -borderwidth 2 -relief raised",
680*37da2899SCharles.Forsyth	"text .f.t -width 200 -height 60 -borderwidth 1 -bg white -font /fonts/charon/plain.normal.font",
681*37da2899SCharles.Forsyth	"button .f.b -text {Cancel} -command {send butchan cancel} -width 70 -font /fonts/charon/plain.normal.font",
682*37da2899SCharles.Forsyth	"grid .f.t -row 0 -column 0 -padx 10 -pady 10",
683*37da2899SCharles.Forsyth	"grid .f.b -row 1 -column 0 -sticky n",
684*37da2899SCharles.Forsyth	"grid rowconfigure .f 1 -minsize 30",
685*37da2899SCharles.Forsyth};
686*37da2899SCharles.Forsyth
687*37da2899SCharles.Forsythmountsrv(srvpath, qid: string, coords: draw->Rect):int
688*37da2899SCharles.Forsyth{
689*37da2899SCharles.Forsyth	(top, nil) := tkclient->toplevel(ctxt, "", nil, tkclient->Plain);
690*37da2899SCharles.Forsyth	ctlchan := chan of string;
691*37da2899SCharles.Forsyth	butchan := chan of string;
692*37da2899SCharles.Forsyth	tk->namechan(top, butchan, "butchan");
693*37da2899SCharles.Forsyth	tkcmds(top, mountscr);
694*37da2899SCharles.Forsyth	tkcmd(top, ". configure "+getcentre(top, coords)+"; pack .f; update");
695*37da2899SCharles.Forsyth	spawn mountit(srvpath, qid, ctlchan);
696*37da2899SCharles.Forsyth	pid := int <-ctlchan;
697*37da2899SCharles.Forsyth	tkclient->onscreen(top, "exact");
698*37da2899SCharles.Forsyth	tkclient->startinput(top, "kbd"::"ptr"::nil);
699*37da2899SCharles.Forsyth	for (;;) {
700*37da2899SCharles.Forsyth		alt {
701*37da2899SCharles.Forsyth		s := <-top.ctxt.kbd =>
702*37da2899SCharles.Forsyth			tk->keyboard(top, s);
703*37da2899SCharles.Forsyth		s := <-top.ctxt.ptr =>
704*37da2899SCharles.Forsyth			tk->pointer(top, *s);
705*37da2899SCharles.Forsyth		e := <- ctlchan =>
706*37da2899SCharles.Forsyth			if (e[0] == '!') {
707*37da2899SCharles.Forsyth				tkcmd(top, ".f.t insert end {"+e[1:]+"}");
708*37da2899SCharles.Forsyth				tkcmd(top, ".f.b configure -text {close}; update");
709*37da2899SCharles.Forsyth				pid = -1;
710*37da2899SCharles.Forsyth			}
711*37da2899SCharles.Forsyth			else if (e == "ok")
712*37da2899SCharles.Forsyth				return 1;
713*37da2899SCharles.Forsyth			else
714*37da2899SCharles.Forsyth				tkcmd(top, ".f.t insert end {"+e+"}; update");
715*37da2899SCharles.Forsyth		<- butchan =>
716*37da2899SCharles.Forsyth			if (pid != -1)
717*37da2899SCharles.Forsyth				kill(pid);
718*37da2899SCharles.Forsyth			return 0;
719*37da2899SCharles.Forsyth		}
720*37da2899SCharles.Forsyth	}
721*37da2899SCharles.Forsyth	return 0;
722*37da2899SCharles.Forsyth}
723*37da2899SCharles.Forsyth
724*37da2899SCharles.Forsythmountit(srvpath, qid: string, ctlchan: chan of string)
725*37da2899SCharles.Forsyth{
726*37da2899SCharles.Forsyth	ctlchan <-= string sys->pctl(0,nil);
727*37da2899SCharles.Forsyth
728*37da2899SCharles.Forsyth	n := 0;
729*37da2899SCharles.Forsyth	(nil, lst) := sys->tokenize(srvpath, "/");
730*37da2899SCharles.Forsyth	stype := hd tl lst;
731*37da2899SCharles.Forsyth	name := hd tl tl lst;
732*37da2899SCharles.Forsyth	addr := "";
733*37da2899SCharles.Forsyth	ctlchan <-= "Connecting...\n";
734*37da2899SCharles.Forsyth	lsrv := srvbrowse->servicepath2Service(srvpath, qid);
735*37da2899SCharles.Forsyth	if (len lsrv < 1) {
736*37da2899SCharles.Forsyth		ctlchan <-= "!could not find service";
737*37da2899SCharles.Forsyth		return;
738*37da2899SCharles.Forsyth	}
739*37da2899SCharles.Forsyth	srvc := hd lsrv;
740*37da2899SCharles.Forsyth	currattach = srvc.attach(nil, nil);
741*37da2899SCharles.Forsyth	if (currattach == nil) {
742*37da2899SCharles.Forsyth		ctlchan <-= "!attach failed";
743*37da2899SCharles.Forsyth		return;
744*37da2899SCharles.Forsyth	}
745*37da2899SCharles.Forsyth	ctlchan <-= "Mounting...\n";
746*37da2899SCharles.Forsyth	if (sys->mount(currattach.fd, nil, "/n/remote", sys->MREPL, nil) != -1) {
747*37da2899SCharles.Forsyth		ctlchan <-= "ok";
748*37da2899SCharles.Forsyth		currsrv = srvc;
749*37da2899SCharles.Forsyth	}
750*37da2899SCharles.Forsyth	else
751*37da2899SCharles.Forsyth		ctlchan <-= "!mount failed";
752*37da2899SCharles.Forsyth}
753*37da2899SCharles.Forsyth
754*37da2899SCharles.Forsythgetcoords(top: ref Tk->Toplevel): draw->Rect
755*37da2899SCharles.Forsyth{
756*37da2899SCharles.Forsyth	h := int tkcmd(top, ". cget -height");
757*37da2899SCharles.Forsyth	w := int tkcmd(top, ". cget -width");
758*37da2899SCharles.Forsyth	x := int tkcmd(top, ". cget -actx");
759*37da2899SCharles.Forsyth	y := int tkcmd(top, ". cget -acty");
760*37da2899SCharles.Forsyth	r := draw->Rect((x,y),(x+w,y+h));
761*37da2899SCharles.Forsyth	return r;
762*37da2899SCharles.Forsyth}
763*37da2899SCharles.Forsyth
764*37da2899SCharles.Forsythgetcentre(top: ref Tk->Toplevel, winr: draw->Rect): string
765*37da2899SCharles.Forsyth{
766*37da2899SCharles.Forsyth	h := int tkcmd(top, ".f cget -height");
767*37da2899SCharles.Forsyth	w := int tkcmd(top, ".f cget -width");
768*37da2899SCharles.Forsyth	midx := winr.min.x + (winr.dx() / 2);
769*37da2899SCharles.Forsyth	midy := winr.min.y + (winr.dy() / 2);
770*37da2899SCharles.Forsyth	newx := midx - (w/2);
771*37da2899SCharles.Forsyth	newy := midy - (h/2);
772*37da2899SCharles.Forsyth	return "-x "+string newx+" -y "+string newy;
773*37da2899SCharles.Forsyth}
774*37da2899SCharles.Forsyth
775*37da2899SCharles.Forsythchangestep(top: ref Tk->Toplevel, step: int, label: string)
776*37da2899SCharles.Forsyth{
777*37da2899SCharles.Forsyth	root, rlabel: string;
778*37da2899SCharles.Forsyth	if (step == MOUNT) {
779*37da2899SCharles.Forsyth		tkcmd (top, ".f.ftop.bp configure -state normal");
780*37da2899SCharles.Forsyth		br.changeview(2);
781*37da2899SCharles.Forsyth			rlabel = label;
782*37da2899SCharles.Forsyth		if (currsrv.addr == "Local Machine")
783*37da2899SCharles.Forsyth			root = "/";
784*37da2899SCharles.Forsyth		else
785*37da2899SCharles.Forsyth			root = "/n/remote/";
786*37da2899SCharles.Forsyth	}
787*37da2899SCharles.Forsyth	else if (step == IMAGE) {
788*37da2899SCharles.Forsyth		br.changeview(1);
789*37da2899SCharles.Forsyth		if (currsrv != nil) {
790*37da2899SCharles.Forsyth			sys->unmount(nil, "/n/remote");
791*37da2899SCharles.Forsyth			currattach = nil;
792*37da2899SCharles.Forsyth			currsrv = nil;
793*37da2899SCharles.Forsyth		}
794*37da2899SCharles.Forsyth		srvbrowse->refreshservices(srvfilter);
795*37da2899SCharles.Forsyth		root = "services/";
796*37da2899SCharles.Forsyth		rlabel = "Image Services";
797*37da2899SCharles.Forsyth		sel.showframe("image");
798*37da2899SCharles.Forsyth		tkcmd (top, ".f.ftop.bp configure -state disabled");
799*37da2899SCharles.Forsyth		# addlocalservice();
800*37da2899SCharles.Forsyth		sel.select("image", nil, DESELECT);
801*37da2899SCharles.Forsyth	}
802*37da2899SCharles.Forsyth	currstep = step;
803*37da2899SCharles.Forsyth	br.selectfile(1, DESELECT, File (nil, nil), nil);
804*37da2899SCharles.Forsyth	br.selectfile(0, DESELECT,File (nil, nil), nil);
805*37da2899SCharles.Forsyth	actionbutton(top, nil, nil);
806*37da2899SCharles.Forsyth
807*37da2899SCharles.Forsyth	br.newroot(root, rlabel);
808*37da2899SCharles.Forsyth	if (currstep == MOUNT)
809*37da2899SCharles.Forsyth		br.selectfile(0, SELECT, File (root, nil), ".fbrowse.fl.f0.l");
810*37da2899SCharles.Forsyth	tkcmd(top, "update");
811*37da2899SCharles.Forsyth}
812*37da2899SCharles.Forsyth
813*37da2899SCharles.Forsythaddlocalservice()
814*37da2899SCharles.Forsyth{
815*37da2899SCharles.Forsyth	lsrv : Service;
816*37da2899SCharles.Forsyth	attrs := ("resource", "Data source") ::
817*37da2899SCharles.Forsyth		("name", "Local Filestore") ::
818*37da2899SCharles.Forsyth		("type", "styx") :: nil;
819*37da2899SCharles.Forsyth	lsrv.attrs = Attributes.new(attrs);
820*37da2899SCharles.Forsyth	lsrv.addr = "@your local filestore";
821*37da2899SCharles.Forsyth	srvbrowse->addservice(ref lsrv);
822*37da2899SCharles.Forsyth}
823*37da2899SCharles.Forsyth
824*37da2899SCharles.Forsythtkcmd(top: ref Tk->Toplevel, cmd: string): string
825*37da2899SCharles.Forsyth{
826*37da2899SCharles.Forsyth	e := tk->cmd(top, cmd);
827*37da2899SCharles.Forsyth	if (e != "" && e[0] == '!')
828*37da2899SCharles.Forsyth		sys->print("Tk error: '%s': %s\n",cmd,e);
829*37da2899SCharles.Forsyth	return e;
830*37da2899SCharles.Forsyth}
831*37da2899SCharles.Forsyth
832*37da2899SCharles.Forsythtkcmds(top: ref Tk->Toplevel, a: array of string)
833*37da2899SCharles.Forsyth{
834*37da2899SCharles.Forsyth	for (j := 0; j < len a; j++)
835*37da2899SCharles.Forsyth		tkcmd(top, a[j]);
836*37da2899SCharles.Forsyth}
837*37da2899SCharles.Forsyth
838*37da2899SCharles.Forsythreadfile(f: string): string
839*37da2899SCharles.Forsyth{
840*37da2899SCharles.Forsyth	fd := sys->open(f, sys->OREAD);
841*37da2899SCharles.Forsyth	if(fd == nil)
842*37da2899SCharles.Forsyth		return nil;
843*37da2899SCharles.Forsyth
844*37da2899SCharles.Forsyth	buf := array[8192] of byte;
845*37da2899SCharles.Forsyth	n := sys->read(fd, buf, len buf);
846*37da2899SCharles.Forsyth	if(n < 0)
847*37da2899SCharles.Forsyth		return nil;
848*37da2899SCharles.Forsyth
849*37da2899SCharles.Forsyth	return string buf[:n];
850*37da2899SCharles.Forsyth}
851*37da2899SCharles.Forsyth
852*37da2899SCharles.Forsythsetsrvfilter()
853*37da2899SCharles.Forsyth{
854*37da2899SCharles.Forsyth	imagefilter := ("proto", "styx") :: ("auth", "none") :: ("Image resource", "1") :: nil;
855*37da2899SCharles.Forsyth	srvfilter = imagefilter :: nil;
856*37da2899SCharles.Forsyth}
857*37da2899SCharles.Forsyth
858*37da2899SCharles.Forsythgetpreview(tkpath, imgpath: string, img: ref Image)
859*37da2899SCharles.Forsyth{
860*37da2899SCharles.Forsyth	if (imgpath != nil && imgpath[len imgpath - 4:] == ".jpg") {
861*37da2899SCharles.Forsyth		tkcmd (sel.top, ".f.ftop.bn configure -state normal");
862*37da2899SCharles.Forsyth		return;
863*37da2899SCharles.Forsyth	}
864*37da2899SCharles.Forsyth	if (img == nil) {
865*37da2899SCharles.Forsyth		img = display.open(imgpath);
866*37da2899SCharles.Forsyth		if (img == nil) {
867*37da2899SCharles.Forsyth			browser->dialog(ctxt, sel.top, "ok" :: nil, "Alert",
868*37da2899SCharles.Forsyth				sys->sprint("Invalid '.bit' image: %r"));
869*37da2899SCharles.Forsyth			sel.delselection("image", blurtkpath);
870*37da2899SCharles.Forsyth			blurimage = nil;
871*37da2899SCharles.Forsyth			blursrvc = nil;
872*37da2899SCharles.Forsyth			return;
873*37da2899SCharles.Forsyth		}
874*37da2899SCharles.Forsyth	}
875*37da2899SCharles.Forsyth	previmg := preview(img, 100);
876*37da2899SCharles.Forsyth	tk->cmd(sel.top, "destroy .preview");
877*37da2899SCharles.Forsyth	tkcmd(sel.top, "image create bitmap .preview");
878*37da2899SCharles.Forsyth	tk->putimage(sel.top, ".preview", previmg, nil);
879*37da2899SCharles.Forsyth	tkcmd(sel.top, sys->sprint("%s configure -image .preview -width %d -height %d",
880*37da2899SCharles.Forsyth		tkpath, previmg.r.dx(), previmg.r.dy()));
881*37da2899SCharles.Forsyth	tkcmd(sel.top, "grid forget "+tkpath+"; grid "+tkpath+" -row 1 "+
882*37da2899SCharles.Forsyth			"-column 0 -columnspan 3 -pady 5 -sticky ew;");
883*37da2899SCharles.Forsyth	sel.setscrollr(sel.currfname);
884*37da2899SCharles.Forsyth	tkcmd (sel.top, ".f.ftop.bn configure -state normal");
885*37da2899SCharles.Forsyth	tkcmd(sel.top, "update;");
886*37da2899SCharles.Forsyth}
887*37da2899SCharles.Forsyth
888*37da2899SCharles.Forsythpreview(img: ref Image, maxsize: int): ref Image
889*37da2899SCharles.Forsyth{
890*37da2899SCharles.Forsyth	mx := max(img.r.dx(), img.r.dy());
891*37da2899SCharles.Forsyth	if (mx <= maxsize) {
892*37da2899SCharles.Forsyth		imgcache = img;
893*37da2899SCharles.Forsyth		return img;
894*37da2899SCharles.Forsyth	}
895*37da2899SCharles.Forsyth	prevr := Rect ((0,0), (img.r.dx()*maxsize/mx, img.r.dy()*maxsize/mx));
896*37da2899SCharles.Forsyth	tmpimg := display.newimage(img.r, Draw->RGB24, 0, Draw->White);
897*37da2899SCharles.Forsyth	previmg := display.newimage(prevr, Draw->RGB24, 0, Draw->White);
898*37da2899SCharles.Forsyth	tmpimg.draw(img.r, img, nil, (0,0));
899*37da2899SCharles.Forsyth
900*37da2899SCharles.Forsyth	getr := Rect ((0,0), (img.r.dx() / prevr.dx(), img.r.dy() / prevr.dy()));
901*37da2899SCharles.Forsyth
902*37da2899SCharles.Forsyth	nopixels := getr.dx() * getr.dy();
903*37da2899SCharles.Forsyth	getrgb := array[nopixels * 3] of byte;
904*37da2899SCharles.Forsyth	newrgb := array[3] of byte;
905*37da2899SCharles.Forsyth	for (y := 0; y < prevr.dy(); y++) {
906*37da2899SCharles.Forsyth		for (x := 0; x < prevr.dx(); x++) {
907*37da2899SCharles.Forsyth			tmpimg.readpixels(getr.addpt((x*getr.dx(), y*getr.dy())), getrgb);
908*37da2899SCharles.Forsyth			tmprgb := array[] of { 0, 0, 0 };
909*37da2899SCharles.Forsyth			for (i := 0; i < len getrgb; i++)
910*37da2899SCharles.Forsyth				tmprgb[i%3] += int getrgb[i];
911*37da2899SCharles.Forsyth			for (i = 0; i < 3; i++)
912*37da2899SCharles.Forsyth				newrgb[i] = byte (tmprgb[i] / nopixels);
913*37da2899SCharles.Forsyth			previmg.writepixels(((x,y),(x+1,y+1)), newrgb);
914*37da2899SCharles.Forsyth		}
915*37da2899SCharles.Forsyth	}
916*37da2899SCharles.Forsyth	imgcache = previmg;
917*37da2899SCharles.Forsyth	return previmg;
918*37da2899SCharles.Forsyth}
919*37da2899SCharles.Forsyth
920*37da2899SCharles.Forsythmax(a,b: int): int
921*37da2899SCharles.Forsyth{
922*37da2899SCharles.Forsyth	if (a > b)
923*37da2899SCharles.Forsyth		return a;
924*37da2899SCharles.Forsyth	return b;
925*37da2899SCharles.Forsyth}
926*37da2899SCharles.Forsyth
927*37da2899SCharles.Forsythpreviewscr := array[] of {
928*37da2899SCharles.Forsyth	"frame .f",
929*37da2899SCharles.Forsyth	"panel .f.p -borderwidth 2 -relief raised",
930*37da2899SCharles.Forsyth	"button .f.bs -text Select -font /fonts/charon/plain.normal.font -command {send prevchan select} -state disabled",
931*37da2899SCharles.Forsyth	"button .f.bc -text Close -font /fonts/charon/plain.normal.font -command {send prevchan close} -state disabled",
932*37da2899SCharles.Forsyth	"pack .f",
933*37da2899SCharles.Forsyth	"grid .f.p -row 0 -column 0 -columnspan 2 -padx 5 -pady 5",
934*37da2899SCharles.Forsyth	"grid .f.bs .f.bc -row 1 -padx 5 -pady 5",
935*37da2899SCharles.Forsyth	"update",
936*37da2899SCharles.Forsyth};
937*37da2899SCharles.Forsyth
938*37da2899SCharles.Forsythpreviewwin(oldtop: ref Tk->Toplevel, chanout: chan of string, path: string)
939*37da2899SCharles.Forsyth{
940*37da2899SCharles.Forsyth	(top, titlectl) := tkclient->toplevel(ctxt, "", "Loading...", 0);
941*37da2899SCharles.Forsyth	prevchan := chan of string;
942*37da2899SCharles.Forsyth	tk->namechan(top, prevchan, "prevchan");
943*37da2899SCharles.Forsyth	tkclient->onscreen(top, "exact");
944*37da2899SCharles.Forsyth
945*37da2899SCharles.Forsyth	img := display.open(path);
946*37da2899SCharles.Forsyth	if (img == nil) {
947*37da2899SCharles.Forsyth		browser->dialog(ctxt, oldtop, "ok" :: nil, "Alert", "Invalid '.bit' image");
948*37da2899SCharles.Forsyth		return;
949*37da2899SCharles.Forsyth	}
950*37da2899SCharles.Forsyth
951*37da2899SCharles.Forsyth	previmg := preview(img, 100);
952*37da2899SCharles.Forsyth	tkcmds(top, previewscr);
953*37da2899SCharles.Forsyth	tk->putimage(top, ".f.p", previmg, nil);
954*37da2899SCharles.Forsyth	tkcmd(top, ".Wm_t.title configure -text Preview");
955*37da2899SCharles.Forsyth	tkcmd(top, ".f.p dirty; update");
956*37da2899SCharles.Forsyth	browser->setcentre(oldtop, top);
957*37da2899SCharles.Forsyth	tkcmd(top, ".f.bs configure -state normal; .f.bc configure -state normal");
958*37da2899SCharles.Forsyth	tkclient->startinput(top, "kbd"::"ptr"::nil);
959*37da2899SCharles.Forsyth
960*37da2899SCharles.Forsyth	main: for(;;) alt {
961*37da2899SCharles.Forsyth		s := <-top.ctxt.kbd =>
962*37da2899SCharles.Forsyth			tk->keyboard(top, s);
963*37da2899SCharles.Forsyth		s := <-top.ctxt.ptr =>
964*37da2899SCharles.Forsyth			tk->pointer(top, *s);
965*37da2899SCharles.Forsyth		s := <- prevchan =>
966*37da2899SCharles.Forsyth			if (s == "select")
967*37da2899SCharles.Forsyth				chanout <-= "add "+path+" 1";
968*37da2899SCharles.Forsyth			break main;
969*37da2899SCharles.Forsyth		s := <-top.ctxt.ctl or
970*37da2899SCharles.Forsyth		s = <-top.wreq or
971*37da2899SCharles.Forsyth		s = <- titlectl =>
972*37da2899SCharles.Forsyth			if (s == "exit")
973*37da2899SCharles.Forsyth				break main;
974*37da2899SCharles.Forsyth			else
975*37da2899SCharles.Forsyth				tkclient->wmctl(top, s);
976*37da2899SCharles.Forsyth	}
977*37da2899SCharles.Forsyth}
978