v06i039: WsXc - Poor man's UIL, Part01/01
Martin Brunecky
sunpeaks!auto-trol!marbru at Central
Wed Mar 21 20:29:34 AEST 1990
Submitted-by: sunpeaks!auto-trol!marbru at Central (Martin Brunecky)
Posting-number: Volume 6, Issue 39
Archive-name: wsxc/part01
WsXc - POOR MAN'S UIL
This posting contains WsXc, an Xt Intrinsic extension alowing to
specify the entire user interface within X resource database. A
HelloWorld example using Motif widgets is included. It is provided
on as-is basis, without any support or waranties, to gain feedback
about this approach of user interface definition.
CONTENTS:
o README Basic description of WsXc facility
This is neither a tutorial, nor a reference manual.For more details
about individual functions, plese refer to the source - it contains
detailed description of each function. I am sorry I can't provide
man pages nor Makefile, I just don't know how.
The following files contain the code, based on R3 Xt Intrinsics,
tested on SPARC, Ultrix/RISC and VAX/VMS. I assume compatibility
with R4, even though it has not been tested.
o WsCreateXrm.h defines available public functions
o WsCreateXrmFunc.c widget tree creation and control
o WsCvtStrToCallback.c string to callback resource convertor
The following is a demo application, using the code listed above,
and Motif (1.0). You can modify the code to use your favorite
widget set, and play with application resource files.
o HelloWorld.c sample application
o HelloWorldBasic basic X resource file, move to ~/HelloWorld
o HelloWorldMore an expanded X resource file
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: README WsCreateXrm.h WsCreateXrmFunc.c
# WsCvtStrToCallback.c HelloWorld.c HelloWorld_Basic HelloWorld_More
# Wrapped by marbru at auto-trol on Fri Mar 16 19:31:21 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(9584 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
X UIL or NOT to UIL ?
X
X A few weeks ago, comp.windows.x carried a discussion of the
X advantages and disadvantages of UIL. Some people suggested that UIL
X is essentially useless, that the X resource database is enough,
X while others have pointed out that there are things you cannot do
X with the database alone, such as definition of a widget tree,
X callbacks, compound strings etc.
X
X Prompted by this discussion, I have put together some code which, in
X my belief, extends the the X Resource Database so that an ENTIRE
X USER INTERFACE can be defined (and customized) within the database.
X This avoidins the need for multiple sources of user interface
X definition by replacing UIL. I am posting an overview of this "POOR
X MAN'S UIL" here to get some feedback.
X
X To start, let me present a simple example of an application-class X
X resource file for a Motif based HelloWorld:
X
X #
X # shell - an application shell, containing RowColumn organizer
X #
X HelloWorld.managed.child_0: box,xmRowColumn
X #
X # box - the main container, contains label and button
X #
X Helloworld.box.spacing: 8
X HelloWorld.box.managed.child_0: label,xmLabel
X HelloWorld.box.managed.child_1: button,xmPushButton
X #
X # label
X #
X HelloWorld.box.label.labelString: Hello, WORLD !
X #
X # button
X #
X HelloWorld.box.button.labelString: Push ME
X HelloWorld.box.button.activateCallback: push(Push again to EXIT)
X #
X
X Except for the top-level shell creation, there is NO widget creation
X code in my HelloWorld. The entire widget tree definition is shown
X above. For any widget, I can specify any number of children with
X all their resources, and all recursively. Callbacks are specified
X in a similar way, by passing a string argument as call data. Note
X the example is a starting point: It does NOT show all the
X functionality such as deffered subtree creation, manage/unmanage
X callbacks, etc...
X
X
X APPLICATION CODE IMPACT
X
X A runtime interpreter must be able to translate X resource database
X strings into widget classes (or widget creation routines), and
X callbacks. Even though some systems (VMS for example) allow dynamic
X binding, the current implementation uses registration routines:
X
X WsRegisterObjectClass ( app, "xmlabel", xmLabel );
X WsRegisterObjectClass ( app, "xmpushbutton", xmPushButton );
X WsRegisterConstructor ( app, "xmRowColumn", XmCreateRowColumn );
X
X WsRegisterCallback ( app, "push", pushCB, NULL );
X
X In environments supporting shareable images, all toolkit classes and
X constructors may be registered during toolkit initialization.
X
X To initiate creation of the widget tree from the definitions stored
X in the X resource database, an application must (either directly, or
X by means of a callback) invoke the routine:
X
X WsCreateXrmChildren ( widget );
X
X
X WIDGET TREE CREATION MECHANISM
X
X The WsCreateXrmChildren routine scans the X resource database for
X widget subresources in the following format:
X
X path...widget.[un]managed.child_n: name,class[,nonrecursive]
X
X For each such subresource, the routine creates a child as specified
X by the name and object class (or the creation routine -
X constructor). Creation recursively descends the widget tree, unless
X stopped by a non-composite widget/object or the "nonrecursive"
X option. The latter may be used to defer sub-tree creation, using a
X callback which invokes WsCreateXrmChildren (for example,
X WsCreateXrmChildrenCB).
X
X When a child is created, WsCreateXrmChildren checks the resource
X database for xrmCreateCallback resource for the child, and executes
X such callbacks if present. This mechanism allows the delivery of
X child's widget ID to other, already existing widgets (such as a
X Motif defaultButton resource in dialog boxes).
X
X
X CALLBACK STRING CONVERSION
X
X A string to callback converter is provided with the package. The
X converter builds an XtCallbackList using registered callback names.
X Any callback on the list may have an optional string argument. A
X pointer to the string is used as callback client data. If no
X argument (string) is provided, the default client data value
X provided at registration time is used. The callback resource
X specification in the X resource database has the following format:
X
X path...widget.callbackName: name[(args)][,name[(args)]]...
X
X where name is the callback name assigned by WsRegisterCallback, and
X args presents an arbitrary string.
X
X
X WIDGET TREE CONTROL CALLBACKS
X
X The package provides basic callbacks for widget tree control. The
X callbacks take a (list of) widget names as "client data". The
X widget name is qualified according to Xrm rules: box.label. The
X following is list of the provided callbacks:
X
X o CreateXrmChildrenCB ( widgetName, widgetname, ... )
X creates children of the named widgets as specified in the X
X resource database
X
X o ManageNamedChildrenCB ( widgetName, widgetName, ... )
X manages a (list of) named widget(s)
X
X o UnmanageNamedChildrenCB ( widgetName, widgetName, ... )
X unmanages a (list of) named widget(s).
X
X o SetWidgetResourceCB ( resourceName, widgetname, ... )
X sets the specified resource in a (list of) named widget(s) to
X the widget id of the widget invoking the callback.
X
X Consider the callbacks above as a starting point. More callbacks
X can be provided to control popup/popdown, to load additional
X resource files and much more.
X
X
X COMPARISON WITH UIL
X
X The X resource database user interface definition, here (for lack of
X better names) referred to as WsXc, performs essentialy the same
X function as UIL. A complete comparison with UIL can not be done
X without additional input. Here I try only to mention several
X important differences between UIL and WsXc.
X
X Implementation:
X A UIL application uses multiple user interface definition sources
X (application code, UIL file, compiled UID file and an X resource
X file). WsXc requires only application code and an X resource file,
X and the application code would be limited to callback functions.
X The UIL approach is based on a compiler generating intermediate code
X which is interpreted by Mrm at runtime. WsXc is purely a runtime
X interpreter.
X
X Performance:
X Since UIL uses pre-compiled, machine specific data, the widget tree
X creation could be faster than that for WsXc. However, even UIL
X widget creation accesses the X resource database for resources NOT
X explicitly specified by the UIL file. Since MOST resources are
X usually NOT explictly specified, the overhead depends more on the
X Xrm database volume, than on the widget creation method used.
X Preliminary experience with WsXc is favorable. However, final
X
X Page 4
X
X
X judgement requires much more experience than is currently available.
X
X Extensibility.
X Adding new widgets to UIL, even with the new Motif WML facility, is
X not an easy process. Adding new data types (resource representation
X types) to UIL is sometimes impossible. On the contarry, there is
X nothing special about adding additional widgets to WsXc. The same
X method also applies to adding new data types. The only requirement
X is the addition of a convertor from string to a particular data
X type.
X
X Syntax Checking:
X The UIL compiler can perform rigorous syntax checking for widget
X resources, thus assisting in user interface development. WsXc can
X not catch any syntax errors in resource pathname specification, such
X resources are simply ignored. However, errors in resource value
X specification can be caught by the resource converter. In addition,
X a simple tool that acquires a widget's resource list and performs X
X resource file syntax checking can be provided.
X
X Value Computations:
X The UIL compiler can compute the geometry of individual widgets
X using arbitrary arithmetic expressions. Geometry values in the X
X resource database can not, currently, contain expressions. But,
X since Xrm uses cpp, a string substitution could be applied. This
X limitation is a resource converter issue. A more intelligent string
X to integer converter could evaluate arithmetic expressions,
X including X resource database value substitution. Besides, geometry
X configuration should be left to the geometry manager widgets and not
X hardcoded.
X
X Resource Conversions:
X UIL supports resource conversions such as colors, pixelmaps and
X compound strings. Many of the conversions are performed at runtime,
X using resource converters, the same as WsXc. For some resources,
X such as Compound Strings, UIL compile time conversion provides some
X runtime savings. In addition, the current string to compound string
X resource converters are not intelligent enough to allow an unlimited
X compound string specification in an X resource file.
X
END_OF_FILE
if test 9584 -ne `wc -c <'README'`; then
echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'WsCreateXrm.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'WsCreateXrm.h'\"
else
echo shar: Extracting \"'WsCreateXrm.h'\" \(1153 characters\)
sed "s/^X//" >'WsCreateXrm.h' <<'END_OF_FILE'
X/*
X*******************************************************************************
X*
X* SCCS_data: %Z%%M% %I%(%G%)
X*
X* Include_name:
X*
X* WsCreateXrm.h
X*
X* Subsystem_group:
X*
X* Window System
X*
X* Related_keywords:
X*
X* Public Defines
X*
X* Include_description:
X*
X* Public defines for the Window System widget tree creation from
X* the Xrm database.
X*
X* Include_history:
X*
X* mm/dd/yy initials action
X* -------- -------- -------------------------------------------------------
X* 03/02/90 marbru created
X*
X*******************************************************************************
X*/
X#ifndef _WsCreateXrm_h
X#define _WsCreateXrm_h
X
X
X/* -- Widget constructor registration routine */
X
Xextern void WsRegisterObjectClass ();
Xextern void WsRegisterConstructor ();
Xextern void WsRegisterCallback ();
Xextern void WsRegisterXrmCallbacks();
X
X/* -- Widget creation routine */
X
Xextern void WsCreateXrmChildren ();
X
X/* -- Convenience callbacks */
X
Xextern void WsCreateXrmChildrenCB();
Xextern void WsManageNamedChildrenCB();
Xextern void WsUnmanageNamedChildrenCB();
Xextern void WsSetWidgetResourceCB();
X
X#endif /* _WsCreateXrm_h */
END_OF_FILE
if test 1153 -ne `wc -c <'WsCreateXrm.h'`; then
echo shar: \"'WsCreateXrm.h'\" unpacked with wrong size!
fi
# end of 'WsCreateXrm.h'
fi
if test -f 'WsCreateXrmFunc.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'WsCreateXrmFunc.c'\"
else
echo shar: Extracting \"'WsCreateXrmFunc.c'\" \(22340 characters\)
sed "s/^X//" >'WsCreateXrmFunc.c' <<'END_OF_FILE'
X/*
X*******************************************************************************
X*
X* SCCS_data: %Z%%M% %I%(%G%)
X*
X* Module_name:
X*
X* WsCreateXrmFunc.c
X*
X* Subsystem_group:
X*
X* Window System, Widget tree creation from Xrm database
X*
X* Related_keywords:
X*
X* Widget, Creation
X*
X* Module_description:
X*
X* This module contains the functions and convenience callbacks
X* used to create and manage a widget tree using the Xrm databse.
X* The Xrm database format used to define widget's children is
X* as follows:
X*
X* toplevel...widget.managed.child_n: name,constructor[,n[onrecursive]]
X* toplevel...widget.unmanged.child_n: name,constructor[,n[onrecursive]]
X*
X* Example:
X* helloWorld.managed.child_0: box,XmCreateRowColumn
X* helloWorld.box.managed.child_0: label,XmCreateLabel
X* helloWorld.box.managed.child_1: button,XmCreatePushButton
X* helloWorld.box.label.labelString: Hello, World !
X* helloWorld.box.button.labelString: Bye Bye, World !
X* helloworld.box.button.activateCallback: push(EXIT)
X*
X* Since (for portability reasons) we can not assume runtime binding,
X* all widget classes or creation routines (constructors) must be
X* "registered" by the application BEFORE widget tree creation.
X*
X* The widget tree creation is performed by the WsCreateXrmChildren()
X* function, which descends the widget tree recursively until no more
X* children are found, or widget creation is flagged as "nonrecursive",
X* or a non-composite widget/object is found.
X*
X* Several convenience callbacks are provided here, more will probbably
X* follow.
X*
X* Module_interface_summary:
X*
X*
X* Xt Widget/Object Class Registration Routine:
X*
X* WsRegisterObjectClass(
X* WsAppContext app, - application context
X* String name, - class name, case insensitive
X* WidgetClass class ) - class record pointer
X*
X*
X* Xt Widget/Object Contructor Registration Routine:
X*
X* WsRegisterConstructor(
X* WsAppContext app, - application context
X* String name, - constructor name, case insens.
X* (*Widget)() const ) - constructor function pointer
X*
X*
X* Standard callback registration routine (all the following callbacks)
X*
X* WsRegisterXrmCallbacks (
X* WsAppContext app ) - application context
X*
X* Convenience Callbacks:
X*
X* WsCreateXrmChildrenCB () - creates children for named widgets
X* WsManageNamedChildrenCB () - manages named widgets
X* WsUnmanageNamedChidrenCB() - unmanages named widgets
X* WsSetWidgetResourceCB () - sets widget resource in named widgets
X* WsLoadResourceFileCB () - loads a new database file
X*
X*
X* Module_history:
X*
X* mm/dd/yy initials function action
X* -------- -------- -------- ---------------------------------------------
X* 02/26/90 MarBru All Created
X* 02/16/90 MarBru Create.. Limited creation to composite widgets/objects
X*
X* Design_notes:
X
X* For VMS, we could have used LIB$FIND_IMAGE_SYMBOL and use dynamic
X* (runtime) binding. But since most UNIX systems lack such capability,
X* we stick to the concept of "registration" routines.
X*
X*******************************************************************************
X*/
X/*
X*******************************************************************************
X* Include_files.
X*******************************************************************************
X*/
X
X/* -- Operating system includes */
X#include <strings.h>
X#include <ctype.h>
X
X/* -- X Window System includes */
X#include <X11/IntrinsicP.h>
X#include <X11/StringDefs.h>
X
X/* -- Auto-trol Window System includes */
X
X/*
X*******************************************************************************
X* Private_constant_declarations.
X*******************************************************************************
X*/
X#undef NUL
X#define NUL '\0'
X#define MAX_XRMSTRING 1024 /* max length of the Xrm DB string */
X#define MAX_ERRMSG 1024 /* max length of error message */
X#define MAX_CHILDREN 1024 /* max number of widget's children */
X#define ADD_CLASSES 16 /* increment of class cache */
X
X#define WsNxrmCreateCallback "xrmCreateCallback"
X#define WsCXrmCreateCallback "XrmCreateCallback"
X
X/*
X*******************************************************************************
X* Private_type_declarations.
X*******************************************************************************
X Class/constructor cache record contains both class and constructor,
X one of which must be NULL.
X*/
Xtypedef struct /* Class cache record */
X{
X XrmQuark quark; /* quarkified callback name */
X Widget (*constructor)(); /* constructor function ptr */
X WidgetClass class; /* widget class pointer */
X} ClCacheRec;
X
X/*
X*******************************************************************************
X* Private_macro_definitions.
X*******************************************************************************
X*/
X
X/*
X*******************************************************************************
X* Private_data_definitions.
X*******************************************************************************
X The following cache/registry of known widget classes and contructors,
X initially empty, are loaded by the application using "registration"
X routines.
X Assuming small numbers of constructors, the sequential search
X of such cache is (initially) considered acceptable.
X*/
X
X/* -- Named object classes cache, intially empty */
X
Xstatic int classes_num = 0;
Xstatic int classes_max = 0;
Xstatic ClCacheRec *classes_ptr = NULL;
X
X/*
X*******************************************************************************
X* Private_function_declarations.
X*******************************************************************************
X*/
X
X
X/*
X -- Names to Widget List
X******************************************************************************
X This routine converts a string of comma separated widget names
X (or widget pathes) into a list of widget id's. Blank space ignored
X If a NULL string is provided, the widget ID of reference widget
X is put on the list
X The widget search starts at the TOP of widget hierarchy (using the
X top level shell as a reference widget), thus the widget pathname
X must include all the widget parents (excluding the shell).
X*/
Xstatic void NamesToWidgetList ( w, client, widget_list, widget_count )
XWidget w; /* reference widget */
Xcaddr_t client; /* callback client data - string of names */
XWidget *widget_list; /* returned widget list */
XCardinal *widget_count; /* returned widget count */
X{
X char *string = (String)client;
X char name[MAX_XRMSTRING];
X register char *s;
X register char *d;
X
X/* -- default case, no string provided, return the calling widget */
X if (!string)
X {
X widget_list[0] = w;
X *widget_count = 1;
X return;
X }
X
X/* -- find the reference widget as the toplevel shell */
X while ( XtParent(w) ) w = XtParent(w);
X
X/* -- parse the input string "name.name,name.name,name.name.name" */
X *widget_count = 0;
X for ( d = name, s = string; ; s++ )
X {
X if ( *s == ',' || *s == NUL )
X {
X Widget widget;
X if ( *s == NUL && d == name ) return;
X *d = NUL;
X widget = XtNameToWidget ( w, name );
X if ( widget )
X {
X widget_list[*widget_count] = widget;
X (*widget_count)++;
X }
X else
X XtStringConversionWarning (name, "Widget");
X d = name;
X }
X else if ( *s > ' ' )
X {
X *d++ = *s;
X }
X else
X ;
X }
X}
X/*
X -- Call Create Callback
X*******************************************************************************
X This function calls the CreateCallback defined for the widget in Xrm
X resource database.
X Note the xrmCreateCallback "resource" is NOT a true widget resource,
X there are no instance data associated with it, and only exists in the
X Xrm resource database, used ONLY at widget creation time.
X*/
Xstatic Widget CallCreateCallback ( w )
XWidget w; /* child's parent */
X{
X static XtResource res[] =
X {
X { WsNxrmCreateCallback, WsCXrmCreateCallback, XtRCallback,
X sizeof(XtCallbackList), 0, XtRImmediate, (caddr_t)NULL
X },
X };
X XtCallbackList callback = NULL;
X
X XtGetApplicationResources ( w, &callback, res, XtNumber(res), NULL, 0 );
X
X /* If there was any callback list defined, invoke all callbacks on list */
X if ( callback )
X {
X XtCallbackRec *cb = callback;
X for ( cb = callback; cb->callback; cb++ )
X (*cb->callback) ( w, cb->closure, NULL );
X
X }
X}
X
X/*
X -- Create Database Child
X*******************************************************************************
X This function checks the resource database for a presence of widget's
X subresource in a form:
X
X ...widget.type.child_nn: name.constr_name[,n[onrecursive]]
X
X where type is either "managed" or "unmanaged".
X
X If such a resource is present, the child is created and, if nonrecursive
X option is NOT present, the CreateDatabseChildren is called for this
X child causing recursive tree creation. Creation stops if child_0 or
X two subsequent children are not defined. Creation also stops at any
X non-composite widget/object. Thus, popup-shells etc. must be created
X as manager children.
X
X*/
Xstatic Widget CreateDatabaseChild ( w, nn, type )
XWidget w; /* child's parent */
Xint nn; /* child # to look for */
XString type; /* child type: managed or unmanaged */
X{
X static XtResource c_resource[] =
X {
X { NULL, NULL, XtRString, sizeof(String), 0, XtRImmediate, (caddr_t)NULL },
X };
X Boolean recursive;
X char res_name[20];
X String string;
X
X /* update our resource list to look for type.child_n subresource */
X sprintf ( res_name, "child_%d", nn );
X /* toolkit quarkifies resource lists, (flagged by negative offset) */
X if ( ((int)c_resource[0].resource_offset) < 0 )
X {
X XrmQuark qname = XrmStringToQuark(res_name);
X c_resource[0].resource_name = (String)qname;
X c_resource[0].resource_class = (String)qname; /* no class used */
X }
X else
X {
X c_resource[0].resource_name = res_name;
X c_resource[0].resource_class = res_name; /* no class allowed / used */
X }
X XtGetSubresources ( w, &string, type, type, c_resource, 1, NULL, 0 );
X
X /* Xrm query returned a string for [un]managed.child_n resource, process */
X if ( string )
X {
X void WsCreateXrmChildren();
X XrmQuark quark;
X Widget (*found_const)() = NULL;
X WidgetClass found_class = NULL;
X char name [MAX_XRMSTRING];
X char constr[MAX_XRMSTRING];
X register char *s;
X register char *d;
X register int i;
X
X /* extract widget name */
X for ( d=name, s=string; (*s && *s!=','); )
X *d++ = *s++;
X *d = NUL;
X
X /* check for missing class/constructor name */
X if ( *s != ',' )
X {
X char msg [MAX_ERRMSG];
X sprintf ( msg,
X "Resource db error, missing constructor specifier for %s", name );
X XtWarning( msg );
X return (Widget)NULL;
X }
X s++;
X
X /* extract class/constructor name and force lowercase, no white space */
X for ( d=constr; (*s && *s!=','); )
X if (*s > ' ')
X *d++ = (isupper(*s)) ? tolower(*s++) : *s++;
X else
X s++;
X *d = NUL;
X
X /* check for non-recursive option */
X recursive = ( *s==',' && (s[1]=='n' || s[1]=='N') ) ? FALSE : TRUE;
X
X
X /* try to locate class/constructor in our caches */
X quark = XrmStringToQuark ( constr );
X for (i=0; i<classes_num; i++)
X if ( classes_ptr[i].quark == quark )
X {
X found_class = classes_ptr[i].class;
X found_const = classes_ptr[i].constructor;
X break;
X }
X
X /* if we'w found a class or constructor, create child, call callback */
X if (found_class || found_const )
X {
X Widget child;
X if ( found_class )
X child = XtCreateWidget ( name, found_class, w, NULL, 0 );
X else
X child = (*found_const) ( w, name, NULL, 0 );
X
X CallCreateCallback ( child );
X if ( recursive ) WsCreateXrmChildren ( child );
X return (child);
X }
X else
X {
X char msg[MAX_ERRMSG];
X sprintf ( msg,"Cannot create child %s using %s, unknown class/constructor",
X name, constr );
X XtWarning( msg );
X return (Widget)NULL;
X }
X }
X else
X {
X return (Widget)NULL;
X }
X}
X
X/*
X*******************************************************************************
X* Public_function_declarations.
X*******************************************************************************
X*/
X/*
X -- Register Object Class
X*******************************************************************************
X This procedure adds object class name to our list of registered
X classes/constructors. So far very simplistic ... without checking for
X duplicate entries, no cache hashing scheme....no ties to app_context.
X*/
Xvoid WsRegisterObjectClass ( app, name, class )
XXtAppContext app; /* not used (yet), must be present */
XString name; /* constructor name, case insensitive */
XWidgetClass class; /* Xt object class pointer */
X{
X char cr_name[MAX_XRMSTRING];
X register char *s;
X register char *d;
X
X for ( d=cr_name, s=name; *s; s++)
X *d++ = (isupper(*s)) ? tolower (*s) : *s;
X *d = '\0';
X
X if (classes_num >= classes_max )
X {
X classes_max += ADD_CLASSES;
X classes_ptr = (ClCacheRec*) XtRealloc((char*)classes_ptr,
X sizeof(ClCacheRec) * classes_max);
X }
X classes_ptr[classes_num].quark = XrmStringToQuark ( cr_name );
X classes_ptr[classes_num].constructor = NULL;
X classes_ptr[classes_num].class = class;
X classes_num++;
X}
X
X/*
X -- Register constructor
X*******************************************************************************
X This procedure adds constructor procedure/name to our list of registered
X classes/constructors. So far very simplistic ... without checking for
X duplicate entries, no cache hashing scheme....no ties to app_context.
X
X Note the constructor is a "standard" widget creation routine
X Widget WsCreateXyyyZyyy ( parent, name, args, nargs )
X*/
Xvoid WsRegisterConstructor ( app, name, constructor )
XXtAppContext app; /* not used (yet), must be present */
XString name; /* constructor name, case insensitive */
XWidget (*constructor) (); /* pointer to a widget creation routine */
X{
X char cr_name[MAX_XRMSTRING];
X register char *s;
X register char *d;
X
X for ( d=cr_name, s=name; *s; s++)
X *d++ = (isupper(*s)) ? tolower (*s) : *s;
X *d = '\0';
X
X if (classes_num >= classes_max )
X {
X classes_max += ADD_CLASSES;
X classes_ptr = (ClCacheRec*) XtRealloc((char*)classes_ptr,
X sizeof(ClCacheRec) * classes_max);
X }
X classes_ptr[classes_num].quark = XrmStringToQuark ( cr_name );
X classes_ptr[classes_num].constructor = constructor;
X classes_ptr[classes_num].class = NULL;
X classes_num++;
X}
X
X/*
X -- Create Xrm Database Children
X*******************************************************************************
X This routine creates widget children as defined in X reosurce databse.
X We look for children defintion starting at child 0 (first looking
X for managed, then unmanaged child). The child lookup terminates if
X child_0 is not present, or two two subsequent child lookups failed
X (allowing to continue if one child was defined incorrectly).
X
X To reduce the databse search overhead, we only attempt to create
X children for composite widgets and objects.
X*/
Xvoid WsCreateXrmChildren ( w )
XWidget w;
X{
X Widget child;
X Widget prev;
X Widget managed[MAX_CHILDREN];
X register int i,num;
X
X/* -- check if the requested widget is a manager ( composite ) */
X if (! ( XtIsSubclass( w, compositeWidgetClass )
X || XtIsSubclass( w, compositeObjectClass ) /* not in R3 intrinsics */
X ) ) return;
X
X
X/* -- look for children definition until we have 2 subsequent misses */
X child = (Widget) 1;
X prev = (Widget) 0; /* this makes the child_0 mandatory */
X
X for ( i=0, num=0; (prev || child) ;i++)
X {
X child = CreateDatabaseChild ( w, i, "managed" );
X if ( child )
X managed[num++] = child;
X else
X child = CreateDatabaseChild ( w, i, "unmanaged" );
X prev = child;
X }
X XtManageChildren(managed, num );
X}
X
X
X/*
X -- Create Xrm Children callback
X*******************************************************************************
X
X For each widget specified by the list of widget names in client data,
X (or the widget invoking this callback if client data is NULL), this
X callback creates any children defined in the Xrm database:
X
X ....widget.managed.child_0: name,constr_name[,n[onrecursive]]
X ....widget.unmanaged.child_0: name,constr_name[,n[onrecursive]]
X
X If resource above (child_0 - child_nn) exists, the callback creates
X (and optionally manages) a child using a constructor routine registered
X under "constr_name".
X The creation process recursivly follows the widget tree, unless
X the constructor is specified with the "nonrecursive" option, or
X a non-composite widget/object is found.
X
X The search for "child_n" resource stops if two subsequent children
X or child_0 are not specified, or their creation fails (error).
X
X After all children have been created, the string of widget names
X is changed to an empty one ("\0"), to prevent duplicate widget
X creation.
X
X*/
Xvoid WsCreateXrmChildrenCB ( w, client, call )
XWidget w;
Xcaddr_t client; /* client data, list of named children */
Xcaddr_t call; /* call data, not used */
X{
X Widget* widget_list[MAX_CHILDREN];
X Cardinal widget_count;
X int i;
X
X
X /* for NULL client, we get back "w", for "\0" we get zero widget count */
X NamesToWidgetList ( w, client, widget_list, &widget_count );
X
X for ( i=0; i<widget_count; i++)
X WsCreateXrmChildren(widget_list[i]);
X
X /* prevent repeated invokation by changing string to empty "\0" one */
X if ( client )
X *client = NUL;
X}
X
X/*
X -- Manage named children callback
X*******************************************************************************
X This callback translates string passed in as client data into a widget id
X and manages it. A comma separated list of children can be specified.
X NULL string pointer defaults widget invoking the callback
X*/
Xvoid WsManageNamedChildrenCB ( w, client, call )
XWidget w;
Xcaddr_t client; /* client data, list of named children */
Xcaddr_t call; /* call data, not used */
X{
X Widget* widget_list[MAX_CHILDREN];
X Cardinal widget_count;
X
X NamesToWidgetList ( w, client, widget_list, &widget_count );
X XtManageChildren ( widget_list, widget_count );
X}
X
X
X/*
X -- Unmanage named children callback
X*******************************************************************************
X This callback translates string passed in as client data into a widget id
X and manages it. A comma separated list of children can be specified.
X NULL string pointer defaults widget invoking the callback
X*/
Xvoid WsUnmanageNamedChildrenCB ( w, client, call )
XWidget w;
Xcaddr_t client; /* client data, list of named children */
Xcaddr_t call; /* call data, not used */
X{
X Widget* widget_list[MAX_CHILDREN];
X Cardinal widget_count;
X
X NamesToWidgetList ( w, client, widget_list, &widget_count );
X XtUnmanageChildren ( widget_list, widget_count );
X}
X
X
X/*
X -- Set Widget Resource Callback
X*******************************************************************************
X This callback loads invoking widget into the prescribed resource of the
X named widget(s).
X Typically, this callback is used to set the "XmNdefaultButton" resource,
X and is invoked from button creation callback.
X
X The client data argument has a format:
X
X resource_name,target_widget_name[,target_widget_name...]
X*/
Xvoid WsSetWidgetResourceCB ( w, client, call )
XWidget w;
Xcaddr_t client; /* client data, resource name, list of named children */
Xcaddr_t call; /* call data, not used */
X{
X Widget* widget_list[MAX_CHILDREN];
X Cardinal widget_count;
X char resource[MAX_XRMSTRING];
X register char *d,*s;
X register int i;
X Arg args[1];
X
X for ( d=resource, s=client; (*s && *s!=','); s++ )
X if (*s > ' ') *d++ = *s;
X *d = NUL;
X
X if (*s == ',' ) s++;
X if (*s == NUL )
X {
X XtWarning("No widget names for WsSetWidgetresourceCB");
X return;
X }
X NamesToWidgetList ( w, s, widget_list, &widget_count );
X
X /* set the resource to set */
X args[0].name = resource;
X args[0].value = (XtArgVal)w;
X
X for (i=0; i<widget_count; i++)
X XtSetValues ( widget_list[i], args, 1 );
X}
X
X/*
X -- Load Resource File
X*******************************************************************************
X This callbacks loads the specified resource file into application
X resource database. It allows to load the resources on as-needed
X basis, reducing the intitial resource load overhead.
X
X Two locations are searched for a specified file:
X
X XAPP_DEFAULT_PATH
X XUSER_DEFAULT_PATH (or env.variable "XAPPLRESLANGPATH")
X
X Not implemented -- too toolkit dependent ( R3/Motif/R4 ).
X*/
Xvoid WsLoadResourceFileCB ( w, client, call )
XWidget w;
Xcaddr_t client; /* client data, X resources file name */
Xcaddr_t call; /* call data, not used */
X{
X printf("Sorry, deffered resource load not implemented, file %s\n",call);
X printf("Merge your file into application class file\n");
X}
X
X/*
X -- WsRegisterXrmCallbacks
X*******************************************************************************
X*/
Xvoid WsRegisterXrmCallbacks ( app )
XXtAppContext app;
X{
X#define REG( name, cb, cl ) WsRegisterCallback ( app, name, cb, cl )
X
X REG("CreateXrmChildrenCB", WsCreateXrmChildrenCB, NULL );
X REG("ManageNamedChildrenCB", WsManageNamedChildrenCB, NULL );
X REG("UnmanageNamedChildrenCB", WsUnmanageNamedChildrenCB, NULL );
X REG("SetWidgetResourceCB", WsSetWidgetResourceCB, NULL );
X
X#undef REG
X}
END_OF_FILE
if test 22340 -ne `wc -c <'WsCreateXrmFunc.c'`; then
echo shar: \"'WsCreateXrmFunc.c'\" unpacked with wrong size!
fi
# end of 'WsCreateXrmFunc.c'
fi
if test -f 'WsCvtStrToCallback.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'WsCvtStrToCallback.c'\"
else
echo shar: Extracting \"'WsCvtStrToCallback.c'\" \(10320 characters\)
sed "s/^X//" >'WsCvtStrToCallback.c' <<'END_OF_FILE'
X/*
X*******************************************************************************
X*
X* SCCS_data: %Z%%M% %I%(%G%)
X*
X* Module_name:
X*
X* WsCvtStrToCallback
X*
X* Subsystem_group:
X*
X* Window System, Widget Set, Converters
X*
X* Related_keywords:
X*
X* Converter
X*
X* Module_description:
X*
X* This module contains the String To Callback X resource converter.
X*
X* The converter parses the resource string in the format:
X*
X* ...path: name[(args)][,name[(args)]]...
X*
X* where: name: specifies the registered callback function name
X* args: specifies the string passed to a callback as
X* "client data".
X*
X* Multiple callbacks can be specified for a single callback list
X* resource. Any callbacks must be "registered" by the application
X* prior converter invocation (.i.e.prior widget creation).
X* If no "args" string is provided, the default "client data"
X* specified at callback registration are used.
X*
X* Module_interface_summary:
X*
X*
X* Resource converter is invoked indirectly by the toolkit. The
X* converter is added to the toolkit by widgets calling
X* WsAddStrToCallbackP() in the widget intialization code.
X*
X* To register application callbacks, use:
X*
X* WsRegisterCallback (
X* WsAppContext app, - application context
X* String name, - register name, case insensitive
X* Callback callback, - callback function pointer
X* ClientData closure ) - default client data
X*
X* Module_history:
X*
X* mm/dd/yy initials function action
X* -------- -------- -------- ---------------------------------------------
X* 02/26/90 MarBru All Created
X*
X* Design_notes:
X*
X* For VMS, we could have used LIB$FIND_IMAGE_SYMBOL and use dynamic
X* (runtime) binding. But since most UNIX systems lack such capability,
X* we stick to the concept of "registration" routines.
X*
X*******************************************************************************
X*/
X/*
X*******************************************************************************
X* Include_files.
X*******************************************************************************
X*/
X
X/* -- Operating system includes */
X#include <strings.h>
X#include <ctype.h>
X
X/* -- X Window System includes */
X#include <X11/IntrinsicP.h>
X#include <X11/StringDefs.h>
X
X/* -- Auto-trol Window System includes */
X
X/*
X*******************************************************************************
X* Private_constant_declarations.
X*******************************************************************************
X*/
X#undef NUL
X#define NUL '\0'
X
X/*
X*******************************************************************************
X* Private_type_declarations.
X*******************************************************************************
X*/
X#define MAX_XRMSTRING 1024 /* max length of the DB string */
X#define MAX_CALLBACKS 64 /* max number of callbacks per list */
X#define ADD_CALLBACKS 16 /* increment of callback cache size */
X
X/*
X*******************************************************************************
X* Private_macro_definitions.
X*******************************************************************************
X*/
X
X/*
X*******************************************************************************
X* Private_data_definitions.
X*******************************************************************************
X The following cache/registry of known callbacks, initially empty,
X is loaded by the application using "registration" routines.
X Assuming small numbers of callbacks, the sequential search
X of such cache is (initially) considered acceptable.
X*/
X
X/* -- Named callback procedures cache, intially empty */
X
Xtypedef struct
X{
X XrmQuark quark; /* quarkified callback name */
X XtCallbackProc callback; /* callback procedure pointer */
X caddr_t closure; /* default client data */
X} CBCacheRec;
X
X
X
Xstatic int callbacks_num = 0;
Xstatic int callbacks_max = 0;
Xstatic CBCacheRec *callbacks_ptr = NULL;
X
X
X/*
X*******************************************************************************
X* Private_function_declarations.
X*******************************************************************************
X*/
X
X/*
X -- Convert String To Callback
X*******************************************************************************
X This conversion creates a callback list structure from the X resource
X database string in format:
X
X name(arg),name(arg).....
X
X Note "name" is not case sensitive, while "arg" may be - it is passed to
X a callback as client data as a null terminated string (first level
X parenthesis stripped off).
X*/
Xvoid CvtStringToCallback (args, num_args, fromVal, toVal)
X
XXrmValue *args;
XCardinal *num_args;
XXrmValue *fromVal;
XXrmValue *toVal;
X{
X typedef struct
X {
X char *nsta,*nend; /* callback name start, end */
X char *asta,*aend; /* argument string start, end */
X } Segment;
X
X static XtCallbackRec *cb;
X XtCallbackRec callback_list[MAX_CALLBACKS];
X int callback_num = 0;
X String string = (char *) fromVal->addr;
X Segment segs[MAX_CALLBACKS];
X Segment *seg;
X register char *s;
X register int i,ipar;
X
X/* -- assume error or undefined input argument */
X toVal->size = 0;
X toVal->addr = (caddr_t) NULL;
X if (s == NULL) return;
X
X/* -- parse input string finding segments "name(arg)" comma separated */
X ipar = 0;
X seg = segs;
X seg->nsta = string;
X seg->nend = seg->asta = seg->aend = (char*)NULL;
X
X for ( s=string; *s; s++ )
X {
X switch (*s)
X {
X case ',': if ( ipar > 0 ) break; /* commas in arguments ignored */
X if ( seg->nend == NULL ) seg->nend = s-1; /* no argument */
X seg++; /* start the next segment */
X seg->nsta = (s[1]) ? s+1 : (char*)NULL;
X seg->nend = seg->asta = seg->aend = (char*)NULL;
X break;
X
X case '(': if ( ipar++ == 0 ) { seg->nend = s-1; seg->asta = s+1; };
X break;
X
X case ')': if ( --ipar == 0 ) { seg->aend = s-1; };
X break;
X deafult: ;
X }
X }
X seg++; /* start the terminating segment */
X seg->nsta = (char*)NULL;
X
X if (ipar)
X {
X XtStringConversionWarning (string, "Callback, unbalanced parenthesis");
X return;
X }
X
X
X/* -- process individual callback string segments "name(arg)" */
X for( seg = segs; seg->nsta; seg++)
X {
X char cb_name[MAX_XRMSTRING];
X XtCallbackProc found = (XtCallbackProc)NULL;
X XrmQuark quark;
X register char *d;
X register char *end;
X
X /* our callback cache names are case insensitive, no white space */
X for ( s=seg->nsta, d=cb_name; s<=seg->nend; )
X if ( *s > ' ')
X *d++ = (isupper(*s) ) ? tolower (*s++) : *s++;
X else
X s++;
X *d = NUL;
X
X /* try to locate callback in our cache of callbacks */
X quark = XrmStringToQuark (cb_name);
X for (i=0; i<callbacks_num; i++)
X if ( callbacks_ptr[i].quark == quark )
X {
X register XtCallbackRec *rec = &callback_list[callback_num];
X rec->callback = found = callbacks_ptr[i].callback;
X rec->closure = callbacks_ptr[i].closure;
X break;
X }
X
X /* we have found a registered callback, process arguments */
X if (found)
X {
X register char *arg;
X register int alen;
X register XtCallbackRec *rec = &callback_list[callback_num];
X
X if ( seg->asta )
X {
X alen = (int)seg->aend - (int)seg->asta +1;
X arg = XtMalloc(alen+1);
X strncpy ( arg, seg->asta, alen );
X arg[alen+1] = NUL;
X rec->closure = (caddr_t)arg;
X }
X callback_num++;
X }
X else
X {
X XtStringConversionWarning (cb_name, "Callback, unknown callback name");
X }
X } /* end for seg loop */
X
X/* -- terminate the callback list */
X {
X register XtCallbackRec *rec = &callback_list[callback_num];
X rec->callback = NULL;
X rec->closure = NULL;
X callback_num++;
X }
X
X/* -- make a permanent copy of the new callback list, and return a pointer */
X cb = (XtCallbackRec*)XtMalloc( callback_num * sizeof (XtCallbackRec) );
X memcpy ( (char*)cb, (char*)callback_list,
X callback_num * sizeof (XtCallbackRec));
X toVal->size = sizeof (XtCallbackRec*);
X toVal->addr = (caddr_t)&cb;
X}
X
X/*
X*******************************************************************************
X* Public_function_declarations.
X*******************************************************************************
X*/
X
X/*
X -- Add String To Callback Convertor
X*******************************************************************************
X*/
X
Xvoid WsAddStringToCallbackP ()
X{
X static Boolean added = FALSE;
X if ( !added )
X {
X XtAddConverter (XtRString,
X XtRCallback,
X CvtStringToCallback,
X (XtConvertArgList)NULL,
X (Cardinal)0);
X added = TRUE;
X }
X}
X
X
X/*
X -- Register callback
X*******************************************************************************
X This procedure adds callback procedure/name to our list of registered
X callbacks. So far very simplistic ... without checking for duplicate
X entries, no cache hashing scheme, no ties to app_context.
X*/
Xvoid WsRegisterCallback ( app, name, callback, closure )
XXtAppContext app; /* not used (yet), must be present */
XString name; /* callback name, case insensitive */
XXtCallbackProc callback; /* callback function pointer */
Xcaddr_t closure; /* default closure (client data) */
X{
X char cb_name[MAX_XRMSTRING];
X register char *s;
X register char *d;
X
X for ( d=cb_name, s=name; *s; s++)
X *d++ = (isupper(*s)) ? tolower (*s) : *s;
X *d = '\0';
X
X if (callbacks_num >= callbacks_max )
X {
X callbacks_max += ADD_CALLBACKS;
X callbacks_ptr = (CBCacheRec*) XtRealloc((char*)callbacks_ptr,
X sizeof(CBCacheRec) * callbacks_max);
X }
X callbacks_ptr[callbacks_num].quark = XrmStringToQuark ( cb_name );
X callbacks_ptr[callbacks_num].callback = callback;
X callbacks_ptr[callbacks_num].closure = closure;
X callbacks_num++;
X}
END_OF_FILE
if test 10320 -ne `wc -c <'WsCvtStrToCallback.c'`; then
echo shar: \"'WsCvtStrToCallback.c'\" unpacked with wrong size!
fi
# end of 'WsCvtStrToCallback.c'
fi
if test -f 'HelloWorld.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'HelloWorld.c'\"
else
echo shar: Extracting \"'HelloWorld.c'\" \(3743 characters\)
sed "s/^X//" >'HelloWorld.c' <<'END_OF_FILE'
X/*
X*******************************************************************************
X* HelloWorld.c
X*******************************************************************************
X This program demonstrates usage of the Xrm (X resource management) databse
X for a widget tree definition and management.
X There is very little code in this example, since the entire user interface
X definition is stored in the Xrm database, preferably in the application
X class resource file: ~/HelloWorld
X
X ATTC NOTE: This example does NOT use Ws, since it's intended for use
X outside Auto-trol.
X/*
X*******************************************************************************
X* Include_files.
X*******************************************************************************
X*/
X
X#include <Xm/Xm.h> /* Motif public header file */
X#include <Xm/Label.h> /* Motif label widget */
X#include <Xm/PushB.h> /* Motif pushbutton widget */
X#include <Xm/BulletinB.h> /* Motif bulletin board widget */
X#include <Xm/RowColumn.h> /* Motif row column widget */
X#include "WsCreateXrm.h" /* Window System Xrm Creation routines */
X
X/*
X*******************************************************************************
X* Application callback declaration (callbacks should be in a separate file)
X*******************************************************************************
X*/
Xvoid pushCB();
X
X/*
X*******************************************************************************
X* MAIN function
X*******************************************************************************
X*/
X
Xmain ( argc, argv )
Xint argc;
Xchar **argv;
X{
X Widget app_shellW; /* application shell widget */
X XtAppContext app;
X
X/* -- Intialize AWS creating the application shell */
X app_shellW = XtInitialize ( "helloWorld","HelloWorld",
X NULL, 0, &argc, argv );
X app = XtWidgetToApplicationContext(app_shellW);
X
X/* -- Register the string to callback converter, used for a pushbutton */
X WsAddStringToCallbackP();
X
X/* -- Register available Widget constructors */
X WsRegisterConstructor ( app, "xmLabel", XmCreateLabel );
X WsRegisterConstructor ( app, "xmPushButton", XmCreatePushButton);
X WsRegisterConstructor ( app, "xmRowColumn", XmCreateRowColumn );
X WsRegisterObjectClass ( app, "xmBulletinBoard", xmBulletinBoardWidgetClass);
X
X/* -- Register available callbacks */
X WsRegisterXrmCallbacks( app );
X WsRegisterCallback ( app, "push", pushCB, NULL );
X
X
X/* -- Create children of the toplevel shell defined by the Xrm database */
X WsCreateXrmChildren ( app_shellW );
X
X/* -- Realize the widget tree and enter the main application loop */
X XtRealizeWidget ( app_shellW );
X XtMainLoop ( );
X}
X/*
X*******************************************************************************
X Application callbacks (should be in a separate file)
X*******************************************************************************
X*/
X/*
X -- Push callback
X*******************************************************************************
X This callback is a state machine; the first invocation loads the text
X specified as client data into XmNlabelString resource of invoking widget;
X the next invocation exits the application.
X*/
Xvoid pushCB ( w, client, call )
XWidget w;
Xcaddr_t client;
Xcaddr_t call;
X{
X static Boolean first = TRUE;
X
X if ( first )
X {
X static Arg setargs[] = { XmNlabelString, NULL };
X String text = ( client ) ? (String) client : "No text in Xrdb" ;
X
X setargs[0].value = (XtArgVal)XmStringCreateLtoR(text,XmSTRING_DEFAULT_CHARSET);
X WsSetResources ( w, setargs, 1);
X first = FALSE;
X }
X else
X {
X exit();
X }
X}
END_OF_FILE
if test 3743 -ne `wc -c <'HelloWorld.c'`; then
echo shar: \"'HelloWorld.c'\" unpacked with wrong size!
fi
# end of 'HelloWorld.c'
fi
if test -f 'HelloWorld_Basic' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'HelloWorld_Basic'\"
else
echo shar: Extracting \"'HelloWorld_Basic'\" \(851 characters\)
sed "s/^X//" >'HelloWorld_Basic' <<'END_OF_FILE'
X# HelloWorld - global resources
X#
X*fontList: -*-Helvetica-Medium-R-Normal--14*
X#
X# shell
X#
XHelloWorld.managed.child_0: box,xmRowColumn
X#
X# box - the main container
X#
XHelloWorld.box.spacing: 2
XHelloWorld.box.background: red
XHelloWorld.box.marginWidth: 4
XHelloWorld.box.marginHeight: 4
XHelloWorld.box.entryAlignment: alignment_center
XHelloWorld.box.managed.child_0: label,xmlabel
XHelloWorld.box.managed.child_1: button,xmpushbutton
X#
X# label
X#
XHelloWorld.box.label.background: white
XHelloWorld.box.label.foreground: blue
XHelloWorld.box.label.labelString: Hello, WORLD !
X#
X# button
X#
XHelloWorld.box.button.background: lightBlue
XHelloWorld.box.button.foreground: white
XHelloWorld.box.button.location: center
XHelloWorld.box.button.labelString: Push ME
XHelloWorld.box.button.activateCallback: push(Push to EXIT)
X#
END_OF_FILE
if test 851 -ne `wc -c <'HelloWorld_Basic'`; then
echo shar: \"'HelloWorld_Basic'\" unpacked with wrong size!
fi
# end of 'HelloWorld_Basic'
fi
if test -f 'HelloWorld_More' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'HelloWorld_More'\"
else
echo shar: Extracting \"'HelloWorld_More'\" \(2171 characters\)
sed "s/^X//" >'HelloWorld_More' <<'END_OF_FILE'
X#
X# HelloWorld
X# box main container
X# lbl1 headline label - hello world
X# box1 bulletin board for default button testing
X# btn1 default button
X# btn2 button controlling lbl2
X# btn3 button controlling lbl2
X# lbl2 footnote
X#
X# global resources
X#
X*fontList: -*-Helvetica-Medium-R-Normal--14*
X#
X# shell
X#
XHelloworld.input: true
XHelloWorld.managed.child_0: box,xmRowColumn
X#
X# box - the main container
X#
XHelloWorld.box.layout: column
XHelloWorld.box.spacing: 8
XHelloWorld.box.background: red
XHelloWorld.box.marginWidth: 0
XHelloWorld.box.marginHeight: 0
XHelloWorld.box.entryAlignment: alignment_center
XHelloWorld.box.managed.child_0: lbl1,xmLabel
XHelloWorld.box.managed.child_1: box1,xmBulletinBoard
XHelloWorld.box.managed.child_2: btn2,xmPushButton
XHelloWorld.box.managed.child_3: btn3,xmPushButton
XHelloWorld.box.managed.child_4: lbl2,xmLabel
X#
X# lbl1
X#
XHelloWorld.box.lbl1.background: white
XHelloWorld.box.lbl1.foreground: blue
XHelloWorld.box.lbl1.labelString: Hello, WORLD !
X#
X# box1
X#
XHelloWorld.box.box1.marginWidth: 8
XHelloWorld.box.box1.marginHeight: 8
XHelloWorld.box.box1.managed.child_0: btn1,xmPushButton
X#
X# btn1
X#
XHelloWorld.box.box1.btn1.labelString: Push ME
XHelloWorld.box.box1.btn1.background: lightBlue
XHelloWorld.box.box1.btn1.foreground: red
XHelloWorld.box.box1.btn1.showAsDefault: 2
XHelloWorld.box.box1.btn1.xrmCreateCallback: SetWidgetResourceCB(defaultButton,box.box1)
XHelloWorld.box.box1.btn1.activateCallback: push(Push to EXIT !)
X#
X# btn2
X#
XHelloWorld.box.btn2.background: lightBlue
XHelloWorld.box.btn2.foreground: blue
XHelloWorld.box.btn2.labelString: Remove Footnote
XHelloWorld.box.btn2.activateCallback: UnmanageNamedChildrenCB(box.lbl2)
X#
X# btn3
X#
XHelloWorld.box.btn3.background: lightBlue
XHelloWorld.box.btn3.foreground: blue
XHelloWorld.box.btn3.labelString: Add Footnote
XHelloWorld.box.btn3.activateCallback: ManageNamedChildrenCB(box.lbl2)
X#
X# lbl2
X#
XHelloWorld.box.lbl2.background: white
XHelloWorld.box.lbl2.foreground: blue
XHelloWorld.box.lbl2.labelString: Ain't it WONDERFULL ?
X#
END_OF_FILE
if test 2171 -ne `wc -c <'HelloWorld_More'`; then
echo shar: \"'HelloWorld_More'\" unpacked with wrong size!
fi
# end of 'HelloWorld_More'
fi
echo shar: End of shell archive.
exit 0
dan
-----------------------------------------------------------
O'Reilly && Associates
argv at sun.com / argv at ora.com
632 Petaluma Ave, Sebastopol, CA 95472
800-338-NUTS, in CA: 800-533-NUTS, FAX 707-829-0104
Opinions expressed reflect those of the author only.
More information about the Comp.sources.x
mailing list