/*****************************************************************************
* Setting attributes for objects.					     *
******************************************************************************
* (C) Gershon Elber, Technion, Israel Institute of Technology                *
******************************************************************************
* Written by:  Gershon Elber				Ver 0.2, Mar. 1990   *
*****************************************************************************/

#include <string.h>
#include <stdio.h>
#include <math.h>
#include "irit_sm.h"
#include "imalloc.h"
#include "miscattr.h"

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to set a color attribute.					     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:     Where to place the color attribute.                           M
*   Color:     New color.		                                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* SEE ALSO:                                                                  M
*   AttrGetColor, AttrSetRGBColor, AttrGetRGBColor, AttrSetWidth,            M
*   AttrGetWidth, AttrSetIntAttrib, AttrSetObjectColor			     M
*                                                                	     *
* KEYWORDS:                                                                  M
*   AttrSetColor, attributes, color	                                     M
*****************************************************************************/
void AttrSetColor(IPAttributeStruct **Attrs, int Color)
{
    AttrSetIntAttrib(Attrs, "color", Color);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to return a color attribute.					     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:     For which we would like to know the color of.                 M
*                                                                            *
* RETURN VALUE:                                                              M
*   int:      Color or IP_ATTR_NO_COLOR if no color set.	             M
*                                                                            *
* SEE ALSO:                                                                  M
*   AttrSetColor, AttrSetRGBColor, AttrGetRGBColor, AttrSetWidth,	     M
*   AttrGetWidth, AttrGetIntAttrib, AttrGetObjectColor			     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrGetColor, attributes, color 	                                     M
*****************************************************************************/
int AttrGetColor(IPAttributeStruct *Attrs)
{
    IPAttributeStruct
	*Attr = AttrFindAttribute(Attrs, "color");

    if (Attr != NULL) {
	if (Attr -> Type == IP_ATTR_INT)
	    return Attr -> U.I;
	else if (Attr -> Type == IP_ATTR_STR)
	    return atoi(Attr -> U.Str);
	else
	    return IP_ATTR_NO_COLOR;
    }
    else
        return IP_ATTR_NO_COLOR;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to set an RGB color attribute.				     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:		Where to place the TGB color attribute.              M
*   Red, Green, Blue:   Component of RGB color.                              M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* SEE ALSO:                                                                  M
*   AttrSetColor, AttrGetColor, AttrGetRGBColor, AttrSetWidth, AttrGetWidth, M
*   AttrSetIntAttrib, AttrSetObjectRGBColor				     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrSetRGBColor, attributes, color, rgb                                  M
*****************************************************************************/
void AttrSetRGBColor(IPAttributeStruct **Attrs, int Red, int Green, int Blue)
{
    char SRGB[30];

    sprintf(SRGB, "%d,%d,%d", Red, Green, Blue);

    AttrSetStrAttrib(Attrs, "rgb", SRGB);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to return a RGB attribute.				     	     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:     		For which we would like to know the RGB of.          M
*   Red, Green, Blue:   Component of RGB color to initialize.                M
*                                                                            *
* RETURN VALUE:                                                              M
*   int:     TRUE if does have an RGB color attribute, FALSE otherwise.      M
*                                                                            *
* SEE ALSO:                                                                  M
*   AttrSetColor, AttrGetColor, AttrSetRGBColor, AttrSetWidth, AttrGetWidth, M
*   AttrSetIntAttrib, AttrGetObjectRGBColor				     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrGetRGBColor, attributes, color, rgb	                             M
*****************************************************************************/
int AttrGetRGBColor(IPAttributeStruct *Attrs, int *Red, int *Green, int *Blue)
{
    char
	*p = AttrGetStrAttrib(Attrs, "rgb");

    return p != NULL && sscanf(p, "%d,%d,%d", Red, Green, Blue) == 3;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to set a width attribute.					     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:     Where to place the width attribute.                           M
*   Width:     New width.		                                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* SEE ALSO:                                                                  M
*   AttrSetColor, AttrGetColor, AttrSetRGBColor, AttrGetRGBColor,            M
*   AttrGetWidth, AttrSetRealAttrib, AttrSetObjectWidth			     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrSetWidth, attributes, width	                                     M
*****************************************************************************/
void AttrSetWidth(IPAttributeStruct **Attrs, RealType Width)
{
    AttrSetRealAttrib(Attrs, "width", Width);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to return a width attribute.					     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:     For which we would like to know the width of.                 M
*                                                                            *
* RETURN VALUE:                                                              M
*   RealType:  Width or IP_ATTR_NO_WIDTH if no width set.	             M
*                                                                            *
* SEE ALSO:                                                                  M
*   AttrSetColor, AttrGetColor, AttrSetRGBColor, AttrGetRGBColor,            M
*   AttrSetWidth, AttrGetRealAttrib, AttrGetObjectWidth			     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrGetWidth, attributes, width 	                                     M
*****************************************************************************/
RealType AttrGetWidth(IPAttributeStruct *Attrs)
{
    IPAttributeStruct
	*Attr = AttrFindAttribute(Attrs, "width");

    if (Attr != NULL) {
	if (Attr -> Type == IP_ATTR_REAL)
	    return Attr -> U.R;
	else if (Attr -> Type == IP_ATTR_STR) {
	    RealType r;

	    sscanf("%lf", Attr -> U.Str, &r);
	    return r;
	}
	else
	    return IP_ATTR_NO_WIDTH;
    }
    else
        return IP_ATTR_NO_WIDTH;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Routine to set an integer attribute.				     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:     Attribute list where to place new attribute.                  M
*   Name:      Name of thely introducedattribute                             M
*   Data:      Ingeter attribute to save.                                    M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* SEE ALSO:                                                                  M
*   AttrGetIntAttrib, AttrSetPtrAttrib, AttrGetPtrAttrib, AttrSetRealAttrib, M
*   AttrGetRealAttrib, AttrSetStrAttrib, AttrGetStrAttrib		     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrSetIntAttrib, attributes                                             M
*****************************************************************************/
void AttrSetIntAttrib(IPAttributeStruct **Attrs, char *Name, int Data)
{
    IPAttributeStruct
        *Attr = AttrFindAttribute(*Attrs, Name);
    
    if (Attr) {
	_AttrFreeAttributeData(Attr);
	Attr -> U.I = Data;
	Attr -> Type = IP_ATTR_INT;
    }
    else {
	Attr = _AttrMallocAttribute(Name, IP_ATTR_INT);
	Attr -> U.I = Data;
	Attr -> Pnext = *Attrs;
	*Attrs = Attr;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Routine to get an integer attribute.				     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:    Attribute list to search for requested attribute.              M
*   Name:     Name of requested attribute.                                   M
*                                                                            *
* RETURN VALUE:                                                              M
*   int:      Found attribute, or IP_ATTR_BAD_INT if not found.              M
*                                                                            *
* SEE ALSO:                                                                  M
*   AttrSetIntAttrib, AttrSetPtrAttrib, AttrGetPtrAttrib, AttrSetRealAttrib, M
*   AttrGetRealAttrib, AttrSetStrAttrib, AttrGetStrAttrib		     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrGetIntAttrib, attributes                                             M
*****************************************************************************/
int AttrGetIntAttrib(IPAttributeStruct *Attrs, char *Name)
{
    IPAttributeStruct
	*Attr = AttrFindAttribute(Attrs, Name);

    if (Attr != NULL) {
	if (Attr -> Type == IP_ATTR_INT)
	    return Attr -> U.I;
	else if (Attr -> Type == IP_ATTR_REAL)
	    return (int) Attr -> U.R;
	else if (Attr -> Type == IP_ATTR_STR)
	    return atoi(Attr -> U.Str);
    }

    return IP_ATTR_BAD_INT;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Routine to set a pointer attribute.		 			     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:     Attribute list where to place new attribute.                  M
*   Name:      Name of thely introducedattribute                             M
*   Data:      Pointer attribute to save.                                    M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* SEE ALSO:                                                                  M
*   AttrSetIntAttrib, AttrGetIntAttrib, AttrGetPtrAttrib, AttrSetRealAttrib, M
*   AttrGetRealAttrib, AttrSetStrAttrib, AttrGetStrAttrib		     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrSetPtrAttrib, attributes                                             M
*****************************************************************************/
void AttrSetPtrAttrib(IPAttributeStruct **Attrs, char *Name, VoidPtr Data)
{
    IPAttributeStruct
        *Attr = AttrFindAttribute(*Attrs, Name);

    if (Attr) {
	_AttrFreeAttributeData(Attr);
	Attr -> U.Ptr = Data;
	Attr -> Type = IP_ATTR_PTR;
    }
    else {
	Attr = _AttrMallocAttribute(Name, IP_ATTR_PTR);
	Attr -> U.Ptr = Data;
	Attr -> Pnext = *Attrs;
	*Attrs = Attr;
    }
}
/*****************************************************************************
* DESCRIPTION:                                                               M
*   Routine to get a pointer attribute.					     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:    Attribute list to search for requested attribute.              M
*   Name:     Name of requested attribute.                                   M
*                                                                            *
* RETURN VALUE:                                                              M
*   VoidPtr: Found attribute, or NULL if not found. 		             M
*                                                                            *
* SEE ALSO:                                                                  M
*   AttrSetIntAttrib, AttrGetIntAttrib, AttrSetPtrAttrib, AttrSetRealAttrib, M
*   AttrGetRealAttrib, AttrSetStrAttrib, AttrGetStrAttrib		     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrGetPtrAttrib, attributes                                             M
*****************************************************************************/
VoidPtr AttrGetPtrAttrib(IPAttributeStruct *Attrs, char *Name)
{
    IPAttributeStruct
	*Attr = AttrFindAttribute(Attrs, Name);

    if (Attr != NULL && Attr -> Type == IP_ATTR_PTR)
        return Attr -> U.Ptr;
    else
        return NULL;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Routine to set a RealType attribute.				     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:     Attribute list where to place new attribute.                  M
*   Name:      Name of thely introducedattribute                             M
*   Data:      RealType attribute to save.                                   M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* SEE ALSO:                                                                  M
*   AttrSetIntAttrib, AttrGetIntAttrib, AttrSetPtrAttrib, AttrGetPtrAttrib,  M
*   AttrGetRealAttrib, AttrSetStrAttrib, AttrGetStrAttrib		     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrSetRealAttrib, attributes                                            M
*****************************************************************************/
void AttrSetRealAttrib(IPAttributeStruct **Attrs, char *Name, RealType Data)
{
    IPAttributeStruct
        *Attr = AttrFindAttribute(*Attrs, Name);
    
    if (Attr) {
	_AttrFreeAttributeData(Attr);
	Attr -> U.R = Data;
	Attr -> Type = IP_ATTR_REAL;
    }
    else {
	Attr = _AttrMallocAttribute(Name, IP_ATTR_REAL);
	Attr -> U.R = Data;
	Attr -> Pnext = *Attrs;
	*Attrs = Attr;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Routine to get a RealType attribute.				     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:    Attribute list to search for requested attribute.              M
*   Name:     Name of requested attribute.                                   M
*                                                                            *
* RETURN VALUE:                                                              M
*   RealType: Found attribute, or IP_ATTR_BAD_REAL if not found.             M
*                                                                            *
* SEE ALSO:                                                                  M
*   AttrSetIntAttrib, AttrGetIntAttrib, AttrSetPtrAttrib, AttrGetPtrAttrib,  M
*   AttrSetRealAttrib, AttrSetStrAttrib, AttrGetStrAttrib,		     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrGetRealAttrib, attributes                                            M
*****************************************************************************/
RealType AttrGetRealAttrib(IPAttributeStruct *Attrs, char *Name)
{
    IPAttributeStruct
	*Attr = AttrFindAttribute(Attrs, Name);

    if (Attr != NULL) {
	if (Attr -> Type == IP_ATTR_REAL)
	    return Attr -> U.R;
	else if (Attr -> Type == IP_ATTR_INT)
	    return (RealType) Attr -> U.I;
	else if (Attr -> Type == IP_ATTR_STR) {
	    RealType r;

	    sscanf("%lf", Attr -> U.Str, &r);
	    return r;
	}
    }

    return IP_ATTR_BAD_REAL * 10;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Routine to set a string attribute.					     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:     Attribute list where to place new attribute.                  M
*   Name:      Name of thely introducedattribute                             M
*   Data:      String attribute to save.                                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* SEE ALSO:                                                                  M
*   AttrSetIntAttrib, AttrGetIntAttrib, AttrSetPtrAttrib, AttrGetPtrAttrib,  M
*   AttrSetRealAttrib, AttrGetRealAttrib, AttrGetStrAttrib		     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrSetStrAttrib, attributes                                             M
*****************************************************************************/
void AttrSetStrAttrib(IPAttributeStruct **Attrs, char *Name, char *Data)
{
    IPAttributeStruct
        *Attr = AttrFindAttribute(*Attrs, Name);

    if (Attr) {
	_AttrFreeAttributeData(Attr);
	Attr -> U.Str = IritStrdup(Data);
	Attr -> Type = IP_ATTR_STR;
    }
    else {
	Attr = _AttrMallocAttribute(Name, IP_ATTR_STR);
	Attr -> U.Str = IritStrdup(Data);
	Attr -> Pnext = *Attrs;
	*Attrs = Attr;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Routine to get a string attribute.					     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:    Attribute list to search for requested attribute.              M
*   Name:     Name of requested attribute.                                   M
*                                                                            *
* RETURN VALUE:                                                              M
*   char *:   Found attribute, or NULL if not found.   		             M
*                                                                            *
* SEE ALSO:                                                                  M
*   AttrSetIntAttrib, AttrGetIntAttrib, AttrSetPtrAttrib, AttrGetPtrAttrib,  M
*   AttrSetRealAttrib, AttrGetRealAttrib, AttrSetStrAttrib		     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrGetStrAttrib, attributes                                             M
*****************************************************************************/
char *AttrGetStrAttrib(IPAttributeStruct *Attrs, char *Name)
{
    IPAttributeStruct
	*Attr = AttrFindAttribute(Attrs, Name);

    if (Attr != NULL && Attr -> Type == IP_ATTR_STR)
        return Attr -> U.Str;
    else
        return NULL;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to aid in scanning a list of attributes.                           M
*   If TraceAttrs != NULL, a ptr to its attribute list is saved and the      M
* next attribute is returned every call until the end of the list is         M
* reached, in which NULL is returned.                                        M
*   FirstAttrs should be NULL in all but the first call in the sequence.     M
*   Attributes with names starting with an underscore '_' are assumed to be  M
* temporary or internal and are skipped.				     M 
*                                                                            *
* PARAMETERS:                                                                M
*   TraceAttrs:    If not NULL, contains the previously returned attribute.  M
*   FirstAttrs:    First attribute in list, usually NULL in all but the      M
*                  first invokation in a psuence.			     M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPAttributeStruct *:  Next attribute in list.                            M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrTraceAttributes, attributes                                          M
*****************************************************************************/
IPAttributeStruct *AttrTraceAttributes(IPAttributeStruct *TraceAttrs,
				       IPAttributeStruct *FirstAttrs)
{
    if (FirstAttrs != NULL)
	TraceAttrs = FirstAttrs;
    else if (TraceAttrs != NULL)
	TraceAttrs = TraceAttrs -> Pnext;
    else
	return NULL;

    while (TraceAttrs) {
	if (TraceAttrs -> Name[0] != '_') {
	    return TraceAttrs;
	}
	else
	    TraceAttrs = TraceAttrs -> Pnext;
    }

    return NULL;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Routine to convert an attribute to a string.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attr:      To convert to a string.                                       M
*   DataFileFormat:  If TRUE, the attribute is formated in the IRIT data     M
*		file format.  Otherwise, just the attribute value is	     M
*		returned as a string.					     M
*                                                                            *
* RETURN VALUE:                                                              M
*   char *:    A pointer to a static string representing/describing the      M
*              given attribute.						     M
*                                                                            *
* KEYWORDS:                                                                  M
*   Attr2String, attributes                                                  M
*****************************************************************************/
char *Attr2String(IPAttributeStruct *Attr, int DataFileFormat)
{
    static char Str[LINE_LEN_LONG];

    Str[0] = 0;

    if (DataFileFormat) {
	switch (Attr -> Type) {
	    case IP_ATTR_INT:
	        sprintf(Str, "[%s %d]", Attr -> Name, Attr -> U.I);
		break;
	    case IP_ATTR_REAL:
		sprintf(Str, "[%s %g]", Attr -> Name, Attr -> U.R);
		break;
	    case IP_ATTR_STR:
		if (strchr(Attr -> U.Str, '"') != NULL) {
		    /* Need to escape the quotes. */
		    int i, j;

		    sprintf(Str, "[%s \"", Attr -> Name);

		    /* Need to quote the string or escape the internal " */
		    for (i = j = 0; i < strlen(Attr -> U.Str); i++) {
			if (Attr -> U.Str[i] == '"')
			    Str[j++] = '\\';
			Str[j++] = Attr -> U.Str[i];
		    }
		    Str[j] = 0;
		    strcat(Str, "\"]");
		}
		else if (strlen(Attr -> U.Str) > 0)
		    sprintf(Str, "[%s \"%s\"]", Attr -> Name, Attr -> U.Str);
		else
		    sprintf(Str, "[%s]", Attr -> Name);
		break;
	    case IP_ATTR_OBJ:
		sprintf(Str, "[%s _OBJ_ATTR_NOT_CNVRTED_]", Attr -> Name);
		break;
	    case IP_ATTR_PTR:
		sprintf(Str, "[%s _PTR_ATTR_NOT_CNVRTED_]", Attr -> Name);
		break;
	    default:
		IritFatalError("Undefined attribute type");
		break;
	}
    }
    else {
	switch (Attr -> Type) {
	    case IP_ATTR_INT:
	        sprintf(Str, "%d", Attr -> U.I);
		break;
	    case IP_ATTR_REAL:
		sprintf(Str, "%g", Attr -> U.R);
		break;
	    case IP_ATTR_STR:
		if (strchr(Attr -> U.Str, '"') != NULL) {
		    /* Need to escape the quotes. */
		    int i, j;

		    strcpy(Str, "\"");

		    /* Need to quote the string or escape the internal " */
		    for (i = j = 0; i < strlen(Attr -> U.Str); i++) {
			if (Attr -> U.Str[i] == '"')
			    Str[j++] = '\\';
			Str[j++] = Attr -> U.Str[i];
		    }
		    Str[j] = 0;
		    strcat(Str, "\"");
		}
		else if (strlen(Attr -> U.Str) > 0)
		    sprintf(Str, "\"%s\"", Attr -> U.Str);
		else
		    sprintf(Str, "%s", Attr -> U.Str);
		if (strlen(Str) == 0)
		    strcpy(Str, "\"\"");
		break;
	    case IP_ATTR_OBJ:
		strcpy(Str, "_OBJ_ATTR_NOT_CNVRTED_");
		break;
	    case IP_ATTR_PTR:
		strcpy(Str, "_PTR_ATTR_NOT_CNVRTED_");
		break;
	    default:
		IritFatalError("Undefined attribute type");
		break;
	}
    }

    return Str;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Routine to initialize the attributes of the given Attr list.	     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:   To initialize.                                                  M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrResetAttributes, attributes                                          M
*****************************************************************************/
void AttrResetAttributes(IPAttributeStruct **Attrs)
{
    *Attrs = NULL;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Routine to reverse the given Attr list.				     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:   To reverse, in place.                                           M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPAttributeStruct:  The reversed list, in place.			     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrReverseAttributes, attributes                                        M
*****************************************************************************/
IPAttributeStruct *AttrReverseAttributes(IPAttributeStruct *Attr)
{
    IPAttributeStruct
	*NewAttrs = NULL;

    while (Attr) {
	IPAttributeStruct
	    *Pnext = Attr -> Pnext;

	Attr -> Pnext = NewAttrs;
	NewAttrs = Attr;

	Attr = Pnext;
    }

    return NewAttrs;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Routine to search for an attribute by Name.				     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:    Attribute list to search.                                      M
*   Name:     Attribute to search by this name.                              M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPAttributeStruct *:  Attribute if found, otherwise NULL.                M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrFindAttribute, attributes                                            M
*****************************************************************************/
IPAttributeStruct *AttrFindAttribute(IPAttributeStruct *Attrs, char *Name)
{
    for (; Attrs != NULL; Attrs = Attrs -> Pnext)
	if (stricmp(Name, Attrs -> Name) == 0)
	    return Attrs;

    return NULL;
}

/*****************************************************************************
* DESCRIPTION:                                                               *
* Allocated a new attribute structure.                                       *
*                                                                            *
* PARAMETERS:                                                                *
*   Name:   Name of newly created attribute.                                 *
*   Type:   Type of newly created attribute.                                 *
*                                                                            *
* RETURN VALUE:                                                              *
*   IPAttributeStruct *:  The newly created attribute.                       *
*****************************************************************************/
IPAttributeStruct *_AttrMallocAttribute(char *Name, IPAttributeType Type)
{
    IPAttributeStruct
	*Attr = (IPAttributeStruct *) IritMalloc(sizeof(IPAttributeStruct));

    Attr -> Type = Type;
    Attr -> Name = IritStrdup(Name);
    Attr -> Pnext = NULL;

    return Attr;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to remove and delete the attribute named Name from the given       M
* Attr list.                                                                 M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:   To search for an attribute named Name and remove and delete it. M
*   Name:    Name of attribute to remove and delete.                         M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrFreeOneAttribute, attributes                                         M
*****************************************************************************/
void AttrFreeOneAttribute(IPAttributeStruct **Attrs, char *Name)
{
    IPAttributeStruct *TmpAttr,
	*Attr = *Attrs;

    if (Attr) {
	if (stricmp(Name, Attr -> Name) == 0) {
	    /* It is the first one - delete first in list. */
	    *Attrs = Attr -> Pnext;
	    Attr -> Pnext = NULL;
	    AttrFreeAttributes(&Attr);
	}
	else {
	    /* Search the rest of the list and delete if found. */
	    while (Attr -> Pnext != NULL) {
		if (stricmp(Name, Attr -> Pnext -> Name) == 0) {
		    TmpAttr = Attr -> Pnext;
		    Attr -> Pnext = TmpAttr -> Pnext;
		    TmpAttr -> Pnext = NULL;
		    AttrFreeAttributes(&TmpAttr);
		}
		else
		    Attr = Attr -> Pnext;
	    }
	}
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to remove anddelete all attributes of the given Attr list.         M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:   To remove and delete.                                           M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrFreeAttributes, attributes                                           M
*****************************************************************************/
void AttrFreeAttributes(IPAttributeStruct **Attrs)
{
    IPAttributeStruct *Attr;

    if (*Attrs == NULL)
	return;

    for (Attr = *Attrs; Attr != NULL; ) {
    	IPAttributeStruct
	    *Next = Attr -> Pnext;

	_AttrFreeAttributeData(Attr);
	IritFree((VoidPtr) Attr -> Name);
	IritFree((VoidPtr) Attr);
	Attr = Next;
    }

    *Attrs = NULL;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Routine to copy an attribute list.					     M
*                                                                            *
* PARAMETERS:                                                                M
*   Src:       Attribute list to duplicate.                                  M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPAttributeStruct *:   Duplicated attribute list.                        M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrCopyAttributes,attributes                                            M
*****************************************************************************/
IPAttributeStruct *AttrCopyAttributes(IPAttributeStruct *Src)
{
    IPAttributeStruct
	*DestAttr = NULL,
	*Dest = NULL;

    for ( ; Src != NULL; Src = Src -> Pnext) {
	if (Src -> Name[0] == '_')       /* Do not copy internal attributes. */
	    continue;

	if (Dest == NULL) {	
	    Dest = DestAttr = AttrCopyOneAttribute(Src);
	}
	else {
	    DestAttr -> Pnext = AttrCopyOneAttribute(Src);

	    DestAttr = DestAttr -> Pnext;
	}
    }

    return Dest;
}
