david@jpl-devvax.jpl.nasa.gov (David E. Smyth) (12/18/90)
Submitted-by: david@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@sun.com / argv@ora.com Opinions expressed reflect those of the author only. -- dan ---------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com Opinions expressed reflect those of the author only.