/*
 *  FILE: scrollbar.c
 *  Support routines for making scroll-bar and -button gadgets.
 *
 *  Public Domain, but keep my name in it as the original author.
 *  31-Aug-88	Jan Sven Trabandt   first release version
 *  30-Sep-88	Jan Sven Trabandt   keep up with changes to gadget.c
 */


#define I_AM_SCROLLBAR
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/scrollbar.h"
#include "gimmelib/macros.h"


struct Gadget *gimmeOneScroll( window, id, dirflags, myflags )
    struct Window   *window;
    USHORT	    id;
    ULONG	    dirflags, myflags;
{
    register struct Gadget  *gp;
    void    *gadgmh = NULL;
    USHORT  *data;
    USHORT  *imagedata;

    GUESS
	QUIF( !id );
	gp = chainAllocMem( &gadgmh, (ULONG)sizeof(struct Gadget),
				MEMF_CLEAR | MEMF_PUBLIC );
	QUIF( !gp );
	gp->GadgetType = BOOLGADGET;
	gp->GadgetRender = (APTR) gimmeImage( &gadgmh, GOS_BITDEPTH,
						GOS_BITWIDTH, GOS_BITHEIGHT );
	QUIF( !gp->GadgetRender );

	if( dirflags & FREEVERT ) {
	    gp->LeftEdge = -(GOS_BITWIDTH -1);
	    gp->Width = GOS_BITWIDTH;
	    gp->Height = GOS_BITHEIGHT;
	    if( myflags & GOS_TOP ) {
		if( window ) {
		    gp->TopEdge = window->BorderTop - 1;
		} else {
		    gp->TopEdge = GIM_DFLT_TBHEIGHT;
		}
		gp->Flags = GADGIMAGE | GADGHCOMP | GRELRIGHT;
		imagedata = gimDataOneScrollUp;
	    } else {
		gp->TopEdge = -GIM_SZHEIGHT - (GOS_BITHEIGHT -1);
		gp->Flags = GADGIMAGE | GADGHCOMP | GRELRIGHT | GRELBOTTOM;
		imagedata = gimDataOneScrollDown;
	    }
	    gp->Activation = RELVERIFY | RIGHTBORDER;
	} else {		/* otherwise we have FREEHORIZ */
	    gp->TopEdge = -(GOS_BITHEIGHT -1);
	    gp->Width = GOS_BITWIDTH;
	    gp->Height = GOS_BITHEIGHT;
	    if( myflags & GOS_LEFT ) {
		gp->LeftEdge = 0;
		gp->Flags = GADGIMAGE | GADGHCOMP | GRELBOTTOM;
		imagedata = gimDataOneScrollLeft;
	    } else {
		gp->LeftEdge = -GIM_SZWIDTH - (GOS_BITWIDTH - 1);
		gp->Flags = GADGIMAGE | GADGHCOMP | GRELBOTTOM | GRELRIGHT;
		imagedata = gimDataOneScrollRight;
	    }
	    gp->Activation = RELVERIFY | BOTTOMBORDER;
	}
	copyDataImage( imagedata, (struct Image *) gp->GadgetRender );
	if( window ) {
	    if( window->Flags & GIMMEZEROZERO ) {
		gp->GadgetType |= GZZGADGET;
	    }
	}
	gp->GadgetID = id;
	gp->UserData = gadgmh;
	return( gp );
    ENDGUESS
    if( gadgmh ) {
	chainFreeMem( gadgmh );
	return( NULL );
    }
} /* gimmeOneScroll */


struct Gadget *gimmeScrollBar( window, id, propflags, myflags )
    struct Window   *window;
    USHORT	    id;
    ULONG	    propflags, myflags;
{
    register struct Gadget  *gp;
    SHORT   ones_size = 0;
    SHORT   left, top, width, height;
    ULONG   gadgflags, activation;
    void    *gadgmh = NULL;

    GUESS
	QUIF( !id );
	if( propflags & FREEVERT ) {
	    propflags &= ~FREEHORIZ;
	    if( myflags & GSB_ONE_SCROLL ) {
		ones_size = GOS_BITHEIGHT;
	    }
	    left = - (GOS_BITWIDTH -1);
	    top  = ones_size;
	    if( !(myflags & GSB_NO_TITLEBAR) ) {
		if( window ) {
		    top += window->BorderTop - 1;
		} else {
		    top += GIM_DFLT_TBHEIGHT;
		}
	    }
	    width  = GOS_BITWIDTH;
	    height = -top - ones_size - GIM_SZHEIGHT;
	    gadgflags  = GADGHCOMP | GADGIMAGE | GRELRIGHT | GRELHEIGHT;
	    activation = RELVERIFY | RIGHTBORDER;
	} else {		/* otherwise we have FREEHORIZ */
	    propflags &= ~FREEVERT;
	    if( myflags & GSB_ONE_SCROLL ) {
		ones_size = GOS_BITWIDTH;
	    }
	    left = ones_size;
	    top  = - (GOS_BITHEIGHT -1);
	    width  = -GIM_SZWIDTH - (ones_size<<1);
	    height = GOS_BITHEIGHT;
	    gadgflags  = GADGHCOMP | GADGIMAGE | GRELBOTTOM | GRELWIDTH;
	    activation = RELVERIFY | BOTTOMBORDER;
	}
	gp = gimmePropGadget( window, id, left, top, width, height, NULL,
				NULL, activation, propflags );
	QUIF( !gp );
	gp->Flags = gadgflags;
	if( window ) {
	    ((struct PropInfo *)gp->SpecialInfo)->VertBody =
				0x0FFFFL * window->Height / window->MaxHeight;
	    ((struct PropInfo *)gp->SpecialInfo)->HorizBody =
				0x0FFFFL * window->Width / window->MaxWidth;
	}
	linkChainMem( &gp->UserData, gadgmh );
	return( gp );
    ENDGUESS
    if( gadgmh ) {
	chainFreeMem( gadgmh );
	return( NULL );
    }
} /* gimmeScrollBar */


struct Gadget *gimmeFullScrollBar( window, id, propflags, myflags, id1, id2 )
    struct Window   *window;
    USHORT	    id;
    ULONG	    propflags, myflags;
    USHORT	    id1, id2;
{
    register struct Gadget  *gp;

    GUESS
	QUIF( !id );
	gp = gimmeScrollBar( window, id, propflags, myflags | GSB_ONE_SCROLL );
	QUIF( !gp );
	/* top or left one-scroll */
	gp->NextGadget = gimmeOneScroll( window, id1, propflags,
					    GOS_TOP | GOS_LEFT );
	QUIF( !gp->NextGadget );
	/* bottom or right one-scroll */
	gp->NextGadget->NextGadget = gimmeOneScroll( window, id2, propflags,
					    GOS_BOT | GOS_RIGHT );
	QUIF( !gp->NextGadget->NextGadget );
	return( gp );
    ENDGUESS
    if( gp ) {
	getRidOfGadgets( gp );
    }
    return( NULL );
} /* gimmeFullScrollBar */
