david@devvax.Jpl.Nasa.Gov (David E. Smyth) (07/06/90)
Submitted-by: david@devvax.Jpl.Nasa.Gov (David E. Smyth) Posting-number: Volume 8, Issue 35 Archive-name: wcl/part05 # to unbundle, "sh" this file -- DO NOT use csh # SHAR archive format. Archive created Tue Jul 3 16:49:35 PDT 1990 echo x - WcCreateFunc.c sed 's/^X//' > WcCreateFunc.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: @(#)WcCreateFunc.c 1.0 ( 19 June 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. The WcDeferred resource allows widget heirarchies to X* be created after the initial widget tree - their creation is X* deferred. Only the root of a deferred heirarchy has its X* WcDeferred resource set True. For example, let's say your interface X* includes a box world, where the user can create an arbitrary number X* of various types of boxes: X* X* *box_world.wcClass: MyBoxWorldWidgetClass X* *box_world.wcChildren: box_type1, box_type2, box_type3 X* *box_type1.wcClass: MyBoxType1WidgetClass X* *box_type1.WcDeferred: True X* *box_type2.wcClass: MyBoxType2WidgetClass X* *box_type2.WcDeferred: True X* *box_type3.wcClass: MyBoxType3WidgetClass X* *box_type3.wcClass: True X* *box_type3.wcChildren: child1, child2, child3, child4 X* *button1.callback: WcCreateCB( *box_type1 ) X* *button2.callback: WcCreateCB( *box_type2 ) X* *button3.callback: WcCreateCB( *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* 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.wcDeferred: true/false (default = false) 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 "wcDeferred" resource is TRUE, or a X* 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 WcCallbacks.c X* X* Module_history: X X* mm/dd/yy initials function action X* -------- -------- -------- --------------------------------------------- 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 "WidgetCreate.h" X#include "WidgetCreateP.h" X X/* X******************************************************************************* X* Private_data_definitions. X******************************************************************************* X*/ X Xstatic char msg[MAX_ERRMSG]; X X/* -- Creation resources 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 { 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 { WcNwcDeferred, WcCWcDeferred, XtRBoolean, sizeof(Boolean), X XtOffset(ResourceRecPtr, deferred), XtRImmediate, (caddr_t) FALSE 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 -- 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 Unless the force flag is TRUE, this function will NOT create widgets X whose WcDeferred resource is TRUE. The force flag is only true on X the initial widget when a tree of widgets is being created. X*/ X Xstatic Widget WcCreateDatabaseChild ( pw, name, force, managed ) X Widget pw; /* child's parent */ X char* name; /* child name to create */ X int force; /* T/F: force creation of deferred widget? */ X int *managed; /* returned T/F: this child to be managed ? */ X{ X char* parentName; /* for err msgs, must be XtFree'd */ X ResourceRec res; /* child's creation resources */ X Widget child; /* what we create */ X X /* Cobble together the child name from the parent's full path name X ** and the child's name. X */ X parentName = WcWidgetToFullName( pw ); 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 /* Don't create widgets with WcDeferred resource unless forced */ X if ( res.deferred && !force ) X { X child = (Widget)NULL; X } X X else if ( !res.class && !res.classFromName && !res.constructor ) X { 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 } X X else if ( res.class || res.classFromName ) X { X if ( res.class && res.classFromName && res.constructor ) X { 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 } X else if ( res.class && res.classFromName ) X { 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 } X else if ( res.class && res.constructor ) X { 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 } X else if ( res.classFromName && res.constructor ) X { 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 } 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 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 } X } X X else if ( res.constructor ) X { X child = res.constructor->constructor( pw, name, NULL, 0 ); X X if ( !child ) X { 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 } 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* name = WcWidgetToFullName( child ); X fprintf(stderr,"Wc %s: %s of class %s\n", X ((res.managed) ? " managed" : "unmanaged"), name, X child->core.widget_class->core_class.class_name); X XtFree(name); 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 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 } X } X } X X XtFree( parentName ); 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 The force flag is passed to WcCreateDatabaseChild() and is used to X indicate that children are to be created even if their WcDeferred X resource is TRUE. X*/ X Xstatic void WcCreateAndManageChildren ( pw, names, force ) X Widget pw; /* children's parent */ X char* names; /* (list of) widget names to create */ X int force; /* force creation of deferred widgets */ X{ X Widget child; X int widget_count = 0; X Widget widget_list[MAX_CHILDREN]; X char cleanName[MAX_XRMSTRING]; X char* next; X int managed; X X if ( !names ) return; X X next = WcCleanName( names, cleanName ); X X while ( cleanName[0] ) X { X child = WcCreateDatabaseChild ( pw, cleanName, force, &managed ); X if ( child && managed ) X widget_list[widget_count++] = child; X next = WcSkipWhitespace_Comma( next ); X next = WcCleanName( next, cleanName ); X } X X if ( widget_count ) X XtManageChildren( widget_list, widget_count ); X} X X/* X******************************************************************************* X* Public_function_declarations. X******************************************************************************* X*/ X X/* X -- Create Widget Tree from Xrm Database X******************************************************************************* X This routine creates widget children as defined in Xrm database. X It checks the widget resource "WcChildren", which is a list of X names of children to create. Each child must then be further defined X in the databse. X X This function is frequently called from an application's main() X procedure after the application shell is created via XtInitialize(). X X Note that this function registers the converters for StringToWidget, X StringToCallback, and so forth. X*/ X Xvoid WcWidgetCreation ( root ) X Widget root; X{ X XtAppContext app = XtWidgetToApplicationContext( root ); X char* fullName = WcWidgetToFullName( root ); /* must be XtFree'd */ X ResourceRec res; X X /* register the root of this widget */ X (void)WcRootWidget(root); X X /* register the 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.", X fullName ); 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 ); X XtWarning( msg ); X } X X XtFree ( fullName ); X} X X/* X -- Create Named Children from Xrm Database X******************************************************************************* X These functions create widget's children specified by names list, using X information contained in X resource database. After creation, children X are managed (unless WcManaged resource is FALSE). X X Children whose WcDeferred resource is True are NOT created by X WcCreateNamedChildren(). They are only created with an explicit call X to WcCreateDeferredChildren(). X*/ X Xvoid WcCreateDeferredChildren ( pw, names ) X Widget pw; /* children's parent */ X char* names; /* (list of) widget names to create */ X{ X WcCreateAndManageChildren ( pw, names, TRUE ); /* create even if deferred */ X} X Xvoid WcCreateNamedChildren ( pw, names ) X Widget pw; /* children's parent */ X char* names; /* (list of) widget names to create */ X{ X WcCreateAndManageChildren ( pw, names, FALSE ); /* don't create deferred */ X} +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 21152 Jul 3 10:26 WcCreateFunc.c (as sent)' chmod u=rw,g=r,o=r WcCreateFunc.c ls -l WcCreateFunc.c echo x - WcMotifP.h sed 's/^X//' > WcMotifP.h <<'+FUNKY+STUFF+' X/* X** Copyright (c) 1990 David E. Smyth X** X** Redistribution and use in source and binary forms are permitted X** provided that the above copyright notice and this paragraph are X** duplicated in all such forms and that any documentation, advertising X** materials, and other materials related to such distribution and use X** acknowledge that the software was developed by David E. Smyth. The X** name of David E. Smyth may not be used to endorse or promote products X** derived from this software without specific prior written permission. X** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X** WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X** X*/ X X/* X* SCCS_data: @(#)WcMotifP.h 1.0 ( 19 June 1990 ) X*/ X X#ifndef _WcMotifP_h_ X#define _WcMotifP_h_ X X/* Core, Object, RectObj, WindowObj, X** XmGadget, XmPrimitive, and XmComposite, X** Shell, OverrideShell, WMShell, VendorShell, TopLevelShell, ApplicationShell, X** Constraint, XmManager. X*/ X#include <Xm/XmP.h> X X/* XmGadget Subclasses X*/ X#include <Xm/ArrowBGP.h> X#include <Xm/SeparatoGP.h> X#include <Xm/LabelGP.h> X#include <Xm/CascadeBGP.h> X#include <Xm/PushBGP.h> X#include <Xm/ToggleBGP.h> X X/* XmPrimitive Subclasses X*/ X#include <Xm/ArrowBP.h> X#include <Xm/ListP.h> X#include <Xm/ScrollBarP.h> X#include <Xm/SeparatorP.h> X#include <Xm/TextP.h> X#include <Xm/LabelP.h> X#include <Xm/CascadeBP.h> X#include <Xm/DrawnBP.h> X#include <Xm/PushBP.h> X#include <Xm/ToggleBP.h> X X/* XmManager Subclasses X*/ X#include <Xm/DrawingAP.h> X#include <Xm/FrameP.h> X#include <Xm/PanedWP.h> X#include <Xm/RowColumnP.h> X#include <Xm/ScaleP.h> X#include <Xm/ScrolledWP.h> X#include <Xm/MainWP.h> X#include <Xm/BulletinBP.h> X#include <Xm/FormP.h> X#include <Xm/MessageBP.h> X#include <Xm/SelectioBP.h> X#include <Xm/CommandP.h> X#include <Xm/FileSBP.h> X X/* Shell Subclasses X*/ X#include <Xm/X11/ShellP.h> X#include <Xm/X11/VendorP.h> X#include <Xm/MenuShellP.h> X#include <Xm/DialogSP.h> X X/* Apparently Obsolete X*/ X#include <Xm/SashP.h> X X#endif +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 2054 Jun 28 09:13 WcMotifP.h (as sent)' chmod u=rw,g=r,o=r WcMotifP.h ls -l WcMotifP.h echo x - WcNameFuncs.c sed 's/^X//' > WcNameFuncs.c <<'+FUNKY+STUFF+' X/* X** Copyright (c) 1990 David E. Smyth X** X** Redistribution and use in source and binary forms are permitted X** provided that the above copyright notice and this paragraph are X** duplicated in all such forms and that any documentation, advertising X** materials, and other materials related to such distribution and use X** acknowledge that the software was developed by David E. Smyth. The X** name of David E. Smyth may not be used to endorse or promote products X** derived from this software without specific prior written permission. X** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X** WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X** X*/ X X/****************************************************************************** X** SCCS_data: @(#)WcNameFuncs.c 1.0 ( 19 June 1990 ) X** X** Description: Implements several name-to-widget and widget-to-name X** functions which are generally useful, especially a name X** to widget function which really works: X** X** Widget WcFullNameToWidget(char* widget_name) X** X** Notes: Most of the "private" part of this file goes away when X** the bug in the Xt Intrinsics is fixed which causes X** XtNameToWidget() to dump core whenever a Gadget exists X** in the widget heirarchy... X** X******************************************************************************/ X X/****************************************************************************** X* Include_files. X******************************************************************************/ X X#include <ctype.h> /* isupper() and tolower macros */ X X/* -- X Window System includes */ X#include <X11/StringDefs.h> X X#ifdef MOTIF X#include <Xm/XmP.h> X#endif X X/* -- Widget Creation Library includes */ X#include "WidgetCreate.h" X#include "WidgetCreateP.h" X X/* X******************************************************************************* X* Private_data_definitions. X******************************************************************************* X*/ X X/* NOTE: These are shared arrays because they are large: i.e., X** this is a performacne optimization intended to reduce page X** faults which can occur while making large extensions to the X** stack space. Wait a minute: wouldn't this just happen X** once, and then the stack space is alloc'd? Yes, but a X** huge stack space runs the risk of getting swapped, which causes X** page faults. This is probably a nit-picky sort of optimization. X** Remember that D.Smyth is an old sys programmer from the stone X** ages, and pity him instead of flaming him. X** Be careful when filling msg not to call any funcs in here, X** so the message does not get garbled. X*/ X Xstatic char msg[MAX_ERRMSG]; Xstatic char cleanName[MAX_PATHNAME]; X X/* X******************************************************************************* X* Private_function definitions. X******************************************************************************* X The following implements XtNameToWidget() in a way which really works. X X Note: the #if defined... assumes a FIXED version of R4. The version X even as of 19 June 1990 still is not correct (dumps core on Gadgets). X*/ X X#if defined(XtSpecificationRelease) && XtSpecificationRelease > 4 X XWidget WcChildNameToWidget( Widget ref, char* childName) X{ X return XtNameToWidget( ref, childName ); X} X X#else X X/* NOTE: The Motif XtNameToWidget is broken: it cannot find X** names with wild cards. The R4 XtNameToWidget is also broken: it X** cannot handle encounters with Gadgets. X** X** Below is the code extracted from the X11R4 distribution, with very X** minor changes to make it independent from the rest of the R4 Intrinsics, X** and to fix the bug in encountering Gadgets. X** X** Fixes: Added the two lines following this comment block. X** Renamed XtNameToWidget to WcChildNameToWidget to avoid warning. X** Removed "register" from arg type decls, as dbx does these X** incorrectly, and a decent compiler (gcc) does this anyway. X** --> Before looking for children, see if a widget is a gadget. X** Gadgets can't have children, in fact those fields are X** something else entirely!!! X*/ X#include "Xtos.h" X#define _XtAllocError XtError X X/*************** Begin source from X11R4 lib/Xt/Intrinsics.c ***************/ X Xstatic Widget NameListToWidget(); X Xtypedef Widget (*NameMatchProc)(); X Xstatic Widget MatchExactChildren(names, bindings, children, num, X in_depth, out_depth, found_depth) X XrmNameList names; X XrmBindingList bindings; X WidgetList children; X int num; X int in_depth, *out_depth, *found_depth; X{ X Cardinal i; X XrmName name = *names; X Widget w, result = NULL; X int d, min = 10000; X X for (i = 0; i < num; i++) { X if (name == children[i]->core.xrm_name) { X w = NameListToWidget(children[i], &names[1], &bindings[1], X in_depth+1, &d, found_depth); X if (w != NULL && d < min) {result = w; min = d;} X } X } X *out_depth = min; X return result; X} X Xstatic Widget MatchWildChildren(names, bindings, children, num, X in_depth, out_depth, found_depth) X XrmNameList names; X XrmBindingList bindings; X WidgetList children; X int num; X int in_depth, *out_depth, *found_depth; X{ X Cardinal i; X Widget w, result; X int d, min = 10000; X X for (i = 0; i < num; i++) { X w = NameListToWidget(children[i], names, bindings, X in_depth+1, &d, found_depth); X if (w != NULL && d < min) {result = w; min = d;} X } X *out_depth = min; X return result; X} X Xstatic Widget SearchChildren(root, names, bindings, matchproc, X in_depth, out_depth, found_depth) X Widget root; X XrmNameList names; X XrmBindingList bindings; X NameMatchProc matchproc; X int in_depth, *out_depth, *found_depth; X{ X Widget w1, w2; X int d1, d2; X X#ifdef MOTIF X if (XmIsGadget(root)) { X#else X if (!XtIsWidget(root)) { X#endif X *out_depth = 10000; /* I don't know what this should be */ X return (Widget)NULL; X } X if (XtIsComposite(root)) { X w1 = (*matchproc)(names, bindings, X ((CompositeWidget) root)->composite.children, X ((CompositeWidget) root)->composite.num_children, X in_depth, &d1, found_depth); X } else d1 = 10000; X w2 = (*matchproc)(names, bindings, root->core.popup_list, X root->core.num_popups, in_depth, &d2, found_depth); X *out_depth = (d1 < d2 ? d1 : d2); X return (d1 < d2 ? w1 : w2); X} X Xstatic Widget NameListToWidget(root, names, bindings, X in_depth, out_depth, found_depth) X Widget root; X XrmNameList names; X XrmBindingList bindings; X int in_depth, *out_depth, *found_depth; X{ X Widget w1, w2; X int d1, d2; X X if (in_depth >= *found_depth) { X *out_depth = 10000; X return NULL; X } X X if (names[0] == NULLQUARK) { X *out_depth = *found_depth = in_depth; X return root; X } X X if (*bindings == XrmBindTightly) { X return SearchChildren(root, names, bindings, MatchExactChildren, X in_depth, out_depth, found_depth); X X } else { /* XrmBindLoosely */ X w1 = SearchChildren(root, names, bindings, MatchExactChildren, X in_depth, &d1, found_depth); X w2 = SearchChildren(root, names, bindings, MatchWildChildren, X in_depth, &d2, found_depth); X *out_depth = (d1 < d2 ? d1 : d2); X return (d1 < d2 ? w1 : w2); X } X} /* NameListToWidget */ X XWidget WcChildNameToWidget( ref, name ) /* was XtNameToWidget */ X Widget ref; X char* name; X{ X XrmName *names; X XrmBinding *bindings; X int len, depth, found = 10000; X Widget result; X X len = strlen(name); X if (len == 0) return NULL; X X names = (XrmName *) ALLOCATE_LOCAL((unsigned) (len+1) * sizeof(XrmName)); X bindings = (XrmBinding *) X ALLOCATE_LOCAL((unsigned) (len+1) * sizeof(XrmBinding)); X if (names == NULL || bindings == NULL) _XtAllocError("alloca"); X X XrmStringToBindingQuarkList(name, bindings, names); X if (names[0] == NULLQUARK) { X DEALLOCATE_LOCAL((char *) names); X DEALLOCATE_LOCAL((char *) bindings); X return NULL; X } X X result = NameListToWidget(ref, names, bindings, 0, &depth, &found); X X DEALLOCATE_LOCAL((char *) names); X DEALLOCATE_LOCAL((char *) bindings); X return result; X} /* WcChildNameToWidget */ X X/*************** End of source from X11R4 lib/Xt/Intrinsics.c ***************/ X#endif X X/****************************************************************************** X** Public functions X******************************************************************************/ X X/******************************************************************************* X** Allocate and return a lower case copy of the input string. X** Caller must free output string! X*******************************************************************************/ X Xchar* WcLowerCaseCopy( in ) X char* in; X{ X char* retVal = (char*)XtMalloc( 1 + strlen ( in ) ); X char* cp = retVal; X X while (*in) X { X *cp = (isupper(*in) ? tolower(*in) : *in ); X cp++ ; in++ ; X } X *cp = NUL; X return retVal; X} X X/****************************************************************************** X** Return "clean" widget name, resource, or value from string X******************************************************************************* X This function strips leading and trailing whitespace from the X passed in char*. Note that the caller must allocate and free X the returned character buffer. X******************************************************************************/ X Xchar* WcSkipWhitespace( cp ) X char* cp; X{ X while ( *cp && *cp <= ' ' ) X cp++; X return cp; X} X Xchar* WcSkipWhitespace_Comma( cp ) X char* cp; X{ X while ( *cp && *cp <= ' ' ) /* cp = WcSkipWhitespace ( cp ); */ X cp++; X if ( *cp == ',' ) X cp++; X return cp; X} X Xchar* WcCleanName( in, out ) X char* in; X char* out; X{ X /* copy from in[] into out[], X ** ignore initial whitespace, X ** stop at trailing whitespace or comma. X ** Returns pointer to whitespace or comma following name. X */ X while ( *in && *in <= ' ' ) /* in = WcSkipWhitespace( in ); */ X in++; X for ( ; (*in > ' ' && *in != ',') ; in++ ) X *out++ = *in; X *out = NUL; X return in; /* this points at 1st whitespace or comma following "out" */ X} X X/* This function is necessary because XtNameToWidget cannot really X** take a widget name which begins at the top level shell, but rather X** only names which pretend the widget BELOW the top level shell is X** the top level shell. I have no idea why some thought the X** Xt implementation is correct. Quoting from the Xt manual: X** X** XtNameToWidget returns the descendent [of root] ... according to X** the following rules, ... : X** X** o ... qualifying the name of each object with the names of all X** its ancestors up to _but_not_including_ the reference widget. X** X** Since this is not useful for our purposes, we need to first do some X** screwing around to see if the user specified the widget name like one X** would specify any other widget name in the resource file. X*/ X Xchar* WcStripWhitespaceFromBothEnds( name ) X char* name; X{ X char* first; X char* last; X char* buff; X char* bp; X X for ( first = name ; *first <= ' ' ; first ++ ) X ; X for ( last = first ; *last ; last++ ) X ; X for ( last-- ; *last <= ' ' ; last-- ) X ; X buff = (char*)XtMalloc( (last - first) + 2 ); X for ( bp = buff ; first <= last ; bp++, first++ ) X *bp = *first; X *bp = NUL; X X return buff; X} X XWidget WcFullNameToWidget( w, name ) X Widget w; X char* name; X{ X Widget retWidget; X char *widgetName; /* name stripped of whitespace at both ends */ X char *lowerName; X Widget root; X char *rootName; X char *lowerRootName; X int rootNameLen; X int startsWithRootName; X X widgetName = WcStripWhitespaceFromBothEnds( name ); /* must be XtFree'd */ X lowerName = WcLowerCaseCopy( widgetName ); /* must be XtFree'd */ X X root = WcRootWidget( w ); X rootName = XrmQuarkToString( root->core.xrm_name ); X lowerRootName = WcLowerCaseCopy( rootName ); /* must be XtFree'd */ X rootNameLen = strlen( lowerRootName ); X startsWithRootName = !strncmp( lowerName, lowerRootName, rootNameLen ); X X if ( startsWithRootName && widgetName[rootNameLen] == '*' ) X { X /* the first component of the widget name is the application shell X ** name, and it is followed by a `*' so strip the root name, X ** but keep the star as it implies loose binding. X */ X retWidget = WcChildNameToWidget( root, &(widgetName[rootNameLen]) ); X } X X else if ( startsWithRootName && widgetName[rootNameLen] == '.' ) X { X /* the first component of the widget name is the application shell X ** name, and it is followed by a `.' so strip the root name, X ** and strip the period to imply tight binding. X */ X retWidget = WcChildNameToWidget( root, &(widgetName[++rootNameLen]) ); X } X X else if ( widgetName[0] == '*' ) X { X retWidget = WcChildNameToWidget( root, widgetName ); X } X X else if ( 0 == strcmp( "this", lowerName ) ) X { X retWidget = w; X } X X else X { X#ifdef DEBUG X sprintf( msg, X "WcFullNameToWidget cannot convert `%s' to widget \n\ X Problem: Widget name must start with `*' or `%s' or be `this'", X widgetName, rootName ); X XtWarning( msg ); X#endif X retWidget = (Widget)NULL; X } X X XtFree( widgetName ); X XtFree( lowerName ); X XtFree( lowerRootName ); X return retWidget; X} X X/* X -- Names to Widget List X****************************************************************************** X This routine converts a string of comma separated widget names X (or widget paths) into a list of widget id's. Blank space ignored. X If a NULL string is provided, NULL is put on the list. X X The return value is the list of names which could NOT be X converted. Note that this list is fixed size, and is re-used. X*/ X Xchar* WcNamesToWidgetList ( w, names, widget_list, widget_count ) X Widget w; /* reference widget */ X char* names; /* string of widget names */ X Widget widget_list[]; /* returned widget list */ X Cardinal *widget_count; /* in widget_list[len], out widget count */ X{ X static char ignored[MAX_XRMSTRING]; X char* next = names; X int max = *widget_count; X X/* -- parse the input names "widgetpath [, widgetpath] ..." */ X ignored[0] = NUL; X *widget_count = 0; X X do X { X next = WcCleanName ( next, cleanName ); X X if ( widget_list[*widget_count] = WcFullNameToWidget ( w, cleanName ) ) X (*widget_count)++; X else X { X if (ignored[0] == NUL) X strcpy(ignored, cleanName); X else X { X strcat(ignored, ", "); X strcat(ignored, cleanName); X } X } X next = WcSkipWhitespace_Comma ( next ); X X } while ( *next && *widget_count < max) ; X X return ignored; X} X X/* X -- WidgetToFullName X******************************************************************************* X Traverse up the widget tree, sprintf each name right up to X the root of the widget tree. sprintf the names to buffer. Use X recursion so order of names comes out right. Client MUST free X the char string alloc's and returned by WcWidgetToFullName(). X X Note: If using the Motif widget set, it is likely (almost inavoidable) X that the "widget" may actually be a Gadget. Well, Gadgets don't have X many things, particularly a core.name member. Therefore, if using X Motif we must check to see if the "widget" is not actually an XmGadget. X If is it, then we must use XrmQuarkToString(w->core.xrm_name) rather X than core.name (unfortunately). I'd rather not use the xrm name because X the case has been flattened: everything is lower case. Name something X SomeComplexLongName and you get back somecomplexlongname. The case X is always insignificant, but the mixed case name is easier to read. X*/ X Xstatic char* nextChar; X Xstatic int FullNameLen( w ) X Widget w; X{ X int len; X X#ifdef MOTIF X if (XmIsGadget(w)) X#else X if (XtIsWidget(w) == 0) X#endif X len = 1 + strlen ( XrmQuarkToString(w->core.xrm_name) ); X else X len = 1 + strlen ( w->core.name ); X X if (w->core.parent) X len += FullNameLen(w->core.parent); X return len; X} X Xstatic void WidgetToFullName( w ) X Widget w; X{ X char* cp; X X if (w->core.parent) X { X WidgetToFullName( w->core.parent ); /* nextChar AFTER parent name */ X *nextChar++ = '.'; /* inter-name `dot' */ X } X X#ifdef MOTIF X if (XmIsGadget(w)) X#else X if (XtIsWidget(w) == 0) X#endif X cp = XrmQuarkToString(w->core.xrm_name); X else X cp = w->core.name; X X while (*cp) X *nextChar++ = *cp++; X} X Xchar* WcWidgetToFullName( w ) X Widget w; X{ X char* cp; X char* buff = XtMalloc( FullNameLen( w ) ); X X nextChar = buff; X X WidgetToFullName( w ); X *nextChar = NUL; X X return buff; X} X X/* X -- Convert resource value from string to whatever the widget needs X******************************************************************************* X Gets the XtResourceList from the widget, searches the list for X the resource name to determine the type required, then uses the X resource manager to convert from string to the required type. X Calls XtSetValue with converted type. X*/ X Xvoid WcSetValueFromString( w, res_name, res_val ) X Widget w; /* MUST already be init'd */ X char* res_name; X char* res_val; /* NUL terminated, but may have whitespace */ X{ X XtResource* res_list; X int i, num; X char* ret_val; X char* ta; X XrmValue fr_val; X XrmValue to_val; X Arg arg[1]; X X XtGetResourceList( w->core.widget_class, &res_list, &num ); X X for ( i = 0 ; i < num ; i++ ) X { X if (0 == strcmp( res_name, res_list[i].resource_name)) X break; X else if (0 == strcmp( res_name, res_list[i].resource_class)) X break; X } X if ( i == num ) X { X if (w->core.parent) X sprintf(msg,"%s is not a resource of %s.%s", X res_name, w->core.parent->core.name, w->core.name ); X else X sprintf(msg,"%s is not a resource of %s", X res_name, w->core.name ); X XtWarning(msg); X return; X } X else X { X fr_val.size = strlen(res_val) + 1; X fr_val.addr = (caddr_t)res_val; X to_val.size = 0; X to_val.addr = NULL; X XtConvert( X w, /* the widget */ X XtRString, /* from type */ X &fr_val, /* from value */ X res_list[i].resource_type, /* to type */ X &to_val /* the converted value */ X ); X X if (to_val.addr) X { X /* Conversion worked. */ X switch(to_val.size) X { X case sizeof(char): X XtSetArg( arg[0], res_name, *(char*)to_val.addr ); X break; X case sizeof(short): X XtSetArg( arg[0], res_name, *(short*)to_val.addr ); X break; X case sizeof(int): X XtSetArg( arg[0], res_name, *(int*)to_val.addr ); X break; X default: X sprintf(msg, X "Bizarre Resource Size in SetValueFromString: %d", X to_val.size); X XtWarning(msg); X return; X } X XtSetValues( w, arg, 1 ); X return; X } X else X { X /* conversion failed - assume converter called XtWarning */ X return; X } X } X} X X X/* X******************************************************************************* X* Private Data involving the root widget list X******************************************************************************* X*/ X Xstatic int numRoots = 0; Xstatic Widget rootWidgets[MAX_ROOT_WIDGETS]; X X/* X -- Forget about a root widget X******************************************************************************* X When a root widget gets destroyed, we need to take that widget out X of our list of root widgets. This is a destroy callback routine X which is added to a root widget's destroy callback list by WcRootWidget. X*/ X Xstatic void ForgetRoot ( w, client, call ) X Widget w; X caddr_t client; X caddr_t call; X{ X int i; X for (i = 0 ; i < numRoots ; i++ ) X { X if ( w == rootWidgets[i] ) X { X for ( ; i < numRoots ; i++ ) X { X } X } X } X /* should never get here */ X} X X/* X -- Find root widget X******************************************************************************* X If a widget is passed, then find the root of that widget. See if X it is one of the root widgets we already know about. Add to list X if not. Return the root widget. X X If no widget is passed, then return the first root widget we know X about. If we know of no root widgets, then we will return a NULL X since the rootWidgets[] array starts out filled with nulls, and X gets re-filled as roots are destroyed. X*/ X XWidget WcRootWidget( w ) X Widget w; X{ X int i; X X if (w) X { X while ( XtParent(w) ) X w = XtParent(w); X X for (i = 0 ; i < numRoots ; i++) X { X if ( w == rootWidgets[i] ) X return w; X } X X rootWidgets[i] = w; X numRoots++; X XtAddCallback( w, XtNdestroyCallback, ForgetRoot, NULL ); X return w; X } X else X { X return rootWidgets[0]; X } X} +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 21635 Jul 3 10:24 WcNameFuncs.c (as sent)' chmod u=rw,g=r,o=r WcNameFuncs.c ls -l WcNameFuncs.c echo x - WcRegIntrinsic.c sed 's/^X//' > WcRegIntrinsic.c <<'+FUNKY+STUFF+' X/* X** Copyright (c) 1990 David E. Smyth X** X** Redistribution and use in source and binary forms are permitted X** provided that the above copyright notice and this paragraph are X** duplicated in all such forms and that any documentation, advertising X** materials, and other materials related to such distribution and use X** acknowledge that the software was developed by David E. Smyth. The X** name of David E. Smyth may not be used to endorse or promote products X** derived from this software without specific prior written permission. X** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X** WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X** X*/ X X/* X* SCCS_data: @(#)WcRegIntrinsic.c 1.0 ( 19 June 1990 ) X* X* Subsystem_group: X* X* Widget Creation Library - Intrinsic Resource Interpreter X* X* Module_description: X* X* This module contains registration routine for all Intrinsic X* widget constructors and classes. X* X* Module_interface_summary: X* X* void WcRegisterIntrinsic ( XtAppContext app ) X* X* Module_history: X* X* mm/dd/yy initials function action X* -------- -------- -------- --------------------------------------------- X* 06/19/90 D.Smyth all create. X* X* Design_notes: X* X******************************************************************************* X*/ X/* X******************************************************************************* X* Include_files. X******************************************************************************* X*/ X X#include <X11/Intrinsic.h> X X#include <X11/Object.h> X#include <X11/RectObj.h> X#include <X11/Shell.h> X#include <X11/Vendor.h> X X/* -- Widget constructor routines */ X XWidget WcCreateApplicationShell (); XWidget WcCreateOverrideShell (); XWidget WcCreateShell (); XWidget WcCreateTopLevelShell (); XWidget WcCreateTransientShell (); XWidget WcCreateVendorShell (); XWidget WcCreateWMShell (); X X Xvoid WcRegisterIntrinsic ( app ) X XtAppContext app; X{ X X#define RCN( name, class ) WcRegisterClassName ( app, name, class ); X#define RCP( name, class ) WcRegisterClassPtr ( app, name, class ); X#define RCR( name, func ) WcRegisterConstructor(app, name, func ); X X /* -- register all Intrinsic widget classes */ X X RCN("Object", objectClass ); X RCP("objectClass", objectClass ); X RCN("RectObj", rectObjClass ); X RCP("rectObjClass", rectObjClass ); X RCN("Core", coreWidgetClass ); X RCP("coreWidgetClass", coreWidgetClass ); X RCN("Composite", compositeWidgetClass ); X RCP("compositeWidgetClass", compositeWidgetClass ); X RCN("Constraint", constraintWidgetClass ); X RCP("constraintWidgetClass", constraintWidgetClass ); X RCN("ApplicationShell", applicationShellWidgetClass ); X RCP("applicationShellWidgetClass", applicationShellWidgetClass ); X RCN("OverrideShell", overrideShellWidgetClass ); X RCP("overrideShellWidgetClass", overrideShellWidgetClass ); X RCN("Shell", shellWidgetClass ); X RCP("shellWidgetClass", shellWidgetClass ); X RCN("TopLevelShell", topLevelShellWidgetClass ); X RCP("topLevelShellWidgetClass", topLevelShellWidgetClass ); X RCN("TransientShell", transientShellWidgetClass ); X RCP("transientShellWidgetClass", transientShellWidgetClass ); X RCN("VendorShell", vendorShellWidgetClass ); X RCP("vendorShellWidgetClass", vendorShellWidgetClass ); X RCN("WmShell", wmShellWidgetClass ); X RCP("wmShellWidgetClass", wmShellWidgetClass ); X X /* -- register all Intrinsic constructors */ X X RCR("XtCreateApplicationShell", WcCreateApplicationShell); X RCR("XtCreateOverrideShell", WcCreateOverrideShell); X RCR("XtCreateShell", WcCreateShell); X RCR("XtCreateTopLevelShell", WcCreateTopLevelShell); X RCR("XtCreateTransientShell", WcCreateTransientShell); X RCR("XtCreateWMShell", WcCreateWMShell); X RCR("XtCreateVendorShell", WcCreateVendorShell); X X#undef RCN X#undef RCP X#undef RCR X} X X/* X -- Create Application Shell X******************************************************************************* X This function creates an application shell widget. X X*/ XWidget WcCreateApplicationShell ( pw, name, args, nargs ) XWidget pw; /* children's parent */ XString name; /* widget name to create */ XArg *args; /* args for widget */ XCardinal nargs; /* args count */ X{ X X XtCreatePopupShell(name, applicationShellWidgetClass, pw, args, nargs); X return; X} X X/* X -- Create Override Shell X******************************************************************************* X This function creates an override shell widget. X X*/ XWidget WcCreateOverrideShell ( pw, name, args, nargs ) XWidget pw; /* children's parent */ XString name; /* widget name to create */ XArg *args; /* args for widget */ XCardinal nargs; /* args count */ X{ X X return(XtCreatePopupShell(name, overrideShellWidgetClass, pw, args, nargs)); X} X X/* X -- Create Shell X******************************************************************************* X This function creates a shell widget. X X*/ XWidget WcCreateShell ( pw, name, args, nargs ) XWidget pw; /* children's parent */ XString name; /* widget name to create */ XArg *args; /* args for widget */ XCardinal nargs; /* args count */ X{ X X return(XtCreatePopupShell(name, shellWidgetClass, pw, args, nargs)); X} X X/* X -- Create TopLevel Shell X******************************************************************************* X This function creates a top level shell widget. X X*/ XWidget WcCreateTopLevelShell ( pw, name, args, nargs ) XWidget pw; /* children's parent */ XString name; /* widget name to create */ XArg *args; /* args for widget */ XCardinal nargs; /* args count */ X{ X X return(XtCreatePopupShell(name, topLevelShellWidgetClass, pw, args, nargs)); X} X X/* X -- Create Transient Shell X******************************************************************************* X This function creates an transient shell widget. X X*/ XWidget WcCreateTransientShell ( pw, name, args, nargs ) XWidget pw; /* children's parent */ XString name; /* widget name to create */ XArg *args; /* args for widget */ XCardinal nargs; /* args count */ X{ X X return(XtCreatePopupShell(name, transientShellWidgetClass, pw, args, nargs)); X} X X/* X -- Create Vendor Shell X******************************************************************************* X This function creates a vendor shell widget. X X*/ XWidget WcCreateVendorShell ( pw, name, args, nargs ) XWidget pw; /* children's parent */ XString name; /* widget name to create */ XArg *args; /* args for widget */ XCardinal nargs; /* args count */ X{ X X return(XtCreatePopupShell(name, vendorShellWidgetClass, pw, args, nargs)); X} X X/* X -- Create WM Shell X******************************************************************************* X This function creates an WM shell widget. X X*/ XWidget WcCreateWMShell ( pw, name, args, nargs ) XWidget pw; /* children's parent */ XString name; /* widget name to create */ XArg *args; /* args for widget */ XCardinal nargs; /* args count */ X{ X X return(XtCreatePopupShell(name, wmShellWidgetClass, pw, args, nargs)); X} X +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 7396 Jul 2 12:22 WcRegIntrinsic.c (as sent)' chmod u=rw,g=r,o=r WcRegIntrinsic.c ls -l WcRegIntrinsic.c echo x - WcRegister.c sed 's/^X//' > WcRegister.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: @(#)WcRegister.c 1.0 ( 19 June 1990 ) X* X* Subsystem_group: X* X* Widget Creation Library X* X* Module_description: X* X* Since (for portability reasons) we can not assume runtime binding, X* all widget classes, creation routines (constructors), and callbacks X* must be "registered" by the application BEFORE widget tree creation. X* X* All four of the functions defined in this module load dynamically X* allocated and extended arrays of structures. The size increment X* of the arrays starts at a reasonably small size (INCR_REGISTRY, X* initially 32), and is doubled in size everytime a given registry is X* filled. This allows registries to be small, yet to not have to be X* realloc'd frequently when they grow large. X* X* The registries are arrays of structs. In all four cases, the X* structs are very similar: they contain a name string which holds the X* class, constructor, or callback name as it was registered; a quark X* which is based on an all lower case representation of the name, and X* class, constructor, or callback specific information. The name X* as registered should be as shown in reference documents and source X* code, as it is used for user error messages. X* X* The registries are intended to be used by string-to-whatever converters. X* X* All four registration functions currently check for duplicate X* entries, but do no fancy hashing scheme, nor any ties to the X* application context. Assumming a relatively small number of X* entries in these regestries, it is assumed that a sequential X* search using quarks will be adequate and simple. X X* Module_interface_summary: X* X* WcRegisterClassPtr( X* XtAppContext app, - application context X* String name, - class ptr name, as in ref manuals X* WidgetClass class ) - class record pointer X* X* WcRegisterClassName( X* XtAppContext app, - application context X* String name, - class name, as in ref manuals X* WidgetClass class ) - class record pointer X* X* WcRegisterConstructor( X* XtAppContext app, - application context X* String name, - constructor name, as in ref manuals X* (*Widget)() const ) - constructor function pointer X* X* WcRegisterCallback( X* XtAppContext app, - application context X* String name, - callback name, "nice" capitalization X* void (*func)() ) - pointer to callback function X* X* Module_history: X X* mm/dd/yy initials function action X* -------- -------- -------- --------------------------------------------- X* 19Jun90 D.Smyth Version 1.0 Widget Creation Library X* 06/08/90 D.Smyth All Added "name" member for better user msgs. X* 02/26/90 MarBru All Created X* 02/16/90 MarBru Create.. Limited creation to composite widgets/objects X* X* Design_notes: X* X* For VMS, we could have used LIB$FIND_IMAGE_SYMBOL and use dynamic X* (runtime) binding. But since most UNIX systems lack such capability, X* we stick to the concept of "registration" routines. X* X******************************************************************************* X*/ X/* X******************************************************************************* X* Include_files. X******************************************************************************* X*/ X X/* -- Widget Creation Includes */ X#include "WidgetCreate.h" X#include "WidgetCreateP.h" X X/* X******************************************************************************* X* Private_data_definitions. X******************************************************************************* X The following cache/registry of known widget classes, contructors, X and callbacks are initially empty, and are loaded by the application X using "registration" routines. X*/ X Xstatic char msg[MAX_ERRMSG]; X X/* -- Named class pointer cache, intially empty */ X Xint classes_num = 0; Xint classes_max = 0; XClCacheRec *classes_ptr = NULL; X X/* -- Class name cache, intially empty */ X Xint cl_nm_num = 0; Xint cl_nm_max = 0; XClNameCacheRec* cl_nm_ptr = NULL; X X/* -- Named object constructor cache, intially empty */ X Xint constrs_num = 0; Xint constrs_max = 0; XConCacheRec *constrs_ptr = NULL; X X/* -- Named callback procedures cache, intially empty */ X Xint callbacks_num = 0; Xint callbacks_max = 0; XCBCacheRec *callbacks_ptr = NULL; X X/* X******************************************************************************* X* Private_function_declarations. X******************************************************************************* X*/ X X/* X******************************************************************************* X* Public_function_declarations. X******************************************************************************* X*/ X X/* X -- Register Class Pointer Name X******************************************************************************* X This procedure adds class pointer name to our list of registered X classes. Note that the class ptr name is effectively case insensitive X as it is being quarkified. However, one should register the class ptr X names using the "standard" capitalization (whatever is in the reference X manual for the widget set) as the name as registered is used for error X messages. X X The registry is primarily used by CvtStringToClassPtr(). X*/ X Xvoid WcRegisterClassPtr ( app, name, class ) X XtAppContext app; /* not used (yet), must be present */ X char* name; /* class ptr name, case insensitive */ X WidgetClass class; /* Xt object class pointer */ X{ X char *lowerCaseName; X XrmQuark quark; X ClCacheRec *rec; X int i; X X /* Might need to grow cache. Note that growth increment is exponential: X ** if lots of classes, don't need to keep realloc'ing so often. X */ X if (classes_num >= classes_max ) X { X classes_max += (classes_max ? classes_max : INCR_REGISTRY); X classes_ptr = (ClCacheRec*) XtRealloc((char*)classes_ptr, X sizeof(ClCacheRec) * classes_max); X } X X /* See if this object has been registered. Compare quarks. X */ X lowerCaseName = WcLowerCaseCopy( name ); X quark = XrmStringToQuark ( lowerCaseName ); X XtFree ( lowerCaseName ); X X for (i = 0 ; i < classes_num ; i++ ) X { X if (classes_ptr[i].quark == quark) X { X /* already registered this class */ X sprintf(msg, X "WcRegisterClassPtr (%s) - Failed \n\ X Problem: Duplicate class registration ignored.", X name ); X XtWarning( msg ); X return; X } X } X X rec = &classes_ptr[classes_num++]; /* ClCacheRec to be filled */ X rec->quark = quark; X rec->class = class; X rec->name = XtMalloc( strlen(name) + 1 ); X strcpy ( rec->name, name ); X} X X/* X -- Register Class Name X******************************************************************************* X This procedure adds a class name to our list of registered X classes. Note that the class name is effectively case insensitive X as it is being quarkified. However, one should register the class X names using the "standard" capitalization (whatever is in the reference X manual for the widget set) as the name as registered is used for error X messages. X X The registry is primarily used by CvtStringToClassName(). X*/ X Xvoid WcRegisterClassName ( app, name, class ) X XtAppContext app; /* not used (yet), must be present */ X char* name; /* class name, case insensitive */ X WidgetClass class; /* Xt object class pointer */ X{ X char *lowerCaseName; X XrmQuark quark; X ClNameCacheRec *rec; X int i; X X /* Might need to grow cache. Note that growth increment is exponential: X ** if lots of classes, don't need to keep realloc'ing so often. X */ X if (cl_nm_num >= cl_nm_max ) X { X cl_nm_max += (cl_nm_max ? cl_nm_max : INCR_REGISTRY); X cl_nm_ptr = (ClNameCacheRec*) XtRealloc((char*)cl_nm_ptr, X sizeof(ClNameCacheRec) * cl_nm_max); X } X X /* See if this object has been registered. Compare quarks. X */ X lowerCaseName = WcLowerCaseCopy( name ); X quark = XrmStringToQuark ( lowerCaseName ); X XtFree ( lowerCaseName ); X X for (i = 0 ; i < cl_nm_num ; i++ ) X { X if (cl_nm_ptr[i].quark == quark) X { X /* already registered this class */ X sprintf(msg, X "WcRegisterClassName (%s) - Failed \n\ X Problem: Duplicate class registration ignored.", X name ); X XtWarning( msg ); X return; X } X } X X rec = &cl_nm_ptr[cl_nm_num++]; /* ClNameCacheRec to be filled */ X rec->quark = quark; X rec->class = class; X rec->name = XtMalloc( strlen(name) + 1 ); X strcpy ( rec->name, name ); X} X X/* X -- Register constructor X******************************************************************************* X This procedure adds constructor procedure/name to our list of registered X constructors. Note that the name is effectively case insensitive X as it is being quarkified. However, one should register the X names using the "standard" capitalization (whatever is in the reference X manual for the widget set) as the name as registered is used for error X messages. X X Note the constructor is a "Motif Style" widget creation routine, X commonly called a "confusion function." X X The registry is primarily used by CvtStringToConstructor(). X*/ X Xvoid WcRegisterConstructor ( app, name, constructor ) X XtAppContext app; /* not used (yet), must be present */ X char* name; /* constructor name, case insensitive */ X Widget (*constructor) (); /* pointer to a widget creation routine */ X{ X char *lowerCaseName; X XrmQuark quark; X ConCacheRec *rec; X int i; X X /* Might need to grow cache. Note that growth increment is exponential: X ** if lots of constructors, don't need to keep realloc'ing so often. X */ X if (constrs_num >= constrs_max ) X { X constrs_max += (constrs_max ? constrs_max : INCR_REGISTRY); X constrs_ptr = (ConCacheRec*) XtRealloc((char*)constrs_ptr, X sizeof(ConCacheRec) * constrs_max); X } X X /* See if this object has been registered. Compare quarks. X */ X lowerCaseName = WcLowerCaseCopy( name ); X quark = XrmStringToQuark ( lowerCaseName ); X XtFree ( lowerCaseName ); X X for (i = 0 ; i < constrs_num ; i++ ) X { X if (constrs_ptr[i].quark == quark) X { X /* already registered this class */ X sprintf(msg, X "WcRegisterConstructor (%s) - Failed \n\ X Problem: Duplicate constructor registration ignored.", X name ); X XtWarning( msg ); X return; X } X } X X rec = &constrs_ptr[constrs_num++]; /* ClCacheRec to be filled */ X rec->quark = quark; X rec->constructor = constructor; X rec->name = XtMalloc( strlen(name) + 1 ); X strcpy ( rec->name, name ); X} X X/* X -- Register Callbacks X******************************************************************************* X Register callback functions which can then be bound to widget X callback lists by the string-to-callback converter X CvtStringToCallback(). X*/ X Xvoid WcRegisterCallback ( app, name, callback, closure ) X XtAppContext app; /* not used (yet), must be present */ X String name; /* callback name, case insensitive */ X XtCallbackProc callback; /* callback function pointer */ X caddr_t closure; /* default client data */ X{ X char *lowerCaseName; X XrmQuark quark; X CBCacheRec *rec; X int i; X X /* Might need to grow cache. Note that growth increment is exponential: X ** if lots of constructors, don't need to keep realloc'ing so often. X */ X if (callbacks_num >= callbacks_max ) X { X callbacks_max += (callbacks_max ? callbacks_max : INCR_REGISTRY); X callbacks_ptr = (CBCacheRec*) XtRealloc((char*)callbacks_ptr, X sizeof(CBCacheRec) * callbacks_max); X } X X /* See if this callback has been registered. Compare quarks. X */ X lowerCaseName = WcLowerCaseCopy( name ); X quark = XrmStringToQuark ( lowerCaseName ); X XtFree ( lowerCaseName ); X X for (i = 0 ; i < callbacks_num ; i++ ) X { X if (callbacks_ptr[i].quark == quark) X { X /* already registered this callback */ X sprintf(msg, X "WcRegisterCallback (%s) - Failed \n\ X Problem: Duplicate callback registration ignored.", X name ); X XtWarning( msg ); X return; X } X } X X rec = &callbacks_ptr[callbacks_num++]; /* ClCacheRec to be filled */ X rec->quark = quark; X rec->callback = callback; X rec->closure = closure; X rec->name = XtMalloc( strlen(name) + 1 ); X strcpy ( rec->name, name ); X} +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 15306 Jun 28 09:13 WcRegister.c (as sent)' chmod u=rw,g=r,o=r WcRegister.c ls -l WcRegister.c exit 0 dan ---------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com Opinions expressed reflect those of the author only.