/********************************************************************************/
/* Urouhack V1.7 by Tinic Urou 08.04.96                                         */
/*                                                                              */
/* Please leave me a mail, if you are using this code.                          */
/* And, it would be nice, if you could send me a copy of your modified codes    */
/* uuencoded via mail.                                                          */
/*                                                                              */
/* 5uro@informatik.uni-hamburg.de                                               */
/********************************************************************************/

/********************************************************************************/
/* Some macros for class creation handling                                      */
/********************************************************************************/

#define BOOPSI_Class( initName, dispatchName, ClassID, SuperClass, SuperClassPtr, InstantStruct, Flags)\
Class  *initName(void);\
ULONG   dispatchName(struct IClass *, Object *, Msg);\
Class * initName(void)\
{\
	Class *cl;\
	extern ULONG HookEntry();\
	if(cl=MakeClass(ClassID,SuperClass,SuperClassPtr,sizeof(struct InstantStruct), Flags))\
	{\
		cl->cl_Dispatcher.h_Entry   = HookEntry;\
		cl->cl_Dispatcher.h_SubEntry= dispatchName;\
	}\
	return(cl);\
}\
__geta4 ULONG dispatchName(struct IClass *cl, Object *object,Msg msg)\
{\
	struct InstantStruct *data;\
	data=(struct *InstantStruct)0;\
	switch(msg->MethodID)\
	{

#define BOOPSI_Method( MethodID)\
		case MethodID:

#define BOOPSI_Method_End\
		break;

#define BOOPSI_InitData\
		data=INST_DATA(cl,object);

#define BOOPSI_Method_SuperDefault\
		default : return(DoSuperMethodA(cl,object,msg));

#define BOOPSI_Method_SuperReturn\
		return(DoSuperMethodA(cl,object,msg));

#define BOOPSI_Method_OldH(oldH)\
		return(oldH);

#define BOOPSI_Method_dOldH(oldH)\
		default : return(oldH);


#define BOOPSI_End\
	}\
}

/********************************************************************************/
/* Includes and libbases                                                        */
/********************************************************************************/

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/classes.h>
#include <intuition/classusr.h>
#include <intuition/imageclass.h>
#include <intuition/gadgetclass.h>
#include <intuition/cghooks.h>
#include <intuition/icclass.h>
#include <utility/tagitem.h>
#include <utility/hooks.h>
#include <clib/intuition_protos.h>
#include <clib/utility_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#include <intuition/IntuitionBase.h>
#include <graphics/gfxbase.h>
#include <graphics/text.h>
#include <graphics/scale.h>
#include <datatypes/datatypes.h>
#include <datatypes/pictureclass.h>
#include <dos/dos.h>
#include <dos/rdargs.h>
#include <exec/memory.h>
#include <exec/tasks.h>
#include <clib/macros.h>
#include <datatypes/datatypesclass.h>
#include <datatypes/datatypes.h>
#include <datatypes/pictureclass.h>
#include <dos/dostags.h>

extern       struct IntuitionBase *IntuitionBase;
extern       struct Library       *UtilityBase;
			 struct Library       *DataTypesBase;
static const char                 *version="$VER: Urouhack V1.7 by Tinic Urou. This is GIFTWARE!";

ULONG       *swim_in_my_pool;

BOOL    pframes         = TRUE,
		psysi           = TRUE,
		sysihackstyle   = FALSE,
		pwin            = TRUE,
		trymwb          = FALSE,
		XStyle          = FALSE;

/********************************************************************************/
/* Append new pens to the DrawInfo and allocate them                            */
/********************************************************************************/

#define HALFSHADOWPEN   (0x000C)
#define HALFSHINEPEN    (0x000D)
#define DARKPAINTPEN    (0x000E)    /* Brown  on MagicWB */
#define SHINEPAINTPEN   (0x000F)    /* Orange on MagicWB */

#define NEWNUMDRIPENS   (0x0010)
#define NEWDRIVERSION   (0x0003)
#define GADMAGIC        ((APTR)(0xFFDEADED))

struct NewPenStruct
{
	UWORD halfdark;
	UWORD halfshine;
	UWORD darkpaint;
	UWORD shinepaint;
};

struct ExtNewPenStruct
{
	ULONG   c1r;
	ULONG   c1g;
	ULONG   c1b;
	ULONG   c2r;
	ULONG   c2g;
	ULONG   c2b;
	ULONG   c3r;
	ULONG   c3g;
	ULONG   c3b;
	ULONG   c4r;
	ULONG   c4g;
	ULONG   c4b;
};

/********************************************************************************/
/* Default shit                                                                 */
/********************************************************************************/

BYTE    b_top   = 3,
		b_bottom= 3,
		b_left  = 3,
		b_right = 3,

		b_height=14,
		b_width =18;

struct NewPenStruct p1={1,0,1,1};
struct NewPenStruct p2={4,5,6,7};

struct NewPenStruct *penlist[256]=
{
	&p1,
	&p2
};

BOOL exttrymwb[256];

char *namelist[256]=
{
	"Free Britanny!",
	"Workbench"
};

char    *imagestyle;

BOOL    onlywb=FALSE;

/********************************************************************************/
/* Patch area                                                                   */
/********************************************************************************/

static ULONG AllocVecPooled(ULONG *pool, ULONG memsize)
{
	ULONG *memory;
	memsize += ( sizeof(ULONG) + sizeof(ULONG) );
	if(memory=(ULONG *)AllocPooled(pool,memsize))
	{
		memory[0]=pool;
		memory[1]=memsize;
		memory+=2L;       
	}                    
	return(memory);
}
static void  FreeVecPooled(ULONG *memory)
{
	FreePooled(memory[-2L],memory-2L,memory[-1L]);
}

int GetPubScreens(struct Screen *src, char *namelist[])
{
	struct List     *PubScreenList;
	struct PubScreenNode *ScreenNode;

	PubScreenList = LockPubScreenList();
	for(ScreenNode=(struct PubScreenNode *)PubScreenList->lh_Head;ScreenNode->psn_Node.ln_Succ;ScreenNode=(struct PubScreenNode *)ScreenNode->psn_Node.ln_Succ)
	{
		if(ScreenNode->psn_Screen==src)
		{
			int i=0;

			while(namelist[i])
			{
				if(strcmp(ScreenNode->psn_Node.ln_Name,namelist[i])==0)
				{
					UnlockPubScreenList();
					return(i);
				}
				i++;
			}
			UnlockPubScreenList();
			return(0);
		}
	}
	UnlockPubScreenList();
	return(0);
}

/* Extra pen information array */

#define OLD_PENS        (0x00)
#define IMG_SCREEN      (0x01)
#define MAX_EXT         (0x03)

__geta4 void allocNewPens(__A2 struct Screen *scr)
{
	struct DrawInfo *dr;
	int              i;
	BOOL             doit=TRUE;

	static struct ExtNewPenStruct defpens=
	{
		0x80808080,0x80808080,0x80808080,
		0xafafafaf,0xafafafaf,0xafafafaf,
		0xaaaaaaaa,0x99999999,0x77777777,
		0xffffffff,0xa9a9a9a9,0x97979797
	};

	if(dr=GetScreenDrawInfo(scr))
	{
		if(dr->dri_Version==DRI_VERSION)
		{
			UWORD   *newpens;
			if(newpens=(UWORD *)AllocVecPooled(swim_in_my_pool, (NEWNUMDRIPENS+1) * sizeof(UWORD) + sizeof(ULONG) * MAX_EXT ))
			{
				((ULONG *)newpens)[OLD_PENS     ]   = dr->dri_Pens;
				((ULONG *)newpens)[IMG_SCREEN   ]   = scr;
				((ULONG *)newpens)                 += MAX_EXT;

				CopyMem(dr->dri_Pens,newpens,NUMDRIPENS<<1);
				dr->dri_Pens            = newpens;
				dr->dri_Version         = NEWDRIVERSION;
				newpens[NEWNUMDRIPENS]  = ~0;

				if(i=GetPubScreens(scr,namelist))
				{
					if(exttrymwb[i])
					{
						i=ObtainBestPen(scr->ViewPort.ColorMap,defpens.c1r,defpens.c1g, defpens.c1b,OBP_Precision,PRECISION_IMAGE,TAG_DONE);
						newpens[HALFSHADOWPEN]= i>-1 ? i : penlist[0]->halfdark;
						i=ObtainBestPen(scr->ViewPort.ColorMap,defpens.c2r,defpens.c2g, defpens.c2b,OBP_Precision,PRECISION_IMAGE,TAG_DONE);
						newpens[HALFSHINEPEN] = i>-1 ? i : penlist[0]->halfshine;
						i=ObtainBestPen(scr->ViewPort.ColorMap,defpens.c3r,defpens.c3g, defpens.c3b,OBP_Precision,PRECISION_IMAGE,TAG_DONE);
						newpens[DARKPAINTPEN] = i>-1 ? i : penlist[0]->darkpaint;
						i=ObtainBestPen(scr->ViewPort.ColorMap,defpens.c4r,defpens.c4g, defpens.c4b,OBP_Precision,PRECISION_IMAGE,TAG_DONE);
						newpens[SHINEPAINTPEN]= i>-1 ? i : penlist[0]->shinepaint;
					}
					else
					{
						newpens[HALFSHADOWPEN]=penlist[i]->halfdark;
						newpens[HALFSHINEPEN]= penlist[i]->halfshine;
						newpens[DARKPAINTPEN]= penlist[i]->darkpaint;
						newpens[SHINEPAINTPEN]=penlist[i]->shinepaint;
					}
				}
				else
				{
					if(trymwb)
					{
						i=ObtainBestPen(scr->ViewPort.ColorMap,defpens.c1r,defpens.c1g, defpens.c1b,OBP_Precision,PRECISION_IMAGE,OBP_FailIfBad,TRUE,TAG_DONE);
						newpens[HALFSHADOWPEN]= i>-1 ? i : penlist[0]->halfdark;
						i=ObtainBestPen(scr->ViewPort.ColorMap,defpens.c2r,defpens.c2g, defpens.c2b,OBP_Precision,PRECISION_IMAGE,OBP_FailIfBad,TRUE,TAG_DONE);
						newpens[HALFSHINEPEN] = i>-1 ? i : penlist[0]->halfshine;
						i=ObtainBestPen(scr->ViewPort.ColorMap,defpens.c3r,defpens.c3g, defpens.c3b,OBP_Precision,PRECISION_IMAGE,OBP_FailIfBad,TRUE,TAG_DONE);
						newpens[DARKPAINTPEN] = i>-1 ? i : penlist[0]->darkpaint;
						i=ObtainBestPen(scr->ViewPort.ColorMap,defpens.c4r,defpens.c4g, defpens.c4b,OBP_Precision,PRECISION_IMAGE,OBP_FailIfBad,TRUE,TAG_DONE);
						newpens[SHINEPAINTPEN]= i>-1 ? i : penlist[0]->shinepaint;
					}
					else
					{
						newpens[HALFSHADOWPEN]= penlist[0]->halfdark;
						newpens[HALFSHINEPEN] = penlist[0]->halfshine;
						newpens[DARKPAINTPEN] = penlist[0]->darkpaint;
						newpens[SHINEPAINTPEN]= penlist[0]->shinepaint;
					}
				}
			}
		}
		FreeScreenDrawInfo(scr,dr);
	}
}

__geta4 freeNewPens(__A0 struct Screen *scr)
{
	struct DrawInfo *dr;
	if(dr=GetScreenDrawInfo(scr))
	{
		if(dr->dri_Version==NEWDRIVERSION)
		{
			UWORD *newpens  = dr->dri_Pens;
			dr->dri_Pens    = (UWORD *)((ULONG *)newpens)[(-MAX_EXT)+OLD_PENS];
			dr->dri_Version = DRI_VERSION;

			FreeVecPooled     (((ULONG *)newpens)-MAX_EXT);
		}
		FreeScreenDrawInfo(scr,dr);
	}
}

#define GM_EXTIMG       0x0FAD

__geta4 AddGadgetExtra(__A0 struct Window *win, __A1 struct Gadget *gad)
{
	do
	{
		if(gad->UserData==GADMAGIC)DoMethod(gad,GM_EXTIMG,win->WScreen);
	}
	while(gad=gad->NextGadget);
}


/********************************************************************************/
/* This change is needed for some programs like DeliTrackerII etc...            */
/********************************************************************************/

__geta4 void changeSize(__A0 struct NewWindow *win,__A1 struct TagItem *tags)
{
	struct TagItem  *ti;
	if(tags)
	{
		ULONG flags=GetTagData(WA_Flags,win ? win->Flags : 0 ,tags); /* Oh yeah, I forgot to check if win was TRUE in 1.3 8)) */
		if(flags&WFLG_SIZEGADGET)
		{
			if(flags&WFLG_SIZEBBOTTOM)
			{
				if(ti=FindTagItem(WA_InnerHeight,tags))
				{
					ti->ti_Data+=(b_height-10);
				}
			}
			if(flags&WFLG_SIZEBRIGHT)
			{
				if(ti=FindTagItem(WA_InnerWidth,tags))
				{
					ti->ti_Data+=(b_width-10);
				}
			}
		}
	}
}

/********************************************************************************/
/* standard function for drawing frames, I should convert this to assembler.... */
/********************************************************************************/

void draw_frame(struct RastPort *rp, UWORD x, UWORD y, UWORD width, UWORD height, UWORD col1, UWORD col2, UWORD col3, UWORD col4, UWORD col5, BOOL bg)
{
	if((width>x)&&(height>y))
	{
		UWORD *ptr=rp->AreaPtrn; rp->AreaPtrn=0L;
		SetAPen(rp,col1);
		RectFill(rp,x,y,width,y);
		RectFill(rp,x,y,x,height);
		SetAPen(rp,col2);
		RectFill(rp,width,y,width,height);
		RectFill(rp,x,height,width,height);
		x++;y++;height--;width--;
		if(bg)
		{
			SetAPen(rp,col5);
			RectFill(rp,x+1,y+1,width-1,height-1);
		}
		SetAPen(rp,col3);
		RectFill(rp,x,y,width,y);
		RectFill(rp,x,y,x,height);
		SetAPen(rp,col4);
		RectFill(rp,x,height,width,height);
		RectFill(rp,width,y,width,height);
		rp->AreaPtrn=ptr;
	}
}

void draw_simple(struct RastPort *rp,UWORD x, UWORD y, UWORD width, UWORD height, UWORD col1, UWORD col2)
{
	if((width>x)&&(height>y))
	{
		SetAPen(rp,col1);
		RectFill(rp,x,y,width,y);
		RectFill(rp,x,y,x,height);
		SetAPen(rp,col2);
		RectFill(rp,width,y,width,height);
		RectFill(rp,x,height,width,height);
	}
}

/******************************************************************/
/* FRAMEICLASS Hack                                               */
/******************************************************************/

struct FRAMEData
{
	ULONG type;
	ULONG edgesonly;
	ULONG recessed;
	ULONG data;
	BOOL  yes;
};

BOOL DrawXEN(struct impDraw *imsg,struct FRAMEData *data, struct RastPort *rp, UWORD minx, UWORD miny, UWORD maxx, UWORD maxy, UWORD *pens)
{
	switch (data->type)
	{
		case    FRAME_BUTTON:
				if (imsg->imp_State==IDS_NORMAL)
				{
					if(data->edgesonly)
					{
						if(!data->recessed) draw_frame (rp,minx,miny,maxx,maxy,pens[SHINEPEN],pens[SHADOWPEN],pens[HALFSHINEPEN],pens[HALFSHADOWPEN],0,FALSE);
						else                draw_frame (rp,minx,miny,maxx,maxy,pens[SHADOWPEN],pens[SHINEPEN],pens[HALFSHADOWPEN],pens[HALFSHINEPEN],0,FALSE);
					}
					else
					{
						if(!data->recessed) draw_frame (rp,minx,miny,maxx,maxy,pens[SHADOWPEN],pens[SHADOWPEN],pens[SHINEPEN],pens[HALFSHADOWPEN],pens[HALFSHINEPEN],TRUE);
						else                draw_frame (rp,minx,miny,maxx,maxy,pens[SHADOWPEN],pens[SHADOWPEN],pens[HALFSHADOWPEN],pens[SHINEPEN],pens[BACKGROUNDPEN],TRUE);
					}
				}
				else
				{
					if(data->edgesonly)     draw_frame (rp,minx,miny,maxx,maxy,pens[SHADOWPEN],pens[SHINEPEN],pens[HALFSHADOWPEN],pens[HALFSHINEPEN],0,FALSE);
					else                    draw_frame (rp,minx,miny,maxx,maxy,pens[SHADOWPEN],pens[SHADOWPEN],pens[HALFSHADOWPEN],pens[SHINEPEN],pens[BACKGROUNDPEN],TRUE);
				}
				break;
		case    FRAME_RIDGE:
				if(data->edgesonly)
				{
					if(!data->recessed)     draw_frame (rp,minx,miny,maxx,maxy,pens[SHINEPEN],pens[SHADOWPEN],pens[SHADOWPEN],pens[SHINEPEN],0,FALSE);
					else                    draw_frame (rp,minx,miny,maxx,maxy,pens[SHADOWPEN],pens[SHINEPEN],pens[SHINEPEN],pens[SHADOWPEN],0,FALSE);
				}
				else
				{
					if(!data->recessed)     draw_frame (rp,minx,miny,maxx,maxy,pens[SHINEPEN],pens[SHADOWPEN],pens[SHADOWPEN],pens[SHINEPEN],pens[BACKGROUNDPEN],TRUE);
					else                    draw_frame (rp,minx,miny,maxx,maxy,pens[SHADOWPEN],pens[SHINEPEN],pens[SHINEPEN],pens[SHADOWPEN],pens[BACKGROUNDPEN],TRUE);
				}
				break;
	}
	return(TRUE);
}

BOOL DrawX(struct impDraw *imsg,struct FRAMEData *data, struct RastPort *rp, UWORD minx, UWORD miny, UWORD maxx, UWORD maxy, UWORD *pens)
{
	switch (data->type)
	{
		case    FRAME_DEFAULT:
		case    FRAME_BUTTON:
				if (imsg->imp_State==IDS_NORMAL)
				{
					if(data->edgesonly)
					{
						if(!data->recessed) draw_frame (rp,minx,miny,maxx,maxy,pens[SHINEPEN],pens[HALFSHADOWPEN],pens[SHINEPEN],pens[HALFSHADOWPEN],0,FALSE);
						else                draw_frame (rp,minx,miny,maxx,maxy,pens[HALFSHADOWPEN],pens[SHINEPEN],pens[HALFSHADOWPEN],pens[SHINEPEN],0,FALSE);
					}
					else
					{
						if(!data->recessed) draw_frame (rp,minx,miny,maxx,maxy,pens[SHINEPEN],pens[HALFSHADOWPEN],pens[SHINEPEN],pens[HALFSHADOWPEN],pens[HALFSHINEPEN],TRUE);
						else                draw_frame (rp,minx,miny,maxx,maxy,pens[HALFSHADOWPEN],pens[SHINEPEN],pens[HALFSHADOWPEN],pens[SHINEPEN],pens[BACKGROUNDPEN],TRUE);
					}
				}
				else
				{
					if(data->edgesonly)     draw_frame (rp,minx,miny,maxx,maxy,pens[HALFSHADOWPEN],pens[SHINEPEN],pens[HALFSHADOWPEN],pens[SHINEPEN],0,FALSE);
					else                    draw_frame (rp,minx,miny,maxx,maxy,pens[HALFSHADOWPEN],pens[SHINEPEN],pens[HALFSHADOWPEN],pens[SHINEPEN],pens[BACKGROUNDPEN],TRUE);
				}
				break;
		case    FRAME_RIDGE:
				if(data->edgesonly)
				{
					if(!data->recessed)     draw_frame (rp,minx,miny,maxx,maxy,pens[SHINEPEN],pens[HALFSHADOWPEN],pens[HALFSHADOWPEN],pens[SHINEPEN],0,FALSE);
					else                    draw_frame (rp,minx,miny,maxx,maxy,pens[HALFSHADOWPEN],pens[SHINEPEN],pens[SHINEPEN],pens[HALFSHADOWPEN],0,FALSE);
				}
				else
				{
					if(!data->recessed)     draw_frame (rp,minx,miny,maxx,maxy,pens[SHINEPEN],pens[HALFSHADOWPEN],pens[HALFSHADOWPEN],pens[SHINEPEN],pens[BACKGROUNDPEN],TRUE);
					else                    draw_frame (rp,minx,miny,maxx,maxy,pens[HALFSHADOWPEN],pens[SHINEPEN],pens[SHINEPEN],pens[HALFSHADOWPEN],pens[BACKGROUNDPEN],TRUE);
				}
				break;
	}
	return(TRUE);
}

BOOL fstrcmp(UBYTE *str1, UBYTE *str2)
{
	int i;
	for(i=0;str1[i]&&str2[i];i++) if(str1[i]!=str2[i])  return(FALSE);
	if((!str1[i])&&(!str2[i]))                          return(TRUE);
	else                                                return(FALSE);
}

BOOPSI_Class(initFRAMEClass,dispatchFRAME,"frameiclass","breizhclass",NULL,FRAMEData, 0)

	BOOPSI_Method(OM_NEW)
	{
		ULONG   type,edgesonly,recessed;
		type      =GetTagData(IA_FrameType,0L,((struct opSet *)msg)->ops_AttrList);
		edgesonly =GetTagData(IA_EdgesOnly,0L,((struct opSet *)msg)->ops_AttrList);
		recessed  =GetTagData(IA_Recessed ,0L,((struct opSet *)msg)->ops_AttrList);
		if(object=(Object *)DoSuperMethodA(cl,object,msg))
		{
			struct Task *task=(struct Task *)FindTask(NULL);

			BOOPSI_InitData
			data->type      =type;
			data->edgesonly =edgesonly;
			data->recessed  =recessed;
			data->yes       =TRUE;
		}
		return(object);
	}
	BOOPSI_Method_End

	BOOPSI_Method(IM_DRAWFRAME)
	BOOPSI_Method(IM_DRAW)
	{
		BOOPSI_InitData

		if(data->yes)
		if((data->type==FRAME_BUTTON)|(data->type==FRAME_RIDGE))
		{
			struct  impDraw     *imsg;
			imsg=(struct impDraw *)msg;
			if(imsg->imp_DrInfo)
			{
				UWORD   *pens;
				pens=imsg->imp_DrInfo->dri_Pens;
				if(imsg->imp_DrInfo->dri_Version==NEWDRIVERSION)
				{
					UWORD   minx,miny,maxx,maxy;
					struct  RastPort    *rp;
					rp  =imsg->imp_RPort;
					minx=imsg->imp_Offset.X+((struct Image *)object)->LeftEdge;
					miny=imsg->imp_Offset.Y+((struct Image *)object)->TopEdge;
					maxx=minx+((msg->MethodID==IM_DRAWFRAME) ? imsg->imp_Dimensions.Width  : ((struct Image *)object)->Width )-1;
					maxy=miny+((msg->MethodID==IM_DRAWFRAME) ? imsg->imp_Dimensions.Height : ((struct Image *)object)->Height)-1;
					if(XStyle)
					{
						return(DrawX(imsg,data,rp,minx,miny,maxx,maxy,pens));
					}
					else
					{
						return(DrawXEN(imsg,data,rp,minx,miny,maxx,maxy,pens));
					}
				}
			}
		}
		BOOPSI_Method_SuperReturn
	}
	BOOPSI_Method_End

	BOOPSI_Method_SuperDefault

BOOPSI_End

/******************************************************************/
/* ImageLoadTask                                                  */
/******************************************************************/

#define IML_LOAD    1
#define IML_FREE    0

struct iht_msg
{
	struct  Message ts_Message;

	ULONG           MethodID;

	char            *file;
	char            *screen;
	Object          *object;
	struct  BitMap  *bitmap;
	struct BitMapHeader *bmhd;
};

BOOL PutToPort(struct Message *message)
{
	struct MsgPort *port;

	Forbid();
	port = (struct MsgPort *)FindPort("UrouHack ImageLoader");
	if (port) PutMsg(port, (struct Message *) message);
	Permit();
	return(port ? TRUE : FALSE);
}

__geta4 void ImageLoaderTask(void)
{
	struct MsgPort  *ilt_port;
	ULONG            ilt_mask;
	struct iht_msg  *msg;

	if(ilt_port=(struct MsgPort *)CreatePort("UrouHack ImageLoader",0))
	{
		ilt_mask = 1L << (ilt_port->mp_SigBit);
		for(;;)
		{
			Wait(ilt_mask);
			while(msg=(struct iht_msg *)GetMsg(ilt_port))
			{
				if(DataTypesBase==(struct Library *)2L)DataTypesBase=(struct Library *)OpenLibrary("datatypes.library",0L);
				if(DataTypesBase)
				{
					if(msg->MethodID==IML_LOAD)
					{
						msg->object=NULL;
						if(msg->file&&msg->screen)
						{
							if (msg->object = (Object *)NewDTObject(msg->file,
								DTA_GroupID          ,GID_PICTURE,
								PDTA_Screen          ,msg->screen,
								PDTA_FreeSourceBitMap,TRUE,
								OBP_Precision        ,PRECISION_GUI,
								TAG_DONE))
							if (!DoDTMethod(msg->object,NULL,NULL,DTM_PROCLAYOUT,NULL,1))
							{
								DisposeDTObject(msg->object);
								msg->object=NULL;
							}
												GetDTAttrs(msg->object,PDTA_BitMapHeader,&msg->bmhd,PDTA_DestBitMap,&msg->bitmap,TAG_DONE);
							if (&msg->bitmap)   GetDTAttrs(msg->object,PDTA_BitMap,                                 &msg->bitmap,TAG_DONE);
						}
					}
					else
					{
						if(msg->object) DisposeDTObject(msg->object);
					}
				}
				ReplyMsg(msg);
			}
		}
	}
	Wait(0L);
}

/********************************************************************/
/* GADCLASS Hack                                                    */
/********************************************************************/

#define BTOP_NONE       0
#define BTOP_KINGCON    1

#define ICONIFYIMAGE    (0x12L)
#define SNAPIMAGE       (0x13L)
#define POPIMAGE        (0x14L)
#define MUIIMAGE        (0x15L)

struct GADData
{
	UWORD           btop;
	UWORD           load;
	Object         *image;
};

struct gpExtra
{
	ULONG           MethodID;
	struct Screen  *scr;
}

show(char *msg)
{
	static struct EasyStruct easymsg =
	{
	sizeof(struct EasyStruct),
	0,
	"UrouHack information",
	0L,
	"OK"
	};
	easymsg.es_TextFormat=msg;
	EasyRequest(NULL, &easymsg, NULL);
}

BOOPSI_Class(initGADClass, dispatchGADClass, "buttongclass","tinicclass",NULL,GADData, 0)

	BOOPSI_Method(OM_NEW)
	{
		ULONG type          = GetTagData  (GA_SysGType,0L,((struct opSet *)msg)->ops_AttrList);
		ULONG btop          = FindTagItem (GA_TopBorder,((struct opSet *)msg)->ops_AttrList);
		ULONG *bd           = (struct Image *)GetTagData  (GA_Image,0L,((struct opSet *)msg)->ops_AttrList);

		if(object=(Object *)DoSuperMethodA(cl,object,msg))
		{
			BOOPSI_InitData

			data->btop=BTOP_NONE;
			if(type==GTYP_SIZING)
			{
				SetAttrs(object,GA_RelBottom,1-((struct Gadget *)(object))->Height,
								GA_RelRight, 1-((struct Gadget *)(object))->Width,
								TAG_DONE);
			}           
			else if(btop)
			{
				struct Task *task=(struct Task *)FindTask(NULL);
				if(fstrcmp("CON",task->tc_Node.ln_Name))
				{
					data->btop =BTOP_KINGCON;
					data->load =TRUE;
					((struct Gadget *)object)->UserData=GADMAGIC;
				}
			}
		}
		return(object);
	}
	BOOPSI_Method_End

	BOOPSI_Method(GM_EXTIMG)

		struct DrawInfo *dr;

		BOOPSI_InitData

		if(dr=GetScreenDrawInfo(((struct gpExtra *)msg)->scr))
		{
			if(data->btop==BTOP_KINGCON)
			{
				((struct Gadget *)object)->LeftEdge++;
				if(data->load)
				{
					if(data->image=(Object *)NewObject(NULL, "sysiclass",
						IA_Top,         0,
						IA_Left,        0,
						IA_Height,      ((struct Gadget *)object)->Height,
						IA_Width,       ((struct Gadget *)object)->Width,
						SYSIA_Which,    ICONIFYIMAGE,
						SYSIA_DrawInfo, dr,
					TAG_DONE))
					SetAttrs(object,GA_Image,data->image,TAG_DONE);
					data->load=FALSE;
				}
			}
			FreeScreenDrawInfo(((struct gpExtra *)msg)->scr,dr);
		}
		return(NULL);

	BOOPSI_Method_End

	BOOPSI_Method(OM_DISPOSE)

		BOOPSI_InitData

		if(data->image)DisposeObject(data->image);

		BOOPSI_Method_SuperReturn

	BOOPSI_Method_End

	BOOPSI_Method_SuperDefault

BOOPSI_End

/********************************************************************/
/* PROPCLASS Hack                                                   */
/********************************************************************/

struct PROPData
{
	ULONG dummy;
};

BOOPSI_Class(initPROPClass, dispatchPROPClass, "propgclass","gwenclass",NULL,PROPData, 0)

	BOOPSI_Method(GM_HANDLEINPUT)

		BOOPSI_Method_SuperReturn;

	BOOPSI_Method_End

	BOOPSI_Method(GM_GOACTIVE)

		BOOPSI_Method_SuperReturn;

	BOOPSI_Method_End

	BOOPSI_Method(GM_GOINACTIVE)

		BOOPSI_Method_SuperReturn;

	BOOPSI_Method_End

	BOOPSI_Method(GM_RENDER)
	{
		WORD    minx,miny,maxx,maxy;
		struct  RastPort    *rp     = ((struct gpRender *)msg)->gpr_RPort;
		struct  DrawInfo    *di     = ((struct gpRender *)msg)->gpr_GInfo->gi_DrInfo;
		UWORD               *pens   = di->dri_Pens;

		if(di&&rp)
		{
			if(di->dri_Version==NEWDRIVERSION)
			{
				minx=((struct Gadget *)object)->LeftEdge;
				miny=((struct Gadget *)object)->TopEdge;
				maxx=((struct Gadget *)object)->Width  - 1;
				maxy=((struct Gadget *)object)->Height - 1;                
				if(minx<0)
				{
					minx=((struct gpRender *)msg)->gpr_GInfo->gi_Window->Width+minx-1;
				}
				if(maxx<0)
				{
					maxx=((struct gpRender *)msg)->gpr_GInfo->gi_Window->Width+maxx+((struct gpRender *)msg)->gpr_GInfo->gi_Window->BorderLeft;
				}
				else maxx+=minx;
				if(miny<0)
				{
					miny=((struct gpRender *)msg)->gpr_GInfo->gi_Window->Height+miny-1;
				}
				if(maxy<0)
				{
					maxy=((struct gpRender *)msg)->gpr_GInfo->gi_Window->Height+maxy+((struct gpRender *)msg)->gpr_GInfo->gi_Window->BorderTop;
				}
				else maxy+=miny;
				draw_frame (rp,minx,miny,maxx,maxy,pens[SHADOWPEN],pens[SHADOWPEN],pens[HALFSHADOWPEN],pens[SHINEPEN],pens[BACKGROUNDPEN],TRUE);
				return(NULL);
			}
		}
		BOOPSI_Method_SuperReturn;
	}
	BOOPSI_Method_End

	BOOPSI_Method_SuperDefault

BOOPSI_End

/******************************************************************/
/* SYSIClass Hack                                                 */
/******************************************************************/

struct SYSIData
{
	UWORD            what;
	struct  BitMap  *image;
	Object          *dtobj;
	BOOL             fixed;
	UWORD            w,h;
	struct Screen   *scr;
	BOOL             init;
};

struct BitMap *allocBM(Object *object, char *type_sel, struct SYSIData *data )
{
	struct  BitMap       *srcbmp=NULL;
	char    filnam[256]="s:urouhack/", foo[32];
	ULONG   w,h;

	GetAttr(IA_Height,object,&h);
	GetAttr(IA_Width, object,&w);

	if(imagestyle)
	{
		struct MsgPort *port;
		if(port= CreatePort(0,0))
		{
			struct iht_msg  *msg;
			if(msg = (struct iht_msg *)AllocVecPooled(swim_in_my_pool,sizeof(struct iht_msg)))
			{
				strcat(filnam,imagestyle); strcat(filnam,type_sel); sprintf(foo,"%dx%d",w,h); strcat(filnam,foo);
				msg->ts_Message.mn_Node.ln_Type  = NT_MESSAGE;
				msg->ts_Message.mn_ReplyPort     = port;
				msg->ts_Message.mn_Length        = sizeof ( struct iht_msg );
				msg->file                        = filnam;
				msg->screen                      = data->scr;
				msg->MethodID                    = IML_LOAD;
				if(PutToPort(msg))
				{
					WaitPort(port);
					if(msg=(struct iht_msg *)GetMsg(port))
					{
						if(data->dtobj=msg->object)
						{
							srcbmp=msg->bitmap;
							data->fixed=FALSE;
						}
						else
						{
							strcpy(filnam,"s:urouhack/"); strcat(filnam,imagestyle); strcat(filnam,type_sel); strcat(filnam,"fixed");
							msg->ts_Message.mn_Node.ln_Type  = NT_MESSAGE;
							msg->ts_Message.mn_ReplyPort     = port;
							msg->ts_Message.mn_Length        = sizeof ( struct iht_msg );
							msg->file                        = filnam;
							msg->screen                      = data->scr;
							msg->MethodID                    = IML_LOAD;
							if(PutToPort(msg))
							{
								WaitPort(port);
								if(msg=(struct iht_msg *)GetMsg(port))
								{
									if(data->dtobj=msg->object)
									{
										struct BitMapHeader *bmhd=msg->bmhd;
										srcbmp                   =msg->bitmap;
										data->w=bmhd->bmh_Width/3;
										data->h=bmhd->bmh_Height;
										data->fixed=TRUE;
									}
									else
									{
										strcpy(filnam,"s:urouhack/"); strcat(filnam,imagestyle); strcat(filnam,type_sel); strcat(filnam,"scale");
										msg->ts_Message.mn_Node.ln_Type  = NT_MESSAGE;
										msg->ts_Message.mn_ReplyPort     = port;
										msg->ts_Message.mn_Length        = sizeof ( struct iht_msg );
										msg->file                        = filnam;
										msg->screen                      = data->scr;
										msg->MethodID                    = IML_LOAD;
										if(PutToPort(msg))
										{
											WaitPort(port);
											if(msg=(struct iht_msg *)GetMsg(port))
											{
												if(data->dtobj=msg->object)
												{
													struct BitMapHeader *bmhd=NULL;
													struct BitMap       *bm=NULL;
													srcbmp=msg->bitmap;
													bmhd  =msg->bmhd;
													if(srcbmp&&bmhd)
													{
														if(bm = (struct BitMap *)AllocBitMap(w+w+w,h,srcbmp->Depth,NULL,NULL))
														{
															struct BitScaleArgs bsa=
															{
																0,0,
																bmhd->bmh_Width,bmhd->bmh_Height,
																bmhd->bmh_Width,bmhd->bmh_Height,
																0,0,
																0,0,
																w+w+w,h,
																srcbmp,
																bm,
																NULL,
																NULL,NULL,
																NULL,
																NULL
															};
															BitMapScale(&bsa);
															FreeVecPooled(msg);
															DeletePort(port);
															return(bm);
														}
														else
														{
															bm=NULL;
															srcbmp=NULL;
														}
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
				FreeVecPooled(msg);
			}
			DeletePort(port);
		}
	}
	return(srcbmp);
}

ULONG DrawUrou(struct SYSIData *data,struct impDraw *imsg,Object *object, Class *cl, Msg msg)
{
	UWORD   y_size,dummy,minx,miny,maxx,maxy;
	struct  RastPort    *rp;
	UWORD   *pens;
	pens=imsg->imp_DrInfo->dri_Pens;
	rp=imsg->imp_RPort;
	y_size=((struct Image *)object)->Height-1;
	dummy=(y_size+1)>>1;
	minx=imsg->imp_Offset.X+((struct Image *)object)->LeftEdge;
	miny=imsg->imp_Offset.Y+((struct Image *)object)->TopEdge;
	maxx=minx+((struct Image *)object)->Width-1;
	maxy=miny+((struct Image *)object)->Height-1;

	switch (data->what)
	{
		case    SDEPTHIMAGE:
				SetAPen(rp,pens[BACKGROUNDPEN]);
				RectFill(rp,minx+1,miny+1,maxx-1,maxy-1);
		case    ZOOMIMAGE:
		case    DEPTHIMAGE:
		case    ICONIFYIMAGE:
				minx++;
		case    LEFTIMAGE:
		case    UPIMAGE:
		case    DOWNIMAGE:
		case    RIGHTIMAGE:
		case    SIZEIMAGE:
		case    CLOSEIMAGE:
				if(XStyle)
				{
					if(imsg->imp_State==IDS_SELECTED) draw_frame (rp,minx,miny,maxx,maxy,pens[HALFSHADOWPEN],pens[SHINEPEN],pens[HALFSHADOWPEN],pens[SHINEPEN],pens[HALFSHINEPEN],TRUE);
					else                              draw_frame (rp,minx,miny,maxx,maxy,pens[SHINEPEN],pens[HALFSHADOWPEN],pens[SHINEPEN],pens[HALFSHADOWPEN],pens[HALFSHINEPEN],TRUE);
				}
				else
				{
					if(imsg->imp_State==IDS_SELECTED) draw_frame (rp,minx,miny,maxx,maxy,pens[SHADOWPEN],pens[SHINEPEN],pens[HALFSHADOWPEN],pens[HALFSHINEPEN],pens[BACKGROUNDPEN],TRUE);
					else                              draw_frame (rp,minx,miny,maxx,maxy,pens[SHINEPEN],pens[SHADOWPEN],pens[HALFSHINEPEN],pens[HALFSHADOWPEN],pens[BACKGROUNDPEN],TRUE);
				}
				break;
	};
	switch (data->what)
	{
		case    LEFTIMAGE:
				SetAPen(rp,pens[SHADOWPEN]);
				Move(rp,minx+3,miny+dummy);
				Draw(rp,maxx-3,maxy-3);
				Draw(rp,maxx-3,miny+3);
				SetAPen(rp,pens[SHINEPEN]);
				Draw(rp,minx+3,maxy-dummy);
				return(0L);
		case    RIGHTIMAGE:
				SetAPen(rp,pens[SHINEPEN]);
				Move(rp,maxx-3,maxy-dummy);
				Draw(rp,minx+3,miny+3);
				Draw(rp,minx+3,maxy-3);
				SetAPen(rp,pens[SHADOWPEN]);
				Draw(rp,maxx-3,miny+dummy);
				return(0L);
		case    UPIMAGE:
				SetAPen(rp,pens[SHADOWPEN]);
				Move(rp,maxx-((maxx-minx)>>1),miny+3);
				Draw(rp,maxx-3,maxy-3);
				Draw(rp,minx+3,maxy-3);
				SetAPen(rp,pens[SHINEPEN]);
				Draw(rp,minx+((maxx-minx)>>1),miny+3);
				return(0L);
		case    DOWNIMAGE:
				SetAPen(rp,pens[SHADOWPEN]);
				Move(rp,maxx-((maxx-minx)>>1),maxy-3);
				Draw(rp,maxx-3,miny+3);
				SetAPen(rp,pens[SHINEPEN]);
				Draw(rp,minx+3,miny+3);
				Draw(rp,minx+((maxx-minx)>>1),maxy-3);
				return(0L);
				break;
		case    SIZEIMAGE:
				switch (imsg->imp_State)
				{
					case    IDS_NORMAL:
					case    IDS_SELECTED:
							SetAPen(rp,pens[FILLPEN]);
							RectFill(rp,minx+1,miny+1,minx+((maxx-minx)>>1)-1,miny+dummy-1);
							break;
				}
				SetAPen(rp,pens[SHADOWPEN]);
				RectFill(rp,minx+1,miny+dummy,minx+((maxx-minx)>>1),miny+dummy);
				RectFill(rp,minx+((maxx-minx)>>1),miny+1,minx+((maxx-minx)>>1),miny+dummy);
				SetAPen(rp,pens[SHINEPEN]);
				RectFill(rp,minx+1,miny+dummy+1,minx+((maxx-minx)>>1)+1,miny+dummy+1);
				RectFill(rp,minx+((maxx-minx)>>1)+1,miny+1,minx+((maxx-minx)>>1)+1,miny+dummy+1);
				return(0L);
		case    CLOSEIMAGE:
				SetAPen(rp,pens[SHINEPEN]);
				RectFill(rp,maxx+1,miny+1,maxx+1,maxy);
				switch (imsg->imp_State)
				{
					case    IDS_NORMAL:
							SetAPen(rp,pens[SHINEPEN]);
							RectFill(rp,minx+4,miny+dummy-2,maxx-4,miny+dummy-2);
							RectFill(rp,minx+4,miny+dummy-2,minx+4,miny+dummy+1);
							SetAPen(rp,pens[SHADOWPEN]);
							RectFill(rp,minx+4,miny+dummy+1,maxx-4,miny+dummy+1);
							RectFill(rp,maxx-4,miny+dummy-2,maxx-4,miny+dummy+1);
							SetAPen(rp,pens[FILLPEN]);
							RectFill(rp,minx+5,miny+dummy-1,maxx-5,miny+dummy);
							break;
					case    IDS_SELECTED:
							RectFill(rp,minx+6,miny+dummy-2,maxx-6,miny+dummy-2);
							RectFill(rp,minx+6,miny+dummy-2,minx+6,miny+dummy+1);
							SetAPen(rp,pens[SHADOWPEN]);
							RectFill(rp,minx+6,miny+dummy+1,maxx-6,miny+dummy+1);
							RectFill(rp,maxx-6,miny+dummy-2,maxx-6,miny+dummy+1);
							SetAPen(rp,pens[FILLPEN]);
							RectFill(rp,minx+7,miny+dummy-1,maxx-7,miny+dummy);
							break;
					default:
							SetAPen(rp,pens[SHINEPEN]);
							RectFill(rp,minx+4,miny+dummy-2,maxx-4,miny+dummy-2);
							RectFill(rp,minx+4,miny+dummy-2,minx+4,miny+dummy+1);
							SetAPen(rp,pens[SHADOWPEN]);
							RectFill(rp,minx+4,miny+dummy+1,maxx-4,miny+dummy+1);
							RectFill(rp,maxx-4,miny+dummy-2,maxx-4,miny+dummy+1);
							break;
				}
				return(0L);
		case    DEPTHIMAGE:
		case    SDEPTHIMAGE:
				minx--;
				SetAPen(rp,pens[SHADOWPEN]);
				RectFill(rp,minx,miny+1,minx,maxy);
				switch (imsg->imp_State)
				{
					case    IDS_NORMAL:
							draw_simple(rp,minx+((maxx-minx)>>1)-1,miny+5,maxx-3,maxy-3,pens[SHINEPEN],pens[SHADOWPEN]);
							draw_simple(rp,minx+4,miny+3,minx+((maxx-minx)>>1)+3,maxy-5,pens[SHINEPEN],pens[SHADOWPEN]);
							SetAPen(rp,pens[FILLPEN]);
							RectFill(rp,minx+5,miny+4,minx+((maxx-minx)>>1)+2,maxy-6);
							break;
					case    IDS_SELECTED:
							draw_simple(rp,minx+4,miny+3,minx+((maxx-minx)>>1)+3,maxy-5,pens[SHINEPEN],pens[SHADOWPEN]);
							draw_simple(rp,minx+((maxx-minx)>>1)-1,miny+5,maxx-3,maxy-3,pens[SHINEPEN],pens[SHADOWPEN]);
							SetAPen(rp,pens[FILLPEN]);
							RectFill(rp,minx+((maxx-minx)>>1),miny+6,maxx-4,maxy-4);
							break;
					default:
							draw_simple(rp,minx+((maxx-minx)>>1)-1,miny+5,maxx-3,maxy-3,pens[SHINEPEN],pens[SHADOWPEN]);
							draw_simple(rp,minx+4,miny+3,minx+((maxx-minx)>>1)+3,maxy-5,pens[SHINEPEN],pens[SHADOWPEN]);
							SetAPen(rp,pens[BACKGROUNDPEN]);
							RectFill(rp,minx+5,miny+4,minx+((maxx-minx)>>1)+2,maxy-6);
							break;
				}
				return(0L);
		case    ZOOMIMAGE:
				minx--;
				SetAPen(rp,pens[SHADOWPEN]);
				RectFill(rp,minx,miny+1,minx,maxy);
				draw_simple(rp,minx+((maxx-minx)>>1)-1,miny+dummy-1,maxx-((maxx-minx)>>1)+2,miny+dummy,pens[SHADOWPEN],pens[SHINEPEN]);
				return(0L);
		case    ICONIFYIMAGE:
				minx--;
				SetAPen(rp,pens[SHADOWPEN]);
				RectFill(rp,minx,miny+1,minx,maxy);
				draw_simple(rp,minx+5,maxy-((y_size-3)>>1)-1,maxx-(((maxx-minx)-2)>>1),maxy-4,pens[SHINEPEN],pens[SHADOWPEN]);
				return(0L);
		default:
				BOOPSI_Method_SuperReturn
	}
}

ULONG DrawSysiHack(struct SYSIData *data,struct impDraw *imsg,Object *object, Class *cl, Msg msg)
{
	UWORD   y_size,dummy,minx,miny,maxx,maxy,h,w;
	struct  RastPort    *rp;
	UWORD   *pens;
	pens=imsg->imp_DrInfo->dri_Pens;
	rp=imsg->imp_RPort;
	y_size=((struct Image *)object)->Height-1;
	dummy=(y_size+1)>>1;
	minx=imsg->imp_Offset.X+((struct Image *)object)->LeftEdge;
	miny=imsg->imp_Offset.Y+((struct Image *)object)->TopEdge;
	w=((struct Image *)object)->Width;
	h=((struct Image *)object)->Height;
	maxx=minx+w-1;
	maxy=miny+h-1;

	switch (data->what)
	{
		case    ZOOMIMAGE:
		case    DEPTHIMAGE:
		case    ICONIFYIMAGE:
				minx++;
		case    LEFTIMAGE:
		case    UPIMAGE:
		case    DOWNIMAGE:
		case    RIGHTIMAGE:
		case    SIZEIMAGE:
		case    CLOSEIMAGE:
				switch(imsg->imp_State)
				{
					case    IDS_SELECTED:
					case    IDS_NORMAL:
							SetAPen(rp,pens[FILLPEN]);
							break;
					default:
							SetAPen(rp,pens[BACKGROUNDPEN]);
							break;
				}
				RectFill(rp,minx+1,miny+1,maxx-1,maxy-1);
				draw_simple(rp,minx,miny,maxx,maxy,pens[SHINEPEN],pens[SHADOWPEN]);
				break;
		case    SDEPTHIMAGE:
				SetAPen(rp,pens[BACKGROUNDPEN]);
				RectFill(rp,minx+1,miny+1,maxx-1,maxy-1);
				if(imsg->imp_State==IDS_SELECTED) draw_simple(rp,minx+1,miny,maxx,maxy,pens[SHADOWPEN],pens[SHINEPEN]);
				else                              draw_simple(rp,minx+1,miny,maxx,maxy,pens[SHINEPEN],pens[SHADOWPEN]);
				break;
	};
	switch (data->what)
	{
		case    LEFTIMAGE:
				SetAPen(rp,pens[SHADOWPEN]);
				Move(rp,minx+3,miny+dummy);
				Draw(rp,maxx-3,maxy-3);
				Draw(rp,maxx-3,miny+3);
				SetAPen(rp,pens[SHINEPEN]);
				Draw(rp,minx+3,maxy-dummy);
				return(0L);
		case    RIGHTIMAGE:
				SetAPen(rp,pens[SHINEPEN]);
				Move(rp,maxx-3,maxy-dummy);
				Draw(rp,minx+3,miny+3);
				Draw(rp,minx+3,maxy-3);
				SetAPen(rp,pens[SHADOWPEN]);
				Draw(rp,maxx-3,miny+dummy);
				return(0L);
		case    UPIMAGE:
				SetAPen(rp,pens[SHADOWPEN]);
				Move(rp,maxx-((maxx-minx)>>1),miny+3);
				Draw(rp,maxx-3,maxy-3);
				Draw(rp,minx+3,maxy-3);
				SetAPen(rp,pens[SHINEPEN]);
				Draw(rp,minx+((maxx-minx)>>1),miny+3);
				return(0L);
		case    DOWNIMAGE:
				SetAPen(rp,pens[SHADOWPEN]);
				Move(rp,maxx-((maxx-minx)>>1),maxy-3);
				Draw(rp,maxx-3,miny+3);
				SetAPen(rp,pens[SHINEPEN]);
				Draw(rp,minx+3,miny+3);
				Draw(rp,minx+((maxx-minx)>>1),maxy-3);
				return(0L);
				break;
		case    ZOOMIMAGE:
				minx--;
				SetAPen(rp,pens[SHADOWPEN]);
				RectFill(rp,minx,miny+1,minx,maxy);
				if(imsg->imp_State==IDS_SELECTED)
				{
					draw_simple(rp,minx+4,miny+3,maxx-4,maxy-3,pens[SHINEPEN],pens[SHADOWPEN]);
					draw_simple(rp,minx+5,miny+4,maxx-((w-4)>>1),maxy-((h-4)>>1)-1,pens[SHADOWPEN],pens[SHINEPEN]);
				}
				else
				{
					draw_simple(rp,minx+4,miny+3,maxx-4,maxy-3,pens[SHADOWPEN],pens[SHINEPEN]);
					draw_simple(rp,minx+5,miny+4,maxx-((w-4)>>1),maxy-((h-4)>>1)-1,pens[SHINEPEN],pens[SHADOWPEN]);
				}
				return(0L);
		case    CLOSEIMAGE:
				{
					UWORD foo,fao;
					SetAPen(rp,pens[SHINEPEN]);
					RectFill(rp,maxx+1,miny+1,maxx+1,maxy);
					foo=(h-1)/3;
					fao=(w-1)/3;
					if(imsg->imp_State==IDS_SELECTED)
					{

						draw_simple(rp,minx+fao+1,miny+foo+1,maxx-fao-1,maxy-foo-1,pens[SHADOWPEN],pens[SHINEPEN]);
					}
					else
					{
						draw_simple(rp,minx+fao,miny+foo,maxx-fao,maxy-foo,pens[SHADOWPEN],pens[SHINEPEN]);
					}
				}
				return(0L);
		case    DEPTHIMAGE:
				minx--;
				SetAPen(rp,pens[SHADOWPEN]);
				RectFill(rp,minx,miny+1,minx,maxy);
				switch (imsg->imp_State)
				{
					case    IDS_NORMAL:
							draw_simple(rp,minx+((maxx-minx)>>1)-1,miny+5,maxx-3,maxy-2,pens[SHINEPEN],pens[SHADOWPEN]);
							draw_simple(rp,minx+4,miny+3,minx+((maxx-minx)>>1)+3,maxy-4,pens[SHADOWPEN],pens[SHINEPEN]);
							SetAPen(rp,pens[FILLPEN]);
							RectFill(rp,minx+((maxx-minx)>>1),miny+6,maxx-4,maxy-3);
							break;
					case    IDS_SELECTED:
							draw_simple(rp,minx+4,miny+3,minx+((maxx-minx)>>1)+3,maxy-4,pens[SHINEPEN],pens[SHADOWPEN]);
							draw_simple(rp,minx+((maxx-minx)>>1)-1,miny+5,maxx-3,maxy-2,pens[SHINEPEN],pens[SHADOWPEN]);
							break;
					default:
							draw_simple(rp,minx+((maxx-minx)>>1)-1,miny+5,maxx-3,maxy-2,pens[SHINEPEN],pens[SHADOWPEN]);
							draw_simple(rp,minx+4,miny+3,minx+((maxx-minx)>>1)+3,maxy-4,pens[SHADOWPEN],pens[SHINEPEN]);
							SetAPen(rp,pens[BACKGROUNDPEN]);
							RectFill(rp,minx+((maxx-minx)>>1),miny+6,maxx-4,maxy-3);
							break;
				}
				return(0L);
		case    ICONIFYIMAGE:
				minx--;
				SetAPen(rp,pens[SHADOWPEN]);
				RectFill(rp,minx,miny+1,minx,maxy);
				if(imsg->imp_State==IDS_SELECTED)
				{
					draw_simple(rp,minx+4,miny+3,maxx-4,maxy-3,pens[SHINEPEN],pens[SHADOWPEN]);
					draw_simple(rp,minx+5,maxy-((h-4)>>1)-1,maxx-((w-4)>>1),maxy-4,pens[SHADOWPEN],pens[SHINEPEN]);
				}
				else
				{
					draw_simple(rp,minx+4,miny+3,maxx-4,maxy-3,pens[SHADOWPEN],pens[SHINEPEN]);
					draw_simple(rp,minx+5,maxy-((h-4)>>1)-1,maxx-((w-4)>>1),maxy-4,pens[SHINEPEN],pens[SHADOWPEN]);
				}
				return(0L);
		case    SDEPTHIMAGE:
				SetAPen(rp,pens[SHADOWPEN]);
				RectFill(rp,minx,miny+1,minx,maxy);
				switch (imsg->imp_State)
				{
					case    IDS_NORMAL:
							draw_simple(rp,minx+((maxx-minx)>>1)-1,miny+5,maxx-3,maxy-2,pens[SHINEPEN],pens[SHADOWPEN]);
							draw_simple(rp,minx+4,miny+3,minx+((maxx-minx)>>1)+3,maxy-4,pens[SHADOWPEN],pens[SHINEPEN]);
							SetAPen(rp,pens[BACKGROUNDPEN]);
							RectFill(rp,minx+((maxx-minx)>>1),miny+6,maxx-4,maxy-3);
							break;
					case    IDS_SELECTED:
							draw_simple(rp,minx+4,miny+3,minx+((maxx-minx)>>1)+3,maxy-4,pens[SHINEPEN],pens[SHADOWPEN]);
							draw_simple(rp,minx+((maxx-minx)>>1)-1,miny+5,maxx-3,maxy-2,pens[SHINEPEN],pens[SHADOWPEN]);
							break;
					default:
							draw_simple(rp,minx+((maxx-minx)>>1)-1,miny+5,maxx-3,maxy-2,pens[SHINEPEN],pens[SHADOWPEN]);
							draw_simple(rp,minx+4,miny+3,minx+((maxx-minx)>>1)+3,maxy-4,pens[SHADOWPEN],pens[SHINEPEN]);
							SetAPen(rp,pens[BACKGROUNDPEN]);
							RectFill(rp,minx+((maxx-minx)>>1),miny+6,maxx-4,maxy-3);
							break;
				}
				return(0L);
		case    SIZEIMAGE:
				minx--;
				SetAPen(rp,pens[SHADOWPEN]);
				Move(rp,maxx-3,miny+3);
				Draw(rp,maxx-3,maxy-3);
				Draw(rp,minx+3,maxy-3);
				SetAPen(rp,pens[SHINEPEN]);
				Draw(rp,maxx-3,miny+3);
				return(0L);
		default:
				BOOPSI_Method_SuperReturn
	}
}

BOOPSI_Class(initSYSIClass,dispatchSYSIClass,"sysiclass","urouclass",NULL,SYSIData, 0)

	static char *types[]=
	{
		"/depth/",
		"/zoom/",
		"/size/",
		"/close/",
		"/sdepth/",
		"",
		"",
		"",
		"",
		"",
		"/left/",
		"/up/",
		"/right/",
		"/down/",
		"/checkmark/",
		"/mx/",
		"",
		"",
		"/iconify/"
	};

	BOOPSI_Method(OM_NEW)
	{
		ULONG               what;
		BOOL                adjust_h=TRUE;
		BOOL                adjust_w=TRUE;
		struct  DrawInfo    *mydr;
		ULONG               type=TRUE;

		if(FindTagItem(IA_Height,((struct opSet *)msg)->ops_AttrList))adjust_h=FALSE;
		if(FindTagItem(IA_Width, ((struct opSet *)msg)->ops_AttrList))adjust_w=FALSE;

		what=GetTagData(SYSIA_Which, 0x0, ((struct opSet *)msg)->ops_AttrList);
		if(what>(0x11L))
		{
			struct TagItem *tag;
			if(what=ICONIFYIMAGE)
			{
				if(tag=FindTagItem(SYSIA_Which,((struct opSet *)msg)->ops_AttrList))
				{
					tag->ti_Data=DEPTHIMAGE;
				}
			}
		}
		mydr=(struct DrawInfo *)GetTagData(SYSIA_DrawInfo,0x0,((struct opSet *)msg)->ops_AttrList);
		if(object=(Object *)DoSuperMethodA(cl,object,msg))
		{
			BOOPSI_InitData
			data->what  = what;
			data->image = NULL;
			data->init  = FALSE;
			if(mydr->dri_Version==NEWDRIVERSION)
			{
				switch(what)
				{
					case    SIZEIMAGE:
							SetAttrs(object,IA_Width,b_width,IA_Height,b_height,TAG_DONE);
							break;
					case    LEFTIMAGE:
					case    RIGHTIMAGE:
					case    UPIMAGE:
					case    DOWNIMAGE:
							if(adjust_h)
							{
								SetAttrs(object,IA_Height,b_height,TAG_DONE);
							}
							if(adjust_w)
							{
								SetAttrs(object,IA_Width,b_width,TAG_DONE);
							}
							break;
					case    CLOSEIMAGE:
					case    ZOOMIMAGE:
					case    DEPTHIMAGE:
							{
								LONG    tmp;
								GetAttr(IA_Height,object,&tmp);
								if(tmp)  SetAttrs(object,IA_Height,tmp+(b_top-2),TAG_DONE);
							}
							break;
				}
				if(data->scr=(struct Screen *)((ULONG *)mydr->dri_Pens)[(-MAX_EXT)+IMG_SCREEN])
				{
					data->image = (struct BitMap *)allocBM(object,types[data->what],data);
				}
			}
		}
		return(object);
	}
	BOOPSI_Method_End

	BOOPSI_Method(IM_DRAW)
	{
		BOOPSI_InitData;

		if(((struct impDraw *)msg)->imp_DrInfo->dri_Version==NEWDRIVERSION)
		{
			if(data->image)
			{

				UWORD   minx,miny,maxx,maxy;
				struct  RastPort    *rp=((struct impDraw *)msg)->imp_RPort;

				minx=((struct impDraw *)msg)->imp_Offset.X+((struct Image *)object)->LeftEdge;
				miny=((struct impDraw *)msg)->imp_Offset.Y+((struct Image *)object)->TopEdge;
				maxx=((struct Image *)object)->Width ;
				maxy=((struct Image *)object)->Height;

				if(!data->fixed)
				{
					switch(((struct impDraw *)msg)->imp_State)
					{
						case    IDS_SELECTED:
								BltBitMapRastPort(data->image,maxx+maxx ,0,rp,minx,miny,maxx,maxy,0xc0);
								break;
						case    IDS_NORMAL:
								BltBitMapRastPort(data->image,maxx      ,0,rp,minx,miny,maxx,maxy,0xc0);
								break;
						default:
								BltBitMapRastPort(data->image,0         ,0,rp,minx,miny,maxx,maxy,0xc0);
								break;
					}
				}
				else switch(((struct impDraw *)msg)->imp_State)
				{
					case    IDS_SELECTED:
							BltBitMapRastPort(data->image,data->w+data->w,0,rp,minx+((maxx-data->w)>>1),miny+((maxy-data->h)>>1),data->w,data->h,0xc0);
							break;
					case    IDS_NORMAL:
							BltBitMapRastPort(data->image,data->w        ,0,rp,minx+((maxx-data->w)>>1),miny+((maxy-data->h)>>1),data->w,data->h,0xc0);
							break;
					default:
							BltBitMapRastPort(data->image,0              ,0,rp,minx+((maxx-data->w)>>1),miny+((maxy-data->h)>>1),data->w,data->h,0xc0);
							break;
				}
				return(TRUE);
			}
			else switch (data->what)
			{
				case    CHECKIMAGE:
				case    MXIMAGE:
						{
							UWORD   minx,miny,maxx,maxy;
							struct  RastPort    *rp=((struct impDraw *)msg)->imp_RPort;
							UWORD   *pens=((struct impDraw *)msg)->imp_DrInfo->dri_Pens;
							minx=((struct impDraw *)msg)->imp_Offset.X+((struct Image *)object)->LeftEdge;
							miny=((struct impDraw *)msg)->imp_Offset.Y+((struct Image *)object)->TopEdge;
							maxx=minx+((struct Image *)object)->Width -1;
							maxy=miny+((struct Image *)object)->Height-1;
							if(XStyle)
							{
								if(((struct impDraw *)msg)->imp_State==IDS_SELECTED) draw_frame (rp,minx,miny,maxx,maxy,pens[HALFSHADOWPEN],pens[SHINEPEN],pens[HALFSHADOWPEN],pens[SHINEPEN],pens[HALFSHINEPEN],TRUE);
								else                              draw_frame (rp,minx,miny,maxx,maxy,pens[SHINEPEN],pens[HALFSHADOWPEN],pens[SHINEPEN],pens[HALFSHADOWPEN],pens[HALFSHINEPEN],TRUE);
							}
							else
							{
								if(((struct impDraw *)msg)->imp_State==IDS_SELECTED) draw_frame (rp,minx,miny,maxx,maxy,pens[SHADOWPEN],pens[SHADOWPEN],pens[HALFSHADOWPEN],pens[SHINEPEN],pens[HALFSHINEPEN],TRUE);
								else                              draw_frame (rp,minx,miny,maxx,maxy,pens[SHADOWPEN],pens[SHADOWPEN],pens[SHINEPEN],pens[HALFSHADOWPEN],pens[HALFSHINEPEN],TRUE);
							}
							if(((struct impDraw *)msg)->imp_State==IDS_SELECTED)
							{
								SetAPen(rp,pens[FILLPEN]);
								if(((maxx-minx)>5)&&((maxy-miny)>5)) RectFill(rp,minx+3,miny+3,maxx-3,maxy-3);
							}
						}
						return(TRUE);
						break;
				default:
						if(sysihackstyle)
						{
							return(DrawSysiHack(data,((struct impDraw *)msg),object,cl,msg));
						}
						else
						{
							return(DrawUrou    (data,((struct impDraw *)msg),object,cl,msg));
						}
						break;
			}
		}
		BOOPSI_Method_SuperReturn
	}
	BOOPSI_Method_End

	BOOPSI_Method(OM_DISPOSE)
		struct MsgPort *port;

		BOOPSI_InitData;
		if(data->dtobj)
		if(port= CreatePort(0,0))
		{
			struct iht_msg  *imsg;
			if(imsg = (struct iht_msg *)AllocVecPooled(swim_in_my_pool,sizeof(struct iht_msg)))
			{
				imsg->ts_Message.mn_Node.ln_Type  = NT_MESSAGE;
				imsg->ts_Message.mn_ReplyPort     = port;
				imsg->ts_Message.mn_Length        = sizeof ( struct iht_msg );
				imsg->object                      = data->dtobj;
				imsg->MethodID                    = IML_FREE;
				if(PutToPort(imsg))
				{
					WaitPort(port);
					GetMsg(port);
				}
				FreeVecPooled(imsg);
			}
			DeletePort(port);
		}
		BOOPSI_Method_SuperReturn
	BOOPSI_Method_End

	BOOPSI_Method_SuperDefault

BOOPSI_End

/************************************************************************/
/* Patched functions                                                    */
/************************************************************************/

ULONG  oldAGRoutine;
extern newAGRoutine();
ULONG  oldAGLRoutine;
extern newAGLRoutine();
ULONG  oldNMPRoutine;
extern newNMPRoutine();
ULONG  oldOTLRoutine;
extern newOTLRoutine();
ULONG  oldOSRoutine;
extern newOSRoutine();
ULONG  oldCSRoutine;
extern newCSRoutine();
ULONG  oldOWTLRoutine;
extern newOWTLRoutine();
ULONG  oldOWRoutine;
extern newOWRoutine();

fail()
{
	PutStr("***uRøURAçK sUCKS! Please run it before any screen was opened or IPrefs was started!\n\nPlease reboot your machine now, the system could be unstable!");
	exit(0);
}

enum{SCRFIL,IMG_STYLE,WIN_TOP,WIN_BOT,WIN_LEF,WIN_RIG,FINBOT,FINRIG,PATFRAME,PATSYSI,ONLYWIN,TRYMWB,SYSISTYLE,XWIN,ONLYWB,ARG_COUNT};
#define ARGTEMPLATE "SCREENFILE,IMGSTYLE/K,WTOP/K/N,WBOTTOM/K/N,WLEFT/K/N,WRIGHT/K/N,SBOTTOM/K/N,SRIGHT/K/N,NOFRAME/S,NOSYSI/S,ONLYWINIMG/S,TRYMAGICWB/S,SYSIHACK/S,XWIN/S,ONLYWB/S"

enum{SCRNAME,SCRPEN1,SCRPEN2,SCRPEN3,SCRPEN4,ALLMWB,SCRARG_COUNT};
#define SCRARGTMPL "SCREEN,PEN1/N,PEN2/N,PEN3/N,PEN4/N,ALLOCATEMWB/S"

getscreenlist(char *filename)
{
	BPTR    file;
	STRPTR  *ArgArray;
	char    *line,*name;

	if(line=(char *)AllocVecPooled(swim_in_my_pool,256L))
	{
		if(file=(BPTR)Open(filename,MODE_OLDFILE))
		{
			int i=0;
			while(FGets(file,line,255))
			{
				i++;
				if(penlist[i]=(struct NewPenStruct *)AllocVecPooled(swim_in_my_pool,sizeof(struct NewPenStruct)))
				{
					if(ArgArray = (STRPTR *)AllocVecPooled(swim_in_my_pool,(sizeof(STRPTR) * (SCRARG_COUNT)) + 16L))
					{
						struct RDArgs *rd;
						if(rd=(struct RDArgs *)AllocDosObject(DOS_RDARGS,TAG_DONE))
						{
							rd->RDA_Source.CS_Buffer=line;
							rd->RDA_Source.CS_Length=strlen(line);
							rd->RDA_Source.CS_CurChr=0L;

							if(ReadArgs(SCRARGTMPL,(LONG *)ArgArray,rd))
							{
								if(ArgArray[SCRNAME])
								{
									if(name = (char *)ArgArray[SCRNAME])
									{
										if(namelist[i]=(char *)AllocVecPooled(swim_in_my_pool,strlen(name)+1L))
										{
											strcpy(namelist[i],name);
										}
									}
								}
								if(ArgArray[SCRPEN1])
								{
									penlist[i]->halfdark   = (UWORD)(*(LONG *)ArgArray[SCRPEN1])&0xFFFF;
								}
								if(ArgArray[SCRPEN2])
								{
									penlist[i]->halfshine  = (UWORD)(*(LONG *)ArgArray[SCRPEN2])&0xFFFF;
								}
								if(ArgArray[SCRPEN3])
								{
									penlist[i]->darkpaint  = (UWORD)(*(LONG *)ArgArray[SCRPEN3])&0xFFFF;
								}
								if(ArgArray[SCRPEN4])
								{
									penlist[i]->shinepaint = (UWORD)(*(LONG *)ArgArray[SCRPEN4])&0xFFFF;
								}
								if(ArgArray[ALLMWB])
								{
									exttrymwb[i]=TRUE;
								}
								FreeArgs(rd);
							}
							FreeDosObject(rd);
						}
						FreeVecPooled(ArgArray);
					}
				}
			}
			Close(file);
		}
		else PutStr("***UROUHACK: Could not open screenlist file!");
		FreeVecPooled(line);
	}
}

getconfig()
{
	ULONG *ArgArray;
	if(ArgArray = (STRPTR *)AllocVecPooled(swim_in_my_pool,(sizeof(ULONG)*(ARG_COUNT)) + 16L))
	{
		struct RDArgs *rd;
		if(rd=(struct RDArgs *)ReadArgs(ARGTEMPLATE,(LONG *)ArgArray,NULL))
		{
			if(ArgArray[SCRFIL])
			{
				getscreenlist((char *)ArgArray[SCRFIL]);
			}
			if(ArgArray[IMG_STYLE])
			{
				if(imagestyle=(char *)AllocVecPooled(swim_in_my_pool,strlen(ArgArray[IMG_STYLE])+4L))
				{
					strcpy(imagestyle,ArgArray[IMG_STYLE]);
				}
			}
			if(ArgArray[WIN_TOP])
			{
				b_top = (BYTE)(*(LONG *)ArgArray[WIN_TOP])&0xFF;
			}
			if(ArgArray[WIN_BOT])
			{
				b_bottom = (BYTE)(*(LONG *)ArgArray[WIN_BOT])&0xFF;
			}
			if(ArgArray[WIN_LEF])
			{
				b_left = (BYTE)(*(LONG *)ArgArray[WIN_LEF])&0xFF;
			}
			if(ArgArray[WIN_RIG])
			{
				b_right = (BYTE)(*(LONG *)ArgArray[WIN_RIG])&0xFF;
			}
			if(ArgArray[FINBOT])
			{
				b_height = (*(LONG *)ArgArray[FINBOT])&0xFF;
			}
			if(ArgArray[FINRIG])
			{
				b_width = (*(LONG *)ArgArray[FINBOT])&0xFF;
			}
			if(ArgArray[PATFRAME])
			{
				pframes=FALSE;
			}
			if(ArgArray[PATSYSI])
			{
				psysi=FALSE;
			}
			if(ArgArray[ONLYWIN])
			{
				pwin=FALSE;
			}
			if(ArgArray[TRYMWB])
			{
				trymwb=TRUE;
			}
			if(ArgArray[SYSISTYLE])
			{
				sysihackstyle=TRUE;
			}
			if(ArgArray[XWIN])
			{
				XStyle=TRUE;
			}
			if(ArgArray[ONLYWB])
			{
				onlywb=TRUE;
			}
			FreeArgs(rd);
		}
		else PutStr("***UROUHACK: Unknown arguments or error in commandline!");
		FreeVecPooled(ArgArray);
	}
}

void main(int argc, char *argv[])
{
	Class       *my_cl,
				*oldcl;
	Object      *g;

	if(swim_in_my_pool=(ULONG *)CreatePool(MEMF_CLEAR|MEMF_PUBLIC,8192L,4096L))
	{
		getconfig();

		Forbid();
		oldOTLRoutine = SetFunction(IntuitionBase,(WORD)-612,newOTLRoutine);
		oldOSRoutine  = SetFunction(IntuitionBase,(WORD)-198,newOSRoutine);
		oldCSRoutine  = SetFunction(IntuitionBase,(WORD)-66 ,newCSRoutine);
		Permit();

		if(pframes)
		{
			if( g=(Object *)NewObject(NULL,"frameiclass",IA_Width,10,IA_Height,10, TAG_DONE))
			{
				oldcl=OCLASS(g); DisposeObject(g);
				Forbid();

				oldcl->cl_ID="breizhclass";

				if(my_cl=initFRAMEClass())
				{
					AddClass(my_cl);
					Permit();
				}
				else fail();
			}
			else fail();
		}
		if(psysi)
		{
			DataTypesBase=(struct Library *)2L;
			if(CreateNewProcTags(
					NP_Entry,       ImageLoaderTask,
					NP_Name,        "UrouHack ImageLoaderProcess",
					NP_Priority,    0,
					TAG_DONE
			  ))
			{
				static UWORD   pens[8];
				static struct  TextAttr topaz_font = { "topaz.font", 8, 0, FPF_ROMFONT, };
				static struct  DrawInfo mydrawinfo = { DRI_VERSION, 9, &pens[BACKGROUNDPEN], 0, 2, 1, 1, NULL, NULL, NULL, 0, 0, 0, 0, 0 };

				mydrawinfo.dri_Font=(struct TextFont *)OpenFont(&topaz_font);

				Forbid();
				oldOWTLRoutine= SetFunction(IntuitionBase,(WORD)-606,newOWTLRoutine);
				oldOWRoutine  = SetFunction(IntuitionBase,(WORD)-204,newOWRoutine);
				Permit();

				if( g=(Object *)NewObject(NULL, "sysiclass", SYSIA_Which, RIGHTIMAGE, SYSIA_DrawInfo, &mydrawinfo, TAG_DONE))
				{
					oldcl=OCLASS(g); DisposeObject(g);
					Forbid();

					oldcl->cl_ID="urouclass";

					if(my_cl=initSYSIClass())
					{
						AddClass(my_cl);
						Permit();
					}
					else fail();

				}
				else fail();

				if( g=(Object *)NewObject(NULL,"buttongclass",GA_Width,10,GA_Height,10,TAG_DONE))
				{
					oldcl=OCLASS(g); DisposeObject(g);
					Forbid();

					oldcl->cl_ID="tinicclass";

					if(my_cl=initGADClass())
					{
						AddClass(my_cl);
						Permit();
					}
					else fail();
				}
				else fail();

				oldAGRoutine = SetFunction(IntuitionBase,(WORD)-42, newAGRoutine);
			}
		}
		if(Cli()) ((struct CommandLineInterface *)Cli())->cli_Module=0L; /* That wwas a good tip ;-)) */
		else      Wait(0L);
	}
	else PutStr("***UROUHACK: Could not create memory pool!");
}

