/*****************************************************************************
* Setting attributes for geometric objects.				     *
*									     *
* Written by:  Gershon Elber				Ver 0.2, Mar. 1990   *
*****************************************************************************/

#include <string.h>
#include <stdio.h>
#include <math.h>
#include "irit_sm.h"
#include "iritprsr.h"
#include "attribut.h"
#include "allocate.h"

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to set the color of an object.				     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:      Object to set its color to Color.                             M
*   Color:     New color for PObj.                                           M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrSetObjectColor, attributes, color                                    M
*****************************************************************************/
void AttrSetObjectColor(IPObjectStruct *PObj, int Color)
{
    AttrSetObjectIntAttrib(PObj, "color", Color);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to return the color of an object.				     M
*                                                                            M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:     For which we would like to know the color of.                  M
*                                                                            *
* RETURN VALUE:                                                              M
*   int:      Color of PObj or IP_ATTR_NO_COLOR if no color set.             M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrGetObjectColor, attributes, color                                    M
*****************************************************************************/
int AttrGetObjectColor(IPObjectStruct *PObj)
{
    IPAttributeStruct
	*Attr = AttrFindAttribute(PObj -> 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 the RGB color of an object.				     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:               Object to set its RGB color.                         M
*   Red, Green, Blue:   Component of color.                                  M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrSetObjectRGBColor, attributes, color, rgb                            M
*****************************************************************************/
void AttrSetObjectRGBColor(IPObjectStruct *PObj, int Red, int Green, int Blue)
{
    char SRGB[30];

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

    AttrSetObjectStrAttrib(PObj, "rgb", SRGB);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to return the RGB color of an object.			     	     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:               Object to get its RGB color.                         M
*   Red, Green, Blue:   Component of color to initialize.                    M
*                                                                            *
* RETURN VALUE:                                                              M
*   int:     TRUE if PObj does have an RGB color attribute, FALSE otherwise. M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrGetObjectRGBColor, attributes, color, rgb                            M
*                                                                            M
*****************************************************************************/
int AttrGetObjectRGBColor(IPObjectStruct *PObj,
			  int *Red,
			  int *Green,
			  int *Blue)
{
    char
	*p = AttrGetStrAttrib(PObj -> Attrs, "rgb");

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

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to set an integer attribute for an object.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:     To add an integer attribute for.                               M
*   Name:     Name of attribute.                                             M
*   Data:     Content of attribute.                                          M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrSetObjectIntAttrib, attributes                                       M
*****************************************************************************/
void AttrSetObjectIntAttrib(IPObjectStruct *PObj, char *Name, int Data)
{
    int i;
    IPObjectStruct *PObjTmp;

    if (IP_IS_OLST_OBJ(PObj)) {
	for (i = 0; (PObjTmp = ListObjectGet(PObj, i)) != NULL; i++)
	    AttrSetObjectIntAttrib(PObjTmp, Name, Data);
    }
    else {
	AttrSetIntAttrib(&PObj -> Attrs, Name, Data);
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to get an integer attribute from an object.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:     Object from which to get an ingeter attribute.                 M
*   Name:     Name of integer attribute.                                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   int:      Found attribute, or IP_ATTR_BAD_INT if not found.              M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrGetObjectIntAttrib, attributes                                       M
*****************************************************************************/
int AttrGetObjectIntAttrib(IPObjectStruct *PObj, char *Name)
{
    return AttrGetIntAttrib(PObj -> Attrs, Name);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to set a pointer attribute for an object.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:     To add a pointer attribute for.                                M
*   Name:     Name of attribute.                                             M
*   Data:     Content of attribute.                                          M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrSetObjectPtrAttrib, attributes                                       M
*****************************************************************************/
void AttrSetObjectPtrAttrib(IPObjectStruct *PObj, char *Name, VoidPtr Data)
{
    int i;
    IPObjectStruct *PObjTmp;

    if (IP_IS_OLST_OBJ(PObj)) {
	for (i = 0; (PObjTmp = ListObjectGet(PObj, i)) != NULL; i++)
	    AttrSetObjectPtrAttrib(PObjTmp, Name, Data);
    }
    else {
	AttrSetPtrAttrib(&PObj -> Attrs, Name, Data);
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to get a pointer attribute from an object.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:     Object from which to get a pointer attribute.                  M
*   Name:     Name of pointer attribute.                                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   VoidPtr:  Found attribute, or NULL if not found. 		             M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrGetObjectPtrAttrib, attributes                                       M
*****************************************************************************/
VoidPtr AttrGetObjectPtrAttrib(IPObjectStruct *PObj, char *Name)
{
    return AttrGetPtrAttrib(PObj -> Attrs, Name);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to set a real attribute for an object.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:     To add a real attribute for.      	                     M
*   Name:     Name of attribute.                                             M
*   Data:     Content of attribute.                                          M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrSetObjectRealAttrib, attributes                                      M
*****************************************************************************/
void AttrSetObjectRealAttrib(IPObjectStruct *PObj, char *Name, RealType Data)
{
    int i;
    IPObjectStruct *PObjTmp;

    if (IP_IS_OLST_OBJ(PObj)) {
	for (i = 0; (PObjTmp = ListObjectGet(PObj, i)) != NULL; i++)
	    AttrSetObjectRealAttrib(PObjTmp, Name, Data);
    }
    else {
	AttrSetRealAttrib(&PObj -> Attrs, Name, Data);
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to get a real attribute from an object.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:     Object from which to get a real attribute.                     M
*   Name:     Name of real attribute.                                        M
*                                                                            *
* RETURN VALUE:                                                              M
*   RealType:  Found attribute, or IP_ATTR_BAD_REAL if not found. 	     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrGetObjectRealAttrib, attributes                                      M
*****************************************************************************/
RealType AttrGetObjectRealAttrib(IPObjectStruct *PObj, char *Name)
{
    return AttrGetRealAttrib(PObj -> Attrs, Name);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to set a string attribute for an object.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:     To add a string attribute for.                                 M
*   Name:     Name of attribute.                                             M
*   Data:     Content of attribute.                                          M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrSetObjectStrAttrib, attributes                                       M
*****************************************************************************/
void AttrSetObjectStrAttrib(IPObjectStruct *PObj, char *Name, char *Data)
{
    int i;
    IPObjectStruct *PObjTmp;

    if (IP_IS_OLST_OBJ(PObj)) {
	for (i = 0; (PObjTmp = ListObjectGet(PObj, i)) != NULL; i++)
	    AttrSetObjectStrAttrib(PObjTmp, Name, Data);
    }
    else {
	AttrSetStrAttrib(&PObj -> Attrs, Name, Data);
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to get a string attribute from an object.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:     Object from which to get a string attribute.                   M
*   Name:     Name of string attribute.                                      M
*                                                                            *
* RETURN VALUE:                                                              M
*   char *:      Found attribute, or NULL if not found. 	             M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrGetObjectStrAttrib, attributes                                       M
*****************************************************************************/
char *AttrGetObjectStrAttrib(IPObjectStruct *PObj, char *Name)
{
    return AttrGetStrAttrib(PObj -> Attrs, Name);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to set an object attribute for an object.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:     To add an object attribute for.                                M
*   Name:     Name of attribute.                                             M
*   Data:     Content of attribute.                                          M
*   CopyData: If TRUE, Data object is duplicated first.			     M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrSetObjectObjAttrib, attributes                                       M
*****************************************************************************/
void AttrSetObjectObjAttrib(IPObjectStruct *PObj,
			    char *Name,
			    IPObjectStruct *Data,
			    int CopyData)
{
    int i;
    IPObjectStruct *PObjTmp;

    if (IP_IS_OLST_OBJ(PObj)) {
	/* Must copy attribute if set on a list. */
	for (i = 0; (PObjTmp = ListObjectGet(PObj, i)) != NULL; i++)
	    AttrSetObjectObjAttrib(PObjTmp, Name, Data, TRUE);
	if (!CopyData)
	    IPFreeObject(Data);
    }
    else {
	AttrSetObjAttrib(&PObj -> Attrs, Name, Data, CopyData);
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to set an object 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
*   CopyData:  If TRUE, object Data is duplicated first.                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrSetObjAttrib, attributes                                             M
*****************************************************************************/
void AttrSetObjAttrib(IPAttributeStruct **Attrs,
		      char *Name,
		      IPObjectStruct *Data,
		      int CopyData)
{
    IPAttributeStruct
        *Attr = AttrFindAttribute(*Attrs, Name);

    if (Attr) {
	_AttrFreeAttributeData(Attr);
	Attr -> U.PObj = CopyData ? CopyObject(NULL, Data, TRUE) : Data;
	Attr -> U.PObj -> Pnext = NULL; 
	Attr -> Type = IP_ATTR_OBJ;
    }
    else {
	Attr = _AttrMallocAttribute(Name, IP_ATTR_OBJ);
	Attr -> U.PObj = CopyData ? CopyObject(NULL, Data, TRUE) : Data;
	Attr -> U.PObj -> Pnext = NULL; 
	Attr -> Pnext = *Attrs;
	*Attrs = Attr;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to get an object attribute from an object.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:     Object from which to get a object attribute.                   M
*   Name:     Name of object attribute.                                      M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:  Found attribute, or NULL if not found.	 	     M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrGetObjectObjAttrib, attributes                                       M
*****************************************************************************/
IPObjectStruct *AttrGetObjectObjAttrib(IPObjectStruct *PObj, char *Name)
{
    return AttrGetObjAttrib(PObj -> Attrs, Name);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to get an object attribute.					     M
*                                                                            *
* PARAMETERS:                                                                M
*   Attrs:    Attribute list to search for requested attribute.              M
*   Name:     Name of requested attribute.                                   M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:  Found attribute, or NULL if not found.                M
*                                                                            *
* KEYWORDS:                                                                  M
*   AttrGetObjAttrib, attributes                                             M
*****************************************************************************/
IPObjectStruct *AttrGetObjAttrib(IPAttributeStruct *Attrs, char *Name)
{
    IPAttributeStruct
	*Attr = AttrFindAttribute(Attrs, Name);

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

/*****************************************************************************
* DESCRIPTION:                                                               *
* Routine to release the data slot of an attribute.			     *
*   This routine also exists in miscatt2.c without object handling.	     *
*   The routine in miscatt2.c will be linked in iff no object handling is    *
*  used (i.e. this file is not linked in).				     *
*                                                                            *
* PARAMETERS:                                                                *
*   Attr:     To free.                                                       *
*                                                                            *
* RETURN VALUE:                                                              *
*   void                                                                     *
*****************************************************************************/
void _AttrFreeAttributeData(IPAttributeStruct *Attr)
{
    switch (Attr -> Type) {
	case IP_ATTR_INT:
	    break;
	case IP_ATTR_REAL:
	    break;
	case IP_ATTR_STR:
	    IritFree((VoidPtr) Attr -> U.Str);
	    break;
	case IP_ATTR_PTR:
	    IritFree((VoidPtr) Attr -> U.Ptr);
	    break;
	case IP_ATTR_OBJ:
	    IPFreeObject(Attr -> U.PObj);
	    break;
	default:
	    IritPrsrFatalError("Undefined attribute type");
	    break;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               *
* Routine to copy one attribute.					     *
*   This routine also exists in miscatt3.c without object handling.	     *
*   The routine in miscatt3.c will be linked in iff no object handling is    *
*  used (i.e. this file is not linked in).				     *
*                                                                            *
* PARAMETERS:                                                                *
*   Src:       Attribute to duplicate.                                       *
*                                                                            *
* RETURN VALUE:                                                              *
*   IPAttributeStruct *:   Duplicated attribute.                             *
*****************************************************************************/
IPAttributeStruct *AttrCopyOneAttribute(IPAttributeStruct *Src)
{
    IPAttributeStruct *Dest;

    if (Src -> Name[0] == '_')	       /* Do not copy internal attributes. */
	return NULL;

    Dest = _AttrMallocAttribute(Src -> Name, Src -> Type);

    switch (Src -> Type) {
        case IP_ATTR_INT:
	    Dest -> U.I = Src -> U.I;
	    break;
	case IP_ATTR_REAL:
	    Dest -> U.R = Src -> U.R;
	    break;
	case IP_ATTR_STR:
	    Dest -> U.Str = IritStrdup(Src -> U.Str);
	    break;
	case IP_ATTR_OBJ:
	    Dest -> U.PObj = CopyObject(NULL, Src -> U.PObj, TRUE);
	    break;
	case IP_ATTR_PTR:
	    IritPrsrFatalError("Attempt to copy a pointer attribute");
	    break;
	default:
	    IritPrsrFatalError("Undefined attribute type");
	    break;
    }

    return Dest;
}
