/* strgad.c -- easy create/destroy of string gadgets	*/

/*
Copyright (c) 1989 Commodore-Amiga, Inc.

Executables based on this information may be used in software
for Commodore Amiga computers. All other rights reserved.
This information is provided "as is"; no warranties are made.
All use is at your own risk, and no liability or responsibility
is assumed.
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <intuition/sghooks.h>

#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/exec_protos.h>

#include <string.h>
#include <stdlib.h>

#include "strgad.h"

/* getStringGadget()
 *
 * sets flags to some default values, override them after
 * it is allocated.  Likewise LongInt: set it up after
 * the fact.
 */

struct SG {
	struct Gadget		sg_Gadget;
	struct StringInfo	sg_Info;
	struct Border		sg_Border;
	UWORD			sg_XY[ 10 ];
	struct IntuiText	sg_IText;
};

struct Gadget *getOneSG();

struct Gadget *
getStringGadgets( sgs, num )
struct SGSpec	*sgs;
{
    struct Gadget	*firstg;
    struct Gadget	*sg;

    if ( num <= 0 ) return ( NULL );

    if ( ! (firstg = sg = getOneSG( sgs )) ) return ( NULL );

    while ( --num )
    {
	if ( !(sg->NextGadget = getOneSG( ++sgs )) )
	{
	    freeStringGadgets( firstg, num );
	    return ( NULL );
	}
	sg = sg->NextGadget;
    }
    return ( firstg );
}

/*
 * stops at null terminator or NULL link
 * can use -1 for num
 * returns next gadget in chain
 */
struct Gadget *
freeStringGadgets( sgadget, num )
struct Gadget	*sgadget;
{
    int memsize;
    struct Gadget *nextgadget;

    while ( sgadget && num-- )
    {
	memsize = sizeof ( struct SG );
	memsize += 2 * (((struct StringInfo *) sgadget->SpecialInfo)->MaxChars);
	nextgadget = sgadget->NextGadget;
	FreeMem( sgadget, (LONG) memsize );
	sgadget = nextgadget;
    }
    return ( sgadget );
}

struct Gadget *
getOneSG( sgs )
struct SGSpec	*sgs;
{
    int		memsize;
    CPTR	membase;
    struct SG   	*sg;
    struct Gadget	*sgadget;
    struct StringInfo   *sinfo;
    WORD		*xyp;
    int			txlength;

    /* figure out how much memory to allocate	*/
    memsize = sizeof ( struct SG );
    memsize += 2 * (sgs->sgs_NumChars + 1);	/* for buffers	*/

    /* try to get the memory	*/
    membase = (CPTR) AllocMem( (ULONG) memsize, (ULONG) MEMF_CLEAR );
    if ( membase == NULL ) return ( NULL );

    /* hook together pieces of memory	*/
    sg = (struct SG *) membase;
    membase += sizeof (struct SG);

    sg->sg_Info.Buffer = (UBYTE *) membase;
    membase += sgs->sgs_NumChars + 1;
    sg->sg_Info.UndoBuffer = (UBYTE *) membase;

    sgadget = &sg->sg_Gadget;
    sgadget->SpecialInfo =  (APTR) &sg->sg_Info;
    sinfo = &sg->sg_Info;
    sgadget->GadgetRender = (APTR) &sg->sg_Border;
    sgadget->GadgetText = &sg->sg_IText;

    /* initialize text		*/
    sg->sg_IText.FrontPen = 1;
    sg->sg_IText.BackPen =  0;
    sg->sg_IText.DrawMode = JAM2;
    txlength = TextLength( sgs->sgs_RPort, sgs->sgs_Title,
	(LONG) strlen( sgs->sgs_Title ) );
    sg->sg_IText.LeftEdge = -TITLEGAP - txlength;
    sg->sg_IText.TopEdge = 0;
    sg->sg_IText.ITextFont = NULL;
    sg->sg_IText.NextText = NULL;
    sg->sg_IText.IText = (UBYTE *) sgs->sgs_Title;	/* note: no copy	*/

    /* initialize border	*/
    sg->sg_Border.LeftEdge = sg->sg_Border.TopEdge = 0;
    sg->sg_Border.FrontPen = 1; sg->sg_Border.BackPen = 0;
    sg->sg_Border.DrawMode = JAM2;
    sg->sg_Border.Count = 5;
    sg->sg_Border.XY = (SHORT *) sg->sg_XY;
    sg->sg_Border.NextBorder = NULL;

    /* initialize string info	*/
    sinfo->BufferPos = 0;
    sinfo->MaxChars = sgs->sgs_NumChars + 1;
    sinfo->DispPos = 0;

    /* initialize gadget	*/
    sgadget->NextGadget = NULL;
    sgadget->LeftEdge = sgs->sgs_Left;
    sgadget->TopEdge = sgs->sgs_Top;
    sgadget->Width = sgs->sgs_Width;
    sgadget->Height = sgs->sgs_TxHeight + 2;
    sgadget->Flags = GADGHCOMP;
    sgadget->Activation = RELVERIFY | sgs->sgs_StringActives;
    sgadget->GadgetType = STRGADGET;
    sgadget->GadgetID = sgs->sgs_ID;
    sgadget->UserData = NULL;
    {
	UBYTE	*to;
	UBYTE	*from;
	to = sinfo->Buffer;
	from = (UBYTE *) sgs->sgs_InitString;

	while (*to++ = *from++);
    }
    

    /* init border polyline	*/
    xyp = (WORD *) sg->sg_XY;
    *xyp++ = sgadget->Width+BORDERGAP; *xyp++ = -(1+BORDERGAP);
    *xyp++ = sgadget->Width+BORDERGAP; *xyp++ = sgadget->Height+BORDERGAP;
    *xyp++ = -(1+BORDERGAP); *xyp++ = sgadget->Height+BORDERGAP;
    *xyp++ = -(1+BORDERGAP); *xyp++ = -(1+BORDERGAP);
    *xyp++ = sgadget->Width+BORDERGAP; *xyp++ = -(1+BORDERGAP);

    return ( sgadget );
}

