/*
** menu1.c:  Menu example with font-sensitivity.
**
** (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>

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

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

void main(int, char *[]);
void bail_out(int);
BOOL HandleMenuEvent(UWORD);
BOOL OpenFunc(UWORD);
BOOL SaveFunc(UWORD);
BOOL PrintFunc(UWORD);
BOOL QuitFunc(UWORD);

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

/* Here we specify what we want our menus to contain: */

struct NewMenu mynewmenu[] =
{
	{ NM_TITLE, "Project",	  0 , 0, 0, 0,},
	{  NM_ITEM, "Open...",	 "O", 0, 0, OpenFunc,},
	{  NM_ITEM, "Save",	  0 , 0, 0, SaveFunc,},
	{  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0,},
	{  NM_ITEM, "Print",	  0 , 0, 0, 0,},
	{   NM_SUB, "Draft",	  0 , 0, 0, PrintFunc,},
	{   NM_SUB, "NLQ",	  0 , 0, 0, PrintFunc,},
	{  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0,},
	{  NM_ITEM, "Quit...",	 "Q", 0, 0, QuitFunc,},

	{ NM_TITLE, "Edit",	  0 , 0, 0, 0,},
	{  NM_ITEM, "Cut",	 "X", 0, 0, 0,},
	{  NM_ITEM, "Copy",	 "C", 0, 0, 0,},
	{  NM_ITEM, "Paste",	 "V", 0, 0, 0,},
	{  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0,},
	{  NM_ITEM, "Undo",	 "Z", 0, 0, 0,},

	{   NM_END, 0,		  0 , 0, 0, 0,},
};

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

struct TextAttr customtattr;
struct TextAttr *tattr;

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

extern struct Library *SysBase;
struct GfxBase *GfxBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
struct Library *GadToolsBase = NULL;
struct Library *DiskfontBase = NULL;
struct Screen *mysc = NULL;
struct Menu *menu = NULL;
struct Window *mywin = NULL;
struct TextFont *customfont = NULL;
void *vi = NULL;

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

BOOL terminated;

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

void main(argc, argv)

int argc;
char *argv[];

{
    struct IntuiMessage *imsg;
    ULONG imsgClass;
    UWORD imsgCode;
    ULONG errorcode = 0;

    terminated = FALSE;

    if (argc == 2)
    {
	printf("Usage:\n\tmenu1\nor\n\tmenu1 fontname.font fontsize\n");
	printf("Example:\n\tmenu1 courier.font 15\n");
	bail_out(0);
    }
    /* Open all libraries: */

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

    if (!(vi = GetVisualInfo(mysc,
	TAG_DONE)))
	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);
	}
    }

    /* Build and layout menus using the right font: */
    if (!(menu = CreateMenus(mynewmenu,
	GTMN_FrontPen, 0,
	GTMN_SecondaryError, &errorcode,
	TAG_DONE)))
    {
	switch ( errorcode )
	{
	    case GTMENU_INVALID:
		/* Bad ordering of menu elements in the NewMenu structure. */
		printf("Invalid menu structure!\n");
		break;

	    case GTMENU_NOMEM:
		printf("Out of memory in CreateMenus()!\n");
		break;

	    default:
		printf("Failed to create menus for unknown reason\n");
		break;
	}
	bail_out(20);
    }

    if (errorcode == GTMENU_TRIMMED)
    {
	/* This condition does not cause failure.  Your menu will
	 * be trimmed instead.  (This won't happen in the example, since
	 * the maximum number of menus, items, or sub-items is not
	 * exceeded.  The test is included to demonstrate its use.
	 */
	printf(" Too many menu elements -- some have been trimmed off\n");
    }

    if (!LayoutMenus(menu, vi,
	GTMN_TextAttr, tattr,
	TAG_DONE))
	bail_out(20);

    if (!(mywin = OpenWindowTags(NULL,
	WA_Width, 500,
	WA_InnerHeight, 100,

	WA_Activate, TRUE,
	WA_DragBar, TRUE,
	WA_DepthGadget, TRUE,
	WA_CloseGadget, TRUE,
	WA_SizeGadget, TRUE,
	WA_SimpleRefresh, TRUE,

	/* NOTE: NOCAREREFRESH is not allowed if you use GadTools Gadgets! */
	WA_NoCareRefresh, TRUE,

	WA_IDCMP, CLOSEWINDOW | MENUPICK,

	WA_MinWidth, 50,
	WA_MinHeight, 50,
	WA_Title, "GadTools Menu Demo",

	TAG_DONE)))
	bail_out(20);

    SetMenuStrip(mywin, menu);

    while (!terminated)
    {
	Wait (1 << mywin->UserPort->mp_SigBit);
	/* NOTE:  If you use GadTools gadgets, you must use GT_GetIMsg()
	 * and GT_ReplyIMsg() instead of GetMsg() and ReplyMsg().
	 */
	while ((!terminated) && (imsg = (struct IntuiMessage *)GetMsg(mywin->UserPort)))
	{
	    imsgClass = imsg->Class;
	    imsgCode = imsg->Code;
	    ReplyMsg(imsg);
	    switch (imsgClass)
	    {
		case MENUPICK:
		    terminated = HandleMenuEvent(imsgCode);
		    break;

		case CLOSEWINDOW:
		    printf("CLOSEWINDOW.\n");
		    terminated = TRUE;
		    break;
	    }
	}
    }
    bail_out(0);
}

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

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

void bail_out(code)

int code;

{
    if (mywin)
    {
	ClearMenuStrip(mywin);
	CloseWindow(mywin);
    }

    /* None of these two calls mind a NULL parameter, so it's not
     * necessary to check for non-NULL before calling.  If we do that,
     * we must be certain that the OpenLibrary() of GadTools succeeded,
     * or else we would be jumping into outer space:
     */
    if (GadToolsBase)
    {
	FreeMenus(menu);
	FreeVisualInfo(vi);
	CloseLibrary(GadToolsBase);
    }

    if (customfont)
    {
	CloseFont(customfont);
    }

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

    if (DiskfontBase)
    {
	CloseLibrary(DiskfontBase);
    }

    if (IntuitionBase)
    {
	CloseLibrary(IntuitionBase);
    }

    if (GfxBase)
    {
	CloseLibrary(GfxBase);
    }

    exit(code);
}


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

/*/ HandleMenuEvent()
 *
 * This function handles IntuiMessage events of type MENUPICK.  It
 * demonstrates one of the best uses for the MenuItem UserData field
 * provided by GadTools, namely a place to store pointers-to-functions.
 *
 */

BOOL HandleMenuEvent(code)

UWORD code;

{
    struct MenuItem *item;
    BOOL terminated = FALSE;
    BOOL (*fptr)(UWORD);

    printf("MENUPICK:  ");
    /* Get all menu events including NextEvents until a terminating
     * selection is made (such as Quit)
     */
    while ((code != MENUNULL) && (!terminated))
    {
	item = ItemAddress(menu, code);
	if (fptr = GTMENUITEM_USERDATA(item))
	{
	    terminated = (*fptr)(code);
	}
	else
	{
	    printf("No function.  ");
	}
	code = item->NextSelect;
    }
    printf("\n");

    return(terminated);
}

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

BOOL OpenFunc(code)

UWORD code;

{
    printf("OpenFunc called.  ");
    return(FALSE);
}

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

BOOL SaveFunc(code)

UWORD code;

{
    printf("SaveFunc called.  ");
    return(FALSE);
}
/*------------------------------------------------------------------------*/

BOOL PrintFunc(code)

UWORD code;

{
    printf("PrintFunc called ");
    if (code == FULLMENUNUM(0, 3, 0))
    {
	printf("(Draft).  ");
    }
    else
    {
	printf("(NLQ).  ");
    }
    return(FALSE);
}
/*------------------------------------------------------------------------*/

BOOL QuitFunc(code)

UWORD code;

{
    printf("QuitFunc called.  ");
    return(TRUE);
}
/*------------------------------------------------------------------------*/
