/*
 *	File:					GroupFrameClass.c
 *	Description:	GroupFrame BOOPSI class
 *
 *	(C) 1995, Ketil Hunn
 *
 */


#define	INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <exec/memory.h>
//#include <dos/dos.h>
//#include <dos/dosextens.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <intuition/intuitionbase.h>
#include <intuition/classusr.h>
//#include <intuition/imageclass.h>
#include <intuition/gadgetclass.h>
#include <intuition/cghooks.h>
#include <intuition/icclass.h>
#include <intuition/classes.h>
#include <intuition/sghooks.h>
#include <graphics/gfxbase.h>
#include <graphics/text.h>
#include <graphics/gfxmacros.h>
#include <utility/tagitem.h>
#include <utility/hooks.h>

#include <clib/macros.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/utility_protos.h>

#define USE_BUILTIN_MATH
#include <string.h>

#define PRO_Min			(TAG_USER + 9)
#define PRO_Max			(TAG_USER + 10)
#define PRO_Current		(TAG_USER + 11)
#define PRO_ShowPercent (TAG_USER + 12)

#define FLAG_SHOWPERCENT 1

struct GroupFrameData
{
	UWORD min;
	UWORD max;
	UWORD current;
	UWORD flags;
};

ULONG __asm dispatchGroupFrame(register __a0 Class *class, register __a2 Object *o, register __a1 Msg msg);
ULONG RenderGroupFrame(Class *class, struct Gadget *g, struct gpRender *msg, struct GroupFrameData *inst);

Class *InitGroupFrameClass(void)
{
  Class *class;

	if(class=MakeClass( NULL, "gadgetclass", NULL, sizeof(struct GroupFrameData), 0))
		class->cl_Dispatcher.h_Entry = (ULONG(*)()) dispatchGroupFrame;
	return class;
}

BYTE FreeGroupFrameClass(Class *class)
{
	return (BYTE)FreeClass(class);
}

ULONG __asm dispatchGroupFrame(register __a0 Class *class, register __a2 Object *o, register __a1 Msg msg)
{
  struct Gadget *g= (struct Gadget *)o;
//  struct RastPort *rp;
  struct GroupFrameData *inst;
  struct TagItem *ti;
//  struct opGet *opget;
  ULONG retval;
  Object *object;


	switch(msg->MethodID)
	{
		case OM_NEW:
			if(retval=(ULONG)(object=(Object *)DoSuperMethodA(class, o, msg)))
			{
				ti= ((struct opSet *)msg)->ops_AttrList;

				inst= INST_DATA(class, object);
				inst->min = GetTagData(PRO_Min,   0, ti);
				inst->max = GetTagData(PRO_Max, 100, ti);
				inst->current = GetTagData(PRO_Current, 0, ti);
				inst->flags = (GetTagData(PRO_ShowPercent, 0, ti) ? FLAG_SHOWPERCENT : 0);
			}
			break;
		case GM_RENDER:
			inst=INST_DATA(class, o);
			retval=RenderGroupFrame(class, g, (struct gpRender *)msg, inst);
			break;
/*		case OM_SET:
			ti= ((struct opSet *)msg)->ops_AttrList;
			if(FindTagItem(GA_Width,  ti) ||
				FindTagItem(GA_Height, ti) ||
				FindTagItem(GA_Top,    ti) ||
				FindTagItem(GA_Left,   ti) ||
				FindTagItem(PRO_Min, ti) ||
				FindTagItem(PRO_Max, ti) ||
				FindTagItem(PRO_Current, ti) ||
				FindTagItem(PRO_ShowPercent, ti))
				{
				WORD x,y,w,h;
				
				x= g->LeftEdge;
				y= g->TopEdge;
				w= g->Width;
				h= g->Height;

				retval= DoSuperMethodA(class, o, msg);

				if( rp=ObtainGIRPort( ((struct opSet *)msg)->ops_GInfo) )
					{
					UWORD *pens= ((struct opSet *)msg)->ops_GInfo->gi_DrInfo->dri_Pens;
					struct TagItem *tmp;
					
					if( x!=g->LeftEdge || y!=g->TopEdge || w!=g->Width || h!=g->Height )
						{
						SetAPen(rp, pens[BACKGROUNDPEN]);
						SetDrMd(rp, JAM1);
						RectFill(rp, x, y, x+w, y+h);
						}

					inst= INST_DATA(class, o);

					inst->min = GetTagData(PRO_Min, (LONG)inst->min, ti);
					inst->max = GetTagData(PRO_Max, (LONG)inst->max, ti);
					inst->current = GetTagData(PRO_Current, (LONG)inst->current, ti);
					if( tmp=FindTagItem(PRO_ShowPercent, ti) )
						{
						inst->flags = ( tmp->ti_Data ? FLAG_SHOWPERCENT : 0);
						}

					DoMethod(o, GM_RENDER, ((struct opSet *)msg)->ops_GInfo, rp, GREDRAW_REDRAW);
					ReleaseGIRPort(rp);
					}
				}
			else
				{
				retval= DoSuperMethodA(class, o, msg);
				}
			break;
		case OM_GET:
			opget= (struct opGet *)msg;
			inst= INST_DATA(class, o);
			retval= TRUE;
			switch( opget->opg_AttrID )
				{
				case PRO_Current:
					*(opget->opg_Storage)= (ULONG)inst->current;
					break;
				case PRO_Min:
					*(opget->opg_Storage)= (ULONG)inst->min;
					break;
				case PRO_Max:
					*(opget->opg_Storage)= (ULONG)inst->max;
					break;
				case PRO_ShowPercent:
					*(opget->opg_Storage)= (ULONG)( inst->flags & FLAG_SHOWPERCENT );
					break;
				default:
					retval= DoSuperMethodA(class, o, msg);
				}
			break;
*/
		case GM_HITTEST:
		case GM_GOACTIVE:
		case GM_HANDLEINPUT:
		case GM_GOINACTIVE:
		default:
			retval= DoSuperMethodA(class, o ,msg);
			break;
		}
	return( retval );
}

ULONG RenderGroupFrame(Class *class, struct Gadget *g, struct gpRender *msg, struct GroupFrameData *inst)
{
  struct RastPort *rp;
  ULONG retval=TRUE;
  UWORD *pens= msg->gpr_GInfo->gi_DrInfo->dri_Pens;

	if( msg->MethodID == GM_RENDER )
		rp= msg->gpr_RPort;
	else
		rp= ObtainGIRPort(msg->gpr_GInfo);

	if(rp)
	{
		UBYTE shine, shadow;
		UWORD x, y;
		UBYTE oldAPen, oldDrMd;

		oldAPen= rp->FgPen;
		oldDrMd= rp->DrawMode;

		shine = pens[SHADOWPEN];
		shadow= pens[SHINEPEN];

		SetAPen(rp, shadow);
		RectFill(rp,	x=g->LeftEdge,
									y=g->TopEdge,
									x+g->Width,
									y+g->Height);
		SetAPen(rp, oldAPen);
		SetDrMd(rp, oldDrMd);

		if( msg->MethodID != GM_RENDER )
			{
			ReleaseGIRPort(rp);
			}
	}
	else
		retval= FALSE;

	return( retval );
}
