[comp.sources.x] v11i037: wcl - Widget Creation Library, Part25/35

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

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

#! /bin/sh

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

echo "This is wc 1.05 kit 25 (of 35).  If kit 25 is complete, the line"
echo '"'"End of kit 25 (of 35)"'" will echo at the end.'
echo ""
export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
mkdir DemosAthena Wc Xmp 2>/dev/null
echo Extracting Wc/WcName.c
sed >Wc/WcName.c <<'!STUFFY!FUNK!' -e 's/X//'
X/*
X** Copyright (c) 1990 David E. Smyth
X**
X** Redistribution and use in source and binary forms are permitted
X** provided that the above copyright notice and this paragraph are
X** duplicated in all such forms and that any documentation, advertising
X** materials, and other materials related to such distribution and use
X** acknowledge that the software was developed by David E. Smyth.  The
X** name of David E. Smyth may not be used to endorse or promote products
X** derived from this software without specific prior written permission.
X** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
X** WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
X** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X**
X*/
X
X/******************************************************************************
X** SCCS_data: @(#)WcName.c 1.1 ( 19 Nov 90 )
X**
X** Description:	Implements several name-to-widget and widget-to-name
X**		functions which are generally useful, especially a name 
X**		to widget function which really works:
X**
X**			Widget WcFullNameToWidget(char* widget_name)
X**
X**		The widget names understood by WcFullNameToWidget() are
X**		a superset of those understood by XtNameToWidget in
X**		the X11R4 version of libXt.  XtNameToWidget only knows
X**		how to find children of a reference widget, and so the
X**		names start _below- the refernce widget.  However,
X**		WcFullNameToWidget knows how to find widgets anywhere
X**		in the widget tree: it normally starts the name search
X**		from the root of the widget tree, but it can also
X**		perform the name search relatively from the reference
X**		widget, both up and down the widget tree.
X**
X**		When name searches start at the root of the widget
X**		tree, the same syntax as that understood by Xrm is
X**		used.  Below are four examples of acceptable names:
X**
X**			*foo			*foo.XmRowColumn*glorp
X**			Mri.some*other.foo	*Form.glorp
X**
X**		Note that components may be class names, such as
X**		XmRowColumn, or may be instance names of the widgets.
X**		Ambiguous names are resolved exactly as done by 
X**		XtNameToWidget: shallowest wins, `.' binds tighter
X**		than `*', instance names bind tighter than class
X**		names.
X**
X**		In addition to resolving names from the root of the
X**		widget tree, WcFullNameToWidget also can find widget
X**		using a relative root prefix.  Three special characters
X**		are used:
X**
X**			^	means "parent"
X**			~	means the closest shell ancestor
X**			.	means start at the reference widget
X**
X**		The relative root prefix characters are exactly that:
X**		a prefix of a name which will then be passed to
X**		XtNameToWidget.  Some examples:
X**
X**			.foo	a child of the reference widget
X**			^foo	a sibling of the reference widget
X**			^^foo	a sibling of the ref' widgets's parent
X**			~foo	a child of the shell ancestor.
X**			~~*foo	some child of the shell's shell ancestor.
X**
X**		The ^ and ~ prefix characters are only valid at the 
X**		beginning.  They effectively operate on the reference
X**		widget.
X**
X**		In all cases, the characters are scanned left to right.
X**		So, the first character is acted upon, then the second,
X**		and so on.
X**		
X** Notes:	Most of the "private" part of this file goes away when 
X**		the bug in the Xt Intrinsics is fixed which causes 
X**		XtNameToWidget() to dump core whenever a Gadget exists 
X**		in the widget heirarchy...
X**
X******************************************************************************/
X
X/******************************************************************************
X* Include_files.
X******************************************************************************/
X
X#include <ctype.h>      /* isupper() and tolower macros */
X
X/*  -- X Window System includes */
X#include <X11/IntrinsicP.h>
X#include <X11/StringDefs.h>
X
X/*  -- Widget Creation Library includes */
X#include "WcCreate.h"
X#include "WcCreateP.h"
X
X/*
X*******************************************************************************
X* Private_data_definitions.
X*******************************************************************************
X*/
X
X/* shared error message and name buffers
X*******************************************************************************
X** NOTE: These are shared arrays because they are large: i.e.,
X** this is a performacne optimization intended to reduce page
X** faults which can occur while making large extensions to the
X** stack space.  Wait a minute: wouldn't this just happen
X** once, and then the stack space is alloc'd?  Yes, but a
X** huge stack space runs the risk of getting swapped, which causes
X** page faults.  This is probably a nit-picky sort of optimization.
X** Remember that D.Smyth is an old sys programmer from the stone
X** ages, and pity him instead of flaming him.
X** Be careful when filling msg not to call any funcs in here,
X** so the message does not get garbled.
X*/
X
Xstatic char     msg[MAX_ERRMSG];
Xstatic char     cleanName[MAX_PATHNAME];
X
X/* Private Data involving the root widget list
X*******************************************************************************
X*/
X
Xstatic int    numRoots = 0;
Xstatic Widget rootWidgets[MAX_ROOT_WIDGETS];
X
X/*
X*******************************************************************************
X* Private_function definitions.
X*******************************************************************************
X
X/*
X    The following implements XtNameToWidget() in a way which really works.
X
X    Note: the #if defined... assumes a FIXED version of R4.  The version
X    even as of 19 June 1990 still is not correct (dumps core on Gadgets).
X*/
X
X#if defined(XtSpecificationRelease) && XtSpecificationRelease > 4
X
XWidget WcChildNameToWidget( Widget ref, char* childName)
X{
X    return XtNameToWidget( ref, childName );
X}
X
X#else
X
X/* NOTE: The Motif 1.0 XtNameToWidget is broken: it cannot find
X** names with wild cards.  The R4 XtNameToWidget is also broken: it
X** cannot handle encounters with Gadgets.
X**
X** Below is the code extracted from the X11R4 distribution, with very
X** minor changes to make it independent from the rest of the R4 Intrinsics, 
X** and to fix the bug in encountering Gadgets.
X** 
X** Fixes: Added the two lines following this comment block.
X**	  Renamed XtNameToWidget to WcChildNameToWidget to avoid warning.
X**	  Removed "register" from arg type decls, as dbx does these
X**	  incorrectly, and a decent compiler (gcc) does this anyway.
X** -->	  Before looking for children, see if a widget is a gadget.
X**	     Gadgets can't have children, in fact those fields are
X**	     something else entirely!!!
X**
X** Here is the Copyright notice in the X11R4 files from which the
X** following section of code, through the line containing
X**		#endif from X11R4
X***********************************************************
XCopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
Xand the Massachusetts Institute of Technology, Cambridge, Massachusetts.
X
X                        All Rights Reserved
X
XPermission to use, copy, modify, and distribute this software and its
Xdocumentation for any purpose and without fee is hereby granted,
Xprovided that the above copyright notice appear in all copies and that
Xboth that copyright notice and this permission notice appear in
Xsupporting documentation, and that the names of Digital or MIT not be
Xused in advertising or publicity pertaining to distribution of the
Xsoftware without specific, written prior permission.
X
XDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
XDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
XANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
XARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
XSOFTWARE.
X
X******************************************************************
X*/
X
X/*************** Begin source from X11R4 Xtos.h ***************/
X
X#ifndef ALLOCATE_LOCAL
X#define ALLOCATE_LOCAL(size) XtMalloc((unsigned long)(size))
X#define DEALLOCATE_LOCAL(ptr) XtFree((caddr_t)(ptr))
X#endif /* ALLOCATE_LOCAL */
X
X/*************** End source from X11R4 Xtos.h ***************/
X
X#define _XtAllocError		XtError
X
X/*************** Begin source from X11R4 lib/Xt/Intrinsics.c ***************/
X
Xstatic Widget NameListToWidget();
X
Xtypedef Widget (*NameMatchProc)();
X
Xstatic Widget MatchExactChildren(names, bindings, children, num,
X        in_depth, out_depth, found_depth)
X    XrmNameList     names;
X    XrmBindingList  bindings;
X    WidgetList children;
X    int num;
X    int in_depth, *out_depth, *found_depth;
X{
X    Cardinal   i;
X    XrmName    name = *names;
X    Widget w, result = NULL;
X    int d, min = 10000;
X
X    for (i = 0; i < num; i++) {
X        if (name == children[i]->core.xrm_name) {
X            w = NameListToWidget(children[i], &names[1], &bindings[1],
X                    in_depth+1, &d, found_depth);
X            if (w != NULL && d < min) {result = w; min = d;}
X        }
X    }
X    *out_depth = min;
X    return result;
X}
X
Xstatic Widget MatchWildChildren(names, bindings, children, num,
X        in_depth, out_depth, found_depth)
X    XrmNameList     names;
X    XrmBindingList  bindings;
X    WidgetList children;
X    int num;
X    int in_depth, *out_depth, *found_depth;
X{
X    Cardinal   i;
X    Widget w, result = NULL;
X    int d, min = 10000;
X
X    for (i = 0; i < num; i++) {
X        w = NameListToWidget(children[i], names, bindings,
X                in_depth+1, &d, found_depth);
X        if (w != NULL && d < min) {result = w; min = d;}
X    }
X    *out_depth = min;
X    return result;
X}
X
Xstatic Widget SearchChildren(root, names, bindings, matchproc,
X        in_depth, out_depth, found_depth)
X    Widget root;
X    XrmNameList     names;
X    XrmBindingList  bindings;
X    NameMatchProc matchproc;
X    int in_depth, *out_depth, *found_depth;
X{
X    Widget w1, w2;
X    int d1, d2;
X
X    if (!XtIsWidget(root)) {
X	*out_depth = 10000;	/* I don't know what this should be */
X	return (Widget)NULL;
X    }
X    if (XtIsComposite(root)) {
X        w1 = (*matchproc)(names, bindings,
X                ((CompositeWidget) root)->composite.children,
X                ((CompositeWidget) root)->composite.num_children,
X                in_depth, &d1, found_depth);
X    } else d1 = 10000;
X    w2 = (*matchproc)(names, bindings, root->core.popup_list,
X            root->core.num_popups, in_depth, &d2, found_depth);
X    *out_depth = (d1 < d2 ? d1 : d2);
X    return (d1 < d2 ? w1 : w2);
X}
X
Xstatic Widget NameListToWidget(root, names, bindings,
X        in_depth, out_depth, found_depth)
X    Widget root;
X    XrmNameList     names;
X    XrmBindingList  bindings;
X    int in_depth, *out_depth, *found_depth;
X{
X    Widget w1, w2;
X    int d1, d2;
X
X    if (in_depth >= *found_depth) {
X        *out_depth = 10000;
X        return NULL;
X    }
X
X    if (names[0] == NULLQUARK) {
X        *out_depth = *found_depth = in_depth;
X        return root;
X    }
X
X    if (*bindings == XrmBindTightly) {
X        return SearchChildren(root, names, bindings, MatchExactChildren,
X                in_depth, out_depth, found_depth);
X
X    } else {    /* XrmBindLoosely */
X        w1 = SearchChildren(root, names, bindings, MatchExactChildren,
X                in_depth, &d1, found_depth);
X        w2 = SearchChildren(root, names, bindings, MatchWildChildren,
X                in_depth, &d2, found_depth);
X        *out_depth = (d1 < d2 ? d1 : d2);
X        return (d1 < d2 ? w1 : w2);
X    }
X} /* NameListToWidget */
X
XWidget WcChildNameToWidget( ref, name )  /* was XtNameToWidget */
X    Widget ref;
X    char*  name;
X{
X    XrmName *names;
X    XrmBinding *bindings;
X    int len, depth, found = 10000;
X    Widget result;
X
X    len = strlen(name);
X    if (len == 0) return NULL;
X
X    names = (XrmName *) ALLOCATE_LOCAL((unsigned) (len+1) * sizeof(XrmName));
X    bindings = (XrmBinding *)
X        ALLOCATE_LOCAL((unsigned) (len+1) * sizeof(XrmBinding));
X    if (names == NULL || bindings == NULL) _XtAllocError("alloca");
X
X    XrmStringToBindingQuarkList(name, bindings, names);
X    if (names[0] == NULLQUARK) {
X        DEALLOCATE_LOCAL((char *) names);
X        DEALLOCATE_LOCAL((char *) bindings);
X        return NULL;
X    }
X
X    result = NameListToWidget(ref, names, bindings, 0, &depth, &found);
X
X    DEALLOCATE_LOCAL((char *) names);
X    DEALLOCATE_LOCAL((char *) bindings);
X    return result;
X} /* WcChildNameToWidget */
X
X/*************** End of source from X11R4 lib/Xt/Intrinsics.c ***************/
X#endif /* from X11R4 */
X
X/******************************************************************************
X** Public functions
X******************************************************************************/
X
X/*******************************************************************************
X** Allocate and return a lower case copy of the input string.
X** Caller must free output string!
X*******************************************************************************/
X
Xchar* WcLowerCaseCopy( in )
X    char* in;
X{
X    char* retVal = (char*)XtMalloc( 1 + strlen ( in ) );
X    char* cp = retVal;
X
X    while (*in)
X    {
X	*cp = (isupper(*in) ? tolower(*in) : *in );
X	cp++ ; in++ ;
X    }
X    *cp = NUL;
X    return retVal;
X}
X
X/******************************************************************************
X**  Return "clean" widget name, resource, or value from string
X*******************************************************************************
X    This function strips leading and trailing whitespace from the
X    passed in char*.  Note that the caller must allocate and free
X    the returned character buffer.
X******************************************************************************/
X
Xchar* WcSkipWhitespace( cp )
X    char* cp;
X{
X    while ( *cp && *cp <= ' ' )
X        cp++;
X    return cp;
X}
X
Xchar* WcSkipWhitespace_Comma( cp )
X    char* cp;
X{
X    while ( *cp && *cp <= ' ' )		/* cp = WcSkipWhitespace ( cp ); */
X        cp++;
X    if ( *cp == ',' )
X        cp++;
X    return cp;
X}
X
Xchar* WcCleanName( in, out )
X    char* in;
X    char* out;
X{
X    /* copy from in[] into out[],
X    ** ignore initial whitespace,
X    ** stop at trailing whitespace or comma.
X    ** Returns pointer to whitespace or comma following name.
X    */
X    while ( *in && *in <= ' ' )		/* in = WcSkipWhitespace( in ); */
X	in++;
X    for ( ; (*in > ' ' && *in != ',') ; in++ )
X        *out++ = *in;
X    *out = NUL;
X    return in;  /* this points at 1st whitespace or comma following "out" */
X}
X
X/* This function is necessary because XtNameToWidget cannot really
X** take a widget name which begins at the top level shell, but rather
X** only names which pretend the widget BELOW the top level shell is
X** the top level shell.  I have no idea why some thought the
X** Xt implementation is correct.  Quoting from the Xt manual:
X**
X**   XtNameToWidget returns the descendent [of root] ... according to
X**   the following rules, ... :
X**
X**   o	... qualifying the name of each object with the names of all
X**	its ancestors up to _but_not_including_ the reference widget.
X**
X** Since this is not useful for our purposes, we need to first do some 
X** screwing around to see if the user specified the widget name like one 
X** would specify any other widget name in the resource file.
X*/
X
Xchar* WcStripWhitespaceFromBothEnds( name )
X    char* name;
X{
X    char* first; 
X    char* last;
X    char* buff;
X    char* bp;
X
X    for ( first = name ; *first <= ' ' ; first ++ )
X	;
X    for ( last = first ; *last ; last++ )
X	;
X    for ( last-- ; *last <= ' ' ; last-- )
X	;
X    buff = (char*)XtMalloc( (last - first) + 2 );
X    for ( bp = buff ; first <= last ; bp++, first++ )
X	*bp = *first;
X    *bp = NUL;
X
X    return buff;
X}
X
X/*
X    -- Find the named widget
X*******************************************************************************
X
X    This function uses WcChildNameToWidget to search a widget tree for a
X    widget with the given name.  WcChildNameToWidget is basically
X    XtNameToWidget from X11R4, but hacked so it works when there are
X    Gadgets in the widget tree.
X
X    WcChildNameToWidget, like XtNameToWidget, starts searching for children
X    of a reference widget.  WcFullNameToWidget examines the first few
X    characters of the `name' argument in order to determine which widget is
X    the reference whidget where the search will begin.
X
X    The possibilities are these:  The `name' can begin with one or more of
X    the relative prefix characters: ^ or ~, which means the reference
X    widget will be some relative node in the widget tree, such as the
X    parent or the shell ancestor.  Otherwise, the  root widget will be the
X    starting point.
X*/
X
XWidget WcFullNameToWidget( w, name )
X    Widget w;
X    char*  name;
X{
X    Widget retWidget;
X    char  *widgetName;
X    char  *lowerName;
X    int    i;
X
X    widgetName = WcStripWhitespaceFromBothEnds( name );	/* must be XtFree'd */
X
X    if ( widgetName[0] == '*' )
X    {
X	retWidget = WcChildNameToWidget( WcRootWidget(w), widgetName );
X	XtFree( widgetName );
X	return retWidget;
X    }
X
X    if (widgetName[0] == '^' 
X     || widgetName[0] == '~' 
X     || widgetName[0] == '.')
X    {
X	i = 0;
X	while (widgetName[i] == '^' 	/* parent */
X	    || widgetName[i] == '~' 	/* shell ancestor */
X	    || widgetName[i] == '.')	/* eaten and ignored */
X	{
X	    if (widgetName[i] == '^')
X	    {
X		w = XtParent( w );
X	    }
X	    else if (widgetName[i] == '~')
X	    {
X		/* There is a bug in /usr/include/X11/IntrinsicP.h, in
X		** the XtIsShell() macro.  It does not parenthesize its
X		** argument when it uses it.  Therefore, the extra 
X		** parens are necessary here!
X		*/
X		while (! XtIsShell( (w = XtParent(w)) ) )
X		    ;
X	    }
X	    i++;
X	}
X	if (widgetName[i] == '\0')
X	    retWidget = w;
X	else
X	    retWidget = WcChildNameToWidget( w, &(widgetName[i]) );
X	XtFree( widgetName );
X	return retWidget;
X    }
X
X    lowerName  = WcLowerCaseCopy( widgetName );         /* must be XtFree'd */
X
X    if ( 0 == strcmp( "this", lowerName ) )
X    {
X	XtFree( widgetName );
X	XtFree( lowerName  );
X	return w;
X    }
X
X    /* Apparently, the widget name starts with a name.  We need to find
X    ** which root widget has this name.  We need to go down the list of
X    ** root widgets maintained by WcRootWidget().
X    */
X
X    {
X	Widget	root;
X	Widget  root_of_w;
X	char*	rootName;
X	char*	lowerRootName;
X	int     widgetNameLen = strlen(lowerName);
X	int	rootNameLen;
X	int	startsWithRootName;
X	char*	stripped;
X
X	/* most of the time, a widget names something else in its
X	** own widget heirarchy.  Therefore, see if the naming starts
X	** at the root widget of `w' but don't check that widget again.
X	*/
X	root_of_w = root = WcRootWidget( w ) ;
X	i = -1;
X
X	while(1)
X	{
X	    rootName = XrmQuarkToString( root->core.xrm_name );
X	    lowerRootName = WcLowerCaseCopy( rootName );       /* XtFree this */
X	    rootNameLen = strlen( lowerRootName );
X	    startsWithRootName = !strncmp(lowerName,lowerRootName,rootNameLen);
X
X	    if ( startsWithRootName && widgetName[rootNameLen] == '*' )
X	    {
X	        /* the root widget name is followed by a `*' so strip the
X		** root name, but keep the star as it implies loose binding.
X		*/
X		stripped = &widgetName[rootNameLen];
X                retWidget = WcChildNameToWidget( root, stripped );
X		XtFree( widgetName    );
X		XtFree( lowerName     );
X		XtFree( lowerRootName );
X		return retWidget;
X	    }
X
X	    else if ( startsWithRootName && widgetName[rootNameLen] == '.' )
X	    {
X		/* the root widget name is followed by a `.' so strip the
X		** root name and the period to imply tight binding.
X		*/
X		stripped = &widgetName[++rootNameLen];
X		retWidget = WcChildNameToWidget( root, stripped );
X		XtFree( widgetName    );
X		XtFree( lowerName     );
X		XtFree( lowerRootName );
X		return retWidget;
X	    }
X
X	    else if ( startsWithRootName && (widgetNameLen == rootNameLen) )
X	    {
X		/* widgetName is the root widget. */
X		XtFree( widgetName    );
X                XtFree( lowerName     );
X                XtFree( lowerRootName );
X                return root;
X	    }
X
X	    /* Did not find the root name.  Try the next, but skip the
X	    ** root_of_w which we checked first.
X	    */
X	    if (++i == numRoots)
X		break;
X	    if (root_of_w == (root = rootWidgets[i]) )
X	    {
X		if (++i == numRoots)
X		    break;
X	        root = rootWidgets[i];
X	    }
X	}
X
X	/* Completely unsucessful in parsing this name. */
X#ifdef DEBUG
X	sprintf( msg,
X	    "WcFullNameToWidget cannot convert `%s' to widget \n\
X	     Problem: Widget name must start with `*' or `.' or `~' or `^'\n\
X	              or `<aRoot>*' or `<aRoot>.' or be `this'" ,
X	     widgetName );
X	XtWarning( msg ); 
X#endif
X
X	XtFree( widgetName );
X	XtFree( lowerName );
X	XtFree( lowerRootName );
X	return NULL;
X    }
X}
X
X/*
X    -- Names to Widget List
X******************************************************************************
X    This routine converts a string of comma separated widget names
X    (or widget paths) into a list of widget id's. Blank space ignored.
X    If a NULL string is provided, NULL is put on the list.
X
X    The return value is the list of names which could NOT be
X    converted.  Note that this list is fixed size, and is re-used.
X*/
X
Xchar* WcNamesToWidgetList ( w, names, widget_list, widget_count )
X    Widget      w;                  /* reference widget */
X    char*       names;              /* string of widget names */
X    Widget      widget_list[];      /* returned widget list */
X    int	       *widget_count;       /* in widget_list[len], out widget count */
X{
X    static char ignored[MAX_XRMSTRING];
X    char*	next   = names;
X    int		max    = *widget_count;
X
X/*  -- parse the input names "widgetpath [, widgetpath] ..." */
X    ignored[0] = NUL;
X    *widget_count = 0;
X
X    do 
X    {
X	next = WcCleanName ( next, cleanName );
X
X	if ( widget_list[*widget_count] = WcFullNameToWidget ( w, cleanName ) )
X	    (*widget_count)++;
X	else
X	{
X	    if (ignored[0] == NUL)
X		strcpy(ignored, cleanName);
X	    else
X	    {
X		strcat(ignored, ", ");
X		strcat(ignored, cleanName);
X	    }
X	}
X	next = WcSkipWhitespace_Comma ( next );
X
X    } while ( *next && *widget_count < max) ;
X
X    return ignored;
X}
X
X/*
X    -- WidgetToFullName
X*******************************************************************************
X    Traverse up the widget tree, sprintf each name right up to
X    the root of the widget tree.  sprintf the names to buffer.  Use
X    recursion so order of names comes out right.  Client MUST free
X    the char string alloc's and returned by WcWidgetToFullName().
X
X    Note: If using the Motif widget set, it is likely (almost inavoidable)
X    that the "widget" may actually be a Gadget.  Well, Gadgets don't have
X    many things, particularly a core.name member.  Therefore, if using
X    Motif we must check to see if the "widget" is not actually an XmGadget.
X    If is it, then we must use XrmQuarkToString(w->core.xrm_name) rather
X    than core.name (unfortunately).  I'd rather not use the xrm name because
X    the case has been flattened: everything is lower case.  Name something
X    SomeComplexLongName and you get back somecomplexlongname.  The case
X    is always insignificant, but the mixed case name is easier to read.
X*/
X
Xstatic char* nextChar;
X
Xstatic int FullNameLen( w )
X    Widget w;
X{
X    int len;
X
X    if ( XtIsWidget(w) )
X	len = 1 + strlen ( w->core.name );
X    else
X	len = 1 + strlen ( XrmQuarkToString(w->core.xrm_name) );
X
X    if (w->core.parent)
X	len += FullNameLen(w->core.parent);
X    return len;
X}
X
Xstatic void WidgetToFullName( w )
X    Widget w;
X{
X    char* cp;
X
X    if (w->core.parent)
X    {
X        WidgetToFullName( w->core.parent );	/* nextChar AFTER parent name */
X	*nextChar++ = '.';			/* inter-name `dot' */
X    }
X
X    if ( XtIsWidget(w) )
X        cp = w->core.name;
X    else
X	cp = XrmQuarkToString(w->core.xrm_name);
X
X    while (*cp)
X	*nextChar++ = *cp++;
X}
X
Xchar* WcWidgetToFullName( w )
X    Widget w;
X{
X    char* buff = XtMalloc( FullNameLen( w ) );
X
X    nextChar = buff;
X
X    WidgetToFullName( w );
X    *nextChar = NUL;
X			
X    return buff;
X}
X
X/*
X    -- Search widget's resource list for resource_type
X*******************************************************************************
X    Gets the XtResourceList from the widget, searches the list for
X    the resource name to determine the type required, which is then
X    returned to the caller.
X*/
X
Xchar* WcGetResourceType( w, res_name )
X    Widget w;
X    char*  res_name;
X{
X    XtResource* res_list;
X    int         i, num;
X    char*	retstr;
X
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	 || 0 == strcmp( res_name, res_list[i].resource_class) )
X	{
X            retstr = XtNewString(res_list[i].resource_type);
X	    XtFree( res_list );
X	    return retstr;
X	}
X    }
X
X    w = XtParent( w );
X    if (XtIsConstraint( w ))
X    {
X	XtGetConstraintResourceList( 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	     || 0 == strcmp( res_name, res_list[i].resource_class) )
X            {
X                retstr = XtNewString(res_list[i].resource_type);
X                XtFree( res_list );
X                return retstr;
X            }
X	}
X    }
X
X    return NULL;
X}
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
X    Note that if the widget does not have the specified resource
X    type, it is not set.  WcGetResourceType() checks for both
X    widget resources and constraint resources.
X
X    Note also that no converter-failed behavior is necessary,
X    because converters generally give their own error messages.
X*/
X
Xvoid WcSetValueFromString( w, res_name, res_val )
X    Widget w;		 /* MUST already be init'd */
X    char*  res_name;
X    char*  res_val;	/* NUL terminated, should NOT have whitespace */
X{
X    char*	res_type;	/* must be XtFree'd */
X
X    if ( res_type = WcGetResourceType( w, res_name ) )
X    {
X	/* This widget does know about this resource type */
X	WcSetValueFromStringAndType( w, res_name, res_val, res_type );
X    }
X    XtFree( res_type );
X}
X
Xvoid WcSetValueFromStringAndType( w, res_name, res_val, res_type )
X    Widget w;
X    char*  res_name;
X    char*  res_val;
X    char*  res_type;
X{
X    XrmValue    fr_val;
X    XrmValue    to_val;
X    Arg		arg[1];
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            XtRString,	/* from type */
X            &fr_val,	/* from value */
X            res_type,	/* to type */
X            &to_val		/* the converted value */
X    );
X
X    if (to_val.addr)
X    {
X        /* Conversion worked.  */
X	if ( 0 == strcmp(res_type, "String"))
X	    XtSetArg( arg[0], res_name, to_val.addr );
X	else
X	{
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	        XtSetArg( arg[0], res_name, to_val.addr );
X            }
X	}
X        XtSetValues( w, arg, 1 );
X    }
X}
X
X/*
X*******************************************************************************
X* Private Data involving the root widget list, declared at top of this file
X*	static int numRoots = 0;
X*	static Widget rootWidgets[MAX_ROOT_WIDGETS];
X*******************************************************************************
X*/
X
X
X/*
X    -- Forget about a root widget
X*******************************************************************************
X    When a root widget gets destroyed, we need to take that widget out
X    of our list of root widgets.  This is a destroy callback routine
X    which is added to a root widget's destroy callback list by WcRootWidget.
X*/
X
Xstatic void ForgetRoot ( w, client, call )
X    Widget  w;
X    caddr_t client;
X    caddr_t call;
X{
X    int i;
X    for (i = 0 ; i < numRoots ; i++ )
X    {
X        if ( w == rootWidgets[i] )
X	{
X	    /* move all following widgets up to close the gap */
X	    for ( ; i < numRoots ; i++ )
X	    {
X		rootWidgets[i] = rootWidgets[i+1];
X	    }
X	    numRoots-- ;
X	    return;
X	}
X    }
X    /* should never get here */
X}
X
X/*
X    -- Find root widget
X*******************************************************************************
X    If a widget is passed, then find the root of that widget.  See if
X    it is one of the root widgets we already know about.  Add to list
X    if not.  Return the root widget.
X
X    If no widget is passed, then return the first root widget we know
X    about.  If we know of no root widgets, then we will return a NULL
X    since the rootWidgets[] array starts out filled with nulls, and
X    gets re-filled as roots are destroyed.
X*/
X
XWidget WcRootWidget( w )
X    Widget w;
X{
X    int i;
X
X    if (w)
X    {
X	while ( XtParent(w) )
X	    w = XtParent(w);
X
X	for (i = 0 ; i < numRoots ; i++)
X	{
X	    if ( w == rootWidgets[i] )
X		return w;
X	}
X
X	rootWidgets[i] = w;
X	numRoots++;
X	XtAddCallback( w, XtNdestroyCallback, ForgetRoot, NULL );
X	return w;
X    }
X    else
X    {
X	return rootWidgets[0];
X    }
X}
X
X/*
X   -- Equivalent to ANSI C library function strstr()
X*******************************************************************************
X   This function is only necessary on systems which do not have
X   ANSI C libraries.  Soon, it looks like everybody will have
X   such libraries, what with the recent SVR4 and OSF efforts
X   to include everything for everybody.  In the meantime,
X   this will always be included in the library.  Why not put
X   #ifdef's around it?  because the problem really arises not
X   when the library is built, but when applications are built.
X   I can't very well require all application writers in the
X   world to know what this library uses...
X*/
X
Xchar* WcStrStr( s1, s2 )
X    char* s1;
X    char* s2;
X{
X    while (*s1)
X    {
X	if (*s1 == *s2)
X	{
X	    char* start = s1;
X	    char* c = s2;
X	    while (*++s1 & *++c && *s1 == *c)
X		;
X	    if (*c == '\0')
X		return start;
X	    else
X		s1 = ++start;
X	}
X	else
X	{
X	    s1++ ;
X	}
X    }
X    return (char*)0;
X}
!STUFFY!FUNK!
echo Extracting Xmp/XmpRegAll.c
sed >Xmp/XmpRegAll.c <<'!STUFFY!FUNK!' -e 's/X//'
X/*
X** Copyright (c) 1990 David E. Smyth
X**
X** This file was derived from work performed by Martin Brunecky at
X** Auto-trol Technology Corporation, Denver, Colorado, under the
X** following copyright:
X**
X*******************************************************************************
X* Copyright 1990 by Auto-trol Technology Corporation, Denver, Colorado.
X*
X*                        All Rights Reserved
X*
X* Permission to use, copy, modify, and distribute this software and its
X* documentation for any purpose and without fee is hereby granted, provided
X* that the above copyright notice appears on all copies and that both the
X* copyright and this permission notice appear in supporting documentation
X* and that the name of Auto-trol not be used in advertising or publicity
X* pertaining to distribution of the software without specific, prior written
X* permission.
X*
X* Auto-trol disclaims all warranties with regard to this software, including
X* all implied warranties of merchantability and fitness, in no event shall
X* Auto-trol be liable for any special, indirect or consequential damages or
X* any damages whatsoever resulting from loss of use, data or profits, whether
X* in an action of contract, negligence or other tortious action, arising out
X* of or in connection with the use or performance of this software.
X*******************************************************************************
X**
X** Redistribution and use in source and binary forms are permitted
X** provided that the above copyright notice and this paragraph are
X** duplicated in all such forms and that any documentation, advertising
X** materials, and other materials related to such distribution and use
X** acknowledge that the software was developed by David E. Smyth.  The
X** name of David E. Smyth may not be used to endorse or promote products
X** derived from this software without specific prior written permission.
X** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
X** WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
X** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X**
X*/
X
X/*
X* SCCS_data: @(#)XmpRegAll.c 1.2 ( 1 Jan 91 )
X*
X*     This module contains registration routine for all Motif
X*     widget/gadget constructors and classes.  It also provides
X*     Motif specific converters.
X*
X*     The two functions XmpRegisterAll() and MriRegisterMotif()
X*     are exactly equivalent.
X*
X* Module_interface_summary: 
X*
X*     void XmpRegisterAll   ( XtAppContext app )
X*     void MriRegisterMotif ( XtAppContext app )
X*
X*******************************************************************************
X*/
X
X#include "X11/StringDefs.h"
X
X#include <Xm/Xm.h>
X
X#include <Xm/ArrowB.h>
X#include <Xm/ArrowBG.h>
X#include <Xm/BulletinB.h>
X#include <Xm/CascadeB.h>
X#include <Xm/CascadeBG.h>
X#include <Xm/Command.h>
X#include <Xm/DialogS.h>
X#include <Xm/DrawingA.h>
X#include <Xm/DrawnB.h>
X#include <Xm/FileSB.h>
X#include <Xm/Form.h>
X#include <Xm/Frame.h>
X#include <Xm/Label.h>
X#include <Xm/LabelG.h>
X#include <Xm/List.h>
X#include <Xm/MainW.h>
X#include <Xm/MenuShell.h>
X#include <Xm/MessageB.h>
X#include <Xm/PanedW.h>
X#include <Xm/PushB.h>
X#include <Xm/PushBG.h>
X#include <Xm/RowColumn.h>
X#include <Xm/RowColumnP.h>	/* for CvtStringToMenuWidget */
X#include <Xm/Scale.h>
X#include <Xm/ScrollBar.h>
X#include <Xm/ScrolledW.h>
X#include <Xm/SelectioB.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#include <Xmp/Table.h>
X
X#include <Wc/WcCreate.h>
X#include <Wc/WcCreateP.h>
X
X#ifdef DEBUG
X#include "MriMotifP.h"
X#endif
X
X/*
X*******************************************************************************
X* Private_macro_definitions.
X*******************************************************************************
X*/
X
X#define done( type, value )                     \
X{                                               \
X    if ( toVal->addr != NULL )                  \
X    {                                           \
X        if ( toVal->size < sizeof( type ) )     \
X        {                                       \
X            toVal->size = sizeof( type );       \
X            return;                             \
X        }                                       \
X        *(type*)(toVal->addr) = (value);        \
X    }                                           \
X    else                                        \
X    {                                           \
X        static type static_val;                 \
X        static_val = (value);                   \
X        toVal->addr = (caddr_t)&static_val;     \
X    }                                           \
X    toVal->size = sizeof(type);                 \
X    return;                                     \
X}
X
X/*
X*******************************************************************************
X**  Motif specific resource converters
X*******************************************************************************
X*/
X
X/*
X    -- Convert String To MenuWidget
X*******************************************************************************
X    This conversion converts strings into menu widgets for use on
X    cascade button subMenuId resource specifications.
X*/
X
Xvoid CvtStringToMenuWidget (args, num_args, fromVal, toVal)
X    XrmValue *args;
X    Cardinal *num_args;
X    XrmValue *fromVal;
X    XrmValue *toVal;
X{
X    char        cleanName[MAX_XRMSTRING];
X    Widget      root;
X    Widget      widget;
X    Arg         existing[1];
X
X    (void)WcCleanName( fromVal->addr, cleanName );
X
X    if ( NULL == (root = WcRootWidget(NULL)) )
X    {
X        XtStringConversionWarning (cleanName,
X                "MenuWidget - can't find a root widget for WcFullNameToWidget");
X        return;
X    }
X
X    if (cleanName[0] == '^' || cleanName[0] == '~')
X    {
X        XtStringConversionWarning (cleanName,
X"MenuWidget - Relative paths cannot be converted.  Use path from root widget."
X        );
X        return;
X    }
X
X    widget = WcFullNameToWidget( root, cleanName );
X
X    if ( widget == NULL )
X    {
X        XtStringConversionWarning (cleanName,
X                "MenuWidget - no such widget.  Misspelled? Forgot the path?");
X        return;
X    }
X    else if ( XmIsRowColumn( widget )
X      && (   RC_Type ( (XmRowColumnWidget)widget ) == XmMENU_PULLDOWN
X          || RC_Type ( (XmRowColumnWidget)widget ) == XmMENU_POPUP    ) )
X    {
X        done ( Widget, widget );
X    }
X    XtStringConversionWarning (cleanName,
X                "MenuWidget - not XmMENU_PULLDOWN or XmMENU_POPUP.");
X}
X
X/*
X    -- Action to popup a Motif PopupMenu
X*******************************************************************************
X*/
X
Xvoid MriPopupACT( w, event, params, num_params )
X    Widget      w;
X    XEvent     *event;
X    String     *params;
X    Cardinal   *num_params;
X{
X    Widget      menuPane;
X
X    if (*num_params < 1)
X	return;
X
X    menuPane = WcFullNameToWidget ( w, params[0] );
X    XmMenuPosition( menuPane, event );
X    XtManageChild( menuPane );
X}
X
X/*
X    -- Register all Motif widgets, converters, callbacks, actions.
X*******************************************************************************
X*/
Xvoid XmpRegisterAll();
X
Xvoid MriRegisterMotif ( app )
X    XtAppContext app;
X{
X    XmpRegisterAll(app);
X}
X
Xvoid XmpRegisterAll ( app )
X    XtAppContext app;
X{
X    ONCE_PER_XtAppContext( app );
X
X/* -- Register Motif specific action functions */
X    WcRegisterAction(app, "MriPopupACT", MriPopupACT );
X
X/* -- Register Motif specific converters */
X    XtAddConverter       (XtRString,
X                          WcRWidget,  /* "Window" is wrong, but it works !?! */
X                          XmuCvtStringToWidget,
X                          (XtConvertArgList)NULL,
X                          (Cardinal)0);
X
X    XtAddConverter       (XtRString,
X                          XmRMenuWidget,
X                          CvtStringToMenuWidget,
X                          (XtConvertArgList)NULL,
X                          (Cardinal)0);
X
X#define RCO( name, func  )  WcRegisterConstructor ( app, name, func  )
X#define RCN( name, class )  WcRegisterClassName   ( app, name, class )
X#define RCP( name, class )  WcRegisterClassPtr    ( app, name, class )
X
X/* -- register all Xmp widget constructors */
X RCO( "XmpCreateTable",			XtCreateTable			);
X
X/* -- register all Xmp widget classes */
X RCN( "XmpTable",			tableWidgetClass		);
X RCP( "xmpTableWidgetClass",		tableWidgetClass		);
X
X/* -- register all Motif constructors */
X RCO( "XmCreateArrowButton",		XmCreateArrowButton		);
X RCO( "XmCreateArrowButtonGadget",	XmCreateArrowButtonGadget	);
X RCO( "XmCreateBulletinBoard",		XmCreateBulletinBoard		);
X RCO( "XmCreateBulletinBoardDialog",	XmCreateBulletinBoardDialog	);
X RCO( "XmCreateCascadeButton",		XmCreateCascadeButton		);
X RCO( "XmCreateCascadeButtonGadget",	XmCreateCascadeButtonGadget	);
X RCO( "XmCreateCommand",		XmCreateCommand			);
X RCO( "XmCreateDialogShell",		XmCreateDialogShell		);
X RCO( "XmCreateDrawingArea",		XmCreateDrawingArea		);
X RCO( "XmCreateDrawnButton",		XmCreateDrawnButton		);
X RCO( "XmCreateErrorDialog",		XmCreateErrorDialog		);
X RCO( "XmCreateFileSelectionBox",	XmCreateFileSelectionBox	);
X RCO( "XmCreateFileSelectionDialog",	XmCreateFileSelectionDialog	);
X RCO( "XmCreateForm",			XmCreateForm			);
X RCO( "XmCreateFormDialog",		XmCreateFormDialog		);
X RCO( "XmCreateFrame",			XmCreateFrame			);
X RCO( "XmCreateInformationDialog",	XmCreateInformationDialog	);
X RCO( "XmCreateLabel",			XmCreateLabel			);
X RCO( "XmCreateLabelGadget",		XmCreateLabelGadget		);
X RCO( "XmCreateList",			XmCreateList			);
X RCO( "XmCreateMainWindow",		XmCreateMainWindow		);
X RCO( "XmCreateMenuBar",		XmCreateMenuBar			);
X RCO( "XmCreateMenuShell",		XmCreateMenuShell		);
X RCO( "XmCreateMessageBox",		XmCreateMessageBox		);
X RCO( "XmCreateMessageDialog",		XmCreateMessageDialog		);
X RCO( "XmCreateOptionMenu",		XmCreateOptionMenu		);
X RCO( "XmCreatePanedWindow",		XmCreatePanedWindow		);
X RCO( "XmCreatePopupMenu",		XmCreatePopupMenu		);
X RCO( "XmCreatePromptDialog",		XmCreatePromptDialog		);
X RCO( "XmCreatePulldownMenu",		XmCreatePulldownMenu		);
X RCO( "XmCreatePushButton",		XmCreatePushButton		);
X RCO( "XmCreatePushButtonGadget",	XmCreatePushButtonGadget	);
X RCO( "XmCreateQuestionDialog",		XmCreateQuestionDialog		);
X RCO( "XmCreateRadioBox",		XmCreateRadioBox		);
X RCO( "XmCreateRowColumn",		XmCreateRowColumn		);
X RCO( "XmCreateScale",			XmCreateScale			);
X RCO( "XmCreateScrollBar",		XmCreateScrollBar		);
X RCO( "XmCreateScrolledList",		XmCreateScrolledList		);
X RCO( "XmCreateScrolledText",		XmCreateScrolledText		);
X RCO( "XmCreateScrolledWindow",		XmCreateScrolledWindow		);
X RCO( "XmCreateSelectionBox",		XmCreateSelectionBox		);
X RCO( "XmCreateSelectionDialog",	XmCreateSelectionDialog		);
X RCO( "XmCreateSeparator",		XmCreateSeparator		);
X RCO( "XmCreateSeparatorGadget",	XmCreateSeparatorGadget		);
X RCO( "XmCreateText",			XmCreateText			);
X RCO( "XmCreateToggleButton",		XmCreateToggleButton		);
X RCO( "XmCreateToggleButtonGadget",	XmCreateToggleButtonGadget	);
X RCO( "XmCreateWarningDialog",		XmCreateWarningDialog		);
X RCO( "XmCreateWorkingDialog",		XmCreateWorkingDialog		);
X
X/* -- register Motif widget classes */
X RCP("xmArrowButtonWidgetClass",	xmArrowButtonWidgetClass	);
X RCN("XmArrowButton",			xmArrowButtonWidgetClass	);
X RCP("xmArrowButtonGadgetClass",	xmArrowButtonGadgetClass	);
X RCN("XmArrowButtonGadget",		xmArrowButtonGadgetClass	);
X RCP("xmBulletinBoardWidgetClass",	xmBulletinBoardWidgetClass	);
X RCN("XmBulletinBoard",			xmBulletinBoardWidgetClass	);
X RCP("xmCascadeButtonWidgetClass",	xmCascadeButtonWidgetClass	);
X RCN("XmCascadeButton",			xmCascadeButtonWidgetClass	);
X RCP("xmCascadeButtonGadgetClass",	xmCascadeButtonGadgetClass	);
X RCN("XmCascadeButtonGadget",		xmCascadeButtonGadgetClass	);
X RCP("xmCommandWidgetClass",		xmCommandWidgetClass		);
X RCN("XmCommand",			xmCommandWidgetClass		);
X RCP("xmDialogShellWidgetClass",	xmDialogShellWidgetClass	);
X RCN("XmDialogShell",			xmDialogShellWidgetClass	);
X RCP("xmDrawingAreaWidgetClass",	xmDrawingAreaWidgetClass	);
X RCN("XmDrawingArea",			xmDrawingAreaWidgetClass	);
X RCP("xmDrawnButtonWidgetClass",	xmDrawnButtonWidgetClass	);
X RCN("XmDrawnButton",			xmDrawnButtonWidgetClass	);
X RCP("xmFileSelectionBoxWidgetClass",	xmFileSelectionBoxWidgetClass	);
X RCN("XmFileSelectionBox",		xmFileSelectionBoxWidgetClass	);
X RCP("xmFormWidgetClass",		xmFormWidgetClass		);
X RCN("XmForm",				xmFormWidgetClass		);
X RCP("xmFrameWidgetClass",		xmFrameWidgetClass		);
X RCN("XmFrame",				xmFrameWidgetClass		);
X RCP("xmGadgetClass",			xmGadgetClass			);
X RCN("XmGadget",			xmGadgetClass			);
X RCP("xmLabelWidgetClass",		xmLabelWidgetClass		);
X RCN("XmLabel",				xmLabelWidgetClass		);
X RCP("xmLabelGadgetClass",		xmLabelGadgetClass		);
X RCN("XmLabelGadget",			xmLabelGadgetClass		);
X RCP("xmListWidgetClass",		xmListWidgetClass		);
X RCN("XmList",				xmListWidgetClass		);
X RCP("xmMainWindowWidgetClass",		xmMainWindowWidgetClass		);
X RCN("XmMainWindow",			xmMainWindowWidgetClass		);
X RCP("xmManagerWidgetClass",		xmManagerWidgetClass		);
X RCN("XmManager",			xmManagerWidgetClass		);
X RCP("xmMenuShellWidgetClass",		xmMenuShellWidgetClass		);
X RCN("XmMenuShell",			xmMenuShellWidgetClass		);
X RCP("xmMessageBoxWidgetClass",		xmMessageBoxWidgetClass		);
X RCN("XmMessageBox",			xmMessageBoxWidgetClass		);
X RCP("xmPanedWindowWidgetClass",	xmPanedWindowWidgetClass	);
X RCN("XmPanedWindow",			xmPanedWindowWidgetClass	);
X RCP("xmPrimitiveWidgetClass",		xmPrimitiveWidgetClass		);
X RCN("XmPrimitive",			xmPrimitiveWidgetClass		);
X RCP("xmPushButtonWidgetClass",		xmPushButtonWidgetClass		);
X RCN("XmPushButton",			xmPushButtonWidgetClass		);
X RCP("xmPushButtonGadgetClass",		xmPushButtonGadgetClass		);
X RCN("XmPushButtonGadget",		xmPushButtonGadgetClass		);
X RCP("xmRowColumnWidgetClass",		xmRowColumnWidgetClass		);
X RCN("XmRowColumn",			xmRowColumnWidgetClass		);
X RCP("xmScaleWidgetClass",		xmScaleWidgetClass		);
X RCN("XmScale",				xmScaleWidgetClass		);
X RCP("xmScrollBarWidgetClass",		xmScrollBarWidgetClass		);
X RCN("XmScrollBar",			xmScrollBarWidgetClass		);
X RCP("xmScrolledWindowWidgetClass",	xmScrolledWindowWidgetClass	);
X RCN("XmScrolledWindow",		xmScrolledWindowWidgetClass	);
X RCP("xmSelectionBoxWidgetClass",	xmSelectionBoxWidgetClass	);
X RCN("XmSelectionBox",			xmSelectionBoxWidgetClass	);
X RCP("xmSeparatorWidgetClass",		xmSeparatorWidgetClass		);
X RCN("XmSeparator",			xmSeparatorWidgetClass		);
X RCP("xmSeparatorGadgetClass",		xmSeparatorGadgetClass		);
X RCN("XmSeparatorGadget",		xmSeparatorGadgetClass		);
X RCP("xmTextWidgetClass",		xmTextWidgetClass		);
X RCN("XmText",				xmTextWidgetClass		);
X RCP("xmToggleButtonWidgetClass",	xmToggleButtonWidgetClass	);
X RCN("XmToggleButton",			xmToggleButtonWidgetClass	);
X RCP("xmToggleButtonGadgetClass",	xmToggleButtonGadgetClass	);
X RCN("XmToggleButtonGadget",		xmToggleButtonGadgetClass	);
X}
!STUFFY!FUNK!
echo Extracting Xmp/Imakefile
sed >Xmp/Imakefile <<'!STUFFY!FUNK!' -e 's/X//'
X#include "../Wc.tmpl"
X
X/**/# Imakefile for libXmp
X
XHEADERS = Table.h TableP.h
X
XSRCS = Table.c XmpRegAll.c
XOBJS = Table.o XmpRegAll.o
X
Xall::
X#if HasSunOSSharedLibraries
X# if DebugLibWc
XSharedAndDebuggedLibraryObjectRule()
X# else
XSharedLibraryObjectRule()
X# endif
X#else
X# if DebugLibWc && ProfileLibWc
XDebuggedAndProfiledLibraryObjectRule()
X# else
X#  if DebugLibWc
XDebuggedLibraryObjectRule()
X#  else
X#   if ProfileLibWc
XProfiledLibraryObjectRule()
X#   else
XNormalLibraryObjectRule()
X#   endif
X#  endif
X# endif
X#endif
X
X/*
X * always generate unshared library too
X */
X#if HasSunOSSharedLibraries
XNormalSharedLibraryTarget(Xmp,$(SoWcRev),$(OBJS))
XInstallSharedLibrary(Xmp,$(SoWcRev),$(INSTLIB))
X#endif
XNormalLibraryTarget(Xmp,$(OBJS))
XInstallLibrary(Xmp,$(INSTLIB))
X
XLintLibraryTarget(Xmp,$(SRCS))
XInstallLintLibrary(Xmp,$(INSTLIN))
X
X#if ProfileLibWc
XProfiledLibraryTarget(Xmp,$(OBJS))
XInstallLibrary(Xmp_p,$(INSTLIB))
X#endif
X
X#if DebugLibWc
XDebuggedLibraryTarget(Xmp,$(OBJS))
X
X#endif
X
XMakeDirectories(install,$(INSTINC)/Xmp)
XInstallMultiple($(HEADERS),$(INSTINC)/Xmp)
X
XDependTarget()
X
XNormalLintTarget($(SRCS))
X
!STUFFY!FUNK!
echo Extracting DemosAthena/App
sed >DemosAthena/App <<'!STUFFY!FUNK!' -e 's/X//'
!STUFFY!FUNK!
echo " "
echo "End of kit 25 (of 35)"
cat /dev/null >kit25isdone
run=''
config=''
for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35; do
    if test -f kit${iskit}isdone; then
	run="$run $iskit"
    else
	todo="$todo $iskit"
    fi
done
case $todo in
    '')
	echo "You have run all your kits.  Please read README."
	for combo in `find . -name '*:AA' -print`; do
	    if test -f "$combo"; then
		realfile=`echo $combo | sed 's/:AA$//'`
		cat $realfile:[A-Z][A-Z] >$realfile
		rm -rf $realfile:[A-Z][A-Z]
	    fi
	done
	rm -rf kit*isdone
	chmod ugo+x test*
	;;
    *)  echo "You have run$run."
	echo "You still need to run$todo."
	;;
esac
: Someone might mail this, so...
exit

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