head	1.1;
access;
symbols;
locks;
comment	@ * @;


1.1
date	93.07.02.18.26.52;	author wolff;	state Exp;
branches;
next	;


desc
@@


1.1
log
@Initial revision
@
text
@/*
 * Complex Gadtols Example Program
 * Programmed By Mike Schwartz
 * Donated to the Amiga public Domain to aid in future 2.0
 * application development.
 *
 * To compile:
 *	lc gt.c
 *	blink lib:c.o+gt.o to gt library lib:lc.lib+lib:amiga2.0.lib
 * Executeable = 12124 bytes.
 */

#include	"exec/types.h"
#include	"libraries/gadtools.h"
#include	"intuition/gadgetclass.h"
#include	"graphics/displayinfo.h"
#include	"proto/intuition.h"
#include	"proto/gadtools.h"

/*
 * I wish the standard headers from CBM were typedefed like this (below).
 * It saves me the trouble of typing the word "struct" in every declaration
 * and cast (casts are ugly enough and tend to make your source lines run
 * off the right edge of the screen.
 */
typedef struct Library		LIBRARY;
typedef struct TagItem		TAGS;
typedef struct List		LIST;
typedef struct Node		NODE;
typedef struct VisualInfo	VINFO;
typedef struct Gadget		GADGET;
typedef struct NewGadget	NEWGAD;
typedef struct Screen		SCREEN;
typedef struct Window		WINDOW;
typedef struct ViewPort		VPORT;
typedef struct RastPort		RPORT;
typedef struct IntuiMessage	IMSG;
typedef struct TextAttr		TATTR;
typedef struct StringInfo	STRINGINFO;

/*
 * By making an Array of these, you can write a short routine to open
 * and close the libraries.  This saves memory and makes it easy to
 * open an additional library/base.  I tried to use LIBRARY ** intead
 * of APTR *, but the compiler complained.
 */
typedef struct {
	char	*name;
	APTR	*base;
} LIBDEFS;

/*
 * By making an Array of these, you can use a simple/short routine to
 * create GadTools gadgets.  These fields are copied into the NewGadget
 * structure.
 */
typedef struct GADDEF {
	TAGS	*tags;
	ULONG	kind;
	UWORD	left,top,width,height;
	ULONG	flags;
	char	*text;
} GADDEF;

void	panic0();

/************************************************************************/

/*
 * List of libraries used
 */
struct IntuitionBase	*IntuitionBase = 0;
struct GfxBase	*GfxBase = 0;
LIBRARY	*DiskfontBase = 0;
LIBRARY	*AslBase = 0;
LIBRARY	*GadToolsBase = 0;

/*
 * Without this look3D array passed to the OpenScreenTags() call, you
 * don't get the 3D effect.  Why this isn't the default, only CBM knows :)
 */
UWORD	look3D[] = { ~0, };

/*
 * This text attribute is the default text attribute used for various
 * features.  It should be openable via OpenFont(), which implies an
 * OpenDiskFont() call to load it into memory.  In this case, topaz80
 * is a ROM font, so I don't bother.  BEWARE if you choose another !!!
 */
TATTR	topaz80 = { "topaz.font", 8, 0,0 };

/*
 * Standard Intuition/GadTools variables.  The gList list is public because
 * I prefer to use Tag arrays instead of the varargs versions of the functions.
 * TagArrays can be used in multiple calls, while varargs requires the tagarrays
 * to be duplicated for each use.
 */
VINFO	*vi = 0;
SCREEN	*screen = 0;
WINDOW	*window = 0;
VPORT	*vp;
RPORT	*rp;
GADGET	*gList = 0;

/*
 * Array of library names/base pointers.  To open an additional library, define
 * the base above and add a line here.
 */
LIBDEFS	libDefs[] = {
	"intuition.library",(APTR *)&IntuitionBase,
	"graphics.library",(APTR *)&GfxBase,
	"diskfont.library",(APTR *)&DiskfontBase,
	"asl.library",(APTR *)&AslBase,
	"gadtools.library",(APTR *)&GadToolsBase,
	0,0
};

/*
 * IDCMP flags.  GADIDCMP are those for GadTools, MYIDCMP are the ones I personally want.
 */
#define	GADIDCMP	(SLIDERIDCMP|STRINGIDCMP|BUTTONIDCMP|CYCLEIDCMP|LISTVIEWIDCMP)
#define	MYIDCMP		(IDCMP_VANILLAKEY|IDCMP_RAWKEY|IDCMP_REFRESHWINDOW)|GADIDCMP

/*
 * Default color palette
 */
UWORD	palette[] = { 
	0x0888,0x0666,0x0FFF,0x0222,0x000F,0x0F0F,0x00FF,0x0FFF,
	0x0620,0x0E50,0x09F1,0x0EB0,0x055F,0x092F,0x00F8,0x0CCC,
};

/*
 * Used to keep track of which color palette value is being worked on.
 */
UWORD	paletteChoice = 0;

/************************************************************************/

/*
 * This array is converted into an Exec style list for use with the
 * listview gadget.
 */
char	 *listText[] = {
	"item 1",
	"item 2",
	"item 3",
	"item 4",
	"item 5",
	"item 6",
	"item 7",
	"item 8",
	"item 9",
	"item 10",
	"item 11",
	"item 12",
	"item 13",
	"item 14",
	"item 15",
	"item 16",
	"item 17",
	"item 18",
	"item 19",
	"item 20",
	0,
};

/*
 * I wanted to play around with modifying a listview, so I created a read-only
 * one for doing my printf's into (instead of the CLI window).  The default/initial
 * list is created from this array.  Apparently, an empty (initialized) list header
 * doesn't work.
 */
char	*eventText[] = {
	"Gadtools events displayed",
	"in this ListView",
	0,
};

/*
 * Text arrays for the mx gadget and cycle gadget
 */
char	*mxText[] = { "mx 1", "mx 2", "mx 3", 0 };
char	*cycleText[] = { "choice1", "choice2", "choice3", 0 };

/*
 * Exec linked list headers for the list views
 */
LIST	lvList;
LIST	eventList;

/* 
 * Misc tags arrays 
 */
TAGS	nullTags[] = { TAG_DONE,0 };
TAGS	disableTags[] = { GA_Disabled,TRUE, TAG_DONE,0 };
TAGS	enableTags[] = { GA_Disabled,FALSE, TAG_DONE,0 };

TAGS	cycleTags[] = { GTCY_Labels,&cycleText[0], GTBB_Recessed,FALSE, TAG_DONE,0 };
TAGS	mxTags[] = { GTMX_Labels,&mxText[0], GTMX_Spacing,INTERHEIGHT, TAG_DONE,0 };
TAGS	listviewTags[] = { 
	GTLV_Labels,&lvList, 
	GTLV_ReadOnly,FALSE, 
	GTLV_ScrollWidth,16, 
	GTLV_ShowSelected,NULL,
	TAG_DONE,0,
};
TAGS	paletteTags[] = {
	GTPA_Depth,4,
	GTPA_Color,0,
	GTPA_ColorOffset,0,
	GTPA_IndicatorWidth,16,
	GTPA_IndicatorHeight,16,
	TAG_DONE,0,
};
TAGS	rgbTags[] = {
	GTSL_Min,0,
	GTSL_Max,15,
	GTSL_Level,0,
	GTSL_MaxLevelLen,3,
	GTSL_LevelFormat,(APTR)"%2ld",
	GTSL_LevelPlace,PLACETEXT_ABOVE,
	PGA_FREEDOM,LORIENT_VERT,
	TAG_DONE,0
};
TAGS	eventTags[] = { 
	GTLV_Labels,&eventList, 
	GTLV_ReadOnly,TRUE, 
	GTLV_ScrollWidth,16, 
	TAG_DONE,0,
};
TAGS	intTags[] = {
	GTIN_Number,456,
#ifdef STRINGA_ExitHelp
	STRINGA_ExitHelp,TRUE,
#endif
	TAG_DONE,0,
};
TAGS	numberTags[] = {
	GTNM_Number,456,
	GTNM_Border,TRUE,
	TAG_DONE,0,
};
TAGS	stringTags[] = {
	GTTX_CopyText,TRUE,
	GTTX_Border,TRUE,
#ifdef STRINGA_ExitHelp
	STRINGA_ExitHelp,TRUE,
#endif
	TAG_DONE,0,
};

/*
 * The Array of Gadget definitions.  To create a new gadget, add an initializer
 * here, and create the necessary tags...
 */
GADDEF	gadDefs[] = {
	cycleTags, CYCLE_KIND, 140,20,80,12, NG_HIGHLABEL, "CYCLE Gadget:",
	nullTags, CHECKBOX_KIND, 140,34,80,12, NG_HIGHLABEL, "CHECKBOX Gadget:",
	mxTags, MX_KIND, 100,184,100,12, NG_HIGHLABEL, "MX Gadget:",
	nullTags, BUTTON_KIND, 300,200-16,40,12, NG_HIGHLABEL|PLACETEXT_IN, "ADD",
	disableTags, BUTTON_KIND, 300+40+INTERWIDTH,200-16,40,12, NG_HIGHLABEL|PLACETEXT_IN, "DEL",
	listviewTags, LISTVIEW_KIND, 400,100,100,100, NG_HIGHLABEL|PLACETEXT_ABOVE, "LISTVIEW Gadget:",
	paletteTags, PALETTE_KIND, 400,240,100,100, NG_HIGHLABEL|PLACETEXT_ABOVE, "PALETTE:",
	rgbTags, SLIDER_KIND, 520,240,12,100, NG_HIGHLABEL|PLACETEXT_BELOW, "R",
	rgbTags, SLIDER_KIND, 520+12+INTERWIDTH,240,12,100, NG_HIGHLABEL|PLACETEXT_BELOW, "G",
	rgbTags, SLIDER_KIND, 520+12+12+INTERWIDTH+INTERWIDTH,240,12,100, NG_HIGHLABEL|PLACETEXT_BELOW, "B",
	eventTags, LISTVIEW_KIND, 10,240,380,100, NG_HIGHLABEL, "Event List",
	nullTags, BUTTON_KIND, 10,360,80,12, NG_HIGHLABEL|PLACETEXT_IN, "QUIT",
	intTags, INTEGER_KIND, 140,48,80,12, NG_HIGHLABEL, "INTEGER Gadget:",
	numberTags, NUMBER_KIND, 140,62,80,12, NG_HIGHLABEL, "NUMBER Gadget:",
	stringTags, STRING_KIND, 140,76,80,12, NG_HIGHLABEL, "STRING Gadget:",
	0,0,0,0,0,0,0,0,
};

/*
 * Some GadTools gadgets, like ListViews are made of more than one Intuition Gadget.
 * The IAddress field of the IntuiMessage doesn't always point to the gadget that
 * GadTools can use (i.e. with GT_SetGadgetAttrs()).  For this reason, I keep
 * an array of pointer to the gadgets that CreateGadget() returns for each gadget
 * in the GadDefs array above.
 */
GADGET	*gadgetArray[1000];	/* one for each gadtools gadget created */

/*
 * As each gadget in the GadDefs array above is created, it is assigned a UserID
 * field value, incremented from zero.  The following defines are useful for switch
 * statements, etc.  Enum would also work.  Be careful, if you add new gadgets in
 * the middle of the initializations above, because you will need to renumber these
 * defines.
 */
#define	CYCLE_ID	0
#define	CHECKBOX_ID	1
#define	MX_ID		2
#define	ADD_ID		3
#define	DEL_ID		4
#define	LISTVIEW_ID	5
#define	PALETTE_ID	6
#define	RED_ID		7
#define	GREEN_ID	8
#define	BLUE_ID		9
#define	EVENT_ID	10
#define	QUIT_ID		11
#define	INTEGER_ID	12
#define	NUMBER_ID	13
#define	STRING_ID	14

/************************************************************************/

/*
 * These might be the shortest open/close library routines ever :)
 */
void	CloseLibs(LIBDEFS libDefs[]) {
	short	i;

	for (i=0; libDefs[i+1].name; i++);
	while (i >= 0) {
		if (*libDefs[i].base) CloseLibrary((LIBRARY *)*libDefs[i].base);
		*libDefs[i--].base = 0;
	}
}

void	OpenLibs(LIBDEFS libDefs[]) {
	short	i;

	for (i=0; libDefs[i].name; i++) {
		*libDefs[i].base = (APTR)OpenLibrary(libDefs[i].name, 0);
		panic0(*libDefs[i].base, "Can't open %s", libDefs[i].name);
	}
}

/************************************************************************/

/*
 * void	CreateList(list, array);
 * LIST	*list;		List header to initialize and create list for
 * char	*array[];	null terminated array of strings to make into list
 *
 * Synopsis:
 *	Pass this routine a list header and an array of strings, and it
 *	creates an Exec list, suitable for use with ListViews.
 */
void	CreateList(LIST *list, char *array[]) {
	short	i;
	NODE	*np;

	NewList(list);
	for (i=0; array[i]; i++) {
		np = (NODE *)malloc(sizeof(NODE));
		panic0(np, "Can't malloc NODE");
		np->ln_Name = (APTR)array[i];
		np->ln_Pri = 0;
		AddTail(list, np);
	}
}

/*
 * void	AddList(list, s);
 * LIST	*list;		list to add string to
 * char	*s;		string to add to list
 *
 * Synopsis:
 *	Allocates a NODE structure and space to hold the string
 *	and adds the node to the tail of the specified list.
 */
void	AddList(LIST *list, char *s) {
	NODE	*np = (NODE *)malloc(sizeof(NODE));
	panic0(np, "Can't AddList");
	np->ln_Pri = 0;
	np->ln_Name = (APTR)malloc(strlen(s)+1);
	panic0(np->ln_Name, "Can't malloc %d bytes for AddList", strlen(s)+1);
	strcpy(np->ln_Name, s);
	AddTail(list, np);
}

/************************************************************************/

/*
 * gadgetList = CreateGadgets(gadArray);
 * GADGET	*gadgetList;		list of created gadgets
 * GADDEF	gadArray[];		array of gadget initializations
 *
 * Synopsis:
 *	Pass in a gadArray, and you get an initialized list of gadgets,
 *	suitable for linking to a window for GadTools.
 */
GADGET	*CreateGadgets(GADDEF gadArray[]) {
	GADGET	*gadget, *glist = 0;
	short	i;
	NEWGAD	ng;

	gadget = CreateContext(&glist);
	panic0(gadget, "Can't CreateContext");
	for (i=0; gadArray[i].tags; i++) {
		ng.ng_GadgetID = i;
		ng.ng_TextAttr = &topaz80;
		ng.ng_VisualInfo = vi;
		ng.ng_LeftEdge = gadArray[i].left;
		ng.ng_TopEdge = gadArray[i].top;
		ng.ng_Width = gadArray[i].width;
		ng.ng_Height = gadArray[i].height;
		ng.ng_GadgetText = gadArray[i].text;
		ng.ng_Flags = gadArray[i].flags;
		gadgetArray[i] = gadget = CreateGadgetA(gadArray[i].kind, gadget, &ng, gadArray[i].tags);
		panic0(gadget, "Can't CreateGadget");
	}
	return glist;
}

/************************************************************************/

/*
 * void	CloseDisplay();
 *
 * Synopsis:
 *	Close the window and screen, free VisualInfo, and gadgets.
 */
void	CloseDisplay(void) {
	IMSG	*msg;

	if (window) {
		while (msg = (IMSG *)GT_GetIMsg(window->UserPort)) GT_ReplyIMsg(msg);
		CloseWindow(window);
		window = 0;
	}
	if (screen) {
		CloseScreen(screen);
		screen = 0;
	}
	if (vi) {
		FreeVisualInfo(vi);
		vi = 0;
	}
	if (gList) {
		FreeGadgets(gList);
		gList = 0;
	}
}

/*
 * void	OpenDisplay(void);
 *
 * Synopsis:
 *	Open the screen, window, and get visual info... create gadgets.
 */
void	OpenDisplay(void) {
	screen = OpenScreenTags(NULL, 
		SA_Left,0,
		SA_Top,0,
		SA_Width,640,
		SA_Height,400,
		SA_Depth,4,
		SA_DetailPen,0,
		SA_BlockPen,3,
		SA_Title,"  GADTOOLS DEMO By Mike Schwartz",
		SA_ErrorCode,0,
		SA_Font,&topaz80,
		SA_SysFont,0,
		SA_Type,CUSTOMSCREEN,
		SA_ShowTitle,TRUE,
		SA_Pens,&look3D[0],
		SA_DisplayID,HIRESLACE_KEY,
		TAG_DONE
	);
	panic0(screen, "Can't open screen");

	rp = &screen->RastPort;
	vp = &screen->ViewPort;
	LoadRGB4(vp, palette, 16);
	vi = GetVisualInfo(screen, TAG_DONE);
	panic0(vi, "Can't GetVisualInfo");
	gList = CreateGadgets(&gadDefs[0]);
	window = OpenWindowTags(NULL, 
		WA_Left,0,
		WA_Top,0,
		WA_Width,640,
		WA_Height,400,
		WA_DetailPen,0,
		WA_BlockPen,3,
		WA_IDCMP,MYIDCMP,
		WA_Gadgets,gList,
		WA_Title,0,
		WA_CustomScreen,screen,
		WA_SuperBitMap,0,
		WA_MinWidth,30,
		WA_MinHeight,30,
		WA_MaxWidth,-1,
		WA_MaxHeight,-1,
		WA_SizeGadget,FALSE,
		WA_DragBar,FALSE,
		WA_DepthGadget,FALSE,
		WA_CloseGadget,FALSE,
		WA_Backdrop,TRUE,
		WA_ReportMouse,FALSE,
		WA_Borderless,TRUE,
		WA_Activate,TRUE,
		WA_RMBTrap,FALSE,
		WA_SimpleRefresh,TRUE,
		TAG_DONE
	);
	panic0(window, "Can't open window");
	GT_RefreshWindow(window, NULL);
}

/************************************************************************/

/*
 * void	Abort(void);
 *
 * Synopsis:
 *	Cleanup and exit.  Can be called anywhere, anytime, including from
 *	the debugger by setting PC = Abort.
 */
long	abort_code = 0;
void	Abort(void) {
	CloseDisplay();
	CloseLibs(&libDefs[0]);
	exit(abort_code);
}

/*
 * void	Init(void);
 *
 * Synopsis:
 *	Initialize libraries, lists, and the display.
 */
void	Init(void) {
	OpenLibs(&libDefs[0]);
	CreateList(&lvList, &listText[0]);
	CreateList(&eventList, &eventText[0]);
	OpenDisplay();
}

/*
 * void	panic0(v, s,a1,a2,a3,a4);
 * ULONG	v;
 * char		*s;
 * ULONG	a1,a2,a3,a4;
 *
 * Synopsis:
 *	Anywhere you use:
 *		v = (some function);
 *		if (!v) {
 *			printf("some string");
 *			Abort();
 *		}
 *	You can use:
 *		v = (some function);
 *		panic0(v, "some string");
 *	The string and args (a1,a2,a3,a4) are passed to printf...
 */
void	panic0(v, s,a1,a2,a3,a4)
ULONG	v;
char	*s;
ULONG	a1,a2,a3,a4;
{
	if (v) return;
	Printf("Panic: ");
	Printf(s, a1,a2,a3,a4);
	Printf("\n");
	abort_code = 999;
	Abort();
}

/************************************************************************/

/* The meat/guts of the application starts here */

/*
 * void	lvprintf(fmt,a1,a2,a3,a4);
 * char		*fmt;
 * ULONG	a1,a2,a3,a4;
 *
 * Synopsis:
 *	Similar to printf, except the results end up at the end of the
 *	"event" listview.  Only 4 args supported to printf...
 */
void	lvprintf(fmt,a1,a2,a3,a4)
char	*fmt;
ULONG	a1,a2,a3,a4;
{
	char		buf[128];
	static UWORD	ndx = 0;
	GADGET		*eventGadget = gadgetArray[EVENT_ID];

	sprintf(buf, fmt,a1,a2,a3,a4);
	GT_SetGadgetAttrs(eventGadget, window, NULL, GTLV_Labels, ~0, TAG_DONE);
	AddList(&eventList, buf);
	GT_SetGadgetAttrs(eventGadget, window, NULL, GTLV_Labels, &eventList, TAG_DONE);
	GT_SetGadgetAttrs(eventGadget, window, NULL, GTLV_Top, ndx++, TAG_DONE);
}

/*
 * void	PickColor(colorNum);
 * UWORD	colorNum;
 *
 * Synopsis:
 *	This routine is called to select a color in the Palette Gadget.  Can be
 *	called to set the initially chosen color, or when the palette gadget is
 *	hit.  Sets the slider values to the RGB of the selected colors.
 */
void	PickColor(UWORD colorNum)  {
	UWORD	red, green, blue;

	paletteChoice = colorNum;
	red = palette[colorNum];
	green = (red>>4) & 15;
	blue = red & 15;
	red = (red>>8) & 15;
	GT_SetGadgetAttrs(gadgetArray[RED_ID], window, NULL, GTSL_Level, red, TAG_DONE);
	GT_SetGadgetAttrs(gadgetArray[GREEN_ID], window, NULL, GTSL_Level, green, TAG_DONE);
	GT_SetGadgetAttrs(gadgetArray[BLUE_ID], window, NULL, GTSL_Level, blue, TAG_DONE);
	GT_SetGadgetAttrs(gadgetArray[PALETTE_ID], window, NULL, GTPA_Color, colorNum, TAG_DONE);
}

/*
 * void	ModifyColor(r,g,b);
 * short	r,g,b;
 *
 * Synopsis:
 *	Used to set the RGB values of the current palette gadget color to specified values.
 *	r,g, or b can be -1, and the values currently in the palette will be used.
 */
void	ModifyColor(short r, short g, short b) {
	short	red, green, blue;

	red = palette[paletteChoice];
	green = (red>>4) & 15;
	blue = red & 15;
	red = (red>>8) & 15;
	if (r != -1) red = r;
	if (g != -1) green = g;
	if (b != -1) blue = b;
	palette[paletteChoice] = ((red<<8)&0xf00)|((green<<4)&0x0f0)|(blue&0x00f);
	LoadRGB4(vp, palette, 16);
	GT_SetGadgetAttrs(gadgetArray[RED_ID], window, NULL, GTSL_Level, red, TAG_DONE);
	GT_SetGadgetAttrs(gadgetArray[GREEN_ID], window, NULL, GTSL_Level, green, TAG_DONE);
	GT_SetGadgetAttrs(gadgetArray[BLUE_ID], window, NULL, GTSL_Level, blue, TAG_DONE);
}

/*
 * void	ProcessGadget(id, code);
 * UWORD	id;		gadgetID of gadget to process
 * UWORD	code;		IntuiMessage Code
 *
 * Synopsis:
 *	Process IDCMP message for GadTools gadget.  Simply prints an appropriate string
 *	into the event listview, unless it is palette related (handles palette appropriately).
 */
void	ProcessGadget(UWORD id, UWORD code) {
	GADGET	*gad = gadgetArray[id];
	long	val;

	switch (id) {
		case CYCLE_ID:
			lvprintf("Cycle Gadget, %s", cycleText[code]); break;
		case CHECKBOX_ID:
			lvprintf("Checkbox Gadget, %s", (gad->Flags&SELECTED) ? "TRUE" : "FALSE"); break;
		case MX_ID:
			lvprintf("MX Gadget, %s", mxText[code]); break;
		case ADD_ID:
			lvprintf("ADD button"); break;
		case DEL_ID:
			lvprintf("DEL button"); break;
		case LISTVIEW_ID:
			lvprintf("LISTVIEW Gadget: %s", listText[code]); break;
		case PALETTE_ID:
			PickColor(code); break;
		case RED_ID:
			ModifyColor(code, -1,-1); break;
		case GREEN_ID:
			ModifyColor(-1,code,-1); break;
		case BLUE_ID:
			ModifyColor(-1,-1,code); break;
		case EVENT_ID:
			lvprintf("Event ID shouldn't happen"); break;
		case QUIT_ID:
			Abort();
		case INTEGER_ID:
			val = ((STRINGINFO *)gad->SpecialInfo)->LongInt;
			lvprintf("INTEGER gadget: '%d'", val); 
			GT_SetGadgetAttrs(gadgetArray[NUMBER_ID], window, NULL, GTNM_Number, val, TAG_DONE);
			break;
		case NUMBER_ID:
			lvprintf("NUMBER Gadget: code=%x", code); break;
		case STRING_ID:
			lvprintf("STRING gadget: '%s'", ((STRINGINFO *)gad->SpecialInfo)->Buffer); break;
		default:
			lvprintf("ProcessGadget - something wierd"); break;
	}
}

/*
 * void	GadgetUp(m);
 * IMSG	*m;		ptr to IntuiMessage received
 *
 * Synopsis:
 *	Handles Gadtools/Intuition GADGETUP events.  For 2.0 and GadTools, the TAB and HELP
 *	keys are special.  This routine handles these events, also.
 *
 * NOTES:
 *	STRINGA_ExitHelp is not defined in any of the headers I got with SAS 5.10a, so the
 *	HELP feature doesn't work.
 */
void	GadgetUp(IMSG *m) {
	GADGET	*gad = (GADGET *)m->IAddress;

	if (m->Code == 0x09) {
		lvprintf("GadgetUp: Tab key pressed");
	}
	if (m->Code == 0x5f) {
		lvprintf("GadgetUp: Help Key pressed");
	}
	else {
		ProcessGadget(gad->GadgetID, m->Code);
	}
}

/*
 * void	GadgetDown(m);
 * IMSG	*m;		ptr to IntuiMessage received
 *
 * Synopsis:
 *	Handles Gadtools/Intuition GADGETDOWN events.
 */
void	GadgetDown(IMSG *m) {
	GADGET	*gad = (GADGET *)m->IAddress;

	ProcessGadget(gad->GadgetID, m->Code);
}

/*
 * void	MouseMove(m);
 * IMSG	*m;		ptr to IntuiMessage received
 *
 * Synopsis:
 *	Handles Gadtools/Intuition MOUSEMOVE events.
 */
void	MouseMove(IMSG *m) {
	GADGET	*gad = (GADGET *)m->IAddress;

	ProcessGadget(gad->GadgetID, m->Code);
}

/************************************************************************/

/*
 * The main program.  Simply an event handler loop with minimal initialization
 * and cleanup.
 */
void	main(void) {
	IMSG	*m, msg;
	BOOL	done = 0;

	Init();
	PickColor(0);
	while (!done) {
		WaitPort (window->UserPort);
		while (m = GT_GetIMsg(window->UserPort)) {
			msg = *m;
			GT_ReplyIMsg(m);

			switch (msg.Class) {
				case IDCMP_INTUITICKS:
					break;

				case IDCMP_GADGETUP:
					GadgetUp(&msg);
					break;

				case IDCMP_GADGETDOWN:
					GadgetDown(&msg);
					break;

				case IDCMP_MOUSEMOVE:
					MouseMove(&msg);
					break;

				case IDCMP_REFRESHWINDOW:
					lvprintf("REFRESHWINDOW");
					GT_BeginRefresh(window);
					GT_EndRefresh(window, TRUE);
					break;

				case IDCMP_RAWKEY:
					if (msg.Code & 0x80) break;
					lvprintf("RAWKEY Class = %x Code = %x", msg.Class, msg.Code);
					break;

				case IDCMP_VANILLAKEY:
					lvprintf("VANILLAKEY Class = %x Code = %x", msg.Class, msg.Code);
					break;

				case IDCMP_MOUSEBUTTONS:
					if (msg.Code == MENUUP || msg.Code == SELECTUP) break;
					lvprintf("MouseButtons Code = %x, x,y = %d,%d", msg.Code, msg.MouseX, msg.MouseY);
					break;

				default:
					lvprintf("Class = %x Code = %x", msg.Class, msg.Code);
					break;
			}
		}
	}
	Abort();
}


@
