xref: /inferno-os/appl/lib/tcl_tk.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsythimplement TclLib;
2*37da2899SCharles.Forsyth
3*37da2899SCharles.Forsythinclude "sys.m";
4*37da2899SCharles.Forsyth	sys: Sys;
5*37da2899SCharles.Forsyth
6*37da2899SCharles.Forsythinclude "draw.m";
7*37da2899SCharles.Forsyth
8*37da2899SCharles.Forsythinclude "string.m";
9*37da2899SCharles.Forsyth	str : String;
10*37da2899SCharles.Forsyth
11*37da2899SCharles.Forsythinclude "tk.m";
12*37da2899SCharles.Forsyth	tk: Tk;
13*37da2899SCharles.Forsyth
14*37da2899SCharles.Forsythinclude	"tkclient.m";
15*37da2899SCharles.Forsyth	tkclient: Tkclient;
16*37da2899SCharles.Forsyth
17*37da2899SCharles.Forsythinclude "tcl.m";
18*37da2899SCharles.Forsyth
19*37da2899SCharles.Forsythinclude "tcllib.m";
20*37da2899SCharles.Forsyth
21*37da2899SCharles.Forsytherror,started : int;
22*37da2899SCharles.Forsythw_cfg := array[] of {
23*37da2899SCharles.Forsyth	"pack .Wm_t -side top -fill x",
24*37da2899SCharles.Forsyth	"update",
25*37da2899SCharles.Forsyth};
26*37da2899SCharles.Forsyth
27*37da2899SCharles.Forsythtclmod : ref Tcl_Core->TclData;
28*37da2899SCharles.Forsyth
29*37da2899SCharles.Forsythwindows := array[100] of (string, ref Tk->Toplevel, chan of string);
30*37da2899SCharles.Forsyth
31*37da2899SCharles.Forsythvalid_commands:= array[] of {
32*37da2899SCharles.Forsyth		"bind" , "bitmap" , "button" ,
33*37da2899SCharles.Forsyth		"canvas" , "checkbutton" , "destroy" ,
34*37da2899SCharles.Forsyth		"entry" , "focus", "frame" , "grab", "image" , "label" ,
35*37da2899SCharles.Forsyth		"listbox" ,"lower", "menu" , "menubutton" ,
36*37da2899SCharles.Forsyth		"pack" , "radiobutton" , "raise", "scale" ,
37*37da2899SCharles.Forsyth		"scrollbar" , "text" , "update" ,
38*37da2899SCharles.Forsyth		"toplevel" , "variable"
39*37da2899SCharles.Forsyth};
40*37da2899SCharles.Forsyth
41*37da2899SCharles.Forsythabout() : array of string {
42*37da2899SCharles.Forsyth	return valid_commands;
43*37da2899SCharles.Forsyth}
44*37da2899SCharles.Forsyth
45*37da2899SCharles.Forsythinit() : string {
46*37da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
47*37da2899SCharles.Forsyth	str = load String String->PATH;
48*37da2899SCharles.Forsyth	tk = load Tk Tk->PATH;
49*37da2899SCharles.Forsyth	tkclient = load Tkclient Tkclient->PATH;
50*37da2899SCharles.Forsyth	if (tkclient==nil || str==nil || tk==nil)
51*37da2899SCharles.Forsyth		return "Not Initialised";
52*37da2899SCharles.Forsyth	# set up Draw context
53*37da2899SCharles.Forsyth	tkclient->init();
54*37da2899SCharles.Forsyth	started=1;
55*37da2899SCharles.Forsyth	return nil;
56*37da2899SCharles.Forsyth}
57*37da2899SCharles.Forsyth
58*37da2899SCharles.Forsythexec(tcl : ref Tcl_Core->TclData,argv : array of string) : (int,string) {
59*37da2899SCharles.Forsyth	retval : string;
60*37da2899SCharles.Forsyth	retval="";
61*37da2899SCharles.Forsyth	han,whan : ref Tk->Toplevel;
62*37da2899SCharles.Forsyth	whan=nil;
63*37da2899SCharles.Forsyth	msg : string;
64*37da2899SCharles.Forsyth	c : chan of string;
65*37da2899SCharles.Forsyth	msg=nil;
66*37da2899SCharles.Forsyth	error=0;
67*37da2899SCharles.Forsyth	tclmod=tcl;
68*37da2899SCharles.Forsyth	if (!started)
69*37da2899SCharles.Forsyth		if (init()!=nil)
70*37da2899SCharles.Forsyth			return (1,"Can't Initialise TK");
71*37da2899SCharles.Forsyth	if (argv[0][0]!='.')
72*37da2899SCharles.Forsyth		case argv[0] {
73*37da2899SCharles.Forsyth			"destroy" =>
74*37da2899SCharles.Forsyth				for (j:=1;j<len argv;j++){
75*37da2899SCharles.Forsyth					(msg,han)=sweepthru(argv[j]);
76*37da2899SCharles.Forsyth					if (msg==nil){
77*37da2899SCharles.Forsyth						if (argv[j][0]=='.')
78*37da2899SCharles.Forsyth							argv[j]=argv[j][1:];
79*37da2899SCharles.Forsyth						for(i:=0;i<100;i++){
80*37da2899SCharles.Forsyth							(retval,nil,c)=windows[i];
81*37da2899SCharles.Forsyth							if (retval==argv[1]){
82*37da2899SCharles.Forsyth								c <-= "exit";
83*37da2899SCharles.Forsyth								break;
84*37da2899SCharles.Forsyth							}
85*37da2899SCharles.Forsyth						}
86*37da2899SCharles.Forsyth					}
87*37da2899SCharles.Forsyth					else
88*37da2899SCharles.Forsyth						msg=tkcmd(whan,"destroy "+msg);
89*37da2899SCharles.Forsyth				}
90*37da2899SCharles.Forsyth				return (error,msg);
91*37da2899SCharles.Forsyth			"bind" or "bitmap" or "button" or
92*37da2899SCharles.Forsyth			"canvas" or "checkbutton" or "entry" or
93*37da2899SCharles.Forsyth			"focus" or "frame" or "grab" or
94*37da2899SCharles.Forsyth			"image" or "label" or "listbox" or "lower" or
95*37da2899SCharles.Forsyth			"menu" or "menubutton" or "pack" or
96*37da2899SCharles.Forsyth			"radiobutton" or "raise" or "scale" or
97*37da2899SCharles.Forsyth			"scrollbar" or "text" or "update" or
98*37da2899SCharles.Forsyth			"variable" =>
99*37da2899SCharles.Forsyth					; # do nothing
100*37da2899SCharles.Forsyth			"toplevel" =>
101*37da2899SCharles.Forsyth				msg=do_toplevel(argv);
102*37da2899SCharles.Forsyth				return (error,msg);
103*37da2899SCharles.Forsyth			* =>
104*37da2899SCharles.Forsyth				return (0,"Unknown");
105*37da2899SCharles.Forsyth		}
106*37da2899SCharles.Forsyth	# so it's a tk-command ... replace any -command with
107*37da2899SCharles.Forsyth	# a send on the tcl channel.
108*37da2899SCharles.Forsyth	if (argv[0]=="bind")
109*37da2899SCharles.Forsyth		argv[3]="{send Tcl_Chan "+argv[3]+"}";
110*37da2899SCharles.Forsyth	for (i:=0;i<len argv;i++){
111*37da2899SCharles.Forsyth		(argv[i],han)=sweepthru(argv[i]);
112*37da2899SCharles.Forsyth		if (han!=nil) whan=han;
113*37da2899SCharles.Forsyth		if (argv[i]!="-tcl")
114*37da2899SCharles.Forsyth			retval+=argv[i];
115*37da2899SCharles.Forsyth		if (i+1<len argv &&
116*37da2899SCharles.Forsyth			(argv[i]=="-command" || argv[i]=="-yscrollcommand"
117*37da2899SCharles.Forsyth			|| argv[i]=="-tcl" || argv[i]=="-xscrollcommand"))
118*37da2899SCharles.Forsyth			argv[i+1]="{send Tcl_Chan "+argv[i+1]+"}";
119*37da2899SCharles.Forsyth		if (argv[i]!="-tcl")
120*37da2899SCharles.Forsyth			retval[len retval]=' ';
121*37da2899SCharles.Forsyth	}
122*37da2899SCharles.Forsyth	retval=retval[0:len retval -1];
123*37da2899SCharles.Forsyth	if (tclmod.debug==1)
124*37da2899SCharles.Forsyth		sys->print("Sending [%s] to tkcmd.\n",retval);
125*37da2899SCharles.Forsyth	msg=tkcmd(whan,retval);
126*37da2899SCharles.Forsyth	if (msg!="" && msg[0]=='!')
127*37da2899SCharles.Forsyth		error=1;
128*37da2899SCharles.Forsyth	return (error,msg);
129*37da2899SCharles.Forsyth}
130*37da2899SCharles.Forsyth
131*37da2899SCharles.Forsyth
132*37da2899SCharles.Forsythsweepthru(s: string) : (string,ref Tk->Toplevel) {
133*37da2899SCharles.Forsyth	han : ref Tk->Toplevel;
134*37da2899SCharles.Forsyth	ret : string;
135*37da2899SCharles.Forsyth	if (s=="" || s=="." || s[0]!='.')
136*37da2899SCharles.Forsyth		return (s,nil);
137*37da2899SCharles.Forsyth	(wname,rest):=str->splitl(s[1:],".");
138*37da2899SCharles.Forsyth	for (i:=0;i<len windows;i++){
139*37da2899SCharles.Forsyth		(ret,han,nil)=windows[i];
140*37da2899SCharles.Forsyth		if (ret==wname)
141*37da2899SCharles.Forsyth			break;
142*37da2899SCharles.Forsyth	}
143*37da2899SCharles.Forsyth	if (i==len windows)
144*37da2899SCharles.Forsyth		return (s,nil);
145*37da2899SCharles.Forsyth	return (rest,han);
146*37da2899SCharles.Forsyth}
147*37da2899SCharles.Forsyth
148*37da2899SCharles.Forsythdo_toplevel(argv : array of string): string
149*37da2899SCharles.Forsyth{
150*37da2899SCharles.Forsyth	name : string;
151*37da2899SCharles.Forsyth	whan : ref Tk->Toplevel;
152*37da2899SCharles.Forsyth	if (len argv!=2)
153*37da2899SCharles.Forsyth		return notify(1,"toplevel name");
154*37da2899SCharles.Forsyth	if (argv[1][0]=='.')
155*37da2899SCharles.Forsyth		argv[1]=argv[1][1:];
156*37da2899SCharles.Forsyth	for(i:=0;i<len windows;i++){
157*37da2899SCharles.Forsyth		(name,whan,nil)=windows[i];
158*37da2899SCharles.Forsyth		if(whan==nil || name==argv[1])
159*37da2899SCharles.Forsyth			break;
160*37da2899SCharles.Forsyth	}
161*37da2899SCharles.Forsyth	if (i==len windows)
162*37da2899SCharles.Forsyth		return notify(0,"Too many top level windows");
163*37da2899SCharles.Forsyth	if (name==argv[1])
164*37da2899SCharles.Forsyth		return notify(0,argv[1]+" is already a window name in use.");
165*37da2899SCharles.Forsyth
166*37da2899SCharles.Forsyth	(top, menubut) := tkclient->toplevel(tclmod.context, "", argv[1], Tkclient->Appl);
167*37da2899SCharles.Forsyth	whan = top;
168*37da2899SCharles.Forsyth
169*37da2899SCharles.Forsyth	windows[i]=(argv[1],whan,menubut);
170*37da2899SCharles.Forsyth	if (tclmod.debug==1)
171*37da2899SCharles.Forsyth		sys->print("creating window %d, name %s, handle %ux\n",i,argv[1],whan);
172*37da2899SCharles.Forsyth	cmd := chan of string;
173*37da2899SCharles.Forsyth	tk->namechan(whan, cmd, argv[1]);
174*37da2899SCharles.Forsyth	for(i=0; i<len w_cfg; i++)
175*37da2899SCharles.Forsyth		tk->cmd(whan, w_cfg[i]);
176*37da2899SCharles.Forsyth	tkclient->onscreen(whan, nil);
177*37da2899SCharles.Forsyth	tkclient->startinput(whan, "kbd"::"ptr"::nil);
178*37da2899SCharles.Forsyth	stop := chan of int;
179*37da2899SCharles.Forsyth	spawn tkclient->handler(whan, stop);
180*37da2899SCharles.Forsyth	spawn menulisten(whan,menubut, stop);
181*37da2899SCharles.Forsyth	return nil;
182*37da2899SCharles.Forsyth}
183*37da2899SCharles.Forsyth
184*37da2899SCharles.Forsyth
185*37da2899SCharles.Forsythmenulisten(t : ref Tk->Toplevel, menubut : chan of string, stop: chan of int) {
186*37da2899SCharles.Forsyth	for(;;) alt {
187*37da2899SCharles.Forsyth	menu := <-menubut =>
188*37da2899SCharles.Forsyth		if(menu == "exit"){
189*37da2899SCharles.Forsyth			for(i:=0;i<len windows;i++){
190*37da2899SCharles.Forsyth			(name,whan,nil):=windows[i];
191*37da2899SCharles.Forsyth				if(whan==t)
192*37da2899SCharles.Forsyth				break;
193*37da2899SCharles.Forsyth			}
194*37da2899SCharles.Forsyth			if (i!=len windows)
195*37da2899SCharles.Forsyth				windows[i]=("",nil,nil);
196*37da2899SCharles.Forsyth			stop <-= 1;
197*37da2899SCharles.Forsyth			exit;
198*37da2899SCharles.Forsyth		}
199*37da2899SCharles.Forsyth		tkclient->wmctl(t, menu);
200*37da2899SCharles.Forsyth	}
201*37da2899SCharles.Forsyth}
202*37da2899SCharles.Forsyth
203*37da2899SCharles.Forsythtkcmd(t : ref Tk->Toplevel, cmd: string): string {
204*37da2899SCharles.Forsyth	if (len cmd ==0 || tclmod.top==nil) return nil;
205*37da2899SCharles.Forsyth	if (t==nil){
206*37da2899SCharles.Forsyth		 t=tclmod.top;
207*37da2899SCharles.Forsyth		#sys->print("Sending to WishPad\n");
208*37da2899SCharles.Forsyth	}
209*37da2899SCharles.Forsyth	s := tk->cmd(t, cmd);
210*37da2899SCharles.Forsyth	tk->cmd(t,"update");
211*37da2899SCharles.Forsyth	return s;
212*37da2899SCharles.Forsyth}
213*37da2899SCharles.Forsyth
214*37da2899SCharles.Forsythnotify(num : int,s : string) : string {
215*37da2899SCharles.Forsyth	error=1;
216*37da2899SCharles.Forsyth	case num{
217*37da2899SCharles.Forsyth		1 =>
218*37da2899SCharles.Forsyth			return sys->sprint(
219*37da2899SCharles.Forsyth			"wrong # args: should be \"%s\"",s);
220*37da2899SCharles.Forsyth		* =>
221*37da2899SCharles.Forsyth			return s;
222*37da2899SCharles.Forsyth	}
223*37da2899SCharles.Forsyth}
224