[comp.sources.x] v11i013: wcl - Widget Creation Library, Part01/35

david@devvax.Jpl.Nasa.Gov (David E. Smyth) (02/01/91)

Submitted-by: david@devvax.Jpl.Nasa.Gov (David E. Smyth)
Posting-number: Volume 11, Issue 13
Archive-name: wcl/part01

The Widget Creation Library allows user interfaces to be completely
defined within a resource file: the widget heirarchy, widget types, and
bindings of widget callback lists and translations to application
functions are specified in the resource file using Wc* resources.

#! /bin/sh

# Make a new directory for the wc sources, cd to it, and run kits 1
# thru 35 through sh.  When all 35 kits have been run, read README.

echo "This is wc 1.05 kit 1 (of 35).  If kit 1 is complete, the line"
echo '"'"End of kit 1 (of 35)"'" will echo at the end.'
echo ""
export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
mkdir Doc 2>/dev/null
echo Extracting Doc/3rdREADME
sed >Doc/3rdREADME <<'!STUFFY!FUNK!' -e 's/X//'
XWidget Creation Resources
X-------------------------
X
XThe Widget Creation Library allows user interfaces to be completely
Xdefined within a resource file: the widget heirarchy, widget types, and
Xbindings of widget callback lists and translations to application
Xfunctions are specified in the resource file using Wc* resources.
X
XThe following is the complete set of resources which are
Xinterpreted by the Widget Creation Library:
X
X     ...widget.wcResFile:      resourceFileName
X     ...widget.wcClass:        classPointerName
X     ...widget.wcClassName:    className
X     ...widget.wcConstructor:  constructorFunctionName
X     ...widget.wcTrace:        true/false (default = false)
X     ...widget.wcCallback:     callback1(args), callback2(args), ...
X     ...widget.wcPopups:       popupChildName1, popupChildName2, ...
X     ...widget.wcChildren:     childName1, childName2, ...
X     ...widget.wcManaged:      true/false (default = true)
X
XIn all cases, the Widget Creation resource names can be specified as
XWc<name> or wc<name>, with the capitalized form having looser binding
X(representing the resource class).
X
XWcResFile Resource
X------------------
X
XThis resource allows you to put additional resource specifications
Xrelated to a widget or its children in a separate file.  Like all
Xwidget creation resources, the WcResFile resource value is retrieved
Xfrom the Xrm database at widget creation time.
X
XBefore the widget is created, the specified resource file is loaded
Xinto the Xrm database, and then another query of the Xrm database is
Xmade to obtain the other Wc resources.  Therefore, all wc resources
X(except of course the WcResFile resource) and other widget resources
Xmay be specified in the new resource file.  
X
XWcClass, WcClassName, and WcConstructor Resources
X-------------------------------------------------
X
XThese resources allow you to specify the type of the widget.  Only one
Xof these resources should be specified for each widget.  
X
XWcTrace Resource
X----------------
X
XThis resource is useful for debugging your user interface.  When `True'
Xthe full name and class name of the widget is printed to stderr right
Xafter the widget is created.
X
XWcCallback Resource
X-------------------
X
XThis resource allows you to specify a list of callback functions
Xwhich are invoked after the widget is created, and before it is
Xmanaged.  The callback functions receive the newly created widget as
Xtheir widget argument, and whatever is within the parenthesis following
Xthe callback function name as a string argument as client data.  For
Xexample:
X
X	*foo.wcCallback:	FooSpecialCB( Hi there )
X
XThis specification will cause the function `FooSpecialCB' to be
Xcalled.  The widget argument will be the newly created widget foo, and
Xthe client_data argument will be the null terminated character array "
XHi there ".  The call_data is whatever was specified when the
XFooSpecialCB callback function was registered with
XWcRegisterCallback().
X
XThis is generally how the interface can create related objects within
Xthe application.  For example, if your application has a storage
Xobject, each widget which provides storage related behaviors or
Xattribute displays might register themselves with your application's
Xstorage object.
X
XWcPopups and WcChildren Resource
X--------------------------------
X
XAfter a widget is created, but before it is managed, all of its
Xchildren are created: first the pop-up children, and then the normal
Xchildren.  Only composite widgets can have normal children, but any
Xwidget can have pop-up children.   The names of children widgets are
Xspecified by the WcPopups and WcChildren resources.  The order of the
Xnames in the resource value indicate the left-to-right order of widget
Xcreation.  The names of the widgets in the example below imply the
Xorder of creation:
X
X	*foo.wcPopups:		ONE, TWO
X	*foo.wcChildren:	THREE, FOUR, FIVE
X
XEach widget creation is recursive, the widgets are created depth
Xfirst.  I.e., the widget `ONE' and all of ONE's children will be
Xcreated before widget `TWO' will be created.
X
XWcManaged Resource
X------------------
X
XThis resource only applies to widgets specified in WcChildren resource
Xspecifications.  WcManaged allows you to specify that a child of a
Xcomposite widget should not be managed following its creation.  By
Xdefault, widgets specified with WcChildren are managed together with
Xtheir siblings after all siblings are created.  Wc uses a single call
Xto XtManageChildren when possible.
X
X
XHow the Application Interacts with the Widget Creation Library 
X--------------------------------------------------------------
X
XThe typical Wc client application (including Ari and Mri) will create
Xan application shell and load the Xrm database by calling
XXtInitialize().  It will then register widgets, callbacks, and actions
Xwith the Wc library, and then pass the application shell to the
XWcWidgetCreation() function.  This function returns when the entire
Xconnected widget heirarchy specified in the Xrm database is created.
XThe widget tree is realized, and then the XtMainLoop is entered.
XBriefly:
X
X	appShell = XtInitialize( ... );
X
X	/* Register widgets, callbacks, and actions */
X
X	WcWidgetCreation( appShell );
X	XtRealizeWidget( appShell );
X	XtMainLoop();
X
XWhen Resources are Loaded Into the Xrm Database
X-----------------------------------------------
X
XXtInitialize loads an initial set of resource files into the resource
Xdatabase before any widgets are created.  This initial database may
Xcontain references to other resource files by way of WcResFile resource
Xspecifications.  If a widget `Foo' has a resource specification like
Xthis:
X
X    *Foo.wcResFile:	FooResources
X
Xthen the resource file named FooResources will be merged into the
Xresource database before the widget Foo is created.  In fact, several
Xfiles named FooResources may be loaded, as the standard Xt resource
Xfile search and load is performed.  See section 2.2 and 11.11 of the
XX11R4 Xt Intrinsics - C Language Interface manual for more
Xinformation.
X
X
XWhen Resources are Retrieved from the Xrm Database
X--------------------------------------------------
X
XResources are retrieved from the Xrm resource database when widgets are
Xcreated.  If the resource database changes after widget `Foo' is
Xcreated, subsequent changes to the database will have absolutely no
Xeffect upon widget `Foo.'
X
XHow Widgets Are Created from the Xrm Database
X---------------------------------------------
X
XThe Widget Creation Library starts creating widgets when the
XWcWidgetCreation() function is called.  Here is the recursive
Xscenario.  The initial widget is usually the application shell:
X
X    1.	Fetch the wcChildren resource from Xrm database for the
X	initial widget.  This will be a list of widget names.
X
X    2.	For each child: 
X
X    3.	Fetch the set of Wc resources.  
X
X    3a.	If wcResFile is specified, load that resource file and 
X	fetch the Wc resources again.
X
X    3b.	Using the wcClass, wcClassName, or wcConstructor resource, 
X	create the new child widget.  Widget creation uses other 
X	resources defined in the Xrm database specific to the type 
X	of the widget, such as labelString for XmLabels.
X
X    3c. Re-fetch the Wc* resources to obtain resources which may
X	apply due to the class of the created widget.
X
X    3d.	If wcCallback resource is defined (specifying a list of
X	callback functions), invoke each callback in order.  
X
X    3e. If wcTrace is True, then dump the name of the just created
X	widget to stdout.
X
X    3f.	If wcManaged is True (the default), then this widget will be
X	managed along with all of its siblings, after they are all
X	created (a single call to XtManageChildren is invoked by Wc).
X
X    3f. If the newly created widget has wcPopups or wcChildren specified, 
X	then recursively invoke step (2.) above.  Note that this
X	implements a depth first creation policy, which is generally
X	optimal for widget trees with manager widget nodes.
X
X
XThe resource files themselves have no explicit flow of control
Xmechanisms.  However, the order of events during widget creation causes
Xthe resources to be evaluated in a deterministic and sometimes
Xrepetitive pattern.
X
XThe most significant control over resource evaluation is the order that
Xwidgets are created.  Widget creation is ordered by the order of widget
Xnames in wcPopups and wcChildren resource lists.  The names of widgets in the
Xexample below reflects the order these widgets will be created.  The
Xorder of the resource specifications themselves are irrelevent to the
Xorder of creation:
X
X	Mri.wcChildren:			one, four
X	Mri.one.wcClassName:		XmRowColumn
X	Mri.one.wcChildren:		two, three
X	Mri.one.two.wcClassName:	XmLabel
X	Mri.one.three.wcClassName:	XmPushButton
X	Mri.four.wcConstructor:		XmCreateWorkingDialog
X
XWidgets can also be created after the initial widget tree.  For example,
Xhelp dialogs may be dynamically created only when necessary, so an
Xexperienced user does not need to suffer the additional start-up time
Xof creating a large number of widgets which are not needed, nor is
Xmemory or swap space consumed by the unnecessary widgets.
X
XHere are resources which demonstrate how a help dialog could be created
Xdue to a button press.  In this case, the newly created widget will
Xbecome a child of the application shell (Mri if the resource file is
Xbeing interpreted by Mri).  The resources for the help dialog are
Xsegregated into another set of resource files which are named
X`HelpDialogResources.'  The standard Xt resource file search path is
Xused, so /usr/lib/X11/app-defaults/HelpDialogResources, ...,
X~/apps-defaults/HelpDialogResources, may be loaded into the Xrm
Xdatabase due to this one WcResFile specification:
X
X	/* in initial resource file: */
X	*helpButton.activateCallback:	WcCreatePopupsCB( Mri, helpDialog )
X	*helpDialog.wcResFile:		HelpDialogResources
X
X	/* in HelpDialogResources: */
X	*helpDialog.wcConstructor:	XmCreateMessageDialog
X	*helpDialog.messageLabel:	Some help message...
X	*helpDialog.okCallback:		WcDestroyCB( this )
X
XFrequently, you probably want such dialogs to remain once they are
Xcreated.  See the M5.Dialogs resource file for one way to do this.
X
XIn the above example, notice that the resources specified in the
XHelpDialogResources file are unknown to the Xrm database until an
Xattempt is made to create the helpDialog widget.
!STUFFY!FUNK!
echo Extracting Doc/1stREADME
sed >Doc/1stREADME <<'!STUFFY!FUNK!' -e 's/X//'
X                        Widget Creation Library,
X                       Motif Resource Interpreter,
X                      Athena Resource Interpreter:
X
X                An Easier Way to Develop Applications
X                    using Motif and Athena Widgets.
X
XWindow-based applications are notoriously difficult to program.  When
Xthe Macintosh was introduced in early 1984, Bill Gates projected that
X50% of Microsoft revenues would come from Mac application by October
X1984.  In reality, the first Mac applications were only beginning to be
Xshipped by that date.
X
XWhen Steve Jobs left Apple and developed the NeXT computer, the window
Xenvironment was specifically designed to support a WYSIWYG interface
Xbuilder.  NextStep and the NeXT IB were the results of this effort.
X
XThe X developers at MIT and DEC also needed an easy way to develop
Xwindowed applications.  Instead of developing a WYSIWYG tool like NeXT,
Xthey developed a toolkit where interfaces were specified using C code,
Xand could be significantly modified via `resource files' using a
Xminimum number of attribute specifications. They provided an instance
Xattribute inheritance mechanism to propogate attributes throughout an
Xinterface.  This allows such simple specification as the following to
Xalter every font in an interface:
X
X        *font: 9x15
X
XThe toolkit is called the Xt Intrinsics.  The windows, buttons, menus,
Xscrollbars, etc., are called Widgets.  The Athena Widgets are one set
Xof user interface objects built upon the Xt Intrinsics.  Motif is
Xanother set of widgets.
X
XAs time went on, developers of widget-based applications found the
Xresource files to be more and more useful.  For the fourth release of
Xthe X11 window system, many of the example programs evolved to the
Xpoint that only the raw behavior of the applications were specified in
XC, with most of the look and feel being specified using resource
Xfiles.
X
XAt the fourth annual X Technical Conference, several people pointed out
Xthat resource files could be used to specify everything about a widget
Xbased user interface, except the actual "tree" of widgets, their types,
Xand bindings of behaviors to the user interface widgets.  Could the
Xresource mechanism be enhanced to allow these to be specified as well?
X
XMartin Brunecky at Auto-Trol in Denver Colorado took up the challenge,
Xand posted a simple set of routines which he called WsXc, for "Window
XSystem: Xrm Creation."
X
XXrm stands for X Resource Manager, which is a heirarchical database for
Xkeeping arbitrary named data related to X window interfaces.  The Xt
XIntrinsics use Xrm for widget resources.  The basic idea of WsXc is to
Xsearch the Xrm database, starting at the root, and pull out resources
Xwhich describe the widget heirarchy and bindings to callback
Xfunctions.
X
XOver the next several months, WsXc was repackaged as Mri (Motif
XResource Interpreter), and then Ari (Athena Resource Interpreter), and
Xfinally generalized into the Widget Creation Library.  The result
Xprovides several significant benefits to the developer and the user:
X
X        o Rapid Prototyping: Arbitrarily complex widget interfaces
X                may be specified, and many common behaviors (pop-up,
X                change attributes, exit) can be specified for the
X                interface.
X
X        o Prototyping Environment is the Development Environment is
X                the Delivery Environment: There is no specific breaking
X                point between prototyping, developing, and tuning a
X                delivered program.
X
X        o Minimum Specifications: The Xrm and Xt Intrinsics instance
X                attribute inheritance mechanism is fully utilized, so
X                a minimum number of specifications can describe a
X                complete user interface.
X
X        o Extensible:  Adding new widget types and callback routines
X                is trivial.
X
X        o Widget Set Independent: The library itself is completely 
X		widget set independent.
X
X	o Mostly Widget Set Independent Applications:  Much of the
X		C code which provides the behavior of the application 
X		can be written in a widget set independent manner.
X                This allows an application to be written which supports
X                multiple look-and-feel definitions: Motif, OpenLook,
X                and Athena interfaces can all be front-ends to the
X                same underlying application.
X
X        o The user can make any change to the interface: Deeply nested
X                menus can be substituted for dialog boxes, or vice 
X		versa.  Any label or image can be altered, which 
X		supports internationalization.
X
XOne of the guiding principles was and is KISS.  This is intended to be
Xa very small library which provides very big gains in productivity for
Xprogrammers developing applications using the various widget sets based
Xon the Xt Intrinsics.  A large number of the total lines of code
Xprovide error messages.  The rest is quite straight forward.
X
X
XThe Widget Creation Library Distribution
X----------------------------------------
X
XThe distribution contains files which make up the Widget Creation
XLibrary, Ari (the Athena Resource Interpreter), Mri (the Motif Resource
XInterpreter), and Athena and Motif demos.
X
X
XAuthors
X-------
X
XMartin Brunecky at Auto-trol Technology, Denver (marbru@auto-trol.UUCP)
Xwrote the initial code and posted it to comp.windows.x with the title
XPOOR MAN's UIL - WsXc.
X
XDavid Harrison of the UC Berkeley Electronics Research Lab
X(davidh@ic.Berkeley.EDU or ...!ucbvax!ucbcad!davidh) wrote a very
Xuseful Table widget.  Kee Hinckley (nazgul@alphalpa.com) wrote a
Xversion of Table which works with Motif.  The Table widget, in both its
Xincarnations, is so good I've included it with this distribution.  It
Xis separately available from archive sites.  See TableHEARYE and
XTableFIRST for information on this widget.
X
XMany people helped alot by providing bug fixes, enhancements,
Xsuggestions, and just plain feedback.  There are many who helped,
Xincluding Andrew Peebles at MIPS, Randy Brown, Art Poley, Mike Yee of
XOSF, Richard Hesketh, and our own Kaleb Keithley.
X
XThe rest was done by me, and here is my standard .sig:
X
X-------------------------------------------------------------------------
XDavid Smyth				david@jpl-devvax.jpl.nasa.gov
XSenior Software Engineer,		seismo!cit-vax!jpl-devvax!david
XX and Object Guru.			(818)393-0983
XJet Propulsion Lab, M/S 230-103, 4800 Oak Grove Drive, Pasadena, CA 91109
X-------------------------------------------------------------------------
X
X
XMri and Ari Widget Resource Interpreters
X----------------------------------------
X
XTwo "interpreters" are provided which allow widget based user
Xinterfaces to be developed and to have a few useful behaviors.  These
Xinterpreters are intended to be useful for prototyping.
X
XAri is the Athena Resource Interpreter, and it knows about all the
XAthena widgets.  Mri is the Motif Resource Interpreter, and is knows
Xabout all the Motif widgets.  Both interpreters also know about the
Xvery useful Table widget, which is described in the files Table*.
X
XEach interpreter consists of a main() procedure, and a function which
Xregisters all the known widget types.  Mri consists of Mri.c and
XMriRegAll.c while Ari consists of Ari.c and AriRegAll.c.  The
Xregistration files are intended to be independent.
X
XIt is a simple task to build a single interpreter which knows about
Xevery widget on earth, but if you don't have shared libs, the resulting
Xexecutable is HUGE.
X
XSeveral resource files are provided for each of the interpreters.  They
Xare named A<nn>_<description> and M<nn>_<description>.  To try out the
Xinterpreters (after you build them), do the following:
X
X    % cd Ari
X    % alias se setenv XENVIRONMENT
X    % se A08_ClkLogo
X    % Ari
X    % cd ../Mri
X    % se M7_Periodic
X    % Mri
X
XThe resource files are intended to be tutorials, so they are heavily
Xcommented and they explore various topics you may find interesting.
X
XOnce an interface is prototyped using Mri or Ari, one can take the
XMri or Ari source files and makefiles and evolve them into applications.
X
X
XSample Applications
X-------------------
X
XThe program App is exactly one such example application.  The file
XAri.c was gradually modified as additional behaviors were defined,
Xregistered with the Wc library, and bound to the appropriate widgets
Xwithin the App01.All resource file.
X
XIf you look at App.c, you will notice that main() is very minimal.  The
Xapplication is really defined by its resource file (the look and feel)
Xand the callbacks (the behavior).  Notice that the callbacks use
Xseveral routines provided by the Wc library.  They will be introduced
Xin another README file.
X
XAfter you build App, you can try it out as follows:
X
X    % cd DemosAthena
X    % se App01.All
X    % App
X
XAnother sample application included with the distribution is MD, which
Xis built as two versions: MDathena and MDmotif.  The Motif version
Xcurrently does not work very well due buggy interactions between Motif
Xand the Intrinsics.  This application demonstrates how a single
Xapplication can support multiple display connections with multiple
Xwidget heirarchies.  These may be executed like this:
X
X    % se MD
X    % MDathena
X    % cd ../DemosMotif
X    % MDmotif
X
!STUFFY!FUNK!
echo Extracting Doc/4thREADME
sed >Doc/4thREADME <<'!STUFFY!FUNK!' -e 's/X//'
XWidget Creation Library Standard Callbacks
X------------------------------------------
X
XThe standard Wc callbacks are intended to map closely to existing Xt
Xfunctions.  They simply provide XtCallbackProc wrappers to many
Xcommonly used Xt functions.  These wrapper procs perform argument
Xparsing: e.g., converting strings to widgets using WcFullNameToWidget.
X
XBelow is a complete list of callbacks which are registered by Wc
Xwhenever you call WcWidgetCreation.  The "arguments" below are
Xprototypes of what one puts in a resouce file.  The terms mean:
X
X   parent       name of widget, full path or wildcarded.
X   child        name of child starting from the parent widget.
X   widget       see parent
X   resLHS       <widget path name>
X   resRHS       <any legal resource value>
X   resType	<any legal resource type, sich as Font or Pixel>
X
X    WcCreatePopupsCB     ( parent, child [, child] ... )
X    WcCreateChildrenCB   ( parent, child [, child] ... )
X    WcManageChildrenCB   ( parent, child [, child] ... )
X    WcUnmanageChildrenCB ( parent, child [, child] ... )
X
X    WcManageCB         ( widget [, widget] ... )
X    WcUnmanageCB       ( widget [, widget] ... )
X    WcDestroyCB        ( widget [, widget] ... )
X    WcSetSensitiveCB   ( widget [, widget] ... )
X    WcSetInsensitiveCB ( widget [, widget] ... )
X
X    WcPopupCB     ( widget )
X    WcPopupGrabCB ( widget )
X    WcPopdownCB   ( widget )
X    WcMapCB       ( widget )
X    WcUnmapCB     ( widget )
X
X    WcSetValueCB     ( resLHS: resRHS )
X    WcSetTypeValueCB ( resLHS: resType, resRHS )
X    
X    WcLoadResourceFileCB ( filename )
X    
X    WcSystemCB ( shell command line )
X    WcTraceCB  ( annotation )
X
X    WcExitCB ( exitValue )
X
XSee the file WcCallb.c for the implementations of all of these standard
Xcallbacks.  These callbacks are registered together in the function
XWcRegisterWcCallbacks() which is at the bottom of the same source
Xfile.  Clients of Wc do not have to invoke WcRegisterWcCallbacks()
Xdirectly, as it is called from WcWidgetCreation() in the WcCreate.c
Xsource file.
X
X
XWidget Naming in Callback Arguments
X-----------------------------------
X
XIn all of these callbacks, the function WcFullNameToWidget is invoked
Xto convert a string to a widget.  WcFullNameToWidget allows relative
Xwidget naming, relative to the widget which invoked the callback.  The
Xspecial characters are presented in examples below:
X
X    this	means: `the widget which invoked this callback'
X    ^foobar	means: `a sibling widget named foobar'
X    ~foobar	means: `a child of the shell ancestor named foobar'
X    ~^foobar	means: `a sibling of the shell ancestor named foobar'
X
XThe relative naming characters `^' and `~' are parsed left to right.
X
XIn addition, normal wildcarding works as expected - as long as the
Xfinal name component is a widget instance, and not a widget class
Xname.  For example:
X
X    *foobar
X    *Table*XmRowColumn*foobar
X
X
XWcCreatePopupsCB( parent, child [, child] ... )
XWcCreateChildrenCB( parent, child [, child] ... )
X-------------------------------------------------
X
XThese callbacks cause new widgets to be created.  The name of the parent
Xcan include wildcards, or can be a relative pathname from the widget
Xinvoking the callback.  The names of the children widgets must be
Xsingle widget names, not pathnames.  For example:
X
X    *danger.callback:  WcCreateChildrenCB( *Panel, EmergencyControls)
X
XIn this case, pressing a danger button creates a new tree of widgets
Xproviding emergency controls.  The new tree is rooted at the existing
XPanel widget.
X
X
XWcManageChildrenCB( parent, child [, child] ... )
X-------------------------------------------------
X
XThis callback manages multiple children of a single parent.  It is a
Xwrapper around XtManageChildren.  As with WcCreateChildrenCB, the
Xparent name can include wildcards, or can be a relative pathname from
Xthe widget invoking the callback.  The names of the children widgets
Xmust be single widget names, not pathnames.  For example:
X
X    *new.activateCallback:  WcManageChildrenCB( *foo, one, two, three )
X
X
XWcUnmanageChildrenCB( parent, child [, child] ... )
X---------------------------------------------------
X
XIdentical to WcManageChildrenCB, except that the child widgets are 
Xunmanaged rather than managed via a call to XtUnmanageChildren.
X
X
XWcManageCB( widget [, widget] ... )
X-----------------------------------
X
XThis callback takes a list of widget names, each of which
Xcan be wildcarded and/or relative widget pathname.  After
Xthe widget ID is resolved via the WcFullNameToWidget function,
Xthe widgets are managed using XtManageChild().
X
X
XWcUnmanageCB( widget [, widget] ... )
X-------------------------------------
X
XThis callback is identical to WcManageCB, except that the
Xwidgets are unmanaged using XtUnmanageChild().
X
X
XWcDestroyCB( widget [, widget] ... )
X------------------------------------
X
XThis callback allows widgets to be destroyed using XtDestroyWidget().
X
X
XWcSetSensitiveCB( widget [, widget] ... )
X-----------------------------------------
X
XThis callback invokes XtSetSensitive( TRUE ) on each of the
Xwidgets named by the argument.
X
X
XWcSetInsensitiveCB( widget [, widget] ... )
X-------------------------------------------
X
XThis callback is identical to WcSetSensitiveCB, but the widgets
Xare made insensitive.
X
X
XWcPopupCB( widget )
X-------------------
X
XThis callback invokes XtPopup() with the XtGrabKind set to
XXtGrabNonexclusive.  The widget must be a pop-up shell widget.
X
X
XWcPopupGrabCB( widget )
X-----------------------
X
XThis callback invokes XtPopup() with the XtGrabKind set to
XXtGrabExclusive.  The widget must be a pop-up shell widget.
X
X
XWcPopdownCB( widget )
X---------------------
X
XThis callback invokes XtPopdown().  The widget must be a pop-up shell
Xwidget.
X
XWcMapCB( widget )
X---------------------
X
XThis callback invokes XtMapWidget().  The widget must be a shell
Xwidget.
X
XWcUnmapCB( widget )
X---------------------
X
XThis callback invokes XtUnmapWidget().  The widget must be a shell
Xwidget.
X
X
XWcSetValueCB( resLHS: resRHS )
X------------------------------
X
XWcSetValueCB maps very closely to XtSetValues().  An augmented resource
Xfile syntax is accepted so you can cut and paste the arguments and
Xnames.  The widget path name can include wildcards, and it can also be
Xa relative path from the invoking widget.  Real examples:
X
X  *push.activateCallback: WcSetValueCB( *push.activateCallback: WcExitCB(1) ), \
X                          WcSetValueCB( *push.labelString:      Goodbye! )
X
X  *fileMenu.wcCallback:   WcSetValueCB(*file.subMenuId: this)
X
X  *Pink.armCallback:	  WcSetValueCB( ^^drawing.background: Pink )
X
XWcSetTypeValueCB( resLHS: resType, resRHS )
X-------------------------------------------
X
XDon't use this callback unless you absolutely MUST.  The only time you
Xneed to use this callback is when you are setting a sub-resource on a
Xwidget.  For example, if you want to set the font of an Athena or
XMotif text widget.  WcSetValueCB will just complain that the widget does 
Xnot have a Font resource.
X
XYou must specify the correct type of the resource.  Make an error, and you
Xwill very likely get a core dump.  Just like if you use XtSetValues.
X
XWcLoadResourceFileCB( filename )
X--------------------------------
X
XThis callback loads specified resource file into application resource
Xdatabase. It allows resources to be loaded on as-needed basis, reducing the
Xintitial resource file load overhead.  The file to load is specified as
Xclient data. The directory search for the file (should be) the same as
Xfor application class resource file.
X
XTo prevent repeated loads of the same file, the callback keeps track of
Xeach filename.  Note that I do not allow a file to be re-loaded even if
Xit is changed, or if a new file of the same name appears on the search
Xpath.  This was done for two reasons:  first, it makes the code more
Xportable, as I don't have to depend upon various system calls.  Second,
Xresources can't be un-written, so a user might get the wrong impression
Xthat a resource specification can be deleted, and the resource file
Xre-loaded, and something will happen.  It just isn't so.
X
X
XWcSystemCB( shell command line )
X--------------------------------
X
XThis callback passes the entire string argument to you standard shell
Xusing the system() C library function.  Append an ampersand if you want
Xthe shell to fork instead of blocking until complete.
X
X
XWcTraceCB( annotation )
X-----------------------
X
XThis callback can be used to assist in interface debugging. The
Xcallback prints the invoking wiget pathname and a specified message on
Xstdout.
X
X
XWcExitCB( exitValue )
X---------------------
X
XThis callback converts the argument string into a base 10 integer, and
Xpasses the result to exit(), which of course terminates the
Xapplication.
!STUFFY!FUNK!
echo Extracting Doc/6thREADME
sed >Doc/6thREADME <<'!STUFFY!FUNK!' -e 's/X//'
XWidget Creation Functions
X-------------------------
X
XThe widget creation Library provides several types of functions
Xwhich are called by client applictions:
X
X	1.	Registration Functions
X	2.	Creation Functions
X	3.	Callback Argument Parsing Utilities
X
XTwo include files are provided which declare the functions and
Xsupporting data types used by the Widget Creation Library.  Many
Xapplications should only need to include WcCreate.h which
Xcontains what can be considered "public" function declarations.
X
XIf you are writing additional resource converters, or sophisticated
Xcallbacks, you will probably want to include WcCreateP.h which contains
Xwhat can be considered "private" function declarations as well as
Xtypedefs for several datatypes used by the Widget Creation Library.
X
XWidget Set Registration Functions
X---------------------------------
X
XTwo non-library functions are also provided in separate files:
X
XMriRegAll.c contains the single function MriRegisterMotif().  This
Xfunction lets the Wc library know about all the Motif widget class
Xnames (like XmPushButtonGadget), class pointers (like
XxmPushButtonGadgetClass), and convenience constructors (like
XXmCreatePushButtonGadget).
X
XAriRegAll.c contains the single function AriRegisterAthena().  This
Xfunction lets the Wc library know about all the Athena widget class
Xnamed (like Command), and class pointers (like commandWidgetClass).
X
XWcWidgetCreation() - see WcCreate.c
X------------------
X
XThis function takes a Widget as its only argument.  A widget tree
Xrooted at the widget is created from the Xrm database.  This widget
Xis called the root widget in this discussion, but it can really be any
Xwidget.
X
XThe Xrm database is usually loaded as a matter of course by calling
XXtInitialize().  It is possible to load the resource database directly,
Xusing XrmGetFileDatabase() and XrmMergeDatabases().  See the function
XWcLoadResourceFileCB in the file WcCallb.c for an example.
X
XThe algorithm used by WcWidgetCreation is recursive, as follows:
X
X    1.  Fetch the wcChildren resource from Xrm database for the
X        initial widget.  This will be a list of widget names.
X
X    2.  For each child:
X
X    3.  Fetch the set of Wc resources.
X
X    3a. If wcResFile is specified, load that resource file and
X        fetch the Wc resources again.
X
X    3b. Using the wcClass, wcClassName, or wcConstructor resource,
X        create the new child widget.  Widget creation uses other
X        resources defined in the Xrm database specific to the type
X        of the widget, such as labelString for XmLabels.
X
X    3c. If wcCallback resource is defined (specifying a list of
X        callback functions), invoke each callback in order.
X
X    3d. If wcTrace is True, then dump the name of the just created
X        widget to stdout.
X
X    3e. If wcManaged is True (the default), then this widget will be
X        managed along with all of its siblings, after they are all
X        created (a single call to XtManageChildren is invoked by Wc).
X
X    3f. If the newly created widget has wcChildren specified, then
X        recursively invoke step (2.) above.  Note that this
X        implements a depth first creation policy, which is generally
X        optimal for widget trees with manager widget nodes.
X
XNote that WcWidgetCreation() does a depth first creation, and that
Xthe order of creation is controlled by the order of the names in the
XwcChildren resource.
X
XEarlier versions of Wc required bizarre contortions when using
Xconstructors in order to avoid toolkit warnings such as:
X
X    Xt Warning: not all widgets have same parent in XtManageChildren()
X
XYou don't need to worry about this anymore - this behavior was
Xconsidered a `bug' not a `feature' and therefore has been fixed.
X
X
XWcCreateNamedPopups()
XWcCreateNamedChildren() - see WcCreate.c
X----------------------
X
XThese functions create named children of a reference widget by invoking
Xthe same algorithm as WcWidgetCreation, except that only the specifically
Xnamed children are created, rather than all the children.
X
XRegistration Functions - see WcReg.c
X----------------------
X
XThe Widget Creation Library converts strings in the database, such as
X"XmCreateFileSelectionBox", into its needed types, such as constructors,
Xusing Xt converters.  These converters intrinsicly know nothing: they
Xmust be told what each string maps into.  The converters learn about
Xthe appropriate mappings via the registration functions:
X
X    WcRegisterCallback()
X    WcRegisterClassPtr()
X    WcRegisterClassName()
X    WcRegisterConstructor()
X    WcRegisterAction()
X
XBy default, these registration routines ignore attempts to re-register
Xa string-to-whatever mapping.  This is generally useful, in that it
Xhelps to catch duplicate and therefore unneeded invocations of the
Xregistration routines.
X
XIn some clients, there exists the need to override such registrations.
XFor example, interface builders built using the Widget Creation Library
Xand a C interpreter or a dynamic linking environment may allow a given
Xcallback name to refer to different functions as the application
Xevolves.  The following functions are provided to support these cases:
X
X    WcAllowDuplicateRegistration()
X    WcAllowDuplicateCallbackReg()
X    WcAllowDuplicateClassPtrReg()
X    WcAllowDuplicateClassNameReg()
X    WcAllowDuplicateConstructorReg()
X
XAn interface builder will probably call WcAllowDuplicateRegistration()
Xbefore any callbacks, classes, et al are registered.  It may also be
Xappropriate to first register all standard callbacks and widgets, and
Xthen call WcAllowDuplicateRegistration().
X
XWcRegisterCallback() - see WcReg.c
X--------------------
X
XProbably all of your useful applications will require your own
Xcallbacks.  These callbacks are registered with the Widget Creation
XLibrary's string-to-callback converter using WcRegisterCallback().
X
XIn fact, this function is used by Wc itself to register the standard Wc
Xsupplied callbacks, such as WcSetValueCB and WcExitCB.  See the
Xfunction WcRegisterWcCallbacks() at the end of WcCallb.c to see how
XWc uses this function internally.
X
XWcRegisterClassPtr() - see WcReg.c
X--------------------
X
XThis function is used to tell the Widget Creation Library about a
Xwidget class pointer which can be used within XtCreateWidget().  The
Xname of the widget class pointer is passed in as a string (for example,
X"xmPushButtonWidgetClass").  This string value can be provided as the
XwcClass resource value within a resource file.
X
XWcRegisterClassName() - see WcReg.c
X---------------------
X
XThis function is used to tell the Widget Creation Library about a
Xwidget class name.  The name is mapped to a widget class pointer which
Xcan be used within XtCreateWidget().  The name of the widget class  is
Xpassed in as a string (for example, "XmPushButton").  This string value
Xcan be provided as the wcClassName resource value within a resource
Xfile.
X
XWcRegisterConstructor()  - see WcReg.c
X-----------------------
X
XThis function is used to tell the Widget Creation Library about a
Xwidget constructor.  The name of the constructor is passed in as a
Xstring (for example, "XmCreatePushButton").  This string value can be
Xprovided as the wcConstructor resource value within a resource file.
X
XWcRegisterAction()  - see WcReg.c
X-----------------
X
XThis is a simple wrapper around XtAppAddActions().  If you are
Xregistering many actions, you probably should copy the function
XWcRegisterWcActions() in WcActions.c and make the obvious
Xmodifications rather than using this function.  This will help
Xperformance.
X
!STUFFY!FUNK!
echo Extracting Doc/7thREADME
sed >Doc/7thREADME <<'!STUFFY!FUNK!' -e 's/X//'
XWriting Callback Functions
X--------------------------
X
XYour application will consist of two fairly independent parts: the
Xresource file which describes the look and alot of the feel of the
Xapplication, and the callbacks which you write in C (of course,
Xyou can use languages other than C, but C is probably the easiest).
X
XIn order to bind the widgets created due to resource specifications
Xto your callbacks implemented in C, you need to write the callbacks
Xso they adhere to the standard Xt callback proc typedef, and you
Xneed to register your callbacks with the Widget Creation Library's
Xstring-to-callback converter.
X
XXtCallbackProc
X--------------
X
XAs defined by the XtIntrinsics, widget callback procedures must match
Xthis typedef:
X
Xtypedef void (*XtCallbackProc)(
X#if NeedFunctionPrototypes
X    Widget              /* widget */,
X    XtPointer           /* closure */,  /* data the application registered */
X    XtPointer           /* call_data */ /* callback specific data */
X#endif
X);
X
XHere is an example callback proc which does nothing with its
Xarguments:
X
Xvoid MyExitCB ( w, ignored, unused )
X    Widget      w;
X    caddr_t     ignored;
X    caddr_t     unused;
X{
X    exit();
X}
X
XYou must register this function with the Widget Creation Library
Xbefore creating any widgets which might want to bind to it.
XIn general, register your callbacks after calling XtInitialize()
Xand before calling WcCreateWidgets().  Here is an example of
Xhow you register a callback:
X
X#define RCALL( name, func ) WcRegisterCallback ( app, name, func, NULL )
X
X    RCALL( "MyExitCB", MyExitCB );
X
XAll registered callbacks can be bound to widget callback resources
Xwithin the resource database.  For example:
X
X    *foo.activateCallback: MyExitCB
X
XMost callbacks really want to do something with the data they
Xget as arguments.  The closure data, often called client data,
Xcan be specified as a string within the resource database.
XThe string is passed as the second argument.  For example:
X
Xvoid WcSystemCB ( w, shellCmdString, unused )
X    Widget      w;
X    char*       shellCmdString;
X    caddr_t     unused;
X{
X    system( shellCmdString );
X}
X
XNote that leading and trailing whitespace is now filtered out before
Xthe callback gets it.  For example, the resource specification:
X
X    *foo.activateCallback: WcSystemCB( echo Howdy )
X
Xpasses the string "echo Howdy" to the callback.  The resource 
Xspecification:
X
X    *foo.activateCallback: WcSystemCB( echo Howdy \
X				and hello thar)
X
Xpasses the string "echo Howdy \t\t\t\tand hello thar" (where `\t' means
Xthe tab character) to the callback.  Since the callbacks usually need
Xto parse these argument strings, several Widget Creation Library
Xfunctions are provided in the hope of making your life easier:
X
Xchar* WcCleanName( char* src, char* clean )
X-------------------------------------------
X
XThis takes two pointers to char as arguments.  The leading whitespace
Xcharacters from src are skipped, and then all characters up to but
Xnot including a whitespace are copied into the buffer pointed to by
Xclean.  Note the caller must provide storage for clean.  The function
Xreturns a pointer to the first whitespace following what got copied
Xto clean, so this function may be used in a loop.
X
XWidget WcFullNameToWidget ( Widget ref, char* name )
X----------------------------------------------------
X
XThis function uses the reference Widget for relative naming, and to
Xdetermine the widget tree for converting full pathnames to a widget.
XFor example, one may need to get the actual widget which is named by
X"*Foo*bar.glorp"  The ref widget is used to find the root of the widget
Xtree, and start the name search from there.
X
XThe last component MUST be a widget instance name, it cannot be a
Xwidget class name.
X
XAmbiguous names are resolved as done by XtNameToWidget() upon which
XWcFullNameToWidget() is derived.
X
XVery frequently, one gets a name from an argument list using
XWcCleanName() and then passes that name on to WcFullNameToWidget in
Xorder to manipulate that widget.  For example:
X
Xvoid MyPopupCB( w, name, unused )
X    Widget  w;
X    char*   name;
X    caddr_t unused;
X{
X    Widget widget;
X    char   clean[MAX_XRMNAME];
X
X    (void)WcCleanName ( name, cleanName );
X    widget = WcFullNameToWidget ( w, cleanName );
X
X    if (XtIsShell(widget))
X	 XtPopup  ( widget, XtGrabNonexclusive );
X}
X
XEfficiency Considerations
X-------------------------
X
XI know parsing string arguments on every callback invocation is not so
Xincredibly efficient.  When Motif runs on Xt release 4, then I will
Xre-write the string-to-widget converter so it caches the results, and
Xthen callbacks can invoke the caching converter.
X
XAlso, if you are very interested in performance for a real application
X(after you have fleshed out the interface using Ari or Mri), you
Xshould write additional callbacks which are more intelligent, and
Xdetect being called repeatedly from the same widget with the same
Xargument.
X
XYou may want to consider using the XrmQuark functions for keeping
Xtrack of strings as well.  XrmQuarks are effectively indexes into
Xa string symbol table kept by Xrm (part of Xlib).  Doing comparisions
Xand assingments using Quarks is substantially faster at run-time than
Xusing character strings.  XrmQuarkToString() and XrmStringToQuark()
Xare used to convert between Quarks and Strings.
!STUFFY!FUNK!
echo Extracting Doc/8thREADME
sed >Doc/8thREADME <<'!STUFFY!FUNK!' -e 's/X//'
XWcSetTypeValueCB
X----------------
X
XSomebody was reporting that they were having problems setting fonts on
Xtext widgets.  I happened to want to change fonts in an application I'm
Xdoing too.
X
XI tried using the WcSetValuesCB code which did not work, because the
Xfont on an XmText widget (and XawText too) is a sub-resource.  Since
XI try to make Wc a safe library (:^) I had always been checking the
Xappropraite resource type and then invoking the converter registered
Xby the widget.  The library did not need to know anything about the
Xwidgets, and core dumps were nicely avoided.
X
XUnfortunately, there is no way to query widgets for their sub-resources,
Xand therefore the Wcl library cannot know what resource type is required.
XAs we all know, widgets have a habit of dumping core when an inappropriate
Xtype is passed in to XtSetValue.  Well, I can't do anything about it for
Xthese sub resources!  If you specify something incorrectly in the resource
Xfile, it'll dump, exactly as when you do it in C code.
X
XAnyway, this is what now works using version 2.0 of Wcl:
X
XMri.wcChildren:			msgWindow
X
X*msgWindow.wcClassName:         XmText
X*msgWindow.wcPopups:            msgFontMenu
X*msgWindow.fontList:            -adobe-times-bold-i-normal--14-140-*
X*msgWindow.value:               Here is an XmText which has a popup menu
X*msgWindow.translations:   #augment \n\
X                <Btn3Down>: MriPopupACT( *msgFontMenu )
X
X*msgFontMenu.WcConstructor:     XmCreatePopupMenu
X*msgFontMenu.WcChildren:        msgFont1, msgFont2, msgFont3
X
X*msgFont1.wcConstructor:        XmCreateCascadeButton
X*msgFont1.labelString:          courier bold oblique 10
X*msgFont1.fontList:             -adobe-courier-bold-o-normal--10-100-*
X*msgFont1.activateCallback:     WcSetTypeValueCB( \
X                                    *msgWindow.fontList: FontList,\
X                                        -adobe-courier-bold-o-normal--10-100-* )
X*msgFont2.wcConstructor:        XmCreateCascadeButton
X*msgFont2.labelString:          helvetica bold oblique 18
X*msgFont2.fontList:             -adobe-helvetica-bold-o-normal--18-180-*
X*msgFont2.activateCallback:     WcSetTypeValueCB( \
X                                    *msgWindow.fontList: FontList,\
X                                        *-helvetica-bold-o-*--18-*)
X*msgFont3.wcConstructor:        XmCreateCascadeButton
X*msgFont3.labelString:          courier bold oblique 10
X*msgFont3.fontList:             -adobe-courier-bold-o-normal--34-240-*
X*msgFont3.activateCallback:     WcSetTypeValueCB(       \
X                                    *msgWindow*fontList: FontList:      \
X                                        -adobe-courier-bold-o-normal--34-240-* )
X
XNotes:  It just so happens that XmText does rationally allow augmentation
Xof its translations, so the translation specification:
X
X    *msgWindow.translations:   #augment \n\
X                <Btn3Down>: MriPopupACT( *msgFontMenu )
X
Xpredictably causes a pop-up menu to come up when Btn3 (the Menu button 
Xtypically) is pressed.
X
XNote that there is a new Wc resource defined: wcPopups.  This allows
Xpop-up children to be added to any widget, composite or primitive.
X
XNote that there is a new callback: WcSetTypeValueCB.  This callback requires
Xa resource type, which unfortunately must be specified as defined in the
Xwidget include files.  Xm.h, for example, has the following:
X
X	#define XmRFontList                "FontList"
X
XSo, since the XmText Output Resource Set has the following:
X
X	XmNfontList	XmCFontList	XmFontList	fixed	CSG
X
Xand we know ;^) that XmFontList has this special mapping to the define
XXmRFontList, we discover that the appropriate type to provide needs to
Xbe FontList.  Not Font, not font, not anything else.  Anything else
Xwill cause a core dump.  Just like in your C code.  Darn, I wish I
Xcould be more socially responsible, but that's life, folks!
X
!STUFFY!FUNK!
echo Extracting Doc/DocREADME
sed >Doc/DocREADME <<'!STUFFY!FUNK!' -e 's/X//'
XThis directory contains the documentation for the Widget Creation
XLibrary.  The files with .PS suffixes are postscript files which
Xcontain viewgraphs for a Wcl tutorial and a paper which is close to
Xbeing a reference or programmers manual.
X
XThe files with .doc suffixes are pure text files, and contain similar
Xinformation to that presented in the tutorial and paper.
X
XAlso, the Table widget is documented by a .doc file.
!STUFFY!FUNK!
echo Extracting Imakefile
sed >Imakefile <<'!STUFFY!FUNK!' -e 's/X//'
X#include "Wc.tmpl"
X
X#define IHaveSubdirs
X
X#if HaveAthenaWidgetSet
X  ATHENA_DIRS = Xp Ari DemosAthena
X#endif
X
X#if HaveMotifWidgetSet
X   MOTIF_DIRS = Xmp Mri DemosMotif
X#endif
X
X/*
X * It is absolutely essential that sub-directories with libraries
X * come before subdirectories which link against the libraries!
X */
X SUBDIRS = Wc $(ATHENA_DIRS) $(MOTIF_DIRS)
X
X/**/# "make all" builds the library and the applications without
X/**/# installing anything.  If you are using shared libraries, these
X/**/# applications will not work anywhere else!  
X/**/#
X#define PassTestFlags 'CDEBUGFLAGS=-I.. -L../Wc -L../Xp -L../Xmp $(CDEBUGFLAGS)'
X
XNamedTargetSubdirs(all,$(SUBDIRS),"making",PassTestFlags,all)
X
X
X/**/# "make install" first builds the library, then installs the library
X/**/# and includes, then builds all the applications.  We must do it
X/**/# like this so the applications point to the installed library
X/**/# when shared libs are used.
!STUFFY!FUNK!
echo Extracting patchlevel.h
sed >patchlevel.h <<'!STUFFY!FUNK!' -e 's/X//'
X#define PATCHLEVEL 5
!STUFFY!FUNK!
echo " "
echo "End of kit 1 (of 35)"
cat /dev/null >kit1isdone
run=''
config=''
for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35; do
    if test -f kit${iskit}isdone; then
	run="$run $iskit"
    else
	todo="$todo $iskit"
    fi
done
case $todo in
    '')
	echo "You have run all your kits.  Please read README."
	for combo in `find . -name '*:AA' -print`; do
	    if test -f "$combo"; then
		realfile=`echo $combo | sed 's/:AA$//'`
		cat $realfile:[A-Z][A-Z] >$realfile
		rm -rf $realfile:[A-Z][A-Z]
	    fi
	done
	rm -rf kit*isdone
	chmod ugo+x test*
	;;
    *)  echo "You have run$run."
	echo "You still need to run$todo."
	;;
esac
: Someone might mail this, so...
exit

--
dan
----------------------------------------------------
O'Reilly && Associates   argv@sun.com / argv@ora.com
Opinions expressed reflect those of the author only.