implement TclLib; include "sys.m"; sys: Sys; include "draw.m"; include "string.m"; str : String; include "tk.m"; tk: Tk; include "tkclient.m"; tkclient: Tkclient; include "tcl.m"; include "tcllib.m"; error,started : int;w_cfg := array[] of { "pack .Wm_t -side top -fill x", "update",}; tclmod : ref Tcl_Core->TclData; windows := array[100] of (string, ref Tk->Toplevel, chan of string); valid_commands:= array[] of { "bind" , "bitmap" , "button" , "canvas" , "checkbutton" , "destroy" , "entry" , "focus", "frame" , "grab", "image" , "label" , "listbox" ,"lower", "menu" , "menubutton" , "pack" , "radiobutton" , "raise", "scale" , "scrollbar" , "text" , "update" , "toplevel" , "variable"}; about() : array of string { return valid_commands;} init() : string { sys = load Sys Sys->PATH; str = load String String->PATH; tk = load Tk Tk->PATH; tkclient = load Tkclient Tkclient->PATH; if (tkclient==nil || str==nil || tk==nil) return "Not Initialised"; # set up Draw context tkclient->init(); started=1; return nil;} exec(tcl : ref Tcl_Core->TclData,argv : array of string) : (int,string) { retval : string; retval=""; han,whan : ref Tk->Toplevel; whan=nil; msg : string; c : chan of string; msg=nil; error=0; tclmod=tcl; if (!started) if (init()!=nil) return (1,"Can't Initialise TK"); if (argv[0][0]!='.') case argv[0] { "destroy" => for (j:=1;j<len argv;j++){ (msg,han)=sweepthru(argv[j]); if (msg==nil){ if (argv[j][0]=='.') argv[j]=argv[j][1:]; for(i:=0;i<100;i++){ (retval,nil,c)=windows[i]; if (retval==argv[1]){ c <-= "exit"; break; } } } else msg=tkcmd(whan,"destroy "+msg); } return (error,msg); "bind" or "bitmap" or "button" or "canvas" or "checkbutton" or "entry" or "focus" or "frame" or "grab" or "image" or "label" or "listbox" or "lower" or "menu" or "menubutton" or "pack" or "radiobutton" or "raise" or "scale" or "scrollbar" or "text" or "update" or "variable" => ; # do nothing "toplevel" => msg=do_toplevel(argv); return (error,msg); * => return (0,"Unknown"); } # so it's a tk-command ... replace any -command with # a send on the tcl channel. if (argv[0]=="bind") argv[3]="{send Tcl_Chan "+argv[3]+"}"; for (i:=0;i<len argv;i++){ (argv[i],han)=sweepthru(argv[i]); if (han!=nil) whan=han; if (argv[i]!="-tcl") retval+=argv[i]; if (i+1<len argv && (argv[i]=="-command" || argv[i]=="-yscrollcommand" || argv[i]=="-tcl" || argv[i]=="-xscrollcommand")) argv[i+1]="{send Tcl_Chan "+argv[i+1]+"}"; if (argv[i]!="-tcl") retval[len retval]=' '; } retval=retval[0:len retval -1]; if (tclmod.debug==1) sys->print("Sending [%s] to tkcmd.\n",retval); msg=tkcmd(whan,retval); if (msg!="" && msg[0]=='!') error=1; return (error,msg);} sweepthru(s: string) : (string,ref Tk->Toplevel) { han : ref Tk->Toplevel; ret : string; if (s=="" || s=="." || s[0]!='.') return (s,nil); (wname,rest):=str->splitl(s[1:],"."); for (i:=0;i<len windows;i++){ (ret,han,nil)=windows[i]; if (ret==wname) break; } if (i==len windows) return (s,nil); return (rest,han);} do_toplevel(argv : array of string): string{ name : string; whan : ref Tk->Toplevel; if (len argv!=2) return notify(1,"toplevel name"); if (argv[1][0]=='.') argv[1]=argv[1][1:]; for(i:=0;i<len windows;i++){ (name,whan,nil)=windows[i]; if(whan==nil || name==argv[1]) break; } if (i==len windows) return notify(0,"Too many top level windows"); if (name==argv[1]) return notify(0,argv[1]+" is already a window name in use."); (top, menubut) := tkclient->toplevel(tclmod.context, "", argv[1], Tkclient->Appl); whan = top; windows[i]=(argv[1],whan,menubut); if (tclmod.debug==1) sys->print("creating window %d, name %s, handle %ux\n",i,argv[1],whan); cmd := chan of string; tk->namechan(whan, cmd, argv[1]); for(i=0; i<len w_cfg; i++) tk->cmd(whan, w_cfg[i]); tkclient->onscreen(whan, nil); tkclient->startinput(whan, "kbd"::"ptr"::nil); stop := chan of int; spawn tkclient->handler(whan, stop); spawn menulisten(whan,menubut, stop); return nil;} menulisten(t : ref Tk->Toplevel, menubut : chan of string, stop: chan of int) { for(;;) alt { menu := <-menubut => if(menu == "exit"){ for(i:=0;i<len windows;i++){ (name,whan,nil):=windows[i]; if(whan==t) break; } if (i!=len windows) windows[i]=("",nil,nil); stop <-= 1; exit; } tkclient->wmctl(t, menu); }} tkcmd(t : ref Tk->Toplevel, cmd: string): string { if (len cmd ==0 || tclmod.top==nil) return nil; if (t==nil){ t=tclmod.top; #sys->print("Sending to WishPad\n"); } s := tk->cmd(t, cmd); tk->cmd(t,"update"); return s;} notify(num : int,s : string) : string { error=1; case num{ 1 => return sys->sprint( "wrong # args: should be \"%s\"",s); * => return s; }}
implement TclLib;
include "sys.m";
sys: Sys;
include "draw.m";
include "string.m";
str : String;
include "tk.m";
tk: Tk;
include "tkclient.m";
tkclient: Tkclient;
include "tcl.m";
include "tcllib.m";
error,started : int;
w_cfg := array[] of {
"pack .Wm_t -side top -fill x",
"update",
};
tclmod : ref Tcl_Core->TclData;
windows := array[100] of (string, ref Tk->Toplevel, chan of string);
valid_commands:= array[] of {
"bind" , "bitmap" , "button" ,
"canvas" , "checkbutton" , "destroy" ,
"entry" , "focus", "frame" , "grab", "image" , "label" ,
"listbox" ,"lower", "menu" , "menubutton" ,
"pack" , "radiobutton" , "raise", "scale" ,
"scrollbar" , "text" , "update" ,
"toplevel" , "variable"
};
about() : array of string {
return valid_commands;
}
init() : string {
sys = load Sys Sys->PATH;
str = load String String->PATH;
tk = load Tk Tk->PATH;
tkclient = load Tkclient Tkclient->PATH;
if (tkclient==nil || str==nil || tk==nil)
return "Not Initialised";
# set up Draw context
tkclient->init();
started=1;
return nil;
}
exec(tcl : ref Tcl_Core->TclData,argv : array of string) : (int,string) {
retval : string;
retval="";
han,whan : ref Tk->Toplevel;
whan=nil;
msg : string;
c : chan of string;
msg=nil;
error=0;
tclmod=tcl;
if (!started)
if (init()!=nil)
return (1,"Can't Initialise TK");
if (argv[0][0]!='.')
case argv[0] {
"destroy" =>
for (j:=1;j<len argv;j++){
(msg,han)=sweepthru(argv[j]);
if (msg==nil){
if (argv[j][0]=='.')
argv[j]=argv[j][1:];
for(i:=0;i<100;i++){
(retval,nil,c)=windows[i];
if (retval==argv[1]){
c <-= "exit";
break;
}
}
}
else
msg=tkcmd(whan,"destroy "+msg);
}
return (error,msg);
"bind" or "bitmap" or "button" or
"canvas" or "checkbutton" or "entry" or
"focus" or "frame" or "grab" or
"image" or "label" or "listbox" or "lower" or
"menu" or "menubutton" or "pack" or
"radiobutton" or "raise" or "scale" or
"scrollbar" or "text" or "update" or
"variable" =>
; # do nothing
"toplevel" =>
msg=do_toplevel(argv);
return (error,msg);
* =>
return (0,"Unknown");
}
# so it's a tk-command ... replace any -command with
# a send on the tcl channel.
if (argv[0]=="bind")
argv[3]="{send Tcl_Chan "+argv[3]+"}";
for (i:=0;i<len argv;i++){
(argv[i],han)=sweepthru(argv[i]);
if (han!=nil) whan=han;
if (argv[i]!="-tcl")
retval+=argv[i];
if (i+1<len argv &&
(argv[i]=="-command" || argv[i]=="-yscrollcommand"
|| argv[i]=="-tcl" || argv[i]=="-xscrollcommand"))
argv[i+1]="{send Tcl_Chan "+argv[i+1]+"}";
if (argv[i]!="-tcl")
retval[len retval]=' ';
}
retval=retval[0:len retval -1];
if (tclmod.debug==1)
sys->print("Sending [%s] to tkcmd.\n",retval);
msg=tkcmd(whan,retval);
if (msg!="" && msg[0]=='!')
error=1;
return (error,msg);
}
sweepthru(s: string) : (string,ref Tk->Toplevel) {
han : ref Tk->Toplevel;
ret : string;
if (s=="" || s=="." || s[0]!='.')
return (s,nil);
(wname,rest):=str->splitl(s[1:],".");
for (i:=0;i<len windows;i++){
(ret,han,nil)=windows[i];
if (ret==wname)
break;
}
if (i==len windows)
return (s,nil);
return (rest,han);
}
do_toplevel(argv : array of string): string
{
name : string;
whan : ref Tk->Toplevel;
if (len argv!=2)
return notify(1,"toplevel name");
if (argv[1][0]=='.')
argv[1]=argv[1][1:];
for(i:=0;i<len windows;i++){
(name,whan,nil)=windows[i];
if(whan==nil || name==argv[1])
break;
}
if (i==len windows)
return notify(0,"Too many top level windows");
if (name==argv[1])
return notify(0,argv[1]+" is already a window name in use.");
(top, menubut) := tkclient->toplevel(tclmod.context, "", argv[1], Tkclient->Appl);
whan = top;
windows[i]=(argv[1],whan,menubut);
if (tclmod.debug==1)
sys->print("creating window %d, name %s, handle %ux\n",i,argv[1],whan);
cmd := chan of string;
tk->namechan(whan, cmd, argv[1]);
for(i=0; i<len w_cfg; i++)
tk->cmd(whan, w_cfg[i]);
tkclient->onscreen(whan, nil);
tkclient->startinput(whan, "kbd"::"ptr"::nil);
stop := chan of int;
spawn tkclient->handler(whan, stop);
spawn menulisten(whan,menubut, stop);
return nil;
}
menulisten(t : ref Tk->Toplevel, menubut : chan of string, stop: chan of int) {
for(;;) alt {
menu := <-menubut =>
if(menu == "exit"){
for(i:=0;i<len windows;i++){
(name,whan,nil):=windows[i];
if(whan==t)
break;
}
if (i!=len windows)
windows[i]=("",nil,nil);
stop <-= 1;
exit;
}
tkclient->wmctl(t, menu);
}
}
tkcmd(t : ref Tk->Toplevel, cmd: string): string {
if (len cmd ==0 || tclmod.top==nil) return nil;
if (t==nil){
t=tclmod.top;
#sys->print("Sending to WishPad\n");
}
s := tk->cmd(t, cmd);
tk->cmd(t,"update");
return s;
}
notify(num : int,s : string) : string {
error=1;
case num{
1 =>
return sys->sprint(
"wrong # args: should be \"%s\"",s);
* =>
return s;
}
}