[comp.sources.x] v11i039: wcl - Widget Creation Library, Part27/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 39
Archive-name: wcl/part27

#! /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 27 (of 35).  If kit 27 is complete, the line"
echo '"'"End of kit 27 (of 35)"'" will echo at the end.'
echo ""
export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
mkdir Ari Doc Wc 2>/dev/null
echo Extracting Wc/WcCreate.c
sed >Wc/WcCreate.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: @(#)WcCreate.c 1.1 ( 19 Nov 90 )
X*
X* Subsystem_group:
X*
X*     Widget Creation Library
X*
X* Module_description:
X*
X*     This module contains the functions used to create and manage 
X*     a widget tree using the Xrm database.
X
X*     The Xrm database format used to prescribe widget's children
X*     is as follows:
X*
X*     ...parent.wcChildren:         childName1, childName2, ...
X*
X*     The type of each child must be specified.  There are three
X*     ways of doing this: (1) by widget class (class pointer name),
X*     (2) by widget class name, and (3) by widget constructor 
X*     function name.  The resource value given is case insensitive,
X*     although one is encouraged to use the capitalization given
X*     in the reference manuals simply on stylistic grounds.  The 
X*     three examples below are effectively equivalent:
X*
X*     ...drawing.wcClass:	xmDrawingAreaWidgetClass
X*     ...drawing.wcClassName:	XmDrawingArea
X*     ...drawing.wcConstructor: XmCreateDrawingArea
X*
X*     Since there are multiple ways of specifying the widget type,
X*     a precedence is defined: wcClass is the highest precedence,
X*     and wcClass > wcClassName > wcConstructor.
X*
X*     Currently, the Motif widget set defines many constructors, such 
X*     as XmCreateForm or XmCreateFileSelectionBox.  Constructors are 
X*     somtimes called Convenience Functions or even Confusion Functions.  
X*     It is highly recommended that you use the WcTrace resource when
X*     first using Constructors in order to see the resulting widget
X*     heirarchy more clearly.  The WcTrace resource is specified as:
X*
X*     ...drawing.wcTrace:	True
X
X*     By default, all widgets created from the Xrm resource database
X*     are managed.  In some cases, this is not what is desired: for
X*     example, pop-up menus are generally not managed when they are
X*     created, rather they are managed due to some mouse event.  In
X*     such cases, the WcManaged resource should be set False, as below:
X*
X*     *fileMenu.wcManaged:	False
X
X*     It is possible to bind one or more callback functions to the
X*     creation of a widget by using the WcCallback resource.  For 
X*     example, using the Motif widget set, when a menu bar is created 
X*     as a child of an XmMainWindow, the menuBar resource of the 
X*     XmMainWindow needs to be set to refer to the menu bar.  For 
X*     example:
X*
X*     App.main.wcClassName:	XmMainWindow
X*     App.main.wcChildren:	mbar
X*     *mbar.wcConstructor:	XmCreateMenuBar
X*     *mbar.wcCallback:		WcSetResourceCB( *main.menuBar: this)
X
X*     Sometimes widget heirarchies are dynamic: many of the widgets
X*     are created at initialization time, but others need to be created
X*     at run time.  Simply do not include the names of the dynamic
X*     created widgets in any wcChildren resource.  They will then still
X*     be defined in the Xrm database, but they will not be created
X*     during the initial widget tree creation.
X
X*     The WcDeferred resource is an obsolete mechanism which should no
X*     longer be used.
X
X*     For example, let's say your interface includes a box world, where
X*     the user can create an arbitrary number of various types of boxes:
X
X*     *box_world.wcClass:	MyBoxWorldWidgetClass
X*
X*     *box_type1.wcClass:	MyBoxType1WidgetClass
X*     *box_type2.wcClass:	MyBoxType2WidgetClass
X*     *box_type3.wcClass:	MyBoxType3WidgetClass
X*     *box_type3.wcChildren:	child1, child2, child3, child4
X*
X*     *button1.callback:	WcCreateChildrenCB( *box_world, box_type1 )
X*     *button2.callback:	WcCreateChildrenCB( *box_world, box_type2 )
X*     *button3.callback:	WcCreateChildrenCB( *box_world, box_type3 )
X*
X*     Initially, when box_world is created, it will have no children.
X*     Each time button1 is pressed, another instance of box_type1 will
X*     be created as a child of box_world, and managed (since wcManaged
X*     is by default True).  Similarly, everytime button2 is pressed
X*     another box_type2 will be created, and everytime button3 is
X*     pressed another box_type3 will be created, along with children
X*     named child1, child2, child3, and child4, and their children as 
X*     applicable.
X
X*     User interfaces are often rather complex.  Since the Widget
X*     Creation Library allows much more of the interface to be
X*     specified in resource files than in prehistoric days of
X*     Widget application programming, it becomes necessary to allow
X*     interfaces to be specified in a collection of resource files.
X*     
X*     It is very desirable that anything in the interface can be
X*     tailored by the user.  Therefore, each resource filename
X*     loaded to describe an interface must be searched for in 
X*     all the locations defined by the Xt Intrinsics.  This is
X*     exactly the same as the initial resource file.
X*
X*     Since a resource file may override any of the resources on
X*     a given widget, including other creation resources, the
X*     resource file name is first fetched before any of the other
X*     wc* resources.
X*
X*     A resource file name is specified as follows:
X*
X*     *menuBar.wcResFile:	MenuBar
X*
X*     Each of the standard directories will be searched in order
X*     for a file named MenuBar, and each merged into the resource database.
X
X*     The following is the complete set of resources which are 
X*     interpreted by the Widget Creation Library:
X*
X*     ...widget.wcChildren:	childName1, childName2, ...
X*     ...widget.wcClass:	classPointerName
X*     ...widget.wcClassName:	className
X*     ...widget.wcConstructor:  constructorFunctionName
X*     ...widget.wcTrace:	true/false (default = false)
X*     ...widget.wcManaged:	true/false (default = true)
X*     ...widget.wcCallback:	callback1(args), callback2(args), ...
X*     ...widget.wcResFile:	filename
X*
X*     In all cases, the Widget Creation resource names can be
X*     specified as Wc<name> or wc<name>, with the capitalized
X*     form having looser binding (representing the resource class).
X
X*     Example:
X*
X*		HelloWorld.wcChildren:  push
X*
X*		*push.wcClass:          xmPushButtonWidgetClass
X*		*push.labelString:      Hello World
X*		*push.activateCallback: WcExitCB(1)
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 WcCreateDatabaseChild()
X*     function, which descends the widget tree recursively until no more
X*     children are found, or a non-composite widget/object is found.
X*
X*     Several convenience callbacks are provided with the package, allowing 
X*     deferred widget creation, control (manage/unmanage) and other utility
X*     functions.  These are found in WcCallb.c
X*
X* Module_history:
X                                                  
X*   mm/dd/yy  initials  function  action
X*   --------  --------  --------  ---------------------------------------------
X*   13Aug90   D.Smyth	Got rid of WcDefered stuff
X*   11Jul90   D.Smyth   Added wcResFile resource
X*   30Jun90   R.Whitby	WcWidgetCreation added call to WcRegisterWcActions
X*   19Jun90   D.Smyth	Version 1.0
X*   04/18/90  MarBru    many..    Changed w->core.name to XrmQuarkToString...
X*   03/27/90  MarBru    Creation  Converted to a completely new syntax
X*   02/16/90  MarBru    Create..  Limited creation to composite widgets/objects
X*
X* Design_notes:
X*
X*******************************************************************************
X*/
X/*
X*******************************************************************************
X* Include_files.
X*******************************************************************************
X*/
X
X/*  -- Operating system includes */
X#include <stdio.h>
X
X/*  -- X Window System includes */
X#include <X11/IntrinsicP.h>
X#include <X11/StringDefs.h>
X
X/*  -- Widget Creation Includes */
X#include "WcCreate.h"
X#include "WcCreateP.h"
X
X/*
X*******************************************************************************
X* Private_data_definitions.
X*******************************************************************************
X*/
X
Xstatic char     msg[MAX_ERRMSG];
X
X/*  -- Creation resources 
X	NOTE: All resource values are fetched at once, but if WcResFile
X	is specified, then the resource files must be loaded and then
X	the resources re-fetched.  This is an optimization: usually
X	WcResFile is not specified, so two fetches from the Xrm database
X	do not need to be done in the normal case.  If resource files are
X	loaded and the resources are re-fetched, WcResFile is ignored.
X	NOTE: The WcClass and WcClassName resources are both converted to
X        a class pointer, as we can construct useful error messages using:
X		class->core_class.class_name
X	However, the Constructor must be the entire constructor cache
X	record so we have the name of the constructor for the error
X	messages.
X	NOTE: WcClass and WcClassName write to different ResourceRec
X	members, so we can provide better error messages.
X*/
X
XXtResource wc_resources[] =
X  {
X    { WcNwcResFile,	WcCWcResFile,		XtRString,	sizeof(String),
X      XtOffset(ResourceRecPtr, resFile ),	XtRImmediate,	(caddr_t) NULL
X    },
X    { WcNwcChildren,	WcCWcChildren,		XtRString,	sizeof(String),
X      XtOffset(ResourceRecPtr, children ),	XtRImmediate,	(caddr_t) NULL
X    },
X    { WcNwcPopups,	WcCWcPopups,		XtRString,	sizeof(String),
X      XtOffset(ResourceRecPtr, popups ),	XtRImmediate,	(caddr_t) NULL
X    },
X    { WcNwcClass,	WcCWcClass,		WcRClassPtr,	sizeof(caddr_t),
X      XtOffset(ResourceRecPtr, class ),		XtRImmediate,	(caddr_t) NULL
X    },
X    { WcNwcClassName,	WcCWcClassName,		WcRClassName,	sizeof(caddr_t),
X      XtOffset(ResourceRecPtr, classFromName ),	XtRImmediate,	(caddr_t) NULL
X    },
X    { WcNwcConstructor,	WcCWcConstructor, 	WcRConstructor,	sizeof(caddr_t),
X      XtOffset(ResourceRecPtr, constructor ),	XtRImmediate,	(caddr_t) NULL
X    },
X    { WcNwcManaged,	WcCWcManaged,		XtRBoolean,	sizeof(Boolean),
X      XtOffset(ResourceRecPtr, managed),	XtRImmediate,	(caddr_t) TRUE
X    },
X    { WcNwcTrace,	WcCWcTrace,		XtRBoolean,	sizeof(Boolean),
X      XtOffset(ResourceRecPtr, trace),		XtRImmediate,	(caddr_t) FALSE
X    },
X    { WcNwcCallback,	WcCWcCallback,	XtRCallback,	sizeof(XtCallbackList),
X      XtOffset(ResourceRecPtr, callback ),	XtRImmediate,	(caddr_t) NULL
X    }
X  };
X
X/*
X*******************************************************************************
X* Private_function_declarations.
X*******************************************************************************
X*/
X
X#define TRACE_CREATION 1
X#define TRACE_POPUP 2
X
X#ifdef FUNCTION_PROTOTYPES
Xstatic void   GetWcResources( ResourceRec*, Widget, char* nm, char* class );
Xstatic int    DuplicateType ( ResourceRec*, Widget, char* nm, char* callr );
Xstatic Widget CreateWidget  ( ResourceRec*, Widget, char* nm, char* callr );
Xstatic Widget CreatePopup   ( ResourceRec*, Widget, char* nm, char* callr );
Xstatic void   CreationWarningMessage ( ResourceRec* rp, Widget pw, 
X			char* name, char* caller, char* func );
Xstatic void   PrintCreationTrace   ( ResourceRec*, Widget child, int traceTyp );
Xstatic void   CallCreationCallbacks( ResourceRec*, Widget child );
X#else
Xstatic void   GetWcResources();
Xstatic int    DuplicateType();
Xstatic Widget CreateWidget();
Xstatic Widget CreatePopup();
Xstatic void   CreationWarningMessage();
Xstatic void   PrintCreationTrace();
Xstatic void   CallCreationCallbacks();
X#endif
X
X/*
X*******************************************************************************
X* Public_function_declarations.
X*******************************************************************************
X*/
X
X/*
X    -- Create Widget Tree from Xrm Database
X*******************************************************************************
X    This routine creates widget children as defined in Xrm database.
X    It checks the widget resource "WcChildren", which is a list of
X    names of children to create. Each child must then be further defined
X    in the databse.
X
X    This function is frequently called from an application's main()
X    procedure after the application shell is created via XtInitialize().
X
X    Note that this function registers the converters for StringToWidget,
X    StringToCallback, and so forth.
X*/
X
Xvoid WcWidgetCreation ( root )
X    Widget       root;
X{
X    XtAppContext app = XtWidgetToApplicationContext( root );
X    char*	 fullName = WcWidgetToFullName( root );	/* must be XtFree'd */
X    ResourceRec  res;
X
X    /* register the root of this widget */
X    (void)WcRootWidget(root);
X
X    /* register the Xt standard widgets */
X    WcRegisterIntrinsic ( app );
X
X    /* register the Wc converters */
X    WcAddConverters( app );
X
X    /* register the Wc callbacks */
X    WcRegisterWcCallbacks ( app );
X
X    /* register the Wc actions */
X    WcRegisterWcActions ( app );
X
X    if ( XtIsSubclass( root, compositeWidgetClass ) )
X    {
X        XtGetApplicationResources ( root, &res,
X              wc_resources, XtNumber(wc_resources), NULL, 0 );
X    
X	if ( res.popups || res.children )
X	{
X	    if ( res.popups )
X		WcCreateNamedPopups ( root, res.popups );
X            if ( res.children )
X		WcCreateNamedChildren ( root, res.children );
X	}
X        else
X        {
X            sprintf( msg,
X            "WcWidgetCreation (%s) - Failed \n\
X             Problem: No children defined in Xrm database.\n\
X	     Possible: resource file not found (XENVIRONEMENT not set?), \n\
X	     Possible: top level widget in resource file not named %s",
X             fullName, root->core.name );
X            XtWarning( msg );
X	}
X    }
X
X     else
X    {
X        sprintf( msg,
X            "WcWidgetCreation (%s) - Failed \n\
X             Problem: %s is not a composite widget, cannot have children.",
X             fullName, fullName );
X        XtWarning( msg );
X    }
X
X    XtFree ( fullName );
X}
X
X/*
X    -- Create And Manage Named Children from Xrm Database
X*******************************************************************************
X    This function creates widget's children specified by names list,
X    by calling WcCreateDatabaseChild() for each of the names provided.
X
X    All the children are then managed, unless WcManaged resource is FALSE.
X
X    Note that widgets created by WcCreateDatabaseChild may or may not
X    be children of `pw' due to the use of constructors.  Only children
X    of `pw' may be managed via a call to XtManageChildren().  Other
X    widgets must be managed individually.  Usually, these widgets
X    are created by the XmCreateScrolled*() or XmCreate*Dialog confusion 
X    functions.
X*/
X
Xvoid WcCreateNamedChildren ( pw, names )
X    Widget      pw;         /* children's parent                            */
X    char*       names;      /* (list of) widget names to create             */
X{
X    Widget	child;
X    int		children = 0;
X    Widget	widget_children[MAX_CHILDREN];
X    int		other = 0;
X    Widget	widget_other[MAX_CHILDREN];
X    char	cleanName[MAX_XRMSTRING];
X    char*	next;
X    int		managed;
X    int		i;
X
X    if  ( !names ) return;
X
X    next = WcCleanName( names, cleanName );
X
X    while ( cleanName[0] )
X    {
X	child = WcCreateDatabaseChild ( pw, cleanName, &managed );
X	if ( child )
X	{
X	    if ( managed && (XtParent( child ) == pw ) )
X		widget_children[children++] = child;
X	    else if ( managed )
X		widget_other[other++] = child;
X	}
X	next = WcSkipWhitespace_Comma( next );
X	next = WcCleanName( next, cleanName );
X    }
X
X    if ( children ) 
X	XtManageChildren( widget_children, children );
X
X    for (i = 0 ; i < other ; i++)
X	XtManageChild( widget_other[i] );
X}
X
X/*
X    -- Create Named Popup Children from Xrm Database
X*******************************************************************************
X    This function creates widget's popup children specified by names list,
X    by calling WcCreateDatabasePopup() for each of the names provided.
X*/
X
Xvoid WcCreateNamedPopups ( pw, names )
X    Widget      pw;         /* children's parent                            */
X    char*       names;      /* (list of) names of popup widgets to create   */
X{
X    Widget      child;
X    char        cleanName[MAX_XRMSTRING];
X    char*       next;
X
X    if  ( !names ) return;
X
X    next = WcCleanName( names, cleanName );
X
X    while ( cleanName[0] )
X    {
X        child = WcCreateDatabasePopup ( pw, cleanName );
X        next = WcSkipWhitespace_Comma( next );
X        next = WcCleanName( next, cleanName );
X    }
X}
X
X/*
X    -- Create Widget from the Resource Database
X*******************************************************************************
X    WcCreateDatabaseChild() causes a normal child to be created.  This
X    implies that the parent widget is a composite widget.
X*/
X
XWidget WcCreateDatabaseChild ( pw, name, managed  )
X    Widget      pw;         /* child's parent */
X    char*       name;       /* child name to create */
X    int        *managed;    /* returned T/F: this child to be managed ? */
X{
X    ResourceRec res;		/* child's creation resources	*/
X    Widget      child;		/* what we create		*/
X    char*	className;	/* get after child is created	*/
X
X    *managed = FALSE;		/* Assume error */
X
X    if ( !XtIsSubclass( pw, compositeWidgetClass ) )
X    {
X	/* child is not a manager widget, so cannot create children */
X	char* parentName = WcWidgetToFullName( pw );
X	sprintf( msg,
X            "WcCreateDatabaseChild (%s) - children ignored \n\
X             Problem: %s is not a composite, cannot have children.",
X             parentName, parentName );
X	XtWarning( msg );
X	XtFree( parentName );
X	return (Widget)NULL;
X    }
X
X    GetWcResources		( &res, pw, name, name );
X    if (DuplicateType		( &res, pw, name, "WcCreateDatabaseChild" ))
X	return (Widget)NULL;
X
X    child = CreateWidget	( &res, pw, name, "WcCreateDatabaseChild" );
X
X    /* Now that widget is created, we can get the "class" resources */
X    className = child->core.widget_class->core_class.class_name;
X    GetWcResources		( &res, pw, name, className );
X
X    if (res.trace)
X	PrintCreationTrace	( &res, child, TRACE_CREATION );
X    if (res.callback)
X	CallCreationCallbacks	( &res, child );
X
X    if (res.popups)
X	WcCreateNamedPopups	( child, res.popups );
X    if (res.children)
X	WcCreateNamedChildren	( child, res.children );
X
X    *managed = res.managed;
X    return child;
X}
X
X/*
X    -- Create Popup Widget from the Resource Database
X*******************************************************************************
X    WcCreateDatabasePopup() causes a popup widget to be created.  Any
X    widget can have popup chidren.
X*/
X
XWidget WcCreateDatabasePopup ( pw, name )
X    Widget      pw;         /* child's parent */
X    char*       name;       /* child name to create */
X{
X    ResourceRec res;            /* child's creation resources   */
X    Widget      child;          /* what we create               */
X    char*	className;	/* get after child is created	*/
X
X    GetWcResources		( &res, pw, name, name );
X    if (DuplicateType		( &res, pw, name, "WcCreateDatabasePopup" ))
X	return (Widget)NULL;
X
X    child = CreatePopup		( &res, pw, name, "WcCreateDatabasePopup" );
X
X    /* Now that widget is created, we can get the "class" resources */
X    className = child->core.widget_class->core_class.class_name;
X    GetWcResources		( &res, pw, name, className );
X
X    if (res.trace)
X	PrintCreationTrace	( &res, child, TRACE_POPUP );
X    if (res.callback)
X	CallCreationCallbacks	( &res, child );
X
X    if (res.popups)
X	WcCreateNamedPopups	( child, res.popups );
X    if (res.children)
X	WcCreateNamedChildren	( child, res.children );
X
X    return child;
X}
X
X/*
X******************************************************************************* 
X**  Private functions used by WcCreateDatabaseChild and WcCreateDatabasePopup
X*******************************************************************************
X*/
X
X/*
X    -- Get Wc* Resources for named child of pw from Xrm resource database
X*******************************************************************************
X*/
X
Xstatic void GetWcResources( rp, pw, name, className )
X    ResourceRec* rp;
X    Widget       pw;
X    char*        name;
X    char*        className;
X{
X    /* Get creation resources for the child to be created.
X    ** After this XtGetSubresources() call, the resource structure `res'
X    ** contains resources specified in the Xrm database or the defaults.
X    */
X    XtGetSubresources ( pw, rp, name, className, 
X       wc_resources, XtNumber(wc_resources), NULL, 0 );
X
X    /* if a resource file is specified for this widget, first
X    ** load the resource file, then re-fetch the resources.
X    ** Notice that we don't check for resFile again.
X    */
X    if ( rp->resFile )
X    {
X	WcLoadResourceFileCB ( pw, rp->resFile, NULL );
X	XtGetSubresources ( pw, rp, name, className,
X	   wc_resources, XtNumber(wc_resources), NULL, 0 );
X    }
X}
X
X/*
X    -- See if duplicate type resources are specified for this widget
X*******************************************************************************
X   Exactly one of WcClass, WcClassName, or WcConstructor must be
X   specified in order to create a widget.  If none are specified,
X   or if more than one is specified, then this is an error, and
X   this function returns TRUE, and the widget should not then be
X   created.
X*/
X
Xstatic int DuplicateType( rp, pw, name, caller )
X    ResourceRec* rp;
X    Widget	 pw;
X    char*	 name;
X    char*        caller;
X{
X    /* Booleans */
X    int class       = (NULL != rp->class);
X    int className   = (NULL != rp->classFromName);
X    int constructor = (NULL != rp->constructor);
X    char* reason;
X    char* parentName;
X    
X    if ( class + className + constructor == 0 )
X	reason = "No WcClass, WcClassName, nor WcConstructor";
X
X    else if ( class + className + constructor == 3 )
X	reason = "WcClass, WcClassName, and WcConstructor";
X
X    else if ( class + className == 2 )
X	reason = "WcClass and WcClassName";
X
X    else if ( class + constructor == 2 )
X	reason = "WcClass and WcConstructor";
X
X    else if ( className + constructor == 2 )
X	reason = "WcClassName and WcConstructor";
X
X    else
X	return 0; /* OK */
X
X    parentName = WcWidgetToFullName( pw );
X    sprintf( msg,
X            "%s (%s.%s) - Failed (Ambiguous) \n\
X             Problem: %s specified, \n\
X                      child %s.%s not created.",
X	     caller, parentName, name, 
X	     reason, 
X	     parentName, name );
X    XtWarning( msg );
X    XtFree( parentName );
X    return 1;
X}
X
X/*
X    -- Create child widget using XtCreateWidget or constructor
X*******************************************************************************
X*/
X
Xstatic Widget CreateWidget ( rp, pw, name, caller )
X    ResourceRec* rp;
X    Widget       pw;
X    char*        name;
X    char*	 caller;
X{
X    Widget child;
X
X    if ( rp->class )
X	child = XtCreateWidget ( name, rp->class, pw, NULL, 0 );
X    else if ( rp->classFromName )
X	child = XtCreateWidget ( name, rp->classFromName , pw, NULL, 0 );
X    else /* rp->constructor */
X	child = rp->constructor->constructor( pw, name, NULL, 0 );
X
X    if (child)
X	return child;
X    CreationWarningMessage( rp, pw, name, caller, "XtCreateWidget" );
X    return (Widget)NULL;
X}
X
X/*
X    -- Create child widget using XtCreateWidget or constructor
X*******************************************************************************
X*/
X
Xstatic Widget CreatePopup ( rp, pw, name, caller )
X    ResourceRec* rp;
X    Widget       pw;
X    char*        name;
X    char*        caller;
X{
X    Widget child;
X
X    if ( rp->class )
X        child = XtCreatePopupShell ( name, rp->class, pw, NULL, 0 );
X    else if ( rp->classFromName )
X        child = XtCreatePopupShell ( name, rp->classFromName , pw, NULL, 0 );
X    else /* rp->constructor */
X        child = rp->constructor->constructor( pw, name, NULL, 0 );
X
X    if (child)
X        return child;
X    CreationWarningMessage( rp, pw, name, caller, "XtCreatePopupShell" );
X    return (Widget)NULL;
X}
X
X/*
X    -- Print warning message when CreateWidget or CreatePopup fail
X*******************************************************************************
X*/
X
Xstatic void CreationWarningMessage ( rp, pw, name, caller, func )
X    ResourceRec* rp;
X    Widget       pw;
X    char*        name;
X    char*        caller;
X    char*	 func;
X{
X    char* parentName = WcWidgetToFullName( pw );
X    static char funcWithArgs[1024];
X
X    if ( rp->class || rp->classFromName )
X    {
X        sprintf( funcWithArgs, "%s( %s, %s )", 
X                    func, name, rp->class->core_class.class_name );
X    }
X    else /* rp->constructor */
X    {
X        sprintf( funcWithArgs, "%s( %s )", rp->constructor->name, name );
X    }
X
X    sprintf( msg,
X            "%s (%s.%s) - Failed \n\
X             Problem: %s failed.",
X             caller, parentName, name, 
X	     funcWithArgs );
X
X    XtWarning( msg );
X    XtFree( parentName );
X}
X
X/*
X    -- Print creation trace message
X*******************************************************************************
X*/
X
Xstatic void PrintCreationTrace( rp, child, traceType )
X    ResourceRec* rp;
X    Widget       child;
X    int		 traceType;
X{
X    char* childName = WcWidgetToFullName( child );
X    char* trace;
X
X    if (traceType == TRACE_CREATION)
X	trace = (rp->managed) ? "  managed" : "unmanaged";
X    else
X	trace = "   pop-up";
X
X    fprintf(stderr,"Wc %s: %s of class %s\n",
X	trace,
X	childName, 
X	child->core.widget_class->core_class.class_name);
X
X    XtFree( childName  );
X}
X
X/*
X    -- Call creation time callbacks specified by WcCallbacks resource.
X*******************************************************************************
X*/
X
Xstatic void CallCreationCallbacks( rp, child )
X    ResourceRec* rp;
X    Widget       child;
X{
X    XtCallbackRec *cb = rp->callback;
X    for ( ; cb->callback; cb++ )
X        (*cb->callback)( child, cb->closure, NULL );
X}
!STUFFY!FUNK!
echo Extracting Doc/Table.doc
sed >Doc/Table.doc <<'!STUFFY!FUNK!' -e 's/X//'
X
XTable - Geometry Management Widget for the X Toolkit
X
XDavid Harrison
XUC Berkeley Electronics Research Lab
X(davidh@ic.Berkeley.EDU, ...!ucbvax!ucbcad!davidh)
X
XTable is a composite widget designed to manage the size and location
Xof its children.  The widget uses an array model to simplify the
Xarrangement of child widgets.  The widget is directly derived from the
Xcore and composite widgets provided by the X Toolkit and can be used
Xwith any widget set.  It has been tested using the Athena widget set.
XBelow is a short summary on the operation and use of the Table widget.
XIt assumes a working knowledge of the X Toolkit Intrinsics.
X
XThe Table widget addresses formatting for dialog boxes.  Dialog boxes
Xare rectangular windows that contain a wide variety of widgets.  Most
Xdialog boxes are arranged with widgets aligned in a way similar to the
Xlayout found in business forms.  The Table widget is designed to make
Xsuch layouts easy to specify.
X
XWhen designing dialog boxes that resemble business forms, the primary
Xproblem is specifying the alignment between widgets.  The Table widget
Xaddresses this problem by adopting an array model.  Under this model,
Xwidgets are placed at row and column locations in a variable sized
Xarray.  Widgets may span more than one row or column.  The array can
Xexpand or contract in size as needed.  There are options to control
Xjustification and place size restrictions on rows and columns of
Xwidgets.
X
XThe Table widget can contain any number and type of sub-widgets
X(including other Table widgets).  XtCreateWidget() is used to create
Xnew Table widgets using the class variable tableWidgetClass.  The
Xresources listed below are retrieved from the argument list or from
Xthe resource database:
X
X			tableWidgetClass
X
XName		Type		Default			Description
X--------------------------------------------------------------------------------
XXtNbackground	Pixel		XtDefaultBackground	Window background
XXtNborder	Pixel		XtDefaultForeground	Window border
XXtNborderWidth	Dimension	0			Width of border
XXtNx		Position	0			X position of table
XXtNy		Position	0			Y position of table
XXtNwidth	Dimension	(computed at realize)	Width of form
XXtNheight	Dimension	(computed at realize)	Height of form
XXtNmappedWhenManaged Boolean	True			XtMapWidget is automatic
XXtNsensitive	Boolean		True			Widget receives input
XXtNlayout	Layout		None			See text
XXtNinternalHeight Dimension	0			Int. horizontal padding
XXtNinternalWidth Dimension	0			Int. vertical padding
XXtNcolumnSpacing Dimension	0			Inter-column padding
XXtNrowSpacing	Dimension	0			Inter-row padding
XXtNdefaultOptions Options	None			See text
X
X
XWidgets are added to a Table by specifying a Table widget as the
Xparent widget when the widget is created.  Once a widget is added to a
Xtable, it can be assigned a row and column position, a horizontal
Xand vertical span, and justification options.  This information can be
Xspecified in two ways: using public access functions or using the
Xresource database.
X
XPublic access functions allow the programmer to dynamically alter the
Xformatting of children of a Table widget.  One can alter the position,
Xspan, or options of a widget using XtTblConfig:
X
Xvoid XtTblConfig(
X     Widget w,		/* Subwidget to modify          */
X     Position col,	/* Column position (horizontal) */
X     Position row,	/* Row position (vertical)      */
X     Dimension h_span,	/* How many columns to span     */
X     Dimension v_span,	/* How many rows to span        */
X     XtTblMask opt	/* Justification options        */
X);
X
XThe specified widget (which must be a child of a Table widget) will be
Xplaced at column `col' and row `row'.  The widget will span `h_span'
Xcolumns to the right of `col' and `v_span' rows below `row'.  The
Xarray for the table will expand as necessary.  Options are specified
Xby `or'ing together the following option bits: 
X
X   TBL_LEFT		Horizontally left justified.
X   TBL_RIGHT		Horizontally right justified.
X   TBL_TOP		Vertically top justified.
X   TBL_BOTTOM 		Vertically bottom justified.
X   TBL_LK_WIDTH		Don't try to expand the widget horizontally.
X   TBL_LK_HEIGHT	Don't try to expand the widget vertically.
X   TBL_SM_WIDTH		Force the width to be as small as possible.
X   TBL_SM_HEIGHT	Force the height to be as small as possible.
X
XAlternatively,  if `options' is equal to TBL_DEF_OPT,  the options are
Xset to the default options for the Table widget.  The default options
Xfor the Table widget are set using the XtNdefaultOptions resource (see
Xresource specifications below).  The routine changes the formatting
Xinformation in its internal table.  If the Table widget is realized,
Xthe positions of all child widgets are recomputed and the change on
Xthe screen will be immediate.
X
X
XThe Table widget computes the size of a widget based on the minimum
Xsize required for the row(s) and column(s) it occupies.  However, some
Xwidgets may require less space than that computed by the Table widget.
XIn this case, the widget is aligned in the larger space according to
Xthe bits TBL_LEFT, TBL_RIGHT, TBL_TOP, and TBL_BOTTOM.  These bits may
Xbe combined (i.e. TBL_RIGHT|TBL_TOP specifies upper right hand corner
Xjustification). If no justification bits are specified, the widget is
Xcentered.
X
XSome widgets may be amenable to growing to any size specified by the
XTable widget.  Often, it may be desirable to force these widgets to
Xremain at their optimal size for asthetic or operational convenience.
XIf the TBL_LK_WIDTH bit is specified, the Table widget will not make
Xthe widget any wider than it's original desired size.  Similarly, if
Xthe TBL_LK_HEIGHT bit is specified, the Table widget will not make the
Xwidget any taller than it's original size.  Note this may bring widget
Xjustification into play.
X
XWhen a Table widget is resized, it automatically recomputes the sizes
Xof the rows and columns of an array and distributes extra space evenly
Xamong the rows and columns.  Often, it may be useful to control this
Xdistribution of space so that some rows or columns are not resized
Xwhen extra space becomes available.  If the TBL_SM_WIDTH bit is
Xspecified, the entire column(s) containing the widget are excluded
Xfrom the excess space distribution algorithm.  Thus, the column(s) are
Xforced to remain as small as possible.  The TBL_SM_HEIGHT bit works
Xthe same way with respect to the row(s) containing the widget. A title
Xbar is a good example of this concept. When a dialog is resized, any
Xexcess vertical space should be given to the body of the dialog not to
Xthe title bar.  Thus, TBL_SM_HEIGHT would be specified for a title bar
Xwidget.
X
X
XIn most applications, the programmer will not set all of the above
Xinformation for all widgets.  The following convenience functions have
Xbeen defined for use in these cases:
X
Xvoid XtTblPosition(
X     Widget w,		/* Child of table widget        */
X     Position col,	/* Column position (horizontal) */
X     Position row	/* Row position (vertical)      */
X);
X
XThe specified widget (which must be a child of a Table widget) will be
Xplaced at column `col' and row `row'.  The vertical and horizontal
Xspan of the widget will remain unchanged.  If the span of the widget
Xwas not set, it will default to one row and one column.  The
Xjustification options of the widget will remain unchanged.  If the
Xjustification options of the widget were not set, it will default to
XTBL_DEF_OPT (see XtTblConfig).
X
Xvoid XtTblResize(
X     Widget w,		/* Child of table widget        */
X     Dimension h_span,	/* How many columns to span     */
X     Dimention v_span	/* How many rows to span        */
X);
X
XThis routine changes the span of widget `w' (which must be a child of
Xa Table widget) to span `h_span' columns and `v_span' rows.  Any
Xprevious position or options assigned to the widget will be preserved.
XIf no position is associated with the widget,  it will be placed at
X(0,0).  If no options are associated with the widget, its options will
Xbe the defaults for the parent table widget.
X
Xvoid XtTblOptions(
X     Widget w,		/* Child of table widget */
X     XtTblMask opt	/* Option mask           */
X);
X
XThis routine changes the option bits of widget `w' (which must be a
Xchild of a Table widget) to `opt'.  The options are as described for
XXtTblConfig().  Any associated position and span of the widget remains
Xunchanged.  If the widget hasn't been placed, it will be located at
X(0,0) and given a span of (1,1).
X
X
XLayout information may also be specified using XtSetValues() or using
Xthe resource database.  The resources XtNlayout and XtNdefaultOptions
Xmay both be set in this fashion.
X
XThe XtNlayout resource allows the user to specify the row, column,
Xvertical span, horizontal span, and options for a set of widgets
Xstatically through the resource database or dynamically using
XXtSetValues().  The type of this resource is private to the Table
Xwidget.  However, the widget automatically registers a type converter
Xthat converts between a string layout format and the internal form
Xused by the Table widget.  This form is a list of statements separated
Xby semicolons.  Each statement has the form:
X
X	widget_name column row horizontal_span vertical_span opt_list
X
Xwidget_name	Name of the widget as given to XtCreateWidget().
Xcolumn		Integer >= 0 giving column in array
Xrow		Integer >= 0 giving row in array
Xhorizontal_span	Integer >= 1 giving number of columns to span
Xvertical_span	Integer >= 1 giving number of rows to span
Xopt_list	Series of characters each representing an option:
X	l:	TBL_LEFT
X	r:	TBL_RIGHT
X	t:	TBL_TOP
X	b:	TBL_BOTTOM
X	w:	TBL_LK_WIDTH
X	h:	TBL_LK_HEIGHT
X	W:	TBL_SM_WIDTH
X	H:	TBL_SM_HEIGHT
X
XThe options are as described for XtTblConfig().  The horizontal_span,
Xvertical_span, and opt_list are optional and may be omitted.  The
Xhorizontal and vertical spans will default to 1.  The option list will
Xdefault to the default options for the Table widget.  A sample layout
Xdescription is given below:
X
X	"Title 0 0 2 1 H; First 0 1; Second 1 1"
X
XWhen using XtSetValues to specify the XtNlayout resource, the caller
Xshould use the following function to parse a textual form into the
Xinternal form used by the Table widget:
X
Xcaddr_t XtTblParseLayout(
X	String layout		/* String layout specification */
X);
X
XThis function parses `layout' into an internal form that can be passed
Xto a Table widget as the XtNlayout resource.  The form of the layout
Xis described above.
X
XUnless otherwise specified, all options for widgets created under a
XTable widget are set based on the default options for the Table
Xwidget.  These default options are set using the XtNdefaultOptions
Xresource.  This resource can be specified in the resource database as
Xa string of option characters.  This string has the same form as the
Xopt_list described above for XtTblParseLayout().
X
X/*
X * Table Widget Example - Using resources
X *
X * Place the following entries in your resources file:
X *   TableExample.table.Layout: title 0 0 2 1 H; bt1 0 1; bt2 1 1
X *   TableExample*title.label: Title Bar
X *   TableExample*bt1.label: Button One
X *   TableExample*bt2.label: Button Two
X */
X
X#include <X11/StringDefs.h>
X#include <X11/Intrinsic.h>
X#include <X11/Shell.h>
X#include <X11/Label.h>
X#include <X11/Command.h>
X
X#include "Table.h"
X
X#define MAX_ARGS	10
X#define APP_NAME	"TableExample"
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X    Widget initialize(), top, table, title, bt1, bt2;
X    Arg arg_list[MAX_ARGS];
X    int arg_len;
X
X    top = initialize(&argc, argv);
X    arg_len = 0;
X    table = XtCreateManagedWidget("table", tableWidgetClass,
X				  top, arg_list, arg_len);
X    title = XtCreateManagedWidget("title", labelWidgetClass,
X				  table, arg_list, arg_len);
X    bt1 = XtCreateManagedWidget("bt1", commandWidgetClass,
X				table, arg_list, arg_len);
X    bt2 = XtCreateManagedWidget("bt2", commandWidgetClass,
X				table, arg_list, arg_len);
X    XtRealizeWidget(top);
X    XtMainLoop();
X}
X
XWidget initialize(argc_p, argv)
Xint *argc_p;
Xchar *argv[];
X{
X    Widget top;
X    Display *disp;
X    Arg arg_list[MAX_ARGS];
X    int arg_len;
X
X    XtToolkitInitialize();
X    disp = XtOpenDisplay((XtAppContext) 0, "", argv[0], APP_NAME,
X			 (XrmOptionDescRec *) 0, 0, argc_p, argv);
X    arg_len = 0;
X    XtSetArg(arg_list[arg_len], XtNallowShellResize, True); arg_len++;
X    top = XtAppCreateShell(argv[0], APP_NAME, applicationShellWidgetClass,
X			   disp, arg_list, arg_len);
X    return top;
X}
X
X/*
X * Table Widget Example - Direct specification
X *
X * This program creates one button for each string on the command
X * line.  Try "ex2 *" to see all the files in the directory.
X */
X
X#include <X11/StringDefs.h>
X#include <X11/Intrinsic.h>
X#include <X11/Shell.h>
X#include <X11/Label.h>
X#include <X11/Command.h>
X
X#include "Table.h"
X
X#define MAX_ARGS	10
X#define APP_NAME	"TableExample"
X#define NUM_ROWS	3
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X    Widget initialize(), top, table, title, button;
X    Arg arg_list[MAX_ARGS];
X    int arg_len, i, cols;
X
X    top = initialize(&argc, argv);
X    arg_len = 0;
X    table = XtCreateManagedWidget("table", tableWidgetClass,
X				  top, arg_list, arg_len);
X    XtSetArg(arg_list[arg_len], XtNlabel, "Title Bar");  arg_len++;
X    title = XtCreateManagedWidget("title", labelWidgetClass,
X				  table, arg_list, arg_len);
X    /* Each column will have three rows */
X    cols = (argc-1)/NUM_ROWS + 1;
X    XtTblConfig(title, 0, 0, cols, 1, TBL_SM_HEIGHT);
X    for (i = 1;  i < argc;  i++) {
X	arg_len = 0;
X	XtSetArg(arg_list[arg_len], XtNlabel, argv[i]);  arg_len++;
X	button = XtCreateManagedWidget("button", commandWidgetClass,
X				       table, arg_list, arg_len);
X	if (i < argc-1) {
X	    XtTblPosition(button, (i-1)/NUM_ROWS, (i-1)%NUM_ROWS + 1);
X	} else {
X	    /* Last one spans to bottom */
X	    XtTblConfig(button, (i-1)/NUM_ROWS, (i-1)%NUM_ROWS + 1,
X			1, 3 - ((i-1)%NUM_ROWS), TBL_DEF_OPT);
X	}
X    }
X    XtRealizeWidget(top);
X    XtMainLoop();
X}
X
XWidget initialize(argc_p, argv)
Xint *argc_p;
Xchar *argv[];
X{
X    Widget top;
X    Display *disp;
X    Arg arg_list[MAX_ARGS];
X    int arg_len;
X
X    XtToolkitInitialize();
X    disp = XtOpenDisplay((XtAppContext) 0, "", argv[0], APP_NAME,
X			 (XrmOptionDescRec *) 0, 0, argc_p, argv);
X    arg_len = 0;
X    XtSetArg(arg_list[arg_len], XtNallowShellResize, True); arg_len++;
X    top = XtAppCreateShell(argv[0], APP_NAME, applicationShellWidgetClass,
X			   disp, arg_list, arg_len);
X    return top;
X}
!STUFFY!FUNK!
echo Extracting Wc/Xt4GetResL.c
sed >Wc/Xt4GetResL.c <<'!STUFFY!FUNK!' -e 's/X//'
X/*
X    The following is the XtGetConstraintResourceList function from
X    the R4 Intrinsics.  This function is not provided by the Motif
X    1.0 Intrinsics.  Only change: ConstraintClassFlag was changed to
X    _XtConstraintBit.
X
X    This file normally does not get included into the Wc library.  Only
X    if the Widget Creation Library is intended to be used with Motif 1.0
X    (which is generally a bad idea - get Motif 1.1!!!!!!!), this file
X    should be compiled and either added to the library libWc, or 
X    added to the list of object files during linking, placed between
X    libWc and libXtm.
X
X    Or better yet, use Motif 1.1 so you can use the X11R4 Intrinsics!!!
X
X    Here is the standard X11 copyright notice which applies to this
X    file:
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#include <X11/IntrinsicP.h>
X/*************** Begin source from X11R4 GetResList.c ***************/
X
Xstatic Boolean ClassIsSubclassOf(class, superclass)
X    WidgetClass class, superclass;
X{
X    for (; class != NULL; class = class->core_class.superclass) {
X	if (class == superclass) return True;
X    }
X    return False;
X}
X
Xvoid XtGetConstraintResourceList(widget_class, resources, num_resources)
X	WidgetClass widget_class;
X	XtResourceList *resources;
X	Cardinal *num_resources;
X{
X	int size;
X	register int i, dest = 0;
X	register XtResourceList *list, dlist;
X	ConstraintWidgetClass class = (ConstraintWidgetClass)widget_class;
X
X	if (   (class->core_class.class_inited &&
X		!(class->core_class.class_inited & _XtConstraintBit)) /* DES */
X	    || (!class->core_class.class_inited &&
X		!ClassIsSubclassOf(widget_class, constraintWidgetClass))
X	    || class->constraint_class.num_resources == 0) {
X
X	    *resources = NULL;
X	    *num_resources = 0;
X	    return;
X	}
X
X	size = class->constraint_class.num_resources * sizeof(XtResource);
X	*resources = (XtResourceList) XtMalloc((unsigned) size);
X
X	if (!class->core_class.class_inited) {
X	    /* Easy case */
X
X	    bcopy((char *)class->constraint_class.resources,
X		    (char *) *resources, size);
X	    *num_resources = class->constraint_class.num_resources;
X	    return;
X	}
X
X	/* Nope, it's the hard case */
X
X	list = (XtResourceList *) class->constraint_class.resources;
X	dlist = *resources;
X	for (i = 0; i < class->constraint_class.num_resources; i++) {
X	    if (list[i] != NULL) {
X		dlist[dest].resource_name = (String)
X			XrmQuarkToString((XrmQuark) list[i]->resource_name);
X		dlist[dest].resource_class = (String) 
X			XrmQuarkToString((XrmQuark) list[i]->resource_class);
X		dlist[dest].resource_type = (String)
X			XrmQuarkToString((XrmQuark) list[i]->resource_type);
X		dlist[dest].resource_size = list[i]->resource_size;
X		dlist[dest].resource_offset = -(list[i]->resource_offset + 1);
X		dlist[dest].default_type = (String)
X			XrmQuarkToString((XrmQuark) list[i]->default_type);
X		dlist[dest].default_addr = list[i]->default_addr;
X		dest++;
X	    }
X	}
X	*num_resources = dest;
X}
X
X/*************** End source from X11R4 GetResList.c ***************/
!STUFFY!FUNK!
echo Extracting Ari/A02_Scrollbar
sed >Ari/A02_Scrollbar <<'!STUFFY!FUNK!' -e 's/X//'
X  This provides similar functionality as that shown by the Xaw example
X  named xscroll, which demonstrates how to use the Scrollbar widget.
X
XAri.wcChildren:		box
XAri.title:		A02_Scrollbar
X
X*box.wcClassName:	Box
X*Box*allowResize:	True
X*box.wcChildren:	quit, scrollbar
X
X*quit.wcClass:		commandWidgetClass
X*quit.Label:		Quit
X*quit.callback:		WcExitCB
X
X*scrollbar.wcClass:	scrollbarWidgetClass
X*scrollbar.orientation:	horizontal
X*scrollbar.topOfThumb:  0.5
X*scrollbar.length:	300
X*scrollbar.jumpProc:	WcSystemCB(echo Jumped)
X*scrollbar.scrollProc:	WcSystemCB( echo Scrolled)
X
!STUFFY!FUNK!
echo " "
echo "End of kit 27 (of 35)"
cat /dev/null >kit27isdone
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.