[comp.sources.x] v06i068: Motif Resource Interpreter, Part02/03

david@jpl-devvax.jpl.nasa.gov (David E. Smyth) (04/12/90)

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

# to unbundle, "sh" this file -- DO NOT use csh
#  SHAR archive format.  Archive created Wed Apr 11 09:59:58 PDT 1990
echo x - MriCreate.c
sed 's/^X//' > MriCreate.c <<'+FUNKY+STUFF+'
X/*
X*******************************************************************************
X*
X* SCCS_data: %Z%%M% %I%(%G%)
X*
X* Module_name:
X*
X*     MriCreate.c
X*
X* Subsystem_group:
X*
X*     Motif Resource Interpreter, 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.managedChild_n:    name,constructor[,n[onrecursive]]
X*     toplevel...widget.unmangedChild_n:   name,constructor[,n[onrecursive]]
X*     toplevel...widget.dynamicChild_n:    name,constructor[,n[onrecursive]]
X*     toplevel...widget.unmDynamicChild_n: name,constructor[,n[onrecursive]]
X*
X*     Example:
X*     helloWorld.managedChild_0:              box,XmCreateRowColumn
X*     helloWorld.box.managedChild_0:          label,XmCreateLabel
X*     helloWorld.box.managedChild_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 MriCreateXrmChildren()
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*     Mri Public Functions:
X*
X*  void MriCreateXrmChildren ( 		- create children from Xrm
X*	Widget w)	- root of tree
X*
X*     Mri Private Functions:
X*
X*  Widget CallCreateCallback ( w )  	- invokes callbacks after creation
X*  Boolean GetChildNameAndConstructor(	- True if child found
X*	Widget w,	- parent
X*	char* type	- "managed", "unmanaged", "dynamic", or "unmDynamic"
X*	int   nn,	- child 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*  Widget CreateDatabaseChild (
X*	Widget  w,	- child's parent
X*	String  type,	- "managed" or "unmanaged"
X*	int     nn )	- child to look for, ex: managedChild_2
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/03/90  d.smyth   MriSetValueFromString new func
X*   04/05/90  d.smyth	Dynamic Creation, rename to Mri
X*   04/09/90  d.smyth   Now contains only funcs related to creation.
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    -- 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*/
XWidget CallCreateCallback ( w )
XWidget  w;		/* child's parent */
X{
X    static XtResource res[] =
X    {
X      { MriNxrmCreateCallback, MriCXrmCreateCallback, 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
XBoolean GetChildNameAndConstructor( w,  type, nn, name, constr, recur )
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    XtResource c_resource[1];
X    Boolean   recursive;
X    char      res_name[20];     /* unmDynamicChild_nnn is 20 char w/ null */
X    char*     string;           /* will point into Xrm storage */
X
X    /* update our resource list to look for  typeChild_nn subresource */
X    sprintf ( res_name, "%sChild_%d", type, nn );
X    c_resource[0].resource_name  = res_name;
X    c_resource[0].resource_class = res_name;  /* no class allowed / used */
X    c_resource[0].resource_type  = XtRString;
X    c_resource[0].resource_size  = sizeof(String);
X    c_resource[0].resource_offset= 0;
X    c_resource[0].default_type   = XtRImmediate;
X    c_resource[0].default_addr   = (caddr_t)NULL;
X
X    XtGetApplicationResources ( w, &string, c_resource, 1, NULL, 0 );
X
X    /* Xrm query returned a string for [un]managedChild_n resource, process */
X    if ( string == NULL )
X    {
X        /* No such resource stored in the database */
X        return FALSE;
X    }
X    else
X    {
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",
X                *name ) ;
X            XtWarning( msg );
X            return FALSE;
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        *recur = ( *s==',' && (s[1]=='n' || s[1]=='N') ) ? FALSE : TRUE;
X
X        return TRUE;
X    }
X}
X
Xtypedef struct
X{
X    Widget      (*const)();	/* pointer to func, i.e., &XmCreateForm() */
X    WidgetClass	  class;	/* pointer to WidgetClassRec		  */
X} Found;
X
XBoolean FindClassOrConstrFromCache( constr, found )
X    char*	constr;
X    Found*	found;
X{
X    XrmQuark	quark;
X    int		i;
X
X    quark = XrmStringToQuark ( constr );
X    for (i=0; i<classes_num; i++)
X    {
X       if ( classes_ptr[i].quark == quark )
X       {
X            found->class = classes_ptr[i].class;
X            found->const = classes_ptr[i].constructor;
X            return TRUE;
X       }
X    }
X    return FALSE;
X}
X
XWidget CreateChildUsingCache( parent, child_name, constructor, recursive)
X    Widget      parent;
X    char*	child_name;
X    char*       constructor;
X    Boolean     recursive;
X{
X    Found found;
X    found.const = NULL;
X    found.class = NULL;
X
X    if ( FindClassOrConstrFromCache ( constructor, &found ) )
X    {
X	Widget child;
X
X       if ( found.class )
X           child = XtCreateWidget ( child_name,  found.class, parent, NULL, 0 );
X       else
X           child = (*found.const) ( parent, child_name, NULL, 0 );
X
X       if (debugging)
X           MriDumpFullNameOfWidget(child);
X
X       CallCreateCallback ( child );
X
X       if ( recursive )
X           MriCreateXrmChildren ( child );
X
X        return child;
X    }
X    else
X    {
X	char msg[MAX_ERRMSG];
X        sprintf ( msg,
X            "Cannot create child %s using %s, unknown class/constructor",
X             child_name, constructor );
X        XtWarning( msg );
X        return (Widget)NULL;
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.managedChild_nn:    name.constr_name[,n[onrecursive]]
X     ...widget.unmanagedChild_nn:    name.constr_name[,n[onrecursive]]
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,  type, nn )
XWidget  w;		/* child's parent */
XString  type;		/* child type: managed or unmanaged */
Xint     nn;		/* child # to look for */
X{
X    char      name  [MAX_XRMSTRING];
X    char      constr[MAX_XRMSTRING];
X    Boolean   recursive;
X
X    if (GetChildNameAndConstructor( w, type, nn, name, constr, &recursive))
X    {
X	/* if we'w found a class or constructor, create child, call callback */
X	return CreateChildUsingCache( w, name, constr, recursive );
X    }
X    else
X    {
X	return (Widget)NULL;
X    }
X}
X
X/*
X*******************************************************************************
X* Public_function_declarations.
X*******************************************************************************
X*/
X
X/*
X    -- Create Xrm Database Children
X*******************************************************************************
X    This routine creates widget children as defined in X resource database.
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 database search overhead, we only attempt to create
X    children for composite widgets and objects.
X*/
Xvoid MriCreateXrmChildren ( 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, "managed", i );
X	if ( child )
X	  managed[num++] = child;
X	else
X	  child = CreateDatabaseChild ( w, "unmanaged", i );
X 	prev = child;
X    }
X    XtManageChildren(managed, num );
X}
+FUNKY+STUFF+
echo '-rw-r--r--  1 david       11797 Apr 10 09:53 MriCreate.c    (as sent)'
chmod u=rw,g=r,o=r MriCreate.c
ls -l MriCreate.c
echo x - MriCvts.c
sed 's/^X//' > MriCvts.c <<'+FUNKY+STUFF+'
X/*
X*******************************************************************************
X*
X* SCCS_data: %Z%%M% %I%(%G%)
X*
X* Module_name:
X*
X*     MriCvts
X*
X* Subsystem_group:
X*
X*     Motif Resource Interpreter
X*
X* Related_keywords: 
X*
X*     Create Motif Widgets from Xrm Database
X*
X* Module_description:
X*
X*     This module contains the String To Callback X resource converter,
X*     and the String To Widget X resource converter.  These are "old
X*     style converters, registered with XtAddConverters, and do not
X*     get a Display as the first argument.
X*
X*     The String to Callback converter parses the resource string in the 
X*     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*     The String to Widget converter parses the resource string which
X*     matches any valid complete or wildcarded widget name to a widget
X*     id.  The search begins at the root.  The first widget whose name
X*     matches is "returned."
X*
X* Module_interface_summary: 
X*
X*
X*     Resource converters are invoked indirectly by the toolkit. The
X*     converters are added to the toolkit by widgets by calling 
X*     MriAddStringToCallbackP() and MriAddStringToWidgetP() in the 
X*     widget intialization code (see main()).
X*
X* Module_history:
X*                                                  
X*   mm/dd/yy  initials  function  		action
X*   --------  --------  ----------------------  -----------------------------
X*   04/05/90  D.E.Smyth 			Renamed to Mri
X*   03/28/90  D.E.Smyth CvtStringToWidget	Created
X*   02/26/90  MarBru    CvtStringToCallback     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/*  -- Motif Resource Interpreter Include */
X#include "Mri.h"
X#include "MriP.h"
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 (string == 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    -- Convert String To Widget
X*******************************************************************************
X    This conversion simply makes use of XtNameToWidget().
X*/
X
Xvoid
XCvtStringToWidget (args, num_args, fromVal, toVal)
X    XrmValue *args;
X    Cardinal *num_args;
X    XrmValue *fromVal;
X    XrmValue *toVal;
X{
X    toVal->addr = (caddr_t) XtNameToWidget(app_shellW, fromVal->addr);
X}
X
X/*
X*******************************************************************************
X* Public_function_declarations.
X*******************************************************************************
X*/
X
X/*
X    -- Add String To Callback Convertor
X*******************************************************************************
X*/
X
Xvoid MriAddStringToCallbackP ()
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
Xvoid MriAddStringToWidgetP ()
X{
X    static Boolean added = FALSE;
X    if ( !added )
X    {
X       XtAddConverter    (XtRString,
X                          "Window",	/* wrong, but it works !?! */
X                          CvtStringToWidget,
X                          (XtConvertArgList)NULL,
X                          (Cardinal)0);
X       added = TRUE;
X    }
X}
+FUNKY+STUFF+
echo '-rw-r--r--  1 david        8495 Apr 10 10:13 MriCvts.c    (as sent)'
chmod u=rw,g=r,o=r MriCvts.c
ls -l MriCvts.c
echo x - MriDynCreate.c
sed 's/^X//' > MriDynCreate.c <<'+FUNKY+STUFF+'
X/*
X*******************************************************************************
X*
X* SCCS_data: %Z%%M% %I%(%G%)
X*
X* Module_name:
X*
X*     MriDynCreate.c
X*
X* Subsystem_group:
X*
X*     Motif Resource Interpreter, 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 dynamically create and manage a widget tree using the 
X*     Xrm databse.  The Xrm database format used to define widget's 
X*     children is as follows:
X*
X*     toplevel...widget.managedChild_n:    name,constructor[,n[onrecursive]]
X*     toplevel...widget.unmangedChild_n:   name,constructor[,n[onrecursive]]
X*     toplevel...widget.dynamicChild_n:    name,constructor[,n[onrecursive]]
X*     toplevel...widget.unmDynamicChild_n: name,constructor[,n[onrecursive]]
X*
X*     Only the dynamicChild_n and unmDynamicChild_n cases are
X*     handled in this module.
X*
X*     Example:
X*     helloWorld.dynamicChild_n:              box,XmCreateRowColumn
X*     helloWorld.box.managedChild_0:          label,XmCreateLabel
X*     helloWorld.box.managedChild_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*     The widget tree, consisting of the box with a label and button
X*     as its children, are created dynamically, generally as the result
X*     of an ivocation of MriCreateDynamicWidgetCB().
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*     Only the first widget is created herein.  Any children of the first
X*     (the label and button in the example) get created via the 
X*     MriCreateXrmChildren() function.
X*
X* Module_interface_summary: 
X*
X*     Creation and Private Functions:
X*
X*	CreateDynamicChild()
X*
X* Module_history:
X*                                                  
X*   mm/dd/yy  initials  function  action
X*   --------  --------  --------  ---------------------------------------------
X*   04/05/90  d.smyth	Dynamic Creation
X*   04/09/90  d.smyth   Now contains only funcs related to dynamic creation.
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 Named Dynamic Child
X*******************************************************************************
X    Get all the DynamicChild_xx and unmDynamicChild_xx resources
X    for the parent, and create the widget whose name matches the
X    child arg.
X*/
Xvoid CreateDynamicChild( parent, child_name )
X    Widget parent;
X    char  *child_name;
X{
X    int		nn = 0;
X    char	name[MAX_XRMSTRING];
X    char	constr[MAX_XRMSTRING];
X    Boolean	recursive;
X
X    while (GetChildNameAndConstructor( parent, "dynamic", 
X					nn, name, constr, &recursive))
X    {
X	if (strcmp(child_name, name))
X	{
X	    /* Nope, this child is not the one we want, try the next... */
X	    nn++;
X	}
X	else
X	{
X	    /* Yeah!  we found the right child, create and manage it. */
X	    XtManageChild( CreateChildUsingCache(
X				parent, name, constr, recursive));
X	    return;
X	}
X    }
X
X    while (GetChildNameAndConstructor( parent, "unmDynamic",
X                                        nn, name, constr, &recursive))
X    {
X        if (strcmp(child_name, name))
X        {
X            /* Nope, this child is not the one we want, try the next... */
X            nn++;
X        }
X        else
X        {
X            /* Yeah!  we found the right child, create it, but don't manage. */
X	    CreateChildUsingCache( parent, name, constr, recursive );
X            return;
X        }
X    }
X}
X
+FUNKY+STUFF+
echo '-rw-r--r--  1 david        4507 Apr  9 18:16 MriDynCreate.c    (as sent)'
chmod u=rw,g=r,o=r MriDynCreate.c
ls -l MriDynCreate.c
echo x - MriMain.c
sed 's/^X//' > MriMain.c <<'+FUNKY+STUFF+'
X/*
X*******************************************************************************
X*   MriMain.c 
X*******************************************************************************
X    This program uses the Xrm (X resource management) database
X    for a widget tree definition and management.
X    There is very little code in this program, since the entire user interface
X    definition is stored in the Xrm database, preferably in the application
X    class resource file:  ~/apps-defaults/<application>
X/*
X*******************************************************************************
X*   Include_files.
X*******************************************************************************
X    All Motif things are included, so the interface
X    may be arbitrarily complex.
X*/
X
X/******
X* Core (Object, RectObj, WindowObj), Gadget, Composite, Primitive,
X* Shell, OverrideShell, WMShell, VendorShell, TopLevelShell, 
X* ApplicationShell, TransientShell, Constraint, and Manager :
X******/
X#include <Xm/Xm.h>
X
X/****** 
X* Primitive Widgets and Gadgets: 
X******/
X#include <Xm/ArrowB.h>
X#include <Xm/ArrowBG.h>
X#include <Xm/CascadeB.h>
X#include <Xm/CascadeBG.h>
X#include <Xm/DrawnB.h>
X#include <Xm/Label.h>
X#include <Xm/LabelG.h>
X#include <Xm/List.h>
X#include <Xm/PushB.h>
X#include <Xm/PushBG.h>
X#include <Xm/ScrollBar.h>
X#include <Xm/SeparatoG.h>
X#include <Xm/Separator.h>
X#include <Xm/Text.h>
X#include <Xm/ToggleB.h>
X#include <Xm/ToggleBG.h>
X
X/******
X* Shell Widgets:
X******/
X#include <Xm/DialogS.h>
X#include <Xm/MenuShell.h>
X
X/******
X* Manager Widgets:
X******/
X#include <Xm/BulletinB.h>
X#include <Xm/Command.h>
X#include <Xm/DrawingA.h>
X#include <Xm/FileSB.h>
X#include <Xm/Form.h>
X#include <Xm/Frame.h>
X#include <Xm/MainW.h>
X#include <Xm/MessageB.h>
X#include <Xm/PanedW.h>
X#include <Xm/RowColumn.h>
X#include <Xm/Scale.h>
X#include <Xm/ScrolledW.h>
X#include <Xm/SelectioB.h>
X
X/******
X* Other Motif Includes
X******
X* #include <Xm/CutPaste.h>
X* #include <Xm/bitmaps.h>
X* #include <Xm/mwm.h>
X******/
X
X/******
X* Motif Resource Interpreter Xrm Creation and Callback routines
X******/
X#include "Mri.h"
X
XWidget		app_shellW;		/* application shell widget */
XXtAppContext 	app;
XBoolean		debugging = 0;
X
Xstatic XtResource debugRes[] =
X{
X    {	/* set debugging from resource database and command line:	*/
X	"debugging", "Debugging", 	/* resource name and class	*/
X	XmRBoolean, sizeof(Boolean),	/* resource type and size	*/
X	0,				/* no offset - store directly	*/
X    	XmRString, "False"		/* default value		*/
X    }
X};
X
X/* 
X*******************************************************************************
X*   MAIN function
X*******************************************************************************
X*/
X
Xmain ( argc, argv )
Xint    argc;
Xchar **argv;
X{   
X    UserInitialization( &argc, argv );
X
X/*  -- Intialize Xt Toolkit creating the application shell */
X    app_shellW = XtInitialize ( appName, appClass,
X				appOptions, numOptions,
X				&argc, argv );
X    app        = XtWidgetToApplicationContext(app_shellW);
X
X/*  -- set debugging flag */
X    XtGetApplicationResources(	app_shellW, 
X	&debugging, 			/* set debugging from resources	*/
X	debugRes, XtNumber(debugRes),	/* app resource specification	*/
X	NULL, 0);			/* argv not checked here...	*/
X
X    if ('D' == getopt(argc, argv, "D"))	/* ... but here			*/
X        debugging++;
X
X/*  -- Register Converters */
X    MriAddStringToWidgetP();
X    MriAddStringToCallbackP();
X
X/*  -- Register available Widget constructors - N.B. Case Insensitive */
X#define CON(n,c) MriRegisterConstructor(app,n,c)
X
X    CON ( "xmArrowButton",		XmCreateArrowButton		);
X    CON ( "xmArrowButtonGadget",	XmCreateArrowButtonGadget	);
X    CON ( "xmBulletinBoard",		XmCreateBulletinBoard		);
X    CON ( "xmBulletinBoardDialog",	XmCreateBulletinBoardDialog	);
X    CON ( "xmCascadeButton",		XmCreateCascadeButton		);
X    CON ( "xmCascadeButtonGadget",	XmCreateCascadeButtonGadget	);
X    CON ( "xmCommand",			XmCreateCommand			);
X    CON ( "xmDialogShell",		XmCreateDialogShell		);
X    CON ( "xmDrawingArea",		XmCreateDrawingArea		);
X    CON ( "xmDrawnButton",		XmCreateDrawnButton		);
X    CON ( "xmErrorDialog",		XmCreateErrorDialog		);
X    CON ( "xmFileSelectionBox",		XmCreateFileSelectionBox	);
X    CON ( "xmFileSelectionDialog",	XmCreateFileSelectionDialog	);
X    CON ( "xmForm",			XmCreateForm			);
X    CON ( "xmFormDialog",		XmCreateFormDialog		);
X    CON ( "xmFrame",			XmCreateFrame			);
X    CON ( "xmInformationDialog",	XmCreateInformationDialog	);
X    CON ( "xmLabel",			XmCreateLabel			);
X    CON ( "xmLabelGadget",		XmCreateLabelGadget		);
X    CON ( "xmList",			XmCreateList			);
X    CON ( "xmMainWindow",		XmCreateMainWindow		);
X    CON ( "xmMenuBar",			XmCreateMenuBar			);
X    CON ( "xmMenuShell",		XmCreateMenuShell		);
X    CON ( "xmMessageBox",		XmCreateMessageBox		);
X    CON ( "xmMessageDialog",		XmCreateMessageDialog		);
X    CON ( "xmOptionMenu",		XmCreateOptionMenu		);
X    CON ( "xmPanedWindow",		XmCreatePanedWindow		);
X    CON ( "xmPopupMenu",		XmCreatePopupMenu		);
X    CON ( "xmPromptDialog",		XmCreatePromptDialog		);
X    CON ( "xmPushButton",		XmCreatePushButton		);
X    CON ( "xmPushButtonGadget",		XmCreatePushButtonGadget	);
X    CON ( "xmPulldownMenu",		XmCreatePulldownMenu		);
X    CON ( "xmQuestionDialog",		XmCreateQuestionDialog		);
X    CON ( "xmRadioBox",			XmCreateRadioBox		);
X    CON ( "xmRowColumn",		XmCreateRowColumn		);
X    CON ( "xmScrollBar",		XmCreateScrollBar		);
X    CON ( "xmScrolledList",		XmCreateScrolledList		);
X    CON ( "xmScrolledText",		XmCreateScrolledText		);
X    CON ( "xmScrolledWindow",		XmCreateScrolledWindow		);
X    CON ( "xmScale",			XmCreateScale			);
X    CON ( "xmSelectionBox",		XmCreateSelectionBox		);
X    CON ( "xmSelectionDialog",		XmCreateSelectionDialog		);
X    CON ( "xmSeparator",		XmCreateSeparator		);
X    CON ( "xmSeparatorGadget",		XmCreateSeparatorGadget		);
X    CON ( "xmText",			XmCreateText			);
X    CON ( "xmToggleButton",		XmCreateToggleButton		);
X    CON ( "xmToggleButtonGadget",	XmCreateToggleButtonGadget	);
X    CON ( "xmWarningDialog",		XmCreateWarningDialog		);
X    CON ( "xmWorkingDialog",		XmCreateWorkingDialog		);
X
X#undef CON
X
X/*  -- Register Classes */
X    /* An equivalent way of registering constructors: Registering classes
X    ** means XtCreateWidget() is called instead of XmCreate...().
X    ** Above, we've defined all the Motif constructors, so we don't
X    ** need any Motif classes registered.  However, custom widgets
X    ** might not provide convenience functions, and simply rely on
X    ** XtCreateWidget.  Such classes of widgets must be registered below.
X    */
X#define CLASS(n,c) MriRegisterObjectClass(app, n, c)
X/*  CLASS ( "xmBulletinBoard", xmBulletinBoardWidgetClass); */
X#undef CLASS
X
X/*  -- Register available callbacks:
X    ** Register Mri callbacks, including manage, unmanage, setResource 
X    */
X    MriRegisterMriCallbacks      ( app );
X
X    /* Application provided function, registers appl specific callbacks 
X    */
X    RegisterApplicationCallbacks( &argc, argv, app );
X
X
X/*  -- Create children of the toplevel shell defined by the Xrm database */
X
X    MriCreateXrmChildren   ( app_shellW );
X
X/*  -- Realize the widget tree and enter the main application loop */
X
X    XtRealizeWidget  ( app_shellW );
X    XtMainLoop       ( );
X}
+FUNKY+STUFF+
echo '-rw-r--r--  1 david        7250 Apr 10 14:00 MriMain.c    (as sent)'
chmod u=rw,g=r,o=r MriMain.c
ls -l MriMain.c
echo x - MriMisc.c
sed 's/^X//' > MriMisc.c <<'+FUNKY+STUFF+'
X/*
X*******************************************************************************
X*
X* SCCS_data: %Z%%M% %I%(%G%)
X*
X* Module_name:
X*
X*     MriMisc.c
X*
X* Subsystem_group:
X*
X*     Motif Resource Interpreter, Widget tree creation from Xrm database
X*
X* Related_keywords: 
X*
X*     Widget Name to Widget
X*
X* Module_description:
X*
X*     This module contains the functions which seem generally useful
X*     for application writers when using Mri.
X*
X* Module_interface_summary: 
X*
X*	MriSetValueFromString(	- converts string to val, calls XtSetValue()
X*		Widget w,		- widget to which resources apply
X*		String res_name,	- name or class name of resource 
X*		String res_value )	- string to convert from
X*
X*	MriNameToWidgetList(	- converts a string to separate widgets
X*		String names,		- typ client data as rcvd by a callback
X*		Widget widgets[],	- returned array or widgets
X*		int    *num )		- returned number of widgets
X*
X*	MriDumpFullNameOfWidget(	- dump to stderr
X*		Widget w )		- the full name of this widget
X*
X* Module_history:
X*                                                  
X*   mm/dd/yy  initials  function  action
X*   --------  --------  --------  ---------------------------------------------
X*   04/03/90  d.smyth   MriSetValueFromString new func
X*   04/05/90  d.smyth	moved to this file.
X*
X* Design_notes:
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    -- Convert resource value from string to whatever the widget needs
X*******************************************************************************
X    Gets the XtResourceList from the widget, searches the list for
X    the resource name to determine the type required, then uses the
X    resource manager to convert from string to the required type.
X    Calls XtSetValue with converted type.
X*/
Xvoid
XMriSetValueFromString( w, res_name, res_val)
X    Widget w;					/* MUST already be init'd */
X    char*  res_name;
X    char*  res_val;
X{
X    XtResource*	res_list;
X    int		i, num;
X    char	msg[256];
X    char*	ret_val;
X    char*	ta;
X    XrmValue	fr_val;
X    XrmValue	to_val;
X    Arg		arg[1];
X
X    /* Motif returns an un-quarkified resource list - R4's is quarkified */
X    XtGetResourceList( w->core.widget_class, &res_list, &num );
X
X    for ( i = 0 ; i < num ; i++ )
X    {
X	if (0 == strcmp( res_name, res_list[i].resource_name))
X	    break;
X	else if (0 == strcmp( res_name, res_list[i].resource_class))
X	    break;
X    }
X    if ( i == num )
X    {
X	if (w->core.parent)
X	    sprintf(msg,"%s is not a resource of %s.%s",
X		    res_name, w->core.parent->core.name, w->core.name );
X	else
X	    sprintf(msg,"%s is not a resource of %s",
X		    res_name, w->core.name );
X	XtWarning(msg);
X	return;
X    }
X    else
X    {
X	fr_val.size = strlen(res_val) + 1;
X	fr_val.addr = (caddr_t)res_val;
X	to_val.size = 0;
X	to_val.addr = NULL;
X	XtConvert(
X		w,				/* the widget */
X		XmRString,			/* from type */
X		&fr_val,			/* from value */
X		res_list[i].resource_type,	/* to type */
X		&to_val				/* the converted value */
X	);
X
X	if (to_val.addr)
X	{
X	    /* Conversion worked.  */
X	    switch(to_val.size)
X	    {
X	    case sizeof(char):
X		XtSetArg( arg[0], res_name, *(char*)to_val.addr );
X		break;
X	    case sizeof(short):
X		XtSetArg( arg[0], res_name, *(short*)to_val.addr );
X                break;
X	    case sizeof(int):
X		XtSetArg( arg[0], res_name, *(int*)to_val.addr );
X		break;
X	    default:
X		sprintf(msg,
X			"Bizarre Resource Size in MriSetValueFromString: %d",
X			to_val.size);
X		XtWarning(msg);
X		return;
X	    }
X	    XtSetValues( w, arg, 1 );
X	    return;
X	}
X	else
X	{
X	    /* conversion failed - assume converter called XtWarning */
X	    return;
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
X    The name "this" means the reference widget.
X
X    The widget search starts at the TOP of widget hierarchy (using the
X    top level shell as a reference widget).  The name of the top level
X    shell is NOT specified.
X
X    The widget path name can include wildcards.  See XtNameToWidget()
X    in manual for discussion on how it resolves ambiguities.
X*/
Xvoid
XMriNamesToWidgetList ( w, client, widget_list, widget_count )
X    Widget      w;              /* reference widget */
X    caddr_t     client;         /* callback client data - string of names */
X    Widget      *widget_list;   /* returned widget list */
X    Cardinal    *widget_count;  /* returned widget count */
X{
X    Widget         top;
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    top = w;
X    while ( XtParent(top) ) top = XtParent(top);
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 )
X                return;
X            *d = NUL;
X            if (strcmp("this",name) == 0)
X            {
X                widget_list[*widget_count] = w;
X                (*widget_count)++;
X            }
X            else
X            {
X                widget = XtNameToWidget ( top, name );
X                if ( widget )
X                {
X                    widget_list[*widget_count] = widget;
X                    (*widget_count)++;
X                }
X                else
X                    XtStringConversionWarning (name, "Widget");
X            }
X	    if ( *s == NUL )
X		return;
X            d = name;
X        }
X        else if ( *s > ' ' )
X        {
X            *d++ = *s;
X        }
X        else
X        ;
X    }
X}
X
X/*
X    -- Dump Full Name of Widget
X*******************************************************************************
X    Traverse up the widget tree, print out each name right up to
X    the root of the widget tree.  Print the names to stderr.  Use
X    recursion so order of names comes out right.
X*/
X
Xstatic void DumpNameOfWidget(w)
X    Widget w;
X{
X    if (w->core.parent)
X        DumpNameOfWidget(w->core.parent);
X    fprintf(stderr,"%s.",w->core.name);
X}
X
Xvoid MriDumpFullNameOfWidget(w)
X    Widget w;
X{
X    if (w->core.parent)
X        DumpNameOfWidget(w->core.parent);
X    fprintf(stderr,"%s of class %s\n",
X                w->core.name,
X                w->core.widget_class->core_class.class_name);
X}
X
+FUNKY+STUFF+
echo '-rw-r--r--  1 david        7185 Apr 10 17:26 MriMisc.c    (as sent)'
chmod u=rw,g=r,o=r MriMisc.c
ls -l MriMisc.c
exit 0

dan
-----------------------------------------------------------
		    O'Reilly && Associates
		argv@sun.com / argv@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.