This is patch7 for Wafe 0.96. It contains: o All changes included in patch 1 to patch 6 (see wafe-0.96.p1.README, wafe-0.96.p2.README, wafe-0.96.p3.README, wafe-0.96.p4.README, wafe-0.96.p5.README and wafe-0.96.p6.README) o Mosaic 2.1 HTML-widget (instead of Mosaic 2.0) o Some fixes for the XmGraph widget (deletion of arcs caused troubles) o Support for OSF/Motif 1.2 Drag and Drop (needs Motif 1.2 to compile, Motif 1.2 features will only be used when MOTIF12 was specified in the Imakefile); see below o Alternative ways to reference widgets in Wafe applications (Widget IDs); see below o Percent-code %W is substituted by Widget IDs in actions and callback procedures o New/changed X Toolkit commands: + installAccelerators + installAllAccelerators These commands can be used to bind events occuring in one widget (destinationWidget) to actions occuring in another widget (sourceWidget). For this purpose an translations table (a resource named 'accelerators') has to be installed (via sV) in the sourceWidget before installAccelerators (or installAllAccelerators) is issued. installAccelerator installs the accelerators from sourceWidget to targetWidget. installAllAccelerator installs all accelerators from sourceWidget and its descendants targetWidget Note: Earlier versions of Wafe used a version of installAccelerators with three arguments (where the last argument was the acceleration table). The new verison conforms now exactly to the Xt manuals. The accelerators can be cenveniantly specifies using resource mechanisms (mergeResources or defaults files). If your applications need backward compatibility, add the following script to Wafe's tcllib: rename InstallAccelerators newInstallAccelerators proc installAccelerators {source dest accelerators} { sV $source accelerators $accelerators newInstallAccelerators $dest $source } o More sample scripts: m-dnd-simple simple Motif 1.2 drag and drop example m-dnd-slider a slightly more sophisticated Motif 1.2 drag and drop example m-event an event tester for mofe demonstrating percent codes in actions accelerator.tcl a sample script using accelerators o more library files: widget.tcl uniform interface for generic widget related commands; see below o code cleanup + some fixes ("wafe --f" caused a SEGV) + some cleanup and performance improvements + better portability (the new version is supposed to compile without -lucb under Solaris) Motif 1.2 Drag-and-Drop: ======================== Generally speaking, drag-and-drop allows to pick up some information on the screen, move it around, and let it drop into another place. Source and target might be in the same application or a different one. The following features are only available, when Wafe is compiled with Motif 1.2. For older Motif versions or the Athena version of Wafe, please use rdd-style drag and drop. Motif 1.2 supports special - drag-over-effects (the cursor and its color can vary depending on whether it is located over an valid or invalid drop site), - drag-under-effects (the widget under the cursor can change its appearance when the drag cursor is within its scope), and - drop-effects (successful or unsuccessful drags are visualized) In addition to the usual DRAG_COPY operation (an information is grabbed on one place and copied to another one) Motif 1.2 drag-and-drop supports DRAG_MOVE (like DRAG_COPY, but the source information is removed) and DRAG_LINK (currently not supported from the Wafe interface (since not to well documented)) The following commands are available in Wafe (mofe) when it is compiled with Motif 1.2: XmDragStart XmDropSiteRegister XmDropSiteUpdate XmDropSiteUnregister XmDropSiteStartUpdate XmDropSiteEndUpdate XmDropTransferStart Motif drag-and-drop creates the following widget/objects dynamically there is no need to create these `by hand': XmDropSiteManager XmDragContext XmDropTransfer The sample scripts m-dnd-simple m-dnd-slider demonstrate some of the above featurs. In addition they contain a short documentation (much more compact then the 60(!) pages in the Motif 1.2 programmers guide). Widget IDs: =========== Widget IDs are unique identifiers for widgets which can be used instead of widget paths. Widget IDs are conveniant in at least 3 circumstances: (1) Up to now a reference to a widget was always a name, or more precisely a widget path; a formulation like Form f topLevel Command a f Command b f fromHoriz a is interpreted by Wafe as Form f topLevel Command a *f Command b *f fromHoriz *a "*f" and "*a" are widget references in form of widget paths, "f", "a" and "b" are widget names. The last line could be written as well as Command b *f fromHoriz f.a or Command b *f fromHoriz *f.a The name lookup (to obtain the widget pointer from the widget path) is performed in Wafe for all these cases by the Xt Instrinsic function XtName(). Problem: If there are multiple widgets named "a" in an application it is possible, that the wrong instance is looked up. To circumvent this problem a widget path (such as f.a) should be specified. However, if widgets with the same name are children of the same composite widget instance, they cannot be distinguished. Solution: use unique widget names (good advice in general, necessary under the same composite widget) or widgetIds (see below). (2) There is however a more subtle problem with widget identification over name lookup (using XtName()) in connection with dynamic creation and destroying of widgets: If the command "destroyWidget" is issued, the widget is not necessarily immediately destroyed, but at "a later time when it is save to destroy it" - typically after causing event is processed. If there is for example a callback routine, which destroys a widget (widget tree) and creates a new widget with the same name, references to the new widget might be resolved as references to the old instance. See the following example: Form f topLevel Command a f callback destroyAndCreate realize TransientShell t a Command b t proc destroyAndCreate {} { puts " destroying .. [isWidget t]" destroyWidget t TransientShell t a Command b1 t puts " new widget .. [isWidget t]" addTimeOut 0 {puts "NEWEVENT: new widget .. [isWidget t]"} } If the script above is executed and the "a" button is pressed, the following is produced. destroying .. 537782824 new widget .. 537782824 NEWEVENT: new widget .. 537784136 Please note that the last two lines indicate, that the name t refers to two different instances of the widget. addTimeOut generates a new event, the specified tcl command refers to the new instance. The two lines above addTimeOut refer to the 'old' instance of the widget, which destroyal has been triggered. This means that in "Command b1 t" a widget of the Command widget class is added to the old "t", which is doomed to be destroyed an instance later. The new widget "t" will have no children. A possible solution in all Wafe versions is to break up the callback routine into two parts, where the first destroys and triggers the second part, which in turn creates the new widgets. I have done this in a few applications. Another solution is to use widgetIds in such situations. (3) A OSF/Motif only problem: OSF/Motif creates frequently by itself widgets for which it creates its own names. Suppose a scrolled list widget is created in a mofe application: XmRowColumn rc topLevel XmScrolledList mylist rc parent mylist #R: {mylistSW} gV mylistSW children #R: {ListvScrollBar mylist } actually the widget tree has the form topLevel rc mylistSW ListvScrollBar mylist The problem comes here from the fact that Motif inserts a new widget (here: "mylistSW") ABOVE of the widget which was specified (here: "mylist"). In cases where we would like to create our "own" widget "mylistSW" as in XmPushButton mylistSW rc the names or widget paths are not sufficient to distinguish beween Motif's mylistSW and our widget with the same name. Starting with Wafe version 0.96p7 widgetIds are returned whenever a new widget instance is created. This Id can be used in all places where widget paths are used. If an Id is invalid a similar error message as for invalid widget paths is issued. A user should treat widget IDs as opaque quantities and never use it in expressions other than == or !=. The widgetId 0 stands for "not existing". The example with the TransientShell from above can be written now as (the lines marked with "*" are changed): Form f topLevel Command a f callback destroyAndCreate realize TransientShell t a proc destroyAndCreate {} { puts " destroying .. [isWidget t]" destroyWidget t * set id [TransientShell t a] * Command b1 $id * puts " new widget .. $id" addTimeOut 0 {puts "NEWEVENT: new widget .. [isWidget t]"} * addTimeOut 0 "popup $id none" } The output is now as expected: destroying .. 537782888 * new widget .. 537787576 NEWEVENT: new widget .. 537787576 Whenever the name resolution is ambiguous widgetIds should be used. In action and callback functions %W is substituted by the widgetId (%w by the widget name). The function [widgetName $widgetReference] returns the widgetName, [widgetId $widgetReference] returns the widgetId. Some Wafe commands returning currently widget names will be changed to return widgetIds or will get counterparts returning IDs. Widget IDs and widget names CANNOT be intermixed in a widget path. In order to implement this, it would be necessary to reimplement part if XtName. I don't think that this is necessary. widget.tcl ========== Since the Wafe functionality follows closely the Xt funtionality, there are a variety of commands that have various argument patters originated from c-argument passing and sometime complicated names. For example for the abstract concept "widget", we can query its name, its class, its resource names, its children, its popup children, whether it exists, and so on. In once case we have to use [gV ...] to get the answer, in most cases the result is returned as a result of a function, in one case in a variable (Wafe is following the Xt argument conventions). I have to admit, it is not easy to remember all names, especially if you are a infrequent Wafe user. In Tcl there is the neat idea of a major and minor command, where the major command names an abstract object and the minor command an operation. For example for the abstract object string there is a [string length ...], [string match ..], [string trim ....] etc., and and if you don't remember the right command, use "string -help" and you get in the error message the list of valid minor commands. Other examples are [file MINOR ...] or [info MINOR ...]. The library widget.tcl implements a similar major/minor approach using "widget" as major command. The library defines the following commands ($w is always a widget reference, i.e. a widget path or a widgetId): [widget name $w] ...... returns name of widget $w if it exists, "" otherwise [widget id $w] ...... returns the widget ID of $w if it exists, 0 otherwise [widget exists $w] ...... returns non-zero if $w exists, 0 otherwise [widget class $w] ...... returns the class of $w, if $w exists, an error otherwise [widget resourceNames $w] returns the list of resource names of $w, if $w exists, an error otherwise [widget path $w] ...... returns the widget path $w (up to the topLevel) if it exists, an error otherwise [widget parent $w] ...... returns the widget ID of the parent of $w if $w exists, an error otherwise [widget children $w] .... returns the list of children of $w in form of widget IDs if $w exists, an error otherwise [widget popupChildren $w] returns the list of popup children of $w as widget IDs if $w exists, an error otherwise [widget allChildren $w] returns the list of children and popup children of $w if $w exists, an error otherwise The major command "widget" is implemented in Tcl and will be loaded via autoload. INSTALLATION OF THIS PATCH ========================== To apply this patch, "cd" to the wafe 0.96 directory, expand the tar file, and do a "rm -f ../libhtmlw/*.a src/htmlwGen.o; make". If the XmGraph widget is configured in Imakefile, make cd $WAFE/XmGraph make libgraph.a before the 'make' in $WAFE/src Please note that in cases where you have 0.96 not installed, you should a) first get the wafe 0.96 distribution, expand the tar file, expand the wafeapps.tar.gz tar file as indicated in wafe/INSTALL, and b) expand this update 'over' the 0.96 distribution, and follow then the instructions in wafe/INSTALL -gustaf