/*
** gadget2.c:  Font-sensitive GadTools gadgets.
**
** (C) Copyright 1990, 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. No liability or responsibility is assumed.
*/

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <libraries/gadtools.h>

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

#include <string.h>

void printf(STRPTR,...);
int stcd_l(char *, long *);
void exit(int);

extern struct Library *SysBase;

/*------------------------------------------------------------------------*/

BOOL check1 = TRUE;
BOOL check2 = FALSE;
STRPTR settinga = "Bananas";
STRPTR settingb = "Lemons";

STRPTR LeftLabels[] =
{
    "Button One",
    "Button Two",
    "Button Three",
    "Button Four",
};

STRPTR RightLabels[] =
{
    "Setting A:",
    "Setting B:",
    "Check 1:",
    "Check 2:",
};

UWORD WinWidth, WinHeight;

/*------------------------------------------------------------------------*/

void main(int, char *[]);
struct Window *initWindow(struct Screen *, struct TextAttr *);
void uninitWindow(struct Window *);
void bail_out(int);
struct Gadget *CreateAllGadgets(struct Gadget **, void *,
	struct Screen *, struct TextAttr *);
BOOL HandleEvent(struct Window *);
void Hit_Button1(struct Window *, struct Gadget *);
void Hit_Button2(struct Window *, struct Gadget *);
void Hit_Button3(struct Window *, struct Gadget *);
void Hit_Button4(struct Window *, struct Gadget *);
void Hit_Check1(struct Window *, struct Gadget *);
void Hit_Check2(struct Window *, struct Gadget *);

/*------------------------------------------------------------------------*/

/*  These are all the things to be allocated/opened, and later
    freed/closed: */

struct GfxBase *GfxBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
struct Library *GadToolsBase = NULL;
struct Library *DiskfontBase = NULL;
struct Screen *mysc = NULL;
struct Window *win = NULL;
struct TextFont *customfont = NULL;
struct Gadget *glist = NULL;
void *vi = NULL;

/*------------------------------------------------------------------------*/

struct TextAttr customtattr;
struct TextAttr *tattr;

/*------------------------------------------------------------------------*/

void main(argc, argv)

int argc;
char *argv[];

{
    /*  Open all libraries: */

    if (argc == 2)
    {
	printf("Usage:\n\tgadget2\nor\n\tgadget2 fontname.font fontsize\n");
	printf("Example:\n\tgadget2 courier.font 15\n");
	bail_out(0);
    }

    if (!(GfxBase = (struct GfxBase *)
	OpenLibrary("graphics.library", 36L)))
	bail_out(20);

    if (!(IntuitionBase = (struct IntuitionBase *)
	OpenLibrary("intuition.library", 36L)))
	bail_out(20);

    if (!(GadToolsBase = OpenLibrary("gadtools.library", 36L)))
	bail_out(20);

    if (!(DiskfontBase = OpenLibrary("diskfont.library", 36L)))
	bail_out(20);

    if (!(mysc = LockPubScreen(NULL)))
	bail_out(20);

    customtattr.ta_Style = 0;
    customtattr.ta_Flags = 0;
    if (argc < 3)
    {
	/*  Default to screen's font */
	tattr = mysc->Font;
    }
    else
    {
    LONG longval;

	/*  Attempt to use the font specified on the command line: */
	customtattr.ta_Name = argv[1];
	/*  Convert decimal size to long */
	stcd_l(argv[2], &longval);
	customtattr.ta_YSize = longval;
	tattr = &customtattr;
	if (!(customfont = OpenDiskFont(tattr)))
	{
	    printf("Could not open font %s %ld\n", customtattr.ta_Name,
		customtattr.ta_YSize);
	    bail_out(20);
	}
    }

    win = initWindow(mysc, tattr);

    if (win)
    {
	while (!HandleEvent(win))
	    ;
	bail_out(0);
    }
    else
	bail_out(20);
}

/*------------------------------------------------------------------------*/

/*/ initWindow()
 *
 *  Open a window, allocate and add all the gadgets.
 *
 */

struct Window *initWindow(screen, tattr)

struct Screen *screen;
struct TextAttr *tattr;

{
    BOOL ok;
    struct Window *win = NULL;

    ok = ((vi = GetVisualInfo(screen,
	TAG_DONE)) != NULL);

    if (ok)
    {
	ok = (CreateAllGadgets(&glist, vi, screen, tattr) != NULL);
    }

    if (ok)
    {
	/*  Open the window: */
    if (!(win = OpenWindowTags(NULL,
	WA_InnerWidth, WinWidth,
	WA_Height, WinHeight,
	WA_AutoAdjust, TRUE,
	WA_PubScreen, screen,
	WA_Activate, TRUE,
	WA_DragBar, TRUE,
	WA_DepthGadget, TRUE,
	WA_CloseGadget, TRUE,
	WA_SizeGadget, TRUE,
	WA_SimpleRefresh, TRUE,

	WA_IDCMP, CLOSEWINDOW | REFRESHWINDOW | BUTTONIDCMP | CHECKBOXIDCMP,

	WA_MinWidth, 50,
	WA_MinHeight, 50,
	WA_Title, "GadTools Font-Sensitive Gadgets",

	TAG_DONE)))
	bail_out(20);
    }

    if (ok)
    {
	/*  Add gadgets, refresh them, and special-refresh them.
	    GT_RefreshWindow() does the refreshing that RefreshGList()
	    will take care of when we switch over to a custom-gadget
	    implementation: */
	AddGList(win, glist, ((UWORD) -1), ((UWORD) -1), NULL);
	RefreshGList(glist, win, NULL, ((UWORD) -1));
	GT_RefreshWindow(win, NULL);
	return(win);
    }
    else
    {
	uninitWindow(win);
	win = NULL;
	return(NULL);
    }	
}

/*------------------------------------------------------------------------*/

/*/ uninitWindow()
 *
 * Take down a window and free stuff associated with it.
 * It's ok to call this with a NULL pointer.
 *
 */

void uninitWindow(win)

struct Window *win;

{
    if (win)
    {
	CloseWindow(win);
    }
    if (glist)
    {
	FreeGadgets(glist);
	glist = NULL;
    }
    if (vi)
    {
	FreeVisualInfo(vi);
	vi = NULL;
    }
}


/*------------------------------------------------------------------------*/

/*/ bail_out()
 *
 * Function to close down or free any opened or allocated stuff, and then
 * exit.
 *
 */

void bail_out(code)

int code;

{

    uninitWindow(win);
    win = NULL;

    if (customfont)
    {
	CloseFont(customfont);
    }

    if (mysc)
    {
	UnlockPubScreen(NULL, mysc);
    }

    if (GadToolsBase)
    {
	CloseLibrary(GadToolsBase);
    }

    if (DiskfontBase)
    {
	CloseLibrary(DiskfontBase);
    }

    if (IntuitionBase)
    {
	CloseLibrary(IntuitionBase);
    }

    if (GfxBase)
    {
	CloseLibrary(GfxBase);
    }

    exit(code);
}


/*------------------------------------------------------------------------*/

/*/ CreateAllGadgets()
 *
 * Here is where all the initialization and creation of toolkit gadgets
 * take place.  This function requires a pointer to a NULL-initialized
 * gadget list pointer.  It returns a pointer to the last created gadget,
 * which can be checked for success/failure.
 *
 */

struct Gadget *CreateAllGadgets(glistptr, vi, screen, tattr)

struct Gadget **glistptr;
void *vi;
struct Screen *screen;
struct TextAttr *tattr;

{
    struct NewGadget ng;
    struct Gadget *gad;
    WORD row1, row2, row3, row4;
    WORD LeftWidth = 0;
    WORD RightWidth = 0;
    WORD FarRightWidth = 0;
    WORD width;
    struct RastPort TextRP;
    WORD i;
    UWORD topborder;
    struct TextFont *font;

    topborder = screen->WBorTop + (screen->Font->ta_YSize + 1);


    if (!(font = OpenFont(tattr)))
    {
	return(NULL);
    }

    InitRastPort(&TextRP);
    SetFont(&TextRP, font);

    /*  Need to know widest label in left and right columns */
    for (i = 0; i < 3; i++)
    {
	if ( (width = TextLength(&TextRP, LeftLabels[i],
	    (WORD)strlen(LeftLabels[i]))) > LeftWidth)
	{
	    LeftWidth = width;
	}
	if ( (width = TextLength(&TextRP, RightLabels[i],
	    (WORD)strlen(RightLabels[i]))) > RightWidth)
	{
	    RightWidth = width;
	}
    }

    FarRightWidth = TextLength(&TextRP, settinga, strlen(settinga));
    i = TextLength(&TextRP, settingb, strlen(settingb));
    if (i > FarRightWidth)
    {
	FarRightWidth = i;
    }

    /*  We obligingly perform the following operation, required of
	any program that uses the toolkit.  It gives the toolkit a
	place to stuff context data: */
    gad = CreateContext(glistptr);

    /*  Fill out a NewGadget structure for each gadget we want
	to create: */

    ng.ng_LeftEdge = 10;
    row1 = ng.ng_TopEdge = 6+topborder;
    ng.ng_Width = LeftWidth+16;
    ng.ng_Height = font->tf_YSize+4;
    ng.ng_GadgetText = LeftLabels[0];
    ng.ng_TextAttr = tattr;
    ng.ng_Flags = 0;
    ng.ng_UserData = (APTR) Hit_Button1;
    ng.ng_VisualInfo = vi;
    gad = CreateGadget(BUTTON_KIND, gad, &ng,
	TAG_DONE);

    if (gad)
    {
	row2 = ng.ng_TopEdge += gad->Height + 4;
    }
    ng.ng_GadgetText = LeftLabels[1];
    ng.ng_UserData = (APTR) Hit_Button2;
    gad = CreateGadget(BUTTON_KIND, gad, &ng,
	TAG_DONE);

    if (gad)
    {
	row3 = ng.ng_TopEdge += gad->Height + 4;
    }
    ng.ng_GadgetText = LeftLabels[2];
    ng.ng_UserData = (APTR) Hit_Button3;
    gad = CreateGadget(BUTTON_KIND, gad, &ng,
	TAG_DONE);

    if (gad)
    {
	row4 = ng.ng_TopEdge += gad->Height + 4;
    }
    ng.ng_GadgetText = LeftLabels[3];
    ng.ng_UserData = (APTR) Hit_Button4;
    gad = CreateGadget(BUTTON_KIND, gad, &ng,
	TAG_DONE);

    if (gad)
    {
	WinHeight = ng.ng_TopEdge += gad->Height + 8;
    }

    ng.ng_GadgetText = RightLabels[0];
    ng.ng_UserData = NULL;
    /*  The text in a Text gadget will be two pixels beneath a button
	gadget's text. */
    ng.ng_TopEdge = row1+2;
    ng.ng_LeftEdge += ng.ng_Width + 26 + RightWidth;
    ng.ng_Height = font->tf_YSize;
    gad = CreateGadget(TEXT_KIND, gad, &ng,
	GTTX_Text, settinga,
	TAG_DONE);

    if (gad)
    {
	WinWidth = ng.ng_LeftEdge + FarRightWidth + 2;
    }

    ng.ng_GadgetText = RightLabels[1];
    ng.ng_TopEdge = row2+2;
    gad = CreateGadget(TEXT_KIND, gad, &ng,
	GTTX_Text, settingb,
	TAG_DONE);

    ng.ng_GadgetText = RightLabels[2];
    ng.ng_TopEdge = row3;
    ng.ng_UserData = (APTR) Hit_Check1;
    gad = CreateGadget(CHECKBOX_KIND, gad, &ng,
	GTCB_Checked, check1,
	TAG_DONE);

    ng.ng_GadgetText = RightLabels[3];
    ng.ng_TopEdge = row4;
    ng.ng_UserData = (APTR) Hit_Check2;
    gad = CreateGadget(CHECKBOX_KIND, gad, &ng,
	GTCB_Checked, check2,
	TAG_DONE);

    CloseFont(font);
    return(gad);
}


/*------------------------------------------------------------------------*/

/*/ HandleEvent()
 *
 * Handle an Intuition event.  Returns TRUE if a terminating
 * event was found.
 *
 */

BOOL HandleEvent(win)

struct Window *win;

{
    BOOL terminated = FALSE;
    void (*fptr)(struct Window *, struct Gadget *);
    struct IntuiMessage *imsg;
    ULONG imsgClass;
    struct Gadget *gad;

    Wait (1 << win->UserPort->mp_SigBit);
    /*  GT_GetIMsg() returns a cooked-up IntuiMessage with
	more friendly information for complex gadget classes.  Use
	it wherever you get IntuiMessages: */
    while (imsg = GT_GetIMsg(win->UserPort))
    {
	imsgClass = imsg->Class;
	/*  Presuming a gadget, of course, but no harm... */
	gad = (struct Gadget *)imsg->IAddress;
	GT_ReplyIMsg(imsg);
	switch (imsgClass)
	{
	    case GADGETUP:
		if (fptr = (void (*)(struct Window *, struct Gadget *))gad->UserData)
		{
		    (*fptr)(win, gad);
		}
		break;

	    case CLOSEWINDOW:
		terminated = TRUE;
		break;

	    case REFRESHWINDOW:
		/*  You must use GT_BeginRefresh() where you would
		    normally have your first BeginRefresh() */
		GT_BeginRefresh(win);
		GT_EndRefresh(win, TRUE);
		break;
	}
    }
    return(terminated);
}


/*------------------------------------------------------------------------*/

/*/ Hit_Button1()
 *
 * Button1 gadget handler.
 *
 */

void Hit_Button1(win, gad)

struct Window *win;
struct Gadget *gad;

{
    printf("Clicked on Button1\n");
}


/*------------------------------------------------------------------------*/

/*/ Hit_Button2()
 *
 * Button2 gadget handler.
 *
 */

void Hit_Button2(win, gad)

struct Window *win;
struct Gadget *gad;

{
    printf("Clicked on Button2\n");
}


/*------------------------------------------------------------------------*/

/*/ Hit_Button3()
 *
 * Button3 gadget handler.
 *
 */

void Hit_Button3(win, gad)

struct Window *win;
struct Gadget *gad;

{
    printf("Clicked on Button3\n");
}


/*------------------------------------------------------------------------*/

/*/ Hit_Button4()
 *
 * Button4 gadget handler.
 *
 */

void Hit_Button4(win, gad)

struct Window *win;
struct Gadget *gad;

{
    printf("Clicked on Button4\n");
}


/*------------------------------------------------------------------------*/

/*/ Hit_Check1()
 *
 * Check1 gadget handler.
 *
 */

void Hit_Check1(win, gad)

struct Window *win;
struct Gadget *gad;

{
    printf("Check1 now ");
    if (gad->Flags & SELECTED)
	printf("on.\n");
    else
	printf("off.\n");
}


/*------------------------------------------------------------------------*/

/*/ Hit_Check2()
 *
 * Check2 gadget handler.
 *
 */

void Hit_Check2(win, gad)

struct Window *win;
struct Gadget *gad;

{
    printf("Check2 now ");
    if (gad->Flags & SELECTED)
	printf("on.\n");
    else
	printf("off.\n");
}


/*------------------------------------------------------------------------*/
