xref: /inferno-os/appl/charon/gui.b (revision 54041ca415f1fdfa1c3dcd82d524223cfa890940)
137da2899SCharles.Forsyth# Gui implementation for running under wm (tk window manager)
237da2899SCharles.Forsythimplement Gui;
337da2899SCharles.Forsyth
437da2899SCharles.Forsythinclude "common.m";
537da2899SCharles.Forsythinclude "tk.m";
637da2899SCharles.Forsythinclude "tkclient.m";
737da2899SCharles.Forsyth
837da2899SCharles.Forsythinclude "dialog.m";
937da2899SCharles.Forsyth	dialog: Dialog;
1037da2899SCharles.Forsyth
1137da2899SCharles.Forsythsys: Sys;
1237da2899SCharles.Forsyth
1337da2899SCharles.ForsythD: Draw;
1437da2899SCharles.Forsyth	Font,Point, Rect, Image, Screen, Display: import D;
1537da2899SCharles.Forsyth
1637da2899SCharles.ForsythCU: CharonUtils;
1737da2899SCharles.Forsyth
1837da2899SCharles.ForsythE: Events;
1937da2899SCharles.Forsyth	Event: import E;
2037da2899SCharles.Forsyth
2137da2899SCharles.Forsythtk: Tk;
2237da2899SCharles.Forsyth
2337da2899SCharles.Forsythtkclient: Tkclient;
2437da2899SCharles.Forsyth
2537da2899SCharles.ForsythWINDOW, CTLS, PROG, STATUS, BORDER, EXIT: con 1 << iota;
2637da2899SCharles.ForsythREQD: con ~0;
2737da2899SCharles.Forsyth
2837da2899SCharles.Forsythcfg := array[] of {
2937da2899SCharles.Forsyth	(REQD,	"entry .ctlf.url -bg white -font /fonts/lucidasans/unicode.7.font -height 16"),
3037da2899SCharles.Forsyth	(REQD,	"button .ctlf.back -bd 1 -command {send gctl back} -state disabled -text {back} -font /fonts/lucidasans/unicode.7.font"),
3137da2899SCharles.Forsyth	(REQD,	"button .ctlf.stop -bd 1 -command {send gctl stop} -state disabled -text {stop} -font /fonts/lucidasans/unicode.7.font"),
3237da2899SCharles.Forsyth	(REQD,	"button .ctlf.fwd -bd 1 -command {send gctl fwd} -state disabled -text {next} -font /fonts/lucidasans/unicode.7.font"),
3337da2899SCharles.Forsyth	(REQD,	"label .status.status -bd 1 -font /fonts/lucidasans/unicode.6.font -height 14 -anchor w"),
3437da2899SCharles.Forsyth	(REQD,	"button .ctlf.exit -bd 1 -bitmap exit.bit -command {send wm_title exit}"),
3537da2899SCharles.Forsyth	(REQD,	"frame .f -bd 0"),
3637da2899SCharles.Forsyth	(BORDER,	".f configure -bd 2 -relief sunken"),
3737da2899SCharles.Forsyth	(CTLS|EXIT,	"frame .ctlf"),
3837da2899SCharles.Forsyth	(STATUS,	"frame .status -bd 0"),
3937da2899SCharles.Forsyth	(STATUS,	"frame .statussep -bg black -height 1"),
4037da2899SCharles.Forsyth	(STATUS,	"button .status.snarf -text snarf -command {send gctl snarfstatus} -font /fonts/charon/plain.small.font"),
4137da2899SCharles.Forsyth
4237da2899SCharles.Forsyth	(CTLS,	"bind .ctlf.url <Key-\n> {send gctl go}"),
4337da2899SCharles.Forsyth	(CTLS,	"bind .ctlf.url <Key-\u0003> {send gctl copyurl}"),
4437da2899SCharles.Forsyth	(CTLS,	"bind .ctlf.url <Key-\u0016> {send gctl pasteurl}"),
4537da2899SCharles.Forsyth
4637da2899SCharles.Forsyth#	(PROG,	"canvas .prog -bd 0 -height 20"),
4737da2899SCharles.Forsyth#	(PROG,	"bind .prog <ButtonPress-1> {send gctl b1p %X %Y}"),
4837da2899SCharles.Forsyth	(CTLS,	"pack .ctlf.back .ctlf.stop .ctlf.fwd -side left -anchor w -fill y"),
4937da2899SCharles.Forsyth	(CTLS,	"pack .ctlf.url -side left -padx 2 -fill x -expand 1"),
5037da2899SCharles.Forsyth	(EXIT,	"pack .ctlf.exit -side right -anchor e"),
5137da2899SCharles.Forsyth	(CTLS|EXIT,	"pack .ctlf -side top -fill x"),
5237da2899SCharles.Forsyth	(REQD,	"pack .f -side top -fill both -expand 1"),
5337da2899SCharles.Forsyth#	(PROG,	"pack .prog -side bottom -fill x"),
5437da2899SCharles.Forsyth	(STATUS,	"pack .status.snarf -side right"),
5537da2899SCharles.Forsyth	(STATUS,	"pack .status.status -side right -fill x -expand 1"),
5637da2899SCharles.Forsyth	(STATUS,	"pack .statussep -side top -fill x"),
5737da2899SCharles.Forsyth	(STATUS,	"pack .status -side bottom -fill x"),
5837da2899SCharles.Forsyth	(CTLS|EXIT,	"pack propagate .ctlf 0"),
5937da2899SCharles.Forsyth	(STATUS,		"pack propagate .status 0"),
6037da2899SCharles.Forsyth};
6137da2899SCharles.Forsyth
6237da2899SCharles.Forsythframebinds := array[] of {
6337da2899SCharles.Forsyth	"bind .f <Key> {send gctl k %s}",
6437da2899SCharles.Forsyth	"bind .f <FocusOut> {send gctl focusout}",
6537da2899SCharles.Forsyth	"bind .f <ButtonPress-1> {grab set .f;send gctl b1p %X %Y}",
6637da2899SCharles.Forsyth	"bind .f <Double-ButtonPress-1> {send gctl b1p %X %Y}",
6737da2899SCharles.Forsyth	"bind .f <ButtonRelease-1> {grab release .f;send gctl b1r %X %Y}",
6837da2899SCharles.Forsyth	"bind .f <Motion-Button-1> {send gctl b1d %X %Y}",
6937da2899SCharles.Forsyth	"bind .f <ButtonPress-2> {send gctl b2p %X %Y}",
7037da2899SCharles.Forsyth	"bind .f <Double-ButtonPress-2> {send gctl b2p %X %Y}",
7137da2899SCharles.Forsyth	"bind .f <ButtonRelease-2> {send gctl b2r %X %Y}",
7237da2899SCharles.Forsyth	"bind .f <Motion-Button-2> {send gctl b2d %X %Y}",
7337da2899SCharles.Forsyth	"bind .f <ButtonPress-3> {send gctl b3p %X %Y}",
7437da2899SCharles.Forsyth	"bind .f <Double-ButtonPress-3> {send gctl b3p %X %Y}",
7537da2899SCharles.Forsyth	"bind .f <ButtonRelease-3> {send gctl b3r %X %Y}",
7637da2899SCharles.Forsyth	"bind .f <Motion-Button-3> {send gctl b3d %X %Y}",
7737da2899SCharles.Forsyth	"bind .f <Motion> {send gctl m %X %Y}",
7837da2899SCharles.Forsyth};
7937da2899SCharles.Forsyth
8037da2899SCharles.Forsythtktop: ref Tk->Toplevel;
8137da2899SCharles.Forsythmousegrabbed := 0;
8237da2899SCharles.Forsythoffset: Point;
8337da2899SCharles.ForsythZP: con Point(0,0);
8437da2899SCharles.Forsythpopup: ref Popup;
8537da2899SCharles.Forsythpopuptk: ref Tk->Toplevel;
8637da2899SCharles.Forsythgctl: chan of string;
8737da2899SCharles.Forsythdrawctxt: ref Draw->Context;
8837da2899SCharles.Forsyth
8937da2899SCharles.Forsythrealwin: ref Draw->Image;
9037da2899SCharles.Forsythmask: ref Draw->Image;
9137da2899SCharles.Forsyth
9237da2899SCharles.Forsythinit(ctxt: ref Draw->Context, cu: CharonUtils): ref Draw->Context
9337da2899SCharles.Forsyth{
9437da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
9537da2899SCharles.Forsyth	D = load Draw Draw->PATH;
9637da2899SCharles.Forsyth	CU = cu;
9737da2899SCharles.Forsyth	E = cu->E;
9837da2899SCharles.Forsyth	tk = load Tk Tk->PATH;
9937da2899SCharles.Forsyth	tkclient = load Tkclient Tkclient->PATH;
10037da2899SCharles.Forsyth	if(tkclient == nil)
101*54041ca4Sforsyth		raise sys->sprint("EXInternal: can't load module Tkclient: %r");
10237da2899SCharles.Forsyth	tkclient->init();
10337da2899SCharles.Forsyth
10437da2899SCharles.Forsyth	wmctl: chan of string;
10537da2899SCharles.Forsyth	buttons := parsebuttons((CU->config).buttons);
10637da2899SCharles.Forsyth	winopts := parsewinopts((CU->config).framework);
10737da2899SCharles.Forsyth
10837da2899SCharles.Forsyth	(tktop, wmctl) = tkclient->toplevel(ctxt, "", (CU->config).wintitle, buttons);
10937da2899SCharles.Forsyth
11037da2899SCharles.Forsyth	ctxt = tktop.ctxt.ctxt;
11137da2899SCharles.Forsyth	drawctxt = ctxt;
11237da2899SCharles.Forsyth	display = ctxt.display;
11337da2899SCharles.Forsyth
11437da2899SCharles.Forsyth	gctl = chan of string;
11537da2899SCharles.Forsyth	tk->namechan(tktop, gctl, "gctl");
11637da2899SCharles.Forsyth	tk->cmd(tktop, "pack propagate . 0");
11737da2899SCharles.Forsyth	filtertkcmds(tktop, winopts, cfg);
11837da2899SCharles.Forsyth	tkcmds(tktop, framebinds);
11937da2899SCharles.Forsyth	w := (CU->config).defaultwidth;
12037da2899SCharles.Forsyth	h := (CU->config).defaultheight;
12137da2899SCharles.Forsyth	tk->cmd(tktop, ". configure -width " + string w + " -height " + string h);
12237da2899SCharles.Forsyth	tk->cmd(tktop, "update");
12337da2899SCharles.Forsyth	tkclient->onscreen(tktop, nil);
12437da2899SCharles.Forsyth	tkclient->startinput(tktop, "kbd"::"ptr"::nil);
12537da2899SCharles.Forsyth	makewins();
12637da2899SCharles.Forsyth	mask = display.opaque;
12737da2899SCharles.Forsyth	progress = chan of Progressmsg;
12837da2899SCharles.Forsyth	pidc := chan of int;
12937da2899SCharles.Forsyth	spawn progmon(pidc);
13037da2899SCharles.Forsyth	<- pidc;
13137da2899SCharles.Forsyth	spawn evhandle(tktop, wmctl, E->evchan);
13237da2899SCharles.Forsyth	return ctxt;
13337da2899SCharles.Forsyth}
13437da2899SCharles.Forsyth
13537da2899SCharles.Forsythparsebuttons(s: string): int
13637da2899SCharles.Forsyth{
13737da2899SCharles.Forsyth	b := 0;
13837da2899SCharles.Forsyth	(nil, toks) := sys->tokenize(s, ",");
13937da2899SCharles.Forsyth	for (;toks != nil; toks = tl toks) {
14037da2899SCharles.Forsyth		case hd toks {
14137da2899SCharles.Forsyth		"help" =>
14237da2899SCharles.Forsyth			b |= Tkclient->Help;
14337da2899SCharles.Forsyth		"resize" =>
14437da2899SCharles.Forsyth			b |= Tkclient->Resize;
14537da2899SCharles.Forsyth		"hide" =>
14637da2899SCharles.Forsyth			b |= Tkclient->Hide;
14737da2899SCharles.Forsyth		"plain" =>
14837da2899SCharles.Forsyth			b = Tkclient->Plain;
14937da2899SCharles.Forsyth		}
15037da2899SCharles.Forsyth	}
15137da2899SCharles.Forsyth	return b | Tkclient->Help;
15237da2899SCharles.Forsyth}
15337da2899SCharles.Forsyth
15437da2899SCharles.Forsythparsewinopts(s: string): int
15537da2899SCharles.Forsyth{
15637da2899SCharles.Forsyth	b := WINDOW;
15737da2899SCharles.Forsyth	(nil, toks) := sys->tokenize(s, ",");
15837da2899SCharles.Forsyth	for (;toks != nil; toks = tl toks) {
15937da2899SCharles.Forsyth		case hd toks {
16037da2899SCharles.Forsyth		"status" =>
16137da2899SCharles.Forsyth			b |= STATUS;
16237da2899SCharles.Forsyth		"controls" or "ctls" =>
16337da2899SCharles.Forsyth			b |= CTLS;
16437da2899SCharles.Forsyth		"progress" or "prog" =>
16537da2899SCharles.Forsyth			b |= PROG;
16637da2899SCharles.Forsyth		"border" =>
16737da2899SCharles.Forsyth			b |= BORDER;
16837da2899SCharles.Forsyth		"exit" =>
16937da2899SCharles.Forsyth			b |= EXIT;
17037da2899SCharles.Forsyth		"all" =>
17137da2899SCharles.Forsyth			# note: "all" doesn't include 'EXIT' !
17237da2899SCharles.Forsyth			b |= WINDOW | STATUS | CTLS | PROG | BORDER;
17337da2899SCharles.Forsyth		}
17437da2899SCharles.Forsyth	}
17537da2899SCharles.Forsyth	return b;
17637da2899SCharles.Forsyth}
17737da2899SCharles.Forsyth
17837da2899SCharles.Forsythfiltertkcmds(top: ref Tk->Toplevel, filter: int, cmds: array of (int, string))
17937da2899SCharles.Forsyth{
18037da2899SCharles.Forsyth	for (i := 0; i < len cmds; i++) {
18137da2899SCharles.Forsyth		(val, cmd) := cmds[i];
18237da2899SCharles.Forsyth		if (val & filter) {
18337da2899SCharles.Forsyth			if ((e := tk->cmd(top, cmd)) != nil && e[0] == '!')
18437da2899SCharles.Forsyth				sys->print("tk error on '%s': %s\n", cmd, e);
18537da2899SCharles.Forsyth		}
18637da2899SCharles.Forsyth	}
18737da2899SCharles.Forsyth}
18837da2899SCharles.Forsyth
18937da2899SCharles.Forsythtkcmds(top: ref Tk->Toplevel, cmds: array of string)
19037da2899SCharles.Forsyth{
19137da2899SCharles.Forsyth	for (i := 0; i < len cmds; i++)
19237da2899SCharles.Forsyth		if ((e := tk->cmd(top, cmds[i])) != nil && e[0] == '!')
19337da2899SCharles.Forsyth			sys->print("tk error on '%s': %s\n", cmds[i], e);
19437da2899SCharles.Forsyth}
19537da2899SCharles.Forsyth
19637da2899SCharles.Forsythclientr(t: ref Tk->Toplevel, wname: string): Rect
19737da2899SCharles.Forsyth{
19837da2899SCharles.Forsyth	bd := int tk->cmd(t, wname + " cget -borderwidth");
19937da2899SCharles.Forsyth	x := bd + int tk->cmd(t, wname + " cget -actx");
20037da2899SCharles.Forsyth	y := bd + int tk->cmd(t, wname + " cget -acty");
20137da2899SCharles.Forsyth	w := int tk->cmd(t, wname + " cget -actwidth");
20237da2899SCharles.Forsyth	h := int tk->cmd(t, wname + " cget -actheight");
20337da2899SCharles.Forsyth	return Rect((x,y),(x+w,y+h));
20437da2899SCharles.Forsyth}
20537da2899SCharles.Forsyth
20637da2899SCharles.Forsythprogmon(pidc: chan of int)
20737da2899SCharles.Forsyth{
20837da2899SCharles.Forsyth	pidc <-= sys->pctl(0, nil);
20937da2899SCharles.Forsyth	for (;;) {
21037da2899SCharles.Forsyth		msg := <- progress;
21137da2899SCharles.Forsyth#prprog(msg);
21237da2899SCharles.Forsyth		# just handle stop button for now
21337da2899SCharles.Forsyth		if (msg.bsid == -1) {
21437da2899SCharles.Forsyth			case (msg.state) {
21537da2899SCharles.Forsyth			Pstart =>	stopbutton(1);
21637da2899SCharles.Forsyth			* =>		stopbutton(0);
21737da2899SCharles.Forsyth			}
21837da2899SCharles.Forsyth		}
21937da2899SCharles.Forsyth	}
22037da2899SCharles.Forsyth}
22137da2899SCharles.Forsyth
22237da2899SCharles.Forsythst2s := array [] of {
22337da2899SCharles.Forsyth	Punused => "unused",
22437da2899SCharles.Forsyth	Pstart => "start",
22537da2899SCharles.Forsyth	Pconnected => "connected",
22637da2899SCharles.Forsyth	Psslconnected => "sslconnected",
22737da2899SCharles.Forsyth	Phavehdr => "havehdr",
22837da2899SCharles.Forsyth	Phavedata => "havedata",
22937da2899SCharles.Forsyth	Pdone => "done",
23037da2899SCharles.Forsyth	Perr => "error",
23137da2899SCharles.Forsyth	Paborted => "aborted",
23237da2899SCharles.Forsyth};
23337da2899SCharles.Forsyth
23437da2899SCharles.Forsythprprog(m:Progressmsg)
23537da2899SCharles.Forsyth{
23637da2899SCharles.Forsyth	sys->print("%d %s %d%% %s\n", m.bsid, st2s[m.state], m.pcnt, m.s);
23737da2899SCharles.Forsyth}
23837da2899SCharles.Forsyth
23937da2899SCharles.Forsyth
24037da2899SCharles.Forsythr2s(r: Rect): string
24137da2899SCharles.Forsyth{
24237da2899SCharles.Forsyth	return sys->sprint("%d %d %d %d", r.min.x, r.min.y, r.max.x, r.max.y);
24337da2899SCharles.Forsyth}
24437da2899SCharles.Forsyth
24537da2899SCharles.Forsythwinpos(t: ref Tk->Toplevel): Point
24637da2899SCharles.Forsyth{
24737da2899SCharles.Forsyth	return (int tk->cmd(t, ". cget -actx"), int tk->cmd(t, ". cget -acty"));
24837da2899SCharles.Forsyth}
24937da2899SCharles.Forsyth
25037da2899SCharles.Forsythevhandle(t: ref Tk->Toplevel, wmctl: chan of string, evchan: chan of ref Event)
25137da2899SCharles.Forsyth{
25237da2899SCharles.Forsyth	for(;;) {
25337da2899SCharles.Forsyth		ev: ref Event = nil;
25437da2899SCharles.Forsyth		dismisspopup := 1;
25537da2899SCharles.Forsyth		alt {
25637da2899SCharles.Forsyth		s := <-gctl =>
25737da2899SCharles.Forsyth			(nil, l) := sys->tokenize(s, " ");
25837da2899SCharles.Forsyth			case hd l {
25937da2899SCharles.Forsyth			"focusout" =>
26037da2899SCharles.Forsyth				ev = ref Event.Elostfocus;
26137da2899SCharles.Forsyth			"b1p" or "b1r" or "b1d" or
26237da2899SCharles.Forsyth			"b2p" or "b2r" or "b2d" or
26337da2899SCharles.Forsyth			"b3p" or "b3r" or "b3d" or
26437da2899SCharles.Forsyth			"m" =>
26537da2899SCharles.Forsyth				l = tl l;
26637da2899SCharles.Forsyth				pt := Point(int hd l, int hd tl l);
26737da2899SCharles.Forsyth				pt = pt.sub(offset);
26837da2899SCharles.Forsyth				mtype := s2mtype(s);
26937da2899SCharles.Forsyth				dismisspopup = 0;
27037da2899SCharles.Forsyth				if(mtype == E->Mlbuttondown) {
27137da2899SCharles.Forsyth					tk->cmd(t, "focus .f");
27237da2899SCharles.Forsyth					pu := popup;
27337da2899SCharles.Forsyth					if (pu != nil && !pu.r.contains(pt))
27437da2899SCharles.Forsyth						dismisspopup = 1;
27537da2899SCharles.Forsyth					pu = nil;
27637da2899SCharles.Forsyth				}
27737da2899SCharles.Forsyth				ev = ref Event.Emouse(pt, mtype);
27837da2899SCharles.Forsyth			"k" =>
27937da2899SCharles.Forsyth				dismisspopup = 0;
28037da2899SCharles.Forsyth				k := int hd tl l;
28137da2899SCharles.Forsyth				if(k != 0)
28237da2899SCharles.Forsyth					ev = ref Event.Ekey(k);
28337da2899SCharles.Forsyth			"back" =>
28437da2899SCharles.Forsyth				ev = ref Event.Eback;
28537da2899SCharles.Forsyth			"stop" =>
28637da2899SCharles.Forsyth				ev = ref Event.Estop;
28737da2899SCharles.Forsyth			"fwd" =>
28837da2899SCharles.Forsyth				ev = ref Event.Efwd;
28937da2899SCharles.Forsyth			"go" =>
29037da2899SCharles.Forsyth				url := tk->cmd(tktop, ".ctlf.url get");
29137da2899SCharles.Forsyth				if (url != nil)
29237da2899SCharles.Forsyth					ev = ref Event.Ego(url, nil, 0, E->EGnormal);
29337da2899SCharles.Forsyth			"copyurl" =>
29437da2899SCharles.Forsyth				url := tk->cmd(tktop, ".ctlf.url get");
29537da2899SCharles.Forsyth				snarfput(url);
29637da2899SCharles.Forsyth			"pasteurl" =>
29737da2899SCharles.Forsyth				url := tk->quote(tkclient->snarfget());
29837da2899SCharles.Forsyth				tk->cmd(tktop, ".ctlf.url delete 0 end");
29937da2899SCharles.Forsyth				tk->cmd(tktop, ".ctlf.url insert end " + url);
30037da2899SCharles.Forsyth				tk->cmd(tktop, "update");
30137da2899SCharles.Forsyth			"snarfstatus" =>
30237da2899SCharles.Forsyth				url := tk->cmd(tktop, ".status.status cget -text");
30337da2899SCharles.Forsyth				tkclient->snarfput(url);
30437da2899SCharles.Forsyth			}
30537da2899SCharles.Forsyth		s := <-t.ctxt.ctl or
30637da2899SCharles.Forsyth		s = <-t.wreq or
30737da2899SCharles.Forsyth		s = <-wmctl =>
30837da2899SCharles.Forsyth			case s {
30937da2899SCharles.Forsyth			"exit" =>
31037da2899SCharles.Forsyth				hidewins();
31137da2899SCharles.Forsyth				ev = ref Event.Equit(0);
31237da2899SCharles.Forsyth			"task" =>
31337da2899SCharles.Forsyth				if (cancelpopup())
31437da2899SCharles.Forsyth					evchan <-= ref Event.Edismisspopup;
31537da2899SCharles.Forsyth				tkclient->wmctl(t, s);
31637da2899SCharles.Forsyth				if(tktop.image == nil)
31737da2899SCharles.Forsyth					realwin = nil;
31837da2899SCharles.Forsyth			"help" =>
31937da2899SCharles.Forsyth				ev = ref Event.Ego((CU->config).helpurl, nil, 0, E->EGnormal);
32037da2899SCharles.Forsyth			* =>
32137da2899SCharles.Forsyth				if (s[0] == '!' && cancelpopup())
32237da2899SCharles.Forsyth					evchan <-= ref Event.Edismisspopup;
32337da2899SCharles.Forsyth				oldimg := t.image;
32437da2899SCharles.Forsyth				e := tkclient->wmctl(t, s);
32537da2899SCharles.Forsyth				if(s[0] == '!' && e == nil){
32637da2899SCharles.Forsyth					if(t.image != oldimg){
32737da2899SCharles.Forsyth						oldimg = nil;
32837da2899SCharles.Forsyth						makewins();
32937da2899SCharles.Forsyth						ev = ref Event.Ereshape(mainwin.r);
33037da2899SCharles.Forsyth					}
33137da2899SCharles.Forsyth					offset = tk->rect(tktop, ".f", 0).min;
33237da2899SCharles.Forsyth				}
33337da2899SCharles.Forsyth			}
33437da2899SCharles.Forsyth		s := <-t.ctxt.kbd =>
33537da2899SCharles.Forsyth			tk->keyboard(t, s);
33637da2899SCharles.Forsyth		s := <-t.ctxt.ptr =>
33737da2899SCharles.Forsyth			tk->pointer(t, *s);
33837da2899SCharles.Forsyth		}
33937da2899SCharles.Forsyth		if (dismisspopup) {
34037da2899SCharles.Forsyth			if (cancelpopup()) {
34137da2899SCharles.Forsyth				evchan <-= ref Event.Edismisspopup;
34237da2899SCharles.Forsyth			}
34337da2899SCharles.Forsyth		}
34437da2899SCharles.Forsyth		if (ev != nil)
34537da2899SCharles.Forsyth			evchan <-= ev;
34637da2899SCharles.Forsyth	}
34737da2899SCharles.Forsyth}
34837da2899SCharles.Forsyth
34937da2899SCharles.Forsyths2mtype(s: string): int
35037da2899SCharles.Forsyth{
35137da2899SCharles.Forsyth	mtype := E->Mmove;
35237da2899SCharles.Forsyth	if(s[0] == 'm')
35337da2899SCharles.Forsyth		mtype = E->Mmove;
35437da2899SCharles.Forsyth	else {
35537da2899SCharles.Forsyth		case s[1] {
35637da2899SCharles.Forsyth		'1' =>
35737da2899SCharles.Forsyth			case s[2] {
35837da2899SCharles.Forsyth			'p' => mtype = E->Mlbuttondown;
35937da2899SCharles.Forsyth			'r' => mtype = E->Mlbuttonup;
36037da2899SCharles.Forsyth			'd' => mtype = E->Mldrag;
36137da2899SCharles.Forsyth			}
36237da2899SCharles.Forsyth		'2' =>
36337da2899SCharles.Forsyth			case s[2] {
36437da2899SCharles.Forsyth			'p' => mtype = E->Mmbuttondown;
36537da2899SCharles.Forsyth			'r' => mtype = E->Mmbuttonup;
36637da2899SCharles.Forsyth			'd' => mtype = E->Mmdrag;
36737da2899SCharles.Forsyth			}
36837da2899SCharles.Forsyth		'3' =>
36937da2899SCharles.Forsyth			case s[2] {
37037da2899SCharles.Forsyth			'p' => mtype = E->Mrbuttondown;
37137da2899SCharles.Forsyth			'r' => mtype = E->Mrbuttonup;
37237da2899SCharles.Forsyth			'd' => mtype = E->Mrdrag;
37337da2899SCharles.Forsyth			}
37437da2899SCharles.Forsyth		}
37537da2899SCharles.Forsyth	}
37637da2899SCharles.Forsyth	return mtype;
37737da2899SCharles.Forsyth}
37837da2899SCharles.Forsyth
37937da2899SCharles.Forsythmakewins()
38037da2899SCharles.Forsyth{
38137da2899SCharles.Forsyth	if(tktop.image == nil)
38237da2899SCharles.Forsyth		return;
38337da2899SCharles.Forsyth	screen := Screen.allocate(tktop.image, display.transparent, 0);
38437da2899SCharles.Forsyth	offset = tk->rect(tktop, ".f", 0).min;
38537da2899SCharles.Forsyth	r := tk->rect(tktop, ".f", Tk->Local);
38637da2899SCharles.Forsyth	realwin = screen.newwindow(r, D->Refnone, D->White);
38737da2899SCharles.Forsyth	realwin.origin(ZP, r.min);
38837da2899SCharles.Forsyth	if(realwin == nil)
389*54041ca4Sforsyth		raise sys->sprint("EXFatal: can't initialize windows: %r");
39037da2899SCharles.Forsyth
39137da2899SCharles.Forsyth	mainwin = display.newimage(realwin.r, realwin.chans, 0, D->White);
39237da2899SCharles.Forsyth	if(mainwin == nil)
393*54041ca4Sforsyth		raise sys->sprint("EXFatal: can't initialize windows: %r");
39437da2899SCharles.Forsyth}
39537da2899SCharles.Forsyth
39637da2899SCharles.Forsythhidewins()
39737da2899SCharles.Forsyth{
39837da2899SCharles.Forsyth	tk->cmd(tktop, ". unmap");
39937da2899SCharles.Forsyth}
40037da2899SCharles.Forsyth
40137da2899SCharles.Forsythsnarfput(s: string)
40237da2899SCharles.Forsyth{
40337da2899SCharles.Forsyth	tkclient->snarfput(s);
40437da2899SCharles.Forsyth}
40537da2899SCharles.Forsyth
40637da2899SCharles.Forsythsetstatus(s: string)
40737da2899SCharles.Forsyth{
40837da2899SCharles.Forsyth	tk->cmd(tktop, ".status.status configure -text " + tk->quote(s));
40937da2899SCharles.Forsyth	tk->cmd(tktop, "update");
41037da2899SCharles.Forsyth}
41137da2899SCharles.Forsyth
41237da2899SCharles.Forsythseturl(s: string)
41337da2899SCharles.Forsyth{
41437da2899SCharles.Forsyth	tk->cmd(tktop, ".ctlf.url delete 0 end");
41537da2899SCharles.Forsyth	tk->cmd(tktop, ".ctlf.url insert 0 " + tk->quote(s));
41637da2899SCharles.Forsyth	tk->cmd(tktop, "update");
41737da2899SCharles.Forsyth}
41837da2899SCharles.Forsyth
41937da2899SCharles.Forsythauth(realm: string): (int, string, string)
42037da2899SCharles.Forsyth{
42137da2899SCharles.Forsyth	user := prompt(realm + " username?", nil).t1;
42237da2899SCharles.Forsyth	passwd := prompt("password?", nil).t1;
42337da2899SCharles.Forsyth	if(user == nil)
42437da2899SCharles.Forsyth		return (0, nil, nil);
42537da2899SCharles.Forsyth	return (1, user, passwd);
42637da2899SCharles.Forsyth}
42737da2899SCharles.Forsyth
42837da2899SCharles.Forsythalert(msg: string)
42937da2899SCharles.Forsyth{
43037da2899SCharles.Forsythsys->print("ALERT:%s\n", msg);
43137da2899SCharles.Forsyth	return;
43237da2899SCharles.Forsyth}
43337da2899SCharles.Forsyth
43437da2899SCharles.Forsythconfirm(msg: string): int
43537da2899SCharles.Forsyth{
43637da2899SCharles.Forsythsys->print("CONFIRM:%s\n", msg);
43737da2899SCharles.Forsyth	return -1;
43837da2899SCharles.Forsyth}
43937da2899SCharles.Forsyth
44037da2899SCharles.Forsythprompt(msg, dflt: string): (int, string)
44137da2899SCharles.Forsyth{
44237da2899SCharles.Forsyth	if(dialog == nil){
44337da2899SCharles.Forsyth		dialog = load Dialog Dialog->PATH;
44437da2899SCharles.Forsyth		dialog->init();
44537da2899SCharles.Forsyth	}
44637da2899SCharles.Forsyth	return (1, dialog->getstring(drawctxt, mainwin, msg));
44737da2899SCharles.Forsyth	# return (-1, "");
44837da2899SCharles.Forsyth}
44937da2899SCharles.Forsyth
45037da2899SCharles.Forsythstopbutton(enable: int)
45137da2899SCharles.Forsyth{
45237da2899SCharles.Forsyth	state: string;
45337da2899SCharles.Forsyth	if (enable) {
45437da2899SCharles.Forsyth		tk->cmd(tktop, ".ctlf.stop configure -bg red -activebackground red -activeforeground white");
45537da2899SCharles.Forsyth		state = "normal";
45637da2899SCharles.Forsyth	} else {
45737da2899SCharles.Forsyth		tk->cmd(tktop, ".ctlf.stop configure -bg #dddddd");
45837da2899SCharles.Forsyth		state = "disabled";
45937da2899SCharles.Forsyth	}
46037da2899SCharles.Forsyth	tk->cmd(tktop, ".ctlf.stop configure -state " + state + ";update");
46137da2899SCharles.Forsyth}
46237da2899SCharles.Forsyth
46337da2899SCharles.Forsythbackbutton(enable: int)
46437da2899SCharles.Forsyth{
46537da2899SCharles.Forsyth	state: string;
46637da2899SCharles.Forsyth	if (enable) {
46737da2899SCharles.Forsyth		tk->cmd(tktop, ".ctlf.back configure -bg lime -activebackground lime -activeforeground red");
46837da2899SCharles.Forsyth		state = "normal";
46937da2899SCharles.Forsyth	} else {
47037da2899SCharles.Forsyth		tk->cmd(tktop, ".ctlf.back configure -bg #dddddd");
47137da2899SCharles.Forsyth		state = "disabled";
47237da2899SCharles.Forsyth	}
47337da2899SCharles.Forsyth	tk->cmd(tktop, ".ctlf.back configure -state " + state + ";update");
47437da2899SCharles.Forsyth}
47537da2899SCharles.Forsyth
47637da2899SCharles.Forsythfwdbutton(enable: int)
47737da2899SCharles.Forsyth{
47837da2899SCharles.Forsyth	state: string;
47937da2899SCharles.Forsyth	if (enable) {
48037da2899SCharles.Forsyth		tk->cmd(tktop, ".ctlf.fwd  configure -bg lime -activebackground lime -activeforeground red");
48137da2899SCharles.Forsyth		state = "normal";
48237da2899SCharles.Forsyth	} else {
48337da2899SCharles.Forsyth		tk->cmd(tktop, ".ctlf.fwd configure -bg #dddddd");
48437da2899SCharles.Forsyth		state = "disabled";
48537da2899SCharles.Forsyth	}
48637da2899SCharles.Forsyth	tk->cmd(tktop, ".ctlf.fwd configure -state " + state + ";update");
48737da2899SCharles.Forsyth}
48837da2899SCharles.Forsyth
48937da2899SCharles.Forsythflush(r: Rect)
49037da2899SCharles.Forsyth{
49137da2899SCharles.Forsyth	if(realwin != nil) {
49237da2899SCharles.Forsyth		oclipr := mainwin.clipr;
49337da2899SCharles.Forsyth		mainwin.clipr = r;
49437da2899SCharles.Forsyth		realwin.draw(r, mainwin, nil, r.min);
49537da2899SCharles.Forsyth		mainwin.clipr = oclipr;
49637da2899SCharles.Forsyth	}
49737da2899SCharles.Forsyth}
49837da2899SCharles.Forsyth
49937da2899SCharles.Forsythclientfocus()
50037da2899SCharles.Forsyth{
50137da2899SCharles.Forsyth	tk->cmd(tktop, "focus .f");
50237da2899SCharles.Forsyth	tk->cmd(tktop, "update");
50337da2899SCharles.Forsyth}
50437da2899SCharles.Forsyth
50537da2899SCharles.Forsythexitcharon()
50637da2899SCharles.Forsyth{
50737da2899SCharles.Forsyth	hidewins();
50837da2899SCharles.Forsyth	E->evchan <-= ref Event.Equit(0);
50937da2899SCharles.Forsyth}
51037da2899SCharles.Forsyth
51137da2899SCharles.Forsythgetpopup(r: Rect): ref Popup
51237da2899SCharles.Forsyth{
51337da2899SCharles.Forsyth	return nil;
51437da2899SCharles.Forsyth#	cancelpopup();
51537da2899SCharles.Forsyth##	img := screen.newwindow(r, D->White);
51637da2899SCharles.Forsyth#	img := display.newimage(r, screen.image.chans, 0, D->White);
51737da2899SCharles.Forsyth#	if (img == nil)
51837da2899SCharles.Forsyth#		return nil;
51937da2899SCharles.Forsyth#	winr := r.addpt(offset);	# race for offset
52037da2899SCharles.Forsyth#
52137da2899SCharles.Forsyth#	pos := "-x " + string winr.min.x + " -y " + string winr.min.y;
52237da2899SCharles.Forsyth#	(top, nil) := tkclient->toplevel(drawctxt, pos, nil, Tkclient->Plain);
52337da2899SCharles.Forsyth#	tk->namechan(top, gctl, "gctl");
52437da2899SCharles.Forsyth#	tk->cmd(top, "frame .f -bd 0 -bg white -width " + string r.dx() + " -height " + string r.dy());
52537da2899SCharles.Forsyth#	tkcmds(top, framebinds);
52637da2899SCharles.Forsyth#	tk->cmd(top, "pack .f; update");
52737da2899SCharles.Forsyth#	tkclient->onscreen(tktop, "onscreen");
52837da2899SCharles.Forsyth#	tkclient->startinput(tktop, "kbd"::"ptr"::nil);
52937da2899SCharles.Forsyth#	win := screen.newwindow(winr, D->Refbackup, D->White);
53037da2899SCharles.Forsyth#	if (win == nil)
53137da2899SCharles.Forsyth#		return nil;
53237da2899SCharles.Forsyth#	win.origin(r.min, winr.min);
53337da2899SCharles.Forsyth#
53437da2899SCharles.Forsyth#	popuptk = top;
53537da2899SCharles.Forsyth#	popup = ref Popup(r, img, win);
53637da2899SCharles.Forsyth## XXXX need to start a thread to feed mouse/kbd events from popup,
53737da2899SCharles.Forsyth## but we need to know when to tear it down.
53837da2899SCharles.Forsyth#	return popup;
53937da2899SCharles.Forsyth}
54037da2899SCharles.Forsyth
54137da2899SCharles.Forsythcancelpopup(): int
54237da2899SCharles.Forsyth{
54337da2899SCharles.Forsyth	popuptk = nil;
54437da2899SCharles.Forsyth	pu := popup;
54537da2899SCharles.Forsyth	if (pu == nil)
54637da2899SCharles.Forsyth		return 0;
54737da2899SCharles.Forsyth	pu.image = nil;
54837da2899SCharles.Forsyth	pu.window = nil;
54937da2899SCharles.Forsyth	pu = nil;
55037da2899SCharles.Forsyth	popup = nil;
55137da2899SCharles.Forsyth	return 1;
55237da2899SCharles.Forsyth}
55337da2899SCharles.Forsyth
55437da2899SCharles.ForsythPopup.flush(p: self ref Popup, r: Rect)
55537da2899SCharles.Forsyth{
55637da2899SCharles.Forsyth	win := p.window;
55737da2899SCharles.Forsyth	img := p.image;
55837da2899SCharles.Forsyth	if (win != nil && img != nil)
55937da2899SCharles.Forsyth		win.draw(r, img, nil, r.min);
56037da2899SCharles.Forsyth}
561