#define RESOURCES_C
#include "wafe.h"

#ifdef MOTIF11
#include <Xm/Xm.h>
#endif

typedef struct _RESINFO
     {
     WidgetClass       wClass;
     QTypeList         resources;
     Cardinal          num;
     struct _RESINFO  *next;
     } RESINFO, *RESINFOPTR;

static RESINFOPTR  resourceList = NULL;
static RESINFOPTR  constraintList = NULL;

/*
 * The following function returns the address from the corresponding
 * attribute/type list.
 */

extern
addResInfo *
wafeGetAdditionalResources(
#if NeedFunctionPrototypes
     WidgetClass, Cardinal *
#endif
);

#ifdef ATHENA
#include <X11/Xaw/AsciiText.h>
#endif

/*****************************************************************************
 *  The following functions maintain the global lists of ResourceLists, 
 *  one for normal widgets and one for constraint resources. They look up the
 *  resources registered for a specified widget class and - if they are 
 *  queried for the first time - append the new resourceList. In each 
 *  appended resourceList, the string name of the resource will be 
 *  substituted by a quark representation.
 *****************************************************************************/

static QTypeList
resList2QTypeList(rList, rNum, addResPtr, addNum, secondaryRes, numSecondary,
		  total)
XtResourceList  rList;
int   rNum;
addResInfo *addResPtr;
Cardinal   addNum;
#ifdef MOTIF12
XmSecondaryResourceData* secondaryRes;
#else
XtPointer* secondaryRes;
#endif
Cardinal numSecondary;
Cardinal *total;
    {
    int i, sNum = 0;
    QTypeList  returnList, ptr;

#ifdef MOTIF12
    XmSecondaryResourceData* sRes;
    
    for (sRes = secondaryRes, i = numSecondary; 
	 i > 0; 
	 sNum += (*sRes)->num_resources, sRes++, i--);
#endif

    returnList = ptr = 
	(QTypeList) XtMalloc((rNum + addNum + sNum) * sizeof(QType) + 1);

    for (i = 0; i < addNum; i++)
	{
	ptr->qName = XrmStringToQuark(addResPtr[i].resource_name);
	/*fprintf(stderr,"add resname = <%s>\n",addResPtr[i].resource_name);*/
	ptr->type =  addResPtr[i].resource_type;
	ptr->qType = WafePermStringToQuark(ptr->type);
	ptr++;
	}

#ifdef MOTIF12
    /*fprintf(stderr,"num secondary=%d\n",numSecondary);*/
    for (sRes=secondaryRes, i=numSecondary;  i>0;  sRes++, i--)
	{
	XmSecondaryResourceData block = *sRes;
	XtResourceList rl = block->resources;
	int n = block->num_resources;
	for ( ; n > 0; n--, rl++)
	    {
	    ptr->qName = XrmStringToQuark(rl->resource_name);
	    /*fprintf(stderr,"secondary resname = <%s>\n",rl->resource_name);*/
	    ptr->type =  XtNewString(rl->resource_type);
	    ptr->qType = WafePermStringToQuark(ptr->type);
	    ptr++;
	    }
	XtFree((char*)block->resources);
	XtFree((char*)block);
	/*fprintf(stderr,"----------------------------- next secondary\n");*/
	}
    if (numSecondary) XtFree((char*)secondaryRes);
#endif

    for (i = 0; i < rNum; i++)
	{
	ptr->qName = XrmStringToQuark(rList[i].resource_name);
	ptr->type =  XtNewString(rList[i].resource_type);
	ptr->qType = WafePermStringToQuark(ptr->type);
	ptr++;
	}

    XtFree((char *)rList);
    *total = rNum + addNum + sNum;
    return(returnList);
    }



Cardinal
wafeGetResourcesOfClass(wClass, qList)
WidgetClass wClass;
QTypeList  *qList;
    {
    Cardinal  num;
    RESINFOPTR  ptr, lptr;
    XtResourceList resListPtr;
    addResInfo *addResPtr;
    Cardinal    addNum, nrSecondaryResources;
    Boolean     disposeAddResPtr = False;

#ifdef MOTIF12
    XmSecondaryResourceData *secondaryRes;
#else
    XtPointer *secondaryRes = NULL;
#endif    
    
    if (resourceList)  /* there exist already some entries */
	{
	for (lptr = resourceList; 
	     lptr != NULL; 
	     ptr = lptr, lptr = lptr->next) 
	    if (lptr->wClass == wClass)
		{
		*qList = lptr->resources;
		return(lptr->num);
		}
	ptr->next = (RESINFOPTR) XtMalloc(sizeof(RESINFO));
	ptr = ptr->next;
	}
    else
	ptr = resourceList = (RESINFOPTR) XtMalloc(sizeof(RESINFO));
        
    ptr->next = NULL;
    ptr->wClass = wClass;

    XtInitializeWidgetClass(wClass);  /* Just in case it is not yet done... */
    nrSecondaryResources = 
#ifdef MOTIF12
	XmGetSecondaryResourceData(wClass,&secondaryRes);
#else
        0;
#endif    
    XtGetResourceList(wClass, &resListPtr, &num);
    
#ifdef ATHENA
    /* fetch ATHENA AsciiText's subpart resources here! */

    if (wClass == asciiTextWidgetClass)  /* check asciiText's subresources */
	{
	XtResourceList rList[2], rl;
	Cardinal       rNum[2];
	addResInfo    *ptr;
	int            i,j;
	
	XtInitializeWidgetClass(asciiSinkObjectClass);
	XtInitializeWidgetClass(asciiSrcObjectClass);

	XtGetResourceList(asciiSinkObjectClass, &rList[0], &rNum[0]);
	XtGetResourceList(asciiSrcObjectClass, &rList[1], &rNum[1]);

	addNum = rNum[0] + rNum[1];
	addResPtr = (addResInfo *)XtMalloc( (addNum+1)*sizeof(addResInfo));

	for(i=0, ptr=addResPtr; i<2; i++) 
	    for(j=0, rl=rList[i], j=rNum[i]; j>0; j--, rl++, ptr++)
		{
		ptr->resource_name = XtNewString(rl->resource_name);
		ptr->resource_type = XtNewString(rl->resource_type);
		}
        /* *addResPtr  would be wasted, since the values are copied */
	disposeAddResPtr = True;
	}
    else
	{
	addResPtr = Nil(addResInfo);
	addNum = 0;
	}

#else
    addResPtr = wafeGetAdditionalResources(wClass, &addNum);
#endif

    *qList = 
	ptr->resources = 
	    resList2QTypeList(resListPtr, num, 
			      addResPtr, addNum, 
			      secondaryRes, nrSecondaryResources, 
			      &(ptr->num));

    if (disposeAddResPtr) 
	XtFree((char *) addResPtr);

    return ptr->num;
    } 

Cardinal
wafeGetConstraintsOfClass(wClass, qList)
WidgetClass wClass;
QTypeList  *qList;
    {
    Cardinal  num;
    RESINFOPTR  ptr, lptr;
    XtResourceList conListPtr;

    if (constraintList)  /* there exist already some entries */
	{
	for (lptr = constraintList; lptr != NULL; ptr = lptr, lptr = lptr->next) 
	    if (lptr->wClass == wClass)
		{
		*qList = lptr->resources;
		return(lptr->num);
		}
	ptr->next = (RESINFOPTR) XtMalloc(sizeof(RESINFO));
	ptr = ptr->next;
	}
    else
	ptr = constraintList = (RESINFOPTR) XtMalloc(sizeof(RESINFO));
        
    ptr->next = NULL;
    ptr->wClass = wClass;

    XtGetConstraintResourceList(wClass, &conListPtr, &num);

    *qList = 
	ptr->resources = 
	    resList2QTypeList(conListPtr, num, NULL,0, NULL, 0, &(ptr->num));
    return(ptr->num);
    } 



/*****************************************************************************
 *  FUNCTION:  wafeGetQTypeOfAttribute 
 *                                  
 *  Arguments: Widgetclass, parent widget and Quark of attribute to be queried.
 *  Returns:   Type of the attribute as a Quark or NULL.                     
 *                                                                      
 *  Used by    getValues, convert 
 *
 * Vielleicht wäre es besser, eine Struktur mit einem String und einem Quark
 * zu retournieren, um ein etwaiges Zurückumwandeln zu ersparen. 
 * Dringlichkeitsstufe: 0
 *****************************************************************************/

XrmQuark
wafeGetQTypeOfAttribute(wClass, parent, qAttribute)
WidgetClass     wClass;
Widget          parent;
XrmQuark        qAttribute;
    {
    QTypeList    resList;
    int          count;

 /* Check standard resources of this class */
    for (count = wafeGetResourcesOfClass(wClass, &resList); 
	 count>0; 
	 count--, resList++)
      if (qAttribute == resList->qName)
	return(resList->qType);
    
    if (XtIsConstraint(parent))    /* check Constraints if there are any... */
	{
	for (count = wafeGetConstraintsOfClass(XtClass(parent), &resList);
             count>0; count--, resList++)
	    if (qAttribute == resList->qName)
		return(resList->qType);
	}
/*
    else if (XtIsShell(parent)) 
	{
	count = wafeGetResourcesOfClass(XtClass(parent), &resList);

	for (i = 0; i < count; i++, resList++)
	    if (qAttribute == resList->qName)
		return(resList->qType);
	}
*/

    return((XrmQuark)NULL); 
    }

