v06i067: Motif Resource Interpreter, Part01/03

David E. Smyth david at jpl-devvax.jpl.nasa.gov
Thu Apr 12 17:42:56 AEST 1990


Submitted-by: david at jpl-devvax.jpl.nasa.gov (David E. Smyth)
Posting-number: Volume 6, Issue 67
Archive-name: mri/part01

These files make up the Motif Resource Interpreter, called Mri for
short.  It is an evolution of the WsXc package posted to comp.windows.x
by Martin Brunecky about the  21 March, 1990.  Martin did the hard
part, I just repackaged, tuned, and polished a few things.  Several of
us here at JPL find Mri to be useful, I hope you do also.

david at jpl-devvax.jpl.nasa.gov (David E. Smyth)

# to unbundle, "sh" this file -- DO NOT use csh
#  SHAR archive format.  Archive created Wed Apr 11 09:58:12 PDT 1990
echo x - README
sed 's/^X//' > README <<'+FUNKY+STUFF+'
XThese files make up the Motif Resource Interpreter, called Mri for
Xshort.  It is an evolution of the WsXc package posted to comp.windows.x
Xby Martin Brunecky about the  21 March, 1990.  Martin did the hard
Xpart, I just repackaged, tuned, and polished a few things.  Several of
Xus here at JPL find Mri to be useful, I hope you do also.
X
XIf you have any comments, code you want to donate such as String to
Xwhatever converters, or generally useful callbacks, bug reports or
Xsucess reports, ...   please contact me using any of the addressing
Xschemes mentioned in my .sig:
X
X----------------------------------------------------------
XDavid Smyth                david at jpl-devvax.jpl.nasa.gov
XSenior Software Engineer,  seismo!cit-vax!jpl-devvax!david
XX and Object Guru.         (818)354-6344
XJPL, M/S 301-260, 4800 Oak Grove Drive, Pasadena, CA 91109
X----------------------------------------------------------
X
XMri consists of a main() along with several useful routines including
Xgeneral purpose callbacks and resource type converters.
X
XThe intention of Mri is that an application writer can initially
Xdevelop the user interface of an application using the generic App
Xprogram generated by the Makefile and an application specific resource
Xfile.  The supplied resource files R_1, R_2, and R_3 show simple
Xexamples of what can be done with resources and virtually no C code,
Xonly those callbacks defined in Application.c.
X
XAs the application evolves, the application writer need only to write C
Xcode which implement callbacks and a routine which registers these
Xcallbacks.  The file Application.c is an example of such a file.  The
Xapplication writer links the callbacks and registration routine with
Xthe Mri library libMri.a, and the standard Motif and X libraries (See
Xthe Makefile for an example).
X
XOne useful development concept which has evolved over the last couple
Xof weeks of fooling around with Mri is this: since the developer
Xinitially concentrates on the user interface, the application
Xnatuarally evolves as a direct manipulation system: widgets map
Xdirectly to the objects which the application is being developed to
Xmanipulate.
X
XThis suggests that adding a core.extension field to widgets (there
Xalready is a core_class.extension field in WidgetClassRec).  These
Xcore.extension pointers in the widgets could then be used as pointers
Xto application objects.
X
XThe development group of which I am a part has been doing object
Xoriented programming in C for some time now, and this just seems to be
Xa useful scheme to closely link the Widget object concept and our
Xapplication objects.
X
XAfter you have unshared the distribution, you should only have to type
Xthe following commands (assuming the Motif libraries are named libXm.a
Xand libXtm.a):
X
X    % make
X    % setenv XENVIRONMENT R_1
X    % App -D
X
X    % setenv XENVIRONMENT R_2
X    % App
X
X    % setenv XENVIRONMENT R_3
X    % App -D
X
XYou will notice the effect of the -D flag: it causes the names of each
Xwidget to be dumped as it is created.  This is very helpful when you
Xare trying to figure out the names of children created by the Motif
X"Confusion" routines, like XmPulldownMenu or XmScrolledWindow.  This
Xwidget name dump can also be enabled via the "debugging" application
Xresource:
X
X    *debugging: True
X
XNote the dynamicChild_nn resources in the R_3 resource file, and that
Xthe activation callbacks of the "First Channel Set" and "stdout"
Xbuttons dynamically create widgets in the scrolled window on the
Xright.  The callbacks on both the dynamically created widgets destroys
Xthem.
X
XHere is the README as posted by Martin with very minor edits:
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  avoids  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    App.managedChild_0:             box,xmRowColumn
X    #
X    #  box - the main container, contains label and button
X    #
X    App.box.spacing:                 8
X    App.box.managedChild_0:          label,xmLabel
X    App.box.managedChild_1:          button,xmPushButton
X    #
X    #  label
X    #
X    App.box.label.labelString:       Hello, WORLD !
X    #
X    #  button
X    #
X    App.box.button.labelString:      Push ME
X    App.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    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        MriRegisterObjectClass ( app, "xmLabel",      xmLabelWidgetClass);
X        MriRegisterObjectClass ( app, "xmPushButton", xmPushButtonWidgetClass);
X        MriRegisterConstructor ( app, "xmRowColumn",  XmCreateRowColumn );
X
X        MriRegisterCallback    ( 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                      MriCreateXrmChildren ( widget );
X
X
X    WIDGET TREE CREATION MECHANISM
X
X    The initial (static) widget tree is created when the main routine in
X    libMri calls the MriCreateXrmChildren routine.  MriCreateXrmChildren 
X    scans the X resource database for the following widget resources:
X
X    path...widget.managedChild_n:      name,class
X    path...widget.unmanagedChild_n:    name,class
X
X    For each such  resource,  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,  until
X    stopped by a non-composite widget or gadget, or no more managedChild
X    or unmanagedChild resources are found.
X
X    Additional  widgets can be created  dynamically  from the X resource 
X    database by invoking the MriCreateDynamicWidgetCB  callback routine.  
X    This routine takes as an argument the names of the widgets which are 
X    to be created.   The X resource  database is then  searched  for the 
X    following widget resources:
X
X    path...widget.dynamicChild_n:	name, class
X    path...widget.unmDynamicChild_n:	name, class
X
X    to be created.   The X resource  database is then  searched  for the 
X    The names passed as arguments to  MriCreateDynamicWidgetCB  are each
X    broken  apart into the  parent  name and the child name.  The parent
X    name is  used to find the  widget  whose  resources  should  include
X    such dynamicChild and unmDynamicChild resources, with the child name 
X    used to  determine  which of the dynamic children are to be created.  
X    For each child created,  MriCreateXrmChildren  is invoked, causing a 
X    recursive  creation of widgets, again stopping when a  non-composite   
X    widget  or  gadget is  encountered,  or  when  no more  managedChild 
X    and unmanagedChild resources are found.
X    
X    When a child is created,  MriCreateXrmChildren  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 MriRegisterCallback, and
X    args presents an arbitrary string.
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, the names and arguments
X    are shown as they should appear in a resource file:
X
X     o  CreateDynamicWidgetCB ( widgetName, widgetName, ...  )
X        creates dynamic widgets from the Xrm database.  The (list of)
X        named widget(s) is used as a starting point: frequently, 
X	dynamically created widgets have children, and these are 
X	recursively created.
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  SetResourceOnWidgetCB ( resourceName, resourceValue, widgetname, ...  )
X        sets the specified resource in a (list of)  named  widget(s)  to
X        the resource value.   The value is converted from a String using
X	registered resource type converters (for example, the value may
X	may be a callback, and is bound by the String to Callback 
X        converter supplied with Mri).
X
X     o  QuitApplicationCB ()
X	Quits the application, no confirmation is asked for.
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  Motif  Resource  Interpreter  routines, called  Mri  for short,
X    performs essentialy the same function as UIL.  A complete comparison 
X    with UIL  can  not  be  done without  additional input.   Here I try  
X    only  to mention several important differences between UIL and Mri.
X
X    Implementation:
X    can  be  provided  to  control  popup/popdown,  to  load  additional
X    A UIL application uses multiple user  interface  definition  sources 
X    (application  code,  UIL  file,  compiled UID file and an X resource 
X    file).  Mri 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.  Mri  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  Mri.  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  Mri  is  favorable.   However,  final
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 Mri.  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.  Mri 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. A "debugging"
X    resource is defined,  which causes Mri to dump the names and classes
X    of each widget  created, which makes writing a correct resource file
X    significantly  easier.  In  addition, a  simple tool that acquires a 
X    widget's resource list and performs X resource  file syntax checking 
X    will very likely be provided in the next few weeks.
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  Mri.   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
+FUNKY+STUFF+
echo '-rw-r--r--  1 david       14949 Apr 11 09:43 README    (as sent)'
chmod u=rw,g=r,o=r README
ls -l README
echo x - Makefile
sed 's/^X//' > Makefile <<'+FUNKY+STUFF+'
X#
X# Makefile for building libMri.a and an application which uses
X# the Motif Resource Interpreter.
X#
X# This makefile works on Suns, and expects the Motif and X libraries
X# to exist in stadard directories (like /usr/lib) with the following
X# names:
X#	Motif Widget Library:	libXm.a
X#	Motif Intrinsics:	libXtm.a
X#	X11 Xlib Library:	libX11.a
X#
X# This makefile expects that the Motif include files are within
X# /usr/include/Xm and /usr/include/Xm/X11.
X#
X    CC = cc
XCFLAGS = -g -I/usr/include/Xm -L.
X LOBJS = MriCallbacks.o MriCreate.o MriCvts.o MriDynCreate.o MriMain.o \
X	 MriMisc.o MriReg.o
X  LIBS = -lMri -lXm -lXtm -lX11
X AOBJS = Application.o
X
XApp: $(AOBJS) libMri.a
X	$(CC) $(CFLAGS) $(AOBJS) $(LIBS) -o App
X
XlibMri.a: $(LOBJS) Mri.h   MriP.h
X	rm -f libMri.a
X	ar rc libMri.a $(LOBJS)
X	ranlib libMri.a
X
Xclean:
X	rm -f $(LOBJS) $(AOBJS)
X
Xclobber:
X	rm -f $(OBJS) $(AOBJS) App
+FUNKY+STUFF+
echo '-rw-r--r--  1 david         873 Apr 11 07:36 Makefile    (as sent)'
chmod u=rw,g=r,o=r Makefile
ls -l Makefile
echo x - Mri.h
sed 's/^X//' > Mri.h <<'+FUNKY+STUFF+'
X/*
X*******************************************************************************
X*
X* SCCS_data: %Z%%M% %I%(%G%)
X*
X* Include_name:
X*
X*     Mri.h
X*
X* Subsystem_group:
X*
X*     Motif Resource Interpreter
X*
X* Related_keywords:
X*
X*     Public Defines
X*
X* Include_description:
X*
X*     Public defines for the Motif Resource Interpreter which supports
X*     widget tree creation and callback binding from the Xrm database.
X*
X* Include_history:
X*
X*   mm/dd/yy  initials  action
X*   --------  --------  -------------------------------------------------------
X*   03/02/90   marbru   created
X*   04/03/90   d.smyth  added MriSetValueFromString() and globals.
X*   04/05/90   d.smyth  renamed to Mri
X*
X*******************************************************************************
X*/
X#ifndef _Mri_h
X#define _Mri_h
X
X/*
X    -- These MUST be defined by the application 
X*******************************************************************************
X*/
X
Xextern char		appName[];
Xextern char		appClass[];
Xextern XrmOptionDescRec	appOptions[];
Xextern Cardinal		numOptions;
X
Xextern void	UserInitialization();
X/*	int         *argc;	in/out, reflect returned size of argv 
X *	char        *argv[];	in/out, should remove any consumed args 
X */
X
Xextern void RegisterApplicationCallbacks();
X/*    int         *argc;
X *    char        *argv[];
X *    XtAppContext app;
X */
X
X/*
X*******************************************************************************
X*/
X
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
X/* -- Resource Converter Registration Routines
X*******************************************************************************
X*/
X
Xextern void MriAddStringToWidgetP();
Xextern void MriAddStringToCallbackP();
X
X/* -- Widget class, constructor, and callback registration routines
X*******************************************************************************
X*/
X
Xextern void MriRegisterObjectClass ();
X/*	XtAppContext	app;		not used (yet), must be present
X *	char*		name;		class name, case insensitive
X *	WidgetClass	class;		Xt WidgetClassStruct pointer
X */
X
Xextern void MriRegisterConstructor ();
X/*      XtAppContext    app;    	not used (yet), must be present
X *      char*           name;   	constructor name, case insensitive
X *      Widget (*constructor) ();	pointer to a widget creation routine
X */
X
Xextern void MriRegisterCallback    ();
X/*      XtAppContext    app;    	not used (yet), must be present
X *      char*           name;   	callback name, case insensitive
X *	XtCallbackProc  callback;	pointer to callback function
X *	caddr_t         closure;	default closure (client data)
X */
X
Xextern void MriRegisterMriCallbacks();
X/*      XtAppContext    app;            not used (yet), must be present
X */
X
X/* -- Widget creation routine 
X*******************************************************************************
X      Creates widgets declared in the Xrm database.
X*/
X
Xextern void MriCreateXrmChildren  ();
X/*	Widget w;	create children of this widget
X */
X
X/* -- Convenience callbacks: 
X*******************************************************************************
X      In all cases, drop the initial "Mri" to reference any of these
X      callbacks in a resource file.  For example, the following resource
X      file line would cause MriCreateDynamicWidgetCB() to be invoked 
X      creating a new dynamic child of "main" called "foo" due to a 
X      button press on the XmButton widget named "button"
X
X	*button.activateCallback:  MriCreateDynamicWidgetCB( main.foo )
X*/
X
Xextern void MriCreateDynamicWidgetCB();
X/*	Widget w;		widget issuing callback
X *	caddr_t client;		list of named children
X *	caddr_t call;		not used
X */
X
Xextern void MriManageNamedChildrenCB();
X/*	Widget	w;		widget issuing callback
X *	caddr_t	client;		list of named children
X *	caddr_t	call;		not used
X */
X
Xextern void MriUnmanageNamedChildrenCB();
X/*	Widget	w;		widget issuing callback
X *      caddr_t client;         list of named children
X *      caddr_t call;           not used
X */
X
Xextern void MriSetResourceOnWidgetCB();
X/*      Widget  w;              widget issuing callback
X *      caddr_t client;         res_name, res_val, target [,target] ...
X *      caddr_t call;           not used
X */
X
Xextern void MriQuitApplicationCB();
X/*      Widget  w;              widget issuing callback (not used)
X *      caddr_t client;         exit value
X *      caddr_t call;           not used
X */
X
Xextern void MriLoadResourceFileCB();
X/*      Widget  w;              widget issuing callback
X *      caddr_t client;         X resource filename
X *      caddr_t call;           not used
X */
X
X/* -- Convenience functions:
X*******************************************************************************
X*/
X
Xextern void MriNamesToWidgetList();
X/*	Widget	reference;	name search starts at root of this widget
X *	char*	list_of_names;	comma separated full path names
X *	Widget	widget_list[];	returned widget list, caller's storage
X *	int*	widget_count;	returned count of widgets, caller's storage
X */
X
Xextern void MriSetValueFromString();
X/*	Widget	target;		set value on this widget
X *	char*	resource_name;	resource to be set
X *	char*	resource_value;	value converted from string to whatever
X */
X
Xextern void MriDumpFullNameOfWidget();
X/*      Widget w;       dump full path name of this widget to stderr
X */
X
X/* -- Mri control globals */
X
Xextern Widget		app_shellW;	/* application shell widget */
Xextern XtAppContext	app;
Xextern Boolean 		debugging;
X
X#endif  /* _Mri_h */
+FUNKY+STUFF+
echo '-rw-r--r--  1 david        5610 Apr 11 09:30 Mri.h    (as sent)'
chmod u=rw,g=r,o=r Mri.h
ls -l Mri.h
echo x - MriP.h
sed 's/^X//' > MriP.h <<'+FUNKY+STUFF+'
X/*
X*******************************************************************************
X*
X* SCCS_data: %Z%%M% %I%(%G%)
X*
X* Include_name:
X*
X*     MriP.h
X*
X* Subsystem_group:
X*
X*     Motif Resource Interpreter
X*
X* Related_keywords:
X*
X*     Private Defines
X*
X* Include_description:
X*
X*     Private defines for the Motif Resource Interpreter which supports
X*     widget tree creation and callback binding from the Xrm database.
X*
X* Include_history:
X*
X*   mm/dd/yy  initials  action
X*   --------  --------  -------------------------------------------------------
X*   04/09/90   d.smyth  extracted from Mri.c, named MriP.h
X*
X*******************************************************************************
X*/
X
X#ifndef _MrPi_h
X#define _MriP_h
X
X/*
X*******************************************************************************
X* Private_constant_declarations.
X*******************************************************************************
X*/
X
X#undef  NUL
X#define NUL '\0'
X
X#define ADD_CLASSES      16             /* increment of class cache         */
X#define MAX_CALLBACKS    64             /* max number of callbacks per list */
X#define ADD_CALLBACKS    16             /* increment of callback cache size */
X
X#define MriNxrmCreateCallback "xrmCreateCallback"
X#define MriCXrmCreateCallback "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*/
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
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*******************************************************************************
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
Xextern int         classes_num;
Xextern int         classes_max;
Xextern ClCacheRec *classes_ptr;
X
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
Xextern int         callbacks_num;
Xextern int         callbacks_max;
Xextern CBCacheRec *callbacks_ptr;
X
X/*
X*******************************************************************************
X* Private_function_declarations.
X*******************************************************************************
X*/
X
Xextern Widget CallCreateCallback();
X/*	Widget w;	invokes this widget's creation callbacks
X */
X
Xextern Boolean GetChildNameAndConstructor();
X/*	Widget w;	child's parent
X *	char*  type;	"managed", "unmanaged", "dynamic", or "unmDynamic"
X *	int    nn;	child number to look for ex: managedChild_2
X *	char*  name;	returned child name - caller alloc's storage
X *	char*  constr;	returned constructor name - caller alloc's storage
X *	Boolean *recur; returned recursive flag - caller's storage
X */
X
Xextern Boolean FindClassOrConstrFromCache();
X/*	char*		constr;		name of widget constructor
X *	struct Found   *found;		class or constr
X */
X
Xextern Widget CreateChildUsingCache();
X/*	Widget      parent;
X *	char*       child_name;
X *	char*       constructor;
X *	Boolean     recursive;
X */
X
Xextern Widget CreateDatabaseChild();
X/*	Widget w;	child's parent
X *	char*  type;	"managed", "unmanaged", "dynamic", or "unmDynamic"
X *	int    nn;	child number to look for ex: managedChild_2
X */
X
Xextern void CreateDynamicChild();
X/*	Widget w;	child's parent
X *	char*  name;	child's name
X */
X
X#endif _MrPi_h
+FUNKY+STUFF+
echo '-rw-r--r--  1 david        4688 Apr 10 10:37 MriP.h    (as sent)'
chmod u=rw,g=r,o=r MriP.h
ls -l MriP.h
echo x - MriCallbacks.c
sed 's/^X//' > MriCallbacks.c <<'+FUNKY+STUFF+'
X/*
X*******************************************************************************
X*
X* SCCS_data: %Z%%M% %I%(%G%)
X*
X* Module_name:
X*
X*     MriCallbacks.c
X*
X* Subsystem_group:
X*
X*     Motif Resource Interpreter, Utility Callback Routines
X*
X* Related_keywords: 
X*
X*     Widget, Callback
X*
X* Module_description:
X*
X*     This module contains convenience callbacks which seem generally
X*     useful.
X*
X*     Since (for portability reasons) we can not assume runtime binding,
X*     all widget callback routines must be "registered" by the application 
X*     BEFORE widget tree creation.  The standard callbacks, defined
X*     in this file, get registered by the main() routine in MriMain.c
X*     when it invokes MriRegisterStandardCallbacks().
X*
X*     Several convenience callbacks are provided here, more will probably
X*     follow.
X*
X* Module_interface_summary: 
X*
X*     Convenience Callbacks:
X*
X*	MriCreateDynamicWidgetCB ()    - creates named dynamic widget
X*       MriManageNamedChildrenCB ()    - manages named widgets
X*       MriUnmanageNamedChidrenCB()    - unmanages named widgets
X*       MriSetResourceOnWidgetCB ()    - sets resource in named widgets
X*	MriQuitApplicationCB     ()    - calls exit()
X*       MriLoadResourceFileCB    ()    - loads a new database file 
X*					 (currently unimplemented)
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*   04/05/90  d.smyth	Dynamic Creation, rename to Mri
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 <stdio.h>
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#include <X11/CoreP.h>
X#include <XmP.h>
X
X/*  -- Motif Resource Interpreter Includes */
X#include "Mri.h"
X#include "MriP.h"
X
X/*
X    -- Create Dynamic Widgets callback
X*******************************************************************************
X
X    Creates the named widgets dynamically.  The widget names, which
X    is obtained as a string in client data, must be a comma separated
X    list of full widget path names (well, full path except for the 
X    ApplicationShell widget).
X
X    The widgets which may be dynamically created are specified in the
X    resource file like this:
X
X    App.foo.bar.managedDynChild_0:	glorp, XmRowColumn
X    App.foo.bar.unmanagedDynChild_0:	dweep, XmLabel
X
X    The first specifies a child which will be managed after creation,
X    the second widget child will not be managed.  Neither is created
X    initially, but only if specifically named in a call to this callback.
X
X    For example, lets say a button's activate callback is specified to
X    cause a "glorp" to be created as a child of foo.bar according to the 
X    above resource spec:
X
X    App.nerf.button.activateCallback:	CreateDynamicWidgetCB(foo.bar.glorp)
X
X    Multiple dynamic widgets can be created in one invocation, for example:
X
X    App.nerf.button.activateCallback:	CreateDynamicWidgetCB(foo.bar.glorp, \
X							      foo.bar.dweep)
X
X    ( The backslash at the end of the line is recognized by the resource
X    manager and stripped out, allowing arbitrarily long resource specs.)
X    Note that the created widgets can be, and usually are, children of 
X    widgets other than the widget which is invoking the callback: children
X    must be parented by manager widgets, and callbacks are usually invoked 
X    from buttons (subclassed from Primitive, not Manager).
X
X*/
Xvoid MriCreateDynamicWidgetCB ( w,  client, call )
XWidget w;
Xcaddr_t client;		/* client data, list of named children */
Xcaddr_t call;		/* call data,   not used */
X{
X    typedef struct _pair {
X	char         *parent;
X	char         *child;
X	struct _pair *next;
X    } PairStruct, *Pair;
X
X    Pair  pair, first_pair;
X
X    char *first, *last, *comma, *p, *ch, *c;
X
X    pair = first_pair = NULL;
X
X    first = client;
X
X    while ( *first )
X    {
X	if ( *first <= ' ' || *first == ',' )
X	{
X	    first++ ; continue;		/* skip leading whitespace */
X	}
X
X	comma = index( first, ',' );	/* find the next comma */
X	if (comma == NULL)
X	    comma = index( first, '\0' ); /* no comma, so find end */
X
X	last = comma - 1;
X	while (first < last && *last != '.')
X	    last--;
X
X	/* now first points to first char of parent's name, and
X	** last points to last '.' which terminates parent's.  
X	** comma still points to the next comma or the end.
X	*/
X
X	{
X	    Pair new_pair = (Pair)XtMalloc(sizeof(PairStruct));
X	    if (pair == NULL)
X		first_pair = new_pair;	/* never made one before */
X	    else
X		pair->next = new_pair;	/* else add to linked list */
X	    pair = new_pair;
X	}
X
X	pair->parent = p  = (char*)XtMalloc( (last - first) + 1 );
X	pair->child  = ch = (char*)XtMalloc( (comma - last) + 1 );
X	pair->next   = NULL;
X
X	c = first;
X	while (c < last)		/* don't copy final `.' */
X	    *p++ = *c++;
X	*p = NUL;			/* null terminate parent name */
X
X	c++;				/* skip the `.' */
X	while (c < comma && *c > ' ')	/* stop before comma or whitespace */
X	    *ch++ = *c++;
X	*ch = NUL;			/* null terminate child name */
X		
X	first = comma;
X    }
X    if (first_pair == NULL)
X    {
X	XtWarning("No widget names passed to CreateDynamicWidgetCB()");
X	return;
X    }
X
X    /* Create Children */
X    pair = first_pair;
X    while(pair)
X    {
X        Widget widget_list[MAX_CHILDREN];
X        int    widget_count;
X    
X        MriNamesToWidgetList ( w, pair->parent, widget_list, &widget_count );
X        if (widget_count == 1)
X	{
X	    CreateDynamicChild( widget_list[0], pair->child );
X	    pair = pair->next;
X	}
X	else
X	{
X	    /* XtWarning("CreateDynamicWidgetCB arguments are garbled"); */
X	    break;
X	}
X    }
X
X    /* Free allocated temporary storage */
X    pair = first_pair;
X    while(pair)
X    {
X	XtFree(pair->parent);
X	XtFree(pair->child);
X	XtFree(pair);
X	pair = pair->next;
X    }
X    return;
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 MriManageNamedChildrenCB ( 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    MriNamesToWidgetList ( 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 MriUnmanageNamedChildrenCB ( 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    MriNamesToWidgetList ( w, client, widget_list, &widget_count );
X    XtUnmanageChildren  ( widget_list, widget_count );
X}
X
X/*
X    -- Set Resource on Widget(s) Resource Callback
X*******************************************************************************
X    This callback loads resource values into resources on the named widget(s).
X
X    The client data argument has a format:
X        
X        resource_name,resource value,target_widget_name[,target_widget_name...]
X
X    The special resource value of "this" means "this widget."  Typically,
X    using "this" as the resource value is used to set the "XmNdefaultButton" 
X    resource on a XmbulletinBoard, "menuBar", "workArea", etc on XmMainWindows,
X    the subMenuId resource on menuBar cascade buttons, and so on.
X*/
Xvoid MriSetResourceOnWidgetCB ( w,  client, call )
XWidget w;
Xcaddr_t client;		/* client data: res_name, res_val, target [,target] ...
Xcaddr_t call;		/* call data,   not used */
X{
X    char	   resource[MAX_XRMSTRING];
X    char	   res_val[MAX_XRMSTRING];
X    Widget*	   widget_list[MAX_CHILDREN];
X    Cardinal	   widget_count;
X    register char *d,*s;
X    register int   i;
X    Arg            args[1];
X    static char*   msg = 
X"Usage: SetResourceOnWidgetCB( res_name, res_value, widget [,widget ... ] )";
X
X    /* copy from client into resource[]
X    ** ignore all whitespace, warning if no resource name.
X    */
X    s = client;
X    if (*s == ',' || *s == NUL)
X    {
X        XtWarning(msg); return;
X    }
X    for ( d=resource ; (*s && *s!=',') ; s++ )
X        if (*s > ' ') *d++ = *s;
X    *d = NUL;
X
X    /* copy from client into res_val[] 
X    ** skip leading whitespace, warning if no resource value.  
X    */
X    if (*s++ == NUL)
X    {
X	XtWarning(msg); return;
X    }
X    while (*s && *s == ' ')
X	s++;
X    if (*s == ',' || *s == NUL)
X    {
X        XtWarning(msg); return;
X    }
X    for ( d=res_val ; (*s && *s!=',') ; s++ )
X        *d++ = *s;
X    *d = NUL;
X
X    /* now get widgets from the rest of the client[] string */
X    if (*s == ',' ) s++;
X    if (*s == NUL )
X    {
X	XtWarning(msg); return;
X    }
X    MriNamesToWidgetList ( w, s, widget_list, &widget_count );
X
X    /* set the resource on the widgets */
X
X    if (0 == strcmp(res_val,"this"))
X    {
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    else
X    {
X        for (i=0; i<widget_count; i++)
X	{
X	    /* convert to appropriate value and call XtSetValue() */
X	    MriSetValueFromString( widget_list[i], resource, res_val );
X	}
X    }
X}
X
X/*
X    -- Quit the application
X*******************************************************************************
X    Call exit().
X*/
Xvoid MriQuitApplicationCB ( w,  client, call )
XWidget w;
Xcaddr_t client;         /* client data, not used */
Xcaddr_t call;           /* call data,   not used */
X{
X    int exitval = 0;
X    if (client)
X    {
X	/* skip leading garbage before int */
X	while (*client)
X	{
X	    if ('0' < *client && *client <= '9')
X		break; /* found numbers, convert to exitval */
X	    client++;
X	}
X
X	/* convert to int */
X	while (*client)
X	{
X	    if ('0' < *client && *client <= '9')
X	    {
X		exitval = exitval * 10 + (*client - '0');
X		client++;
X	    }
X	    else
X		break;	/* ignore trailing garbage */
X	}
X    }
X    exit(exitval);
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 MriLoadResourceFileCB ( 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
+FUNKY+STUFF+
echo '-rw-r--r--  1 david       11869 Apr 11 09:40 MriCallbacks.c    (as sent)'
chmod u=rw,g=r,o=r MriCallbacks.c
ls -l MriCallbacks.c
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