/* $XConsortium: geoIntrinsic.c /main/4 1995/07/15 21:13:22 drk $ */ /* * @OPENGROUP_COPYRIGHT@ * COPYRIGHT NOTICE * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc. * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for * the full copyright text. * * This software is subject to an open license. It may only be * used on, with or for operating systems which are themselves open * source systems. You must contact The Open Group for a license * allowing distribution and sublicensing of this software on, with, * or for operating systems which are not Open Source programs. * * See http://www.opengroup.org/openmotif/license for full * details of the license agreement. Any use, reproduction, or * distribution of the program constitutes recipient's acceptance of * this agreement. * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY * OR FITNESS FOR A PARTICULAR PURPOSE * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */ /* * HISTORY */ #define INTRINSIC_C #include "IntrinsicI.h" #include "StringDefs.h" #ifndef NO_IDENTIFY_WINDOWS #include #endif #ifndef VMS #include #endif /* VMS */ #ifndef X_NOT_STDC_ENV #include #else extern char *getenv(); #endif #include "geoTattler.h" String XtCXtToolkitError = "XtToolkitError"; Boolean XtIsSubclass(widget, widgetClass) Widget widget; WidgetClass widgetClass; { register WidgetClass w; for (w = widget->core.widget_class; w != NULL; w = w->core_class.superclass) if (w == widgetClass) return (TRUE); return (FALSE); } /* XtIsSubclass */ #if NeedFunctionPrototypes Boolean _XtCheckSubclassFlag( Widget object, _XtXtEnum flag ) #else Boolean _XtCheckSubclassFlag(object, flag) Widget object; XtEnum flag; #endif { if (object->core.widget_class->core_class.class_inited & flag) return True; else return False; } /*_XtVerifySubclass */ #if NeedFunctionPrototypes Boolean _XtIsSubclassOf( Widget object, WidgetClass widgetClass, WidgetClass superClass, _XtXtEnum flag ) #else Boolean _XtIsSubclassOf(object, widgetClass, superClass, flag) Widget object; WidgetClass widgetClass, superClass; XtEnum flag; #endif { if (!(object->core.widget_class->core_class.class_inited & flag)) return False; else { register WidgetClass c = object->core.widget_class; while (c != superClass) { if (c == widgetClass) return True; c = c->core_class.superclass; } return False; } } /*_XtIsSubclassOf */ static void ComputeWindowAttributes(widget,value_mask,values) Widget widget; XtValueMask *value_mask; XSetWindowAttributes *values; { *value_mask = CWEventMask | CWColormap; (*values).event_mask = XtBuildEventMask(widget); (*values).colormap = widget->core.colormap; if (widget->core.background_pixmap != XtUnspecifiedPixmap) { *value_mask |= CWBackPixmap; (*values).background_pixmap = widget->core.background_pixmap; } else { *value_mask |= CWBackPixel; (*values).background_pixel = widget->core.background_pixel; } if (widget->core.border_pixmap != XtUnspecifiedPixmap) { *value_mask |= CWBorderPixmap; (*values).border_pixmap = widget->core.border_pixmap; } else { *value_mask |= CWBorderPixel; (*values).border_pixel = widget->core.border_pixel; } if (widget->core.widget_class->core_class.expose == (XtExposeProc) NULL) { /* Try to avoid redisplay upon resize by making bit_gravity the same as the default win_gravity */ *value_mask |= CWBitGravity; (*values).bit_gravity = NorthWestGravity; } } /* ComputeWindowAttributes */ static void CallChangeManaged(widget) register Widget widget; { register Cardinal i; XtWidgetProc change_managed; register WidgetList children; int managed_children = 0; register CompositePtr cpPtr; register CompositePartPtr clPtr; if (XtIsComposite (widget)) { cpPtr = (CompositePtr)&((CompositeWidget) widget)->composite; clPtr = (CompositePartPtr)&((CompositeWidgetClass) widget->core.widget_class)->composite_class; } else return; children = cpPtr->children; change_managed = clPtr->change_managed; /* CallChangeManaged for all children */ for (i = cpPtr->num_children; i != 0; --i) { CallChangeManaged (children[i-1]); if (XtIsManaged(children[i-1])) managed_children++; } if (change_managed != NULL && managed_children != 0) { _GeoPrintTrace(widget,"Call \"%s\"[%d,%d]'s changemanaged\n", XtName(widget), widget->core.width, widget->core.height); (*change_managed) (widget); } } /* CallChangeManaged */ static void MapChildren(cwp) CompositePart *cwp; { Cardinal i; WidgetList children; register Widget child; children = cwp->children; for (i = 0; i < cwp->num_children; i++) { child = children[i]; if (XtIsWidget (child)){ if (child->core.managed && child->core.mapped_when_managed) { XtMapWidget (children[i]); } } } } /* MapChildren */ static Boolean ShouldMapAllChildren(cwp) CompositePart *cwp; { Cardinal i; WidgetList children; register Widget child; children = cwp->children; for (i = 0; i < cwp->num_children; i++) { child = children[i]; if (XtIsWidget(child)) { if (XtIsRealized(child) && (! (child->core.managed && child->core.mapped_when_managed))){ return False; } } } return True; } /* ShouldMapAllChildren */ static void RealizeWidget(widget) register Widget widget; { XtValueMask value_mask; XSetWindowAttributes values; XtRealizeProc realize; Window window; if (!XtIsWidget(widget) || XtIsRealized(widget)) return; _XtInstallTranslations(widget); ComputeWindowAttributes (widget, &value_mask, &values); realize = widget->core.widget_class->core_class.realize; if (realize == NULL) XtAppErrorMsg(XtWidgetToApplicationContext(widget), "invalidProcedure","realizeProc",XtCXtToolkitError, "No realize class procedure defined", (String *)NULL, (Cardinal *)NULL); else { _GeoPrintTrace(widget,"Call \"%s\"[%d,%d]'s realize proc\n", XtName(widget), widget->core.width, widget->core.height); (*realize) (widget, &value_mask, &values); } window = XtWindow(widget); #ifndef NO_IDENTIFY_WINDOWS if (_XtGetPerDisplay(XtDisplay(widget))->appContext->identify_windows) { int len_nm, len_cl; char *s; len_nm = widget->core.name ? strlen(widget->core.name) : 0; len_cl = strlen(widget->core.widget_class->core_class.class_name); s = XtMalloc((unsigned) (len_nm + len_cl + 2)); s[0] = '\0'; if (len_nm) strcpy(s, widget->core.name); strcpy(s + len_nm + 1, widget->core.widget_class->core_class.class_name); XChangeProperty(XtDisplay(widget), window, XInternAtom(XtDisplay(widget), "_MIT_OBJ_CLASS", False), XA_STRING, 8, PropModeReplace, (unsigned char *) s, len_nm + len_cl + 2); XtFree(s); } #endif #ifdef notdef _XtRegisterAsyncHandlers(widget); #endif _XtRegisterGrabs(widget); _XtRegisterWindow (window, widget); if (XtIsComposite (widget)) { register Cardinal i; register CompositePart *cwp = &(((CompositeWidget)widget)->composite); register WidgetList children = cwp->children; /* Realize all children */ for (i = cwp->num_children; i != 0; --i) { RealizeWidget (children[i-1]); } /* Map children that are managed and mapped_when_managed */ if (cwp->num_children != 0) { if (ShouldMapAllChildren(cwp)) { XMapSubwindows (XtDisplay(widget), window); } else { MapChildren(cwp); } } } /* If this is the application's popup shell, map it */ if (widget->core.parent == NULL && widget->core.mapped_when_managed) { XtMapWidget (widget); } } /* RealizeWidget */ void XtRealizeWidget (widget) register Widget widget; { if (XtIsRealized (widget)) return; CallChangeManaged(widget); RealizeWidget(widget); } /* XtRealizeWidget */ static void UnrealizeWidget(widget) register Widget widget; { register CompositeWidget cw; register Cardinal i; register WidgetList children; if (!XtIsWidget(widget) || !XtIsRealized(widget)) return; /* If this is the application's popup shell, unmap it? */ /* no, the window is being destroyed */ /* Recurse on children */ if (XtIsComposite (widget)) { cw = (CompositeWidget) widget; children = cw->composite.children; /* Unrealize all children */ for (i = cw->composite.num_children; i != 0; --i) { UnrealizeWidget (children[i-1]); } /* Unmap children that are managed and mapped_when_managed? */ /* No, it's ok to be managed and unrealized as long as your parent */ /* is unrealized. XtUnrealize widget makes sure the "top" widget */ /* is unmanaged, we can ignore all descendents */ } if (XtHasCallbacks(widget, XtNunrealizeCallback) == XtCallbackHasSome) XtCallCallbacks(widget, XtNunrealizeCallback, NULL); /* Unregister window */ _XtUnregisterWindow(XtWindow(widget), widget); /* Remove Event Handlers */ /* remove grabs. Happens automatically when window is destroyed. */ /* Destroy X Window, done at outer level with one request */ widget->core.window = None; /* Removing the event handler here saves having to keep track if * the translation table is changed while the widget is unrealized. */ _XtRemoveTranslations(widget); } /* UnrealizeWidget */ void XtUnrealizeWidget (widget) register Widget widget; { Window window = XtWindow(widget); if (! XtIsRealized (widget)) return; if (widget->core.parent != NULL) XtUnmanageChild(widget); UnrealizeWidget(widget); if (window != None) XDestroyWindow(XtDisplay(widget), window); } /* XtUnrealizeWidget */ void XtCreateWindow(widget, window_class, visual, value_mask, attributes) Widget widget; unsigned int window_class; Visual *visual; XtValueMask value_mask; XSetWindowAttributes *attributes; { if (widget->core.window == None) { if (widget->core.width == 0 || widget->core.height == 0) { Cardinal count = 1; XtAppErrorMsg(XtWidgetToApplicationContext(widget), "invalidDimension", "xtCreateWindow", XtCXtToolkitError, "Widget %s has zero width and/or height", &widget->core.name, &count); } widget->core.window = XCreateWindow ( XtDisplay (widget), (widget->core.parent ? widget->core.parent->core.window : widget->core.screen->root), (int)widget->core.x, (int)widget->core.y, (unsigned)widget->core.width, (unsigned)widget->core.height, (unsigned)widget->core.border_width, (int) widget->core.depth, window_class, visual, value_mask, attributes); } } /* XtCreateWindow */ /* ---------------- XtNameToWidget ----------------- */ static Widget NameListToWidget(); typedef Widget (*NameMatchProc)(); static Widget MatchExactChildren(names, bindings, children, num, in_depth, out_depth, found_depth) XrmNameList names; XrmBindingList bindings; register WidgetList children; register int num; int in_depth, *out_depth, *found_depth; { register Cardinal i; register XrmName name = *names; Widget w, result = NULL; int d, min = 10000; for (i = 0; i < num; i++) { if (name == children[i]->core.xrm_name) { w = NameListToWidget(children[i], &names[1], &bindings[1], in_depth+1, &d, found_depth); if (w != NULL && d < min) {result = w; min = d;} } } *out_depth = min; return result; } static Widget MatchWildChildren(names, bindings, children, num, in_depth, out_depth, found_depth) XrmNameList names; XrmBindingList bindings; register WidgetList children; register int num; int in_depth, *out_depth, *found_depth; { register Cardinal i; Widget w, result = NULL; int d, min = 10000; for (i = 0; i < num; i++) { w = NameListToWidget(children[i], names, bindings, in_depth+1, &d, found_depth); if (w != NULL && d < min) {result = w; min = d;} } *out_depth = min; return result; } static Widget SearchChildren(root, names, bindings, matchproc, in_depth, out_depth, found_depth) Widget root; XrmNameList names; XrmBindingList bindings; NameMatchProc matchproc; int in_depth, *out_depth, *found_depth; { Widget w1, w2; int d1, d2; if (XtIsComposite(root)) { w1 = (*matchproc)(names, bindings, ((CompositeWidget) root)->composite.children, ((CompositeWidget) root)->composite.num_children, in_depth, &d1, found_depth); } else d1 = 10000; w2 = (*matchproc)(names, bindings, root->core.popup_list, root->core.num_popups, in_depth, &d2, found_depth); *out_depth = (d1 < d2 ? d1 : d2); return (d1 < d2 ? w1 : w2); } static Widget NameListToWidget(root, names, bindings, in_depth, out_depth, found_depth) register Widget root; XrmNameList names; XrmBindingList bindings; int in_depth, *out_depth, *found_depth; { Widget w1, w2; int d1, d2; if (in_depth >= *found_depth) { *out_depth = 10000; return NULL; } if (names[0] == NULLQUARK) { *out_depth = *found_depth = in_depth; return root; } if (! XtIsWidget(root)) { *out_depth = 10000; return NULL; } if (*bindings == XrmBindTightly) { return SearchChildren(root, names, bindings, MatchExactChildren, in_depth, out_depth, found_depth); } else { /* XrmBindLoosely */ w1 = SearchChildren(root, names, bindings, MatchExactChildren, in_depth, &d1, found_depth); w2 = SearchChildren(root, names, bindings, MatchWildChildren, in_depth, &d2, found_depth); *out_depth = (d1 < d2 ? d1 : d2); return (d1 < d2 ? w1 : w2); } } /* NameListToWidget */ #if NeedFunctionPrototypes Widget XtNameToWidget( Widget root, _Xconst char* name ) #else Widget XtNameToWidget(root, name) Widget root; String name; #endif { XrmName *names; XrmBinding *bindings; int len, depth, found = 10000; Widget result; len = strlen(name); if (len == 0) return NULL; names = (XrmName *) ALLOCATE_LOCAL((unsigned) (len+1) * sizeof(XrmName)); bindings = (XrmBinding *) ALLOCATE_LOCAL((unsigned) (len+1) * sizeof(XrmBinding)); if (names == NULL || bindings == NULL) _XtAllocError(NULL); XrmStringToBindingQuarkList(name, bindings, names); if (names[0] == NULLQUARK) { DEALLOCATE_LOCAL((char *) bindings); DEALLOCATE_LOCAL((char *) names); return NULL; } result = NameListToWidget(root, names, bindings, 0, &depth, &found); DEALLOCATE_LOCAL((char *) bindings); DEALLOCATE_LOCAL((char *) names); return result; } /* XtNameToWidget */ /* Define user versions of intrinsics macros */ #undef XtDisplayOfObject Display *XtDisplayOfObject(object) Widget object; { return XtDisplay(XtIsWidget(object) ? object : _XtWindowedAncestor(object)); } #undef XtDisplay Display *XtDisplay(widget) Widget widget; { return DisplayOfScreen(widget->core.screen); } #undef XtScreenOfObject Screen *XtScreenOfObject(object) Widget object; { return XtScreen(XtIsWidget(object) ? object : _XtWindowedAncestor(object)); } #undef XtScreen Screen *XtScreen(widget) Widget widget; { return widget->core.screen; } #undef XtWindowOfObject Window XtWindowOfObject(object) Widget object; { return XtWindow(XtIsWidget(object) ? object : _XtWindowedAncestor(object)); } #undef XtWindow Window XtWindow(widget) Widget widget; { return widget->core.window; } #undef XtSuperclass WidgetClass XtSuperclass(widget) Widget widget; { return XtClass(widget)->core_class.superclass; } #undef XtClass WidgetClass XtClass(widget) Widget widget; { return widget->core.widget_class; } #undef XtIsManaged Boolean XtIsManaged(object) Widget object; { if (XtIsRectObj(object)) return object->core.managed; else return False; } #undef XtIsRealized Boolean XtIsRealized (object) Widget object; { return XtWindowOfObject(object) != None; } /* XtIsRealized */ #undef XtIsSensitive Boolean XtIsSensitive(object) Widget object; { if (XtIsRectObj(object)) return object->core.sensitive && object->core.ancestor_sensitive; else return False; } /* * Internal routine; must be called only after XtIsWidget returns false */ Widget _XtWindowedAncestor(object) register Widget object; { Widget obj = object; for (object = XtParent(object); object && !XtIsWidget(object);) object = XtParent(object); if (object == NULL) { String params = XtName(obj); Cardinal num_params = 1; XtErrorMsg("noWidgetAncestor", "windowedAncestor", XtCXtToolkitError, "Object \"%s\" does not have windowed ancestor", ¶ms, &num_params); } return object; } #undef XtParent Widget XtParent(widget) Widget widget; { return widget->core.parent; } #undef XtName String XtName(object) Widget object; { return XrmQuarkToString(object->core.xrm_name); } Boolean XtIsObject(object) Widget object; { WidgetClass wc; String class_name; /* perform basic sanity checks */ if (object->core.self != object || object->core.xrm_name == NULLQUARK) return False; wc = object->core.widget_class; if (wc->core_class.class_name == NULL || wc->core_class.xrm_class == NULLQUARK || (class_name = XrmClassToString(wc->core_class.xrm_class)) == NULL || strcmp(wc->core_class.class_name, class_name) != 0) return False; if (XtIsWidget(object)) { if (object->core.name == NULL || (class_name = XrmNameToString(object->core.xrm_name)) == NULL || strcmp(object->core.name, class_name) != 0) return False; } return True; } static Boolean TestFile(path) String path; { #ifdef VMS return TRUE; /* Who knows what to do here? */ #else struct stat status; return (access(path, R_OK) == 0 && /* exists and is readable */ stat(path, &status) == 0 && /* get the status */ #ifndef X_NOT_POSIX S_ISDIR(status.st_mode) == 0); /* not a directory */ #else (status.st_mode & S_IFDIR) == 0); /* not a directory */ #endif /* X_NOT_POSIX else */ #endif /* VMS */ } /* return of TRUE = resolved string fit, FALSE = didn't fit. Not null-terminated and not collapsed if it didn't fit */ static Boolean Resolve(source, len, sub, num, buf, collapse) register char *source; /* The source string */ register int len; /* The length in bytes of *source */ Substitution sub; /* Array of string values to substitute */ Cardinal num; /* Number of substitution entries */ char *buf; /* Where to put the resolved string; */ char collapse; /* Character to collapse */ { register int bytesLeft = PATH_MAX; register char* bp = buf; #ifndef DONT_COLLAPSE Boolean atBeginning = TRUE; Boolean prevIsCollapse = FALSE; #define PUT(ch) \ { \ if (--bytesLeft == 0) return FALSE; \ if (prevIsCollapse) \ if ((*bp = ch) != collapse) { \ prevIsCollapse = FALSE; \ bp++; \ } \ else bytesLeft++; \ else if ((*bp++ = ch) == collapse && !atBeginning) \ prevIsCollapse = TRUE; \ } #else /* DONT_COLLAPSE */ #define PUT(ch) \ { \ if (--bytesLeft == 0) return FALSE; \ *bp++ = ch; \ } #endif /* DONT_COLLAPSE */ #define escape '%' while (len--) { #ifndef DONT_COLLAPSE if (*source == collapse) { PUT(*source); source++; continue; } else #endif /* DONT_COLLAPSE */ if (*source != escape) { PUT(*source); } else { source++; if (len-- == 0) { PUT(escape); break; } if (*source == ':' || *source == escape) PUT(*source) else { /* Match the character against the match array */ register int j; for (j = 0; j < num && sub[j].match != *source; j++) {} /* Substitute the substitution string */ if (j >= num) PUT(*source) else if (sub[j].substitution != NULL) { char *sp = sub[j].substitution; while (*sp) { PUT(*sp); sp++; } } } } source++; #ifndef DONT_COLLAPSE atBeginning = FALSE; #endif /* DONT_COLLAPSE */ } PUT('\0'); return TRUE; #undef PUT #undef escape } #if NeedFunctionPrototypes String XtFindFile( _Xconst char* path, Substitution substitutions, Cardinal num_substitutions, XtFilePredicate predicate ) #else String XtFindFile(path, substitutions, num_substitutions, predicate) String path; Substitution substitutions; Cardinal num_substitutions; XtFilePredicate predicate; #endif { char *buf, *buf1, *buf2, *colon, *start; int len; Boolean firstTime = TRUE; buf = buf1 = XtMalloc((unsigned)PATH_MAX); buf2 = XtMalloc((unsigned)PATH_MAX); if (predicate == NULL) predicate = TestFile; while (1) { start = (String)path; while (1) { colon = index(start, ':'); if (colon == NULL) break; if (colon == path) {start++; path++; continue; } if (*(colon-1) != '%') break; start = colon+1; } if (colon != NULL) len = colon - path; else len = strlen(path); if (Resolve(path, len, substitutions, num_substitutions, buf, '/')) { if (firstTime || strcmp(buf1,buf2) != 0) { #ifdef XNL_DEBUG printf("Testing file %s\n", buf); #endif /* XNL_DEBUG */ /* Check out the file */ if ((*predicate) (buf)) { /* We've found it, return it */ #ifdef XNL_DEBUG printf("File found.\n"); #endif /* XNL_DEBUG */ if (buf == buf1) XtFree(buf2); else XtFree(buf1); return buf; } if (buf == buf1) buf = buf2; else buf = buf1; firstTime = FALSE; } } /* Nope...any more paths? */ if (colon == NULL) break; path = colon+1; } /* No file found */ XtFree(buf1); XtFree(buf2); return NULL; } /* The implementation of this routine is operating system dependent */ static char *ExtractLocaleName(lang) String lang; { #ifdef hpux /* hpux-specific parsing of the locale string */ #define MAXLOCALE 64 /* buffer size of locale name */ char *start; char *end; int len; static char buf[MAXLOCALE]; /* If lang has a substring ":;", extract * from the first such occurrence as the locale name. */ start = lang; if (start = strchr (lang, ':')) { start++; if (end = strchr (start, ';')) { len = end - start; strncpy(buf, start, len); *(buf + len) = '\0'; lang = buf; } } #endif /* hpux */ /* If result is "C", return NULL instead. */ if (strcmp(lang, "C")) return lang; else return NULL; } static void FillInLangSubs(subs, pd) Substitution subs; XtPerDisplay pd; { int len; char *string, *p1, *p2, *p3; char **rest; char *ch; if (pd->language == NULL || pd->language[0] == '\0') { subs[0].substitution = subs[1].substitution = subs[2].substitution = subs[3].substitution = NULL; return; } string = ExtractLocaleName(pd->language); if (string == NULL || string[0] == '\0') { subs[0].substitution = subs[1].substitution = subs[2].substitution = subs[3].substitution = NULL; return; } len = strlen(string) + 1; subs[0].substitution = string; p1 = subs[1].substitution = XtMalloc((Cardinal) 3*len); p2 = subs[2].substitution = subs[1].substitution + len; p3 = subs[3].substitution = subs[2].substitution + len; /* Everything up to the first "_" goes into p1. From "_" to "." in p2. The rest in p3. If no delimiters, all goes into p1. We assume p1, p2, and p3 are large enough. */ *p1 = *p2 = *p3 = '\0'; ch = index(string, '_'); if (ch != NULL) { len = ch - string; (void) strncpy(p1, string, len); p1[len] = '\0'; string = ch + 1; rest = &p2; } else rest = &p1; /* Rest points to where we put the first part */ ch = index(string, '.'); if (ch != NULL) { len = ch - string; strncpy(*rest, string, len); (*rest)[len] = '\0'; (void) strcpy(p3, ch+1); } else (void) strcpy(*rest, string); } static SubstitutionRec defaultSubs[] = { {'N', NULL}, {'T', NULL}, {'S', NULL}, {'C', NULL}, {'L', NULL}, {'l', NULL}, {'t', NULL}, {'c', NULL} }; #if NeedFunctionPrototypes String XtResolvePathname( Display *dpy, _Xconst char* type, _Xconst char* filename, _Xconst char* suffix, _Xconst char* path, Substitution substitutions, Cardinal num_substitutions, XtFilePredicate predicate ) #else String XtResolvePathname(dpy, type, filename, suffix, path, substitutions, num_substitutions, predicate) Display *dpy; String type, filename, suffix, path; Substitution substitutions; Cardinal num_substitutions; XtFilePredicate predicate; #endif { XtPerDisplay pd = _XtGetPerDisplay(dpy); static char *defaultPath = NULL; char *massagedPath; int bytesAllocd, bytesLeft; char *ch, *result; Substitution merged_substitutions; XrmRepresentation db_type; XrmValue value; XrmName name_list[3]; XrmClass class_list[3]; Boolean pathMallocd = False; if (path == NULL) { #ifndef VMS if (defaultPath == NULL) { defaultPath = getenv("XFILESEARCHPATH"); if (defaultPath == NULL) defaultPath = XFILESEARCHPATHDEFAULT; } path = defaultPath; #else path = ""; /* NULL would kill us later */ #endif /* VMS */ } if (filename == NULL) { filename = XrmClassToString(pd->class); } bytesAllocd = bytesLeft = 1000; massagedPath = ALLOCATE_LOCAL(bytesAllocd); if (massagedPath == NULL) _XtAllocError(NULL); if (path[0] == ':') { strcpy(massagedPath, "%N%S"); ch = &massagedPath[4]; bytesLeft -= 4; } else ch = massagedPath; /* Insert %N%S between adjacent colons */ while (*path != '\0') { if (bytesLeft < 8) { int bytesUsed = bytesAllocd - bytesLeft; char *new; bytesAllocd +=1000; new = XtMalloc((Cardinal) bytesAllocd); strncpy( new, massagedPath, bytesUsed ); ch = new + bytesUsed; if (pathMallocd) XtFree(massagedPath); else DEALLOCATE_LOCAL(massagedPath); pathMallocd = True; massagedPath = new; bytesLeft = bytesAllocd - bytesUsed; } if (*path == '%' && *(path+1) == ':') { *ch++ = '%'; *ch++ = ':'; path += 2; bytesLeft -= 2; continue; } if (*path == ':' && *(path+1) == ':') { strcpy(ch, ":%N%S:"); ch += 6; bytesLeft -= 6; while (*path == ':') path++; continue; } *ch++ = *path++; bytesLeft--; } *ch = '\0'; #ifdef XNL_DEBUG printf("Massaged path: %s\n", massagedPath); #endif /* XNL_DEBUG */ if (num_substitutions == 0) merged_substitutions = defaultSubs; else { int i = XtNumber(defaultSubs); Substitution sub, def; merged_substitutions = sub = (Substitution) ALLOCATE_LOCAL((unsigned)(num_substitutions+i)*sizeof(SubstitutionRec)); if (sub == NULL) _XtAllocError(NULL); for (def = defaultSubs; i--; sub++, def++) sub->match = def->match; for (i = num_substitutions; i--; ) *sub++ = *substitutions++; } merged_substitutions[0].substitution = (String)filename; merged_substitutions[1].substitution = (String)type; merged_substitutions[2].substitution = (String)suffix; name_list[0] = pd->name; name_list[1] = XrmPermStringToQuark("customization"); name_list[2] = NULLQUARK; class_list[0] = pd->class; class_list[1] = XrmPermStringToQuark("Customization"); class_list[2] = NULLQUARK; if (XrmQGetResource(XrmGetDatabase(dpy), name_list, class_list, &db_type, &value) && db_type == _XtQString) merged_substitutions[3].substitution = (char *)value.addr; else merged_substitutions[3].substitution = NULL; FillInLangSubs(&merged_substitutions[4], pd); result = XtFindFile(massagedPath, merged_substitutions, num_substitutions + XtNumber(defaultSubs), predicate); if (merged_substitutions[5].substitution != NULL) XtFree( (XtPointer)merged_substitutions[5].substitution ); if (merged_substitutions != defaultSubs) DEALLOCATE_LOCAL(merged_substitutions); if (pathMallocd) XtFree(massagedPath); else DEALLOCATE_LOCAL(massagedPath); return result; } Boolean XtCallAcceptFocus(widget, time) Widget widget; Time *time; { XtAcceptFocusProc ac = XtClass(widget)->core_class.accept_focus; if (ac != NULL) return (*ac) (widget, time); else return FALSE; }