For writing your Tcl scripts, I suggest the fine code editor Alpha. The official home page for Alpha is: Alpha . Alpha has always had a good Tcl editing mode, and the 7.0 version has incorporated many of Vince Darley's improvements which has made it even better. Plus, once you know a little Tcl, you can hack at Alpha as well!
For building your own extensions, currently only CodeWarrior is supported. I suggest getting one of the Pro varieties, since the IDE is significantly improved, and the ANSI C libraries are better.
proc tkOpenDocument {args} { foreach elem $args { puts {Ow! Quit It} } }
There are some dangers to this approach, however. If you double-click on one script to start it up, and then double-click on another, the second script will get sourced into the context of the first script, which may not be what you want.
You can partially solve this problem by creating a new interpreter for each script you source in, and sourcing the script in that interpreter. This is not as easy as it seems, however, since you have to be sure to load Tk into the new interpreter, and mask the exit command so that one script doesn't kill another... It is probably a better idea to use the "Drag & Drop Tclets" application to create Double-Clickable Tcl applications. After all, the Wish shell is only 80k...
Look at the project file in the example_tcl_extension to see how to configure CodeWarrior to build the shared library. Look at the last bit of the example.r file to see how to put in a pkgIndex file so you can use the "package require" command to load your library. Look at the example.c file to see how to write the _Init routine that will be run when your library is loaded.
Tcl_StaticPackage(interp,"Foo",Foo_Init, Foo_SafeInit);
to the Plug_Init function which is in nptcl.c.
load {} Foo
in your Tclet code somewhere.
%file attributes "Wish 8.0p2" -creator WIsH -hidden 0 -readonly 0 -type APPL
The same command will allow you to set the creator or type:
% file attributes "foo.html" -creator "MOSS"
will make the file foo.html a Netscape file.
menu .mbar -tearoff 0 . configure -menu .mbar
This menu is displayed in the Main Macintosh menubar whenever the toplevel that owns it (in this example .) is in the foreground.
.mbar add cascade -label File -menu .mbar.file menu .mbar.file -tearoff 0 .mbar.file add command -label New -accelerator Command-N -command "NewDoc" .mbar.file add command -label Open... -accelerator Command-O -command "OpenFile" .mbar.file add command -label Close -accelerator Command-W -command "CloseDoc" .mbar.file add separator .mbar.file add command -label Save -accelerator Command-S -command "SaveDoc" .mbar.file add command -label "Save As..." -command "SaveDocAs" .mbar.file add separator .mbar.file add command -label Quit -accelerator Command-Q -command exit
toplevel .top
then ".top" will display the same menubar as ".". If later on, you make a new menubar for .top, and then create a child of .top thusly:
.top configure -menu .top.mbar toplevel .top.child
Then . will have its original menubar, and .top AND .top.child will share the menubar given by .top.mbar.
.mbar add cascade -menu .mbar.apple
Then all the menu entries that you add to .mbar.apple will appear under the Apple Menu pulldown, above the separator bar that holds the DRVR entries.
To install entries in the help menu, create a cascade entry whose menu is .mbar.help:
.mbar add cascade -menu .mbar.help
and the entries in this menu will appear below the separator that follows the "Show Balloons" entry.
menu .mbar -tearoff 0 .mbar add cascade -menu .mbar.file -label File .mbar add cascade -menu .mbar.edit -label Edit menu .mbar.edit -tearoff 0 .mbar.edit add command -label Cut -accel Command-X -command { event generate [focus] <<Cut>> } .mbar.edit add command -label Copy -accel Command-C -command { event generate [focus] <<Copy>> } .mbar.edit add command -label Paste -accel Command-V -command { event generate [focus] <<Paste>> } .mbar.edit add command -label Clear -command { event generate [focus] <<Clear>> }
toplevel .t1; unsupported1 style .t1 floatProc
The available styles are: documentProc, dBoxProc, plainDBox, altDBoxProc, movableDBoxProc, zoomDocProc, rDocProc, floatProc, floatZoomProc, floatSideProc, or floatSideZoomProc.
NB at present Tk does not properly support floating windows. They are the REAL foreground window so you cannot have a palette AND a document window concurrently active. This will be fixed in a future release.
toplevel .t1; wm overrideredirect .t1 1
NB. The second part of the example (the wm blahblahblah part) has to be run BEFORE the window is mapped.
wm protocol . WM_DELETE_WINDOW { puts foo }
This will write foo to the console every time the user clicks in the close box. Note that if you intercept the click in the close box, Tk will no longer delete the window for you. There is no problem with keeping the window around, but if you want to get rid of it, you must do:
wm protocol . WM_DELETE_WINDOW { doCleanup; destroy .}
#------------------------------------------------------------------- # readStrList -- # # Read the STR# resource in resource specified in args, which contains # a resource specification (name or id) and optionally a resource file # token. # # Result: # A list of the strings found # #------------------------------------------------------------------- proc readStrList {args} { if {[llength $args] == 1} { set strList [resource read "STR#" [lindex $args 0]] } elseif {[llength $args] == 2} { set strList [resource read "STR#" [lindex $args 0] [lindex $args 1]] } else { error "Wrong # of args, should be \"resource ?resourceFile?\"" } binary scan $strList S numStrs if {$numStrs == 0} { return } set pointer 2 for {set i 0} {$i < $numStrs} {incr i} { binary scan $strList x${pointer}c numChars set $numChars [expr ( $numChars + 0x100 ) % 0x100] incr pointer binary scan $strList x${pointer}a$numChars string lappend result $string incr pointer $numChars } return $result }
To find out the binary format of a resource, just look it up in the .r files in the Apple Rez headers.
NB Adding cursors will introduce a System specific code to your app. The Mac version of Tk does not support the "@filename maskname" syntax for cursor specification that Unix does.
% beep -list {Simple Beep} Sosumi {Wild Eep} Indigo Droplet Quack Basil {Bend Me} {Blue Dust} Bye! Dewdrop Jacaranda Natal {Ryan's Hope} Sheet Solly Transvaal {16-bit Geiger} Stravinsky-short {8-bit Jaaazzz Beep} {16-bit Molitov}
and play a sound using:
% beep {16-bit Geiger}
You can even set the volume with:
%beep -volume 0x01000100 {16-bit Geiger}
where the -volume is the low and high words of a long, corresponding to the right and left speaker volumes. 0x0100 is full on, 0x000 is off.
button .b1 -bitmap myIncrediblyNeatIcon
Note that you are cheating a bit here, since you can use cicn's, which will be rendered in color, although traditionally bitmaps are two-tone. However, the -foreground and -background options will do weird things in this case. It is best to leave them unset.
NB. You CANNOT use these ICON and cicn items in the bitmap image type. So for now, if you want to use an ICON or cicn resource on a canvas, you need to make a label widget, put the bitmap on that, and embed the label in the canvas.
tell application "Wish 8.0p2" to do script "puts Hello"
package require Tclapplescript
After you have loaded the Tclapplescript package, you can use the AppleScript command to execute scripts, for instance:
button .b1 -text "Launch Navigator" -command { AppleScript execute { open application "Netscape Navigator 4.03" } }
For more information see the AppleScript.html page in the tcl8.0 folder of the HTML Docs.
set myScript [AppleScript load myAppleScriptFile] button .b1 -text "Run Script" -command [list AppleScript run $myScript]
You can install your shared libraries here. If your shared library registers a package, then you can also put a TEXT resource named "pkgIndex" in the file to register the package, and it will be found by Tcl. See the pkgindex resource in the Tclapplescript.shlb library for an example.
As for your scripts, you have three choices.
package ifneeded myPkg 1.0 [list source -rsrc myPkg.tcl]
Note that you should also have a package ifneeded statement for the shared library as well. See the package.n.html doc in the Tcl8.0 folder of the HTML Docs for more details.
source -rsrc HelperScript.tcl
As of Tcl8.0, the autoloading mechanism does not support the resource fork of applications, so you have to source the files in by hand.
Seriously, the Tcl Feather is free for you to use. Some nice GIF versions of it ship in tk8.0:library:images folder in the source distribution. The more visibility Tcl has, the more we can justify expending resources developing it.
bind all <Control-Option-ButtonPress> {console show}
For instance, if your installer puts all the tcl script files for your project in some location on the hard drive, you can then define an environment variable MY_SCRIPT_FOLDER, and add this to Tcl's auto_path with:
if {[info exists env(MY_SCRIPT_FOLDER)]} { lappend auto_path $env(MY_SCRIPT_FOLDER) }
That way, Wish will find all your files.
On the Macintosh, this is not always necessary, since you can put the scripts right in the resource fork of the application. However, if you have a large number of scripts that are used in many applications, this still might be a useful model.
So, how do you set the env array on the Macintosh. Simple... There is a resource of type STR# and name "Tcl Environment Variables" in the Wish application. To define a new environment variable, just add another string to this list. The form of the string is
ENVIRONMENT_VARIABLE_NAME=value
Next time you start up Wish, there will be an entry in env, so you get:
%set env(ENVIRONMENT_VARIABLE_NAME) value
Since you can edit resources in Tcl using a combination of the resource and binary commands, you can add these resources from Tcl,. So you could write a Tcl -based installer that would set up the environment variables for the installation!
% parray tcl_platform tcl_platform(byteOrder) = bigEndian tcl_platform(machine) = ppc tcl_platform(os) = MacOS tcl_platform(osVersion) = 8.0 tcl_platform(platform) = macintosh
The second way is to dispatch your own ButtonPress-2,3 events, with something like:
bind all <Control-ButtonPress-1> {event generate %W <ButtonPress-2> \ -x %x -y %y -rootx %X -rooty %Y -button 2 -time %t}
You do have to populate all the detail fields of the event that you are likely to use in your bindings, as this example demonstrates.
The other is that for radiobuttons and checkbuttons, in MacTk8.0p2 you can also not set the background behind the text for the button. This is possible, and is available in the patch file: MacTk-8.0-appearancePatch.sit.hqx. This is just a source patch, you have to rebuild MacTk to use the changes. NB, if you adopt this patch, then the trick of turning off the System-wide Platinum Appearance will no longer work.
This is really a bug; it makes more sense to use the -highlightbackground color for these few pixels. After all, on UNIX, if you set a background on a containing frame, you have to set the -highlightbackground to the frame's background color or you will get these ugly light grey rings around most of your widgets...
This will be fixed in a future version.
For now, it is probably better to use plain "update" on the Mac, since otherwise the user cannot even put your application in the background. The only down side with update is that button presses et.c will be processed, so you have to disable the buttons that you don't want activated.
set menu [tk_optionMenu .m foo DELETE] pack .m $menu entryconfigure 0 -command "after idle {destroy .m}"