/************************************************************************
 *                                                                      *
 *                            Preliminary                               *
 *                        Amiga AppShell (tm)                           *
 *                                                                      *
 *  Copyright (c) 1990,1991 Commodore-Amiga, Inc. All Rights Reserved.  *
 *                                                                      *
 *   This software and information is proprietary, preliminary, and     *
 *   subject to change without notice.                                  *
 *                                                                      *
 *                            DISCLAIMER                                *
 *                                                                      *
 *   THIS SOFTWARE IS PROVIDED "AS IS".                                 *
 *   NO REPRESENTATIONS OR WARRANTIES ARE MADE WITH RESPECT TO THE      *
 *   ACCURACY, RELIABILITY, PERFORMANCE, CURRENTNESS, OR OPERATION      *
 *   OF THIS SOFTWARE, AND ALL USE IS AT YOUR OWN RISK.                 *
 *   NEITHER COMMODORE NOR THE AUTHORS ASSUME ANY RESPONSIBILITY OR     *
 *   LIABILITY WHATSOEVER WITH RESPECT TO YOUR USE OF THIS SOFTWARE.    *
 *                                                                      *
 *                          Non-Disclosure                              *
 *                                                                      *
 *   This information is not to be disclosed to any other company,      *
 *   individual or party.  Discussion is to be restricted to CBM        *
 *   approved discussion areas, such as the closed conferences on bix;  *
 *   amiga.cert, amiga.com, amiga.beta/appshell.                        *
 *                                                                      *
 ************************************************************************
 * ObjectIO.c
 * Copyright (C) 1990 Commodore-Amiga, Inc.
 * written by David N. Junod
 *
 */

#define	SKIP_IPROTOS		TRUE
#define	CLIB_APPSHELL_IPROTOS_H	TRUE

#include <exec/types.h>
#include <intuition/icclass.h>
#include <libraries/asl.h>
#include "ae:support/misc_protos.h"
#include <internal/appshell_internal.h>
#include <libraries/appshell.h>
#include <libraries/appobjects.h>
#include <libraries/gadtools.h>
#include <clib/macros.h>
#include <clib/appshell_protos.h>
#include <clib/appobjects_protos.h>
#include <clib/asl_protos.h>
#include <pragmas/appshell_pragmas.h>
#include <pragmas/appobjects_pragmas.h>
#include <pragmas/asl_pragmas.h>

struct FuncsNode
{
    struct Node fn_Node;
    struct Funcs fn_Func;
    struct ObjectNode *fn_Obj;
};

struct GetRec
{
    ULONG *gr_BaseName;
};

struct DumpRec
{
    struct ObjectInfo *dr_OI;	/* ObjectInfo */
    BPTR dr_FH;			/* File handle to write to */
    STRPTR dr_BaseName;		/* Pointer to the environment base name */
};

struct PrintRec
{
    BPTR pr_FH;
};

static LONG fprint (BPTR fh, UBYTE *format, VOID *data,...)
{
    LONG VFPrintf (BPTR fh, UBYTE * format, LONG * argarray);

    return (VFPrintf (fh, format, (ULONG *) & data));
}

/* ObjectIO.c */
static VOID MakeHeader (BPTR fh, STRPTR name, STRPTR filename);
static VOID findbase (struct ObjectNode * on, ULONG cnt, struct GetRec * gr);
static VOID dumpfcid (struct FuncsNode * fn, ULONG cnt, struct DumpRec * dr);
static VOID dumpproto (struct FuncsNode * fn, ULONG cnt, struct DumpRec * dr);
static VOID dumpfunc (struct FuncsNode * fn, ULONG cnt, struct DumpRec * dr);
static VOID makefunc (struct FuncsNode * fn, ULONG cnt, struct DumpRec * dr);
static VOID makeappdata (struct FuncsNode * fn, ULONG cnt, struct DumpRec * dr);
static VOID dumptext (struct ObjectNode * on, ULONG cnt, struct DumpRec * dr);
static VOID ImageToC (BPTR fh, STRPTR name, struct Image * i);
static VOID dumplist (struct Node * n, ULONG cnt, struct PrintRec * pr);
static VOID printtagdata (BPTR fh, STRPTR name, ULONG t, struct TagItem * tl);
static VOID printFlags (BPTR fh, UBYTE * name, SHORT lvl, UBYTE * pref);
static VOID parseFlags (BPTR fh, ULONG flags, struct ulongFlags * uf, UBYTE * pref, UBYTE * sufx);
static VOID printtags (BPTR fh, STRPTR name, ULONG t, struct TagItem * tl);
static VOID dumptagdata (struct ObjectNode * on, ULONG cnt, struct DumpRec * dr);
static VOID dumptags (struct ObjectNode * on, ULONG cnt, struct DumpRec * dr);
static VOID dumpobject (struct ObjectNode * on, ULONG cnt, struct DumpRec * dr);
VOID SaveObjectList (struct AppInfo * ai, STRPTR cmd, struct TagItem * attrs);

#define	FILL "/**********************************************************************/\n"

VOID
SaveObjectList (struct AppInfo * ai, STRPTR cmd, struct TagItem * attrs)
{
    struct ObjectInfo *oi = NULL;
    STRPTR filename = "RAM:test.c";
    STRPTR name = NULL;

    if (attrs)
    {
	struct Window *win = NULL;

	if (win = (struct Window *) GetTagData (APSH_WinPointer, NULL, attrs))
	{
	    oi = (struct ObjectInfo *) win->UserData;
	}
	else if (name = (STRPTR)
		 GetTagData (APSH_WinName, (ULONG) "Main", attrs))
	{
	    struct MHObject *mho;
	    struct WinNode *wn;

	    /* get a pointer to the message handler data */
	    if (mho = HandlerData (ai, APSH_Handler, "IDCMP", TAG_DONE))
	    {
		/* get a pointer on the data */
		if (wn = (struct WinNode *) FindNameI (&(mho->mho_ObjList), name))
		{
		    oi = wn->wn_OI;
		}
	    }
	}

	/* Get the file name to save to */
	filename = (STRPTR) GetTagData (APSH_NameTag, (ULONG) filename, attrs);
    }

    if (oi)
    {
	BPTR fh = NULL;

	/* Open the output file */
	if (fh = Open (filename, MODE_NEWFILE))
	{
	    struct List *list = (struct List *) oi->oi_UserData;
	    STRPTR base = "obj";

	    MakeHeader (fh, name, filename);

	    /* Find the base name of the environment */
	    HandleList (&(oi->oi_ObjList), findbase, &base);

	    if (list)
	    {
		/* Do the list, calling dumpfcid for every node */
		HandleList (list, dumpfcid, oi, fh, base);

		/* Get a blank line in there */
		fprint (fh, "\n    LAST_ID\n};\n\n", NULL);

		/* Do the list, calling dumpfunc for every node */
		HandleList (list, dumpproto, oi, fh, base);

		/* Blank line */
		fprint (fh, "\n", NULL);

		/* Do the list, calling dumpfunc for every node */
		HandleList (list, makeappdata, oi, fh, base);

		/* Blank line */
		fprint (fh, "};\n\n", NULL);
	    }

	    fprint (fh, FILL, NULL);
	    fprint (fh, "/* Window environment data */\n", NULL);
	    fprint (fh, FILL, NULL);
	    fprint (fh, "\n", NULL);

	    if (list)
	    {
		/* Do the list, calling dumpfunc for every node */
		HandleList (list, dumpfunc, oi, fh, base);

		/* Get a blank line in there */
		fprint (fh, "};\n\n", NULL);

	    }

	    /* Do the list, calling dumptext for every node */
	    HandleList (&(oi->oi_ObjList), dumptext, oi, fh, base);

	    /* Do the list, calling dumptagdata for every node */
	    HandleList (&(oi->oi_ObjList), dumptagdata, oi, fh, base);

	    /* Do the list, calling dumptags for every node */
	    HandleList (&(oi->oi_ObjList), dumptags, oi, fh, base);

	    /* Do the list, calling dumpobject for every node */
	    HandleList (&(oi->oi_ObjList), dumpobject, oi, fh, base);


	    fprint (fh, "/* These tags describe the window environment */\n", NULL);
	    fprint (fh, "struct TagItem %s_env[] =\n", base);
	    fprint (fh, "{\n", NULL);
	    fprint (fh, "    {APSH_NameTag, (ULONG) \"%s\"},\n", base);
	    fprint (fh, "    {APSH_Objects, (ULONG) %s},\n", base);
	    fprint (fh, "    {APSH_WinText, (ULONG) %s_deftext},\n", (LONG) base);
	    fprint (fh, "    {APSH_WinAOpen, %sWinOpenID},\n", (LONG) base);
	    fprint (fh, "    {APSH_WinBClose, %sWinCloseID},\n", (LONG) base);
	    fprint (fh, "    {TAG_DONE,}\n", NULL);
	    fprint (fh, "};\n\n", NULL);
	    fprint (fh, "#define WINDOW_ENV %s_env\n\n", (LONG) base);

	    if (list)
	    {
		fprint (fh, FILL, NULL);
		fprint (fh, "/* Function stubs */\n", NULL);
		fprint (fh, FILL, NULL);
		fprint (fh, "\n", NULL);

		/* Do the list, calling dumpfunc for every node */
		HandleList (list, makefunc, oi, fh, base);
	    }

	    /* Close the file */
	    Close (fh);
	}
    }
}

static VOID MakeHeader (BPTR fh, STRPTR name, STRPTR filename)
{

    fprint (fh, "/* %s --- data for %s\n", filename, name);
    fprint (fh, " *\n */\n\n", NULL);

    fprint (fh, FILL, NULL);
    fprint (fh, "/* Place this section in a global header file */\n", NULL);
    fprint (fh, FILL, NULL);
    fprint (fh, "\n", NULL);

    fprint (fh, "#include <exec/types.h>\n", NULL);
    fprint (fh, "#include <libraries/appshell.h>\n", NULL);
    fprint (fh, "#include <libraries/apshattrs.h>\n", NULL);
    fprint (fh, "#include <libraries/appobjects.h>\n", NULL);
    fprint (fh, "#include <libraries/gadtools.h>\n", NULL);
    fprint (fh, "#include <clib/appshell_protos.h>\n", NULL);
    fprint (fh, "#include <clib/appobjects_protos.h>\n", NULL);
    fprint (fh, "#include <clib/gadtools_protos.h>\n", NULL);
    fprint (fh, "#include <clib/utility_protos.h>\n", NULL);
    fprint (fh, "#include \"ae:support/misc_protos.h\"\n", NULL);
    fprint (fh, "#include <pragmas/appshell.h>\n", NULL);
    fprint (fh, "#include <pragmas/appobjects.h>\n", NULL);
    fprint (fh, "#include <pragmas/gadtools.h>\n", NULL);
    fprint (fh, "#include <pragmas/utility.h>\n", NULL);
    fprint (fh, "\n", NULL);
    fprint (fh, "extern struct Library *SysBase, *DOSBase;\n", NULL);
    fprint (fh, "extern struct Library *AppShellBase, *AppObjectsBase;\n", NULL);
    fprint (fh, "extern struct Library *IntuitionBase, *GadToolsBase, *GfxBase, *UtilityBase;\n", NULL);
    fprint (fh, "\n", NULL);
}

static VOID findbase (struct ObjectNode * on, ULONG cnt, struct GetRec * gr)
{

    if (on)
    {
	struct Object *o = &(on->on_Object);

	if (o->o_Type == OBJ_Window)
	{
	    *gr->gr_BaseName = o->o_Name;
	}
    }
}

static VOID dumpfcid (struct FuncsNode * fn, ULONG cnt, struct DumpRec * dr)
{
    struct ObjectInfo *oi = dr->dr_OI;

    if (fn && oi)
    {
	STRPTR name = fn->fn_Func.fe_Name;
	BPTR fh = dr->dr_FH;

	/* First text item? */
	if (cnt == 0)
	{
	    fprint (fh, "/* Function ID's */\n", NULL);
	    fprint (fh, "enum\n{\n    Dummy = APSH_USER_ID,\n\n", NULL);
	    fprint (fh, "    Open%sID,\n", (LONG) dr->dr_BaseName);
	    fprint (fh, "    %sWinOpenID,\n", (LONG) dr->dr_BaseName);
	    fprint (fh, "    %sWinCloseID,\n", (LONG) dr->dr_BaseName);
	}

	if (name && (strlen (name) > 0))
	{
	    /* Print the enum name */
	    fprint (fh, "    %sID,\n", (LONG) name);
	}
    }
}

static VOID dumpproto (struct FuncsNode * fn, ULONG cnt, struct DumpRec * dr)
{
    if (fn)
    {
	STRPTR name = fn->fn_Func.fe_Name;
	BPTR fh = dr->dr_FH;

	/* First text item? */
	if (cnt == 0)
	{
	    fprint (fh, "/* Function prototypes */\n", NULL);
	    fprint (fh, "VOID Open%sFunc(struct AppInfo *, STRPTR, struct TagItem *);\n", (LONG) dr->dr_BaseName);
	    fprint (fh, "VOID %sWinOpenFunc(struct AppInfo *, STRPTR, struct TagItem *);\n", (LONG) dr->dr_BaseName);
	    fprint (fh, "VOID %sWinCloseFunc(struct AppInfo *, STRPTR, struct TagItem *);\n", (LONG) dr->dr_BaseName);
	}

	if (name && (strlen (name) > 0))
	{
	    fprint (fh, "VOID %sFunc(struct AppInfo *, STRPTR, struct TagItem *);\n", (LONG) name);
	}
    }
}

static VOID dumpfunc (struct FuncsNode * fn, ULONG cnt, struct DumpRec * dr)
{
    if (fn)
    {
	STRPTR name = fn->fn_Func.fe_Name;
	struct ObjectNode *on = fn->fn_Obj;
	BPTR fh = dr->dr_FH;
	ULONG type = 0;

	if (on)
	{
	    type = on->on_Object.o_Type;
	}
	else
	{
	    type = (ULONG) fn->fn_Func.fe_GroupID;
	}

	/* First text item? */
	if (cnt == 0)
	{
	    fprint (fh, "/* Function table */\n", NULL);
	    fprint (fh, "struct Funcs app_funcs[] =\n{\n", NULL);
	    fprint (fh, "    {\"Open%s\", Open%sFunc, Open%sID, \",\", 0, },\n", dr->dr_BaseName, dr->dr_BaseName, dr->dr_BaseName);
	    fprint (fh, "    {\"%sWinOpen\", %sWinOpenFunc, %sWinOpenID, \",\", 0, APSHF_PRIVATE, },\n", dr->dr_BaseName, dr->dr_BaseName, dr->dr_BaseName);
	    fprint (fh, "    {\"%sWinClose\", %sWinCloseFunc, %sWinCloseID, \",\", 0, APSHF_PRIVATE, },\n", dr->dr_BaseName, dr->dr_BaseName, dr->dr_BaseName);
	}

	if (name && (strlen (name) > 0))
	{
	    fprint (fh, "    {\"%s\", %sFunc, %sID,", name, name, name);

	    switch (type)
	    {
		case OBJ_Checkbox:
		    fprint (fh, " \"OFF/S\", 1, },\n", NULL);
		    break;

		case OBJ_Integer:
		case OBJ_Number:
		case OBJ_DirNumeric:
		    fprint (fh, " \"NUM/N\", 1, },\n", NULL);
		    break;

		case OBJ_Listview:
		    fprint (fh, " \"ACTIVE/N,TOP/K/N\", 2, },\n", NULL);
		    break;

		case OBJ_MX:
		case OBJ_Cycle:
		    fprint (fh, " \"ACTIVE/N\", 1, },\n", NULL);
		    break;

		case OBJ_Palette:
		    fprint (fh, " \"COLOR/N\", 1, },\n", NULL);
		    break;

		case OBJ_Scroller:
		    fprint (fh, " \"TOP/N,TOTAL/K/N,VISIBLE/K/N\", 3, },\n", NULL);
		    break;

		case OBJ_Slider:
		    fprint (fh, " \"LEVEL/N,MIN/K/N,MAX/K/N\", 3, },\n", NULL);
		    break;

		case OBJ_String:
		case OBJ_Text:
		case OBJ_DirString:
		case OBJ_MultiText:
		    fprint (fh, " \"TEXT\", 1, },\n", NULL);
		    break;

		case OBJ_Button:
		case OBJ_Display:
		case OBJ_Select:
		default:
		    fprint (fh, " \",\", 0, },\n", NULL);
		    break;
	    }
	}
    }
}

static VOID makeappdata (struct FuncsNode * fn, ULONG cnt, struct DumpRec * dr)
{
    struct TagItem *attrs = NULL;
    STRPTR name = NULL;
    LONG num;

    if (fn)
    {
	struct ObjectNode *on = fn->fn_Obj;
	BPTR fh = dr->dr_FH;
	ULONG type = 0;

	/* First text item? */
	if (cnt == 0)
	{
	    fprint (fh, "/* Application Data */\n", NULL);
	    fprint (fh, "struct AppData\n{\n", NULL);
	}

	if (on)
	{
	    attrs = on->on_OTags;
	    type = on->on_Object.o_Type;
	    name = on->on_Object.o_Name;
	}
	else
	{
	    type = (ULONG) fn->fn_Func.fe_GroupID;
	    name = fn->fn_Func.fe_Name;
	}

	/* See if we're attached to a gadget */
	if (name && (strlen (name) > 0))
	{
	    switch (type)
	    {
		case OBJ_Button:
		case OBJ_Display:
		case OBJ_Select:
		    break;

		case OBJ_Checkbox:
		    fprint (fh, "    BOOL ad_%s;\n", name);
		    break;

		case OBJ_Integer:
		case OBJ_Number:
		case OBJ_DirNumeric:
		    fprint (fh, "    LONG ad_%s;\n", name);
		    break;

		case OBJ_Listview:
		    fprint (fh, "    struct List ad_%sList;\n", name);
		    fprint (fh, "    ULONG ad_%s;\n", name);
		    break;

		    break;

		case OBJ_MX:
		case OBJ_Cycle:
		case OBJ_Palette:
		case OBJ_Scroller:
		case OBJ_Slider:
		    fprint (fh, "    UWORD ad_%s;\n", name);
		    break;

		case OBJ_String:
		case OBJ_Text:
		case OBJ_DirString:
		    num = GetTagData (GTST_MaxChars, 10, attrs);
		    fprint (fh, "    UBYTE ad_%s[%ld];\n", name, num);
		    break;

		case OBJ_Dropbox:
		    break;

		case OBJ_GImage:
		    break;

		case OBJ_MultiText:
		    num = GetTagData (STRINGA_MaxChars, 10, attrs);
		    fprint (fh, "    UBYTE ad_%s[%ld];\n", name, num);
		    break;
	    }
	}
    }
}

STRPTR openfunc_arg[] =
{
    "{\n",
    "    struct AppData *ad = (struct AppData *) ai->ai_UserData;\n",
    "\n",
    "    /* Open the window */\n",
    "    HandlerFunc (ai,\n",
    "		 APSH_Handler, \"IDCMP\",\n",
    "		 APSH_Command, APSH_MH_OPEN,\n",
    "		 APSH_WindowEnv, (ULONG) WINDOW_ENV,\n",
    "		 TAG_DONE);\n",
    "}\n\n",
    NULL
};

STRPTR wopenfunc_arg[] =
{
    "{\n",
    "    struct AppData *ad = (struct AppData *) ai->ai_UserData;\n",
    "\n",
    "    /* This gets called after the window is opened */\n",
    "}\n\n",
    NULL
};

STRPTR wclosefunc_arg[] =
{
    "{\n",
    "    struct AppData *ad = (struct AppData *) ai->ai_UserData;\n",
    "\n",
    "    /* This gets called before the window is closed */\n",
    "}\n\n",
    NULL
};

VOID print_array (BPTR fh, STRPTR * array)
{
    WORD i = 0;

    while (array[i])
    {
	fprint (fh, array[i++], NULL);
    }
}

static VOID makefunc (struct FuncsNode * fn, ULONG cnt, struct DumpRec * dr)
{
    STRPTR name = NULL;

    if (fn)
    {
	BPTR fh = dr->dr_FH;
	struct ObjectNode *on = fn->fn_Obj;
	struct TagItem *attrs = NULL;
	STRPTR dname = NULL;
	ULONG type = 0;

	if (on)
	{
	    attrs = on->on_OTags;
	    type = on->on_Object.o_Type;
	    dname = on->on_Object.o_Name;
	}
	else
	{
	    type = (ULONG) fn->fn_Func.fe_GroupID;
	    dname = fn->fn_Func.fe_Name;
	}

	/* First text item? */
	if (cnt == 0)
	{
	    fprint (fh, "VOID Open%sFunc(struct AppInfo *ai, STRPTR cmd, struct TagItem *attrs)\n", dr->dr_BaseName);
	    print_array (fh, openfunc_arg);

	    fprint (fh, "VOID %sWinOpenFunc(struct AppInfo *ai, STRPTR cmd, struct TagItem *attrs)\n", dr->dr_BaseName);
	    print_array (fh, wopenfunc_arg);

	    fprint (fh, "VOID %sWinCloseFunc(struct AppInfo *ai, STRPTR cmd, struct TagItem *attrs)\n", dr->dr_BaseName);
	    print_array (fh, wclosefunc_arg);
	}

/* Decode argument types */

	/* See if we're attached to a gadget */
	if ((name = fn->fn_Func.fe_Name) && (strlen (name) > 0) && (type > 0))
	{
	    WORD ngad = 0;

	    /* See if we need gadget refresh... */
	    switch (type)
	    {
		case OBJ_Integer:
		case OBJ_Number:
		case OBJ_DirNumeric:
		case OBJ_String:
		case OBJ_DirString:
		case OBJ_MultiText:
		    ngad = 1;
		    break;

		case OBJ_Checkbox:
		case OBJ_MX:
		case OBJ_Cycle:
		case OBJ_Palette:
		case OBJ_Scroller:
		case OBJ_Slider:
		    ngad = 2;
		    break;
	    }

	    fprint (fh, "VOID %sFunc(struct AppInfo *ai, STRPTR cmd, struct TagItem *attrs)\n", name);
	    fprint (fh, "{\n", NULL);
	    fprint (fh, "    struct AppData *ad = (struct AppData *) ai->ai_UserData;\n", NULL);

	    /* Declare the variables needed for gadget refresh */
	    if (ngad)
	    {
		/* Got to pull something from the msg->Code field */
		if (ngad == 2)
		{
		    fprint (fh, "    struct TagItem *tag;\n", NULL);
		}
		else
		{
		    fprint (fh, "    BOOL update = FALSE;\n", NULL);
		}

		fprint (fh, "    struct Window *win;\n", NULL);
		fprint (fh, "    struct Gadget *gad;\n", NULL);
	    }

	    fprint (fh, "    struct Funcs *f;\n", NULL);
	    fprint (fh, "\n", NULL);
	    fprint (fh, "    /* See if we have preparsed command line. */\n", NULL);
	    fprint (fh, "    if (f = (struct Funcs *) GetTagData (APSH_FuncEntry, NULL, attrs))\n", NULL);
	    fprint (fh, "    {\n", NULL);

	    /* Get the parsed variable */
	    switch (type)
	    {
		case OBJ_Checkbox:
		    fprint (fh, "	/* Get a boolean option */\n", NULL);
		    fprint (fh, "	ad->ad_%s = (BOOL) (f->fe_Options[0]) ? FALSE : TRUE;\n", dname);
		    break;

		case OBJ_Integer:
		case OBJ_Number:
		case OBJ_DirNumeric:

		case OBJ_MX:
		case OBJ_Cycle:
		case OBJ_Palette:
		case OBJ_Scroller:
		case OBJ_Slider:
		    fprint (fh, "	/* Get a numeric option */\n", NULL);
		    fprint (fh, "	ad->ad_%s = *((LONG *) f->fe_Options[0]);\n", dname);
		    break;

		case OBJ_String:
		case OBJ_DirString:
		case OBJ_MultiText:
		    fprint (fh, "	/* Get a text option */\n", NULL);
		    fprint (fh, "	strcpy (ad->ad_%s, (STRPTR) f->fe_Options[0]);\n", dname);
		    break;
	    }

	    /* Show that an update is needed */
	    if (ngad)
	    {
		STRPTR tv = "TAG_IGNORE";

		if (ngad == 2)
		{
		    fprint (fh, "\n	/* Get the gadget information */\n", NULL);
		    fprint (fh, "	if (APSHGetGadgetInfo (ai, \"%s\", \"%s\",\n", dr->dr_BaseName, dname);
		    fprint (fh, "			       (ULONG *)&win, (ULONG *)&gad))\n", NULL);
		    fprint (fh, "	{\n", NULL);
		    if (type == OBJ_Scroller)
		    {
			fprint (fh, "	    SetGadgetAttrs (gad, win, NULL,\n", NULL);
		    }
		    else
		    {
			fprint (fh, "	    GT_SetGadgetAttrs (gad, win, NULL,\n", NULL);
		    }

		    switch (type)
		    {
			case OBJ_Checkbox:
			     tv = "GTCB_Checked";
			     break;

			case OBJ_MX:
			     tv = "GTMX_Active";
			     break;

			case OBJ_Cycle:
			     tv = "GTCY_Active";
			     break;

			case OBJ_Palette:
			     tv = "GTPA_Color";
			     break;

			case OBJ_Scroller:
			     tv = "GTSC_Top";
			     break;

			case OBJ_Slider:
			     tv = "GTSL_Level";
			     break;
		    }

		    fprint (fh, "			    %s, ad->ad_%s,\n", tv, dname);
		    fprint (fh, "			    TAG_DONE);\n", NULL);
		    fprint (fh, "	}\n", NULL);
		}
		else
		{
		    fprint (fh, "\n	/* Indicate that gadget needs to be refreshed */\n", NULL);
		    fprint (fh, "	update = TRUE;\n", NULL);
		}
	    }

	    fprint (fh, "    }\n", NULL);

/* Where do we get the parameters */

	    /* Do we need to get a gadget... */
	    if (ngad == 1)
	    {
		fprint (fh, "\n", NULL);
		fprint (fh, "    /* Get the gadget information */\n", NULL);
		fprint (fh, "    if (APSHGetGadgetInfo (ai, \"%s\", \"%s\",\n", dr->dr_BaseName, dname);
		fprint (fh, "			       (ULONG *) & win, (ULONG *) & gad))\n", NULL);
		fprint (fh, "    {\n", NULL);
	    }

	    switch (type)
	    {
		case OBJ_Integer:
		case OBJ_DirNumeric:
		    fprint (fh, "	if (update)\n", NULL);
		    fprint (fh, "	{\n", NULL);
		    fprint (fh, "	    /* Update the numeric gadget if there is one */\n", NULL);
		    fprint (fh, "	    GT_SetGadgetAttrs (gad, win, NULL,\n", NULL);
		    fprint (fh, "			       GTIN_Number, (ULONG) ad->ad_%s,\n", dname);
		    fprint (fh, "			       TAG_DONE);\n", NULL);
		    fprint (fh, "	}\n", NULL);
		    fprint (fh, "	else\n", NULL);
		    fprint (fh, "	{\n", NULL);
		    fprint (fh, "	    ad->ad_%s = ((struct StringInfo *) gad->SpecialInfo)->LongInt;\n", dname);
		    fprint (fh, "	}\n", NULL);
		    break;

		case OBJ_String:
		case OBJ_DirString:
		    fprint (fh, "	if (update)\n", NULL);
		    fprint (fh, "	{\n", NULL);
		    fprint (fh, "	    /* Update the string gadget if there is one */\n", NULL);
		    fprint (fh, "	    GT_SetGadgetAttrs (gad, win, NULL,\n", NULL);
		    fprint (fh, "			       GTST_String, (ULONG) ad->ad_%s,\n", dname);
		    fprint (fh, "			       TAG_DONE);\n", NULL);
		    fprint (fh, "	}\n", NULL);
		    fprint (fh, "	else\n", NULL);
		    fprint (fh, "	{\n", NULL);
		    fprint (fh, "	    strcpy (ad->ad_%s, (STRPTR) ((struct StringInfo *) gad->SpecialInfo)->Buffer);\n", dname);
		    fprint (fh, "	}\n", NULL);
		    break;

		case OBJ_MultiText:
		    fprint (fh, "	if (update)\n", NULL);
		    fprint (fh, "	{\n", NULL);
		    fprint (fh, "	    /* Update the multiline text gadget if there is one */\n", NULL);
		    fprint (fh, "	    SetGadgetAttrs (gad, win, NULL,\n", NULL);
		    fprint (fh, "			    STRINGA_TextVal, ad->ad_%s,\n", dname);
		    fprint (fh, "			    TAG_DONE);\n", NULL);
		    fprint (fh, "	}\n", NULL);
		    fprint (fh, "	else\n", NULL);
		    fprint (fh, "	{\n", NULL);
		    fprint (fh, "	    strcpy (ad->ad_%s, (STRPTR) ((struct StringInfo *) gad->SpecialInfo)->Buffer);\n", dname);
		    fprint (fh, "	}\n", NULL);
		    break;

/* NOT DONE YET */

		case OBJ_Listview:
		    fprint (fh, "    else\n", NULL);
		    fprint (fh, "    {\n", NULL);
		    fprint (fh, "	struct List *list = &(ad->ad_%sList);\n", dname);
		    fprint (fh, "	struct TagItem *tag;\n", NULL);
		    fprint (fh, "	struct Node *node;\n", NULL);
		    fprint (fh, "\n", NULL);
		    fprint (fh, "	/* Find the selected item in a list */\n", NULL);
		    fprint (fh, "	if (tag = FindTagItem (APSH_MsgCode, attrs))\n", NULL);
		    fprint (fh, "	{\n", NULL);
		    fprint (fh, "	    /* Which line was selected */\n", NULL);
		    fprint (fh, "	    ad->ad_%s = (WORD) tag->ti_Data;\n", dname);
		    fprint (fh, "\n", NULL);
		    fprint (fh, "	    /* Locate the corresponding node in the list */\n", NULL);
		    fprint (fh, "	    if (node = FindSelected (list, ad->ad_%s))\n", dname);
		    fprint (fh, "	    {\n", NULL);
		    fprint (fh, "		/* Use the node... */\n", NULL);
		    fprint (fh, "	    }\n", NULL);
		    fprint (fh, "	}\n", NULL);
		    fprint (fh, "    }\n", NULL);
		    break;

		case OBJ_Checkbox:
		case OBJ_MX:
		case OBJ_Cycle:
		case OBJ_Palette:
		case OBJ_Scroller:
		case OBJ_Slider:
		    fprint (fh, "    else if (tag = FindTagItem (APSH_MsgCode, attrs))\n", NULL);
		    fprint (fh, "    {\n", NULL);
		    fprint (fh, "	ad->ad_%s = (UWORD) tag->ti_Data;\n", dname);
		    fprint (fh, "    }\n", NULL);
		    break;
	    }

	    /* Do we need to end the get gadget... */
	    if (ngad == 1)
	    {
		fprint (fh, "    }\n", NULL);
	    }

	    fprint (fh, "}\n\n", NULL);
	}
    }
}

static VOID dumptext (struct ObjectNode * on, ULONG cnt, struct DumpRec * dr)
{
    if (on)
    {
	struct ObjectInfo *oi = dr->dr_OI;
	struct Object *o = &(on->on_Object);
	STRPTR *text = oi->oi_TextTable;
	BPTR fh = dr->dr_FH;

	/* First text item? */
	if (cnt == 0)
	{
	    fprint (fh, "STRPTR %s_deftext[] =\n{\n    \"\",\n", dr->dr_BaseName);
	}

	/* Do we have tags? */
	if (o->o_LabelID)
	{
	    fprint (fh, "    \"%s\",\n", text[o->o_LabelID]);
	}

	/* Is there an object after this one? */
	if (o->o_NextObject == NULL)
	{
	    fprint (fh, "    NULL\n};\n\n", NULL);
	}
    }
}

static VOID ImageToC (BPTR fh, STRPTR name, struct Image * i)
{
    int w, h, d, c, t, cp;
    register int j, k;
    USHORT *data;

    /* Image data portion */
    fprint (fh, "UWORD chip %s_idata[] =\n{\n", name);
    w = i->Width;
    h = i->Height;
    d = i->Depth;
    c = ((w + 15) / 16) * h;
    cp = 0;
    data = i->ImageData;
    for (k = 0; k < d; k++)
    {
	if (k > 0)
	    fprint (fh, "\n", NULL);
	fprint (fh, "/* Plane %ld */\n    ", (LONG) k);
	t = 0;
	for (j = 0; j < c; j++)
	{
	    if (t > 7)
	    {
		fprint (fh, "\n    ", NULL);
		t = 0;
	    }
	    t++;
	    fprint (fh, "0x%04lx,", (LONG) data[cp++]);
	}
    }
    fprint (fh, "\n};\n\n", NULL);

    /* Image structure portion */
    fprint (fh, "static struct Image %s_data =\n{\n", name);
    fprint (fh, "    %ld, %ld,			/* Upper left corner */\n",
	    (LONG) i->LeftEdge, (LONG) i->TopEdge);
    fprint (fh, "    %ld, %ld, %ld,			/* Width, Height, Depth */\n",
	    (LONG) w, (LONG) h, (LONG) d);
    fprint (fh, "    %s_idata,		/* Image data */\n", name);
    fprint (fh, "    0x%04lx, 0x%04lx,		/* PlanePick, PlaneOnOff */\n",
	    (LONG) i->PlanePick, (LONG) i->PlaneOnOff);
    fprint (fh, "    NULL			/* Next image */\n", NULL);
    fprint (fh, "};\n\n", NULL);
}

static VOID dumplist (struct Node * n, ULONG cnt, struct PrintRec * pr)
{
    BPTR fh = pr->pr_FH;

    fprint (fh, "    \"%s\",\n", n->ln_Name);
}

static VOID printtagdata (BPTR fh, STRPTR name, ULONG t, struct TagItem * tl)
{
    struct TagItem *tags = tl;
    struct TagItem *tag;
    ULONG td, tv;

    while (tag = NextTagItem (&tags))
    {
	tv = tag->ti_Tag;
	td = tag->ti_Data;

	if (tv == GTLV_Labels)
	{
	    fprint (fh, "static STRPTR %s_data[] =\n{\n", name);

	    /* Find the base name of the environment */
	    HandleList ((struct List *) td, dumplist, fh);

	    fprint (fh, "    NULL\n};\n\n", NULL);
	}
	else if ((tv == GTCY_Labels) || (tv == GTMX_Labels))
	{
	    STRPTR *text = (STRPTR *) td;
	    WORD i = 0;

	    fprint (fh, "static STRPTR %s_data[] =\n{\n", name);

	    while (text[i])
	    {
		fprint (fh, "    \"%s\",\n", text[i]);
		i++;
	    }

	    fprint (fh, "    NULL\n};\n\n", NULL);
	}
	else if (tv == APSH_ObjData)
	{
	    ImageToC (fh, name, (struct Image *) td);
	}
    }
}

STRPTR wintags[] =
{
    "APSH_WindowEnv",
    "APSH_TextAttr",
    "APSH_NewScreen",
    "APSH_NewScreenTags",
    "APSH_Palette",
    "APSH_NewWindow",
    "APSH_NewWindowTags",
    "APSH_HotKeys",
    "APSH_Menu",
    "APSH_Gadgets",
    "APSH_GTMenu",
    "APSH_GTGadgets",
    "APSH_GTFlags",
    "APSH_Objects",
    "APSH_ObjDown",
    "APSH_ObjHold",
    "APSH_ObjRelease",
    "APSH_ObjDblClick",
    "APSH_ObjAbort",
    "APSH_ObjAltHit",
    "APSH_ObjShiftHit",
    "APSH_ObjData",
    "APSH_ObjInner",
    "APSH_ObjPointer",
    "APSH_DefWinFlags",
    "APSH_ObjName",
    "APSH_WinName",
    NULL,
    "APSH_WinPointer",
    "APSH_ShowSelected",
    "APSH_Screen",
    "APSH_ObjExtraRelease",
    "APSH_ObjAltData",
    "APSH_ParentWindow",
    "APSH_TTMenu",
    NULL
};

STRPTR gadtool1[] =
{
    "GTVI_NewWindow",
    "GTVI_NWTags",
    "GT_Private0",
    "GTCB_Checked",
    "GTLV_Top",
    "GTLV_Labels",
    "GTLV_ReadOnly",
    "GTLV_ScrollWidth",
    "GTMX_Labels",
    "GTMX_Active",
    "GTTX_Text",
    "GTTX_CopyText",
    "GTNM_Number",
    "GTCY_Labels",
    "GTCY_Active",
    "GTPA_Depth",
    "GTPA_Color",
    "GTPA_ColorOffset   ",
    "GTPA_IndicatorWidth",
    "GTPA_IndicatorHeigh",
    "GTSC_Top",
    "GTSC_Total",
    "GTSC_Visible",
    "GTSC_Overlap",
    NULL
};

STRPTR gadtool2[] =
{
    "GTSL_Min",
    "GTSL_Max",
    "GTSL_Level",
    "GTSL_MaxLevelLen",
    "GTSL_LevelFormat",
    "GTSL_LevelPlace",
    "GTSL_DispFunc",
    "GTST_String",
    "GTST_MaxChars",
    "GTIN_Number",
    "GTIN_MaxChars",
    "GTMN_TextAttr",
    "GTMN_FrontPen",
    "GTBB_Recessed",
    "GT_VisualInfo",
    "GTLV_ShowSelected",
    "GTLV_Selected",
    "GT_Reserved0",
    "GT_Reserved1",
    "GTTX_Border",
    "GTNM_Border",
    "GTSC_Arrows",
    "GTMN_Menu",
    "GTMX_Spacing",
    NULL
};

STRPTR appobject1[] =
{
    "CGTA_reserved1",
    "CGTA_reserved2",
    "CGTA_HighPens",
    "CGTA_NextField",
    "CGTA_PrevField",
    "CGTA_Total",
    "CGTA_Visible",
    "CGTA_Top",
    "CGTA_List",
    NULL
};

STRPTR appobject2[] =
{
    "CGTA_Increment",
    "CGTA_Decrement",
    NULL
};

STRPTR appobject3[] =
{
    "CGTA_LabelInfo",
    "CGTA_Keystroke",
    "CGTA_Borderless",
    "CGTA_DisplayOnly",
    "CGTA_MinWidth",
    "CGTA_MinHeight",
    "CGTA_MaxWidth",
    "CGTA_MaxHeight",
    "CGTA_FrameInfo",
    "CGTA_Constraint",
    "CGTA_Nominal",
    "CGTA_TextAttr",
    "CGTA_Master",
    "CGTA_Transparent",
    "CGTA_InBorder",
    NULL
};

STRPTR intui1[] =
{
    "GA_LEFT",
    "GA_RELRIGHT",
    "GA_TOP",
    "GA_RELBOTTOM",
    "GA_WIDTH",
    "GA_RELWIDTH",
    "GA_HEIGHT",
    "GA_RELHEIGHT",
    "GA_TEXT",
    "GA_IMAGE",
    "GA_BORDER",
    "GA_SELECTRENDE",
    "GA_HIGHLIGHT",
    "GA_DISABLED",
    "GA_GZZGADGET",
    "GA_ID",
    "GA_USERDATA",
    "GA_SPECIALINFO",
    "GA_SELECTED",
    "GA_ENDGADGET",
    "GA_IMMEDIATE",
    "GA_RELVERIFY",
    "GA_FOLLOWMOUSE",
    "GA_RIGHTBORDER",
    "GA_LEFTBORDER",
    "GA_TOPBORDER",
    "GA_BOTTOMBORDER",
    "GA_TOGGLESELECT",
    "GA_SYSGADGET",
    "GA_SYSGTYPE",
    "GA_PREVIOUS",
    "GA_NEXT",
    "GA_DRAWINFO",
    "GA_INTUITEXT",
    "GA_LABELIMAGE",
    NULL
};

STRPTR intui2[] =
{
    "PGA_FREEDOM",
    "PGA_BORDERLESS",
    "PGA_HORIZPOT",
    "PGA_HORIZBODY",
    "PGA_VERTPOT",
    "PGA_VERTBODY",
    "PGA_TOTAL",
    "PGA_VISIBLE",
    "PGA_TOP",
    NULL
};

STRPTR intui3[] =
{
    "STRINGA_MaxChars",
    "STRINGA_Buffer",
    "STRINGA_UndoBuffer",
    "STRINGA_WorkBuffer",
    "STRINGA_BufferPos",
    "STRINGA_DispPos",
    "STRINGA_AltKeyMap",
    "STRINGA_Font",
    "STRINGA_Pens",
    "STRINGA_ActivePens",
    "STRINGA_EditHook",
    "STRINGA_EditModes",
    "STRINGA_ReplaceMode",
    "STRINGA_FixedFieldMode",
    "STRINGA_NoFilterMode",
    "STRINGA_Justification",
    "STRINGA_LongVal",
    "STRINGA_TextVal",
    NULL
};

STRPTR intui4[] =
{
    "WA_Left",
    "WA_Top",
    "WA_Width",
    "WA_Height",
    "WA_DetailPen",
    "WA_BlockPen",
    "WA_IDCMP",
    "WA_Flags",
    "WA_Gadgets",
    "WA_Checkmark",
    "WA_Title",
    "WA_ScreenTitle",
    "WA_CustomScreen",
    "WA_SuperBitMap",
    "WA_MinWidth",
    "WA_MinHeight",
    "WA_MaxWidth",
    "WA_MaxHeight",
    "WA_InnerWidth",
    "WA_InnerHeight",
    "WA_PubScreenName",
    "WA_PubScreen",
    "WA_PubScreenFallBack",
    "WA_WindowName",
    "WA_Colors",
    "WA_Zoom",
    "WA_MouseQueue",
    "WA_BackFill",
    "WA_RptQueue",
    "WA_SizeGadget",
    "WA_DragBar",
    "WA_DepthGadget",
    "WA_CloseGadget",
    "WA_Backdrop",
    "WA_ReportMouse",
    "WA_NoCareRefresh",
    "WA_Borderless",
    "WA_Activate",
    "WA_RMBTrap",
    "WA_WBenchWindow",
    "WA_SimpleRefresh",
    "WA_SmartRefresh",
    "WA_SizeBRight",
    "WA_SizeBBottom",
    "WA_AutoAdjust",
    "WA_GimmeZeroZero",
    NULL
};


STRPTR objname1[] =		/* 1 - 14 */
{
 /* GadTools gadgets */
    "OBJ_Generic",
    "OBJ_Button",
    "OBJ_Checkbox",
    "OBJ_Integer",
    "OBJ_Listview",
    "OBJ_MX",
    "OBJ_Number",
    "OBJ_Cycle",
    "OBJ_Palette",
    "OBJ_Scroller",
    "OBJ_reserved1",
    "OBJ_Slider",
    "OBJ_String",
    "OBJ_Text",
    NULL
};

STRPTR objname2[] =		/* 30 - 38 */
{
 /* other gadgets */
    "OBJ_Display",
    "OBJ_Select",
    "OBJ_Dropbox",
    "OBJ_GImage",
    "OBJ_MultiText",
    "OBJ_reserved2",
    "OBJ_DirString",
    "OBJ_DirNumeric",
    "OBJ_boopsi",
    NULL
};

STRPTR objname3[] =		/* 50 */
{
 /* images */
    "OBJ_Image",
    NULL
};

STRPTR objname4[] =		/* 60 - 64 */
{
 /* borders */
    "OBJ_reserved3",
    "OBJ_BevelIn",
    "OBJ_BevelOut",
    "OBJ_DblBevelIn",
    "OBJ_DblBevelOut",
};

STRPTR objname5[] =		/* 70 - 77 */
{
 /* other object types */
    "OBJ_Screen",
    "OBJ_Window",
    "OBJ_Group",
    "OBJ_VFill",
    "OBJ_HFill",
    "OBJ_VGroup",
    "OBJ_HGroup",
    "OBJ_MGroup",
};

/* a flag parsing method... convert Flag to Text */
struct ulongFlags
{
    ULONG uf_Flag;
    UBYTE *uf_Text;
};

struct ulongFlags GadToolsFlags[] =
{
    {0x0001, "PLACETEXT_LEFT"},
    {0x0002, "PLACETEXT_RIGHT"},
    {0x0004, "PLACETEXT_ABOVE"},
    {0x0008, "PLACETEXT_BELOW"},
    {0x0010, "PLACETEXT_IN"},
    {0x0020, "NG_HIGHLABEL"},
    {0x0040, "PLACETEXT_ABOVEC"},
    {0x0080, "PLACETEXT_ABOVEI"},
    {0x0100, "PLACETEXT_BELOWI"},
    {0x0200, "PLACETEXT_BELOWC"},
    {0, NULL}
};

struct ulongFlags ObjectFlags[] =
{
    {(1L << 0), "APSH_OBJF_ACTIVATE"},
    {(1L << 1), "APSH_OBJF_CLOSEWINDOW"},
    {(1L << 2), "APSH_OBJF_NOADJUST"},
    {0, NULL}
};

static VOID printFlags (BPTR fh, UBYTE * name, SHORT lvl, UBYTE * pref)
{
    static SHORT tlen = 0;

    if (lvl > 0)
    {
	if (tlen > 40)
	{
	    fprint (fh, "\n%s", pref);
	    tlen = 0;
	}
	fprint (fh, " | %s", name);
    }
    else
    {
	tlen = 0;
	fprint (fh, "%s", name);
    }
    tlen += strlen (name);
}

static VOID parseFlags (BPTR fh, ULONG flags, struct ulongFlags * uf,
			 UBYTE * pref, UBYTE * sufx)
{
    USHORT j = 0;

    fprint (fh, "%s", pref);
    do
    {
	if (flags & uf->uf_Flag)
	{
	    printFlags (fh, uf->uf_Text, j++, pref);
	    flags &= ~uf->uf_Flag;	/* strip out used flags */
	}
	*uf++;
    } while (uf->uf_Text);

    if (j == 0)
    {
	if (flags == 0L)
	    fprint (fh, "NULL", NULL);
	else
	    fprint (fh, "0x0%lx", (LONG) flags);
    }
    else if (flags > 0L)
    {
	/* print out leftover flags */
	fprint (fh, " | 0x0%lx", (LONG) flags);
    }
    fprint (fh, "%s", sufx);
}

static VOID printtags (BPTR fh, STRPTR name, ULONG t, struct TagItem * tl)
{
    struct TagItem *tags = tl;
    struct TagItem *tag;
    ULONG td, tv;

    while (tag = NextTagItem (&tags))
    {
	td = tag->ti_Data;
	tv = tag->ti_Tag;

	if (tv == APSH_ObjName)
	{
	    fprint (fh, "    {APSH_ObjName, (ULONG) \"%s\"},\n", td);
	}
	else if (tv == APSH_WinName)
	{
	    fprint (fh, "    {APSH_WinName, (ULONG) \"%s\"},\n", td);
	}
	else if (tv == APSH_ShowSelected)
	{
	    fprint (fh, "    {APSH_ShowSelected, (ULONG) \"%s\"},\n", td);
	}
	else if (tv == GTLV_Labels)
	{
	    fprint (fh, "    {GTLV_Labels, (ULONG) %s_data},\n", name);
	}
	else if (tv == GTCY_Labels)
	{
	    fprint (fh, "    {GTCY_Labels, (ULONG) %s_data},\n", name);
	}
	else if (tv == GTMX_Labels)
	{
	    fprint (fh, "    {GTMX_Labels, (ULONG) %s_data},\n", name);
	}
	else if (tv == APSH_ObjData)
	{
	    fprint (fh, "    {APSH_ObjData, (ULONG) &%s_data},\n", name);
	}
	else if (tv == APSH_GTFlags)
	{
	    parseFlags (fh, (ULONG) td, &GadToolsFlags[0],
			"    {APSH_GTFlags, ", "},\n");

	}
	else if ((tv >= APSH_WindowEnv) && (tv <= APSH_TTMenu))
	{
	    tv -= APSH_WindowEnv;
	    fprint (fh, "    {%s, %ld},\n", wintags[tv], td);
	}
	else if ((tv >= GTVI_NewWindow) && (tv <= GTSC_Overlap))
	{
	    tv -= GTVI_NewWindow;
	    fprint (fh, "    {%s, %ld},\n", gadtool1[tv], td);
	}
	else if ((tv >= GTSL_Min) && (tv <= GTMX_Spacing))
	{
	    tv -= GTSL_Min;
	    fprint (fh, "    {%s, %ld},\n", gadtool2[tv], td);
	}
	else if ((tv >= CGTA_reserved1) && (tv <= CGTA_List))
	{
	    tv -= CGTA_reserved1;
	    fprint (fh, "    {%s, %ld},\n", appobject1[tv], td);
	}
	else if ((tv >= CGTA_Increment) && (tv <= CGTA_Decrement))
	{
	    tv -= CGTA_Increment;
	    fprint (fh, "    {%s, %ld},\n", appobject2[tv], td);
	}
	else if ((tv >= CGTA_LabelInfo) && (tv <= CGTA_InBorder))
	{
	    tv -= CGTA_LabelInfo;
	    fprint (fh, "    {%s, %ld},\n", appobject3[tv], td);
	}
	else if ((tv >= GA_LEFT) && (tv <= GA_LABELIMAGE))
	{
	    tv -= GA_LEFT;
	    fprint (fh, "    {%s, %ld},\n", intui1[tv], td);
	}
	else if ((tv >= PGA_FREEDOM) && (tv <= PGA_TOP))
	{
	    tv -= PGA_FREEDOM;
	    fprint (fh, "    {%s, %ld},\n", intui2[tv], td);
	}
	else if ((tv >= STRINGA_MaxChars) && (tv <= STRINGA_TextVal))
	{
	    tv -= STRINGA_MaxChars;
	    fprint (fh, "    {%s, %ld},\n", intui3[tv], td);
	}
	else if ((tv >= WA_Left) && (tv <= WA_GimmeZeroZero))
	{
	    tv -= WA_Left;
	    fprint (fh, "    {%s, %ld},\n", intui4[tv], td);
	}
	else if (tv == APSH_ObjIDHold)
	{
	    /* Don't print anything for this one. */
	}
	else
	{
	    fprint (fh, "    {0x%lx, %ld},\n", tv, td);
	}
    }

    fprint (fh, "    {TAG_DONE,}\n", NULL);
}

static BOOL anytags (struct TagItem * tl)
{
    struct TagItem *tags = tl;
    struct TagItem *tag;
    BOOL ret = FALSE;
    ULONG td, tv;

    if (tl)
    {
	while (tag = NextTagItem (&tags))
	{
	    td = tag->ti_Data;
	    tv = tag->ti_Tag;

	    if (tv == APSH_GTFlags)
	    {
		if (td)
		{
		    ret = TRUE;
		}
	    }
	    else if ((tv == TAG_DONE) || (tv == APSH_ObjIDHold))
	    {
	    }
	    else
	    {
		ret = TRUE;
	    }
	}
    }

    return (ret);
}

static VOID dumptagdata (struct ObjectNode * on, ULONG cnt, struct DumpRec * dr)
{

    if (on)
    {
	struct Object *o = &(on->on_Object);
	BPTR fh = dr->dr_FH;

	/* Do we have tags? */
	if (anytags (on->on_OTags))
	{
	    /* Dump the tags */
	    printtagdata (fh, o->o_Name, o->o_Type, on->on_OTags);
	}
    }
}

static VOID dumptags (struct ObjectNode * on, ULONG cnt, struct DumpRec * dr)
{

    if (on)
    {
	struct Object *o = &(on->on_Object);
	BPTR fh = dr->dr_FH;

	/* Do we have tags? */
	if (anytags (on->on_OTags))
	{
	    /* Dump the tags */
	    fprint (fh, "static struct TagItem %s_tags[] =\n", o->o_Name);
	    fprint (fh, "{\n", NULL);
	    printtags (fh, o->o_Name, o->o_Type, on->on_OTags);
	    fprint (fh, "};\n\n", NULL);
	}
    }
}

/* This is a lot like FindTextEntry() */
static struct FuncsNode *FindFuncsNode (struct List * list, ULONG id)
{
    struct Node *node, *nxtnode;
    struct FuncsNode *fn;
    struct Funcs *fe;
    ULONG cnt = 0L;

    if (list && id)
    {
	/* Make sure there are entries in the list */
	if (list->lh_TailPred != (struct Node *) list)
	{
	    /* Let's start at the very beginning... */
	    node = list->lh_Head;

	    /* Continue while there are still nodes */
	    while (nxtnode = node->ln_Succ)
	    {
		fn = (struct FuncsNode *) node;
		fe = &(fn->fn_Func);

		if (fe->fe_ID == id)
		{
		    return (fn);
		}

		/* Go on to the next node */
		node = nxtnode;
		cnt++;
	    }
	}
    }

    return (NULL);
}

static VOID dumpobject (struct ObjectNode * on, ULONG cnt, struct DumpRec * dr)
{

    if (on)
    {
	struct ObjectInfo *oi = dr->dr_OI;
	struct List *list = (struct List *) oi->oi_UserData;
	struct FuncsNode *fn;
	struct Object *o = &(on->on_Object);
	struct IBox *b = &(on->on_OBox);
	BPTR fh = dr->dr_FH;
	static ULONG textid;
	STRPTR name = NULL;
	LONG id;

	if (cnt == 0)
	{
	    fprint (fh, "struct Object %s[] =\n", dr->dr_BaseName);
	    fprint (fh, "{\n", NULL);
	    textid = 0L;
	}

	/* Is there an object after this one? */
	if (o->o_NextObject)
	{
	    fprint (fh, "    {&%s[%ld], ", dr->dr_BaseName, (cnt + 1L));
	}
	else
	{
	    fprint (fh, "    {NULL,   ", NULL);
	}

	fprint (fh, "%ld, %ld, ",
		(LONG) o->o_Group, (LONG) o->o_Priority);

	/* Print the #define name of the object */
	{
	    if ((o->o_Type >= 1) && (o->o_Type <= 14))
	    {
		name = objname1[(o->o_Type - 1)];
	    }
	    else if ((o->o_Type >= 30) && (o->o_Type <= 38))
	    {
		name = objname2[(o->o_Type - 30)];
	    }
	    else if ((o->o_Type >= 50) && (o->o_Type <= 50))
	    {
		name = objname3[(o->o_Type - 50)];
	    }
	    else if ((o->o_Type >= 60) && (o->o_Type <= 64))
	    {
		name = objname4[(o->o_Type - 60)];
	    }
	    else if ((o->o_Type >= 70) && (o->o_Type <= 77))
	    {
		name = objname5[(o->o_Type - 70)];
	    }

	    if (name)
	    {
		fprint (fh, "%s, ", name);
	    }
	    else
	    {
		fprint (fh, "NULL, ");
	    }
	}

	id = GetTagData (APSH_ObjIDHold, NULL, o->o_Tags);
	if ((fn = FindFuncsNode (list, id)) &&
	    (name = fn->fn_Func.fe_Name) &&
	    (strlen(name) > 0))
	{
	    fprint (fh, "%sID, ", fn->fn_Func.fe_Name);
	}
	else
	{
	    fprint (fh, "NULL, ", NULL);
	}

	if (o->o_Flags)
	{
	    parseFlags (fh, (ULONG) o->o_Flags, &ObjectFlags[0], "", ", ");
	}
	else
	{
	    fprint (fh, "NULL, ", NULL);
	}

	if (o->o_Key)
	{
	    fprint (fh, "'%lc', ", (LONG) o->o_Key);
	}
	else
	{
	    fprint (fh, "NULL, ", NULL);
	}

	if (o->o_Name)
	{
	    fprint (fh, "\"%s\", ", o->o_Name);
	}
	else
	{
	    fprint (fh, "NULL, ", NULL);
	}

	if (o->o_LabelID)
	{
	    textid++;
	    fprint (fh, "%ldL,\n", textid);
	}
	else
	{
	    fprint (fh, "NULL,\n", NULL);
	}

	/* Line 2 */
	fprint (fh, "     {%ld, %ld, %ld, %ld}, ",
	    (LONG) b->Left, (LONG) b->Top, (LONG) b->Width, (LONG) b->Height);

	/* Do we have tags? */
	if (anytags (on->on_OTags))
	{
	    /* Dump the tags */
	    fprint (fh, "%s_tags, ", o->o_Name);
	}

	/* Is there an object after this one? */
	if (o->o_NextObject == NULL)
	{
	    /* End the line */
	    fprint (fh, "},\n", NULL);

	    /* End of the array */
	    fprint (fh, "};\n\n", NULL);
	}
	else
	{
	    /* End the line */
	    fprint (fh, "},\n", NULL);

	    /* Get an extra blank in there... */
	    if (o->o_Type == OBJ_Window)
	    {
		fprint (fh, "\n", NULL);
	    }
	}
    }
}
