/* BOOPSI Support Functions */

#include <intuition/classes.h>
#include <intuition/intuitionbase.h>
#include <clib/alib_protos.h>
#include <clib/intuition_protos.h>
#include <clib/utility_protos.h>
#include <pragmas/intuition_pragmas.h>
#include <pragmas/utility_pragmas.h>

#include <stdarg.h>

#include "Definitions.h"


extern struct IntuitionBase *IntuitionBase;
extern struct Library	    *UtilityBase;

/* This needs less code than SetGadgetAttr_s_ for a single Attribute */

Prototype ULONG SetGadgetAttr (struct Gadget *o, struct Window *w, struct Requester *r, ULONG attrID, ULONG ti_data);
ULONG SetGadgetAttr (struct Gadget *o, struct Window *w, struct Requester *r, ULONG attrID, ULONG ti_data)
{
    return SetGadgetAttrs (o, w, r, attrID, ti_data, TAG_DONE);
} /* SetGadgetAttr */


/* This needs less code than SetAttr_s_ for a single Attribute */

Prototype ULONG SetAttr (Object *o, ULONG attrID, ULONG ti_data);
ULONG SetAttr (Object *o, ULONG attrID, ULONG ti_data)
{
    return SetAttrs (o, attrID, ti_data, TAG_DONE);
} /* SetAttr */


/* Get multiple Attributes at one time */
/* True, if _ALL_ attributes are got, False if at least one get has failed */

Prototype ULONG GetAttrsA (Object *o, struct TagItem *ti);
ULONG GetAttrsA (Object *o, struct TagItem *ti)
{
    ULONG rv = 1;
    struct TagItem *tstate;
    tstate = ti;
    while (ti = NextTagItem(&tstate))
    {
	rv = rv && GetAttr (ti->ti_Tag, o, (ULONG *)ti->ti_Data);
    }
    return rv;
} /* GetAttrsA */


/* VarArgs Stubs for GetAttrsA */

Prototype ULONG GetAttrs (Object *o, ...);
ULONG GetAttrs (Object *o, ...)
{
    ULONG   rv;
    va_list tags;
    va_start(tags, o);
    rv = GetAttrsA (o, (struct TagItem *)tags);
    va_end  (tags);
    return rv;
} /* GetAttrs */

/* Shortcuts for some Rootclass Methods ... */

Prototype ULONG RemoveObject (Object *m);
ULONG RemoveObject (Object *m)
{
    return DoMethod(m, OM_REMOVE);
} /* RemoveObject */

Prototype ULONG AppendObject (Object *m, struct MinList *l);
ULONG AppendObject (Object *m, struct MinList *l)
{
    return DoMethod (m, OM_ADDTAIL, l);
} /* AppendObject */

Prototype ULONG RemMember (Object *l, Object *m);
ULONG RemMember (Object *l, Object *m)
{
    return DoMethod(l, OM_REMMEMBER, m);
} /* AddMember */

/* hmmm wouldn't it be nice, if we added 2 Args ... Mode & Position */

Prototype ULONG AddMember (Object *l, Object *m);
ULONG AddMember (Object *l, Object *m)
{
    return DoMethod(l, OM_ADDMEMBER, m);
} /* AddMember */



static ULONG BoopsiSupport_rootsize = 0;

DEFAUTOINIT( BoopsiSupport_Initialize )
{
    Object *o;
    o = NewObject(NULL, "rootclass", TAG_END);
    if (!o)
    {
	BoopsiSupport_rootsize = sizeof (struct _Object);
    }
    else
    {
#	if 0
	    /* ---- won't work, sorry ... */
	    struct IClass *cl = OCLASS(o);
#	    if 1
		BoopsiSupport_rootsize =  cl->cl_InstSize;
#	    else
		BoopsiSupport_rootsize = -cl->cl_InstOffset;
#	    endif
#	else
	    /* ---- slow, but safe ... */
	    struct MinList  l;
	    struct MinNode *n;
	    NewList	  ((struct List *)&l);
	    AppendObject  (o, &l);
	    n			   = l.mlh_Head;
	    BoopsiSupport_rootsize = (ULONG)o - (ULONG)n;
	    RemoveObject  (o);
#	endif
	DisposeObject (o);
    }
} /* BoopsiSupport_Initialize */

Prototype struct MinNode *Object2Node (Object *o);
struct MinNode *Object2Node (Object *o)
{
    return o? (struct MinNode *)((ULONG)o - BoopsiSupport_rootsize): NULL;
} /* Object2Node */

Prototype Object *Node2Object (struct MinNode *n);
Object *Node2Object (struct MinNode *n)
{
    return n? (Object *)((ULONG)n + BoopsiSupport_rootsize) : NULL;
} /* Node2Object */


#ifdef TEST
extern int printf (char *, ...);

int main (int ac, char ** av)
{
    ULONG zz = 100;
    zz -= (ULONG)Object2Node((APTR)zz);
    printf ("sizeof RootNode = %ld\n", zz);
    return 0;
} /* main */
#endif

#if 0

extern struct Library *GadToolsBase;

int GT_GetGadgetAttr (struct Gadget *gad, Tag tag, ULONG *data)
{
    if (Gad-ToolsBase->lib_Version == 37) {
	switch (tag) {
	/*case GTCB_Checked:
	case GTCY_Labels:
	case GTLV_Labels:
	case GTLV_Top:
	case GTPA_Color:
	case GTPA_ColorOffset:
	case GTPA_ColorTable:
	case GTSC_Top:
	case GTSC_Total:
	case GTSC_Visible:
	case GTSL_Level:
	case GTSL_Max:
	case GTSL_Min:
	case GTTX_Text:*/

	case GTLV_Selected:
	case GTCY_Active:
	    *data = *((UWORD *)((ULONG)(gad + 1)) + 6));
	    break;
	case GTMX_Active:
	    *data = *((UWORD *)((ULONG)(gad + 1)) + 38));
	    break;
	case GTIN_Number:
	    *data = ((struct StringInfo *)gad->SpecialInfo)->LongInt;
	    break;
	case GTST_String:
	    *data = (ULONG)((struct StringInfo *)gad->SpecialInfo)->Buffer;
	    break;
	case GA_Disabled:
	    *data = (gad->Flags & GFLG_DISABLED) ? 1: 0;
	    break;
	default:
	    return 0;
	} /* switch */
	return 1;
    } else {
	return GT_GetGadgetAttrs (gad, NULL, NULL, tag, data, TAG_END);
    } /* if */
} /* GT_GetGadgetAttr */

#endif
