16c321187Smrg/*
20cc2eac3Smrg
36c321187SmrgCopyright 1989, 1998  The Open Group
46c321187Smrg
56c321187SmrgPermission to use, copy, modify, distribute, and sell this software and its
66c321187Smrgdocumentation for any purpose is hereby granted without fee, provided that
76c321187Smrgthe above copyright notice appear in all copies and that both that
86c321187Smrgcopyright notice and this permission notice appear in supporting
96c321187Smrgdocumentation.
106c321187Smrg
116c321187SmrgThe above copyright notice and this permission notice shall be included in
126c321187Smrgall copies or substantial portions of the Software.
136c321187Smrg
146c321187SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
156c321187SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
166c321187SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
176c321187SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
186c321187SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
196c321187SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
206c321187Smrg
216c321187SmrgExcept as contained in this notice, the name of The Open Group shall not be
226c321187Smrgused in advertising or otherwise to promote the sale, use or other dealings
236c321187Smrgin this Software without prior written authorization from The Open Group.
246c321187Smrg
256c321187Smrg*/
266c321187Smrg
276c321187Smrg/*
286c321187Smrg * Author:  Jim Fulton, MIT X Consortium
296c321187Smrg */
306c321187Smrg
316c321187Smrg
326c321187Smrg
336c321187Smrg#ifdef HAVE_CONFIG_H
346c321187Smrg#include <config.h>
356c321187Smrg#endif
366c321187Smrg#include <stdio.h>
376c321187Smrg#include <stdlib.h>
386c321187Smrg#include <X11/Xos.h>
396c321187Smrg#include <X11/IntrinsicP.h>
406c321187Smrg#include <X11/Xmu/CharSet.h>
416c321187Smrg#include <X11/Xmu/WidgetNode.h>
426c321187Smrg
436c321187Smrg/*
446c321187Smrg * Prototypes
456c321187Smrg */
466c321187Smrgstatic char *binsearch(char*, char*, int, int,
476c321187Smrg		       int (*__compar)(_Xconst void*, _Xconst void*));
486c321187Smrgstatic int compare_resource_entries(_Xconst void *a,  _Xconst void *b);
499dedec0cSmrgstatic XmuWidgetNode *find_resource(XmuWidgetNode*, _Xconst char*, Bool);
506c321187Smrgstatic void mark_resource_owner(XmuWidgetNode*);
516c321187Smrg/*
526c321187Smrg * Implementation
536c321187Smrg */
546c321187Smrgstatic char *
556c321187Smrgbinsearch(char *key, char *base, int nelems, int elemsize,
566c321187Smrg	  int compar(_Xconst void*, _Xconst void*))
576c321187Smrg     /*
586c321187Smrg      * key		- template of object to find
596c321187Smrg      * base		- beginning of array
606c321187Smrg      * nelems		- number of elements in array
616c321187Smrg      * elemsize	- sizeof an element
626c321187Smrg      * compar		- qsort-style compare function
636c321187Smrg      */
646c321187Smrg{
656c321187Smrg    int lower = 0, upper = nelems - 1;
666c321187Smrg
676c321187Smrg    while (lower <= upper) {
686c321187Smrg	int middle = (lower + upper) / 2;
696c321187Smrg	char *p = base + middle * elemsize;
706c321187Smrg	int res = (*compar) (p, key);
716c321187Smrg
726c321187Smrg	if (res < 0) {
736c321187Smrg	    lower = middle + 1;
746c321187Smrg	} else if (res == 0) {
756c321187Smrg	    return p;
766c321187Smrg	} else {
776c321187Smrg	    upper = middle - 1;
786c321187Smrg	}
796c321187Smrg    }
806c321187Smrg
816c321187Smrg    return NULL;
826c321187Smrg}
836c321187Smrg
846c321187Smrg
856c321187Smrgstatic int
866c321187Smrgcompare_resource_entries(register _Xconst void *a,
876c321187Smrg			 register _Xconst void *b)
886c321187Smrg{
899d0b5e55Smrg    return strcmp (((_Xconst XtResource *)a)->resource_name,
909d0b5e55Smrg		   ((_Xconst XtResource *)b)->resource_name);
916c321187Smrg}
926c321187Smrg
936c321187Smrg
946c321187Smrgstatic XmuWidgetNode *
959dedec0cSmrgfind_resource(XmuWidgetNode *node, _Xconst char *name, Bool cons)
966c321187Smrg{
976c321187Smrg    register XmuWidgetNode *sup;
986c321187Smrg    XtResource res;
996c321187Smrg
1006c321187Smrg#define reslist ((char *) (cons ? sup->constraints : sup->resources))
1016c321187Smrg#define nreslist (int) (cons ? sup->nconstraints : sup->nresources)
1026c321187Smrg
1036c321187Smrg    res.resource_name = name;
1040cc2eac3Smrg    for (sup = node->superclass;
1056c321187Smrg	 sup && (XtResourceList) binsearch ((char *) &res,
1066c321187Smrg					    reslist, nreslist,
1076c321187Smrg					    sizeof(XtResource),
1086c321187Smrg					    compare_resource_entries);
1096c321187Smrg	 node = sup, sup = sup->superclass) ;
1106c321187Smrg
1116c321187Smrg#undef reslist
1126c321187Smrg#undef nreslist
1136c321187Smrg
1146c321187Smrg    return node;
1156c321187Smrg}
1166c321187Smrg
1176c321187Smrg
1186c321187Smrgstatic void
1196c321187Smrgmark_resource_owner(register XmuWidgetNode *node)
1206c321187Smrg{
1216c321187Smrg    register Cardinal i;
1226c321187Smrg    XtResourceList childres;
1236c321187Smrg
1246c321187Smrg    childres = node->resources;
1256c321187Smrg    for (i = 0; i < node->nresources; i++, childres++) {
1266c321187Smrg	node->resourcewn[i] = find_resource (node, childres->resource_name,
1276c321187Smrg					     False);
1286c321187Smrg    }
1296c321187Smrg
1306c321187Smrg    childres = node->constraints;
1316c321187Smrg    for (i = 0; i < node->nconstraints; i++, childres++) {
1326c321187Smrg	node->constraintwn[i] = find_resource (node, childres->resource_name,
1336c321187Smrg						True);
1346c321187Smrg    }
1356c321187Smrg}
1366c321187Smrg
1376c321187Smrg
1386c321187Smrg/*
1396c321187Smrg * 			       Public Interfaces
1406c321187Smrg */
1416c321187Smrg
1426c321187Smrgvoid
1436c321187SmrgXmuWnInitializeNodes(XmuWidgetNode *nodearray, int nnodes)
1446c321187Smrg{
1456c321187Smrg    int i;
1466c321187Smrg    XmuWidgetNode *wn;
1476c321187Smrg
1486c321187Smrg    /*
1496c321187Smrg     * Assume that the node array is in alphabetic order, so we need to
1506c321187Smrg     * search backwards to make sure that the children are listed forward.
1516c321187Smrg     */
1526c321187Smrg    for (i = nnodes - 1, wn = nodearray + (nnodes - 1); i >= 0; i--, wn--) {
1536c321187Smrg	WidgetClass superclass = XmuWnSuperclass(wn);
1546c321187Smrg	int j;
1556c321187Smrg	XmuWidgetNode *swn;
1566c321187Smrg	int lablen = strlen (wn->label);
1576c321187Smrg	int namelen = strlen (XmuWnClassname(wn));
1586c321187Smrg
1596c321187Smrg	wn->lowered_label = XtMalloc (lablen + namelen + 2);
1606c321187Smrg#if 0
1616c321187Smrg	/* XtMalloc exits if failed */
1626c321187Smrg	if (!wn->lowered_label) {
1636c321187Smrg	    fprintf (stderr,
1646c321187Smrg		     "%s:  unable to allocate %d bytes for widget name\n",
1656c321187Smrg		     "XmuWnInitializeNodes", lablen + namelen + 2);
1666c321187Smrg	    exit (1);
1676c321187Smrg	}
1686c321187Smrg#endif
1696c321187Smrg	wn->lowered_classname = wn->lowered_label + (lablen + 1);
1706c321187Smrg	XmuCopyISOLatin1Lowered (wn->lowered_label, wn->label);
1716c321187Smrg	XmuCopyISOLatin1Lowered (wn->lowered_classname, XmuWnClassname(wn));
1726c321187Smrg	wn->superclass = NULL;
1736c321187Smrg	wn->have_resources = False;
1746c321187Smrg	wn->resources = NULL;
1756c321187Smrg	wn->resourcewn = NULL;
1766c321187Smrg	wn->nresources = 0;
1776c321187Smrg	wn->constraints = NULL;
1786c321187Smrg	wn->constraintwn = NULL;
1796c321187Smrg	wn->nconstraints = 0;
1806c321187Smrg	wn->data = (XtPointer) NULL;
1816c321187Smrg
1826c321187Smrg	/*
1836c321187Smrg	 * walk up the superclass chain
1846c321187Smrg	 */
1856c321187Smrg	while (superclass) {
1866c321187Smrg	    for (j = 0, swn = nodearray; j < nnodes; j++, swn++) {
1876c321187Smrg		if (superclass == XmuWnClass(swn)) {
1886c321187Smrg		    wn->superclass = swn;
1896c321187Smrg		    goto done;		/* stupid C language */
1906c321187Smrg	        }
1916c321187Smrg	    }
1926c321187Smrg	    /*
1936c321187Smrg	     * Hmm, we have a hidden superclass (such as in core in R4); just
1946c321187Smrg	     * ignore it and keep on walking
1956c321187Smrg	     */
1966c321187Smrg	    superclass = superclass->core_class.superclass;
1976c321187Smrg	}
1980cc2eac3Smrg      done:
1996c321187Smrg	if (wn->superclass) {
2006c321187Smrg	    wn->siblings = wn->superclass->children;
2016c321187Smrg	    wn->superclass->children = wn;
2026c321187Smrg	}
2036c321187Smrg    }
2046c321187Smrg
2056c321187Smrg    return;
2066c321187Smrg}
2076c321187Smrg
2086c321187Smrg
2096c321187Smrgvoid
2106c321187SmrgXmuWnFetchResources(XmuWidgetNode *node, Widget toplevel,
2116c321187Smrg		    XmuWidgetNode *topnode)
2126c321187Smrg{
2136c321187Smrg    Widget dummy;
2146c321187Smrg    XmuWidgetNode *wn;
2156c321187Smrg
2166c321187Smrg    if (node->have_resources) return;
2176c321187Smrg
2186c321187Smrg    dummy = XtCreateWidget (node->label, XmuWnClass(node), toplevel,
2196c321187Smrg			    NULL, 0);
2206c321187Smrg    if (dummy) XtDestroyWidget (dummy);
2216c321187Smrg
2226c321187Smrg
2236c321187Smrg    /*
2249dedec0cSmrg     * walk up tree getting resources; since we've instantiated the widget,
2256c321187Smrg     * we know that all of our superclasses have been initialized
2266c321187Smrg     */
2276c321187Smrg    for (wn = node; wn && !wn->have_resources; wn = wn->superclass) {
2286c321187Smrg	XtGetResourceList (XmuWnClass(wn), &wn->resources, &wn->nresources);
2296c321187Smrg	if (wn->resources) {
2306c321187Smrg	    qsort ((char *) wn->resources, wn->nresources,
2316c321187Smrg		   sizeof(XtResource), compare_resource_entries);
2326c321187Smrg	}
2336c321187Smrg	wn->resourcewn = (XmuWidgetNode **) XtCalloc (wn->nresources,
2346c321187Smrg						  sizeof (XmuWidgetNode *));
2356c321187Smrg	if (!wn->resourcewn) {
2366c321187Smrg	    fprintf (stderr,
2376c321187Smrg		     "%s:  unable to calloc %d %ld byte widget node ptrs\n",
2386c321187Smrg		     "XmuWnFetchResources", wn->nresources,
2396c321187Smrg		     (unsigned long)sizeof (XmuWidgetNode *));
2406c321187Smrg	    exit (1);
2416c321187Smrg	}
2426c321187Smrg
2436c321187Smrg	XtGetConstraintResourceList (XmuWnClass(wn), &wn->constraints,
2446c321187Smrg				     &wn->nconstraints);
2456c321187Smrg	if (wn->constraints) {
2466c321187Smrg	    qsort ((char *) wn->constraints, wn->nconstraints,
2476c321187Smrg		   sizeof(XtResource), compare_resource_entries);
2486c321187Smrg	}
2496c321187Smrg	wn->constraintwn = (XmuWidgetNode **)
2506c321187Smrg	  XtCalloc (wn->nconstraints, sizeof (XmuWidgetNode *));
2516c321187Smrg	if (!wn->constraintwn) {
2526c321187Smrg	    fprintf (stderr,
2536c321187Smrg		     "%s:  unable to calloc %d %ld byte widget node ptrs\n",
2546c321187Smrg		     "XmuWnFetchResources", wn->nconstraints,
2556c321187Smrg		     (unsigned long)sizeof (XmuWidgetNode *));
2566c321187Smrg	    exit (1);
2576c321187Smrg	}
2586c321187Smrg
2596c321187Smrg	wn->have_resources = True;
2606c321187Smrg	if (wn == topnode) break;
2616c321187Smrg    }
2626c321187Smrg
2636c321187Smrg
2646c321187Smrg    /*
2656c321187Smrg     * Walk up tree removing all resources that appear in superclass; we can
2666c321187Smrg     * mash the resource list in place since it was copied out of widget.
2676c321187Smrg     */
2686c321187Smrg    for (wn = node; wn; wn = wn->superclass) {
2696c321187Smrg	mark_resource_owner (wn);
2706c321187Smrg	if (wn == topnode) break;
2716c321187Smrg    }
2726c321187Smrg
2736c321187Smrg    return;
2746c321187Smrg}
2756c321187Smrg
2766c321187Smrg
2776c321187Smrgint
2786c321187SmrgXmuWnCountOwnedResources(XmuWidgetNode *node, XmuWidgetNode *ownernode,
2796c321187Smrg			 Bool cons)
2806c321187Smrg{
2816c321187Smrg    register int i;
2826c321187Smrg    XmuWidgetNode **wn = (cons ? node->constraintwn : node->resourcewn);
2836c321187Smrg    int nmatches = 0;
2846c321187Smrg
2856c321187Smrg    for (i = (cons ? node->nconstraints : node->nresources); i > 0; i--, wn++)
2866c321187Smrg      if (*wn == ownernode) nmatches++;
2876c321187Smrg    return nmatches;
2886c321187Smrg}
2896c321187Smrg
2906c321187Smrg
2916c321187SmrgXmuWidgetNode *
2926c321187SmrgXmuWnNameToNode(XmuWidgetNode *nodelist, int nnodes, _Xconst char *name)
2936c321187Smrg{
2946c321187Smrg    int i;
2956c321187Smrg    XmuWidgetNode *wn;
2966c321187Smrg    char tmp[1024];
2976c321187Smrg
2986c321187Smrg    XmuNCopyISOLatin1Lowered(tmp, name, sizeof(tmp));
2996c321187Smrg    for (i = 0, wn = nodelist; i < nnodes; i++, wn++) {
3006c321187Smrg	if (strcmp (tmp, wn->lowered_label) == 0 ||
3016c321187Smrg	    strcmp (tmp, wn->lowered_classname) == 0) {
3026c321187Smrg	  return wn;
3036c321187Smrg	}
3046c321187Smrg    }
3056c321187Smrg    return NULL;
3066c321187Smrg}
307