/*****************************************************************************
* 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"

/*****************************************************************************
*   Routine to set the color of an object.				     *
*****************************************************************************/
void AttrSetObjectColor(IPObjectStruct *PObj, int Color)
{
    AttrSetObjectIntAttrib(PObj, "color", Color);
}

/*****************************************************************************
*   Routine to return the color of an object.				     *
*****************************************************************************/
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;
}

/*****************************************************************************
*   Routine to set the RGB color of an object.				     *
*****************************************************************************/
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);
}

/*****************************************************************************
*   Routine to return the RGB color of an object.			     *
*****************************************************************************/
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;
}

/*****************************************************************************
*   Routine to set an integer attribute to an object.			     *
*****************************************************************************/
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);
    }
}

/*****************************************************************************
*   Routine to get an integer attribute from an object.			     *
*****************************************************************************/
int AttrGetObjectIntAttrib(IPObjectStruct *PObj, char *Name)
{
    return AttrGetIntAttrib(PObj -> Attrs, Name);
}

/*****************************************************************************
*   Routine to set a pointer attribute to an object.			     *
*****************************************************************************/
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);
    }
}

/*****************************************************************************
*   Routine to get a pointer attribute from an object.			     *
*****************************************************************************/
VoidPtr AttrGetObjectPtrAttrib(IPObjectStruct *PObj, char *Name)
{
    return AttrGetPtrAttrib(PObj -> Attrs, Name);
}

/*****************************************************************************
*   Routine to set a real attribute to an object.			     *
*****************************************************************************/
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);
    }
}

/*****************************************************************************
*   Routine to get a real attribute from an object.			     *
*****************************************************************************/
RealType AttrGetObjectRealAttrib(IPObjectStruct *PObj, char *Name)
{
    return AttrGetRealAttrib(PObj -> Attrs, Name);
}

/*****************************************************************************
*   Routine to set a string attribute to an object.			     *
*****************************************************************************/
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);
    }
}

/*****************************************************************************
*   Routine to get a string attribute from an object.			     *
*****************************************************************************/
char *AttrGetObjectStrAttrib(IPObjectStruct *PObj, char *Name)
{
    return AttrGetStrAttrib(PObj -> Attrs, Name);
}

/*****************************************************************************
*   Routine to set an object attribute to an object.			     *
*****************************************************************************/
void AttrSetObjectObjAttrib(IPObjectStruct *PObj, char *Name,
							IPObjectStruct *Data)
{
    int i;
    IPObjectStruct *PObjTmp;

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

/*****************************************************************************
*   Routine to set an object attribute.					     *
*****************************************************************************/
void AttrSetObjAttrib(IPAttributeStruct **Attrs, char *Name,
							IPObjectStruct *Data)
{
    IPAttributeStruct
        *Attr = AttrFindAttribute(*Attrs, Name);

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

/*****************************************************************************
*   Routine to get an object attribute from an object.			     *
*****************************************************************************/
IPObjectStruct *AttrGetObjectObjAttrib(IPObjectStruct *PObj, char *Name)
{
    return AttrGetObjAttrib(PObj -> Attrs, Name);
}

/*****************************************************************************
*   Routine to get an object attribute.					     *
*****************************************************************************/
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;
}

/*****************************************************************************
*   Routine to release the data slot of an attribute.			     *
* This routine also exists in miscatt2.c without object handling. It will be *
* pulled iff no object handling is used (i.e. this file is not linked in).   *
*****************************************************************************/
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;
    }
}

/*****************************************************************************
*   Routine to copy an attribute list.					     *
*****************************************************************************/
IPAttributeStruct *AttrCopyAttributes(IPAttributeStruct *Src)
{
    IPAttributeStruct *DestAttr,
	*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;
}

/*****************************************************************************
*   Routine to copy one attribute item.					     *
*****************************************************************************/
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;
}
