/* gadtoolsgadgets.c
** Simple example of using a number of gadtools gadgets.
**
** Here's a working example showing how to set up and use a linked list
** of GadTools gadgets complete with keyboard shortcuts.
**
** Compiled with SAS C v5.10a
** lc -b1 -cfistq -v -y gadtoolsgadgets
** blink FROM LIB:c.o gadtoolsgadgets.o TO gadtoolsgadgets LIB LIB:lc.lib LIB:amiga.lib
*/
#define INTUI_V36_NAMES_ONLY
#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/gadtools_protos.h>
#include <stdio.h>
#ifdef LATTICE
int CXBRK(void) { return(0); } /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); } /* really */
#endif
/* Gadget defines of our choosing, to be used as GadgetID's,
** also used as the index into the gadget array my_gads[].
*/
#define MYGAD_SLIDER (0)
#define MYGAD_STRING1 (1)
#define MYGAD_STRING2 (2)
#define MYGAD_STRING3 (3)
#define MYGAD_BUTTON (4)
/* Range for the slider: */
#define SLIDER_MIN (1)
#define SLIDER_MAX (20)
struct TextAttr Topaz80 = { "topaz.font", 8, 0, 0, };
struct Library *IntuitionBase;
struct Library *GfxBase;
struct Library *GadToolsBase;
/* Print any error message. We could do more fancy handling (like
** an EasyRequest()), but this is only a demo.
*/
void errorMessage(STRPTR error)
{
if (error)
printf("Error: %s\n", error);
}
/*
** Function to handle a GADGETUP or GADGETDOWN event. For GadTools gadgets,
** it is possible to use this function to handle MOUSEMOVEs as well, with
** little or no work.
*/
VOID handleGadgetEvent(struct Window *win, struct Gadget *gad, UWORD code,
WORD *slider_level, struct Gadget *my_gads[])
{
switch (gad->GadgetID)
{
case MYGAD_SLIDER:
/* Sliders report their level in the IntuiMessage Code field: */
printf("Slider at level %ld\n", code);
*slider_level = code;
break;
case MYGAD_STRING1:
/* String gadgets report GADGETUP's */
printf("String gadget 1: '%s'.\n",
((struct StringInfo *)gad->SpecialInfo)->Buffer);
break;
case MYGAD_STRING2:
/* String gadgets report GADGETUP's */
printf("String gadget 2: '%s'.\n",
((struct StringInfo *)gad->SpecialInfo)->Buffer);
break;
case MYGAD_STRING3:
/* String gadgets report GADGETUP's */
printf("String gadget 3: '%s'.\n",
((struct StringInfo *)gad->SpecialInfo)->Buffer);
break;
case MYGAD_BUTTON:
/* Buttons report GADGETUP's (button resets slider to 10) */
printf("Button was pressed, slider reset to 10.\n");
*slider_level = 10;
GT_SetGadgetAttrs(my_gads[MYGAD_SLIDER], win, NULL,
GTSL_Level, *slider_level,
TAG_END);
break;
}
}
/*
** Function to handle vanilla keys.
*/
VOID handleVanillaKey(struct Window *win, UWORD code,
WORD *slider_level, struct Gadget *my_gads[])
{
switch (code)
{
case 'v':
/* increase slider level, but not past maximum */
if (++*slider_level > SLIDER_MAX)
*slider_level = SLIDER_MAX;
GT_SetGadgetAttrs(my_gads[MYGAD_SLIDER], win, NULL,
GTSL_Level, *slider_level,
TAG_END);
break;
case 'V':
/* decrease slider level, but not past minimum */
if (--*slider_level < SLIDER_MIN)
*slider_level = SLIDER_MIN;
GT_SetGadgetAttrs(my_gads[MYGAD_SLIDER], win, NULL,
GTSL_Level, *slider_level,
TAG_END);
break;
case 'c':
case 'C':
/* button resets slider to 10 */
*slider_level = 10;
GT_SetGadgetAttrs(my_gads[MYGAD_SLIDER], win, NULL,
GTSL_Level, *slider_level,
TAG_END);
break;
case 'f':
case 'F':
ActivateGadget(my_gads[MYGAD_STRING1], win, NULL);
break;
case 's':
case 'S':
ActivateGadget(my_gads[MYGAD_STRING2], win, NULL);
break;
case 't':
case 'T':
ActivateGadget(my_gads[MYGAD_STRING3], win, NULL);
break;
}
}
/*
** Here is where all the initialization and creation of GadTools 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(struct Gadget **glistptr, void *vi,
UWORD topborder, WORD slider_level, struct Gadget *my_gads[])
{
struct NewGadget ng;
struct Gadget *gad;
/* All the gadget creation calls accept a pointer to the previous gadget, and
** link the new gadget to that gadget's NextGadget field. Also, they exit
** gracefully, returning NULL, if any previous gadget was NULL. This limits
** the amount of checking for failure that is needed. You only need to check
** before you tweak any gadget structure or use any of its fields, and finally
** once at the end, before you add the gadgets.
*/
/* The following operation is required of any program that uses GadTools.
** It gives the toolkit a place to stuff context data.
*/
gad = CreateContext(glistptr);
/* Since the NewGadget structure is unmodified by any of the CreateGadget()
** calls, we need only change those fields which are different.
*/
ng.ng_LeftEdge = 140;
ng.ng_TopEdge = 20+topborder;
ng.ng_Width = 200;
ng.ng_Height = 12;
ng.ng_GadgetText = "_Volume: ";
ng.ng_TextAttr = &Topaz80;
ng.ng_VisualInfo = vi;
ng.ng_GadgetID = MYGAD_SLIDER;
ng.ng_Flags = NG_HIGHLABEL;
my_gads[MYGAD_SLIDER] = gad = CreateGadget(SLIDER_KIND, gad, &ng,
GTSL_Min, SLIDER_MIN,
GTSL_Max, SLIDER_MAX,
GTSL_Level, slider_level,
GTSL_LevelFormat, "%2ld",
GTSL_MaxLevelLen, 2,
GT_Underscore, '_',
TAG_END);
ng.ng_TopEdge += 20;
ng.ng_Height = 14;
ng.ng_GadgetText = "_First:";
ng.ng_GadgetID = MYGAD_STRING1;
my_gads[MYGAD_STRING1] = gad = CreateGadget(STRING_KIND, gad, &ng,
GTST_String, "Try pressing",
GTST_MaxChars, 50,
GT_Underscore, '_',
TAG_END);
ng.ng_TopEdge += 20;
ng.ng_GadgetText = "_Second:";
ng.ng_GadgetID = MYGAD_STRING2;
my_gads[MYGAD_STRING2] = gad = CreateGadget(STRING_KIND, gad, &ng,
GTST_String, "TAB or Shift-TAB",
GTST_MaxChars, 50,
GT_Underscore, '_',
TAG_END);
ng.ng_TopEdge += 20;
ng.ng_GadgetText = "_Third:";
ng.ng_GadgetID = MYGAD_STRING3;
my_gads[MYGAD_STRING3] = gad = CreateGadget(STRING_KIND, gad, &ng,
GTST_String, "To see what happens!",
GTST_MaxChars, 50,
GT_Underscore, '_',
TAG_END);
ng.ng_LeftEdge += 50;
ng.ng_TopEdge += 20;
ng.ng_Width = 100;
ng.ng_Height = 12;
ng.ng_GadgetText = "_Click Here";
ng.ng_GadgetID = MYGAD_BUTTON;
ng.ng_Flags = 0;
gad = CreateGadget(BUTTON_KIND, gad, &ng,
GT_Underscore, '_',
TAG_END);
return(gad);
}
/*
** Standard message handling loop with GadTools message handling functions
** used (GT_GetIMsg() and GT_ReplyIMsg()).
*/
VOID process_window_events(struct Window *mywin,
WORD *slider_level, struct Gadget *my_gads[])
{
struct IntuiMessage *imsg;
ULONG imsgClass;
UWORD imsgCode;
struct Gadget *gad;
BOOL terminated = FALSE;
while (!terminated)
{
Wait (1 << mywin->UserPort->mp_SigBit);
/* GT_GetIMsg() returns an IntuiMessage with more friendly information for
** complex gadget classes. Use it wherever you get IntuiMessages where
** using GadTools gadgets.
*/
while ((!terminated) &&
(imsg = GT_GetIMsg(mywin->UserPort)))
{
/* Presuming a gadget, of course, but no harm...
** Only dereference this value (gad) where the Class specifies
** that it is a gadget event.
*/
gad = (struct Gadget *)imsg->IAddress;
imsgClass = imsg->Class;
imsgCode = imsg->Code;
/* Use the toolkit message-replying function here... */
GT_ReplyIMsg(imsg);
switch (imsgClass)
{
/* --- WARNING --- WARNING --- WARNING --- WARNING --- WARNING ---
** GadTools puts the gadget address into IAddress of IDCMP_MOUSEMOVE
** messages. This is NOT true for standard Intuition messages,
** but is an added feature of GadTools.
*/
case IDCMP_GADGETDOWN:
case IDCMP_MOUSEMOVE:
case IDCMP_GADGETUP:
handleGadgetEvent(mywin, gad, imsgCode, slider_level, my_gads);
break;
case IDCMP_VANILLAKEY:
handleVanillaKey(mywin, imsgCode, slider_level, my_gads);
break;
case IDCMP_CLOSEWINDOW:
terminated = TRUE;
break;
case IDCMP_REFRESHWINDOW:
/* With GadTools, the application must use GT_BeginRefresh()
** where it would normally have used BeginRefresh()
*/
GT_BeginRefresh(mywin);
GT_EndRefresh(mywin, TRUE);
break;
}
}
}
}
/*
** Prepare for using GadTools, set up gadgets and open window.
** Clean up and when done or on error.
*/
VOID gadtoolsWindow(VOID)
{
struct TextFont *font;
struct Screen *mysc;
struct Window *mywin;
struct Gadget *glist, *my_gads[4];
void *vi;
WORD slider_level = 5;
UWORD topborder;
/* Open topaz 8 font, so we can be sure it's openable
** when we later set ng_TextAttr to &Topaz80:
*/
if (NULL == (font = OpenFont(&Topaz80)))
errorMessage( "Failed to open Topaz 80");
else
{
if (NULL == (mysc = LockPubScreen(NULL)))
errorMessage( "Couldn't lock default public screen");
else
{
if (NULL == (vi = GetVisualInfo(mysc, TAG_END)))
errorMessage( "GetVisualInfo() failed");
else
{
/* Here is how we can figure out ahead of time how tall the */
/* window's title bar will be: */
topborder = mysc->WBorTop + (mysc->Font->ta_YSize + 1);
if (NULL == createAllGadgets(&glist, vi, topborder,
slider_level, my_gads))
errorMessage( "createAllGadgets() failed");
else
{
if (NULL == (mywin = OpenWindowTags(NULL,
WA_Title, "GadTools Gadget Demo",
WA_Gadgets, glist, WA_AutoAdjust, TRUE,
WA_Width, 400, WA_MinWidth, 50,
WA_InnerHeight, 140, WA_MinHeight, 50,
WA_DragBar, TRUE, WA_DepthGadget, TRUE,
WA_Activate, TRUE, WA_CloseGadget, TRUE,
WA_SizeGadget, TRUE, WA_SimpleRefresh, TRUE,
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW |
IDCMP_VANILLAKEY | SLIDERIDCMP | STRINGIDCMP |
BUTTONIDCMP,
WA_PubScreen, mysc,
TAG_END)))
errorMessage( "OpenWindow() failed");
else
{
/* After window is open, gadgets must be refreshed with a
** call to the GadTools refresh window function.
*/
GT_RefreshWindow(mywin, NULL);
process_window_events(mywin, &slider_level, my_gads);
CloseWindow(mywin);
}
}
/* FreeGadgets() even if createAllGadgets() fails, as some
** of the gadgets may have been created...If glist is NULL
** then FreeGadgets() will do nothing.
*/
FreeGadgets(glist);
FreeVisualInfo(vi);
}
UnlockPubScreen(NULL, mysc);
}
CloseFont(font);
}
}
/*
** Open all libraries and run. Clean up when finished or on error..
*/
void main(void)
{
if (NULL == (IntuitionBase = OpenLibrary("intuition.library", 37)))
errorMessage( "Requires V37 intuition.library");
else
{
if (NULL == (GfxBase = OpenLibrary("graphics.library", 37)))
errorMessage( "Requires V37 graphics.library");
else
{
if (NULL == (GadToolsBase = OpenLibrary("gadtools.library", 37)))
errorMessage( "Requires V37 gadtools.library");
else
{
gadtoolsWindow();
CloseLibrary(GadToolsBase);
}
CloseLibrary(GfxBase);
}
CloseLibrary(IntuitionBase);
}
}