/*
** gaugeclass V0.9 by Tinic Urou
**
** Class implementation
**
** tested compilers:
**
** · DCC 2.6.2
** · GCC 2.7.0 with libnix V1.0 (libnix is necessary!!)
**
*/

#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 <intuition/screens.h>
#include <graphics/gfxbase.h>
#include <graphics/text.h>
#include <graphics/gfxmacros.h>
#include <utility/tagitem.h>
#include <utility/hooks.h>
#include <string.h>
#include "gaugeclass.h"

#define col_label       0
#define col_format      1
#define col_base        2
#define col_current     3
#define col_negative    4
#define col_bright      5
#define col_dark        6
#define col_bg          7

#define ind_centered    0
#define ind_left        1
#define ind_right       2

struct GaugeData
{
	ULONG   min;
	ULONG   max;
	ULONG   current;
	ULONG   base;
	ULONG   old_cur;
	ULONG   old_bas;
	WORD   labelpos;
	UBYTE   fmtind;

	ULONG   type;

	char    *txtlbl;
	char    *txtfmt;

	struct  GAU_Color Colors[GAU_UsedColors];

	BOOL    Style3D;
	BOOL    StyleBorder;
	BOOL    StyleBackground;
	BOOL    StyleShadowLabel;
	BOOL    StyleNoGauge;
	BOOL    StyleNoFormat;
	BOOL    StyleNoBase;

	struct  TextFont *textFont;

	ULONG   Pens[GAU_UsedColors];
	BOOL    PorC[GAU_UsedColors];

	BOOL    InitNotDone;

	struct  RastPort *nolock_rp;

	LONG   histpos;

	WORD   text_y;
	struct  Locale *locale;
	char    clocktxt[256];
	char    voltxt[64];

	struct  RastPort   *bg_buffer;
	struct  RastPort   *wk_buffer;
	struct  RastPort   *hs_buffer;

	WORD   clockpos;

	BOOL    highlight;
	WORD    oldclockx;
	WORD    oldclockw;

	ULONG   voltype;
};

extern ULONG DoSuperMethodA( struct IClass *cl, Object *obj, Msg message );
extern ULONG DoMethod( Object *obj, unsigned long MethodID, ... );
extern ULONG HookEntry();

#ifdef __GNUC__
ULONG dispatchGaugeGadget();
#else
static ULONG dispatchGaugeGadget(__a0 Class *cl,__a2 Object *o,__a1 Msg msg);
#endif

static ULONG renderGauge(Class *cl,struct Gadget *g, struct gpRender *msg);
void SPrintf(STRPTR buffer, STRPTR format, ...);

Class *initGaugeGadgetClass(void)
{
    Class *cl;
    if( cl = (Class *)MakeClass( NULL, "gadgetclass", NULL, sizeof(struct GaugeData), 0) )
    {
	cl->cl_Dispatcher.h_Entry    = (ULONG(*)()) HookEntry;
	cl->cl_Dispatcher.h_SubEntry = (ULONG(*)()) dispatchGaugeGadget;
	return(cl);
    }
    return(0L);
}

BOOL freeGaugeGadgetClass( Class *cl )
{
    return FreeClass(cl);
}

struct TextAttr topaz_font =
{
    "topaz.font",
    8,
    0,
    FPF_ROMFONT,
};

struct TextFont *OpenTopaz()
{
    return((struct TextFont *)OpenFont( &topaz_font));
}

void SPrintf(STRPTR buffer, STRPTR format, ...)
{
    struct Library *SysBase= *((void **)4L);
    RawDoFmt( format, (APTR)(&format+1), (void (*)())"\x16\xc0\x4E\x75", buffer);
}

int my_strlen(char s[])
{
   int i=0;
   while (s[i]!='\0')++i;
   return(i);
}

struct GAU_Color dummycol={ TRUE, 0, 0, 0 };
struct GAU_Color *GetGaugePen(WORD pen){ dummycol.red=pen; return(&dummycol); }

GetGaugePenNew(struct gpRender *msg,struct GaugeData *inst,struct GAU_Color *col,ULONG number)
{
    inst->PorC[number]= col->pen ? FALSE    : TRUE;
    inst->Pens[number]= col->pen ? col->red : ObtainBestPenA(msg->gpr_GInfo->gi_Screen->ViewPort.ColorMap, col->red, col->green, col->blue, 0L);
}

ULONG newGauge(Class *cl,struct Gadget *g,struct gpRender *msg,struct GaugeData *inst)
{
    struct   TagItem *ti;

    ti      = ((struct opSet *)msg)->ops_AttrList;
    if(inst->textFont = (struct TextFont *)GetTagData(GAU_TextFont,OpenTopaz(),ti))
    {
	struct RastPort *dummy;
	if(dummy=(struct RastPort *)AllocVec(sizeof(struct RastPort),0L))
	{
	    InitRastPort(dummy);
	    dummy->Font=inst->textFont;

	    inst->min               = GetTagData(GAU_Min,        0, ti);
	    inst->max               = GetTagData(GAU_Max,    65535L, ti);
	    inst->current           = GetTagData(GAU_Current,32162L, ti);
	    inst->base              = GetTagData(GAU_Base,   16384L, ti);
	    inst->txtfmt            = (char *)GetTagData(GAU_TextFormat, "%td", ti);
	    inst->txtlbl            = (char *)GetTagData(GAU_Label, "Gauge", ti);
	    inst->labelpos          = GetTagData(GAU_LabelPos,TextLength(dummy,inst->txtlbl,my_strlen(inst->txtlbl))+4, ti);

	    inst->Style3D           = GetTagData(GAU_3D,  TRUE, ti);
	    inst->StyleBorder       = GetTagData(GAU_Border, TRUE, ti);
	    inst->StyleBackground   = GetTagData(GAU_Background, FALSE, ti);
	    inst->StyleShadowLabel  = GetTagData(GAU_ShadowLabel, FALSE, ti);
	    inst->StyleNoGauge      = GetTagData(GAU_NoGauge,   FALSE, ti);
	    inst->StyleNoFormat     = GetTagData(GAU_NoFormat,  FALSE, ti);
	    inst->StyleNoBase       = GetTagData(GAU_NoBase,  FALSE, ti);
	    inst->fmtind            = GetTagData(GAU_FmtIndent, FALSE, ti);
	    inst->type              = GetTagData(GAU_Type, GAU_Type_gauge, ti);
	    inst->voltype           = GetTagData(GAU_VolType, 0L, ti);
	    inst->locale            = ( inst->type==GAU_Type_clock ) ? (struct Locale *)OpenLocale(NULL) : 0L ;

	    CopyMem(GetTagData(GAU_ColLabel     , GetGaugePen(2), ti), &inst->Colors[col_label],sizeof(struct GAU_Color));
	    CopyMem(GetTagData(GAU_ColFormat    , GetGaugePen(2), ti), &inst->Colors[col_format],sizeof(struct GAU_Color));
	    CopyMem(GetTagData(GAU_ColBase      , GetGaugePen(1), ti), &inst->Colors[col_base],sizeof(struct GAU_Color));
	    CopyMem(GetTagData(GAU_ColCurrent   , GetGaugePen(3), ti), &inst->Colors[col_current],sizeof(struct GAU_Color));
	    CopyMem(GetTagData(GAU_ColNegative  , GetGaugePen(1), ti), &inst->Colors[col_negative],sizeof(struct GAU_Color));
	    CopyMem(GetTagData(GAU_ColBrightEdg , GetGaugePen(2), ti), &inst->Colors[col_bright],sizeof(struct GAU_Color));
	    CopyMem(GetTagData(GAU_ColDarkEdg   , GetGaugePen(1), ti), &inst->Colors[col_dark],sizeof(struct GAU_Color));
	    CopyMem(GetTagData(GAU_ColBackground, GetGaugePen(0), ti), &inst->Colors[col_bg],sizeof(struct GAU_Color));

	    inst->InitNotDone=TRUE;
	    inst->highlight=TRUE;
	    inst->oldclockw=0L;
	    inst->oldclockx=0L;

	    FreeVec(dummy);
	    return((ULONG)g);
	}
	else return(0L);
    }
    else return(0L);
}

freeRPorts(struct GaugeData *inst)
{
    if(inst->bg_buffer)
    {
	FreeBitMap(inst->bg_buffer->BitMap);
	FreeVec(inst->bg_buffer);
	inst->bg_buffer=0L;
    }

    if(inst->wk_buffer)
    {
	FreeBitMap(inst->wk_buffer->BitMap);
	FreeVec(inst->wk_buffer);
	inst->wk_buffer=0L;
    }

    if(inst->hs_buffer)
    {
	FreeBitMap(inst->hs_buffer->BitMap);
	FreeVec(inst->hs_buffer);
	inst->hs_buffer=0L;
    }

}

ULONG disposeGauge(Class *cl,struct Gadget *g,struct gpRender *msg)
{
    CloseLocale(((struct GaugeData *)INST_DATA(cl,g))->locale);
    freeRPorts (INST_DATA(cl,g));
}

ULONG getGauge(Class *cl,struct Gadget *g,struct gpRender *msg)
{
    struct GaugeData *inst=INST_DATA(cl,g);
    switch (((struct opGet *)msg)->opg_AttrID)
    {
	case    GAU_RPBackground:
		*(((struct opGet *)msg)->opg_Storage)=(ULONG)inst->bg_buffer;
		break;
	case    GAU_Base:
		*(((struct opGet *)msg)->opg_Storage)=(ULONG)inst->base;
		break;
	case    GAU_Current:
		*(((struct opGet *)msg)->opg_Storage)=(ULONG)inst->current;
		break;
	default:
		return((ULONG)FALSE);
		break;
    }
    return((ULONG)TRUE);
}

setGauge(Class *cl,struct Gadget *g,struct gpRender *msg)
{
    struct TagItem      *ti,*tstate=((struct opSet *)msg)->ops_AttrList;
    struct GaugeData    *inst=INST_DATA(cl,g);
    struct RastPort     *rp;
    ULONG  t_data;

    while(ti=(struct TagItem *)NextTagItem(&tstate))
    {
	t_data=(ULONG)ti->ti_Data;
	switch(ti->ti_Tag)
	{
	    case    GAU_Current:
		    inst->current=  (ULONG)t_data;
		    break;
	    case    GAU_Base:
		    inst->base=     (ULONG)t_data;
		    break;
	    case    GAU_Max:
		    inst->max=      (ULONG)t_data;
		    break;
	    case    GAU_VolType:
		    inst->voltype=  (ULONG)t_data;
		    break;
	}
    }
    if ( FindTagItem(GA_Width,  ((struct opSet *)msg)->ops_AttrList) ||
	 FindTagItem(GA_Height, ((struct opSet *)msg)->ops_AttrList) ||
	 FindTagItem(GA_Top,    ((struct opSet *)msg)->ops_AttrList) ||
	 FindTagItem(GA_Left,   ((struct opSet *)msg)->ops_AttrList) )
    {
	inst->highlight=TRUE;
	inst->InitNotDone=TRUE;
	freeRPorts(inst);
    }
}

UBYTE long_2_string_with_thousand(ULONG num, char output[], char point, BOOL negative)
{
    char             output_private[16];
    char             n      = 0;
    char             n_1    = 0;

    if(negative)output[n_1++]='-';
    SPrintf(output_private,"%12ld",num);
    while(output_private[n]==0x20)n++;
    for(;(output_private[n]!=0)&(output_private[n]!=0x20);n++)
    {
	output[n_1++]=output_private[n];
	if((n==2)||(n==5)||(n==8)) output[n_1++]=(char)point;
    }
    output[n_1]=0;
    return(n_1);
}

char *formattext(ULONG current, ULONG base, ULONG max, char format[], ULONG special)
{
    int         i=0,
		j=0;
    char        temp_str_1[64];
    BOOL        negative;
    static char temp_str[256];

    while(format[i]!=0)
    {
	if(format[i]=='%')
	{
	    ULONG   dummy=0;
	    UBYTE   dummy_2=0,
		    dummy_1=0,
		    dummy_3=0;
	    i++;
	    if(format[i]=='t'){dummy_2=1;i++;}
	    if(format[i]=='T'){dummy_2=4;i++;}
	    if(format[i]=='k'){dummy_1=1;i++;}
	    if(format[i]=='m'){dummy_1=2;i++;}
	    if(format[i]=='o'){dummy_3=1;i++;}
	    if(format[i]=='%'){dummy_2=3;i++;}
	    switch(format[i])
	    {
		case    'd':
			dummy=current;
			negative=FALSE;
			break;
		case    'b':
			dummy=base;
			negative=FALSE;
			break;
		case    'f':
			dummy   = base<current ? current-base   : base-current;
			negative= base<current ? TRUE           : FALSE;
			break;
		case    'a':
			dummy=max;
			negative=FALSE;
			break;
		case    'p':
			dummy_2=2; dummy=current;
			negative=FALSE;
			break;
		case    'v':
			dummy_2=5;
			break;
		default:
			goto noforward;
			break;
	    }
	    i++;
noforward:
	    if(dummy_3==1)dummy=max-dummy;
	    if(dummy_1==1)dummy=dummy>>10;
	    if(dummy_1==2)dummy=dummy>>20;
	    switch(dummy_2)
	    {
		case    4:
			dummy_2=long_2_string_with_thousand(dummy,&temp_str_1[0],'.',negative);
			for(dummy_1=0;dummy_1<dummy_2;dummy_1++) temp_str[j++]=temp_str_1[dummy_1];
			break;
		case    1:
			dummy_2=long_2_string_with_thousand(dummy,&temp_str_1[0],',',negative);
			for(dummy_1=0;dummy_1<dummy_2;dummy_1++) temp_str[j++]=temp_str_1[dummy_1];
			break;
		case    2:
			dummy_2=0;
			if(negative) SPrintf(&temp_str_1[0],"-%ld",(((dummy>>8)*100)/((max>>8)+1)));
			else         SPrintf(&temp_str_1[0],"%ld", (((dummy>>8)*100)/((max>>8)+1)));
			while ((temp_str_1[dummy_2] != 0)&(dummy_2<64)) temp_str[j++]=temp_str_1[dummy_2++];
			break;
		case    0:
			dummy_2=0;
			if(negative) SPrintf(&temp_str_1[0],"-%ld",dummy);
			else         SPrintf(&temp_str_1[0],"%ld", dummy);
			while ((temp_str_1[dummy_2] != 0)&(dummy_2<64)) temp_str[j++]=temp_str_1[dummy_2++];
			break;
		case    3:
			temp_str[j++]='%';
			break;
		case    5:
			if(special&0xFF000000)temp_str[j++]=(char)((special>>24)&0xFF);
			if(special&0x00FF0000)temp_str[j++]=(char)((special>>16)&0xFF);
			if(special&0x0000FF00)temp_str[j++]=(char)((special>>8) &0xFF);
			temp_str[j++]='\\';
			temp_str[j++]=(char)( special     &0xFF)+0x30;
			break;
	    }
	}
	else temp_str[j++]=format[i++];
    }
    temp_str[j++]=0;
    return(temp_str);
}

void draw_border_new( struct RastPort *rp,ULONG x, ULONG y, ULONG width, ULONG height, int b_col1, int b_col2 )
{
    width--;height--;
    SetAPen(rp,b_col2);
    RectFill(rp,x+width,y+1,x+width,y+height);
    RectFill(rp,x,y+height,x+width,y+height);
    SetAPen(rp,b_col1);
    RectFill(rp,x,y,x,y+height-1);
    RectFill(rp,x,y,x+width-1,y);
}

my_RectFill(struct RastPort *rp,WORD x,WORD y,WORD width,WORD height)
{
    if(((x+width)>1)&&((y+height)>1)) RectFill(rp,x,y,x+width-1,y+height-1);
}

putChar_hook(struct Hook *hook,struct Locale *locale,ULONG thechar)
{
    struct GaugeData *data;
    geta4(); data=(struct GaugeData *)hook->h_Data;
    data->clocktxt[data->clockpos++]=(UBYTE)(thechar);
}

struct Hook putCharHook = { { 0,0 },(void *)HookEntry,(void *)putChar_hook, NULL };

my_Blit(struct RastPort *src, WORD topx, WORD topy, struct RastPort *dest, WORD dtopx, WORD dtopy, WORD width, WORD height)
{
    ClipBlit(src,topx,topy,dest,dtopx,dtopy,width,height,0xC0);
}

char *getSTR(struct GaugeData *inst)
{
    switch (inst->current-inst->max)
    {
	case    GAU_err_busy:
		return("Disk is busy");
	case    GAU_err_notmount:
		return("Not mounted");
	case    GAU_err_notpresent:
		return("No disk present");
	case    GAU_err_unreadable:
		return("Disk unreadable");
	case    GAU_err_nodos:
		return("No DOS format");
	case    GAU_err_notavail:
		return("n.a.");
	case    GAU_err_kickstart:
		return("Kickstart disk");
		break;
	default:
		return(formattext(inst->current,inst->base,inst->max,inst->txtfmt,inst->voltype));
    }
}

ULONG renderGauge(Class *cl,struct Gadget *g,struct gpRender *msg)
{
    struct  RastPort    *rp;
    struct  BitMap      *work_bm;
    struct  RastPort    *wk_rp,*bg_rp,*hs_rp;
    struct  GaugeData   *inst=INST_DATA(cl,g);
    struct  DateStamp   d_stamp;
    WORD                text_x,w,h;
    WORD                x1,x2,g_x,g_size,g_height,t_length;
    char                *fmt,*mlm;
    LONG                max;

    if(rp = ( msg->MethodID == GM_RENDER ) ? msg->gpr_RPort : (struct RastPort *) ObtainGIRPort(msg->gpr_GInfo) )
    {

	if(inst->InitNotDone)
	{
	    if(work_bm=(struct BitMap *)AllocBitMap(g->Width,g->Height+2,rp->BitMap->Depth,BMF_CLEAR,rp->BitMap))
	    {
		if(inst->bg_buffer=(struct RastPort *)AllocVec(sizeof(struct RastPort)+8,MEMF_CLEAR|MEMF_PUBLIC))
		{
		    InitRastPort(inst->bg_buffer);
		    inst->bg_buffer->BitMap=work_bm;

		    my_Blit(rp,g->LeftEdge,g->TopEdge,inst->bg_buffer,0,0,g->Width,g->Height);
		}
		else
		{
		    FreeBitMap(work_bm);
		    return(0L);
		}
	    }
	    else return(0L);

	    if(work_bm=(struct BitMap *)AllocBitMap(g->Width,g->Height+2,rp->BitMap->Depth,BMF_CLEAR,inst->bg_buffer->BitMap))
	    {
		if(inst->wk_buffer=(struct RastPort *)AllocVec(sizeof(struct RastPort)+8,MEMF_CLEAR|MEMF_PUBLIC))
		{
		    InitRastPort(inst->wk_buffer);
		    inst->wk_buffer->BitMap=work_bm;

		    inst->text_y=((g->Height-((inst->textFont->tf_Baseline+inst->textFont->tf_YSize)>>1))>>1);
		    if(inst->textFont->tf_Baseline<inst->textFont->tf_YSize)
		    {
			inst->text_y+=inst->textFont->tf_Baseline-1;
			if(inst->text_y<inst->textFont->tf_Baseline)inst->text_y=inst->textFont->tf_Baseline;
		    }
		    else
		    {
			inst->text_y+=inst->textFont->tf_YSize-1;
			if(inst->text_y<inst->textFont->tf_YSize)   inst->text_y=inst->textFont->tf_YSize;
		    }

		    SetDrMd(inst->wk_buffer,JAM1);
		    SetFont(inst->wk_buffer,inst->textFont);
		}
		else
		{
		    FreeBitMap(work_bm);
		    return(0L);
		}
	    }
	    else return(0L);

	    for(w=0;w<GAU_UsedColors;w++)GetGaugePenNew(msg,inst,&inst->Colors[w],w);

	    if(inst->type==GAU_Type_histmeter)
	    {
		if(work_bm=(struct BitMap *)AllocBitMap(g->Width,g->Height+2,rp->BitMap->Depth,BMF_CLEAR,inst->wk_buffer->BitMap))
		{
		    if(inst->hs_buffer=(struct RastPort *)AllocVec(sizeof(struct RastPort)+8,MEMF_CLEAR|MEMF_PUBLIC))
		    {
			inst->histpos=0;
			InitRastPort(inst->hs_buffer);
			inst->hs_buffer->BitMap=work_bm;
			SetAPen(inst->hs_buffer,inst->Pens[col_bg]);
			if(inst->StyleBackground)
			{
			    my_Blit(inst->bg_buffer,0,0,inst->hs_buffer,0,0,g->Width,g->Height);
			}
			else
			{
			    my_RectFill(inst->hs_buffer,0,0,g->Width,g->Height);
			}
		    }
		    else
		    {
			FreeBitMap(work_bm);
			return(0L);
		    }
		}
		else return(0L);
	    }
	    inst->old_cur=-1;
	    inst->old_bas=-1;
	    inst->InitNotDone=FALSE;
	}

	wk_rp=inst->wk_buffer;
	bg_rp=inst->bg_buffer;
	switch (inst->type)
	{
	    case    GAU_Type_gauge:
		    w=g->Width;
		    h=g->Height;
		    max=inst->max>>8;
		    if((inst->current!=inst->old_cur)||(inst->base!=inst->old_bas))
		    {
			inst->old_cur=inst->current;
			inst->old_bas=inst->base;
			if(inst->highlight)
			{
			    SetDrMd(bg_rp,JAM1);
			    SetFont(bg_rp,inst->textFont);
			    if(inst->StyleBorder)draw_border_new(bg_rp,inst->labelpos,0,w-inst->labelpos,g->Height,inst->Pens[col_dark],inst->Pens[col_bright]);
			    if(inst->StyleShadowLabel)
			    {
				SetAPen(bg_rp,inst->Pens[col_dark]);
				Move(bg_rp,1,inst->text_y+1);
				Text(bg_rp,inst->txtlbl,my_strlen(inst->txtlbl));
			    }
			    SetAPen(bg_rp,inst->Pens[col_label]);
			    Move(bg_rp,0,inst->text_y);
			    Text(bg_rp,inst->txtlbl,my_strlen(inst->txtlbl));
			    inst->highlight=FALSE;
			}
			my_Blit(bg_rp,0,0,wk_rp,0,0,w,h);
			g_x=1+inst->labelpos;
			g_size=w-inst->labelpos-2;
			g_height=h-2;
			if((!inst->StyleNoGauge)&&(inst->current<inst->max))
			{
			    x1=g_size-(WORD)(((inst->base>>8)   *g_size)/((max)==0 ? 1 : (max)));
			    x2=g_size-(WORD)(((inst->current>>8)*g_size)/((max)==0 ? 1 : (max)));

			    if(!inst->StyleNoBase)
			    {
				if(x1<x2)
				{
				    SetAPen(wk_rp,inst->Pens[col_base]);
				    my_RectFill(wk_rp,g_x,1,x1,g_height);
				    SetAPen(wk_rp,inst->Pens[col_current]);
				    my_RectFill(wk_rp,g_x+x1,1,x2-x1,g_height);

				    if(!inst->StyleBackground)
				    {
					SetAPen(wk_rp,inst->Pens[col_bg]);
					my_RectFill(wk_rp,g_x+x2,1,g_size-x2,g_height);
				    }
				    if(inst->Style3D)
				    {
					if(x1>1)   draw_border_new(wk_rp,g_x,1,x1,g_height,inst->Pens[col_bright],inst->Pens[col_dark]);
					if(x2-x1>1)draw_border_new(wk_rp,g_x+x1,1,x2-x1,g_height,inst->Pens[col_bright],inst->Pens[col_dark]);
				    }
				}
				else if(x1>x2)
				{
				    SetAPen(wk_rp,inst->Pens[col_base]);
				    my_RectFill(wk_rp,g_x,1,x2,g_height);
				    SetAPen(wk_rp,inst->Pens[col_negative]);
				    my_RectFill(wk_rp,g_x+x2,1,x1-x2,g_height);

				    if(!inst->StyleBackground)
				    {
					SetAPen(wk_rp,inst->Pens[col_bg]);
					my_RectFill(wk_rp,g_x+x1,1,g_size-x1,g_height);
				    }
				    if(inst->Style3D)
				    {
					if(x2>1)   draw_border_new(wk_rp,g_x,1,x2,g_height,inst->Pens[col_bright],inst->Pens[col_dark]);
					if(x1-x2>1)draw_border_new(wk_rp,g_x+x2,1,x1-x2,g_height,inst->Pens[col_bright],inst->Pens[col_dark]);
				    }
				}
				else
				{
				    SetAPen(wk_rp,inst->Pens[col_base]);
				    my_RectFill(wk_rp,g_x,1,x1,g_height);

				    if(!inst->StyleBackground)
				    {
					SetAPen(wk_rp,inst->Pens[col_bg]);
					my_RectFill(wk_rp,g_x+x1,1,g_size-x1,g_height);
				    }
				    if((inst->Style3D)&&(x1>1))draw_border_new(wk_rp,g_x,1,x1,g_height,inst->Pens[col_bright],inst->Pens[col_dark]);
				}
			    }
			    else
			    {
				SetAPen(wk_rp,inst->Pens[col_current]);
				my_RectFill(wk_rp,g_x,1,x2,g_height);
				if(!inst->StyleBackground)
				{
				    SetAPen(wk_rp,inst->Pens[col_bg]);
				    my_RectFill(wk_rp,g_x+x2,1,g_size-x2,g_height);
				}
				if(inst->Style3D) draw_border_new(wk_rp,g_x,1,x2,g_height,inst->Pens[col_bright],inst->Pens[col_dark]);
			    }
			}
			if(!inst->StyleNoFormat)
			{
			    fmt=getSTR(inst);
			    SetAPen(wk_rp,inst->Pens[col_format]);
			    t_length=TextLength(wk_rp,fmt,my_strlen(fmt));
			    if(t_length<(w-inst->labelpos-1))
			    {
				switch(inst->fmtind)
				{
				    case    ind_centered:
					    text_x=g_x+((g_size-t_length)>>1);
					    break;
				    case    ind_left:
					    text_x=g_x+2;
					    break;
				    case    ind_right:
					    text_x=w-t_length-3;
					    break;
				}
				Move(wk_rp,text_x,inst->text_y);
				Text(wk_rp,fmt,my_strlen(fmt));
			    }
			}
			my_Blit(wk_rp,0,0,rp,g->LeftEdge,g->TopEdge,w,h);
		    }
		    break;
	    case    GAU_Type_histmeter:
		    max=inst->max>>8;
		    w=g->Width;
		    h=g->Height;
		    g_size=h-2;
		    hs_rp=inst->hs_buffer;
		    if((!inst->StyleNoGauge)&&(inst->current<inst->max))
		    {
			x1=(WORD)(((inst->base   >>8)*(g_size-1))/((max)==0 ? 1 : (max)))+1;
			x2=(WORD)(((inst->current>>8)*(g_size-1))/((max)==0 ? 1 : (max)))+1;
			inst->histpos++;
			if(inst->histpos>w-3)
			{
			    WORD dummy;
			    dummy=w-(w>>1)-2;
			    SetAPen(hs_rp,inst->Pens[col_bg]);
			    my_Blit(hs_rp,w>>1,0,hs_rp,0,0,dummy,h);
			    if(inst->StyleBackground)
			    {
				my_Blit(inst->bg_buffer,dummy,0,inst->hs_buffer,dummy,0,w-dummy,h);
			    }
			    else
			    {
				RectFill(hs_rp,dummy,0,w,h);
			    }
			    inst->histpos=dummy;
			}
			if(!inst->StyleNoBase)
			{
			    SetAPen(hs_rp,inst->Pens[col_base]);
			    if(x1>x2)
			    {
				RectFill(hs_rp,inst->histpos,x1,inst->histpos,g_size);
				SetAPen(hs_rp,inst->Pens[col_current]);
				RectFill(hs_rp,inst->histpos,x2,inst->histpos,x1);
			    }
			    else if(x1<x2)
			    {
				RectFill(hs_rp,inst->histpos,x1,inst->histpos,g_size);
				SetAPen(hs_rp,inst->Pens[col_negative]);
				RectFill(hs_rp,inst->histpos,x1,inst->histpos,x2);
			    }
			    else
			    {
				RectFill(hs_rp,inst->histpos,x1,inst->histpos,g_size);
			    }
			}
			else
			{
			    SetAPen(hs_rp,inst->Pens[col_current]);
			    RectFill(hs_rp,inst->histpos,x2,inst->histpos,g_size);
			}
			my_Blit(hs_rp,0,0,wk_rp,0,0,w,h);
		    }
		    if(inst->StyleBorder)draw_border_new(wk_rp,0,0,w,h,inst->Pens[col_dark],inst->Pens[col_bright]);
		    if(!inst->StyleNoFormat)
		    {
			fmt=getSTR(inst);
			SetAPen(wk_rp,inst->Pens[col_format]);
			t_length=TextLength(wk_rp,fmt,my_strlen(fmt));
			if(t_length<w)
			{
			    switch(inst->fmtind)
			    {
				case    ind_centered:
					text_x=((w-t_length)>>1);
					break;
				case    ind_left:
					text_x=2;
					break;
				case    ind_right:
					text_x=w-t_length-2;
					break;
			    }
			    Move(wk_rp,text_x,h-3);
			    Text(wk_rp,fmt,my_strlen(fmt));
			}
		    }
		    my_Blit(wk_rp,0,0,rp,g->LeftEdge,g->TopEdge,w,h);
		    break;
	    case    GAU_Type_clock:
		    w=g->Width-1;
		    h=g->Height;
		    DateStamp(&d_stamp);
		    inst->clockpos=0; putCharHook.h_Data=inst; FormatDate(inst->locale,inst->txtfmt,&d_stamp,&putCharHook);
		    if((t_length=TextLength(wk_rp,&inst->clocktxt[0],my_strlen(&inst->clocktxt[0])))<w)
		    {
			switch(inst->fmtind)
			{
			    case    ind_centered:
				    text_x=(w-t_length)>>1;
				    break;
			    case    ind_left:
				    text_x=0;
				    break;
			    case    ind_right:
				    text_x=w-t_length-1;
				    break;
			}
			if(inst->oldclockw>t_length)
			{
			    my_Blit(bg_rp,inst->oldclockx,0,wk_rp,inst->oldclockx,0,inst->oldclockw,h);
			}
			else
			{
			    my_Blit(bg_rp,text_x,0,wk_rp,text_x,0,t_length,h);
			}
			if(inst->StyleShadowLabel)
			{
			    SetAPen(wk_rp,inst->Pens[col_dark]);
			    Move(wk_rp,text_x+1,inst->text_y+1);
			    Text(wk_rp,&inst->clocktxt[0],my_strlen(&inst->clocktxt[0]));
			}
			SetAPen(wk_rp,inst->Pens[col_format]);
			Move(wk_rp,text_x,inst->text_y);
			Text(wk_rp,&inst->clocktxt[0],my_strlen(&inst->clocktxt[0]));
			if(inst->oldclockw>t_length)
			{
			    my_Blit(wk_rp,inst->oldclockx,0,rp,g->LeftEdge+inst->oldclockx,g->TopEdge,inst->oldclockw,h);
			}
			else
			{
			    my_Blit(wk_rp,text_x,0,rp,g->LeftEdge+text_x,g->TopEdge,t_length,h);
			}
			inst->oldclockx=text_x;
			inst->oldclockw=t_length;
		    }
		    break;
	}
	if(msg->MethodID !=GM_RENDER) ReleaseGIRPort(rp);
	return(TRUE);
    }
    else return(FALSE);
}

#ifdef __GNUC__
ULONG dispatchGaugeGadget(Class *cl,Object *o, Msg msg)
#else
__geta4 ULONG dispatchGaugeGadget(__a0 Class *cl,__a2 Object *o,__a1 Msg msg)
#endif
{
#ifdef __GNUC__
    geta4();
#endif
    switch( msg->MethodID )
    {
	case    OM_SET:
		setGauge(cl,(struct Gadget *)o,(struct gpRender *)msg);
		return(DoSuperMethodA(cl,o,msg));
	case    GM_RENDER:
		return(renderGauge(cl,(struct Gadget *)o,(struct gpRender *)msg));
	case    OM_NEW:
		if(o = (Object *)DoSuperMethodA(cl, o, msg) )
		     return(newGauge(cl,(struct Gadget *)o,(struct gpRender *)msg,INST_DATA(cl, o)));
		else return(0L);
	case    OM_GET:
		return(getGauge(cl,(struct Gadget *)o,(struct gpRender *)msg));
	case    OM_DISPOSE:
		disposeGauge(cl,(struct Gadget *)o,(struct gpRender *)msg);
	default:
		return(DoSuperMethodA(cl,o,msg));
    }
}

