//-------------------------------------
//
// SuperCode (c) 1996 by T.Kühn 
//
// Programmiersprache:	ANSI-C
// Projektstart:			7.9.94
//
// Modul:				Boopsi-Gadgets
//
//-------------------------------------



#include <stdarg.h>
#include <pragma/intuition_lib.h>
#include <pragma/dos_lib.h>
#include <pragma/graphics_lib.h>
#include <pragma/utility_lib.h>
#include <pragma/gadtools_lib.h>
#include <clib/alib_protos.h>
#include <libraries/gadtools.h>
#include <utility/hooks.h>

#include <intuition/gadgetclass.h>
#include <intuition/icclass.h>
#include <intuition/imageclass.h>

#pragma header

#include <Struct.h>


void Class_Init(void);
BOOL Class_Free(void);

Class *class_button=0;
Class *class_text=0;
Class *class_symbol=0;


//-------------------------------------
LONG Txt_DimX(struct RastPort *rp,UBYTE *String,ULONG Size)
{
	WORD Len;

	if (!Size) Size=strlen(String);

	Len=TextLength(rp,String,Size);

	return(Len);
}
//-------------------------------------
LONG Txt_FitX(struct RastPort *rp,UBYTE *String,ULONG Size,ULONG Width,ULONG *newpixlen)
{
	struct TextExtent Te;
	WORD len;

	if (String)
	{
		if (!Size) Size=strlen(String);
	
		len=TextFit(rp,String,Size,&Te,0,1,Width,1000);
	
		if (newpixlen) (*newpixlen)=Te.te_Width;
	}
	return(len);
}
//-------------------------------------
VOID Txt_PrintFit(struct RastPort *rp,UBYTE *txt,ULONG n,ULONG x,ULONG y,ULONG w,ULONG h,ULONG fg,ULONG bg,ULONG flag)
{
	ULONG y2,np,pix=0;

	if (rp)
	{
		if (!h) h=rp->TxHeight;
		if (txt && rp->TxHeight <= h)
		{
			LONG diff=0;
			np=Txt_FitX(rp,txt,n,w,&pix);

			y2= y+(h-rp->TxHeight+1)/2+rp->TxBaseline;

			if (flag&BOX_RIGHT || flag&BOX_CENTER)
			{
				diff=w-pix;
				if (flag&BOX_CENTER) diff/=2;
				if (flag&BOX_FILL)
				{
					SetAPen(rp,bg);
					RectFill(rp,x,y,x+diff,y+h-1);
				}
			}
		
			SetDrMd(rp,JAM2);
			SetBPen(rp,bg);
			SetAPen(rp,fg);
			Move(rp,x+diff,y2);
			Text(rp,txt,np);
	
			if (!(flag&BOX_RIGHT))
			{
				if (flag&BOX_FILL)
				{
					SetAPen(rp,bg);
					RectFill(rp,rp->cp_x,y,x+w-1,y+h-1);
				}
			}
		}
		else
		{
			SetAPen(rp,bg);
			RectFill(rp,x,y,x+w-1,y+h-1);
		}
	}
}
//-------------------------------------


//-------------------------------------
ULONG SetInfoAttrs(struct GadgetInfo *ginfo,struct Gadget *gad,ULONG data ...)
{
	ULONG back=0;

	if (gad)
	{
		if (ginfo)
		{
			back=SetGadgetAttrsA(gad,ginfo->gi_Window,ginfo->gi_Requester,(struct TagItem*)&data);
		}
		else
		{
			back=SetGadgetAttrsA(gad,0,0,(struct TagItem*)&data);
		}
	}
	return back;
}
//-------------------------------------
ULONG GadGetAttr(struct Gadget *gad,ULONG id)
{
	ULONG back=0;

	if (gad)
	{
		back=GetAttr(id,gad,&back);
	}
	return back;
}
//-------------------------------------

#define LEFT (-1)
#define RGHT ( 1)

//-------------------------------------
VOID DrawLineR(struct RastPort *rp,LONG rx,LONG ry,LONG x1,LONG y1,LONG x2,LONG y2,LONG col)
{
	LONG t=0;

	SetAPen(rp,col);

	if (rx>1)
	{
		for (t=rx-1;t>=0;t--)
		{
			Move(rp,x1+t,y1);
			Draw(rp,x2+t,y2);
		}
	}
	else if (ry>1)
	{
		for (t=ry-1;t>=0;t--)
		{
			Move(rp,x1,y1+t);
			Draw(rp,x2,y2+t);
		}
	}
	else
	{
		Move(rp,x1,y1);
		Draw(rp,x2,y2);
	}

}
//-------------------------------------
VOID DrawToR(struct RastPort *rp,LONG rx,LONG ry,LONG x2,LONG y2,LONG col)
{
	LONG x1,y1;

	x1=rp->cp_x;
	y1=rp->cp_y;
	
	DrawLineR(rp,rx,ry,x1,y1,x2,y2,col);
}
//-------------------------------------
VOID DrawBoxR(struct RastPort *rp,LONG rx,LONG ry,ULONG x,ULONG y,ULONG w,ULONG h,LONG c1,LONG c2)
{
	SetDrMd(rp,JAM1);

	DrawLineR(rp,rx,ry,x,y,x,y+h,c1);
	DrawLineR(rp,rx,ry,x,y,x+w,y,c1);
	DrawLineR(rp,rx,ry,x+w,y,x+w,y+h,c2);
	DrawLineR(rp,rx,ry,x+w,y+h,x,y+h,c2);

}
//-------------------------------------
VOID DrawBox(struct RastPort *rp,struct DrawInfo *drinfo,ULONG x,ULONG y,ULONG w,ULONG h,BOOL Border)
{
	UWORD 	*pens=drinfo->dri_Pens;
	UWORD		c1,c2;

/*	LONG		rx=drinfo->dri_Resolution.X;
	LONG		ry=drinfo->dri_Resolution.Y;
	if (rx<ry)			{ rx=ry/rx;ry=1; }
	else if (rx>ry)	{ ry=rx/ry;rx=1; }
	else					{ rx=1;ry=1; }
*/
	LONG		rx=2;
	LONG		ry=1;

	w=w-rx;
	h=h-ry;

	if (!Border)
	{
		c1=pens[SHINEPEN];
		c2=pens[SHADOWPEN];
	}
	else
	{
		c1=pens[SHADOWPEN];
		c2=pens[SHINEPEN];
	}

	SetDrMd(rp,JAM1);

	DrawLineR(rp,rx,ry,x,y,x,y+h,c1);
	DrawLineR(rp,rx,ry,x,y,x+w,y,c1);
	DrawLineR(rp,rx,ry,x+w,y,x+w,y+h,c2);
	DrawLineR(rp,rx,ry,x+w,y+h,x,y+h,c2);

}
//-------------------------------------


//-------------------------------------
void Gadget_UpdateRender(Class *klasse,struct Gadget *gad,struct opUpdate *msg)
{
	struct GadgetInfo	*ginfo=msg->opu_GInfo;

	if (ginfo)
	{
		struct RastPort *rp=ObtainGIRPort(ginfo);
		struct gpRender drmsg=
		{
			GM_RENDER,ginfo,rp,GREDRAW_UPDATE
		};
		if (rp)
		{
			DoMethodA((Object*)gad,(Msg)&drmsg);
			ReleaseGIRPort(rp);
		}
	}
}
//-------------------------------------


//-------------------------------------
struct SymbolData
{
	ULONG					special;
	UBYTE					col_bg,col_fg,sel_bg,sel_fg;
	enum SymbolType 	symbol;
};
//-------------------------------------
BOOL  Gadget_SymbolHitTest(Class *klasse,struct Gadget *gad,struct gpHitTest *ht)
{
	BOOL back=FALSE;
	WORD x=ht->gpht_Mouse.X;
	WORD y=ht->gpht_Mouse.Y;

	WORD gw=gad->Width;
	WORD gh=gad->Height;

	if (x>=0 && x<gw && y>=0 && y<gh ) back=GMR_GADGETHIT;

	return back;
}
//-------------------------------------
ULONG Gadget_SymbolRender(Class *klasse,struct Gadget *gadget,struct gpRender *gp)
{
	struct SymbolData	*data=INST_DATA(klasse,gadget);

	struct GadgetInfo	*ginfo=gp->gpr_GInfo;
	struct DrawInfo	*drinfo=ginfo->gi_DrInfo;
	struct RastPort	*rp=ObtainGIRPort(ginfo);
	UWORD 				*pens=drinfo->dri_Pens;

	LONG		fg,bg;
	BOOL		Border=FALSE;
	LONG		x,y,w,h;
	LONG		dx=0,dy=0;

	LONG		rx=drinfo->dri_Resolution.X;
	LONG		ry=drinfo->dri_Resolution.Y;

	LONG col_l=pens[SHINEPEN];
	LONG col_d=pens[SHADOWPEN];

	if (rx<ry)			{ rx=ry/rx;ry=1; }
	else if (rx>ry)	{ ry=rx/ry;rx=1; }
	else					{ rx=1;ry=1; }

	x=gadget->LeftEdge;
	y=gadget->TopEdge;

	w=gadget->Width;
	h=gadget->Height;

	if (!(gadget->Flags & GFLG_SELECTED))
	{
		fg=pens[data->col_fg];
		bg=pens[data->col_bg];
	}
	else
	{
		if (data->symbol != SYMBOL_CHECKPOINT)
		{
			dx=1;
			dy=1;
		}
		Border=1-Border;
		fg=pens[data->sel_fg];
		bg=pens[data->sel_bg];
	}

	SetAPen(rp,bg);
	RectFill( rp,x,y,x+w-1,y+h-1);
	DrawBox(rp,drinfo,x,y,w,h,Border);

	x+=dx;
	y+=dy;

	dx=w*16/100;
	dy=h*16/100;

	if (dx<rx) dx=rx;
	if (dy<ry) dy=ry;

	x+=dx;
	y+=dy;
	w-=2*dx+rx;
	h-=2*dy+ry;

	SetDrMd(rp,JAM1);
	SetAPen(rp,fg);

	switch(data->symbol)
	{
		case SYMBOL_FONTREQUEST:
			{
				LONG a,b;

				dx=w/4;
				dy=h/4;

				a=y+h-dy;

				DrawLineR(rp,rx,ry, x,y,x+w-dx,y,col_d);
				DrawLineR(rp,rx,ry, x+dx/2,y,x+dx/2,a,col_d);
				a=(a-y)/2;
				DrawLineR(rp,rx,ry, x,y+a,x+2*dx,y+a,col_d);

				a=a/2;
				b=dx;
				DrawLineR(rp,rx,ry, x+b,y+a,x+w,y+a,col_l);
				b=w-((w-b)/2);
				DrawLineR(rp,rx,ry, x+b,y+a,x+b,y+h,col_l);
			}
			break;
		case SYMBOL_FILEREQUEST:
			{
				LONG t;
				dx=w/4;
				dy=h/4;

				DrawLineR(rp,rx,ry, x,y+h,x,y+dy,col_l);
				DrawToR(rp,rx,ry, x+dx,y,col_l);
				DrawToR(rp,rx,ry, x+w,y,col_l);

				DrawToR(rp,rx,ry, x+w,y+h,col_d);
				DrawToR(rp,rx,ry, x+rx,y+h,col_d);

				for (t=0;t<3;t++,y+=dy)
				{
					DrawLineR(rp,rx,ry, x+dx,y+dy,x+w-dx,y+dy, col_d);
					DrawLineR(rp,rx,ry, x+dx,y+dy+1,x+w-dx,y+dy+1, col_l);
				}
			}
			break;
		case SYMBOL_SCRNMODEREQUEST:
			{
				LONG xa,ya,wa,ha;

				dy=h/8;
				dx=w/8;

				xa=x;
				ya=y;
				wa=w;
				ha=h-2*dy;

				DrawBoxR(rp,rx,ry,xa,ya,wa,ha,col_l,col_d);
				DrawBoxR(rp,rx,ry,xa+2,ya+ha+1,wa-4,h-ha-1,col_l,col_d);

				dy=h/5;
				dx=w/5;
				DrawLineR(rp,rx,ry, xa+2*dx,y+dy,xa+dx,y+dy, col_l);
				DrawToR  (rp,rx,ry, xa+dx,y+2*dy ,col_l);
				DrawLineR(rp,rx,ry, xa+wa-2*dx,ya+ha-dy,xa+wa-dx,ya+ha-dy, col_d);
				DrawToR  (rp,rx,ry, xa+wa-dx,ya+ha-2*dy ,col_d);
			}
			break;
		case SYMBOL_PUBSCRNREQUEST:
			{
				LONG xa,ya,wa,ha;

				dy=h/8;
				dx=w/8;

				xa=x;
				ya=y;
				wa=w;
				ha=h;

				DrawBoxR(rp,rx,ry,xa,ya,wa,ha,col_l,col_d);

				dy=h/5;
				dx=w/5;
				DrawBoxR(rp,rx,ry, xa+w-rx-dx,ya,dx,dy,col_l,col_l);
				DrawLineR(rp,rx,ry, xa+rx,ya+dy,xa+w-(rx+dx),ya+dy, col_l);
			}
			break;
		case SYMBOL_ARROWUP:
		case SYMBOL_ARROWDOWN:
		case SYMBOL_ARROWLEFT:
		case SYMBOL_ARROWRIGHT:
			{
				LONG w2=w/2;
				LONG h2=h/2;

				dx=w/8;
				dy=h/8;
				if (dx<rx) dx=rx;
				if (dy<ry) dy=ry;

				switch(data->symbol)
				{
					case SYMBOL_ARROWUP:
						DrawLineR(rp,rx,ry, x+w-dx,y+h-dy,x+w2,y+dy,col_l);
						DrawToR  (rp,rx,ry, x+dx,y+h-dy,col_d);
						break;
					case SYMBOL_ARROWDOWN:
						DrawLineR(rp,rx,ry, x+w-dx,y+dy,x+w2,y+h-dy,col_d);
						DrawToR  (rp,rx,ry, x+dx,y+dy,col_l);
						break;
					case SYMBOL_ARROWLEFT:
						DrawLineR(rp,rx,ry, x+w-dx,y+h-dy,x+dx,y+h2,col_d);
						DrawToR  (rp,rx,ry, x+w-dx,y+dy,col_l);
						break;
					case SYMBOL_ARROWRIGHT:
						DrawLineR(rp,rx,ry, x+dx,y+h-dy,x+w-dx,y+h2,col_d);
						DrawToR  (rp,rx,ry, x+dx,y+dy,col_l);
						break;
				}
			}
			break;
		case SYMBOL_CHECKPOINT:
			{
				LONG w2=w/2;
				LONG h2=h/2;

				if (gadget->Flags & GFLG_SELECTED)
				{
					dx=w/8;
					dy=h/8;
					if (dx<rx) dx=rx;
					if (dy<ry) dy=ry;
	
					DrawLineR(rp,rx,ry, x+dx,y+h2,x+w*2/5,y+h-dy,col_d);
					DrawToR  (rp,rx,ry, x+w-dx,y+dy,col_d);
				}
			}
			break;

	}

	if (rp) ReleaseGIRPort(rp);

	return TRUE;
}
//-------------------------------------
ULONG Gadget_SymbolSetAttrs(Class *klasse,struct Gadget *obj, struct opSet *msg)
{
	struct SymbolData *data=INST_DATA(klasse,obj);
	struct TagItem *tags=msg->ops_AttrList,*tbegin=tags,*tag;
	ULONG tdata,back=FALSE;

	while( (tag=NextTagItem(&tbegin)) )
	{
		tdata=tag->ti_Data;
		switch (tag->ti_Tag)
		{
			case GA_Special:
				data->special=tdata;
				break;
			case GA_Symbol:
				if (data->symbol!=tdata)
				{
					data->symbol=(enum SymbolType)tdata;
					back=TRUE;
				}
				break;
		}
	}

	return back;
}
//-------------------------------------
ULONG Gadget_SymbolGetAttr(Class *klasse,struct Gadget *gad, struct opGet *get)
{
	struct SymbolData *data=INST_DATA(klasse,gad);
	ULONG *get_store=get->opg_Storage;
	ULONG back=FALSE;

	if (get_store)
	{
		switch(get->opg_AttrID)
		{
			case GA_Special:
				(*get_store)=(ULONG)data->special;
				back=TRUE;
				break;
			default:
				back=(ULONG)DoSuperMethodA(klasse,(Object*)gad,(Msg)get);
				break;
		}
	}

	return back;
}
//-------------------------------------
ULONG Gadget_SymbolNotify(Class *klasse,struct Gadget *gad, struct opUpdate *msg)
{
	struct SymbolData *data=INST_DATA(klasse,gad);
	LONG back=FALSE;
	struct TagItem *tags=msg->opu_AttrList,*tbegin=tags,*tag;
	ULONG tdata,num=0;

	while( (tag=NextTagItem(&tbegin)) )
	{
		num++;

		tdata=tag->ti_Data;
		switch (tag->ti_Tag)
		{
			case GA_Special:
//				tag->ti_Data
//				data->special=tdata;
				back=TRUE;
				break;
		}
	}

	return back;
}
//-------------------------------------
ULONG Gadget_SymbolDispatcher( Class *klasse, struct Gadget *obj, Msg msg)
{
	struct SymbolData *data=0;
	ULONG back=0;

	switch (msg->MethodID)
	{
		case OM_NEW:
			back=DoSuperMethodA(klasse, (Object*)obj, msg);
			obj=(struct Gadget*)back;
			if (back)
			{
				data=INST_DATA(klasse,back);
				data->symbol=SYMBOL_NONE;

				data->col_bg=BACKGROUNDPEN;
				data->col_fg=TEXTPEN;
				data->sel_bg=FILLPEN;
				data->sel_fg=FILLTEXTPEN;

				Gadget_SymbolSetAttrs(klasse,(struct Gadget*)back,(struct opSet*)msg);
			}
			break;
		case OM_GET:
			back=Gadget_SymbolGetAttr(klasse,obj,(struct opGet*)msg);
			break;
//		case OM_NOTIFY:
//			back=Gadget_SymbolNotify(klasse,obj,(struct opUpdate*)msg);
//			break;
		case OM_UPDATE:
		case OM_SET:
			back=DoSuperMethodA(klasse,(Object*)obj,msg);
			back+=Gadget_SymbolSetAttrs(klasse,obj,(struct opSet*)msg);
			if (back) Gadget_UpdateRender(klasse,obj,(struct opUpdate*)msg);
			break;
		case GM_RENDER:
			Gadget_SymbolRender(klasse,obj,(struct gpRender*)msg);
			break;
		case GM_HITTEST:
			back=Gadget_SymbolHitTest(klasse,obj,(struct gpHitTest*)msg);
			break;
		default:
			back=DoSuperMethodA(klasse,(Object*)obj,msg);
			break;
	}

//	SetGInfoAttrs(gad_debug1,GA_Integer,msg->MethodID,TAG_END);

//	data=INST_DATA(klasse,obj);
//	SetGInfoAttrs(gad_debug1,GA_Integer,data->special,TAG_END);

	return back;
}
//-------------------------------------


//-------------------------------------
struct ButtonData
{
	UBYTE		*Text;
	UBYTE		col_bg,col_fg,sel_bg,sel_fg;
	struct	TextFont *font;
};
//-------------------------------------
BOOL  Gadget_ButtonHitTest(Class *klasse,struct Gadget *gad,struct gpHitTest *ht)
{
	BOOL back=FALSE;
	WORD x=ht->gpht_Mouse.X;
	WORD y=ht->gpht_Mouse.Y;

	WORD gw=gad->Width;
	WORD gh=gad->Height;

	if (x>=0 && x<gw && y>=0 && y<gh ) back=GMR_GADGETHIT;

	return back;
}
//-------------------------------------
ULONG Gadget_ButtonRender(Class *klasse,struct Gadget *gadget,struct gpRender *gp)
{
	struct ButtonData	*data=INST_DATA(klasse,gadget);
	struct GadgetInfo	*ginfo=gp->gpr_GInfo;
	struct DrawInfo	*drinfo=ginfo->gi_DrInfo;
	struct RastPort	*rp=ObtainGIRPort(ginfo);
	struct TextFont	*font=rp->Font;
	UWORD 				*pens=drinfo->dri_Pens;
	UBYTE					*text=(UBYTE*)data->Text;

	LONG		fg,bg;
	WORD		left,top,height=0,width=0,dx=0,dy=0;
	BOOL		Border=FALSE;

	if (data->font)
	{
		font=data->font;
		SetFont(rp,font);
	}

	left=gadget->LeftEdge;
	top =gadget->TopEdge;

	width=gadget->Width;
	height=gadget->Height;

	if (!(gadget->Flags & GFLG_SELECTED))
	{
		fg=pens[data->col_fg];
		bg=pens[data->col_bg];
	}
	else
	{
		dx=1;dy=1;
		Border=1-Border;
		fg=pens[data->sel_fg];
		bg=pens[data->sel_bg];
	}

	DrawBox(rp,drinfo,left,top,width,height,Border);

	left+=2;
	top+=1;
	width-=4;
	height-=2;

	width--;
	height--;

	SetAPen(rp,bg);
	RectFill( rp,left,top,left+width,top+height);


	if (text)
	{
		left+=dx;
		top+=dy;

		Txt_PrintFit(rp,text,0,left,top,width,height,fg,bg,BOX_CENTER);
	}

	if (rp) ReleaseGIRPort(rp);

	return TRUE;
}
//-------------------------------------
ULONG Gadget_ButtonSetAttrs(Class *klasse,struct Gadget *obj, struct opSet *msg)
{
	struct ButtonData *data=INST_DATA(klasse,obj);
	struct TagItem *tags=msg->ops_AttrList,*tbegin=tags,*tag;
	ULONG tdata,back=FALSE;

	while( (tag=NextTagItem(&tbegin)) )
	{
		tdata=tag->ti_Data;
		switch (tag->ti_Tag)
		{
			case GA_Font:
				if (data->font!=(struct TextFont*)tdata)
				{
					data->font=(struct TextFont*)tdata;
					back=TRUE;
				}
				break;
			case GA_Text:
				if (!data->Text || !tdata || 0!=strcmp(data->Text,(UBYTE*)tdata))
				{
					data->Text=(UBYTE*)tdata;
					back=TRUE;
				}
				break;
			case GA_TextCol:
				if (data->col_fg!=tdata)
				{
					data->col_fg=tdata;
					back=TRUE;
				}
				break;
		}
	}

	return back;
}
//-------------------------------------
ULONG Gadget_ButtonDispatcher( Class *klasse, struct Gadget *obj, Msg msg)
{
	struct ButtonData *data;
	ULONG back=0;

	switch (msg->MethodID)
	{
		case OM_NEW:
			back=DoSuperMethodA(klasse, (Object*)obj, msg);
			if (back)
			{
				struct TagItem *tt=((struct opSet*)msg)->ops_AttrList;
				struct DrawInfo *drinfo=(struct DrawInfo*)GetTagData(SYSIA_DrawInfo,NULL,tt);

				data=INST_DATA(klasse,back);
				data->Text=0;

				data->col_bg=BACKGROUNDPEN;
				data->col_fg=TEXTPEN;
				data->sel_bg=FILLPEN;
				data->sel_fg=FILLTEXTPEN;
				data->font=0;

				Gadget_ButtonSetAttrs(klasse,(struct Gadget*)back,(struct opSet*)msg);
			}
			break;
		case OM_UPDATE:
		case OM_SET:
			back=DoSuperMethodA(klasse,(Object*)obj,msg);
			back+=Gadget_ButtonSetAttrs(klasse,obj,(struct opSet*)msg);
			if (back) Gadget_UpdateRender(klasse,obj,(struct opUpdate*)msg);
			break;
		case GM_RENDER:
			Gadget_ButtonRender(klasse,obj,(struct gpRender*)msg);
			break;
		case GM_HITTEST:
			back=Gadget_ButtonHitTest(klasse,obj,(struct gpHitTest*)msg);
			break;
		default:
			back=DoSuperMethodA(klasse,(Object*)obj,msg);
			break;
	}
	return back;
}
//-------------------------------------


//-------------------------------------
struct TextData
{
	UBYTE		*text;
	LONG		integer;
	BOOL		text_border;
	ULONG		text_just;
	ULONG		col_fg;
	ULONG		col_bg;
	struct	TextFont *font;
};
//-------------------------------------
ULONG Gadget_TextRender(Class *klasse,struct Gadget *gad,struct gpRender *gp)
{
	struct TextData		*data=INST_DATA(klasse,gad);
	struct GadgetInfo		*ginfo=gp->gpr_GInfo;
	struct Window			*win=ginfo->gi_Window;
	struct DrawInfo		*drinfo=ginfo->gi_DrInfo;
	struct RastPort		*rp=ObtainGIRPort(ginfo);
	struct TextFont		*font=rp->Font;
	UWORD						*pens=drinfo->dri_Pens;

	LONG fg=pens[data->col_fg],bg=pens[data->col_bg];
	LONG x,y,w,h;

	if (data->font)
	{
		font=data->font;
		SetFont(rp,font);
	}

	x=gad->LeftEdge;
	y=gad->TopEdge;
	w=gad->Width;
	h=gad->Height;

	DrawBox(rp,drinfo,x,y,w,h,data->text_border);
	SetAPen(rp,bg);
	RectFill(rp,x+2,y+1,x+w-4,y+h-2);

	x+=4;
	w-=8;
	y+=2;
	h-=4;

	if (data->text)
	{
		Txt_PrintFit(rp,data->text,0,x,y,w,h,fg,bg,data->text_just);
	}

	if (rp) ReleaseGIRPort(rp);

	return FALSE;
}
//-------------------------------------
ULONG Gadget_TextSetAttrs(Class *klasse,struct Gadget *gad, struct opSet *msg)
{
	struct TextData	*data=INST_DATA(klasse,gad);
	struct GadgetInfo	*ginfo=msg->ops_GInfo;
	struct TagItem		*tags=msg->ops_AttrList,*tbegin=tags,*tag;
	ULONG 				tdata,back=FALSE;

	while( (tag=NextTagItem(&tbegin)) )
	{
		tdata=tag->ti_Data;
		switch (tag->ti_Tag)
		{
			case GA_Integer:
				if (tdata!=data->integer)
				{
					data->integer=tdata;
					if (data->text) Memory_Free(&data->text);
					data->text=(UBYTE*)Memory_Alloc(100);
					if (data->text) sprintf(data->text,"%d",tdata);
					back=TRUE;
				}
				break;
			case GA_Text:
				if (tdata==0 || data->text==0 || 0!=strcmp(data->text,(char*)tdata))
				{
					if (data->text) Memory_Free(&data->text);
					if (tdata)
					{
						ULONG l=strlen((char*)tdata);
						if (tdata) data->text=(UBYTE*)Memory_Alloc(l+2);
						if (data->text)
						{
							strncpy(data->text,(char*)tdata,l);
							data->text[l+1]=0;
						}
					}
					back=TRUE;
				}
				break;
			case GA_TextJust:
				if (data->text_just!=tdata)
				{
					data->text_just=tdata;
					back=TRUE;
				}
				break;
			case GA_TextCol:
				if (data->col_fg!=tdata)
				{
					data->col_fg=tdata;
					back=TRUE;
				}
				break;
			case GA_BoxCol:
				if (data->col_bg!=tdata)
				{
					data->col_bg=tdata;
					back=TRUE;
				}
				break;
			case GA_BoxBorder:
				if (data->text_border!=tdata)
				{
					data->text_border=tdata;
					back=TRUE;
				}
				break;
			case GA_Font:
				if (data->font!=(struct TextFont*)tdata)
				{
					data->font=(struct TextFont*)tdata;
					back=TRUE;
				}
				break;
		}
	}
	return back;

}
//-------------------------------------
ULONG Gadget_TextDispatcher( Class *klasse, struct Gadget *obj, Msg msg)
{
	struct TextData *data;
	ULONG back=0;

	switch (msg->MethodID)
	{
		case OM_NEW:
			back = DoSuperMethodA(klasse, (Object*)obj, msg);
			if (back)
			{
				obj=(struct Gadget*)back;

				data=INST_DATA(klasse,obj);
				data->col_bg=BACKGROUNDPEN;
				data->col_fg=TEXTPEN;
				data->text_border=TRUE;
				data->text_just=BOX_LEFT;
				data->font=0;
				data->integer=0;
				data->text=0;

				Gadget_TextSetAttrs(klasse,obj,(struct opSet*)msg);	
			}
			break;
		case OM_DISPOSE:
			data=INST_DATA(klasse,obj);
			if (data->text) Memory_Free(&data->text);
			DoSuperMethodA(klasse,(Object*)obj,msg);
			break;
		case OM_UPDATE:
		case OM_SET:
			back+=DoSuperMethodA(klasse,(Object*)obj,msg);
			back+=Gadget_TextSetAttrs(klasse,obj,(struct opSet*)msg);	
			if (back) Gadget_UpdateRender(klasse,obj,(struct opUpdate*)msg);
			break;
		case GM_RENDER:
			DoSuperMethodA(klasse,(Object*)obj,msg);
			Gadget_TextRender(klasse,obj,(struct gpRender *)msg);
		default:
			back=DoSuperMethodA(klasse,(Object*)obj,msg);
			break;
	}

	return back;
}
//-------------------------------------


//-------------------------------------
void Class_Make(Class **klasse,ClassID id,ClassID superid,struct IClass *superclass,ULONG size,
					ULONG flags,VOID *func)
{
	extern ULONG HookEntry();

	do	{	(*klasse)=MakeClass(id,superid,superclass,size,flags);
		}	while((!(*klasse)) && ASK_AGAIN==display_error(ERR_CREATECLASS,ASK_EXIT|ASK_AGAIN));

	if (*klasse)
	{
		(*klasse)->cl_Dispatcher.h_Entry=HookEntry;
		(*klasse)->cl_Dispatcher.h_SubEntry=(VOID*)func;
	}
}
//-------------------------------------
void Class_Close(Class **klasse)
{
	if (*klasse) FreeClass(*klasse);
	(*klasse)=0;
}
//-------------------------------------



//-------------------------------------
void Class_Init()
{
	Class_Make(&class_button	,NULL,BUTTONGCLASS,NULL,sizeof(struct ButtonData),0,(VOID*)Gadget_ButtonDispatcher),
	Class_Make(&class_text  	,NULL,GADGETCLASS ,NULL,sizeof(struct TextData  ),0,(VOID*)Gadget_TextDispatcher);
	Class_Make(&class_symbol	,NULL,BUTTONGCLASS,NULL,sizeof(struct SymbolData),0,(VOID*)Gadget_SymbolDispatcher);
}
//-------------------------------------
BOOL Class_Free()
{
	Class_Close(&class_symbol);
	Class_Close(&class_text);
	Class_Close(&class_button);

	return(TRUE);
}
//-------------------------------------

