#define INTRINSIC_C
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "IntrinsicI.h"
#include "VarargsI.h"
#ifndef NO_IDENTIFY_WINDOWS
#include <X11/Xatom.h>
#endif
#ifndef VMS
#include <sys/stat.h>
#endif
#include <stdlib.h>
String XtCXtToolkitError = "XtToolkitError";
Boolean XtIsSubclass(
Widget widget,
WidgetClass widgetClass)
{
register WidgetClass w;
Boolean retval = FALSE;
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
LOCK_PROCESS;
for (w = widget->core.widget_class; w != NULL; w = w->core_class.superclass)
if (w == widgetClass) {
retval = TRUE;
break;
}
UNLOCK_PROCESS;
UNLOCK_APP(app);
return retval;
}
Boolean _XtCheckSubclassFlag(
Widget object,
_XtXtEnum flag)
{
Boolean retval;
LOCK_PROCESS;
if (object->core.widget_class->core_class.class_inited & flag)
retval = TRUE;
else
retval = FALSE;
UNLOCK_PROCESS;
return retval;
}
Boolean _XtIsSubclassOf(
Widget object,
WidgetClass widgetClass,
WidgetClass superClass,
_XtXtEnum flag)
{
LOCK_PROCESS;
if (!(object->core.widget_class->core_class.class_inited & flag)) {
UNLOCK_PROCESS;
return False;
} else {
register WidgetClass c = object->core.widget_class;
while (c != superClass) {
if (c == widgetClass) {
UNLOCK_PROCESS;
return True;
}
c = c->core_class.superclass;
}
UNLOCK_PROCESS;
return False;
}
}
XtPointer XtGetClassExtension(
WidgetClass object_class,
Cardinal byte_offset,
XrmQuark type,
long version,
Cardinal record_size)
{
ObjectClassExtension ext;
LOCK_PROCESS;
ext = *(ObjectClassExtension *)((char *)object_class + byte_offset);
while (ext && (ext->record_type != type || ext->version < version
|| ext->record_size < record_size)) {
ext = (ObjectClassExtension) ext->next_extension;
}
UNLOCK_PROCESS;
return (XtPointer) ext;
}
static void ComputeWindowAttributes(
Widget widget,
XtValueMask *value_mask,
XSetWindowAttributes *values)
{
XtExposeProc expose;
*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;
}
LOCK_PROCESS;
expose = widget->core.widget_class->core_class.expose;
UNLOCK_PROCESS;
if (expose == (XtExposeProc) NULL) {
*value_mask |= CWBitGravity;
(*values).bit_gravity = NorthWestGravity;
}
}
static void CallChangeManaged(
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;
LOCK_PROCESS;
change_managed = clPtr->change_managed;
UNLOCK_PROCESS;
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) {
CALLGEOTAT(_XtGeoTrace(widget,"Call \"%s\"[%d,%d]'s changemanaged\n",
XtName(widget),
widget->core.width, widget->core.height));
(*change_managed) (widget);
}
}
static void MapChildren(
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]);
}
}
}
}
static Boolean ShouldMapAllChildren(
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;
}
static void RealizeWidget(
Widget widget)
{
XtValueMask value_mask;
XSetWindowAttributes values;
XtRealizeProc realize;
Window window;
Display* display;
String class_name;
Widget hookobj;
if (!XtIsWidget(widget) || XtIsRealized(widget)) return;
display = XtDisplay(widget);
_XtInstallTranslations(widget);
ComputeWindowAttributes (widget, &value_mask, &values);
LOCK_PROCESS;
realize = widget->core.widget_class->core_class.realize;
class_name = widget->core.widget_class->core_class.class_name;
UNLOCK_PROCESS;
if (realize == NULL)
XtAppErrorMsg(XtWidgetToApplicationContext(widget),
"invalidProcedure","realizeProc",XtCXtToolkitError,
"No realize class procedure defined",
(String *)NULL, (Cardinal *)NULL);
else {
CALLGEOTAT(_XtGeoTrace(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);
hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
if (XtHasCallbacks(hookobj,XtNchangeHook) == XtCallbackHasSome) {
XtChangeHookDataRec call_data;
call_data.type = XtHrealizeWidget;
call_data.widget = widget;
XtCallCallbackList(hookobj,
((HookObject)hookobj)->hooks.changehook_callbacks,
(XtPointer)&call_data);
}
#ifndef NO_IDENTIFY_WINDOWS
if (_XtGetPerDisplay(display)->appContext->identify_windows) {
int len_nm, len_cl;
char *s;
len_nm = widget->core.name ? strlen(widget->core.name) : 0;
len_cl = strlen(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, class_name);
XChangeProperty(display, window,
XInternAtom(display, "_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);
_XtRegisterPassiveGrabs(widget);
XtRegisterDrawable (display, window, widget);
_XtExtensionSelect(widget);
if (XtIsComposite (widget)) {
Cardinal i;
CompositePart *cwp = &(((CompositeWidget)widget)->composite);
WidgetList children = cwp->children;
for (i = cwp->num_children; i != 0; --i) {
RealizeWidget (children[i-1]);
}
if (cwp->num_children != 0) {
if (ShouldMapAllChildren(cwp)) {
XMapSubwindows (display, window);
} else {
MapChildren(cwp);
}
}
}
if (widget->core.parent == NULL && widget->core.mapped_when_managed) {
XtMapWidget (widget);
}
}
void XtRealizeWidget (
Widget widget)
{
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
if (XtIsRealized (widget)) {
UNLOCK_APP(app);
return;
}
CallChangeManaged(widget);
RealizeWidget(widget);
UNLOCK_APP(app);
}
static void UnrealizeWidget(
Widget widget)
{
CompositeWidget cw;
Cardinal i;
WidgetList children;
if (!XtIsWidget(widget) || !XtIsRealized(widget)) return;
if (XtIsComposite (widget)) {
cw = (CompositeWidget) widget;
children = cw->composite.children;
for (i = cw->composite.num_children; i != 0; --i) {
UnrealizeWidget (children[i-1]);
}
}
if (XtHasCallbacks(widget, XtNunrealizeCallback) == XtCallbackHasSome)
XtCallCallbacks(widget, XtNunrealizeCallback, NULL);
XtUnregisterDrawable(XtDisplay(widget), XtWindow(widget));
widget->core.window = None;
_XtRemoveTranslations(widget);
}
void XtUnrealizeWidget (
Widget widget)
{
Window window;
Widget hookobj;
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
window = XtWindow(widget);
if (! XtIsRealized (widget)) {
UNLOCK_APP(app);
return;
}
if (widget->core.managed && widget->core.parent != NULL)
XtUnmanageChild(widget);
UnrealizeWidget(widget);
if (window != None)
XDestroyWindow(XtDisplay(widget), window);
hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) {
XtChangeHookDataRec call_data;
call_data.type = XtHunrealizeWidget;
call_data.widget = widget;
XtCallCallbackList(hookobj,
((HookObject)hookobj)->hooks.changehook_callbacks,
(XtPointer)&call_data);
}
UNLOCK_APP(app);
}
void XtCreateWindow(
Widget widget,
unsigned int window_class,
Visual *visual,
XtValueMask value_mask,
XSetWindowAttributes *attributes)
{
XtAppContext app = XtWidgetToApplicationContext(widget);
LOCK_APP(app);
if (widget->core.window == None) {
if (widget->core.width == 0 || widget->core.height == 0) {
Cardinal count = 1;
XtAppErrorMsg(app,
"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);
}
UNLOCK_APP(app);
}
static Widget NameListToWidget(
Widget root,
XrmNameList names,
XrmBindingList bindings,
int in_depth, int *out_depth, int *found_depth);
typedef Widget (*NameMatchProc)(XrmNameList,
XrmBindingList,
WidgetList, Cardinal, int, int *, int *);
static Widget MatchExactChildren(
XrmNameList names,
XrmBindingList bindings,
register WidgetList children,
register Cardinal num,
int in_depth, int *out_depth, int *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(
XrmNameList names,
XrmBindingList bindings,
register WidgetList children,
register Cardinal num,
int in_depth, int *out_depth, int *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(
Widget root,
XrmNameList names,
XrmBindingList bindings,
NameMatchProc matchproc,
int in_depth, int *out_depth, int *found_depth)
{
Widget w1 = 0, 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(
register Widget root,
XrmNameList names,
XrmBindingList bindings,
int in_depth, int *out_depth, int *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 {
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);
}
}
Widget XtNameToWidget(
Widget root,
_Xconst char* name)
{
XrmName *names;
XrmBinding *bindings;
int len, depth, found = 10000;
Widget result;
WIDGET_TO_APPCON(root);
len = strlen(name);
if (len == 0) return NULL;
LOCK_APP(app);
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);
UNLOCK_APP(app);
return NULL;
}
result = NameListToWidget(root, names, bindings, 0, &depth, &found);
DEALLOCATE_LOCAL((char *) bindings);
DEALLOCATE_LOCAL((char *) names);
UNLOCK_APP(app);
return result;
}
#undef XtDisplayOfObject
Display *XtDisplayOfObject(
Widget object)
{
if (XtIsSubclass(object, hookObjectClass))
return DisplayOfScreen(((HookObject)object)->hooks.screen);
return XtDisplay(XtIsWidget(object) ? object : _XtWindowedAncestor(object));
}
#undef XtDisplay
Display *XtDisplay(
Widget widget)
{
return DisplayOfScreen(widget->core.screen);
}
#undef XtScreenOfObject
Screen *XtScreenOfObject(
Widget object)
{
if (XtIsSubclass(object, hookObjectClass))
return ((HookObject)object)->hooks.screen;
return XtScreen(XtIsWidget(object) ? object : _XtWindowedAncestor(object));
}
#undef XtScreen
Screen *XtScreen(
Widget widget)
{
return widget->core.screen;
}
#undef XtWindowOfObject
Window XtWindowOfObject(
Widget object)
{
return XtWindow(XtIsWidget(object) ? object : _XtWindowedAncestor(object));
}
#undef XtWindow
Window XtWindow(
Widget widget)
{
return widget->core.window;
}
#undef XtSuperclass
WidgetClass XtSuperclass(
Widget widget)
{
WidgetClass retval;
LOCK_PROCESS;
retval = XtClass(widget)->core_class.superclass;
UNLOCK_PROCESS;
return retval;
}
#undef XtClass
WidgetClass XtClass(
Widget widget)
{
WidgetClass retval;
LOCK_PROCESS;
retval = widget->core.widget_class;
UNLOCK_PROCESS;
return retval;
}
#undef XtIsManaged
Boolean XtIsManaged(
Widget object)
{
Boolean retval;
WIDGET_TO_APPCON(object);
LOCK_APP(app);
if (XtIsRectObj(object))
retval = object->core.managed;
else
retval = False;
UNLOCK_APP(app);
return retval;
}
#undef XtIsRealized
Boolean XtIsRealized (
Widget object)
{
Boolean retval;
WIDGET_TO_APPCON(object);
LOCK_APP(app);
retval = XtWindowOfObject(object) != None;
UNLOCK_APP(app);
return retval;
}
#undef XtIsSensitive
Boolean XtIsSensitive(
Widget object)
{
Boolean retval;
WIDGET_TO_APPCON(object);
LOCK_APP(app);
if (XtIsRectObj(object))
retval = object->core.sensitive && object->core.ancestor_sensitive;
else
retval = False;
UNLOCK_APP(app);
return retval;
}
Widget _XtWindowedAncestor(
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)
{
return widget->core.parent;
}
#undef XtName
String XtName(
Widget object)
{
return XrmQuarkToString(object->core.xrm_name);
}
Boolean XtIsObject(
Widget object)
{
WidgetClass wc;
String class_name;
if (object->core.self != object || object->core.xrm_name == NULLQUARK)
return False;
LOCK_PROCESS;
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) {
UNLOCK_PROCESS;
return False;
}
UNLOCK_PROCESS;
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;
}
#if defined(WIN32)
static int access_file (
char* path,
char* pathbuf,
int len_pathbuf,
char** pathret)
{
if (access (path, F_OK) == 0) {
if (strlen (path) < len_pathbuf)
*pathret = pathbuf;
else
*pathret = XtMalloc (strlen (path));
if (*pathret) {
strcpy (*pathret, path);
return 1;
}
}
return 0;
}
static int AccessFile (
char* path,
char* pathbuf,
int len_pathbuf,
char** pathret)
{
unsigned long drives;
int i, len;
char* drive;
char buf[MAX_PATH];
char* bufp;
if (access_file (path, pathbuf, len_pathbuf, pathret))
return 1;
drive = getenv ("_XBASEDRIVE");
#ifdef __UNIXOS2__
if (!drive)
drive = getenv ("X11ROOT");
#endif
if (!drive)
drive = "C:";
len = strlen (drive) + strlen (path);
bufp = XtStackAlloc (len + 1, buf);
strcpy (bufp, drive);
strcat (bufp, path);
if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
XtStackFree (bufp, buf);
return 1;
}
#ifndef __UNIXOS2__
drive = getenv ("HOMEDRIVE");
if (drive) {
len = strlen (drive) + strlen (path);
bufp = XtStackAlloc (len + 1, buf);
strcpy (bufp, drive);
strcat (bufp, path);
if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
XtStackFree (bufp, buf);
return 1;
}
}
drives = _getdrives ();
#define C_DRIVE ('C' - 'A')
#define Z_DRIVE ('Z' - 'A')
for (i = C_DRIVE; i <= Z_DRIVE; i++) {
if ((1 << i) & drives) {
len = 2 + strlen (path);
bufp = XtStackAlloc (len + 1, buf);
*bufp = 'A' + i;
*(bufp + 1) = ':';
*(bufp + 2) = '\0';
strcat (bufp, path);
if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
XtStackFree (bufp, buf);
return 1;
}
}
}
#endif
return 0;
}
#endif
static Boolean TestFile(
String path)
{
#ifndef VMS
int ret = 0;
struct stat status;
#if defined(WIN32)
char buf[MAX_PATH];
char* bufp;
int len;
UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
if (AccessFile (path, buf, MAX_PATH, &bufp))
path = bufp;
(void) SetErrorMode (olderror);
#endif
ret = (access(path, R_OK) == 0 &&
stat(path, &status) == 0 &&
#ifndef X_NOT_POSIX
S_ISDIR(status.st_mode) == 0);
#else
(status.st_mode & S_IFMT) != S_IFDIR);
#endif
#if defined(WIN32)
XtStackFree ((XtPointer)bufp, buf);
#endif
return ret;
#else
return TRUE;
#endif
}
static Boolean Resolve(
register _Xconst char *source,
register int len,
Substitution sub,
Cardinal num,
char *buf,
char 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
#define PUT(ch) \
{ \
if (--bytesLeft == 0) return FALSE; \
*bp++ = ch; \
}
#endif
#define escape '%'
while (len--) {
#ifndef DONT_COLLAPSE
if (*source == collapse) {
PUT(*source);
source++;
continue;
}
else
#endif
if (*source != escape) {
PUT(*source);
}
else {
source++;
if (len-- == 0) {
PUT(escape);
break;
}
if (*source == ':' || *source == escape)
PUT(*source)
else {
register Cardinal j;
for (j = 0; j < num && sub[j].match != *source; j++) {}
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
}
PUT('\0');
return TRUE;
#undef PUT
#undef escape
}
String XtFindFile(
_Xconst char* path,
Substitution substitutions,
Cardinal num_substitutions,
XtFilePredicate predicate)
{
char *buf, *buf1, *buf2, *colon;
int len;
Boolean firstTime = TRUE;
buf = buf1 = __XtMalloc((unsigned)PATH_MAX);
buf2 = __XtMalloc((unsigned)PATH_MAX);
if (predicate == NULL) predicate = TestFile;
while (1) {
colon = (String)path;
while (*colon) {
if (*colon != ':') break;
colon++;
path++;
}
for ( ; *colon ; colon++) {
if (*colon == '%' && *(path+1)) {
colon++;
continue;
}
if (*colon == ':')
#ifdef __UNIXOS2__
if (colon > (path+1))
#endif
break;
}
len = colon - path;
if (Resolve(path, len, substitutions, num_substitutions,
buf, '/')) {
if (firstTime || strcmp(buf1,buf2) != 0) {
#ifdef __UNIXOS2__
{
char *bufx = (char*)__XOS2RedirRoot(buf);
strcpy(buf,bufx);
}
#endif
#ifdef XNL_DEBUG
printf("Testing file %s\n", buf);
#endif
if ((*predicate) (buf)) {
#ifdef XNL_DEBUG
printf("File found.\n");
#endif
if (buf == buf1) XtFree(buf2);
else XtFree(buf1);
return buf;
}
if (buf == buf1)
buf = buf2;
else
buf = buf1;
firstTime = FALSE;
}
}
if (*colon == '\0') break;
path = colon+1;
}
XtFree(buf1);
XtFree(buf2);
return NULL;
}
static char *ExtractLocaleName(
String lang)
{
#if defined(hpux) || defined(CSRG_BASED) || defined(sun) || defined(SVR4) || defined(sgi) || defined(__osf__) || defined(AIXV3) || defined(ultrix) || defined(WIN32) || defined(__UNIXOS2__) || defined (linux)
# ifdef hpux
# include <locale.h>
# ifndef _LastCategory
# define SKIPCOUNT 2
# define STARTCHAR ':'
# define ENDCHAR ';'
# else
# define ENDCHAR ' '
# endif
# else
# ifdef ultrix
# define SKIPCOUNT 2
# define STARTCHAR '\001'
# define ENDCHAR '\001'
# else
# if defined(WIN32) || defined(__UNIXOS2__)
# define SKIPCOUNT 1
# define STARTCHAR '='
# define ENDCHAR ';'
# define WHITEFILL
# else
# if defined(__osf__) || (defined(AIXV3) && !defined(AIXV4))
# define STARTCHAR ' '
# define ENDCHAR ' '
# else
# if defined(linux)
# define STARTSTR "LC_CTYPE="
# define ENDCHAR ';'
# else
# if !defined(sun) || defined(SVR4)
# define STARTCHAR '/'
# define ENDCHAR '/'
# endif
# endif
# endif
# endif
# endif
# endif
char *start;
char *end;
int len;
# ifdef SKIPCOUNT
int n;
# endif
static char* buf = NULL;
start = lang;
# ifdef SKIPCOUNT
for (n = SKIPCOUNT;
--n >= 0 && start && (start = strchr (start, STARTCHAR));
start++)
;
if (!start)
start = lang;
# endif
# ifdef STARTCHAR
if (start && (start = strchr (start, STARTCHAR)))
# elif defined (STARTSTR)
if (start && (start = strstr (start,STARTSTR)))
# endif
{
# ifdef STARTCHAR
start++;
# elif defined (STARTSTR)
start += strlen(STARTSTR);
# endif
if ((end = strchr (start, ENDCHAR))) {
len = end - start;
if (buf != NULL) XtFree (buf);
buf = XtMalloc (len + 1);
if (buf == NULL) return NULL;
strncpy(buf, start, len);
*(buf + len) = '\0';
# ifdef WHITEFILL
for (start = buf; start = strchr(start, ' '); )
*start++ = '-';
# endif
return buf;
} else
return start;
}
# ifdef WHITEFILL
if (strchr(lang, ' ')) {
if (buf != NULL) XtFree (buf);
else buf = XtMalloc (strlen (lang) + 1);
if (buf == NULL) return NULL;
strcpy(buf, lang);
for (start = buf; start = strchr(start, ' '); )
*start++ = '-';
return buf;
}
# endif
# undef STARTCHAR
# undef ENDCHAR
# undef WHITEFILL
#endif
return lang;
}
static void FillInLangSubs(
Substitution subs,
XtPerDisplay pd)
{
int len;
char *string, *p1, *p2, *p3;
char **rest;
char *ch;
if (pd->language == NULL ||
(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 != 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;
*p1 = *p2 = *p3 = '\0';
ch = strchr(string, '_');
if (ch != NULL) {
len = ch - string;
(void) strncpy(p1, string, len);
p1[len] = '\0';
string = ch + 1;
rest = &p2;
} else rest = &p1;
ch = strchr(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 char *implementation_default_path(void)
{
#if defined(WIN32) || defined(__UNIXOS2__)
static char xfilesearchpath[] = XFILESEARCHPATHDEFAULT;
static Bool fixed;
char *ch;
if (!fixed) {
for (ch = xfilesearchpath; ch = strchr(ch, ';'); ch++)
*ch = '%';
fixed = True;
}
return xfilesearchpath;
#else
return XFILESEARCHPATHDEFAULT;
#endif
}
static SubstitutionRec defaultSubs[] = {
{'N', NULL},
{'T', NULL},
{'S', NULL},
{'C', NULL},
{'L', NULL},
{'l', NULL},
{'t', NULL},
{'c', NULL}
};
String XtResolvePathname(
Display *dpy,
_Xconst char* type,
_Xconst char* filename,
_Xconst char* suffix,
_Xconst char* path,
Substitution substitutions,
Cardinal num_substitutions,
XtFilePredicate predicate)
{
XtPerDisplay pd;
static char *defaultPath = NULL;
char *impl_default = implementation_default_path();
int idef_len = strlen(impl_default);
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;
LOCK_PROCESS;
pd = _XtGetPerDisplay(dpy);
if (path == NULL) {
#ifndef VMS
if (defaultPath == NULL) {
defaultPath = getenv("XFILESEARCHPATH");
if (defaultPath == NULL)
defaultPath = impl_default;
}
path = defaultPath;
#else
path = "";
#endif
}
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;
while (*path != '\0') {
if (bytesLeft < idef_len) {
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;
}
if (*path == '%' && *(path+1) == 'D') {
strcpy(ch, impl_default);
ch += idef_len;
bytesLeft -= idef_len;
path += 2;
continue;
}
*ch++ = *path++;
bytesLeft--;
}
*ch = '\0';
#ifdef XNL_DEBUG
printf("Massaged path: %s\n", massagedPath);
#endif
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);
UNLOCK_PROCESS;
return result;
}
Boolean XtCallAcceptFocus(
Widget widget,
Time *time)
{
XtAcceptFocusProc ac;
Boolean retval;
WIDGET_TO_APPCON(widget);
LOCK_APP(app);
LOCK_PROCESS;
ac = XtClass(widget)->core_class.accept_focus;
UNLOCK_PROCESS;
if (ac != NULL)
retval = (*ac) (widget, time);
else
retval = FALSE;
UNLOCK_APP(app);
return retval;
}
#ifdef XT_GEO_TATTLER
#define XtNgeoTattler "geoTattler"
#define XtCGeoTattler "GeoTattler"
typedef struct { Boolean geo_tattler ;} GeoDataRec ;
static XtResource geo_resources[] = {
{ XtNgeoTattler, XtCGeoTattler, XtRBoolean, sizeof(Boolean),
XtOffsetOf(GeoDataRec, geo_tattler),
XtRImmediate, (XtPointer) False }
};
static Boolean IsTattled (Widget widget)
{
GeoDataRec geo_data ;
XtGetSubresources(widget, (XtPointer)&geo_data,
(String)NULL, (String)NULL,
geo_resources, XtNumber(geo_resources),
NULL, 0);
return geo_data.geo_tattler;
}
static int n_tab = 0 ;
void
_XtGeoTab (int direction)
{
n_tab += direction ;
}
void
_XtGeoTrace (Widget widget, ...)
{
va_list args;
char *fmt;
int i ;
if (IsTattled(widget)) {
va_start(args, widget);
fmt = va_arg(args, char *);
for (i=0; i<n_tab; i++) printf(" ");
(void) vprintf(fmt, args);
va_end(args);
}
}
#endif