
#include <graphics/gfxmacros.h>
#include <proto/graphics.h>
#include <proto/gadtools.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/utility.h>
#include <proto/asl.h>
#include <intuition/icclass.h>
#include <intuition/imageclass.h>
#include <stdlib.h>
#include <string.h>

#ifndef LINKLIB
    #include "proto/gadoutline.h"
#else
    #include "libraries/gadoutline.h"
    #include "interface.h"
#endif

#include "support/debug.h"

#define CATCOMP_BLOCK 1
#define CATCOMP_NUMBERS 1
#include "gadout_examples.h"

#include "support/rkmmodel.h"

#define NOISY 0

/*********************************************
 **
 ** Main window outline support data
 **
 *********************************************/

// This is a list of IDs to assign to each command (gadget) in the outline.
// Because almost all references to the outline are made through IDs rather
// than pointers, you will need to assign IDs to most commands, including
// any command that has a hotkey attached.  (Hotkeys are stored internally
// as just the ID number of the command that a hotkey is attached to, so
// if it doesn't have a number the library is unable to find the command
// to send an CHM_HOTKEY message to it.)

// These "standard" ID codes can range from 1 to 4095; the value of 0 means
// "no ID code," and the upper 20 bits of the ID are used for storing
// "group" ID codes.  Every command which is given a non-zero standard ID
// must be the only command in the outline with that ID; the library will
// report an error if it finds more than one command with the same ID.

enum {

    LISTVIEW_ID = 1,
    LVEDIT_ID,
    PALETTE_ID,
    CYCLE_ID,
    BUTTON_ID,
    SLIDER_ID,
    CHECKBOX_ID,
    
    BASICPROP_ID,
    BASICINT_ID,
    
    RIGHTIM_ID,
    LEFTIM_ID,
    INTFRAME_ID,
    RKMMODEL_ID,
    VAL2INT_ID,
    VAL2PROP_ID,
    PROP_ID,
    INTEGER_ID,
    LEFT_ID,
    RIGHT_ID,
    
    PROPKNOB_ID,
    DRAWPROP_ID,
    DRAWINT_ID,
    
    JUMPWIN_ID,
    REQFONT_ID,
    ICONIFY_ID,
    WINVALUES_ID,
    OUTVALUES_ID,
    
    KEYSHOW_ID
    
};

// This tag list is located outside of the outline because
// it is fairly long [and this makes a nice example :)].  However,
// when the GadOutline structure is created, space is reserved
// to track these tags just like the tags directly included
// in the outline.

struct TagItem slider_obj_tags[] =
{
    { GA_RelVerify, TRUE },
    { GA_Immediate, TRUE },
    { PGA_FREEDOM, LORIENT_HORIZ },
    { GTSL_Min, 0 },
    { GTSL_Max, 15 },
    { GTSL_Level, 0 },
    { GTSL_LevelFormat, MSG_EX1_SLIDER_FMT },
    { GTSL_LevelPlace, PLACETEXT_RIGHT },
    { GTSL_MaxLevelLen, 2 },
    { TAG_END, 0 }
};

// Now, the drawing tags which all the icons start with:

static ULONG IconInitDraw[] = {
    GODT_FillRect, GO_SCLPNT(BACKGROUNDPEN,0,0,63,63),
    GODT_DrawStdFrame, GO_SCLPNT(SHINEPEN,0,0,63,63),
    GODT_SetRightBound, GO_TSIZE(GOM_Add,-200,GOT_PercStdFrmW),
    GODT_SetBottomBound, GO_TSIZE(GOM_Add,-200,GOT_PercStdFrmH),
    GODT_SetLeftBound, GO_TSIZE(GOM_Add,200,GOT_PercStdFrmW),
    GODT_SetTopBound, GO_TSIZE(GOM_Add,200,GOT_PercStdFrmH),
    TAG_END
};

// And one for BOOPSI-style thin icons:
static ULONG ThinIconInitDraw[] = {
    GODT_MapHighPen, GO_MAPPEN(FILLPEN,FILLPEN),
    GODT_FillRect, GO_SCLPNT(FILLPEN,0,0,63,63),
    GODT_DrawLine, GO_SCLPNT(SHINEPEN,0,0,0,63),
    GODT_DrawLine, GO_SCLPNT(SHADOWPEN,0,63,63,63),
    GODT_DrawLine, GO_SCLPNT(SHADOWPEN,63,0,63,63),
    GODT_DrawLine, GO_SCLPNT(SHINEPEN,0,0,63,0),
    GODT_MapHighPen, GO_MAPPEN(FILLPEN,BACKGROUNDPEN),
    GODT_SetRightBound, GO_TSIZE(GOM_Add,-2,GOT_Pixels),
    GODT_SetBottomBound, GO_TSIZE(GOM_Add,-2,GOT_Pixels),
    GODT_SetLeftBound, GO_TSIZE(GOM_Add,2,GOT_Pixels),
    GODT_SetTopBound, GO_TSIZE(GOM_Add,2,GOT_Pixels),
    TAG_END
};

// And these are the control tags to tell what size
// an icon should be.

static ULONG SmallIconControl[] = {
    GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdSet,400,GOT_PercStdFrmW),
    GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdAdd,200,GOT_PercChar0),
    GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdSet,400,GOT_PercStdFrmH),
    GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdAdd,100,GOT_PercCharH),
    TAG_END
};

// Similarily, for the thin icon.
static ULONG ThinIconControl[] = {
    GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdAdd,200,GOT_PercChar0),
    GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdAdd,125,GOT_PercCharH),
    GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdMax,12,GOT_Pixels),
    GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdMax,8,GOT_Pixels),
    TAG_END
};

// These are the translation tables for a simple prop<=>int interconnection.
struct TagItem prop2intmap[] =
{
    {PGA_Top,   STRINGA_LongVal},
    {TAG_END,}
};
struct TagItem int2propmap[] =
{
    {STRINGA_LongVal,   PGA_Top},
    {TAG_END,}
};


// These are various translation tables used to implement the
// RKMModel demonstration, taken directly from userkmmodel.c.

static struct TagItem go2rkmmodel[] = {
    {PGA_Top, RKMMOD_CurrVal},
    {STRINGA_LongVal, RKMMOD_CurrVal},
    {TAG_END,}
};

static struct TagItem right2rkmmodel[] = {
    {GA_ID, RKMMOD_Up},
    {TAG_END,}
};

static struct TagItem left2rkmmodel[] = {
    {GA_ID, RKMMOD_Down},
    {TAG_END,}
};

static struct TagItem mapcurrval2prop[] = {
    {RKMMOD_CurrVal, PGA_Top},
    {TAG_END,}
};

static struct TagItem mapcurrval2int[] = {
    {RKMMOD_CurrVal, STRINGA_LongVal},
    {TAG_END,}
};

#define VISIBLE             10L
#define TOTAL               100L
#define INITIALVAL          25L

#define STRING_LEN 100

/*********************************************
 **
 ** Main window gadget outline
 **
 *********************************************/

// This is the main outline structure.  It is simply an array of ULONGs,
// organized as a series of commands.  Each command may have up to 8
// parameters and 3 tag lists, although currently the library only
// does something with the first two tag lists.  The first tag list
// is always a list of outline commands (GOCT_*) used to control the
// command - see the header file for information on these.  The
// interpretation of the second tag list depends on the command type --
// It may be a list of GadTools tags, Window tags, Screen tags, GOCT_
// tags to add to the command tag list of following commands, etc.

// When the outline is created, all of the supplied parameters and tag
// lists are copied and used to track the state of the gadgets.  Because
// only the state of tags directly supplied to the outline are tracked,
// you will need to make sure you include GTST_String, GTCY_Active,
// GTCY_Labels, etc., even if you do not set them until the gadgets have
// been created.  If these are not included, during a resize and other
// times that the gadgets need to be rebuilt, they will revert to their
// default values.

// NOTE!!!!!  _ALL_ tag lists in the outline MUST end with a TAG_END.
// The library does not consider a TAG_MORE, or anything else, a list
// terminator.  So when you use TAG_MORE, it will look like this:
//
// ..., TAG_MORE, (ULONG)&more_tags, TAG_END, NEW_COMMAND(), ...

static ULONG outline[] = {

// Default GadOutline GOA_ type tags.  These tags are immediately parsed
// when this command is encountered just as if they were passed to
// AllocGadOutline().

GO_OUTLINETAGS(0,0),

    TAG_END,                        // 1st tag list -- no command tags.
    GOA_FontMinSize,    2,          // 2nd tag list -- new outline tags.
    GOA_WindowResize,   TRUE,
    GOA_LocaleStrBlock, (ULONG)&CatCompBlock[0],
    GOA_CatalogName,    (ULONG)&"gadout_examples.catalog",
    GOA_HighButtons,    TRUE,
    TAG_END,

// Default window tags.  These are supplied as defaults when GO_OpenWindow()
// is called; they will be overridden by any tags passed directly to the
// function call.  Only include this command once.

GO_WINDOWTAGS(0,0),

    TAG_END,                        // 1st tag list -- no command tags.
    WA_Title,           MSG_EX1_TITLE_TXT,
    WA_IDCMP,           IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW | IDCMP_NEWSIZE |
                        IDCMP_GADGETHELP,
    WA_Zoom,            ~0,
    WA_NewLookMenus,    TRUE,
    WA_Activate,        TRUE,
    WA_CloseGadget,     TRUE,
    WA_DepthGadget,     TRUE,
    WA_DragBar,         TRUE,
    WA_SizeGadget,      TRUE,
    WA_SizeBBottom,     TRUE,
    WA_ReportMouse,     TRUE,
    WA_SimpleRefresh,   TRUE,
    TAG_END,

// Global command tags -- Added to the first tag list (command list)
// of every command which follows this and matches the command's ID.
// Since the command ID is 0, this will simply match every command.
// Space will be allocated to track their state just as if they were
// directly supplied to the command.

GO_COMMANDTAGS(0,0),

    TAG_END,
    GOCT_SetHotKey, 0,      // Automatically set hot key code
    GOCT_SetUserHook, 1,    // Set user hook to translation 1
                            // (Computed in translation hook below.)
    TAG_END,

// Global object tags -- Added to the second tag list (object list)
// of every command which follows this and matches its ID.  Since this
// command's GroupID mask is GO_GRPID_L and code is 0, and its StdID is 0,
// this will match every command with the GO_GRPID_L bit set. Space will be
// allocated to track their state just as if they were directly supplied
// to the command.

// Note that the GOA_Underscore global attribute is a much better way to
// automatically set the GT_Underscore tag in each object; this is just
// a way to demonstrate the GO_OBJECTTAGS() command. :)

#define UNDERSCORE_GRP GO_GRPID_L

GO_OBJECTTAGS(UNDERSCORE_GRP,0),

    TAG_END,
    GT_Underscore, '_',     // Add the GadTools underscore tag.
    TAG_END,

// Start the layout.  A layout is organized as a recursive collection
// of "groups."  A group can be either horizontal or vertical, and may
// contain both actual boxes or other groups.

// Initial group.  It has no GrpID and no StdID because we will never
// directly reference it.  The last value, '1', is the "weight" of the
// group.  When multiple boxes and groups are together, their relative
// weights are used to determine how to distribute the space among them.
// In this case, a 1 gives this group all of the weight; since it is the
// root group, this means it gets all the space in the window.
GO_VERTGRP(0,0,1),
// Command tags to set the space around the group.  GOM_PadSet means
// to directly set the amount of padding [padding is space that the
// library is allowed to remove to make a layout fit within its bounds.]
// GOT_PercCharH and GOT_PercCharW are the "type" units - in this case,
// we are asking for 100 Percent of a character height and width.
// These sizing commands are simply executing sequentially by the library,
// allowing you to combine them with different functions [ie, GOM_PadSet
// and then GOM_PadAdd] for more detailed control over the spacing.
GOCT_SizeSpaceAbove, GO_TSIZE(GOM_PadSet,50,GOT_PercCharH),
GOCT_SizeSpaceBelow, GO_TSIZE(GOM_PadSet,50,GOT_PercCharH),
GOCT_SizeSpaceLeft, GO_TSIZE(GOM_PadSet,50,GOT_PercCharW),
GOCT_SizeSpaceRight, GO_TSIZE(GOM_PadSet,50,GOT_PercCharW),
TAG_END,

    /* ----------------------------------------------------------- */
            
    // First we will draw a title at the top of the window.  This involves
    // creating a "DRAWBOX," which is a box that contains GODT_* drawing
    // tags.  GOSD_Normal means this is a standard drawing, rather than
    // a button.  We give this box 0 weight, because we don't want it
    // to get any more spacing than it needs.
    GO_DRAWBOX(GOSD_Normal,0,0,0),
    // These two tags control how much vertical space the body will get.
    // We first set its "standard" space to 1 character height; this is
    // the bare minimum amount of height that this box can have.  We
    // also give it half a character height of padding; this is space
    // which is really nice to have for it to look nice, but the library
    // can get rid of if it needs to try to make the layout fit.
    GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdSet,100,GOT_PercCharH),
    GOCT_SizeBodyHeight, GO_TSIZE(GOM_PadSet,50,GOT_PercCharH),
    TAG_END,
    // Finally, we draw the text.  This looks complicated, but it is
    // fairly straight-forward.  Drawing tags are simply sequentially
    // executed commands use to render onto the window, and control
    // how the rendering should be performed.
    // First, we set the text mode.  "FLGALL" is a special macro used
    // with tags which set flags; these tags can control which bits to
    // set or clear, using "FLGALL," "FLGON," and "FLGOFF."  This tag
    // means to directly set all text mode flags, in this case making
    // it so that text is centered about the X axis, the cursor is left
    // on the right center of the text, and the Y cursor position is
    // relative to the center of the line of text
    GODT_SetTextMode, FLGALL(TXTMD_CENTER | TXTMD_ENDRIGHT | TXTMD_RELCENTER),
    // Next, turn on the BOLD text style.
    GODT_SetTextStyle, FLGON(TXTSTL_BOLD),
    // The "Origin" is a set of two X/Y coordinate pairs, which may be set
    // to a value, and later referenced as offsets.  In this case, it is
    // very useful for drawing 3D text - we can set the origin to the
    // position we want to draw it at, and then draw the shadow one pixel
    // offset from the foreground.
    // GO_SCLPNT is a macro that creates the standard data format for
    // drawing commands.  Its arguments are a standard pen [0 to 15]
    // and two pairs of coordinates, whose values each range from 0 to 63
    // and are interpreted as 'x/63 of the current drawing boundaries.'
    // The default boundaries for a DRAWBOX are simply the box's body,
    // so the point (32,32) will give is the center of the box.
    // Since GODT_SetOrigin doesn't use the pen parameter and we aren't
    // going to use the second X/Y pair, we will set these to 0.
    GODT_SetOrigin, GO_SCLPNT(0,32,32,0,0),
    // We now move one pixel to the left and one pixel below the center
    // point we found above.  GO_PIXPNT is another macro for creating
    // the drawing parameter.  This one takes one of the coordinates
    // previously defined by GODT_SetOrigin and an offset to apply to
    // it; this offset may range from -16 to +15, and may be applied
    // to either the first or second coordinate previously defined
    // by GODT_SetOrigin.
    GODT_MoveTo, GO_PIXPNT(0,PX1(1),PY1(1),0,0),
    // This tag simply set the pen which following text will use.
    GODT_ChooseTextAPen, SHADOWPEN,
    // And then we draw the text.
    GODT_DrawText, MSG_EX1_HEAD_TXT,
    // Next, move back to the exact center point.
    GODT_MoveTo, GO_PIXPNT(0,PX1(0),PY1(0),0,0),
    // And draw the text again, this time using the standard text highlight
    // pen.
    GODT_DrawHighText, MSG_EX1_HEAD_TXT,
    TAG_END,
        
    /* ----------------------------------------------------------- */
            
    // Make a divider bar.
    GO_DRAWBOX(GOSD_Normal,0,0,0),
    // The important thing here is the spacing -- we want to make sure
    // that the body has exactly the amount of space needed by a frame,
    // since our divider bar is simply a standard frame with its top
    // and bottom crunched together so they are touching.  What we do
    // is set set the body width and height large enough to both sides
    // of the frame, and make sure the pad spacing is zero.  The library
    // by default puts any extra space in a box into its body, so the
    // body's width will be stretched across to conform with the rest
    // of the vertical group the box is in.  But since we set this box's
    // weight to 0, the body height will be untouched.
    GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdSet,200,GOT_PercStdFrmW),
    GOCT_SizeBodyWidth, GO_TSIZE(GOM_PadSet,0,GOT_Pixels),
    GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdSet,200,GOT_PercStdFrmH),
    GOCT_SizeBodyHeight, GO_TSIZE(GOM_PadSet,0,GOT_Pixels),
    // We then put some pad spacing in the space areas above and below
    // the box, so things look nice.
    GOCT_SizeSpaceAbove, GO_TSIZE(GOM_PadSet,50,GOT_PercCharH),
    GOCT_SizeSpaceBelow, GO_TSIZE(GOM_PadSet,50,GOT_PercCharH),
    TAG_END,
    // And draw the frame, using the entire body.  The bottom-right side
    // of the frame is draw in the complement of the given pen, so to
    // draw a recessed frame you would just specify a pen of SHADOWPEN.
    GODT_DrawStdFrame, GO_SCLPNT(SHINEPEN,0,0,63,63),
    TAG_END,
    
    /* ----------------------------------------------------------- */
            
    // We now make another drawbox, in which we will supply some
    // additional text.  The main thing to note here is the use of
    // 'GOCT_FmtPtrTag' to determine how large the box should be; this
    // tag is used to get the text from one of the tags in the second
    // list, and use it to set some values which you can later refer
    // to with GO_TSIZE().  In this case, we grab the formatted text
    // which we draw in the body, and use it to determine the width and
    // height which it needs to be contained.
    #if 0
    GO_DRAWBOX(GOSD_Normal,0,0,0),
    GOCT_FmtPtrTag, GODT_DrawStdText,
    GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdMax,100,GOT_PercTextMaxW),
    GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdMax,100,GOT_PercTextMaxH),
    TAG_END,
    GODT_SetTextMode, FLGALL(TXTMD_CENTER | TXTMD_ENDCENTER | TXTMD_RELTOP),
    GODT_MoveTo, GO_SCLPNT(0,32,0,0,0),
    GODT_DrawStdText, MSG_EX1_SUBHEAD_TXT,
    TAG_END,
    #endif
        
    /* ----------------------------------------------------------- */
            
    // Start the main part of the window -- divide into horizontal slices.
    GO_HORIZGRP(0,0,1), TAG_END,

        // Left horizontal slice -- divide into vertical slices.
        GO_VERTGRP(0,0,1), TAG_END,
        
            /* ----------------------------------------------------------- */
            
            // Draw the title text for this section.
            GO_DRAWBOX(GOSD_Normal,0,0,0),
            GOCT_FmtPtrTag, GODT_DrawStdText,
            GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdMax,100,GOT_PercTextMaxW),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdMax,100,GOT_PercTextMaxH),
            TAG_END,
            GODT_SetTextMode, FLGALL(TXTMD_CENTER | TXTMD_ENDCENTER | TXTMD_RELTOP),
            GODT_MoveTo, GO_SCLPNT(0,32,0,0,0),
            GODT_DrawStdText, MSG_EX1_GADTOOLS_TXT,
            TAG_END,
                
            /* ----------------------------------------------------------- */
            
            // Create a GadTools box.  The parameters are, in order,
            // GadTools Kind, GrpID, StdID, Weight, Label, Flags.
            GO_GTBOX(LISTVIEW_KIND, UNDERSCORE_GRP, LISTVIEW_ID, 1,
                MSG_EX1_LISTVIEW_LAB, PLACETEXT_ABOVE|NG_HIGHLABEL),
            // Set the minimum size that the listview's body can be.
            // GOM_StdMax means to set the standard size [the bare
            // minimum size of the box] to the maximum of its current
            // value and the new value being supplied.
            GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdMax,500,GOT_PercCharW),
            //GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdMax,300,GOT_PercCharH),
            // Link this object to another.  These tags tells the library
            // to point the GTLV_ShowSelected tag in this command's
            // second/object/GadTools taglist to the object created
            // by the INFOEDIT_ID command.  This object's creation will
            // be deferred until the object it is linked to has been
            // created; if that object is never created, this one won't
            // be either.
            GOCT_LinkFromTag, GTLV_ShowSelected,
            GOCT_LinkToStdID, LVEDIT_ID,
            // Point hotkey events to the INFOEDIT_ID command.  The
            // standard GadTools hook automatically sets the command's
            // hotkey by examining its label text; this allows us to
            // keep that automatic hotkey while making the hotkey
            // actually refer to a different command.
            GOCT_SetHotKeyCmd, LVEDIT_ID,
            TAG_END,
            // Start of the second - GadTools - taglist.  These are the
            // tags which will be tracked by the library.
            GTLV_Selected, ~0,
            GTLV_Labels, NULL,
            GTLV_ShowSelected, NULL,
            GTLV_Top, NULL,
            TAG_END,

            /* ----------------------------------------------------------- */
            
            // Create a string gadget.  This is the gadget that the
            // previous ListView has a TagLink to.
            GO_GTBOX(STRING_KIND, UNDERSCORE_GRP, LVEDIT_ID, 0, NULL, 0),
            // Tell the library to ignore this box's dimensions
            // when computing both the minimum size of the layout
            // and the final position of all the boxes.  We need to do
            // this because this gadget is attached to the listview,
            // so its dimensions are taken into account there.
            GOCT_IgnoreMinDimens, TRUE, GOCT_IgnoreFinDimens, TRUE,
            TAG_END,
            // Set GadTools tags.  The standard hook looks for
            // GTST_MaxChars and allocates a buffer of that size to track
            // the string gadget's value.  It currently does _NOT_ change
            // the size of this buffer to match a change in this tag,
            // so make sure you leave plenty of room here.
            GTST_MaxChars, STRING_LEN,
            GTST_String, MSG_EX1_EMPTY_STR,
            TAG_END,

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

            GO_GTBOX(PALETTE_KIND, UNDERSCORE_GRP, PALETTE_ID, 0,
                MSG_EX1_PALETTE_LAB, NG_HIGHLABEL|PLACETEXT_ABOVE),
            // Set up an initial value for the indicator.
            GOCT_CopyFromTSize, GO_TSIZE(GOM_Set,15,GOT_Pixels),
            GOCT_CopyTSizeToTag, GTPA_IndicatorHeight,
            // Adjust the body's width and height a bit
            GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdMax,500,GOT_PercCharW),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdMax,200,GOT_PercCharH),
            // Compute a nice size for the palette's indicator.
            GOCT_SizeUser1, GO_TSIZE(GOM_VarSet,20,GOT_PercBodyH),
            GOCT_SizeUser1, GO_TSIZE(GOM_VarMin,250,GOT_PercCharH),
            GOCT_SizeUser1, GO_TSIZE(GOM_VarMax,6,GOT_Pixels),
            // Copy value in User1 to GTPA_IndicatorHeight tag.
            GOCT_CopyUser1ToTag, GTPA_IndicatorHeight,
            TAG_END,
            GTPA_IndicatorHeight, 15,
            GTPA_Color, 0,
            GTPA_Depth, 2,
            TAG_END,

            // Add another vertical group inside the current one.  We are
            // going to do something a bit different with this one...
            GO_VERTGRP(0,0,0),
            // This tag tells the library to exactly align all of the box's
            // label areas, space areas and bodies.
            GOCT_FitToGroup, TRUE,
            TAG_END,
        
                /* ----------------------------------------------------------- */
            
                GO_GTBOX(CYCLE_KIND, UNDERSCORE_GRP, CYCLE_ID, 0,
                    MSG_EX1_CYCLE_LAB, PLACETEXT_LEFT|NG_HIGHLABEL),
                #if 0
                // The CYCLE_KIND minimum dimension hook is now implemented. :)
                // But we will leave this here; these are the commands which
                // can be used to compute the size needed by a cycle gadget.
                //
                // Set up information about the array of strings supplied
                // in the tag "GTCY_Labels" in the second tag list.
                GOCT_TextArrayTag, GTCY_Labels,
                // Set user variable 1 to the maximum width of all of these
                // strings.
                GOCT_SizeUser1, GO_TSIZE(GOM_StdSet,100,GOT_PercTextMaxW),
                // Add 4 pixels to the value in User1.
                GOCT_SizeUser1, GO_TSIZE(GOM_StdAdd,4,GOT_Pixels),
                // Set the body width to the maximum of its current value
                // and the Std value in User1.
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdMax,100,GOT_PercMdUser1),
                // Add 20 pixels for the cycle imagery.  We have now supplied
                // all of the information needed to determine the minimum
                // size of this gadget.  We had to go to all of this work
                // because the library's standard gadtools hook for cycle
                // gadget wasn't finished yet...  But this makes a nice
                // example, anyway... ;)
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdAdd,20,GOT_Pixels),
                #endif
                TAG_END,
                GTCY_Labels, MSG_EX1_CYCLE_GAD,
                GTCY_Active, 0,
                TAG_END,

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

                GO_GTBOX(BUTTON_KIND, UNDERSCORE_GRP, BUTTON_ID, 0,
                    MSG_EX1_BUTTON_LAB, PLACETEXT_IN),
                TAG_END,
                // We need to track the gadget's disabled state.
                GA_Disabled, FALSE,
                TAG_END,
                
                /* ----------------------------------------------------------- */

                GO_GTBOX(SLIDER_KIND, UNDERSCORE_GRP, SLIDER_ID, 1,
                    MSG_EX1_SLIDER_LAB, NG_HIGHLABEL|PLACETEXT_LEFT),
                TAG_END,
                // Include all of the previously declared tags; these will
                // be tracked just as if they appeared right in the outline.
                TAG_MORE, (ULONG)&slider_obj_tags,
                TAG_END,

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

                GO_GTBOX(CHECKBOX_KIND, UNDERSCORE_GRP, CHECKBOX_ID, 0,
                    MSG_EX1_CHECKBOX_LAB, NG_HIGHLABEL|PLACETEXT_LEFT),
                TAG_END,
                GTCB_Checked, TRUE,
                TAG_END,
    
            GO_ENDGRP(),

        GO_ENDGRP(),

        GO_DRAWBOX(GOSD_Normal,0,0,0),
        GOCT_SizeSpaceLeft, GO_TSIZE(GOM_PadSet,50,GOT_PercCharW),
        GOCT_SizeSpaceRight, GO_TSIZE(GOM_PadSet,50,GOT_PercCharW),
        GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdSet,4,GOT_Pixels),
        GOCT_SizeBodyWidth, GO_TSIZE(GOM_PadSet,0,GOT_Pixels),
        GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdSet,2,GOT_Pixels),
        GOCT_SizeBodyHeight, GO_TSIZE(GOM_PadSet,0,GOT_Pixels),
        TAG_END,
        GODT_DrawStdFrame, GO_SCLPNT(SHINEPEN,0,0,63,63),
        TAG_END,
    
        GO_VERTGRP(0,0,1), TAG_END,
        
            // Draw the title text for this section.
            GO_DRAWBOX(GOSD_Normal,0,0,0),
            GOCT_FmtPtrTag, GODT_DrawStdText,
            GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdMax,100,GOT_PercTextMaxW),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdMax,100,GOT_PercTextMaxH),
            TAG_END,
            GODT_SetTextMode, FLGALL(TXTMD_CENTER | TXTMD_ENDCENTER | TXTMD_RELTOP),
            GODT_MoveTo, GO_SCLPNT(0,32,0,0,0),
            GODT_DrawStdText, MSG_EX1_BOOPSI_TXT,
            TAG_END,
            
            GO_EMPTYBOX(0,0,1),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_PadSet,5,GOT_PercCharH),
            TAG_END,
            
            /* ----------------------------------------------------------- */
            /* Basic BOOPSI example.                                       */
            /* This example creates a prop gadget connected to an integer  */
            /* Gadget.  To do this, we make two BOOPSI gadgets of the      */
            /* appropriate type and connect them to each other through     */
            /* ICA_MAP and ICA_TARGET.                                     */
            /* ----------------------------------------------------------- */
            
            GO_HORIZGRP(0,0,0), TAG_END,
            
                // Here we create a BOOPSI gadget.  The first argument is
                // the type of object - in this case, GOSB_AddGad says we
                // are creating a BOOPSI gadget which should be attached to
                // the window.  Next come the standard GrID, StdID and weight.
                // The last two arguments are the class - the first is a class
                // name and the second a class address.  These are sent
                // directly to NewObject().
                GO_BOOPSIBOX(GOSB_AddGad,0,BASICPROP_ID,1,(ULONG)&"propgclass",NULL),
                GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdSet,100,GOT_PercCharH),
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdSet,400,GOT_PercCharW),
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdMax,20,GOT_Pixels),
                GOCT_SizeSpaceRight, GO_TSIZE(GOM_AllSet,0,GOT_Pixels),
                // A "LateLink" is a connection formed between two objects
                // after they are created; it is done by sending low-level
                // messages after the gadget creation cycle is completely
                // finished.  To form the ICA maps, we need to use LateLinks
                // since the objects point to each other -- there is not
                // an order the library can construct the objects in which
                // can be done at build-time.
                GOCT_LateFromTag, ICA_TARGET,
                GOCT_LateToStdID, BASICINT_ID,
                TAG_END,
                ICA_MAP, (ULONG)&prop2intmap[0],
                ICA_TARGET, NULL,
                PGA_Freedom, FREEHORIZ,
                PGA_Total, TOTAL,
                PGA_Top, INITIALVAL,
                PGA_Visible, VISIBLE,
                PGA_NewLook, TRUE,
                TAG_END,
    
                // This is one way to do an integer gadget with a frame --
                // create a horizontal drawing group which draws the frame,
                // and put a borderless int gadget inside the group.

                GO_HDRAWGRP(0,0,0),
                GOCT_FitToGroup, TRUE,
                GOCT_SizeTextLeft, GO_TSIZE(GOM_StdSet,200,GOT_PercStdFrmW),
                GOCT_SizeTextAbove, GO_TSIZE(GOM_StdSet,200,GOT_PercStdFrmH),
                GOCT_SizeTextRight, GO_TSIZE(GOM_StdSet,200,GOT_PercStdFrmW),
                GOCT_SizeTextBelow, GO_TSIZE(GOM_StdSet,200,GOT_PercStdFrmH),
                TAG_END,
                GODT_ResetBounds, GO_FRMBOUNDS(2,2,2,2, 4,4,4,4),
                GODT_DrawStdFrame, GO_SCLPNT(SHINEPEN,0,0,63,63),
                TAG_END,
                
                    GO_BOOPSIBOX(GOSB_AddGad,0,BASICINT_ID,0,(ULONG)&"strgclass",NULL),
                    GOCT_SizeSpaceLeft, GO_TSIZE(GOM_AllSet,0,GOT_Pixels),
                    GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdSet,100,GOT_PercCharH),
                    GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdSet,300,GOT_PercChar0),
                    //GOCT_LinkFromTag, GA_Image,
                    //GOCT_LateToStdID, BASICPROP_ID,
                    GOCT_LateFromTag, ICA_TARGET,
                    GOCT_LateToStdID, BASICPROP_ID,
                    GOCT_CopyTextAttr, STRINGA_Font,
                    TAG_END,
                    ICA_MAP, (ULONG)&int2propmap[0],
                    ICA_TARGET, NULL,
                    STRINGA_LongVal, INITIALVAL,
                    STRINGA_MaxChars, 4,
                    STRINGA_Font, NULL,
                    TAG_END,
                
                GO_ENDGRP(),
                
            GO_ENDGRP(),
    
            GO_EMPTYBOX(0,0,1),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_PadSet,50,GOT_PercCharH),
            TAG_END,
            
            // Draw the title text for this section.
            GO_DRAWBOX(GOSD_Normal,0,0,0),
            GOCT_FmtPtrTag, GODT_DrawStdText,
            GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdMax,100,GOT_PercTextMaxW),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdMax,100,GOT_PercTextMaxH),
            TAG_END,
            GODT_SetTextMode, FLGALL(TXTMD_CENTER | TXTMD_ENDCENTER | TXTMD_RELTOP),
            GODT_MoveTo, GO_SCLPNT(0,32,0,0,0),
            GODT_DrawStdText, MSG_EX1_CUSTOMOBJ_TXT,
            TAG_END,
            
            GO_EMPTYBOX(0,0,1),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_PadSet,5,GOT_PercCharH),
            TAG_END,
            
            /* ----------------------------------------------------------- */
            /* Custom class BOOPSI example.                                */
            /* This example creates a complex BOOPSI structure based on    */
            /* the RKMModel tutorial.  It is comprised of the objects:     */
            /*                                                             */
            /* RIGHTIM_ID, LEFTIM_ID - BOOPSI images for the arrow gads.   */
            /*                                                             */
            /* RIGHT_ID, LEFT_ID - BOOPSI buttons making the arrow gads.   */
            /*                                                             */
            /* INTEGER_ID, INTFRAME_ID - An integer gadget for the value,  */
            /* along with a frame which is attached to the gadget.         */
            /*                                                             */
            /* PROP_ID - The actual prop gadget.                           */
            /*                                                             */
            /* VAL2PROG_ID, VAL2INT_ID - Interconnection objects which     */
            /* are added to our custom class so that it can send update    */
            /* messages back to the integer and prop gadgets.              */
            /*                                                             */
            /* RKMMODEL_ID - Our custom gadget, which manages the          */
            /* interactions between all of the above gadgets.  See the     */
            /* RKMModel tutorial for details on this class.                */
            /* ----------------------------------------------------------- */

            GO_HORIZGRP(0,0,0), TAG_END,

                // For this example, we are going fudge things a bit and draw
                // our own arrow buttons, since the system ones don't scale.
                // But this is how we would have used a system image...
                
                #if 0
                GO_BOOPSIIMAGE(GOSB_Image,0,RIGHTIM_ID,(ULONG)&"sysiclass",NULL),
                GOCT_SetBodyLeft, GO_TSIZE(GOM_Set,0,GOT_Pixels),
                GOCT_SetBodyTop, GO_TSIZE(GOM_Set,0,GOT_Pixels),
                GOCT_SetBodyWidth, GO_BSIZE(GOM_Set,RIGHT_ID,GOTB_BodyWidth),
                GOCT_SetBodyHeight, GO_BSIZE(GOM_Set,RIGHT_ID,GOTB_BodyHeight),
                TAG_END,
                SYSIA_Which, RIGHTIMAGE,
                TAG_END,
                #endif
    
                #if 0
                GO_BOOPSIIMAGE(GOSB_Image,0,LEFTIM_ID,(ULONG)&"sysiclass",NULL),
                GOCT_SetBodyLeft, GO_TSIZE(GOM_Set,0,GOT_Pixels),
                GOCT_SetBodyTop, GO_TSIZE(GOM_Set,0,GOT_Pixels),
                GOCT_SetBodyWidth, GO_BSIZE(GOM_Set,LEFT_ID,GOTB_BodyWidth),
                GOCT_SetBodyHeight, GO_BSIZE(GOM_Set,LEFT_ID,GOTB_BodyHeight),
                TAG_END,
                SYSIA_Which, LEFTIMAGE,
                TAG_END,
                #endif
    
                // Create custom drawings for the up/down buttons.  These
                // are then attached to the actual button gadgets.
                
                #define ARROW_RGT (53)
                #define ARROW_TOP (10)
                #define ARROW_BOT (55)
                #define ARROW_LFT (10)
                #define ARROW_LMID (26)
                #define ARROW_RMID (38)
                
                GO_DRAWIMAGE(GOSD_BoopsiIm,0,RIGHTIM_ID),
                GOCT_SetBodyLeft, GO_TSIZE(GOM_Set,0,GOT_Pixels),
                GOCT_SetBodyTop, GO_TSIZE(GOM_Set,0,GOT_Pixels),
                GOCT_SetBodyWidth, GO_BSIZE(GOM_Set,RIGHT_ID,GOTB_BodyWidth),
                GOCT_SetBodyHeight, GO_BSIZE(GOM_Set,RIGHT_ID,GOTB_BodyHeight),
                TAG_END,
                GODT_ExecDrawing, (ULONG)&ThinIconInitDraw[0],
                GODT_AreaStart, GO_SCLPNT(TEXTPEN,ARROW_RGT,32,0,0),
                GODT_AreaDrawTo2, GO_SCLPNT(TEXTPEN,ARROW_LFT,ARROW_TOP,ARROW_LMID,32),
                GODT_AreaDrawTo2, GO_SCLPNT(TEXTPEN,ARROW_LFT,ARROW_BOT,ARROW_RGT,32),
                GODT_AreaFill, GO_SCLPNT(TEXTPEN,0,0,0,0),
                TAG_END,
                    
                GO_DRAWIMAGE(GOSD_BoopsiIm,0,LEFTIM_ID),
                GOCT_SetBodyLeft, GO_TSIZE(GOM_Set,0,GOT_Pixels),
                GOCT_SetBodyTop, GO_TSIZE(GOM_Set,0,GOT_Pixels),
                GOCT_SetBodyWidth, GO_BSIZE(GOM_Set,RIGHT_ID,GOTB_BodyWidth),
                GOCT_SetBodyHeight, GO_BSIZE(GOM_Set,RIGHT_ID,GOTB_BodyHeight),
                TAG_END,
                GODT_ExecDrawing, (ULONG)&ThinIconInitDraw[0],
                GODT_AreaStart, GO_SCLPNT(TEXTPEN,ARROW_LFT,32,0,0),
                GODT_AreaDrawTo2, GO_SCLPNT(TEXTPEN,ARROW_RGT,ARROW_TOP,ARROW_RMID,32),
                GODT_AreaDrawTo2, GO_SCLPNT(TEXTPEN,ARROW_RGT,ARROW_BOT,ARROW_LFT,32),
                GODT_AreaFill, GO_SCLPNT(TEXTPEN,0,0,0,0),
                TAG_END,
                
                // Create the RKMModel object.  GOCT_AddMember is used by
                // the BOOPSI command to send OM_ADDMEMBER methods to its
                // object when building the layout.
                
                GO_BOOPSIOBJ(GOSB_Object,0,RKMMODEL_ID,NULL,1),
                GOCT_AddMember, VAL2PROP_ID,
                GOCT_AddMember, VAL2INT_ID,
                TAG_END,
                RKMMOD_CurrVal, INITIALVAL,
                RKMMOD_Limit, (TOTAL-VISIBLE),
                TAG_END,
                
                // Create the integer gadget.  In this case, we are going
                // to give it a frame by attaching a custom drawing to
                // the gadget.  Due to problems either in BOOPSI or my
                // understanding of it :), custom drawing attached to another
                // gadget cannot get their drawing size of the size requested
                // by the gadget; we thus have to go through a bit of effort
                // to extract that size on our own.

                GO_DRAWIMAGE(GOSD_BoopsiIm,0,INTFRAME_ID),
                // Put the top-left edge of the frame in the integer gadget's
                // text area.  "Scale by -100 percent" essentially negates
                // a value.
                GOCT_SetBodyLeft, GO_BSIZE(GOM_Set,INTEGER_ID,GOTB_TextLeft),
                GOCT_SetBodyLeft, GO_TSIZE(GOM_Set,-100,GOT_PercScale),
                GOCT_SetBodyTop, GO_BSIZE(GOM_Set,INTEGER_ID,GOTB_TextAbove),
                GOCT_SetBodyTop, GO_TSIZE(GOM_Set,-100,GOT_PercScale),
                // Make the width and height the sum of the two text areas
                // and the body area.
                GOCT_SetBodyWidth, GO_BSIZE(GOM_Set,INTEGER_ID,GOTB_TextLeft),
                GOCT_SetBodyWidth, GO_BSIZE(GOM_Add,INTEGER_ID,GOTB_BodyWidth),
                GOCT_SetBodyWidth, GO_BSIZE(GOM_Add,INTEGER_ID,GOTB_TextRight),
                GOCT_SetBodyHeight, GO_BSIZE(GOM_Set,RIGHT_ID,GOTB_TextAbove),
                GOCT_SetBodyHeight, GO_BSIZE(GOM_Add,RIGHT_ID,GOTB_BodyHeight),
                GOCT_SetBodyHeight, GO_BSIZE(GOM_Add,RIGHT_ID,GOTB_TextBelow),
                TAG_END,
                GODT_DrawStdFrame, GO_SCLPNT(SHINEPEN,0,0,63,63),
                TAG_END,
                
                GO_BOOPSIBOX(GOSB_AddGad,0,INTEGER_ID,0,(ULONG)&"strgclass",NULL),
                GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdSet,100,GOT_PercCharH),
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdSet,300,GOT_PercChar0),
                GOCT_SizeTextLeft, GO_TSIZE(GOM_StdSet,200,GOT_PercStdFrmW),
                GOCT_SizeTextAbove, GO_TSIZE(GOM_StdSet,200,GOT_PercStdFrmH),
                GOCT_SizeTextRight, GO_TSIZE(GOM_StdSet,200,GOT_PercStdFrmW),
                GOCT_SizeTextBelow, GO_TSIZE(GOM_StdSet,200,GOT_PercStdFrmH),
                GOCT_SizeSpaceRight, GO_TSIZE(GOM_AllSet,0,GOT_Pixels),
                GOCT_LinkFromTag, GA_Image,
                GOCT_LinkToStdID, INTFRAME_ID,
                GOCT_LinkFromTag, ICA_TARGET,
                GOCT_LinkToStdID, RKMMODEL_ID,
                GOCT_CopyTextFont, STRINGA_Font,
                TAG_END,
                ICA_MAP, (ULONG)&go2rkmmodel[0],
                ICA_TARGET, NULL,
                STRINGA_LongVal, INITIALVAL,
                STRINGA_MaxChars, 4,
                STRINGA_Font, NULL,
                GA_Image, NULL,
                TAG_END,
    
                GO_BOOPSIBOX(GOSB_AddGad,0,PROP_ID,1,(ULONG)&"propgclass",NULL),
                GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdSet,100,GOT_PercCharH),
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdSet,400,GOT_PercCharW),
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdMax,20,GOT_Pixels),
                GOCT_SizeSpaceLeft, GO_TSIZE(GOM_AllSet,0,GOT_Pixels),
                GOCT_SizeSpaceRight, GO_TSIZE(GOM_AllSet,0,GOT_Pixels),
                GOCT_LinkFromTag, ICA_TARGET,
                GOCT_LinkToStdID, RKMMODEL_ID,
                TAG_END,
                ICA_MAP, (ULONG)&go2rkmmodel[0],
                ICA_TARGET, NULL,
                PGA_Freedom, FREEHORIZ,
                PGA_Total, TOTAL,
                PGA_Top, INITIALVAL,
                PGA_Visible, VISIBLE,
                PGA_NewLook, TRUE,
                TAG_END,
    
                // Create the up/down buttons.  We need to do these this way
                // [rather than just directly making a GO_DRAWBOX()] because
                // we need to get at the underlying BOOPSI button gadget to
                // connect it to the rest of our system.

                GO_BOOPSIBOX(GOSB_AddGad,0,LEFT_ID,0,(ULONG)&"buttongclass",NULL),
                GOCT_ExecSizeTags, (ULONG)&ThinIconControl[0],
                GOCT_SizeSpaceLeft, GO_TSIZE(GOM_AllSet,0,GOT_Pixels),
                GOCT_SizeSpaceRight, GO_TSIZE(GOM_AllSet,0,GOT_Pixels),
                GOCT_LinkFromTag, ICA_TARGET,
                GOCT_LinkToStdID, RKMMODEL_ID,
                GOCT_LinkFromTag, GA_Image,
                GOCT_LinkToStdID, LEFTIM_ID,
                TAG_END,
                ICA_MAP, (ULONG)&left2rkmmodel[0],
                ICA_TARGET, NULL,
                GA_Image, NULL,
                TAG_END,
    
                GO_BOOPSIBOX(GOSB_AddGad,0,RIGHT_ID,0,(ULONG)&"buttongclass",NULL),
                GOCT_ExecSizeTags, (ULONG)&ThinIconControl[0],
                GOCT_SizeSpaceLeft, GO_TSIZE(GOM_AllSet,0,GOT_Pixels),
                GOCT_LinkFromTag, ICA_TARGET,
                GOCT_LinkToStdID, RKMMODEL_ID,
                GOCT_LinkFromTag, GA_Image,
                GOCT_LinkToStdID, RIGHTIM_ID,
                TAG_END,
                ICA_MAP, (ULONG)&right2rkmmodel[0],
                ICA_TARGET, NULL,
                GA_Image, NULL,
                TAG_END,
    
                // Create the interconnection objects which RKMClasses uses
                // to send update messages out to the prop and integer.
                
                GO_BOOPSIOBJ(GOSB_Object,0,VAL2PROP_ID,(ULONG)&"icclass",NULL),
                GOCT_LinkFromTag, ICA_TARGET,
                GOCT_LinkToStdID, PROP_ID,
                TAG_END,
                ICA_MAP, (ULONG)&mapcurrval2prop[0],
                ICA_TARGET, NULL,
                TAG_END,
    
                GO_BOOPSIOBJ(GOSB_Object,0,VAL2INT_ID,(ULONG)&"icclass",NULL),
                GOCT_LinkFromTag, ICA_TARGET,
                GOCT_LinkToStdID, INTEGER_ID,
                TAG_END,
                ICA_MAP, (ULONG)&mapcurrval2int[0],
                ICA_TARGET, NULL,
                TAG_END,
                
            GO_ENDGRP(),
    
            GO_DRAWBOX(GOSD_Normal,0,0,0),
            GOCT_FmtPtrTag, GODT_DrawStdText,
            GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdMax,100,GOT_PercTextMaxW),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdMax,100,GOT_PercTextMaxH),
            TAG_END,
            GODT_SetTextMode, FLGALL(TXTMD_CENTER | TXTMD_ENDCENTER | TXTMD_RELTOP),
            GODT_MoveTo, GO_SCLPNT(0,32,0,0,0),
            GODT_DrawStdText, MSG_EX1_RKMMODEL_LAB,
            TAG_END,
            
            GO_EMPTYBOX(0,0,1),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_PadSet,50,GOT_PercCharH),
            TAG_END,
            
            // Draw the title text for this section.
            GO_DRAWBOX(GOSD_Normal,0,0,0),
            GOCT_FmtPtrTag, GODT_DrawStdText,
            GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdMax,100,GOT_PercTextMaxW),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdMax,100,GOT_PercTextMaxH),
            TAG_END,
            GODT_SetTextMode, FLGALL(TXTMD_CENTER | TXTMD_ENDCENTER | TXTMD_RELTOP),
            GODT_MoveTo, GO_SCLPNT(0,32,0,0,0),
            GODT_DrawStdText, MSG_EX1_CUSTOMIMG_TXT,
            TAG_END,
            
            GO_EMPTYBOX(0,0,1),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_PadSet,5,GOT_PercCharH),
            TAG_END,
            
            /* ----------------------------------------------------------- */
            /* GO drawings with BOOPSI example.                            */
            /* This example gives an idea of what is possible when         */
            /* integrating GadOutline's custom drawings with BOOPSI        */
            /* objects.  It creates a prop/integer gadget just like the    */
            /* first example, and adds a custom drawing which the prop     */
            /* gadget uses as its knob.  It is comprised of the objects:   */
            /*                                                             */
            /* PROPKNOB_ID - The drawing used to make the knob.            */
            /*                                                             */
            /* DRAWINT_ID - The integer gadget.                            */
            /*                                                             */
            /* DRAWPROP_ID - The actual prop gadget.                       */
            /* ----------------------------------------------------------- */

            GO_HORIZGRP(0,0,0), TAG_END,
            
                // This command defines our prop knob.  Unfortunately, the
                // system's prop gadget can't make an auto-sizing knob with
                // a custom knob image, so we force the knob to be a constant
                // percentage of the prop's body.
                
                GO_DRAWIMAGE(GOSD_BoopsiIm,0,PROPKNOB_ID),
                // Top and left are relative to the knob position.
                GOCT_SetBodyLeft, GO_TSIZE(GOM_Set,0,GOT_Pixels),
                GOCT_SetBodyTop, GO_TSIZE(GOM_Set,0,GOT_Pixels),
                // Make the width 15% of the total prop container width.
                GOCT_SetBodyWidth, GO_BSIZE(GOM_Set,BASICPROP_ID,GOTB_BodyWidth),
                GOCT_SetBodyWidth, GO_TSIZE(GOM_Add,-2,GOT_Pixels),
                GOCT_SetBodyWidth, GO_TSIZE(GOM_Set,15,GOT_PercScale),
                // Make the height the container height, without the borders.
                GOCT_SetBodyHeight, GO_BSIZE(GOM_Set,BASICPROP_ID,GOTB_BodyHeight),
                GOCT_SetBodyHeight, GO_TSIZE(GOM_Add,-2,GOT_Pixels),
                TAG_END,
                GODT_DrawStdFrame, GO_SCLPNT(SHINEPEN,0,0,63,63),
                GODT_SetRightBound, GO_TSIZE(GOM_Add,-100,GOT_PercStdFrmW),
                GODT_SetBottomBound, GO_TSIZE(GOM_Add,-100,GOT_PercStdFrmH),
                GODT_SetLeftBound, GO_TSIZE(GOM_Add,100,GOT_PercStdFrmW),
                GODT_SetTopBound, GO_TSIZE(GOM_Add,100,GOT_PercStdFrmH),
                GODT_FillRect, GO_SCLPNT(BACKGROUNDPEN,0,0,63,63),
                GODT_SetDrawMode, FLGOFF(DRWMD_HIGHLIGHT),
                GODT_SetOrigin, GO_SCLPNT(0,16,16,16,48),
                GODT_DrawLine, GO_PIXPNT(SHADOWPEN,PX1(1),PY1(1),PX2(1),PY2(1)),
                GODT_DrawLine, GO_PIXPNT(SHINEPEN,PX1(0),PY1(0),PX2(0),PY2(0)),
                GODT_SetOrigin, GO_SCLPNT(0,32,16,32,48),
                GODT_DrawLine, GO_PIXPNT(SHADOWPEN,PX1(1),PY1(1),PX2(1),PY2(1)),
                GODT_DrawLine, GO_PIXPNT(SHINEPEN,PX1(0),PY1(0),PX2(0),PY2(0)),
                GODT_SetOrigin, GO_SCLPNT(0,48,16,48,48),
                GODT_DrawLine, GO_PIXPNT(SHADOWPEN,PX1(1),PY1(1),PX2(1),PY2(1)),
                GODT_DrawLine, GO_PIXPNT(SHINEPEN,PX1(0),PY1(0),PX2(0),PY2(0)),
                TAG_END,
                
                // Create the prop gadget, connecting its image and selected
                // image to our custom drawing.
                
                GO_BOOPSIBOX(GOSB_AddGad,0,DRAWPROP_ID,1,(ULONG)&"propgclass",NULL),
                GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdSet,100,GOT_PercCharH),
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdSet,400,GOT_PercCharW),
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdMax,20,GOT_Pixels),
                GOCT_SizeSpaceRight, GO_TSIZE(GOM_AllSet,0,GOT_Pixels),
                GOCT_LateFromTag, ICA_TARGET,
                GOCT_LateToStdID, DRAWINT_ID,
                GOCT_LinkFromTag, GA_Image,
                GOCT_LinkToStdID, PROPKNOB_ID,
                GOCT_LinkFromTag, GA_SelectRender,
                GOCT_LinkToStdID, PROPKNOB_ID,
                TAG_END,
                ICA_MAP, (ULONG)&prop2intmap[0],
                ICA_TARGET, NULL,
                PGA_Freedom, FREEHORIZ,
                PGA_Total, TOTAL,
                PGA_Top, INITIALVAL,
                PGA_Visible, VISIBLE,
                PGA_NewLook, TRUE,
                GA_Image, NULL,
                GA_SelectRender, NULL,
                TAG_END,
    
                // Create the integer gadget with frame, just like the
                // first example.
                
                GO_HDRAWGRP(0,0,0),
                GOCT_FitToGroup, TRUE,
                GOCT_SizeTextLeft, GO_TSIZE(GOM_StdSet,200,GOT_PercStdFrmW),
                GOCT_SizeTextAbove, GO_TSIZE(GOM_StdSet,200,GOT_PercStdFrmH),
                GOCT_SizeTextRight, GO_TSIZE(GOM_StdSet,200,GOT_PercStdFrmW),
                GOCT_SizeTextBelow, GO_TSIZE(GOM_StdSet,200,GOT_PercStdFrmH),
                TAG_END,
                GODT_ResetBounds, GO_FRMBOUNDS(2,2,2,2, 4,4,4,4),
                GODT_DrawStdFrame, GO_SCLPNT(SHINEPEN,0,0,63,63),
                TAG_END,
                
                    GO_BOOPSIBOX(GOSB_AddGad,0,DRAWINT_ID,0,(ULONG)&"strgclass",NULL),
                    GOCT_SizeSpaceLeft, GO_TSIZE(GOM_AllSet,0,GOT_Pixels),
                    GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdSet,100,GOT_PercCharH),
                    GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdSet,300,GOT_PercChar0),
                    GOCT_LateFromTag, ICA_TARGET,
                    GOCT_LateToStdID, DRAWPROP_ID,
                    GOCT_LinkFromTag, GA_Image,
                    GOCT_LateToStdID, DRAWPROP_ID,
                    GOCT_CopyTextFont, STRINGA_Font,
                    TAG_END,
                    ICA_MAP, (ULONG)&int2propmap[0],
                    ICA_TARGET, NULL,
                    STRINGA_LongVal, INITIALVAL,
                    STRINGA_MaxChars, 4,
                    STRINGA_Font, NULL,
                    TAG_END,
                
                GO_ENDGRP(),
                
            GO_ENDGRP(),
    
        GO_ENDGRP(),

        GO_DRAWBOX(GOSD_Normal,0,0,0),
        GOCT_SizeSpaceLeft, GO_TSIZE(GOM_PadSet,50,GOT_PercCharW),
        GOCT_SizeSpaceRight, GO_TSIZE(GOM_PadSet,50,GOT_PercCharW),
        GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdSet,4,GOT_Pixels),
        GOCT_SizeBodyWidth, GO_TSIZE(GOM_PadSet,0,GOT_Pixels),
        GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdSet,2,GOT_Pixels),
        GOCT_SizeBodyHeight, GO_TSIZE(GOM_PadSet,0,GOT_Pixels),
        TAG_END,
        GODT_DrawStdFrame, GO_SCLPNT(SHINEPEN,0,0,63,63),
        TAG_END,
    
        GO_VERTGRP(0,0,0), TAG_END,
        
            // Draw the title text for this section.
            GO_DRAWBOX(GOSD_Normal,0,0,0),
            GOCT_FmtPtrTag, GODT_DrawStdText,
            GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdMax,100,GOT_PercTextMaxW),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdMax,100,GOT_PercTextMaxH),
            TAG_END,
            GODT_SetTextMode, FLGALL(TXTMD_CENTER | TXTMD_ENDCENTER | TXTMD_RELTOP),
            GODT_MoveTo, GO_SCLPNT(0,32,0,0,0),
            GODT_DrawStdText, MSG_EX1_DYNAMIC_TXT,
            TAG_END,
            
            GO_EMPTYBOX(0,0,1),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_PadSet,25,GOT_PercCharH),
            TAG_END,

            GO_HORIZGRP(0,0,0), GOCT_FitToGroup, TRUE, TAG_END,
            
                // Draw a font request icon, with title text.
                GO_DRAWBOX(GOSD_BoopsiGad,UNDERSCORE_GRP,REQFONT_ID,
                    GO_WEIGHT(GO_WDIST(1,0,0,0,1,0),GO_WDIST(1,0,0,0,1,0),1)),
                GOCT_SetHotKey, 'f',
                GOCT_FmtPtrTag, GODT_DrawStdText,
                GOCT_SizeTextLeft, GO_TSIZE(GOM_StdSet,100,GOT_PercTextMaxW),
                GOCT_FmtPtrTag, GODT_DrawText,
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdSet,100,GOT_PercTextMaxW),
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdAdd,400,GOT_PercStdFrmW),
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdAdd,3,GOT_Pixels),
                GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdSet,100,GOT_PercTextMaxH),
                GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdAdd,400,GOT_PercStdFrmH),
                TAG_END,
                GODT_ExecDrawing, (ULONG)&IconInitDraw[0],
                GODT_SetDrawMode, FLGOFF(DRWMD_HIGHLIGHT),
                GODT_SetTextMode, FLGALL(TXTMD_LEFT | TXTMD_ENDLEFT | TXTMD_RELCENTER),
                GODT_SetOrigin, GO_SCLPNT(0,0,32,0,0),
                GODT_ChooseTextAPen, SHADOWPEN,
                GODT_MoveTo, GO_PIXPNT(0,PX1(3),PY1(0),0,0),
                GODT_DrawText, MSG_EX1_FONT_FMT,
                GODT_MoveTo, GO_PIXPNT(0,PX1(0),PY1(0),0,0),
                GODT_DrawText, MSG_EX1_FONT_FMT,
                GODT_MoveTo, GO_PIXPNT(0,PX1(2),PY1(0),0,0),
                GODT_ChooseTextAPen, FILLPEN,
                GODT_DrawText, MSG_EX1_FONT_FMT,
                GODT_MoveTo, GO_PIXPNT(0,PX1(1),PY1(0),0,0),
                GODT_DrawHighText, MSG_EX1_FONT_FMT,
                GODT_ResetBounds, GO_BOXBOUNDS(2,3,2,3),
                GODT_SetDrawMode, FLGOFF(DRWMD_HIGHLIGHT),
                GODT_SetTextMode, FLGALL(TXTMD_RIGHT | TXTMD_ENDRIGHT | TXTMD_RELCENTER),
                GODT_SetTextStyle, FLGALL(0),
                GODT_MoveTo, GO_SCLPNT(0,63,32,0,0),
                GODT_DrawStdText, MSG_EX1_FONT_LAB,
                TAG_END,
            
                GO_EMPTYBOX(0,0,1),
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_PadSet,100,GOT_PercCharW),
                TAG_END,
                
                #define JUMP_2TOP (0)
                #define JUMP_2LEFT (25)
                #define JUMP_2RIGHT (63)
                #define JUMP_2MID (18)
                #define JUMP_2BOT (55)
                #define JUMP_1TOP (17)
                #define JUMP_1LEFT (0)
                #define JUMP_1RIGHT (42)
                #define JUMP_1MID (31)
                #define JUMP_1BOT (63)
                #if 0
                #define JUMP_LINEX1 (10)
                #define JUMP_LINEY1 (55)
                #define JUMP_LINEX2 (55)
                #define JUMP_LINEY2 (47)
                #define JUMP_LINEX3 (40)
                #define JUMP_LINEY3 (42)
                #define JUMP_LINEX4 (57)
                #define JUMP_LINEY4 (60)
                #endif
                
                // Draw a "jump screens" icon, with title text.
                GO_DRAWBOX(GOSD_BoopsiGad,UNDERSCORE_GRP,JUMPWIN_ID,
                    GO_WEIGHT(GO_WDIST(1,0,0,0,1,0),GO_WDIST(1,0,0,0,1,0),1)),
                GOCT_SetHotKey, 'j',
                GOCT_FmtPtrTag, GODT_DrawStdText,
                GOCT_SizeTextLeft, GO_TSIZE(GOM_StdSet,100,GOT_PercTextMaxW),
                GOCT_ExecSizeTags, (ULONG)&SmallIconControl[0],
                TAG_END,
                GODT_ExecDrawing, (ULONG)&IconInitDraw[0],
                GODT_SetDrawMode, FLGOFF(DRWMD_HIGHLIGHT),
                GODT_SetRastMode, FLGALL(JAM2),
                //GODT_SetStdFillPat, FLPAT_HASH2,
                GODT_SetDrI15Pen, 0,
                GODT_MapHighPen, GO_MAPPEN(15,15),
                GODT_ChooseBPen, BACKGROUNDPEN,
                GODT_FillRect, GO_SCLPNT(BARBLOCKPEN,JUMP_2LEFT,JUMP_2TOP,JUMP_2RIGHT,JUMP_2MID),
                GODT_FillRect, GO_SCLPNT(BACKGROUNDPEN,JUMP_2RIGHT-5,JUMP_2TOP,JUMP_2RIGHT,JUMP_2MID),
                GODT_DrawRect, GO_SCLPNT(TEXTPEN,JUMP_2LEFT,JUMP_2TOP,JUMP_2RIGHT,JUMP_2MID),
                GODT_FillRect, GO_SCLPNT(15,JUMP_2LEFT,JUMP_2MID,JUMP_2RIGHT,JUMP_2BOT),
                GODT_DrawRect, GO_SCLPNT(TEXTPEN,JUMP_2LEFT,JUMP_2MID,JUMP_2RIGHT,JUMP_2BOT),
                GODT_SetOrigin, GO_SCLPNT(0,JUMP_1LEFT,JUMP_1TOP,JUMP_1RIGHT,JUMP_1BOT),
                //GODT_FillRect, GO_PIXPNT(BACKGROUNDPEN,PX1(-1),PY1(-1),PX2(1),PY2(1)),
                GODT_FillRect, GO_SCLPNT(BARBLOCKPEN,JUMP_1LEFT,JUMP_1TOP,JUMP_1RIGHT,JUMP_1MID),
                GODT_FillRect, GO_SCLPNT(BACKGROUNDPEN,JUMP_1RIGHT-5,JUMP_1TOP,JUMP_1RIGHT,JUMP_1MID),
                GODT_DrawRect, GO_SCLPNT(TEXTPEN,JUMP_1LEFT,JUMP_1TOP,JUMP_1RIGHT,JUMP_1MID),
                GODT_FillRect, GO_SCLPNT(15,JUMP_1LEFT,JUMP_1MID,JUMP_1RIGHT,JUMP_1BOT),
                GODT_DrawRect, GO_SCLPNT(TEXTPEN,JUMP_1LEFT,JUMP_1MID,JUMP_1RIGHT,JUMP_1BOT),
                #if 0
                GODT_SetOrigin, GO_SCLPNT(0,JUMP_LINEX1,JUMP_LINEY1,JUMP_LINEX2,JUMP_LINEY2),
                GODT_DrawLine, GO_PIXPNT(TEXTPEN,PX1(0),PY1(1),PX2(0),PY2(1)),
                GODT_SetOrigin, GO_SCLPNT(0,JUMP_LINEX2,JUMP_LINEY2,JUMP_LINEX3,JUMP_LINEY3),
                GODT_DrawLine, GO_PIXPNT(TEXTPEN,PX1(1),PY1(-1),PX2(1),PY2(-1)),
                GODT_SetOrigin, GO_SCLPNT(0,JUMP_LINEX2,JUMP_LINEY2,JUMP_LINEX4,JUMP_LINEY4),
                GODT_DrawLine, GO_PIXPNT(TEXTPEN,PX1(1),PY1(0),PX2(1),PY2(0)),
                GODT_SetOrigin, GO_SCLPNT(0,JUMP_LINEX1,JUMP_LINEY1,JUMP_LINEX2,JUMP_LINEY2),
                GODT_DrawLine, GO_PIXPNT(HIGHLIGHTTEXTPEN,PX1(0),PY1(0),PX2(0),PY2(0)),
                //GODT_DrawLine, GO_PIXPNT(HIGHLIGHTTEXTPEN,PX1(-1),PY1(0),PX2(-1),PY2(0)),
                GODT_SetOrigin, GO_SCLPNT(0,JUMP_LINEX2,JUMP_LINEY2,JUMP_LINEX3,JUMP_LINEY3),
                GODT_DrawLine, GO_PIXPNT(HIGHLIGHTTEXTPEN,PX1(0),PY1(0),PX2(0),PY2(0)),
                //GODT_DrawLine, GO_PIXPNT(HIGHLIGHTTEXTPEN,PX1(-1),PY1(0),PX2(-1),PY2(0)),
                GODT_SetOrigin, GO_SCLPNT(0,JUMP_LINEX2,JUMP_LINEY2,JUMP_LINEX4,JUMP_LINEY4),
                GODT_DrawLine, GO_PIXPNT(HIGHLIGHTTEXTPEN,PX1(0),PY1(0),PX2(0),PY2(0)),
                //GODT_DrawLine, GO_PIXPNT(HIGHLIGHTTEXTPEN,PX1(-1),PY1(0),PX2(-1),PY2(0)),
                #endif
                GODT_ResetBounds, GO_BOXBOUNDS(2,3,2,3),
                GODT_SetDrawMode, FLGOFF(DRWMD_HIGHLIGHT),
                GODT_SetTextMode, FLGALL(TXTMD_RIGHT | TXTMD_ENDRIGHT | TXTMD_RELCENTER),
                GODT_SetRastMode, FLGALL(JAM1),
                GODT_MoveTo, GO_SCLPNT(0,63,32,0,0),
                GODT_DrawStdText, MSG_EX1_JUMP_LAB,
                TAG_END,
            
            GO_ENDGRP(),

            GO_EMPTYBOX(0,0,1),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_PadSet,25,GOT_PercCharH),
            TAG_END,

            GO_VERTGRP(0,0,0), GOCT_FitToGroup, TRUE, TAG_END,
            
                // Draw a outline values request icon, with title text.
                GO_DRAWBOX(GOSD_BoopsiGad,UNDERSCORE_GRP,OUTVALUES_ID,
                    GO_WEIGHT(GO_WDIST(1,0,0,0,1,0),GO_WDIST(1,0,0,0,1,0),1)),
                GOCT_SetHotKey, 'o',
                GOCT_FmtPtrTag, GODT_DrawStdText,
                GOCT_SizeTextLeft, GO_TSIZE(GOM_StdSet,100,GOT_PercTextMaxW),
                GOCT_FmtPtrTag, GODT_DrawText,
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdSet,100,GOT_PercTextMaxW),
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdAdd,400,GOT_PercStdFrmW),
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdAdd,3,GOT_Pixels),
                GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdSet,100,GOT_PercTextMaxH),
                GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdAdd,400,GOT_PercStdFrmH),
                TAG_END,
                GODT_ExecDrawing, (ULONG)&IconInitDraw[0],
                GODT_SetDrawMode, FLGOFF(DRWMD_HIGHLIGHT),
                GODT_SetTextMode, FLGALL(TXTMD_LEFT | TXTMD_ENDLEFT | TXTMD_RELCENTER),
                GODT_SetOrigin, GO_SCLPNT(0,0,32,0,0),
                GODT_ChooseTextAPen, SHADOWPEN,
                GODT_MoveTo, GO_PIXPNT(0,PX1(3),PY1(0),0,0),
                GODT_DrawText, MSG_EX1_OUTVALUES_FMT,
                GODT_MoveTo, GO_PIXPNT(0,PX1(0),PY1(0),0,0),
                GODT_DrawText, MSG_EX1_OUTVALUES_FMT,
                GODT_MoveTo, GO_PIXPNT(0,PX1(2),PY1(0),0,0),
                GODT_ChooseTextAPen, FILLPEN,
                GODT_DrawText, MSG_EX1_OUTVALUES_FMT,
                GODT_MoveTo, GO_PIXPNT(0,PX1(1),PY1(0),0,0),
                GODT_DrawHighText, MSG_EX1_OUTVALUES_FMT,
                GODT_ResetBounds, GO_BOXBOUNDS(2,3,2,3),
                GODT_SetDrawMode, FLGOFF(DRWMD_HIGHLIGHT),
                GODT_SetTextMode, FLGALL(TXTMD_RIGHT | TXTMD_ENDRIGHT | TXTMD_RELCENTER),
                GODT_SetTextStyle, FLGALL(0),
                GODT_MoveTo, GO_SCLPNT(0,63,32,0,0),
                GODT_DrawStdText, MSG_EX1_OUTVALUES_LAB,
                TAG_END,
            
                // Draw a window values request icon, with title text.
                GO_DRAWBOX(GOSD_BoopsiGad,UNDERSCORE_GRP,WINVALUES_ID,
                    GO_WEIGHT(GO_WDIST(1,0,0,0,1,0),GO_WDIST(1,0,0,0,1,0),1)),
                GOCT_SetHotKey, 'w',
                GOCT_FmtPtrTag, GODT_DrawStdText,
                GOCT_SizeTextLeft, GO_TSIZE(GOM_StdSet,100,GOT_PercTextMaxW),
                GOCT_FmtPtrTag, GODT_DrawText,
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdSet,100,GOT_PercTextMaxW),
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdAdd,400,GOT_PercStdFrmW),
                GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdAdd,3,GOT_Pixels),
                GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdSet,100,GOT_PercTextMaxH),
                GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdAdd,400,GOT_PercStdFrmH),
                TAG_END,
                GODT_ExecDrawing, (ULONG)&IconInitDraw[0],
                GODT_SetDrawMode, FLGOFF(DRWMD_HIGHLIGHT),
                GODT_SetTextMode, FLGALL(TXTMD_LEFT | TXTMD_ENDLEFT | TXTMD_RELCENTER),
                GODT_SetOrigin, GO_SCLPNT(0,0,32,0,0),
                GODT_ChooseTextAPen, SHADOWPEN,
                GODT_MoveTo, GO_PIXPNT(0,PX1(3),PY1(0),0,0),
                GODT_DrawText, MSG_EX1_WINVALUES_FMT,
                GODT_MoveTo, GO_PIXPNT(0,PX1(0),PY1(0),0,0),
                GODT_DrawText, MSG_EX1_WINVALUES_FMT,
                GODT_MoveTo, GO_PIXPNT(0,PX1(2),PY1(0),0,0),
                GODT_ChooseTextAPen, FILLPEN,
                GODT_DrawText, MSG_EX1_WINVALUES_FMT,
                GODT_MoveTo, GO_PIXPNT(0,PX1(1),PY1(0),0,0),
                GODT_DrawHighText, MSG_EX1_WINVALUES_FMT,
                GODT_ResetBounds, GO_BOXBOUNDS(2,3,2,3),
                GODT_SetDrawMode, FLGOFF(DRWMD_HIGHLIGHT),
                GODT_SetTextMode, FLGALL(TXTMD_RIGHT | TXTMD_ENDRIGHT | TXTMD_RELCENTER),
                GODT_SetTextStyle, FLGALL(0),
                GODT_MoveTo, GO_SCLPNT(0,63,32,0,0),
                GODT_DrawStdText, MSG_EX1_WINVALUES_LAB,
                TAG_END,
            
            GO_ENDGRP(),
            
            GO_EMPTYBOX(0,0,1),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_PadSet,25,GOT_PercCharH),
            TAG_END,
            
            GO_DRAWBOX(GOSD_BoopsiGad,UNDERSCORE_GRP,ICONIFY_ID,0),
            GOCT_HotKeyFromTag, GODT_DrawStdText,
            GOCT_FmtPtrTag, GODT_DrawStdText,
            GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdSet,100,GOT_PercTextMaxW),
            GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdAdd,400,GOT_PercStdFrmW),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdSet,100,GOT_PercTextMaxH),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdAdd,400,GOT_PercStdFrmH),
            TAG_END,
            GA_Disabled, FALSE,
            GODT_ExecDrawing, (ULONG)&IconInitDraw[0],
            GODT_SetTextMode, FLGALL(TXTMD_CENTER | TXTMD_ENDLEFT | TXTMD_RELCENTER),
            GODT_MoveTo, GO_SCLPNT(0,32,32,0,0),
            GODT_DrawStdText, MSG_EX1_ICONIFY_LAB,
            TAG_END,
            
            #if 0
            GO_GTBOX(BUTTON_KIND, UNDERSCORE_GRP, ICONIFY_ID, 0,
                MSG_EX1_ICONIFY_LAB, PLACETEXT_IN),
            TAG_END,
            GA_Disabled, FALSE,
            TAG_END,
            #endif
                
            GO_EMPTYBOX(0,0,1),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_PadSet,25,GOT_PercCharH),
            TAG_END,
            
            GO_DRAWBOX(GOSD_Normal,0,0,0),
            GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdSet,2,GOT_Pixels),
            GOCT_SizeBodyWidth, GO_TSIZE(GOM_PadSet,0,GOT_Pixels),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdSet,2,GOT_Pixels),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_PadSet,0,GOT_Pixels),
            GOCT_SizeSpaceAbove, GO_TSIZE(GOM_PadSet,50,GOT_PercCharH),
            GOCT_SizeSpaceBelow, GO_TSIZE(GOM_PadSet,50,GOT_PercCharH),
            TAG_END,
            GODT_DrawLine, GO_SCLPNT(SHINEPEN,0,0,63,0),
            GODT_DrawLine, GO_SCLPNT(SHADOWPEN,0,63,63,63),
            TAG_END,
            
            GO_DRAWBOX(GOSD_Normal,0,KEYSHOW_ID,0),
            GOCT_FmtPtrTag, GODT_DrawStdText,
            GOCT_SizeBodyWidth, GO_TSIZE(GOM_StdMax,100,GOT_PercTextMaxW),
            GOCT_SizeBodyHeight, GO_TSIZE(GOM_StdMax,200,GOT_PercTextMaxH),
            TAG_END,
            GODT_BodyTextPtr, MSG_EX1_EMPTY_STR,
            GODT_LeftTextPtr, MSG_EX1_EMPTY_STR,
            GODT_SetTextMode, FLGALL(TXTMD_CENTER | TXTMD_ENDCENTER | TXTMD_RELTOP),
            GODT_EraseRect, GO_SCLPNT(0,0,0,63,63),
            GODT_MoveTo, GO_SCLPNT(0,32,0,0,0),
            GODT_DrawStdText, MSG_EX1_LASTKEY_LAB,
            GODT_ChooseTextAPen, TEXTPEN,
            GODT_ChooseTextBPen, HIGHLIGHTTEXTPEN,
            GODT_DrawTextTag, GODT_BodyTextPtr,
            TAG_END,
        
        GO_ENDGRP(),
        
    GO_ENDGRP(),
    
GO_ENDGRP(),

// Every outline must end with this command.
GO_ENDOUTLINE()

};

/*********************************************
 **
 ** Example hooks used in outline
 **
 *********************************************/

// This is an example command hook.  It implements the code for finding
// the minimum dimensions of a checkbox and the code for responding to hotkey
// events.
// Note that this hook is not directly referenced in the outline - instead,
// a code is supplied for it in GOCT_SetUserHook and the translation hook
// converts this code to the actual address.  You don't normally need to
// use this circulatory method, but we are doing it here to also demonstrate
// how translation hooks work.

// First, some functions we will use.

static UWORD get_cb_width(struct GadOutline* go)
{
    if(GadToolsBase->lib_Version >= 39) {
        return (UWORD)GO_InterpretTypedSize(go,2,
                    GO_TSIZE(GOM_Add,300,GOT_PercChar0));
    } else {
        return 26;
    }
}

static UWORD get_cb_height(struct GadOutline* go)
{
    if(GadToolsBase->lib_Version >= 39) {
        return (UWORD)GO_InterpretTypedSize(go,3,
                    GO_TSIZE(GOM_Add,100,GOT_PercCharH));
    } else {
        return 11;
    }
}

ULONG __asm __saveds
checkbox_code(register __a0 struct Hook *hook,
              register __a2 struct CmdInfo *ci,
              register __a1 struct CmdHookMsg *msg)
{
    struct GadOutline *go;      // Global outline information.
    struct BoxAttr *ba;         // Box which called this hook.
    struct Gadget *gad;         // Gadget of hook, if created.
    ULONG ret;                  // Return code.
    UWORD kind;                 // GadTools kind of this box.

    // ---------------------------------------------------
    // Find some Universally Interesting variables.
    // ---------------------------------------------------

    if(ci) {
        go = ci->ci_GadOutline;             // Extract GadOutline
        kind = GETCMDSUBC(ci->ci_Command);  // GadTools kind
        gad = ci->ci_Object;                // Currently created gadget
        ba = ci->ci_BoxAttr;                // And BoxAttr of caller.
    } else go = NULL;

    #if NOISY
    D(bug("ID# %08lx: Msg=%08lx; Cmd=%08lx\n",
        ci->ci_CmdID,msg->chm_Message,ci->ci_Command));
    #endif

    // ---------------------------------------------------
    // Sanity checking...
    // ---------------------------------------------------

    if(!hook || !msg || !ci || !go) return 0;

    // ---------------------------------------------------
    // Check if this is correct type of command.
    // ---------------------------------------------------

    if( (ci->ci_Command&GO_OUTCMD(0,0,0xFFFF,0xFFFF,0))
        != GO_OUTCMD(0,0,GOK_Box,GOKB_GadTools,0) ) {
        
        // Continue processing this message.  Note that you must ALWAYS
        // pass along the return value from lower-level hooks if you are
        // not going to set it yourself.
        return GO_ContCmdHookA(ci,msg);
    }

    switch(msg->chm_Message) {

        case CHM_GETMINDIMENS: {

            struct GODimensInfo *gdi;
            WORD height,width;
            
            // The structure to fill in with our dimension information.
            gdi = msg->chm_MinDim;

            // Some example calls, just for the heck of it... :)
            // Note that when a hook is executed, the command is
            // automatically "in context."  This means that TypedSize
            // commands will refer to the current command for such
            // things as finding what the underscore character is.
            height = GO_InterpretTypedSize(go,0,
                        GO_TSIZE(GOM_Set,100,GOT_PercCharH));
            width = GO_ParseTypedSizeList(go,0,
                        GOCT_FmtPtr,ci->ci_BoxText,
                        GOCT_SizeParse,GO_TSIZE(GOM_Set,100,GOT_PercTextMaxW),
                        TAG_END);

            // If this is a checkbox...
            if(kind == CHECKBOX_KIND) {
            
                // Let default hook do what it can.  The library currently
                // knows how to take care of GadTools labels, and we don't
                // really want to duplicate -everything- here.  Note that
                // we save the return value, because we have nothing else
                // to say.
                ret = GO_ContCmdHookA(ci,msg);

                width = get_cb_width(go);
                height = get_cb_height(go);
                
                // Make sure the checkbox's body is big enough.
                if(gdi->gdi_StdBodyWidth < width) {
                    gdi->gdi_StdBodyWidth = width;
                }
                if(gdi->gdi_StdBodyHeight < height) {
                    gdi->gdi_StdBodyHeight = 11;
                }

            } else {
            
                // If not a checkbox, just let the system handle it.
                ret = GO_ContCmdHookA(ci,msg);

            }

        } break;
        
        case CHM_HOTKEY: {

            struct TagItem *tg;

            // Only respond to IDCMP_VANILLAKEY events and IDCMP_RAWKEY
            // down events.

            if( (msg->chm_KeyGOIMsg->StdIMsg.Class != IDCMP_VANILLAKEY
                && msg->chm_KeyGOIMsg->StdIMsg.Class != IDCMP_RAWKEY)
                || (msg->chm_KeyGOIMsg->StdIMsg.Class == IDCMP_RAWKEY
                    && (msg->chm_KeyGOIMsg->StdIMsg.Code&0x80) != 0) ) {

                return GO_ContCmdHookA(ci,msg);
            }
            
            // If this is a checkbox and we are tracking its state...
    
            if( kind == CHECKBOX_KIND
                && (tg=FindTagItem(GTCB_Checked,ci->ci_GadToolsTags)) != NULL ) {

                struct TagItem update[] = {
                    { 0, 0 }, { TAG_END, 0 }
                };

                // A REALLY stupid way to do a checkbox hotkey, but it's
                // the basic code for most other types...

                // If shift is pressed, decrement.

                if( (msg->chm_KeyGOIMsg->StdIMsg.Qualifier
                    &( IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT
                        | IEQUALIFIER_CAPSLOCK ) ) != 0 ) {
                        
                    if(tg->ti_Data <= 0)
                        tg->ti_Data = 1;
                    else
                        tg->ti_Data--;
                        
                // Else, increment.

                } else {

                    if(tg->ti_Data >= 1)
                        tg->ti_Data = 0;
                    else
                        tg->ti_Data++;
                }
                        
                // Send a message to command to update its state.

                update[0].ti_Tag = GTCB_Checked;
                update[0].ti_Data = tg->ti_Data;

                GO_CallCmdHook( ci, CHM_SETOBJATTR, 0, &update[0] );
                
                // If an error occured, exit stage left.
                if(go->go_LastReqReturn) return 0;
                
                // If the gadget has been created, turn the GOIMsg
                // into the correct kind of event.  Yes, we are allowed
                // to do this. :)
    
                if(gad) {
                    msg->chm_KeyGOIMsg->StdIMsg.Class = IDCMP_GADGETUP;
                    msg->chm_KeyGOIMsg->StdIMsg.Code = tg->ti_Data;
                    msg->chm_KeyGOIMsg->StdIMsg.IAddress = (APTR)gad;
                }
                
                // We don't continue this message because we basically
                // just ate it.  Chomp chomp...  yummy...
                ret = 0;
            }
        }
        
        default: {

            ret = GO_ContCmdHookA(ci,msg);

        } break;
    }

    return ret;
}

struct Hook checkbox_hook = {
    { 0 },
    (ULONG (*)())checkbox_code,
    NULL,
    NULL
};

// This is an example translation hook.  This hook is global to the outline
// and allows you to not only localize the outline array, but theoretically
// make it completely independant of any direct references to absolute
// program addresses.

// When first initializing a GadOutline, the library internally only sends
// the CHM_TRANSCMDHOOK message to translate any user command hooks supplied
// in the outline; all other translation messages are sent when the library
// sends CHM_INITCMDATTR and CHM_INITOBJATTR to the command's hook, and thus
// can be modified using a user hook.
// The standard hook asks for translation of GadTools text pointers and the
// standard GadTools tags which supply strings or arrays of strings.

Class *rkmmodcl = NULL;

ULONG __asm __saveds
translation_code(register __a0 struct Hook *hook,
                 register __a2 struct GadOutline *go,
                 register __a1 struct CmdHookMsg *msg)
{
    ULONG ret;                  // Return code.

    // ---------------------------------------------------
    // Sanity checking...
    // ---------------------------------------------------

    if(!hook || !msg || !go) return 0;

    switch(msg->chm_Message) {

        case CHM_TRANSTEXTPTR:
        case CHM_TRANSTEXTFMT:
        case CHM_TRANSNEWTEXTPTR: {

            // Version 3 of the library now contains routines to
            // use locale.library for localization.  Let's see how
            // it does...

            D(bug("Given text code: %ld\n",msg->chm_TransCode));
            ret = GO_ContTransHookA(go,msg);
            D(bug("     Got string: %ls\n",ret));

            return ret;
            
        } break;

        /***
         *** A custom translation code for arrays - looks up the given
         *** string ID, and parses it as a series of \0 terminated
         *** strings.  An empty string (consisting of only \0) ends
         *** the array.
         ***/
        
        case CHM_TRANSTEXTARRAY: {

            UBYTE** array;
            UBYTE* str;
            UBYTE* pos;
            int size;
            
            array = NULL;
            if( (str=GO_GetString(go,msg->chm_TransCode)) ) {
                size = 1;
                pos = str;
                while(*pos) {
                    size++;
                    while(*pos) pos++;
                    pos++;
                }
                size *= sizeof(UBYTE *);    
                if( (array = GO_AllocMem(go,GOTYPE_WARN,size,MEMF_PUBLIC)) ) {
                    size = 0;
                    pos = str;
                    while(*pos) {
                        array[size] = pos;
                        size++;
                        while(*pos) pos++;
                        pos++;
                    }
                    array[size] = NULL;
                }
            }
            return (ULONG)array;
            
        } break;

        case CHM_TRANSCMDHOOK: {

            if(msg->chm_TransCode == 1)
                return (ULONG)&checkbox_hook;
            else return msg->chm_TransCode;
            
        } break;

        case CHM_TRANSPRIVCLASS: {

            D(bug("Trans priv: code=%lx; value=%lx;\n   ID=%ld; obj=%ls\n",
                msg->chm_TransCode,msg->chm_TransCmd->ci_BoxValue,
                msg->chm_TransCmd->ci_CmdID,msg->chm_TransCmd->ci_BoxText));
            if(msg->chm_TransCode == 1)
                return (ULONG)rkmmodcl;
            else return msg->chm_TransCode;
            
        } break;

        default: {

        } break;
    }

    return GO_ContTransHookA(go,msg);
}

struct Hook translation_hook = {
    { 0 },
    (ULONG (*)())translation_code,
    NULL,
    NULL
};

/*********************************************
 **
 ** Program environment
 **
 *********************************************/

static struct Process *me = NULL;
static struct Window *oldwin = NULL;    // what me->pr_WindowPtr previously was

/*********************************************
 **
 ** Current program state
 **
 *********************************************/

static struct GadOutline *gad_outline = NULL;
static struct FontRequester *fr = NULL;
static UBYTE *go_error;                 // Where error results are returned
static struct List info_list;

/*********************************************
 **
 ** All library bases
 **
 *********************************************/

#define MIN_VERSION     37L             // minimum version number for our libs

long __oslibversion = MIN_VERSION;

#ifndef LINKLIB
struct Library *GadOutlineBase = NULL;
#endif

static void quit(UBYTE *err);
static void closedown(void);
static void opendisplay(struct GadOutline *go);
static void handledisplay(struct GadOutline *go);
static void free_list(struct List *list);

/*********************************************
 **
 ** Routines for a clean exit, with optional error display
 **
 *********************************************/

static struct EasyStruct error_es = {
    sizeof(struct EasyStruct), 0,
    "GadOutline Example1 Requester",
    "Problem during startup:\n%ls",
    "Quit"
};

static void quit(UBYTE *err)
{
    closedown();

    if(err == NULL) err = go_error;
    if(err != NULL) (void)EasyRequest(NULL,&error_es, NULL, err);

    _exit(0);
}

static void closedown(void)
{
    if(gad_outline) FreeGadOutline(gad_outline);
    free_list(&info_list);
    if(fr) FreeAslRequest(fr);
    if(rkmmodcl) freeRKMModClass(rkmmodcl);
    if(me) me->pr_WindowPtr = (APTR)oldwin;
    #ifndef LINKLIB
    if(GadOutlineBase) CloseLibrary(GadOutlineBase);
    #endif
}

/*********************************************
 **
 ** Routines for opening the screen, window and gadgets
 **
 *********************************************/

static void create_node(struct List *list,UBYTE *name)
{
    struct Node *nd;
    
    if( nd=AllocVec(sizeof(struct Node)+strlen(name)+5,MEMF_CLEAR) ) {
        nd->ln_Name = (char *)(nd+1);
        strcpy((UBYTE *)(nd+1),name);
        AddTail(list,nd);
    }
}

static void free_list(struct List *list)
{
    struct Node *nd;
    
    while( nd=RemTail(list) ) {
        FreeVec(nd);
    }
}

static void opendisplay(struct GadOutline *go)
{
    // First, set what the ListView will display.
    
    create_node(&info_list,"When creating ListView");
    create_node(&info_list,"gadgets, you may attach");
    create_node(&info_list,"them to strings using a");
    create_node(&info_list,"'TagLink.'  TagLinks are");
    create_node(&info_list,"also used to make");
    create_node(&info_list,"connections between");
    create_node(&info_list,"BOOPSI objects and in");
    create_node(&info_list,"any other places where");
    create_node(&info_list,"you need the tag of one");
    create_node(&info_list,"command to point to the");
    create_node(&info_list,"object created by");
    create_node(&info_list,"another command.");
    create_node(&info_list,"");
    create_node(&info_list,"The library will");
    create_node(&info_list,"automatically determine");
    create_node(&info_list,"what order it needs to");
    create_node(&info_list,"create the objects in");
    create_node(&info_list,"and set the correct tag");
    create_node(&info_list,"values when they are");
    create_node(&info_list,"created.");
    create_node(&info_list,"");
    create_node(&info_list,"A new feature of V3,");
    create_node(&info_list,"LateLinks, allow you");
    create_node(&info_list,"to create links between");
    create_node(&info_list,"two commands, which is");
    create_node(&info_list,"be applied after both");
    create_node(&info_list,"objects are created.");
    create_node(&info_list,"This is needed for");
    create_node(&info_list,"more complicated");
    create_node(&info_list,"BOOPSI designs in which");
    create_node(&info_list,"the links between");
    create_node(&info_list,"objects form a cycle,");
    create_node(&info_list,"in that there is no");
    create_node(&info_list,"order which the objects");
    create_node(&info_list,"can be created that");
    create_node(&info_list,"will automatically");
    create_node(&info_list,"resolve all the links.");

    GO_SetObjAttrs(go,LISTVIEW_ID,0,GTLV_Labels,&info_list,TAG_END);

    GO_OpenWindow(go, TAG_END);

    if(go->go_LastReqReturn || !go->go_Window) return;

    me->pr_WindowPtr = (APTR)go->go_Window;
}

static void get_keys(UBYTE* buffer,UBYTE* label,UBYTE *keys)
{
    UBYTE *pos;
    
    pos = &buffer[0];
    strcpy(pos,"\2337m");
    pos += strlen(pos);
    strcpy(pos,label);
    pos += strlen(pos);
    strcpy(pos,"\2330m\2331m ");
    pos += strlen(pos);
    while( *keys && (pos < &buffer[95]) ) {
        if( (*keys >= ' ' && *keys <= 126) || *keys >= 160 ) {
            *pos = *keys;
            pos++;
            keys++;
        } else if(*keys == '$') {
            *pos = '$';
            pos++;
            *pos = *keys;
            pos++;
            keys++;
        } else {
            *pos = '$';
            pos++;
            *pos = ( ((*keys)/16) >= 10 ) ? ((*keys)/16)+'A'-10 : ((*keys)/16)+'0';
            pos++;
            *pos = ( ((*keys)&15) >= 10 ) ? ((*keys)&15)+'A'-10 : ((*keys)&15)+'0';
            pos++;
            #if 0
            *pos = 'x';
            pos++;
            #endif
            keys++;
        }
    }
    *pos = 0;
}

static UBYTE keybuffer[100];
ULONG ticks = 0;

static void handledisplay(struct GadOutline *go)
{
    struct GOIMsg *msg;
    struct Gadget *gadget;
    ULONG class;
    UWORD code;
    UWORD qual;
    
    if(go == NULL || go->go_Window == NULL) return;

    while (1) {

        Wait( (1L<<go->go_Window->UserPort->mp_SigBit) );

        while (msg = GO_GetGOIMsg(go)) {

            struct GOIMsg *dupmsg;
            class = msg->StdIMsg.Class;
            code = msg->StdIMsg.Code;
            qual = msg->StdIMsg.Qualifier;
            gadget=msg->StdIMsg.IAddress;

            gadget = (struct Gadget *)msg->StdIMsg.IAddress;
            dupmsg = GO_DupGOIMsg(go,msg);

            GO_ReplyGOIMsg(msg);

            switch (class) {

                case IDCMP_CLOSEWINDOW:
                    return;

                case IDCMP_NEWSIZE:
                    D(bug("IDCMP NewSize.\n"));
                    break;

                case IDCMP_CHANGEWINDOW:
                    D(bug("IDCMP Change Window.\n"));
                    break;

                case IDCMP_INTUITICKS:
                    #if 0
                    if(ticks++ > 20) {
                        ticks = 0;
                        GO_SetWindowAttrs(go,0, GOA_Iconify,FALSE,TAG_END);
                    }
                    #endif
                    break;

                case IDCMP_REFRESHWINDOW:
                    D(bug("IDCMP Refresh Window.\n"));
                    GO_BeginRefresh(go);
                    GO_EndRefresh(go, TRUE);
                    break;


                case IDCMP_GADGETHELP:
                    D(bug("IDCMP Gadget Help.\n"));
                    break;

                case IDCMP_VANILLAKEY: {
                    get_keys(&keybuffer[0],"(VAN)",&dupmsg->KeyPress[0]);
                    GO_SetObjAttrs(go,KEYSHOW_ID,0,
                        GODT_LeftTextPtr, "(VAN)",
                        GODT_BodyTextPtr, &keybuffer[0],
                        TAG_END);
                    D(bug("Van key (Code %lx) (Len %ld): '%ls'\n",
                        code,strlen(&dupmsg->KeyPress[0]),&keybuffer[0]));
                } break;
                
                case IDCMP_RAWKEY: {
                    get_keys(&keybuffer[0],"(RAW)",&dupmsg->KeyPress[0]);
                    GO_SetObjAttrs(go,KEYSHOW_ID,0,
                        GODT_LeftTextPtr, "(RAW)",
                        GODT_BodyTextPtr, &keybuffer[0],
                        TAG_END);
                    D(bug("Raw key (Code %lx) (Len %ld): '%ls'\n",
                        code,strlen(&dupmsg->KeyPress[0]),&keybuffer[0]));
                } break;
                
                case IDCMP_GADGETUP: {
                    D(bug("A gadget up type: %ld\n",gadget->GadgetID));
                    switch(gadget->GadgetID) {

                        case ICONIFY_ID: {
                            GO_SetWindowAttrs(go,0, GOA_Iconify,1,TAG_END);
                        } break;
                        
                        case JUMPWIN_ID: {
                            UBYTE nextname[MAXPUBSCREENNAME+1];
            
                            if(NextPubScreen(go->go_Screen,&nextname[0])) {
                                GO_OpenWindow(go,WA_PubScreenName,&nextname[0],TAG_END);
                            }
                        } break;
                        
                        case REQFONT_ID: {

                            // Pop up the font requester
                            if (AslRequestTags(fr,

                                // Supply initial values for requester
                                ASLFO_InitialName, (ULONG)go->go_TextAttr.tta_Name,
                                ASLFO_InitialSize, go->go_TextAttr.tta_YSize,
                                ASLFO_MinHeight, 2,
                                //ASL_FontStyles, go->go_TextAttr.tta_Style,
                                //ASL_FuncFlags, FONF_STYLES,
                                ASLFO_Window, go->go_Window,
                                ASLFO_SleepWindow, TRUE,
                                TAG_END)) {

                                DimenGadOutline(go,
                                                 GOA_TextAttr,&fr->fo_Attr,
                                                 TAG_END);
                            }

                        } break;

                        case OUTVALUES_ID: {
                            ULONG scrn,win,maxw,maxh,minw,minh;
                            UBYTE* fontname;
                            ULONG fontsize,fontstyle;
                            ULONG replev,faillev;
                            ULONG ileft, itop, iwidth, iconify;
                            ULONG winpos;
                            
                            GetGadOutlineAttrs(go, 0,
                                GOA_ScreenAddr, &scrn,
                                GOA_WindowAddr, &win,
                                GOA_MaxWidth, &maxw,
                                GOA_MaxHeight, &maxh,
                                GOA_MinWidth, &minw,
                                GOA_MinHeight, &minh,
                                GOA_FontName, &fontname,
                                GOA_FontSize, &fontsize,
                                GOA_FontStyle, &fontstyle,
                                GOA_ErrorReportLevel, &replev,
                                GOA_ErrorFailLevel, &faillev,
                                GOA_IconLeft, &ileft,
                                GOA_IconTop, &itop,
                                GOA_IconWidth, &iwidth,
                                GOA_WindowPos, &winpos,
                                GOA_Iconify, &iconify,
                                TAG_END);
                            
                            GO_ShowError(go,GO_MAKEERR(GOTYPE_FINE,0),NULL,
                                "Current outline values:\n\n"
                                    "Screen = %08lx  Window = %08lx\n"
                                    "MaxWid = %08lx  MaxHgt = %08lx\n"
                                    "MinWid = %08lx  MinHgt = %08lx\n"
                                    "RepLev = %08lx  FailLv = %08lx\n"
                                    "ILeft  = %08lx  ITop   = %08lx\n"
                                    "IWidth = %08lx  Iconify= %08lx\n"
                                    "WinPos = %08lx\n"
                                    "FSize  = %08lx  FStyle = %08lx\n"
                                    "FName = %ls\n",
                                scrn, win, maxw, maxh, minw, minh,
                                replev, faillev, ileft, itop, iwidth, iconify,
                                winpos, fontsize, fontstyle, fontname);
                        } break;
                        
                        case WINVALUES_ID: {
                            UBYTE* title;
                            ULONG left,top,width,height;
                            ULONG* zoom;
                            
                            GO_GetWindowAttrs(go, 0,
                                WA_Title, &title,
                                WA_Left, &left,
                                WA_Top, &top,
                                WA_Width, &width,
                                WA_Height, &height,
                                WA_Zoom, &zoom,
                                TAG_END);
                            
                            GO_ShowError(go,GO_MAKEERR(GOTYPE_FINE,0),NULL,
                                "Current window values:\n\n"
                                    "Title = %ls\n"
                                    "CurLeft = %08lx  CurTop = %08lx\n"
                                    "CurWdth = %08lx  CurHgt = %08lx\n"
                                    "ZipLeft = %08lx  ZipTop = %08lx\n"
                                    "ZipWdth = %08lx  ZipHgt = %08lx\n",
                                title, left, top, width, height,
                                zoom[0], zoom[1], zoom[2], zoom[3]);
                            
                        } break;
                        
                        #if 0
                        case PUBSCREEN_ID: {
                        
                            UBYTE *name;
                            
                            name = (UBYTE *)GO_GetObjAttr(go,PUBSCREEN_ID,0,
                                                GTST_String,NULL);
                            if(name) {
                                strncpy(pub_screen,name,99);
                            } else {
                                pub_screen[0] = 0;
                            }
                            
                            // This routine automagically closes the previous
                            // window and opens a new window with the gadgets
                            // in the same state.
                            
                            GO_OpenWindow(go,   WA_PubScreenName,   pub_screen,
                                                TAG_END );
                            if(!go->go_Window || go->go_LastReqReturn)
                                quit("Couldn't open window.");
                            update_fontinfo(go);

                        } break;
                        
                        case SETFONT_ID: {

                            // Pop up the font requester
                            if (AslRequestTags(fr,

                                // Supply initial values for requester
                                ASL_FontName, (ULONG)go->go_TargetTA.tta_Name,
                                ASL_FontHeight, go->go_TargetTA.tta_YSize,
                                ASL_FontStyles, go->go_TargetTA.tta_Style,
                                ASL_FuncFlags, FONF_STYLES,
                                ASL_Window, go->go_Window,
                                TAG_END)) {

                                DimenGadOutline(go,
                                                 GOA_TextAttr,&fr->fo_Attr,
                                                 TAG_END);
                            }

                        } break;
                        #endif
                    }
                } break;

            }
            if(dupmsg) GO_UndupGOIMsg(dupmsg);
        }
    }
}

/*********************************************
 **
 ** Program's main entry point
 **
 *********************************************/

void __regargs main(int argc,char **argv)
{
    NewList(&info_list);

    if( !(me = (struct Process *)FindTask(NULL)) ) quit("Can't find	myself!");
    oldwin = (struct Window *)me->pr_WindowPtr;

    if( (rkmmodcl=initRKMModClass()) == NULL ) {
        quit("Can't create RKMModel class!");
    }

    if( (fr = (struct FontRequester *)
        AllocAslRequestTags(ASL_FontRequest,TAG_END)) == NULL) {
        quit("Can't allocate font requester!");
    }
            
#ifndef LINKLIB
    GadOutlineBase = OpenLibrary("gadoutline.library", 0);
    if (!GadOutlineBase)
       quit("Can't open gadoutline.library.");
    D(bug("Opened the library.  Creating outline...\n",NULL));
#endif
    
    gad_outline = AllocGadOutline(outline,
           GOA_ErrorText,       &go_error,
           GOA_ScreenName,      NULL,
           GOA_OutlineSize,     sizeof(outline),
           GOA_SetTransHook,    &translation_hook,
           TAG_END);
    if(gad_outline == NULL) {
        quit(go_error);
    }

    opendisplay(gad_outline);
    handledisplay(gad_outline);

    quit(NULL);
}

