v10i058: wcl -- Widget Creation Library, Part10/11
David E. Smyth
david at jpl-devvax.jpl.nasa.gov
Tue Dec 18 09:18:14 AEST 1990
Submitted-by: david at jpl-devvax.jpl.nasa.gov (David E. Smyth)
Posting-number: Volume 10, Issue 58
Archive-name: wcl/part10
# to unbundle, "sh" this file -- DO NOT use csh
# SHAR archive format. Archive created Fri Oct 19 09:33:23 PDT 1990
echo x - WcConvert.c
sed 's/^X//' > WcConvert.c <<'+FUNKY+STUFF+'
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: @(#)WcConvert.c 1.04 ( 30 September 1990 )
X*
X* Subsystem_group:
X*
X* Widget Creation Library
X*
X* Module_description:
X*
X* This module contains Xt converter functions which convert strings,
X* as found in the Xrm database, into useful types.
X*
X* It also contains the routine which registers all Wc converters.
X*
X* The CvtStringToWidget converter takes a pathname which starts
X* from the application shell an proceeds to a specific widget. The
X* widget must already have been created. Note that this converter
X* needs to be used INSTEAD of the XmuCvtStringToWidget which gets
X* registered by the Athena widgets. The Xmu converter is not so
X* user friendly. This means this file also declares an external
X* function XmuCvtStringToWidget() which is really CvtStringToWidget,
X* and this needs to be linked before Xmu.
X*
X* The CvtStringToCallback converter parses the resource string in
X* the format:
X*
X* ...path: name[(args)][,name[(args)]]...
X*
X* where: name: specifies the registered callback function name
X* args: specifies the string passed to a callback as
X* "client data".
X*
X* Multiple callbacks can be specified for a single callback list
X* resource. Any callbacks must be "registered" by the application
X* prior converter invocation (.i.e.prior widget creation).
X* If no "args" string is provided, the default "client data"
X* specified at callback registration are used.
X*
X* The CvtStringToConstructor converter searches the Constructor
X* cache for a registered constructor.
X*
X* The CvtStringToClass converter searches the Class cache for a
X* registered object (widget) class pointer name.
X*
X* The CvtStringToClassName converter searches the ClassName cache
X* for a registered object (widget) class name.
X
X*
X* Module_interface_summary:
X*
X* Resource converter is invoked indirectly by the toolkit. The
X* converter is added to the toolkit by widgets calling
X* WcAddConverters() in the Wc intialization code.
X*
X* Module_history:
X*
X* mm/dd/yy initials function action
X* -------- -------- -------- ---------------------------------------------
X* 06/08/90 D.Smyth Class, ClassName, and Constructor converters.
X* 05/24/90 D.Smyth WcAddConverters created from something similar
X* 04/03/90 MarBru CvtStr.. Fixed argument termination with a NUL char
X* 02/26/90 MarBru All Created
X*
X* Design_notes:
X*
X* For VMS, we could have used LIB$FIND_IMAGE_SYMBOL and use dynamic
X* (runtime) binding. But since most UNIX systems lack such capability,
X* we stick to the concept of "registration" routines.
X*
X* One time, I considered applying conversion to callback argument, which
X* would take the burden of conversion from the callback code (runtime)
X* to the callback conversion (one time initialization). The problem is
X* that some conversions are widget context specific (color to pixel needs
X* display connection), and at the time of callback conversion I do not
X* have a widget. I could require the widget argument, but this would kill
X* caching of the conversion result.
X*
X* The sequential search of the callback cache is far from optimal. I should
X* use binary search, or the R4 conversion cache. I can't use the R4 cache
X* until Motif 1.1 is released which will (supposedly) run on R4 Intrinsics.
X*
X*******************************************************************************
X*/
X/*
X*******************************************************************************
X* Include_files.
X*******************************************************************************
X*/
X
X#include <ctype.h> /* isupper() and tolower macros */
X#include <stdio.h>
X
X/* -- X Window System includes */
X#include <X11/StringDefs.h>
X
X/* -- Widget Creation Library includes */
X#include "WcCreate.h"
X#include "WcCreateP.h"
X
X#ifdef MOTIF
X
X/* -- Motif specific includes for CvtStringToMenuWidget */
X#include <Xm/Xm.h>
X#include <Xm/RowColumn.h>
X#include <Xm/RowColumnP.h>
X
X#endif /* MOTIF */
X
X/*
X*******************************************************************************
X* Private_constant_declarations.
X*******************************************************************************
X*/
X
X/*
X*******************************************************************************
X* Private_type_declarations.
X*******************************************************************************
X*/
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* Private_data_definitions.
X*******************************************************************************
X*/
X
X/*
X*******************************************************************************
X* Private_function_declarations.
X*******************************************************************************
X*/
X
X/*
X -- Convert String To ClassPtr
X*******************************************************************************
X This conversion searches the Object Class cache for the appropriate
X Cache record. The resource database string is simply the name
X of the class pointer, case insensitive. The value provided is the
X widget class pointer, as passed to XtCreateWidget().
X*/
X
Xvoid CvtStringToClassPtr (args, num_args, fromVal, toVal )
X XrmValue *args;
X Cardinal *num_args;
X XrmValue *fromVal;
X XrmValue *toVal;
X{
X char* string = (char *) fromVal->addr;
X char cleanName[MAX_XRMSTRING];
X char* lowerCase;
X XrmQuark quark;
X int i;
X
X (void)WcCleanName ( string, cleanName );
X lowerCase = WcLowerCaseCopy ( cleanName );
X quark = XrmStringToQuark ( lowerCase );
X XtFree ( lowerCase );
X
X for (i=0; i<classes_num; i++)
X {
X if ( classes_ptr[i].quark == quark )
X {
X done( WidgetClass, classes_ptr[i].class );
X }
X }
X XtStringConversionWarning (cleanName, "Object Class, not registered.");
X}
X
X/*
X -- Convert String To ClassName
X*******************************************************************************
X This conversion searches the Class Name cache for the appropriate
X Cache record. The resource database string is simply the name
X of the class, case insensitive. The value provided is the widget
X class pointer, as passed to XtCreateWidget().
X*/
X
Xvoid CvtStringToClassName (args, num_args, fromVal, toVal )
X XrmValue *args;
X Cardinal *num_args;
X XrmValue *fromVal;
X XrmValue *toVal;
X{
X char* string = (char *) fromVal->addr;
X char cleanName[MAX_XRMSTRING];
X char* lowerCase;
X XrmQuark quark;
X int i;
X
X (void)WcCleanName ( string, cleanName );
X lowerCase = WcLowerCaseCopy ( cleanName );
X quark = XrmStringToQuark ( lowerCase );
X XtFree ( lowerCase );
X
X for (i=0; i<cl_nm_num; i++)
X {
X if ( cl_nm_ptr[i].quark == quark )
X {
X done( WidgetClass, cl_nm_ptr[i].class );
X }
X }
X XtStringConversionWarning (cleanName, "Class Name, not registered.");
X}
X
X/*
X -- Convert String To Constructor
X*******************************************************************************
X This conversion searches the Constructor Cache for the appropriate
X Cache record. The resource database string is simply the name
X of the constructor, case insensitive. The value provided is a
X Contrstructor Cache Record. The constructor (func ptr) itself is
X not provided, as the user of this value (generally WcCreateDatabaseChild)
X also likes to have the constructor name as registered for error messages.
X*/
X
Xvoid CvtStringToConstructor (args, num_args, fromVal, toVal)
X XrmValue *args;
X Cardinal *num_args;
X XrmValue *fromVal;
X XrmValue *toVal;
X{
X char* string = (char *) fromVal->addr;
X char cleanName[MAX_XRMSTRING];
X char* lowerCase;
X XrmQuark quark;
X int i;
X
X (void)WcCleanName ( string, cleanName );
X lowerCase = WcLowerCaseCopy ( cleanName );
X quark = XrmStringToQuark ( lowerCase );
X XtFree ( lowerCase );
X
X for (i=0; i<constrs_num; i++)
X {
X if ( constrs_ptr[i].quark == quark )
X {
X done( ConCacheRec*, &(constrs_ptr[i]) );
X }
X }
X XtStringConversionWarning (cleanName, "Constructor, not registered.");
X}
X
X/*
X -- Convert String To Callback
X*******************************************************************************
X This conversion creates a callback list structure from the X resource
X database string in format:
X
X name(arg),name(arg).....
X
X Note "name" is not case sensitive, while "arg" may be - it is passed to
X a callback as client data as a null terminated string (first level
X parenthesis stripped off). Even if nothing is specified e.g.,
X SomeCallback() there is a null terminated string passed as client
X data to the callback. If it is empty, then it is the null string.
X
X Note also that the argument CANNOT be converted at this point: frequently,
X the argument refers to a widget which has not yet been created, or
X uses the context of the callback (i.e., WcUnmanageCB( this ) uses the
X widget which invoked the callback).
X*/
X
Xvoid CvtStringToCallback (args, num_args, fromVal, toVal)
X XrmValue *args;
X Cardinal *num_args;
X XrmValue *fromVal;
X XrmValue *toVal;
X{
X static XtCallbackRec *cb; /* return pointer, MUST be static */
X
X XtCallbackRec callback_list[MAX_CALLBACKS];
X XtCallbackRec *rec = callback_list;
X int callback_list_len = 0;
X
X typedef struct
X {
X char *nsta,*nend; /* callback name start, end */
X char *asta,*aend; /* argument string start, end */
X } Segment;
X
X Segment name_arg_segments[MAX_CALLBACKS];
X Segment *seg = name_arg_segments;
X char *string = (char *) fromVal->addr;
X register char *s;
X register int in_parens = 0;
X
X register int i;
X
X/* -- assume error or undefined input argument */
X toVal->size = 0;
X toVal->addr = (caddr_t) NULL;
X if (string == NULL) return;
X
X/* -- parse input string finding segments "name(arg)" comma separated */
X seg->nsta = seg->nend = seg->asta = seg->aend = (char*)NULL;
X
X for ( s=string; ; s++ )
X {
X switch (*s)
X {
X case ',': if ( in_parens ) break; /* commas in arguments ignored */
X case NUL: if ( seg->nend == NULL ) seg->nend = s-1; /* no argument */
X seg++; /* start the next segment */
X seg->nsta = seg->nend = seg->asta = seg->aend = (char*)NULL;
X break;
X
X case '(': if ( in_parens++ == 0 ) { seg->nend = s-1; seg->asta = s+1; }
X break;
X
X case ')': if ( --in_parens == 0 ) { seg->aend = s-1; };
X break;
X
X default: if ( *s > ' ' && seg->nsta == NULL )
X /* only start a new segment on non-blank char */
X seg->nsta = s;
X }
X if (*s == NUL) break;
X }
X
X if (in_parens)
X {
X XtStringConversionWarning (string, "Callback, unbalanced parenthesis");
X return;
X }
X
X/* -- process individual callback string segments "name(arg)" */
X for( seg = name_arg_segments; seg->nsta; seg++)
X {
X char cb_name[MAX_XRMSTRING];
X register char *d;
X XrmQuark quark;
X int found;
X
X /* our callback cache names are case insensitive, no white space */
X for ( s=seg->nsta, d=cb_name; s<=seg->nend; )
X if ( *s > ' ')
X *d++ = (isupper(*s) ) ? tolower (*s++) : *s++;
X else
X s++;
X *d = NUL;
X
X /* try to locate callback in our cache of callbacks */
X quark = XrmStringToQuark (cb_name);
X for (found = 0, i=0 ; !found && i<callbacks_num ; i++)
X if ( callbacks_ptr[i].quark == quark )
X {
X rec->callback = callbacks_ptr[i].callback;
X rec->closure = callbacks_ptr[i].closure;
X found++;
X }
X
X /* we have found a registered callback, process arguments */
X if (found)
X {
X register char *arg;
X register int alen;
X
X if ( seg->asta )
X {
X /* arg in parens - pass as string replacing default closure */
X alen = (int)seg->aend - (int)seg->asta +1;
X arg = XtMalloc(alen+1);
X strncpy ( arg, seg->asta, alen );
X arg[alen] = NUL;
X rec->closure = (caddr_t)arg;
X }
X else
X {
X /* no arg in parens. Make sure closure is something -
X ** do NOT return NULL in any event. Causes SEGV too
X ** easily.
X */
X if (rec->closure == NULL)
X rec->closure = (caddr_t)"";
X }
X rec++;
X callback_list_len++;
X }
X else
X {
X XtStringConversionWarning (cb_name,
X "Callback, unknown callback name");
X }
X } /* end for seg loop */
X
X/* -- terminate the callback list */
X {
X rec->callback = NULL;
X rec->closure = NULL;
X callback_list_len++;
X }
X
X/* -- make a permanent copy of the new callback list, and return a pointer */
X cb = (XtCallbackRec*)XtMalloc( callback_list_len * sizeof (XtCallbackRec) );
X memcpy ( (char*)cb, (char*)callback_list,
X callback_list_len * sizeof (XtCallbackRec));
X toVal->size = sizeof (XtCallbackRec*);
X toVal->addr = (caddr_t)&cb;
X}
X
X/*
X -- Convert String To Widget
X*******************************************************************************
X This conversion creates a Widget id from the X resource database string.
X The conversion will fail, and WcFullNameToWidget() will issue a warning,
X if the widget so named has not been created when this converter is called.
X For example, if a widget refers to itself for some reason, during
X its creation when this converter is called, it is not yet created:
X therefore, the converter will fail.
X*/
X
Xvoid XmuCvtStringToWidget (args, num_args, fromVal, toVal)
X XrmValue *args;
X Cardinal *num_args;
X XrmValue *fromVal;
X XrmValue *toVal;
X{
X toVal->addr =
X (caddr_t) WcFullNameToWidget( WcRootWidget(NULL), fromVal->addr);
X toVal->size = sizeof(Widget);
X}
X
X#ifdef MOTIF
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#endif /* MOTIF */
X
X/*
X*******************************************************************************
X* Public_function_declarations.
X*******************************************************************************
X*/
X
X/*
X -- Add String To ... Convertors
X*******************************************************************************
X*/
X
Xvoid WcAddConverters ( app )
X XtAppContext app;
X{
X ONCE_PER_XtAppContext( app );
X
X XtAddConverter (XtRString,
X WcRClassPtr,
X CvtStringToClassPtr,
X (XtConvertArgList)NULL,
X (Cardinal)0);
X
X XtAddConverter (XtRString,
X WcRClassName,
X CvtStringToClassName,
X (XtConvertArgList)NULL,
X (Cardinal)0);
X
X XtAddConverter (XtRString,
X WcRConstructor,
X CvtStringToConstructor,
X (XtConvertArgList)NULL,
X (Cardinal)0);
X
X XtAddConverter (XtRString,
X XtRCallback,
X CvtStringToCallback,
X (XtConvertArgList)NULL,
X (Cardinal)0);
X
X#ifndef MOTIF
X XtAddConverter (XtRString,
X XtRWidget,
X XmuCvtStringToWidget,
X (XtConvertArgList)NULL,
X (Cardinal)0);
X#else
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#endif /* !MOTIF */
X}
+FUNKY+STUFF+
echo '-rw-r--r-- 1 david 20212 Oct 9 17:11 WcConvert.c (as sent)'
chmod u=rw,g=r,o=r WcConvert.c
ls -l WcConvert.c
echo x - WcCreate.c
sed 's/^X//' > WcCreate.c <<'+FUNKY+STUFF+'
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.03 ( 11 July 1990 )
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/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 { 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/*
X*******************************************************************************
X* Public_function_declarations.
X*******************************************************************************
X*/
X
X/*
X -- Create Database Child
X*******************************************************************************
X This function checks the resource database for creation resources
X of the named widget. If found, the child is created using the specified
X class, and the creation callbacks are called.
X
X Note that whenever this function generates a warning message, it
X uses the parent's name. In order to improve run-time efficientcy,
X the parent name is only determined when a warning message is to be
X generated. This adds a few lines of code, but it speeds the
X nominal case where there are no warnings.
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
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, &res, name, name,
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 ( res.resFile )
X {
X WcLoadResourceFileCB ( pw, res.resFile, NULL );
X XtGetSubresources ( pw, &res, name, name,
X wc_resources, XtNumber(wc_resources), NULL, 0 );
X }
X
X if ( !res.class && !res.classFromName && !res.constructor )
X {
X char* parentName = WcWidgetToFullName( pw );
X sprintf( msg,
X "WcCreateDatabaseChild (%s.%s) - Failed \n\
X Problem: No %s, %s, nor %s specified, \n\
X Child `%s' could not be created.",
X parentName, name,
X WcCWcClass, WcCWcClassName, WcCWcConstructor,
X name );
X XtWarning( msg );
X child = (Widget)NULL;
X XtFree( parentName );
X }
X
X else if ( res.class || res.classFromName )
X {
X if ( res.class && res.classFromName && res.constructor )
X {
X char* parentName = WcWidgetToFullName( pw );
X sprintf( msg,
X "WcCreateDatabaseChild (%s.%s) \n\
X Problem: %s, %s, and %s resources specified, \n\
X `%s.%s: %s' and \n\
X `%s.%s: %s' ignored.",
X parentName, name,
X WcCWcClass, WcCWcClassName, WcCWcConstructor,
X name, WcCWcClassName, res.classFromName->core_class.class_name,
X name, WcCWcConstructor, res.constructor->name );
X XtWarning( msg );
X XtFree( parentName );
X }
X else if ( res.class && res.classFromName )
X {
X char* parentName = WcWidgetToFullName( pw );
X sprintf( msg,
X "WcCreateDatabaseChild (%s.%s) \n\
X Problem: %s and %s resources specified, \n\
X `%s.%s: %s' ignored.",
X parentName, name,
X WcCWcClass, WcCWcClassName,
X name, WcCWcClassName, res.classFromName->core_class.class_name);
X XtWarning( msg );
X XtFree( parentName );
X }
X else if ( res.class && res.constructor )
X {
X char* parentName = WcWidgetToFullName( pw );
X sprintf( msg,
X "WcCreateDatabaseChild (%s.%s) \n\
X Problem: %s and %s resources specified, \n\
X `%s.%s: %s' ignored.",
X parentName, name,
X WcCWcClass, WcCWcConstructor,
X name, WcCWcConstructor, res.constructor->name );
X XtWarning( msg );
X XtFree( parentName );
X }
X else if ( res.classFromName && res.constructor )
X {
X char* parentName = WcWidgetToFullName( pw );
X sprintf( msg,
X "WcCreateDatabaseChild (%s.%s) \n\
X Problem: %s and %s resources specified, \n\
X `%s.%s: %s' ignored.",
X parentName, name,
X WcCWcClassName, WcCWcConstructor,
X name, WcCWcConstructor, res.constructor->name );
X XtWarning( msg );
X XtFree( parentName );
X }
X
X if ( res.class )
X child = XtCreateWidget ( name, res.class, pw, NULL, 0 );
X else
X child = XtCreateWidget ( name, res.classFromName, pw, NULL, 0 );
X
X if ( !child )
X {
X char* parentName = WcWidgetToFullName( pw );
X sprintf( msg,
X "WcCreateDatabaseChild (%s.%s) - Failed \n\
X Problem: XtCreateWidget ( %s, %s ) failed.",
X parentName, name, name, res.class->core_class.class_name );
X XtWarning( msg );
X XtFree( parentName );
X }
X }
X
X else if ( res.constructor )
X {
X child = res.constructor->constructor( pw, name, NULL, 0 );
X
X if ( !child )
X {
X char* parentName = WcWidgetToFullName( pw );
X sprintf( msg,
X "WcCreateDatabaseChild (%s.%s) - Failed \n\
X Problem: %s ( %s ) failed.",
X parentName, name, res.constructor->name, name );
X XtWarning( msg );
X XtFree( parentName );
X }
X }
X
X if ( child )
X {
X /* A child widget was created.
X ** print out creation trace, if required
X */
X if ( res.trace )
X {
X char* childName = WcWidgetToFullName( child );
X fprintf(stderr,"Wc %s: %s of class %s\n",
X ((res.managed) ? " managed" : "unmanaged"), childName,
X child->core.widget_class->core_class.class_name);
X XtFree( childName );
X }
X
X /* call creation callbacks */
X if ( res.callback )
X {
X XtCallbackRec *cb = res.callback;
X for ( ; cb->callback; cb++ )
X (*cb->callback)( child, cb->closure, NULL );
X }
X
X if ( res.children )
X {
X if ( XtIsSubclass( child, compositeWidgetClass ) )
X {
X /* child is a manager widget, create its children */
X WcCreateNamedChildren ( child, res.children );
X }
X else
X {
X char* parentName = WcWidgetToFullName( pw );
X sprintf( msg,
X "WcCreateDatabaseChild (%s.%s) - children ignored \n\
X Problem: %s is not a composite, cannot have children.",
X parentName, name, name );
X XtWarning( msg );
X XtFree( parentName );
X }
X }
X }
X
X *managed = res.managed;
X return (child);
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 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.children )
X WcCreateNamedChildren ( root, res.children );
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}
+FUNKY+STUFF+
echo '-rw-r--r-- 1 david 22768 Sep 6 13:21 WcCreate.c (as sent)'
chmod u=rw,g=r,o=r WcCreate.c
ls -l WcCreate.c
echo x - WcCreate.h
sed 's/^X//' > WcCreate.h <<'+FUNKY+STUFF+'
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.h 1.03 ( 16 July 1990 )
X*
X* Include_name:
X*
X* WcCreate.h
X*
X* Subsystem_group:
X*
X* Widget Creation Library
X*
X* Include_description:
X*
X* Public defines for the Widget Creation Library supporting widget
X* tree creation from the Xrm database.
X*
X* Include_history:
X*
X* mm/dd/yy initials action
X* -------- -------- -------------------------------------------------------
X* 07/16/90 D.Smyth added WcAllowDuplicate*Reg... decls
X* 06/30/90 R.Whitby added WcRegisterWcActions declaration
X* 06/19/90 D.Smyth Widget Creation Library version 1.0 Release
X* 04/04/90 marbru updated, added new callbacks
X* 03/27/90 marbru updated for new names
X* 03/02/90 marbru created
X*
X*******************************************************************************
X*/
X#ifndef _WcCreate_h
X#define _WcCreate_h
X
X#include <X11/IntrinsicP.h>
X#include <X11/CoreP.h>
X#include <X11/ObjectP.h>
X
X#ifdef FUNCTION_PROTOTYPES
X/****************************** ANSI FUNC DECLS ******************************/
X
X#define APP XtAppContext
X#define EV extern void
X#define EW extern Widget
X#define EC extern char*
X
X/* -- Widget class, constructor, and callback proc registration routines */
X
XEV WcRegisterClassPtr (APP, char* name, WidgetClass class);
XEV WcRegisterClassName (APP, char* name, WidgetClass class);
XEV WcRegisterConstructor(APP, char* name, Widget(*constructor) () );
XEV WcRegisterCallback (APP, char* CBname, XtCallbackProc, caddr_t defCliData);
XEV WcRegisterAction (APP, char* name, XtActionProc proc );
XEV WcRegisterWcCallbacks(APP );
X
X/* -- Allow duplicate registration of classes, constructors, and callbacks */
X
XEV WcAllowDuplicateRegistration ( int allowed );
XEV WcAllowDuplicateClassPtrReg ( int allowed );
XEV WcAllowDuplicateClassNameReg ( int allowed );
XEV WcAllowDuplicateConstructorReg ( int allowed );
XEV WcAllowDuplicateCallbackReg ( int allowed );
X
X/* -- Widget action registration routine */
X
XEV WcRegisterWcActions ( APP );
X
X/* -- Widget creation routines */
X
XEV WcWidgetCreation ( Widget root );
XEV WcCreateNamedChildren ( Widget parent, char* names );
XEW WcCreateDatabaseChild ( Widget parent, char* name, int* managed );
X
X/* -- Widget name routines
X** The character buffer returned by WcNamesToWidgetList contains the
X** names which could not be converted to widgets. This buffer is static,
X** so its contents are changed everytime WcNamesToWidgetList is called.
X** The character buffer returned by WcWidgetToFullName must be XtFree'd
X** by the caller.
X*/
X
XEW WcChildNameToWidget ( Widget w, char* childName );
XEW WcFullNameToWidget ( Widget w, char* name );
XEC WcNamesToWidgetList ( Widget, char* names, Widget widgetList[], int* count);
XEC WcWidgetToFullName ( Widget w );
X
X/* -- Useful for argument parsing */
X
XEC WcLowerCaseCopy ( char* in ); /* caller frees buf */
XEC WcSkipWhitespace ( char* cp );
XEC WcSkipWhitespace_Comma ( char* cp );
XEC WcCleanName ( char* in, char* out ); /* out[] must exist */
XEC WcStripWhitespaceFromBothEnds (char* name ); /* caller frees buf */
X
XEC WcGetResourceType ( Widget, char* rName ); /* caller frees buf */
XEV WcSetValueFromString ( Widget, char* rName, char* rVal );
XEV WcSetValueFromStringAndType( Widget, char* rName, char* rVal, char* rType );
X
XEC WcStrStr( char* searchThis, char* forThisPattern ); /* like ANSI strstr */
X
X#undef APP
X#undef EV
X#undef EW
X#undef EC
X
X#else
X/**************************** NON-ANSI FUNC DECLS ****************************/
X
X/* -- Widget constructor registration routine */
X
Xextern void WcRegisterClassPtr ();
Xextern void WcRegisterClassName ();
Xextern void WcRegisterConstructor ();
Xextern void WcRegisterCallback ();
Xextern void WcRegisterAction ();
Xextern void WcRegisterWcCallbacks ();
X
X/* -- Allow duplicate registration of classes, constructors, and callbacks */
X
Xextern void WcAllowDuplicateRegistration ();
Xextern void WcAllowDuplicateClassPtrReg ();
Xextern void WcAllowDuplicateClassNameReg ();
Xextern void WcAllowDuplicateConstructorReg ();
Xextern void WcAllowDuplicateCallbackReg ();
X
X/* -- Widget action registration routine */
X
Xextern void WcRegisterWcActions ();
X
X/* -- Widget creation routines */
X
Xextern void WcWidgetCreation ();
Xextern void WcCreateNamedChildren ();
Xextern Widget WcCreateDatabaseChild ();
X
X/* -- Widget name routine */
X
Xextern Widget WcChildNameToWidget ();
Xextern Widget WcFullNameToWidget ();
Xextern char* WcNamesToWidgetList (); /* rets: names not converted */
Xextern char* WcWidgetToFullName (); /* ret'd buff must be free'd */
X
Xextern char* WcLowerCaseCopy (); /* ret'd buff must be free'd */
Xextern char* WcSkipWhitespace ();
Xextern char* WcSkipWhitespace_Comma ();
Xextern char* WcCleanName ();
Xextern char* WcStripWhitespaceFromBothEnds (); /* ret'd buff must be free'd */
X
Xextern char* WcGetResourceType (); /* ret'd buff must be free'd */
Xextern void WcSetValueFromString ();
Xextern void WcSetValueFromStringAndType ();
X
Xextern char* WcStrStr (); /* same as ANSI strstr() */
X
X#endif /* FUNCTION_PROTOTYPES */
X
X#endif /* _WcCreate_h */
+FUNKY+STUFF+
echo '-rw-r--r-- 1 david 7319 Oct 9 14:55 WcCreate.h (as sent)'
chmod u=rw,g=r,o=r WcCreate.h
ls -l WcCreate.h
exit 0
dan
----------------------------------------------------
O'Reilly && Associates argv at sun.com / argv at ora.com
Opinions expressed reflect those of the author only.
--
dan
----------------------------------------------------
O'Reilly && Associates argv at sun.com / argv at ora.com
Opinions expressed reflect those of the author only.
More information about the Comp.sources.x
mailing list