ref: 3866717cbb020199d58171c1c0cdd7382a74ee82
dir: /appl/lib/tcl_tk.b/
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; } }