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 59 Archive-name: wcl/part11 # to unbundle, "sh" this file -- DO NOT use csh # SHAR archive format. Archive created Fri Oct 19 09:33:30 PDT 1990 echo x - WcCreateP.h sed 's/^X//' > WcCreateP.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: @(#)WcCreateP.h 1.03 ( 13 July 1990 ) X* X* Include_name: X* X* WcCreateP.h X* X* Subsystem_group: X* X* Widget Creation Library X* X* Include_description: X* X* Private 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* 06/30/90 R.Whitby added Action declarations X* 05/24/90 D.Smyth created from provate section of WsCreate.h X* 03/02/90 marbru created X* X******************************************************************************* X*/ X#ifndef _WcCreateP_h X#define _WcCreateP_h X X/* X******************************************************************************* X* Private_constant_declarations. X******************************************************************************* X*/ X#undef NUL X#define NUL '\0' X#define MAX_XRMSTRING 4096 /* max length of the Xrm DB string */ X#define MAX_ERRMSG 1024 /* max length of error message */ X#define MAX_CHILDREN 1024 /* max number of widget's children */ X#define MAX_PATHNAME 1024 /* max length of the pathname */ X#define INCR_REGISTRY 32 /* incr of cl, con, cb registries */ X#define MAX_CALLBACKS 64 /* max callbacks per Xrm resource */ X#define MAX_WIDGETS 512 /* max depth of a widget tree */ X#define MAX_ROOT_WIDGETS 32 /* max # separate widget trees */ X#define MAX_RES_FILES 512 /* max # res file names per interf */ X X#define WcNwcResFile "wcResFile" X#define WcNwcChildren "wcChildren" X#define WcNwcClass "wcClass" X#define WcNwcClassName "wcClassName" X#define WcNwcConstructor "wcConstructor" X#define WcNwcManaged "wcManaged" X#define WcNwcTrace "wcTrace" X#define WcNwcCallback "wcCallback" X X#define WcCWcResFile "WcResFile" X#define WcCWcChildren "WcChildren" X#define WcCWcClass "WcClass" X#define WcCWcClassName "WcClassName" X#define WcCWcConstructor "WcConstructor" X#define WcCWcManaged "WcManaged" X#define WcCWcTrace "WcTrace" X#define WcCWcCallback "WcCallback" X X/* Motif 1.0 has a bug: widgets ask for Windows X** instead of Widgets for their resources... X*/ X#define WcRWidget "Window" X#define WcRClassPtr "ClassPtr" X#define WcRClassName "ClassName" X#define WcRConstructor "Constructor" X/* X******************************************************************************* X* Private_type_declarations. X******************************************************************************* X*/ X Xtypedef Widget (*PtrFuncWidget)(); /* ptr to func returning Widget */ X X/* Registration structs: It is a good idea if the classes, class names, X** constructors, and callbacks are registered with the same upper & lower X** case names as the names in the ref manuals and source files, as this X** makes the user error messages clearer. X*/ X Xtypedef struct /* Class cache record */ X{ X String name; /* class ptr name as registered */ X XrmQuark quark; /* quarkified class ptr name */ X WidgetClass class; /* widget class pointer */ X} ClCacheRec; X Xtypedef struct /* Class Name cache record */ X{ X String name; /* class name as registered */ X XrmQuark quark; /* quarkified class name */ X WidgetClass class; /* widget class pointer */ X} ClNameCacheRec; X Xtypedef struct /* Constructor cache record */ X{ X String name; /* constructor as registered */ X XrmQuark quark; /* quarkified constructor name */ X Widget (*constructor)(); /* constructor function ptr */ X} ConCacheRec; X Xtypedef struct /* Callback cache record */ X{ X String name; /* name as registered */ X XrmQuark quark; /* quarkified callback name */ X XtCallbackProc callback; /* callback procedure pointer */ X caddr_t closure; /* default client data */ X} CBCacheRec; X Xtypedef struct _ResourceRec X{ X String resFile; /* additional resource file name */ X String children; /* list of children names to create */ X WidgetClass class; /* widget class pointer */ X WidgetClass classFromName; /* widget class pointer */ X ConCacheRec* constructor; /* ptr to Constructo cache record */ X Boolean managed; /* created managed (default TRUE) */ X Boolean deferred; /* deferred creation, (def FALSE) */ X Boolean trace; /* creation trace required */ X XtCallbackList callback; /* creation callback list */ X} ResourceRec, *ResourceRecPtr; X X/* X******************************************************************************* X* Private_macro_definitions. X******************************************************************************* X*/ X X#define ONCE_PER_XtAppContext( app ) \ X{ \ X static XtAppContext already[1024]; \ X static int apps = 0; \ X int i; \ X \ X for (i = 0; i < apps ; i++) \ X if (already[i]) \ X return; \ X \ X already[++apps] = app; \ X} X X/* X******************************************************************************* X* Private_data_definitions. X******************************************************************************* X The following cache/registry of known widget classes and contructors, X initially empty, are loaded by the application using "registration" X routines. X Assuming small numbers of constructors, the sequential search X of such cache is (initially) considered acceptable. X*/ X X/* -- Named class pointer cache, intially empty */ X Xextern int classes_num; Xextern int classes_max; Xextern ClCacheRec* classes_ptr; X X/* -- Class name cache, intially empty */ X Xextern int cl_nm_num; Xextern int cl_nm_max; Xextern ClNameCacheRec* cl_nm_ptr; X X/* -- Named object constructor cache, intially empty */ X Xextern int constrs_num; Xextern int constrs_max; Xextern ConCacheRec* constrs_ptr; X X/* -- Callback function cache, initially empty */ X Xextern int callbacks_num; Xextern int callbacks_max; Xextern CBCacheRec* callbacks_ptr; X/* -- Widget Creation resources */ X Xextern XtResource wc_resources[]; X X/* X******************************************************************************* X* Private_function_declarations. X******************************************************************************* X The following functions are generally private functions to the X WcCreate routines, but they may be defined in different files from X where they are used. Client programs probably should not invoke X these functions directly. X*/ X X#ifdef FUNCTION_PROTOTYPES X/****************************** ANSI FUNC DECLS ******************************/ X X#define EV extern void X X/* -- Resource converters */ X XEV WcAddConverters ( XtAppContext ); XEV CvtStringToClassPtr ( XrmValue*, Cardinal*, XrmValue*, XrmValue* ); XEV CvtStringToClassName ( XrmValue*, Cardinal*, XrmValue*, XrmValue* ); XEV CvtStringToConstructor ( XrmValue*, Cardinal*, XrmValue*, XrmValue* ); XEV CvtStringToCallback ( XrmValue*, Cardinal*, XrmValue*, XrmValue* ); XEV CvtStringToWidget ( XrmValue*, Cardinal*, XrmValue*, XrmValue* ); X X/* -- Find root widget of argument, remember if never seen before */ X Xextern Widget WcRootWidget ( Widget ); X X/* -- Convenience Callbacks - Clients generally invoke these only X by binding them to widgets via the resource file. They can X be programmatically bound, but generally should not be. X*/ X XEV WcCreateChildrenCB (Widget w, char* parent_children, caddr_t unused ); XEV WcManageCB (Widget w, char* widgetNames, caddr_t unused ); XEV WcUnmanageCB (Widget w, char* widgetNames, caddr_t unused ); XEV WcManageChildrenCB (Widget w, char* parent_children, caddr_t unused ); XEV WcUnmanageChildrenCB (Widget w, char* parent_children, caddr_t unused ); XEV WcDestroyCB (Widget w, char* widgetNames, caddr_t unused ); XEV WcSetValueCB (Widget w, char* name_res_resVal, caddr_t unused ); XEV WcSetSensitiveCB (Widget w, char* widgetNames, caddr_t unused ); XEV WcSetInsensitiveCB (Widget w, char* widgetNames, caddr_t unused ); XEV WcLoadResourceFileCB (Widget w, char* resFileName, caddr_t unused ); XEV WcTraceCB (Widget w, char* annotation, caddr_t unused ); XEV WcPopupCB (Widget w, char* widgetName, caddr_t unused ); XEV WcPopupGrabCB (Widget w, char* widgetName, caddr_t unused ); XEV WcPopdownCB (Widget w, char* widgetName, caddr_t unused ); XEV WcMapCB (Widget w, char* widgetName, caddr_t unused ); XEV WcUnmapCB (Widget w, char* widgetName, caddr_t unused ); XEV WcSystemCB (Widget w, char* shellCmdString, caddr_t unused ); XEV WcExitCB (Widget w, char* exitValue, caddr_t unused ); X X/* -- Convenience Actions - Clients generally invoke these only X by binding them to widgets via the resource file. They can X be programmatically bound, but generally should not be. X*/ X X#define ACT_ARGS Widget w, XEvent *event, String *params, Cardinal *num_params X XEV WcCreateChildrenACT ( ACT_ARGS ); XEV WcManageACT ( ACT_ARGS ); XEV WcUnmanageACT ( ACT_ARGS ); XEV WcManageChildrenACT ( ACT_ARGS ); XEV WcUnmanageChildrenACT ( ACT_ARGS ); XEV WcDestroyACT ( ACT_ARGS ); XEV WcSetValueACT ( ACT_ARGS ); XEV WcSetSensitiveACT ( ACT_ARGS ); XEV WcSetInsensitiveACT ( ACT_ARGS ); XEV WcLoadResourceFileACT ( ACT_ARGS ); XEV WcTraceACT ( ACT_ARGS ); XEV WcPopupACT ( ACT_ARGS ); XEV WcPopupGrabACT ( ACT_ARGS ); XEV WcPopdownACT ( ACT_ARGS ); XEV WcMapACT ( ACT_ARGS ); XEV WcUnmapACT ( ACT_ARGS ); XEV WcSystemACT ( ACT_ARGS ); XEV WcExitACT ( ACT_ARGS ); X X#undef ACT_ARGS X#undef EV X X#else X/**************************** NON-ANSI FUNC DECLS ****************************/ X X/* -- Resource converters */ X Xextern void WcAddConverters (); Xextern void CvtStringToClassPtr (); Xextern void CvtStringToClassName (); Xextern void CvtStringToConstructor (); Xextern void CvtStringToCallback (); Xextern void CvtStringToWidget (); X X/* -- Find root widget of argument, remember if never seen before */ X Xextern Widget WcRootWidget (); X X/* -- Convenience Callbacks - Clients generally invoke these only X by binding them to widgets via the resource file. They can X be programmatically bound, but generally should not be. X*/ X Xextern void WcCreateChildrenCB (); Xextern void WcManageCB (); Xextern void WcUnmanageCB (); Xextern void WcManageChildrenCB (); Xextern void WcUnmanageChildrenCB (); Xextern void WcDestroyCB (); Xextern void WcSetValueCB (); Xextern void WcSetSensitiveCB (); Xextern void WcSetInsensitiveCB (); Xextern void WcLoadResourceFileCB (); Xextern void WcTraceCB (); Xextern void WcPopupCB (); Xextern void WcPopupGrabCB (); Xextern void WcPopdownCB (); Xextern void WcMapCB (); Xextern void WcUnmapCB (); Xextern void WcSystemCB (); Xextern void WcExitCB (); X X/* -- Convenience Actions - Clients generally invoke these only X by binding them to widgets via the resource file. They can X be programmatically bound, but generally should not be. X*/ X Xextern void WcCreateChildrenACT (); Xextern void WcManageACT (); Xextern void WcUnmanageACT (); Xextern void WcManageChildrenACT (); Xextern void WcUnmanageChildrenACT (); Xextern void WcDestroyACT (); Xextern void WcSetValueACT (); Xextern void WcSetSensitiveACT (); Xextern void WcSetInsensitiveACT (); Xextern void WcLoadResourceFileACT (); Xextern void WcTraceACT (); Xextern void WcPopupACT (); Xextern void WcPopupGrabACT (); Xextern void WcPopdownACT (); Xextern void WcMapACT (); Xextern void WcUnmapACT (); Xextern void WcSystemACT (); Xextern void WcExitACT (); X X#endif /* FUNCTION_PROTOTYPES */ X X#ifdef DEBUG X#ifdef MOTIF X#include "WcMotifP.h" X#else X#include "WcAthenaP.h" X#endif X#endif X X#endif /* _WcCreateP_h */ +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 14725 Oct 16 14:38 WcCreateP.h (as sent)' chmod u=rw,g=r,o=r WcCreateP.h ls -l WcCreateP.h 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 <X11/ShellP.h> X#include <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 2048 Aug 6 09:36 WcMotifP.h (as sent)' chmod u=rw,g=r,o=r WcMotifP.h ls -l WcMotifP.h echo x - WcName.c sed 's/^X//' > WcName.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: @(#)WcName.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** The widget names understood by WcFullNameToWidget() are X** a superset of those understood by XtNameToWidget in X** the X11R4 version of libXt. XtNameToWidget only knows X** how to find children of a reference widget, and so the X** names start _below- the refernce widget. However, X** WcFullNameToWidget knows how to find widgets anywhere X** in the widget tree: it normally starts the name search X** from the root of the widget tree, but it can also X** perform the name search relatively from the reference X** widget, both up and down the widget tree. X** X** When name searches start at the root of the widget X** tree, the same syntax as that understood by Xrm is X** used. Below are four examples of acceptable names: X** X** *foo *foo.XmRowColumn*glorp X** Mri.some*other.foo *Form.glorp X** X** Note that components may be class names, such as X** XmRowColumn, or may be instance names of the widgets. X** Ambiguous names are resolved exactly as done by X** XtNameToWidget: shallowest wins, `.' binds tighter X** than `*', instance names bind tighter than class X** names. X** X** In addition to resolving names from the root of the X** widget tree, WcFullNameToWidget also can find widget X** using a relative root prefix. Three special characters X** are used: X** X** ^ means "parent" X** ~ means the closest shell ancestor X** . means start at the reference widget X** X** The relative root prefix characters are exactly that: X** a prefix of a name which will then be passed to X** XtNameToWidget. Some examples: X** X** .foo a child of the reference widget X** ^foo a sibling of the reference widget X** ^^foo a sibling of the ref' widgets's parent X** ~foo a child of the shell ancestor. X** ~~*foo some child of the shell's shell ancestor. X** X** The ^ and ~ prefix characters are only valid at the X** beginning. They effectively operate on the reference X** widget. X** X** In all cases, the characters are scanned left to right. X** So, the first character is acted upon, then the second, X** and so on. X** X** Notes: Most of the "private" part of this file goes away when X** the bug in the Xt Intrinsics is fixed which causes X** XtNameToWidget() to dump core whenever a Gadget exists X** in the widget heirarchy... X** X******************************************************************************/ X X/****************************************************************************** X* Include_files. X******************************************************************************/ X X#include <ctype.h> /* isupper() and tolower macros */ X X/* -- X Window System includes */ X#include <X11/StringDefs.h> X X#ifdef MOTIF X#include <Xm/XmP.h> X#endif X X/* -- Widget Creation Library includes */ X#include "WcCreate.h" X#include "WcCreateP.h" X X/* X******************************************************************************* X* Private_data_definitions. X******************************************************************************* X*/ X X/* shared error message and name buffers X******************************************************************************* X** NOTE: These are shared arrays because they are large: i.e., X** this is a performacne optimization intended to reduce page X** faults which can occur while making large extensions to the X** stack space. Wait a minute: wouldn't this just happen X** once, and then the stack space is alloc'd? Yes, but a X** huge stack space runs the risk of getting swapped, which causes X** page faults. This is probably a nit-picky sort of optimization. X** Remember that D.Smyth is an old sys programmer from the stone X** ages, and pity him instead of flaming him. X** Be careful when filling msg not to call any funcs in here, X** so the message does not get garbled. X*/ X Xstatic char msg[MAX_ERRMSG]; Xstatic char cleanName[MAX_PATHNAME]; X X/* Private Data involving the root widget list X******************************************************************************* X*/ X Xstatic int numRoots = 0; Xstatic Widget rootWidgets[MAX_ROOT_WIDGETS]; X X/* X******************************************************************************* X* Private_function definitions. X******************************************************************************* X/* X The following is the XtGetConstraintResourceList function from X the R4 Intrinsics. This function is not provided by the Motif X 1.0 Intrinsics. Only change: ConstraintClassFlag was changed to X _XtConstraintBit. X*/ X X#if defined(MOTIF) && defined(MOTIF_MINOR) && MOTIF == 1 && MOTIF_MINOR == 0 X#include <X11/IntrinsicP.h> X/*************** Begin source from X11R4 GetResList.c ***************/ X Xstatic Boolean ClassIsSubclassOf(class, superclass) X WidgetClass class, superclass; X{ X for (; class != NULL; class = class->core_class.superclass) { X if (class == superclass) return True; X } X return False; X} X Xvoid XtGetConstraintResourceList(widget_class, resources, num_resources) X WidgetClass widget_class; X XtResourceList *resources; X Cardinal *num_resources; X{ X int size; X register int i, dest = 0; X register XtResourceList *list, dlist; X ConstraintWidgetClass class = (ConstraintWidgetClass)widget_class; X X if ( (class->core_class.class_inited && X !(class->core_class.class_inited & _XtConstraintBit)) /* DES */ X || (!class->core_class.class_inited && X !ClassIsSubclassOf(widget_class, constraintWidgetClass)) X || class->constraint_class.num_resources == 0) { X X *resources = NULL; X *num_resources = 0; X return; X } X X size = class->constraint_class.num_resources * sizeof(XtResource); X *resources = (XtResourceList) XtMalloc((unsigned) size); X X if (!class->core_class.class_inited) { X /* Easy case */ X X bcopy((char *)class->constraint_class.resources, X (char *) *resources, size); X *num_resources = class->constraint_class.num_resources; X return; X } X X /* Nope, it's the hard case */ X X list = (XtResourceList *) class->constraint_class.resources; X dlist = *resources; X for (i = 0; i < class->constraint_class.num_resources; i++) { X if (list[i] != NULL) { X dlist[dest].resource_name = (String) X XrmQuarkToString((XrmQuark) list[i]->resource_name); X dlist[dest].resource_class = (String) X XrmQuarkToString((XrmQuark) list[i]->resource_class); X dlist[dest].resource_type = (String) X XrmQuarkToString((XrmQuark) list[i]->resource_type); X dlist[dest].resource_size = list[i]->resource_size; X dlist[dest].resource_offset = -(list[i]->resource_offset + 1); X dlist[dest].default_type = (String) X XrmQuarkToString((XrmQuark) list[i]->default_type); X dlist[dest].default_addr = list[i]->default_addr; X dest++; X } X } X *num_resources = dest; X} X X/*************** End source from X11R4 GetResList.c ***************/ X#endif /* MOTIF 1.0 */ X X/* X The following implements XtNameToWidget() in a way which really works. X X Note: the #if defined... assumes a FIXED version of R4. The version X even as of 19 June 1990 still is not correct (dumps core on Gadgets). X*/ X X#if defined(XtSpecificationRelease) && XtSpecificationRelease > 4 X XWidget WcChildNameToWidget( Widget ref, char* childName) X{ X return XtNameToWidget( ref, childName ); X} X X#else X X/* NOTE: The Motif 1.0 XtNameToWidget is broken: it cannot find X** names with wild cards. The R4 XtNameToWidget is also broken: it X** cannot handle encounters with Gadgets. X** X** Below is the code extracted from the X11R4 distribution, with very X** minor changes to make it independent from the rest of the R4 Intrinsics, X** and to fix the bug in encountering Gadgets. X** X** Fixes: Added the two lines following this comment block. X** Renamed XtNameToWidget to WcChildNameToWidget to avoid warning. X** Removed "register" from arg type decls, as dbx does these X** incorrectly, and a decent compiler (gcc) does this anyway. X** --> Before looking for children, see if a widget is a gadget. X** Gadgets can't have children, in fact those fields are X** something else entirely!!! X*/ X X/*************** Begin source from X11R4 Xtos.h ***************/ X X#ifndef ALLOCATE_LOCAL X#define ALLOCATE_LOCAL(size) XtMalloc((unsigned long)(size)) X#define DEALLOCATE_LOCAL(ptr) XtFree((caddr_t)(ptr)) X#endif /* ALLOCATE_LOCAL */ X X/*************** End source from X11R4 Xtos.h ***************/ X X#define _XtAllocError XtError X X/*************** Begin source from X11R4 lib/Xt/Intrinsics.c ***************/ X Xstatic Widget NameListToWidget(); X Xtypedef Widget (*NameMatchProc)(); X Xstatic Widget MatchExactChildren(names, bindings, children, num, X in_depth, out_depth, found_depth) X XrmNameList names; X XrmBindingList bindings; X WidgetList children; X int num; X int in_depth, *out_depth, *found_depth; X{ X Cardinal i; X XrmName name = *names; X Widget w, result = NULL; X int d, min = 10000; X X for (i = 0; i < num; i++) { X if (name == children[i]->core.xrm_name) { X w = NameListToWidget(children[i], &names[1], &bindings[1], X in_depth+1, &d, found_depth); X if (w != NULL && d < min) {result = w; min = d;} X } X } X *out_depth = min; X return result; X} X Xstatic Widget MatchWildChildren(names, bindings, children, num, X in_depth, out_depth, found_depth) X XrmNameList names; X XrmBindingList bindings; X WidgetList children; X int num; X int in_depth, *out_depth, *found_depth; X{ X Cardinal i; X Widget w, result = NULL; X int d, min = 10000; X X for (i = 0; i < num; i++) { X w = NameListToWidget(children[i], names, bindings, X in_depth+1, &d, found_depth); X if (w != NULL && d < min) {result = w; min = d;} X } X *out_depth = min; X return result; X} X Xstatic Widget SearchChildren(root, names, bindings, matchproc, X in_depth, out_depth, found_depth) X Widget root; X XrmNameList names; X XrmBindingList bindings; X NameMatchProc matchproc; X int in_depth, *out_depth, *found_depth; X{ X Widget w1, w2; X int d1, d2; X X#if defined(MOTIF) && MOTIF == 1 && MOTIF_MINOR == 0 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 X/* X -- Find the named widget X******************************************************************************* X X This function uses WcChildNameToWidget to search a widget tree for a X widget with the given name. WcChildNameToWidget is basically X XtNameToWidget from X11R4, but hacked so it works when there are X Gadgets in the widget tree. X X WcChildNameToWidget, like XtNameToWidget, starts searching for children X of a reference widget. WcFullNameToWidget examines the first few X characters of the `name' argument in order to determine which widget is X the reference whidget where the search will begin. X X The possibilities are these: The `name' can begin with one or more of X the relative prefix characters: ^ or ~, which means the reference X widget will be some relative node in the widget tree, such as the X parent or the shell ancestor. Otherwise, the root widget will be the X starting point. X*/ X XWidget WcFullNameToWidget( w, name ) X Widget w; X char* name; X{ X Widget retWidget; X char *widgetName; X char *lowerName; X int i; X X widgetName = WcStripWhitespaceFromBothEnds( name ); /* must be XtFree'd */ X X if ( widgetName[0] == '*' ) X { X retWidget = WcChildNameToWidget( WcRootWidget(w), widgetName ); X XtFree( widgetName ); X return retWidget; X } X X if (widgetName[0] == '^' X || widgetName[0] == '~' X || widgetName[0] == '.') X { X i = 0; X while (widgetName[i] == '^' /* parent */ X || widgetName[i] == '~' /* shell ancestor */ X || widgetName[i] == '.') /* eaten and ignored */ X { X if (widgetName[i] == '^') X { X w = XtParent( w ); X } X else if (widgetName[i] == '~') X { X /* There is a bug in /usr/include/X11/IntrinsicP.h, in X ** the XtIsShell() macro. It does not parenthesize its X ** argument when it uses it. Therefore, the extra X ** parens are necessary here! X */ X while (! XtIsShell( (w = XtParent(w)) ) ) X ; X } X i++; X } X if (widgetName[i] == '\0') X retWidget = w; X else X retWidget = WcChildNameToWidget( w, &(widgetName[i]) ); X XtFree( widgetName ); X return retWidget; X } X X lowerName = WcLowerCaseCopy( widgetName ); /* must be XtFree'd */ X X if ( 0 == strcmp( "this", lowerName ) ) X { X XtFree( widgetName ); X XtFree( lowerName ); X return w; X } X X /* Apparently, the widget name starts with a name. We need to find X ** which root widget has this name. We need to go down the list of X ** root widgets maintained by WcRootWidget(). X */ X X { X Widget root; X Widget root_of_w; X char* rootName; X char* lowerRootName; X int widgetNameLen = strlen(lowerName); X int rootNameLen; X int startsWithRootName; X char* stripped; X X /* most of the time, a widget names something else in its X ** own widget heirarchy. Therefore, see if the naming starts X ** at the root widget of `w' but don't check that widget again. X */ X root_of_w = root = WcRootWidget( w ) ; X i = -1; X X while(1) X { X rootName = XrmQuarkToString( root->core.xrm_name ); X lowerRootName = WcLowerCaseCopy( rootName ); /* XtFree this */ X rootNameLen = strlen( lowerRootName ); X startsWithRootName = !strncmp(lowerName,lowerRootName,rootNameLen); X X if ( startsWithRootName && widgetName[rootNameLen] == '*' ) X { X /* the root widget name is followed by a `*' so strip the X ** root name, but keep the star as it implies loose binding. X */ X stripped = &widgetName[rootNameLen]; X retWidget = WcChildNameToWidget( root, stripped ); X XtFree( widgetName ); X XtFree( lowerName ); X XtFree( lowerRootName ); X return retWidget; X } X X else if ( startsWithRootName && widgetName[rootNameLen] == '.' ) X { X /* the root widget name is followed by a `.' so strip the X ** root name and the period to imply tight binding. X */ X stripped = &widgetName[++rootNameLen]; X retWidget = WcChildNameToWidget( root, stripped ); X XtFree( widgetName ); X XtFree( lowerName ); X XtFree( lowerRootName ); X return retWidget; X } X X else if ( startsWithRootName && (widgetNameLen == rootNameLen) ) X { X /* widgetName is the root widget. */ X XtFree( widgetName ); X XtFree( lowerName ); X XtFree( lowerRootName ); X return root; X } X X /* Did not find the root name. Try the next, but skip the X ** root_of_w which we checked first. X */ X if (++i == numRoots) X break; X if (root_of_w == (root = rootWidgets[i]) ) X { X if (++i == numRoots) X break; X root = rootWidgets[i]; X } X } X X /* Completely unsucessful in parsing this name. */ X#ifdef DEBUG X sprintf( msg, X "WcFullNameToWidget cannot convert `%s' to widget \n\ X Problem: Widget name must start with `*' or `.' or `~' or `^'\n\ X or `<aRoot>*' or `<aRoot>.' or be `this'" , X widgetName ); X XtWarning( msg ); X#endif X X XtFree( widgetName ); X XtFree( lowerName ); X XtFree( lowerRootName ); X return NULL; X } X} X X/* X -- Names to Widget List X****************************************************************************** X This routine converts a string of comma separated widget names X (or widget paths) into a list of widget id's. Blank space ignored. X If a NULL string is provided, NULL is put on the list. X X The return value is the list of names which could NOT be X converted. Note that this list is fixed size, and is re-used. X*/ X Xchar* WcNamesToWidgetList ( w, names, widget_list, widget_count ) X Widget w; /* reference widget */ X char* names; /* string of widget names */ X Widget widget_list[]; /* returned widget list */ X int *widget_count; /* in widget_list[len], out widget count */ X{ X static char ignored[MAX_XRMSTRING]; X char* next = names; X int max = *widget_count; X X/* -- parse the input names "widgetpath [, widgetpath] ..." */ X ignored[0] = NUL; X *widget_count = 0; X X do X { X next = WcCleanName ( next, cleanName ); X X if ( widget_list[*widget_count] = WcFullNameToWidget ( w, cleanName ) ) X (*widget_count)++; X else X { X if (ignored[0] == NUL) X strcpy(ignored, cleanName); X else X { X strcat(ignored, ", "); X strcat(ignored, cleanName); X } X } X next = WcSkipWhitespace_Comma ( next ); X X } while ( *next && *widget_count < max) ; X X return ignored; X} X X/* X -- WidgetToFullName X******************************************************************************* X Traverse up the widget tree, sprintf each name right up to X the root of the widget tree. sprintf the names to buffer. Use X recursion so order of names comes out right. Client MUST free X the char string alloc's and returned by WcWidgetToFullName(). X X Note: If using the Motif widget set, it is likely (almost inavoidable) X that the "widget" may actually be a Gadget. Well, Gadgets don't have X many things, particularly a core.name member. Therefore, if using X Motif we must check to see if the "widget" is not actually an XmGadget. X If is it, then we must use XrmQuarkToString(w->core.xrm_name) rather X than core.name (unfortunately). I'd rather not use the xrm name because X the case has been flattened: everything is lower case. Name something X SomeComplexLongName and you get back somecomplexlongname. The case X is always insignificant, but the mixed case name is easier to read. X*/ X Xstatic char* nextChar; X Xstatic int FullNameLen( w ) X Widget w; X{ X int len; X X#if defined(MOTIF) && MOTIF == 1 && MOTIF_MINOR == 0 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#if defined(MOTIF) && MOTIF == 1 && MOTIF_MINOR == 0 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* buff = XtMalloc( FullNameLen( w ) ); X X nextChar = buff; X X WidgetToFullName( w ); X *nextChar = NUL; X X return buff; X} X X/* X -- Search widget's resource list for resource_type X******************************************************************************* X Gets the XtResourceList from the widget, searches the list for X the resource name to determine the type required, which is then X returned to the caller. X*/ X Xchar* WcGetResourceType( w, res_name ) X Widget w; X char* res_name; X{ X XtResource* res_list; X int i, num; X char* retstr; X X XtGetResourceList( w->core.widget_class, &res_list, &num ); X X for ( i = 0 ; i < num ; i++ ) X { X if (0 == strcmp( res_name, res_list[i].resource_name) X || 0 == strcmp( res_name, res_list[i].resource_class) ) X { X retstr = XtNewString(res_list[i].resource_type); X XtFree( res_list ); X return retstr; X } X } X X w = XtParent( w ); X if (XtIsConstraint( w )) X { X XtGetConstraintResourceList( w->core.widget_class, &res_list, &num ); X X for ( i = 0 ; i < num ; i++ ) X { X if (0 == strcmp( res_name, res_list[i].resource_name) X || 0 == strcmp( res_name, res_list[i].resource_class) ) X { X retstr = XtNewString(res_list[i].resource_type); X XtFree( res_list ); X return retstr; X } X } X } X X return NULL; X} X X/* X -- Convert resource value from string to whatever the widget needs X******************************************************************************* X Gets the XtResourceList from the widget, searches the list for X the resource name to determine the type required, then uses the X resource manager to convert from string to the required type. X Calls XtSetValue with converted type. X X Note that if the widget does not have the specified resource X type, it is not set. WcGetResourceType() checks for both X widget resources and constraint resources. X X Note also that no converter-failed behavior is necessary, X because converters generally give their own error messages. X*/ X Xvoid WcSetValueFromString( w, res_name, res_val ) X Widget w; /* MUST already be init'd */ X char* res_name; X char* res_val; /* NUL terminated, should NOT have whitespace */ X{ X char* res_type; /* must be XtFree'd */ X X if ( res_type = WcGetResourceType( w, res_name ) ) X { X /* This widget does know about this resource type */ X WcSetValueFromStringAndType( w, res_name, res_val, res_type ); X } X XtFree( res_type ); X} X Xvoid WcSetValueFromStringAndType( w, res_name, res_val, res_type ) X Widget w; X char* res_name; X char* res_val; X char* res_type; X{ X XrmValue fr_val; X XrmValue to_val; X Arg arg[1]; X X fr_val.size = strlen(res_val) + 1; X fr_val.addr = (caddr_t)res_val; X to_val.size = 0; X to_val.addr = NULL; X XtConvert( X w, /* the widget */ X XtRString, /* from type */ X &fr_val, /* from value */ X res_type, /* to type */ X &to_val /* the converted value */ X ); X X if (to_val.addr) X { X /* Conversion worked. */ X if ( 0 == strcmp(res_type, "String")) X XtSetArg( arg[0], res_name, to_val.addr ); X else X { X switch(to_val.size) X { X case sizeof(char): X XtSetArg( arg[0], res_name, *(char*)to_val.addr ); X break; X case sizeof(short): X XtSetArg( arg[0], res_name, *(short*)to_val.addr ); X break; X case sizeof(int): X XtSetArg( arg[0], res_name, *(int*)to_val.addr ); X break; X default: X XtSetArg( arg[0], res_name, to_val.addr ); X } X } X XtSetValues( w, arg, 1 ); X } X} X X/* X******************************************************************************* X* Private Data involving the root widget list, declared at top of this file X* static int numRoots = 0; X* static Widget rootWidgets[MAX_ROOT_WIDGETS]; X******************************************************************************* X*/ X X X/* X -- Forget about a root widget X******************************************************************************* X When a root widget gets destroyed, we need to take that widget out X of our list of root widgets. This is a destroy callback routine X which is added to a root widget's destroy callback list by WcRootWidget. X*/ X Xstatic void ForgetRoot ( w, client, call ) X Widget w; X caddr_t client; X caddr_t call; X{ X int i; X for (i = 0 ; i < numRoots ; i++ ) X { X if ( w == rootWidgets[i] ) X { X /* move all following widgets up to close the gap */ X for ( ; i < numRoots ; i++ ) X { X rootWidgets[i] = rootWidgets[i+1]; X } X numRoots-- ; X return; X } X } X /* should never get here */ X} X X/* X -- Find root widget X******************************************************************************* X If a widget is passed, then find the root of that widget. See if X it is one of the root widgets we already know about. Add to list X if not. Return the root widget. X X If no widget is passed, then return the first root widget we know X about. If we know of no root widgets, then we will return a NULL X since the rootWidgets[] array starts out filled with nulls, and X gets re-filled as roots are destroyed. X*/ X XWidget WcRootWidget( w ) X Widget w; X{ X int i; X X if (w) X { X while ( XtParent(w) ) X w = XtParent(w); X X for (i = 0 ; i < numRoots ; i++) X { X if ( w == rootWidgets[i] ) X return w; X } X X rootWidgets[i] = w; X numRoots++; X XtAddCallback( w, XtNdestroyCallback, ForgetRoot, NULL ); X return w; X } X else X { X return rootWidgets[0]; X } X} X X/* X -- Equivalent to ANSI C library function strstr() X******************************************************************************* X This function is only necessary on systems which do not have X ANSI C libraries. Soon, it looks like everybody will have X such libraries, what with the recent SVR4 and OSF efforts X to include everything for everybody. In the meantime, X this will always be included in the library. Why not put X #ifdef's around it? because the problem really arises not X when the library is built, but when applications are built. X I can't very well require all application writers in the X world to know what this library uses... X*/ X Xchar* WcStrStr( s1, s2 ) X char* s1; X char* s2; X{ X while (*s1) X { X if (*s1 == *s2) X { X char* start = s1; X char* c = s2; X while (*++s1 & *++c && *s1 == *c) X ; X if (*c == '\0') X return start; X else X s1 = ++start; X } X else X { X s1++ ; X } X } X return (char*)0; X} +FUNKY+STUFF+ echo '-rw-r--r-- 1 david 31942 Oct 15 10:15 WcName.c (as sent)' chmod u=rw,g=r,o=r WcName.c ls -l WcName.c 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.