/*
** 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];

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

        WORD   clockpos;
};

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);
    }
}

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

struct TextFont *OpenTopaz()
{
    struct TextAttr topaz_font =
    {
        "topaz.font",
        8,
        0,
        FPF_ROMFONT,
    };
    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);
}

my_strlen(char s[])           /*liefert die Laenge von 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)
{
    if(col->pen)
    {
        inst->PorC[number]=FALSE;
        inst->Pens[number]=col->red;
    }
    else
    {
        inst->PorC[number]=TRUE;
        inst->Pens[number]=ObtainBestPenA(msg->gpr_GInfo->gi_Screen->ViewPort.ColorMap, col->red, col->green, col->blue, 0L);
    }
}

ReleasePenNew(struct gpRender *msg,struct GaugeData *inst,ULONG number)
{
/*    if(inst->PorC[number])
    {
        ReleasePen(msg->gpr_GInfo->gi_Screen->ViewPort.ColorMap,inst->Pens[number]);
        inst->PorC[number]=FALSE;
    }*/
}


ULONG newGauge(Class *cl,struct Gadget *g,struct gpRender *msg,struct GaugeData *inst)
{
    ULONG    retval;
    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);
                if(inst->type==GAU_Type_clock) inst->locale = (struct Locale *)OpenLocale(NULL);

                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;

                retval=(ULONG)g;
            }
            FreeVec(dummy);
        }
        else { retval=0L;}
    }
    else { retval=0L;}

    return(retval);
}

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)
{
    struct GaugeData *inst;
    ULONG  i;
    inst=INST_DATA(cl,g);
    CloseLocale(inst->locale);
/*    for(i=0;i<8;i++)
    {
        if(inst->PorC[i]==TRUE)
        {
            ReleasePen(msg->gpr_GInfo->gi_Screen->ViewPort.ColorMap,inst->Pens[i]);
            inst->PorC[i]=FALSE;
        }
    }*/
    freeRPorts(inst);
}

ULONG getGauge(Class *cl,struct Gadget *g,struct gpRender *msg)
{
    struct GaugeData *inst;
    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;
    struct RastPort     *rp;
    ULONG  t_data;

    inst=INST_DATA(cl,g);
    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;
        }
    }
    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->InitNotDone=TRUE;
        freeRPorts(inst);
    }
}

UBYTE long_2_string_with_thousand(ULONG num, char output[], char point)
{
    char             output_private[16];
    char             n      = 0;
    char             n_1    = 0;
    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[])
{
    int         i=0,
                j=0;
    char        temp_str_1[64];
    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; i++;
                        break;
                case    'b':
                        dummy=base; i++;
                        break;
                case    'a':
                        dummy=max; i++;
                        break;
                case    'p':
                        dummy_2=2; dummy=current; i++;
                        break;
            }
            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],'.');
                        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],',');
                        for(dummy_1=0;dummy_1<dummy_2;dummy_1++) temp_str[j++]=temp_str_1[dummy_1];
                        break;
                case    2:
                        dummy_2=0;
                        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;
                        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;
            }
        }
        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)>0)&&((y+height-1)>0)) 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)
{
    if((width>0)&&(height>0)&&(width<(dest->BitMap->BytesPerRow<<8))&&(height<dest->BitMap->Rows))
    {
        ClipBlit(src,topx,topy,dest,dtopx,dtopy,width,height,0xC0);
    }
}

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

    inst=INST_DATA(cl,g);

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

    if(rp)
    {

        retval=TRUE;

        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);
                    retval=0L;
                    goto fail;
                }
            }
            else { retval=0L; goto fail; }

            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);
                    retval=0L;
                    goto fail;
                }
            }
            else { retval=0L; goto fail; }

            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);
                        retval=0L;
                        goto fail;
                    }
                }
                else { retval=0L; goto fail; }
            }
            inst->old_cur=-1;
            inst->old_bas=-1;
            inst->InitNotDone=FALSE;
        }

        w=g->Width-1;
        h=g->Height-1;
        wk_rp=inst->wk_buffer;
        bg_rp=inst->bg_buffer;
        hs_rp=inst->hs_buffer;
        max=inst->max>>8;

        switch (inst->type)
        {
            case    GAU_Type_gauge:
                    if((inst->current!=inst->old_cur)||(inst->base!=inst->old_bas))
                    {
                        inst->old_cur=inst->current;
                        inst->old_bas=inst->base;

                        my_Blit(bg_rp,0,0,wk_rp,0,0,g->Width,g->Height);

                        if(inst->StyleBorder)draw_border_new(wk_rp,inst->labelpos,0,g->Width-inst->labelpos,g->Height,inst->Pens[col_dark],inst->Pens[col_bright]);

                        if(inst->StyleShadowLabel)
                        {
                            SetAPen(wk_rp,inst->Pens[col_dark]);
                            Move(wk_rp,1,inst->text_y+1);
                            Text(wk_rp,inst->txtlbl,my_strlen(inst->txtlbl));
                        }

                        SetAPen(wk_rp,inst->Pens[col_label]);
                        Move(wk_rp,0,inst->text_y);
                        Text(wk_rp,inst->txtlbl,my_strlen(inst->txtlbl));

                        if(!inst->StyleNoGauge)
                        {
                            g_x=1+inst->labelpos;
                            g_y=1;
                            g_size=w-inst->labelpos-1;
                            g_height=h-1;

                            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) /* the most used... */
                                {
                                    SetAPen(wk_rp,inst->Pens[col_base]);
                                    my_RectFill(wk_rp,g_x,g_y,x1,g_height);
                                    SetAPen(wk_rp,inst->Pens[col_current]);
                                    my_RectFill(wk_rp,g_x+x1,g_y,x2-x1,g_height);

                                    if(!inst->StyleBackground)
                                    {
                                        SetAPen(wk_rp,inst->Pens[col_bg]);
                                        my_RectFill(wk_rp,g_x+x2,g_y,g_size-x2,g_height);
                                    }
                                    if(inst->Style3D)
                                    {
                                        if(x1>1)   draw_border_new(wk_rp,g_x,g_y,x1,g_height,inst->Pens[col_bright],inst->Pens[col_dark]);
                                        if(x2-x1>1)draw_border_new(wk_rp,g_x+x1,g_y,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,g_y,x2,g_height);
                                        SetAPen(wk_rp,inst->Pens[col_negative]);
                                        my_RectFill(wk_rp,g_x+x2,g_y,x1-x2,g_height);

                                        if(!inst->StyleBackground)
                                        {
                                            SetAPen(wk_rp,inst->Pens[col_bg]);
                                            my_RectFill(wk_rp,g_x+x1,g_y,g_size-x1,g_height);
                                        }
                                        if(inst->Style3D)
                                        {
                                            if(x2>1)   draw_border_new(wk_rp,g_x,g_y,x2,g_height,inst->Pens[col_bright],inst->Pens[col_dark]);
                                            if(x1-x2>1)draw_border_new(wk_rp,g_x+x2,g_y,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,g_y,x1,g_height);

                                        if(!inst->StyleBackground)
                                        {
                                            SetAPen(wk_rp,inst->Pens[col_bg]);
                                            my_RectFill(wk_rp,g_x+x1,g_y,g_size-x1,g_height);
                                        }
                                        if(inst->Style3D) if(x1>1)draw_border_new(wk_rp,g_x,g_y,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,g_y,x2,g_height);

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

                        if(!inst->StyleNoFormat)
                        {
                            fmt=formattext(inst->current,inst->base,inst->max,inst->txtfmt);
                            SetAPen(wk_rp,inst->Pens[col_format]);
                            t_length=TextLength(wk_rp,fmt,my_strlen(fmt));
                            if(t_length<(w-inst->labelpos))
                            {
                                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-2;
                                            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,g->Width,g->Height);
                    }
                    break;

            case    GAU_Type_histmeter:
                    w++;
                    h++;
                    g_size=h-3;
                    if(!inst->StyleNoGauge)
                    {
                        x1=(WORD)(((inst->base   >>8)*g_size)/((max)==0 ? 1 : (max)));
                        x2=(WORD)(((inst->current>>8)*g_size)/((max)==0 ? 1 : (max)));
                        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+2,inst->histpos,g_size+1);
                                SetAPen(hs_rp,inst->Pens[col_current]);
                                RectFill(hs_rp,inst->histpos,x2+2,inst->histpos,x1+1);
                            }
                            if(x1<x2)
                            {
                                RectFill(hs_rp,inst->histpos,x1+2,inst->histpos,g_size+1);
                                SetAPen(hs_rp,inst->Pens[col_negative]);
                                RectFill(hs_rp,inst->histpos,x1+2,inst->histpos,x2+1);
                            }
                            if(x1==x2)
                            {
                                RectFill(hs_rp,inst->histpos,x1+2,inst->histpos,g_size+1);
                            }
                        }
                        else
                        {
                            SetAPen(hs_rp,inst->Pens[col_current]);
                            RectFill(hs_rp,inst->histpos,x2+2,inst->histpos,g_size+1);
                        }
                        my_Blit(hs_rp,0,0,wk_rp,0,0,w,h);
                    }
                    if(inst->StyleBorder)draw_border_new(wk_rp,0,0,g->Width,g->Height,inst->Pens[col_dark],inst->Pens[col_bright]);
                    if(!inst->StyleNoFormat)
                    {
                        fmt=formattext(inst->current,inst->base,inst->max,inst->txtfmt);
                        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,g->Width,g->Height);
                    break;
            case    GAU_Type_clock:
                    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;
                        }
                        my_Blit(bg_rp,text_x,0,wk_rp,text_x,0,t_length,g->Height);
                        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]));
                    }
                    my_Blit(wk_rp,text_x,0,rp,g->LeftEdge+text_x,g->TopEdge,t_length,g->Height);
                    break;
        }
        if(msg->MethodID !=GM_RENDER) ReleaseGIRPort(rp);
    }
    else retval=FALSE;

    fail:

    return(retval);
}

#ifdef __GNUC__
ULONG dispatchGaugeGadget(Class *cl,Object *o, Msg msg)
#else
__geta4 ULONG dispatchGaugeGadget(__a0 Class *cl,__a2 Object *o,__a1 Msg msg)
#endif
{
    struct   Gadget *g= (struct Gadget *)o;
    struct   GaugeData *inst;
    ULONG    retval;
    Object  *object;

#ifdef __GNUC__
    geta4();
#endif
    retval=DoSuperMethodA(cl,o,msg);
    switch( msg->MethodID )
    {
        case    OM_SET:
                setGauge(cl,(struct Gadget *)o,(struct gpRender *)msg);
                break;
        case    GM_RENDER:
                retval=renderGauge(cl,(struct Gadget *)o,(struct gpRender *)msg);
                break;
        case    OM_NEW:
                if(object = (Object *)DoSuperMethodA(cl, o, msg) )
                {
                    inst = INST_DATA(cl, object);
                    retval=newGauge(cl,(struct Gadget *)object,(struct gpRender *)msg,inst);
                }
                break;
        case    OM_GET:
                retval=getGauge(cl,(struct Gadget *)o,(struct gpRender *)msg);
                break;
        case    OM_DISPOSE:
                disposeGauge(cl,g,(struct gpRender *)msg);
                break;
        default:
                break;
    }
    return(retval);
}

