#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xos.h>
#include <X11/IntrinsicP.h>
#include <X11/Xmu/CharSet.h>
#include <X11/Xmu/WidgetNode.h>
static char *binsearch(char*, char*, int, int,
int (*__compar)(_Xconst void*, _Xconst void*));
static int compare_resource_entries(_Xconst void *a, _Xconst void *b);
static XmuWidgetNode *find_resource(XmuWidgetNode*, char*, Bool);
static void mark_resource_owner(XmuWidgetNode*);
static char *
binsearch(char *key, char *base, int nelems, int elemsize,
int compar(_Xconst void*, _Xconst void*))
{
int lower = 0, upper = nelems - 1;
while (lower <= upper) {
int middle = (lower + upper) / 2;
char *p = base + middle * elemsize;
int res = (*compar) (p, key);
if (res < 0) {
lower = middle + 1;
} else if (res == 0) {
return p;
} else {
upper = middle - 1;
}
}
return NULL;
}
static int
compare_resource_entries(register _Xconst void *a,
register _Xconst void *b)
{
return strcmp (((XtResourceList)a)->resource_name,
((XtResourceList)b)->resource_name);
}
static XmuWidgetNode *
find_resource(XmuWidgetNode *node, char *name, Bool cons)
{
register XmuWidgetNode *sup;
XtResource res;
#define reslist ((char *) (cons ? sup->constraints : sup->resources))
#define nreslist (int) (cons ? sup->nconstraints : sup->nresources)
res.resource_name = name;
for (sup = node->superclass;
sup && (XtResourceList) binsearch ((char *) &res,
reslist, nreslist,
sizeof(XtResource),
compare_resource_entries);
node = sup, sup = sup->superclass) ;
#undef reslist
#undef nreslist
return node;
}
static void
mark_resource_owner(register XmuWidgetNode *node)
{
register Cardinal i;
XtResourceList childres;
childres = node->resources;
for (i = 0; i < node->nresources; i++, childres++) {
node->resourcewn[i] = find_resource (node, childres->resource_name,
False);
}
childres = node->constraints;
for (i = 0; i < node->nconstraints; i++, childres++) {
node->constraintwn[i] = find_resource (node, childres->resource_name,
True);
}
}
void
XmuWnInitializeNodes(XmuWidgetNode *nodearray, int nnodes)
{
int i;
XmuWidgetNode *wn;
for (i = nnodes - 1, wn = nodearray + (nnodes - 1); i >= 0; i--, wn--) {
WidgetClass superclass = XmuWnSuperclass(wn);
int j;
XmuWidgetNode *swn;
int lablen = strlen (wn->label);
int namelen = strlen (XmuWnClassname(wn));
wn->lowered_label = XtMalloc (lablen + namelen + 2);
#if 0
if (!wn->lowered_label) {
fprintf (stderr,
"%s: unable to allocate %d bytes for widget name\n",
"XmuWnInitializeNodes", lablen + namelen + 2);
exit (1);
}
#endif
wn->lowered_classname = wn->lowered_label + (lablen + 1);
XmuCopyISOLatin1Lowered (wn->lowered_label, wn->label);
XmuCopyISOLatin1Lowered (wn->lowered_classname, XmuWnClassname(wn));
wn->superclass = NULL;
wn->have_resources = False;
wn->resources = NULL;
wn->resourcewn = NULL;
wn->nresources = 0;
wn->constraints = NULL;
wn->constraintwn = NULL;
wn->nconstraints = 0;
wn->data = (XtPointer) NULL;
while (superclass) {
for (j = 0, swn = nodearray; j < nnodes; j++, swn++) {
if (superclass == XmuWnClass(swn)) {
wn->superclass = swn;
goto done;
}
}
superclass = superclass->core_class.superclass;
}
done:
if (wn->superclass) {
wn->siblings = wn->superclass->children;
wn->superclass->children = wn;
}
}
return;
}
void
XmuWnFetchResources(XmuWidgetNode *node, Widget toplevel,
XmuWidgetNode *topnode)
{
Widget dummy;
XmuWidgetNode *wn;
if (node->have_resources) return;
dummy = XtCreateWidget (node->label, XmuWnClass(node), toplevel,
NULL, 0);
if (dummy) XtDestroyWidget (dummy);
for (wn = node; wn && !wn->have_resources; wn = wn->superclass) {
XtGetResourceList (XmuWnClass(wn), &wn->resources, &wn->nresources);
if (wn->resources) {
qsort ((char *) wn->resources, wn->nresources,
sizeof(XtResource), compare_resource_entries);
}
wn->resourcewn = (XmuWidgetNode **) XtCalloc (wn->nresources,
sizeof (XmuWidgetNode *));
if (!wn->resourcewn) {
fprintf (stderr,
"%s: unable to calloc %d %ld byte widget node ptrs\n",
"XmuWnFetchResources", wn->nresources,
(unsigned long)sizeof (XmuWidgetNode *));
exit (1);
}
XtGetConstraintResourceList (XmuWnClass(wn), &wn->constraints,
&wn->nconstraints);
if (wn->constraints) {
qsort ((char *) wn->constraints, wn->nconstraints,
sizeof(XtResource), compare_resource_entries);
}
wn->constraintwn = (XmuWidgetNode **)
XtCalloc (wn->nconstraints, sizeof (XmuWidgetNode *));
if (!wn->constraintwn) {
fprintf (stderr,
"%s: unable to calloc %d %ld byte widget node ptrs\n",
"XmuWnFetchResources", wn->nconstraints,
(unsigned long)sizeof (XmuWidgetNode *));
exit (1);
}
wn->have_resources = True;
if (wn == topnode) break;
}
for (wn = node; wn; wn = wn->superclass) {
mark_resource_owner (wn);
if (wn == topnode) break;
}
return;
}
int
XmuWnCountOwnedResources(XmuWidgetNode *node, XmuWidgetNode *ownernode,
Bool cons)
{
register int i;
XmuWidgetNode **wn = (cons ? node->constraintwn : node->resourcewn);
int nmatches = 0;
for (i = (cons ? node->nconstraints : node->nresources); i > 0; i--, wn++)
if (*wn == ownernode) nmatches++;
return nmatches;
}
XmuWidgetNode *
XmuWnNameToNode(XmuWidgetNode *nodelist, int nnodes, _Xconst char *name)
{
int i;
XmuWidgetNode *wn;
char tmp[1024];
XmuNCopyISOLatin1Lowered(tmp, name, sizeof(tmp));
for (i = 0, wn = nodelist; i < nnodes; i++, wn++) {
if (strcmp (tmp, wn->lowered_label) == 0 ||
strcmp (tmp, wn->lowered_classname) == 0) {
return wn;
}
}
return NULL;
}