/*
 *  ICON2C.C
 */

#define VERSION "1.1"
static char versiontag[]= "$VER: $Id: icon2c.c,v 1.3 1994/07/17 22:41:02 tf Exp $";

/****** Icon2C ******************************************
*
*   NAME
*	Icon2C -- Generate C sourcecode from an icon image (V36)
*
*   SYNOPSIS
*	Icon2C NAME/A,QUIET/S,TO/K
*
*   FUNCTION
*	Icon2C reads in given ".info" file and writes out well documented
*	and directly compilable C code.  This code if compiled with a symbol
*	TEST defined (usual compiler option: -DTEST) will generate an
*	executable which writes back the icon image file to disk.  This
*	allows you to modify any icon image to your own needs.
*
*   INPUTS
*	NAME          - name of the icon image file.  A trailing ".info"
*			is optional but not required.
*	QUIET         - If this switch is set then Icon2C will not print any
*			warnings.
*	TO            - specifies the output file.  If not specified the
*			standard output stream will be used.
*
*   EXAMPLE
*	;generate C code for the disk icon of the disk in DF0:
*	icon2c df0:disk quiet to ram:diskicon.c
*
*   DISCLAIMER
*	This file is part of the Icon2C and OptIcon distribution.
*
*	Icon2C and OptIcon are free software; you can redistribute them
*	and/or modify them under the terms of the GNU General Public License
*	as published by the Free Software Foundation; either version 1 of
*	the License, or (at your option) any later version.
*
*	Icon2C and Opticon are distributed in the hope that they will be
*	useful, but WITHOUT ANY WARRANTY; without even the implied warranty
*	of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*	GNU General Public License for more details.
*
*	You should have received a copy of the GNU General Public License
*	along with these programs; see the file COPYING.  If not, write to
*	the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*   COPYRIGHT
*	Icon2C and OptIcon are Copyright (C)1994 by Tobias Ferber.
*	You can reach me via E-mail: ukjg@rz.uni-karlsruhe.de
*
*   SEE ALSO
*	PatchIcons, OptIcon
*
******************************************************************************
*
*	Compile w/ -DDEBUG to output more information at runtime
*/

#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>

#include <workbench/workbench.h>
#include <workbench/icon.h>

#include <dos/dos.h>
#include <dos/rdargs.h>

#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#ifdef __GNUC__
/* suggest parentheses around assignment used as truth value */
#define if(assignment) if( (assignment) )
#endif /* __GNUC__ */

extern struct Library *OpenLibrary(STRPTR, ULONG);
extern void CloseLibrary(struct Library *);
extern struct RDArgs *ReadArgs(STRPTR, LONG *, struct RDArgs *);
extern LONG IoErr(void);
extern BOOL PrintFault(LONG, STRPTR);
extern void FreeArgs(struct RDArgs *);
extern struct DiskObject *GetDiskObject(char *);
extern void FreeDiskObject(struct DiskObject *);

struct IconBase *IconBase;

char *whoami, *iname;  /* argv[0], icon filename w/o ".info" */
int quiet= 0;
FILE *fout;


void pout(const char *fmt, ...)
{
  va_list argp;
  va_start(argp,fmt);
  vfprintf(fout,fmt,argp);
  va_end(argp);
}


void warn(const char *fmt, ...)
{
  if(!quiet)
  {
    va_list argp;
    va_start(argp,fmt);
    fprintf(stderr,"%s: %s.info: ",whoami, iname);
    vfprintf(stderr,(char *)fmt,argp);
    fprintf(stderr,"\n");
    fflush(stderr);
    va_end(argp);
  }
}


void display_version_information(void)
{
  static char license[]=
    "Icon2C is free software; you can redistribute it and/or modify\n"
    "it under the terms of the GNU General Public License as published\n"
    "by the Free Software Foundation; either version 1 of the License,\n"
    "or (at your option) any later version.\n"
    "\n"
    "Icon2C is distributed in the hope that it will be useful,\n"
    "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
    "GNU General Public License for more details.\n"
    "\n"
    "You should have received a copy of the GNU General Public License\n"
    "along with Icon2C; see the file COPYING.  If not, write to the\n"
    "Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
    ;

  puts("Icon2C Version " VERSION " (compiled " __DATE__ ", " __TIME__ ")\n"
       "(c)Copyright 1994 by Tobias Ferber, ukjg@rz.uni-karlsruhe.de\n");

  puts(license);
}


#define oops(field,value)  warn("unexpected value 0x%lx for %s",value,field)

#define DISKOBJECT_NAME    "icon"
#define GADGETRENDER_NAME  "gr"
#define SELECTRENDER_NAME  "sr"
#define GADGET_NAME        "g"
#define TTARRAY_NAME       "tt"  /* ToolTypes array */
#define DRAWERDATA_NAME    "dd"

#define BEGIN_CODE(s)      pout(                                                  \
                             "/*\n *  code generated from \"%s.info\"\n */\n\n"    \
                             "#include <intuition/intuition.h>\n"                 \
                             "#include <workbench/workbench.h>\n"                 \
                             "#include <workbench/icon.h>\n\n"                    \
                           ,s)

#define END_CODE           pout(                                                                     \
                             "\n\n#ifdef TEST\n"                                                     \
                             "#include <intuition/intuitionbase.h>\n"                                \
                             "#include <stdlib.h>\n"                                                 \
                             "#include <stdio.h>\n\n"                                                \
                             "extern struct Library *OpenLibrary(STRPTR, ULONG);\n"                  \
                             "extern void CloseLibrary(struct Library *);\n"                         \
                             "extern LONG IoErr(void);\n"                                            \
                             "extern BOOL PrintFault(LONG, STRPTR);\n"                               \
                             "extern BOOL PutDiskObject(char *, struct DiskObject *);\n\n"           \
                             "struct IconBase *IconBase;\n\n"                                        \
                             "main(int argc, char **argv)\n{\n"                                      \
                             "  if(argc == 2)\n"                                                     \
                             "  {\n"                                                                 \
                             "    if( (IconBase= (struct IconBase *)OpenLibrary(ICONNAME,36)) )\n"   \
                             "    {\n"                                                               \
                             "      if( !PutDiskObject(argv[1],&icon) )\n"                           \
                             "        PrintFault(IoErr(),argv[1]);\n"                                \
                             "      CloseLibrary(IconBase);\n"                                       \
                             "    }\n"                                                               \
                             "    else printf(\"%%s: no %%s.\\n\",*argv,ICONNAME);\n"                \
                             "  }\n"                                                                 \
                             "  else printf(\"usage: %%s <filename>\\n\",*argv);\n"                  \
                             "  exit( IoErr() );\n"                                                  \
                             "}\n"                                                                   \
                             "#endif /* TEST */\n"                                                   \
                           )

#define BEGIN_STRUCT(s,n)  pout("\nstruct %s %s = {\n",s,n)
#define END_STRUCT         pout("};\n")
#define BEGIN_FIELD        pout("\t")
#define P_CONST(s)         pout("%s",s)
#define P_NUMVAL(n)        pout("%ld",n)
#define P_HEXVAL(x)        pout("0x%lx",x)
#define P_STRVAL(s)        if(s) { pout("\""); if(*s) pout("%s",s); pout("\""); } else pout("NULL")
#define END_FIELD(f)       if(f && *f) pout(",\t/* %s */\n",f); else pout(",\n")


#ifdef DEBUG

void p_strN(int n, char *s)
{
  if(s)
  { putchar('\"');
    while(*s && 0<n--) putchar(*s++);
    putchar('\"');
  }
  else pout("NULL");
}


void p_Gadget(struct Gadget *g, char *name)
{
  pout("\n#ifdef UNDEFINED\n");

  BEGIN_STRUCT( ((g->Flags & GFLG_EXTENDED) ? "ExtGadget" : "Gadget"), name);

    BEGIN_FIELD;
      P_CONST("NULL");
      if(g->NextGadget)
        pout(" /* 0x%lx */",g->NextGadget);
    END_FIELD("NextGadget");

    BEGIN_FIELD;
      P_NUMVAL(g->LeftEdge);
    END_FIELD("LeftEdge");

    BEGIN_FIELD;
      P_NUMVAL(g->TopEdge);
    END_FIELD("TopEdge");

    BEGIN_FIELD;
      P_NUMVAL(g->Width);
    END_FIELD("Width");

    BEGIN_FIELD;
      P_NUMVAL(g->Height);
    END_FIELD("Height");

    BEGIN_FIELD;
    {
      UWORD f= g->Flags;

      if(f)
      {
        /* <workbench/workbench.h> */
        if(f & GADGBACKFILL)      { P_CONST("GADGBACKFILL");      f &= ~GADGBACKFILL;      if(f) P_CONST("|"); }
        /* <intuition/intuition.h> */
        /*if(f & GFLG_GADGHIGHBITS) { P_CONST("GFLG_GADGHIGHBITS"); f &= ~GFLG_GADGHIGHBITS; if(f) P_CONST("|"); }*/
        if(f & GFLG_GADGHCOMP)    { P_CONST("GFLG_GADGHCOMP");    f &= ~GFLG_GADGHCOMP;    if(f) P_CONST("|"); }
        if(f & GFLG_GADGHBOX)     { P_CONST("GFLG_GADGHBOX");     f &= ~GFLG_GADGHBOX;     if(f) P_CONST("|"); }
        if(f & GFLG_GADGHIMAGE)   { P_CONST("GFLG_GADGHIMAGE");   f &= ~GFLG_GADGHIMAGE;   if(f) P_CONST("|"); }
        if(f & GFLG_GADGHNONE)    { P_CONST("GFLG_GADGHNONE");    f &= ~GFLG_GADGHNONE;    if(f) P_CONST("|"); }
        if(f & GFLG_GADGIMAGE)    { P_CONST("GFLG_GADGIMAGE");    f &= ~GFLG_GADGIMAGE;    if(f) P_CONST("|"); }
        if(f & GFLG_RELBOTTOM)    { P_CONST("GFLG_RELBOTTOM");    f &= ~GFLG_RELBOTTOM;    if(f) P_CONST("|"); }
        if(f & GFLG_RELRIGHT)     { P_CONST("GFLG_RELRIGHT");     f &= ~GFLG_RELRIGHT;     if(f) P_CONST("|"); }
        if(f & GFLG_RELWIDTH)     { P_CONST("GFLG_RELWIDTH");     f &= ~GFLG_RELWIDTH;     if(f) P_CONST("|"); }
        if(f & GFLG_RELHEIGHT)    { P_CONST("GFLG_RELHEIGHT");    f &= ~GFLG_RELHEIGHT;    if(f) P_CONST("|"); }
        if(f & GFLG_RELSPECIAL)   { P_CONST("GFLG_RELSPECIAL");   f &= ~GFLG_RELSPECIAL;   if(f) P_CONST("|"); }
        if(f & GFLG_SELECTED)     { P_CONST("GFLG_SELECTED");     f &= ~GFLG_SELECTED;     if(f) P_CONST("|"); }
        if(f & GFLG_DISABLED)     { P_CONST("GFLG_DISABLED");     f &= ~GFLG_DISABLED;     if(f) P_CONST("|"); }
        if(f & GFLG_LABELMASK)    { P_CONST("GFLG_LABELMASK");    f &= ~GFLG_LABELMASK;    if(f) P_CONST("|"); }
        if(f & GFLG_LABELITEXT)   { P_CONST("GFLG_LABELITEXT");   f &= ~GFLG_LABELITEXT;   if(f) P_CONST("|"); }
        if(f & GFLG_LABELSTRING)  { P_CONST("GFLG_LABELSTRING");  f &= ~GFLG_LABELSTRING;  if(f) P_CONST("|"); }
        if(f & GFLG_LABELIMAGE)   { P_CONST("GFLG_LABELIMAGE");   f &= ~GFLG_LABELIMAGE;   if(f) P_CONST("|"); }
        if(f & GFLG_TABCYCLE)     { P_CONST("GFLG_TABCYCLE");     f &= ~GFLG_TABCYCLE;     if(f) P_CONST("|"); }
        if(f & GFLG_STRINGEXTEND) { P_CONST("GFLG_STRINGEXTEND"); f &= ~GFLG_STRINGEXTEND; if(f) P_CONST("|"); }
        if(f & GFLG_IMAGEDISABLE) { P_CONST("GFLG_IMAGEDISABLE"); f &= ~GFLG_IMAGEDISABLE; if(f) P_CONST("|"); }
        if(f & GFLG_EXTENDED)     { P_CONST("GFLG_EXTENDED");     f &= ~GFLG_EXTENDED;     if(f) P_CONST("|"); }
        if(f) P_NUMVAL(f);
      }
      else P_CONST("NULL");
    }
    END_FIELD("Flags");

    BEGIN_FIELD;
    {
      UWORD a= g->Activation;

      if(a)
      {
        if(a & GFLG_LABELITEXT)   { P_CONST("GFLG_LABELITEXT");   a &= ~GFLG_LABELITEXT;   if(a) P_CONST("|"); }
        if(a & GACT_RELVERIFY)    { P_CONST("GACT_RELVERIFY");    a &= ~GACT_RELVERIFY;    if(a) P_CONST("|"); }
        if(a & GACT_IMMEDIATE)    { P_CONST("GACT_IMMEDIATE");    a &= ~GACT_IMMEDIATE;    if(a) P_CONST("|"); }
        if(a & GACT_ENDGADGET)    { P_CONST("GACT_ENDGADGET");    a &= ~GACT_ENDGADGET;    if(a) P_CONST("|"); }
        if(a & GACT_FOLLOWMOUSE)  { P_CONST("GACT_FOLLOWMOUSE");  a &= ~GACT_FOLLOWMOUSE;  if(a) P_CONST("|"); }
        if(a & GACT_RIGHTBORDER)  { P_CONST("GACT_RIGHTBORDER");  a &= ~GACT_RIGHTBORDER;  if(a) P_CONST("|"); }
        if(a & GACT_LEFTBORDER)   { P_CONST("GACT_LEFTBORDER");   a &= ~GACT_LEFTBORDER;   if(a) P_CONST("|"); }
        if(a & GACT_TOPBORDER)    { P_CONST("GACT_TOPBORDER");    a &= ~GACT_TOPBORDER;    if(a) P_CONST("|"); }
        if(a & GACT_BOTTOMBORDER) { P_CONST("GACT_BOTTOMBORDER"); a &= ~GACT_BOTTOMBORDER; if(a) P_CONST("|"); }
        if(a & GACT_BORDERSNIFF)  { P_CONST("GACT_BORDERSNIFF");  a &= ~GACT_BORDERSNIFF;  if(a) P_CONST("|"); }
        if(a & GACT_TOGGLESELECT) { P_CONST("GACT_TOGGLESELECT"); a &= ~GACT_TOGGLESELECT; if(a) P_CONST("|"); }
        if(a & GACT_BOOLEXTEND)   { P_CONST("GACT_BOOLEXTEND");   a &= ~GACT_BOOLEXTEND;   if(a) P_CONST("|"); }
        if(a & GACT_STRINGLEFT)   { P_CONST("GACT_STRINGLEFT");   a &= ~GACT_STRINGLEFT;   if(a) P_CONST("|"); }
        if(a & GACT_STRINGCENTER) { P_CONST("GACT_STRINGCENTER"); a &= ~GACT_STRINGCENTER; if(a) P_CONST("|"); }
        if(a & GACT_STRINGRIGHT)  { P_CONST("GACT_STRINGRIGHT");  a &= ~GACT_STRINGRIGHT;  if(a) P_CONST("|"); }
        if(a & GACT_LONGINT)      { P_CONST("GACT_LONGINT");      a &= ~GACT_LONGINT;      if(a) P_CONST("|"); }
        if(a & GACT_ALTKEYMAP)    { P_CONST("GACT_ALTKEYMAP");    a &= ~GACT_ALTKEYMAP;    if(a) P_CONST("|"); }
        if(a & GACT_STRINGEXTEND) { P_CONST("GACT_STRINGEXTEND"); a &= ~GACT_STRINGEXTEND; if(a) P_CONST("|"); }
        if(a & GACT_ACTIVEGADGET) { P_CONST("GACT_ACTIVEGADGET"); a &= ~GACT_ACTIVEGADGET; if(a) P_CONST("|"); }
        if(a & GACT_ACTIVEGADGET) { P_CONST("GACT_ACTIVEGADGET"); a &= ~GACT_ACTIVEGADGET; if(a) P_CONST("|"); }
        if(a & GACT_ACTIVEGADGET) { P_CONST("GACT_ACTIVEGADGET"); a &= ~GACT_ACTIVEGADGET; if(a) P_CONST("|"); }
        if(a) P_NUMVAL(a);
      }
      else P_CONST("NULL");
    }
    END_FIELD("Activation");

    BEGIN_FIELD;
    {
      UWORD t= g->GadgetType;

      if(t)
      {
        if(t & GTYP_GADGETTYPE)   { P_CONST("GTYP_GADGETTYPE");   t &= ~GTYP_GADGETTYPE;   if(t) P_CONST("|"); }
        if(t & GTYP_SYSGADGET)    { P_CONST("GTYP_SYSGADGET");    t &= ~GTYP_SYSGADGET;    if(t) P_CONST("|"); }
        if(t & GTYP_SCRGADGET)    { P_CONST("GTYP_SCRGADGET");    t &= ~GTYP_SCRGADGET;    if(t) P_CONST("|"); }
        if(t & GTYP_GZZGADGET)    { P_CONST("GTYP_GZZGADGET");    t &= ~GTYP_GZZGADGET;    if(t) P_CONST("|"); }
        if(t & GTYP_REQGADGET)    { P_CONST("GTYP_REQGADGET");    t &= ~GTYP_REQGADGET;    if(t) P_CONST("|"); }
        if(t & GTYP_SIZING)       { P_CONST("GTYP_SIZING");       t &= ~GTYP_SIZING;       if(t) P_CONST("|"); }
        if(t & GTYP_WDRAGGING)    { P_CONST("GTYP_WDRAGGING");    t &= ~GTYP_WDRAGGING;    if(t) P_CONST("|"); }
        if(t & GTYP_SDRAGGING)    { P_CONST("GTYP_SDRAGGING");    t &= ~GTYP_SDRAGGING;    if(t) P_CONST("|"); }
        if(t & GTYP_WUPFRONT)     { P_CONST("GTYP_WUPFRONT");     t &= ~GTYP_WUPFRONT;     if(t) P_CONST("|"); }
        if(t & GTYP_SUPFRONT)     { P_CONST("GTYP_SUPFRONT");     t &= ~GTYP_SUPFRONT;     if(t) P_CONST("|"); }
        if(t & GTYP_WDOWNBACK)    { P_CONST("GTYP_WDOWNBACK");    t &= ~GTYP_WDOWNBACK;    if(t) P_CONST("|"); }
        if(t & GTYP_SDOWNBACK)    { P_CONST("GTYP_SDOWNBACK");    t &= ~GTYP_SDOWNBACK;    if(t) P_CONST("|"); }
        if(t & GTYP_CLOSE)        { P_CONST("GTYP_CLOSE");        t &= ~GTYP_CLOSE;        if(t) P_CONST("|"); }
        if(t & GTYP_BOOLGADGET)   { P_CONST("GTYP_BOOLGADGET");   t &= ~GTYP_BOOLGADGET;   if(t) P_CONST("|"); }
        if(t & GTYP_GADGET0002)   { P_CONST("GTYP_GADGET0002");   t &= ~GTYP_GADGET0002;   if(t) P_CONST("|"); }
        if(t & GTYP_PROPGADGET)   { P_CONST("GTYP_PROPGADGET");   t &= ~GTYP_PROPGADGET;   if(t) P_CONST("|"); }
        if(t & GTYP_STRGADGET)    { P_CONST("GTYP_STRGADGET");    t &= ~GTYP_STRGADGET;    if(t) P_CONST("|"); }
        if(t & GTYP_CUSTOMGADGET) { P_CONST("GTYP_CUSTOMGADGET"); t &= ~GTYP_CUSTOMGADGET; if(t) P_CONST("|"); }
        if(t & GTYP_GTYPEMASK)    { P_CONST("GTYP_GTYPEMASK");    t &= ~GTYP_GTYPEMASK;    if(t) P_CONST("|"); }
        if(t) P_NUMVAL(t);
      }
      else P_CONST("NULL");
    }
    END_FIELD("GadgetType");

    BEGIN_FIELD;
      if(g->GadgetRender)
        P_CONST("(APTR)&" GADGETRENDER_NAME);
      else
        P_CONST("NULL");
    END_FIELD("GadgetRender");

    BEGIN_FIELD;
      if(g->SelectRender)
        P_CONST("(APTR)&" SELECTRENDER_NAME);
      else
        P_CONST("NULL");
    END_FIELD("SelectRender");

    BEGIN_FIELD;
      P_CONST("NULL");
      if(g->GadgetText)
        pout(" /* 0x%lx */",g->GadgetText);
    END_FIELD("GadgetText");

    BEGIN_FIELD;
      P_NUMVAL(g->MutualExclude);
    END_FIELD("MutualExclude");

    BEGIN_FIELD;
      P_CONST("NULL");
      if(g->SpecialInfo)
        pout(" /* 0x%lx */",g->SpecialInfo);
    END_FIELD("SpecialInfo");

    BEGIN_FIELD;
      P_NUMVAL(g->GadgetID);
    END_FIELD("GadgetID");

    BEGIN_FIELD;
    {
      LONG ud= (LONG)g->UserData;
      LONG dr= ud & WB_DISKREVISIONMASK;

      pout("(APTR)");

      if(ud != dr)
      {
        P_NUMVAL(ud);
        if(dr) P_CONST("|");
      }
      if(dr == WB_DISKREVISION)
        P_CONST("WB_DISKREVISION");
      else
        P_NUMVAL(dr);
    }
    END_FIELD("UserData");

    if(g->Flags & GFLG_EXTENDED)
    {
      struct ExtGadget *eg= (struct ExtGadget *)g;

      BEGIN_FIELD;
      {
        ULONG m= eg->MoreFlags;

        if(m)
        {
          if(m & GMORE_BOUNDS)       { P_CONST("GMORE_BOUNDS");       m &= ~GMORE_BOUNDS;       if(m) P_CONST("|"); }
          if(m & GMORE_GADGETHELP)   { P_CONST("GMORE_GADGETHELP");   m &= ~GMORE_GADGETHELP;   if(m) P_CONST("|"); }
          if(m & GMORE_SCROLLRASTER) { P_CONST("GMORE_SCROLLRASTER"); m &= ~GMORE_SCROLLRASTER; if(m) P_CONST("|"); }
          if(m) P_NUMVAL(m);
        }
        else P_CONST("NULL");
      }
      END_FIELD("MoreFlags");

      BEGIN_FIELD;
        P_NUMVAL(eg->BoundsLeftEdge);
      END_FIELD("BoundsLeftEdge");

      BEGIN_FIELD;
        P_NUMVAL(eg->BoundsTopEdge);
      END_FIELD("BoundsTopEdge");

      BEGIN_FIELD;
        P_NUMVAL(eg->BoundsWidth);
      END_FIELD("BoundsWidth");

      BEGIN_FIELD;
        P_NUMVAL(eg->BoundsHeight);
      END_FIELD("BoundsHeight");
    }

  END_STRUCT;

  pout("\n#endif /* UNDEFINED */\n");
}

#endif /* DEBUG */


void p_DrawerData(struct DrawerData *dd, char *name)
{
  struct NewWindow *nw= &dd->dd_NewWindow;

#ifdef DEBUG
  if(nw->FirstGadget)
    p_Gadget(nw->FirstGadget, "<unknown>");
#endif /* DEBUG */

  BEGIN_STRUCT("DrawerData", name);

    BEGIN_FIELD;
      P_NUMVAL(nw->LeftEdge);
    END_FIELD("dd_NewWindow.LeftEdge");

    BEGIN_FIELD;
      P_NUMVAL(nw->TopEdge);
    END_FIELD("dd_NewWindow.TopEdge");

    BEGIN_FIELD;
      P_NUMVAL(nw->Width);
    END_FIELD("dd_NewWindow.Width");

    BEGIN_FIELD;
      P_NUMVAL(nw->Height);
    END_FIELD("dd_NewWindow.Height");

    BEGIN_FIELD;
      P_NUMVAL(nw->DetailPen);
    END_FIELD("dd_NewWindow.DetailPen");

    BEGIN_FIELD;
      P_NUMVAL(nw->BlockPen);
    END_FIELD("dd_NewWindow.BlockPen");

    BEGIN_FIELD;
    {
      ULONG f= nw->IDCMPFlags;

      if(f)
      {
        if(f & IDCMP_SIZEVERIFY)     { P_CONST("IDCMP_SIZEVERIFY");     f &= ~IDCMP_SIZEVERIFY;     if(f) P_CONST("|"); }
        if(f & IDCMP_NEWSIZE)        { P_CONST("IDCMP_NEWSIZE");        f &= ~IDCMP_NEWSIZE;        if(f) P_CONST("|"); }
        if(f & IDCMP_REFRESHWINDOW)  { P_CONST("IDCMP_REFRESHWINDOW");  f &= ~IDCMP_REFRESHWINDOW;  if(f) P_CONST("|"); }
        if(f & IDCMP_MOUSEBUTTONS)   { P_CONST("IDCMP_MOUSEBUTTONS");   f &= ~IDCMP_MOUSEBUTTONS;   if(f) P_CONST("|"); }
        if(f & IDCMP_MOUSEMOVE)      { P_CONST("IDCMP_MOUSEMOVE");      f &= ~IDCMP_MOUSEMOVE;      if(f) P_CONST("|"); }
        if(f & IDCMP_GADGETDOWN)     { P_CONST("IDCMP_GADGETDOWN");     f &= ~IDCMP_GADGETDOWN;     if(f) P_CONST("|"); }
        if(f & IDCMP_GADGETUP)       { P_CONST("IDCMP_GADGETUP");       f &= ~IDCMP_GADGETUP;       if(f) P_CONST("|"); }
        if(f & IDCMP_REQSET)         { P_CONST("IDCMP_REQSET");         f &= ~IDCMP_REQSET;         if(f) P_CONST("|"); }
        if(f & IDCMP_MENUPICK)       { P_CONST("IDCMP_MENUPICK");       f &= ~IDCMP_MENUPICK;       if(f) P_CONST("|"); }
        if(f & IDCMP_CLOSEWINDOW)    { P_CONST("IDCMP_CLOSEWINDOW");    f &= ~IDCMP_CLOSEWINDOW;    if(f) P_CONST("|"); }
        if(f & IDCMP_RAWKEY)         { P_CONST("IDCMP_RAWKEY");         f &= ~IDCMP_RAWKEY;         if(f) P_CONST("|"); }
        if(f & IDCMP_REQVERIFY)      { P_CONST("IDCMP_REQVERIFY");      f &= ~IDCMP_REQVERIFY;      if(f) P_CONST("|"); }
        if(f & IDCMP_REQCLEAR)       { P_CONST("IDCMP_REQCLEAR");       f &= ~IDCMP_REQCLEAR;       if(f) P_CONST("|"); }
        if(f & IDCMP_MENUVERIFY)     { P_CONST("IDCMP_MENUVERIFY");     f &= ~IDCMP_MENUVERIFY;     if(f) P_CONST("|"); }
        if(f & IDCMP_NEWPREFS)       { P_CONST("IDCMP_NEWPREFS");       f &= ~IDCMP_NEWPREFS;       if(f) P_CONST("|"); }
        if(f & IDCMP_DISKINSERTED)   { P_CONST("IDCMP_DISKINSERTED");   f &= ~IDCMP_DISKINSERTED;   if(f) P_CONST("|"); }
        if(f & IDCMP_DISKREMOVED)    { P_CONST("IDCMP_DISKREMOVED");    f &= ~IDCMP_DISKREMOVED;    if(f) P_CONST("|"); }
        if(f & IDCMP_WBENCHMESSAGE)  { P_CONST("IDCMP_WBENCHMESSAGE");  f &= ~IDCMP_WBENCHMESSAGE;  if(f) P_CONST("|"); }
        if(f & IDCMP_ACTIVEWINDOW)   { P_CONST("IDCMP_ACTIVEWINDOW");   f &= ~IDCMP_ACTIVEWINDOW;   if(f) P_CONST("|"); }
        if(f & IDCMP_INACTIVEWINDOW) { P_CONST("IDCMP_INACTIVEWINDOW"); f &= ~IDCMP_INACTIVEWINDOW; if(f) P_CONST("|"); }
        if(f & IDCMP_DELTAMOVE)      { P_CONST("IDCMP_DELTAMOVE");      f &= ~IDCMP_DELTAMOVE;      if(f) P_CONST("|"); }
        if(f & IDCMP_VANILLAKEY)     { P_CONST("IDCMP_VANILLAKEY");     f &= ~IDCMP_VANILLAKEY;     if(f) P_CONST("|"); }
        if(f & IDCMP_INTUITICKS)     { P_CONST("IDCMP_INTUITICKS");     f &= ~IDCMP_INTUITICKS;     if(f) P_CONST("|"); }
        if(f & IDCMP_IDCMPUPDATE)    { P_CONST("IDCMP_IDCMPUPDATE");    f &= ~IDCMP_IDCMPUPDATE;    if(f) P_CONST("|"); }
        if(f & IDCMP_MENUHELP)       { P_CONST("IDCMP_MENUHELP");       f &= ~IDCMP_MENUHELP;       if(f) P_CONST("|"); }
        if(f & IDCMP_CHANGEWINDOW)   { P_CONST("IDCMP_CHANGEWINDOW");   f &= ~IDCMP_CHANGEWINDOW;   if(f) P_CONST("|"); }
        if(f & IDCMP_GADGETHELP)     { P_CONST("IDCMP_GADGETHELP");     f &= ~IDCMP_GADGETHELP;     if(f) P_CONST("|"); }
        if(f & IDCMP_LONELYMESSAGE)  { P_CONST("IDCMP_LONELYMESSAGE");  f &= ~IDCMP_LONELYMESSAGE;  if(f) P_CONST("|"); }
        if(f) P_NUMVAL(f);
      }
      else P_CONST("NULL");
    }
    END_FIELD("dd_NewWindow.IDCMPFlags");

    BEGIN_FIELD;
    {
      ULONG f= nw->Flags;
      if(f)
      {
        if(f & WFLG_SIZEGADGET)     { P_CONST("WFLG_SIZEGADGET");     f &= ~WFLG_SIZEGADGET;     if(f) P_CONST("|"); }
        if(f & WFLG_DRAGBAR)        { P_CONST("WFLG_DRAGBAR");        f &= ~WFLG_DRAGBAR;        if(f) P_CONST("|"); }
        if(f & WFLG_DEPTHGADGET)    { P_CONST("WFLG_DEPTHGADGET");    f &= ~WFLG_DEPTHGADGET;    if(f) P_CONST("|"); }
        if(f & WFLG_CLOSEGADGET)    { P_CONST("WFLG_CLOSEGADGET");    f &= ~WFLG_CLOSEGADGET;    if(f) P_CONST("|"); }
        if(f & WFLG_SIZEBRIGHT)     { P_CONST("WFLG_SIZEBRIGHT");     f &= ~WFLG_SIZEBRIGHT;     if(f) P_CONST("|"); }
        if(f & WFLG_SIZEBBOTTOM)    { P_CONST("WFLG_SIZEBBOTTOM");    f &= ~WFLG_SIZEBBOTTOM;    if(f) P_CONST("|"); }
        /*if(f & WFLG_REFRESHBITS)    { P_CONST("WFLG_REFRESHBITS");    f &= ~WFLG_REFRESHBITS;    if(f) P_CONST("|"); }*/
        if(f & WFLG_SMART_REFRESH)  { P_CONST("WFLG_SMART_REFRESH");  f &= ~WFLG_SMART_REFRESH;  if(f) P_CONST("|"); }
        if(f & WFLG_SIMPLE_REFRESH) { P_CONST("WFLG_SIMPLE_REFRESH"); f &= ~WFLG_SIMPLE_REFRESH; if(f) P_CONST("|"); }
        if(f & WFLG_SUPER_BITMAP)   { P_CONST("WFLG_SUPER_BITMAP");   f &= ~WFLG_SUPER_BITMAP;   if(f) P_CONST("|"); }
        if(f & WFLG_OTHER_REFRESH)  { P_CONST("WFLG_OTHER_REFRESH");  f &= ~WFLG_OTHER_REFRESH;  if(f) P_CONST("|"); }
        if(f & WFLG_BACKDROP)       { P_CONST("WFLG_BACKDROP");       f &= ~WFLG_BACKDROP;       if(f) P_CONST("|"); }
        if(f & WFLG_REPORTMOUSE)    { P_CONST("WFLG_REPORTMOUSE");    f &= ~WFLG_REPORTMOUSE;    if(f) P_CONST("|"); }
        if(f & WFLG_GIMMEZEROZERO)  { P_CONST("WFLG_GIMMEZEROZERO");  f &= ~WFLG_GIMMEZEROZERO;  if(f) P_CONST("|"); }
        if(f & WFLG_BORDERLESS)     { P_CONST("WFLG_BORDERLESS");     f &= ~WFLG_BORDERLESS;     if(f) P_CONST("|"); }
        if(f & WFLG_ACTIVATE)       { P_CONST("WFLG_ACTIVATE");       f &= ~WFLG_ACTIVATE;       if(f) P_CONST("|"); }
        if(f & WFLG_RMBTRAP)        { P_CONST("WFLG_RMBTRAP");        f &= ~WFLG_RMBTRAP;        if(f) P_CONST("|"); }
        if(f & WFLG_NOCAREREFRESH)  { P_CONST("WFLG_NOCAREREFRESH");  f &= ~WFLG_NOCAREREFRESH;  if(f) P_CONST("|"); }
        if(f & WFLG_NW_EXTENDED)    { P_CONST("WFLG_NW_EXTENDED");    f &= ~WFLG_NW_EXTENDED;    if(f) P_CONST("|"); }
        if(f & WFLG_NEWLOOKMENUS)   { P_CONST("WFLG_NEWLOOKMENUS");   f &= ~WFLG_NEWLOOKMENUS;   if(f) P_CONST("|"); }
        if(f & WFLG_WINDOWACTIVE)   { P_CONST("WFLG_WINDOWACTIVE");   f &= ~WFLG_WINDOWACTIVE;   if(f) P_CONST("|"); }
        if(f & WFLG_INREQUEST)      { P_CONST("WFLG_INREQUEST");      f &= ~WFLG_INREQUEST;      if(f) P_CONST("|"); }
        if(f & WFLG_MENUSTATE)      { P_CONST("WFLG_MENUSTATE");      f &= ~WFLG_MENUSTATE;      if(f) P_CONST("|"); }
        if(f & WFLG_WINDOWREFRESH)  { P_CONST("WFLG_WINDOWREFRESH");  f &= ~WFLG_WINDOWREFRESH;  if(f) P_CONST("|"); }
        if(f & WFLG_WBENCHWINDOW)   { P_CONST("WFLG_WBENCHWINDOW");   f &= ~WFLG_WBENCHWINDOW;   if(f) P_CONST("|"); }
        if(f & WFLG_WINDOWTICKED)   { P_CONST("WFLG_WINDOWTICKED");   f &= ~WFLG_WINDOWTICKED;   if(f) P_CONST("|"); }
        if(f & WFLG_VISITOR)        { P_CONST("WFLG_VISITOR");        f &= ~WFLG_VISITOR;        if(f) P_CONST("|"); }
        if(f & WFLG_ZOOMED)         { P_CONST("WFLG_ZOOMED");         f &= ~WFLG_ZOOMED;         if(f) P_CONST("|"); }
        if(f & WFLG_HASZOOM)        { P_CONST("WFLG_HASZOOM");        f &= ~WFLG_HASZOOM;        if(f) P_CONST("|"); }
        if(f) P_NUMVAL(f);
      }
      else P_CONST("NULL");
    }
    END_FIELD("dd_NewWindow.Flags");

    BEGIN_FIELD;
      P_CONST("NULL");
      if(nw->FirstGadget)
      {
        pout(" /* 0x%lx */",nw->FirstGadget);
        oops("DrawerData.dd_NewWindow.FirstGadget",nw->FirstGadget);
      }
    END_FIELD("dd_NewWindow.FirstGadget");

    BEGIN_FIELD;
      P_CONST("NULL");
      if(nw->CheckMark)
      {
        pout(" /* 0x%lx */",nw->CheckMark);
        oops("DrawerData.dd_NewWindow.CheckMark",nw->CheckMark);
      }
    END_FIELD("dd_NewWindow.CheckMark");

    BEGIN_FIELD;
      P_CONST("NULL");
      if(nw->Title)
      {
#ifdef DEBUG
        pout(" /* ");
        p_strN(80,nw->Title);
        pout(" */");
#endif /* DEBUG */

        pout(" /* 0x%lx */",nw->Title);
        oops("DrawerData.dd_NewWindow.Title",nw->Title);
      }
    END_FIELD("dd_NewWindow.Title");

    BEGIN_FIELD;
      P_CONST("NULL");
      if(nw->Screen)
      {
        pout(" /* 0x%lx */",nw->Screen);
        oops("DrawerData.dd_NewWindow.Screen",nw->Screen);
      }
    END_FIELD("dd_NewWindow.Screen");

    BEGIN_FIELD;
      P_CONST("NULL");
      if(nw->BitMap)
      {
        pout(" /* 0x%lx */",nw->BitMap);
        oops("DrawerData.dd_NewWindow.BitMap",nw->BitMap);
      }
    END_FIELD("dd_NewWindow.BitMap");

    BEGIN_FIELD;
      P_NUMVAL(nw->MinWidth);
    END_FIELD("dd_NewWindow.MinWidth");

    BEGIN_FIELD;
      P_NUMVAL(nw->MinHeight);
    END_FIELD("dd_NewWindow.MinHeight");

    BEGIN_FIELD;
      P_NUMVAL(nw->MaxWidth);
    END_FIELD("dd_NewWindow.MaxWidth");

    BEGIN_FIELD;
      P_NUMVAL(nw->MinWidth);
    END_FIELD("dd_NewWindow.MaxHeight");

    BEGIN_FIELD;
    {
      UWORD t= nw->Type;

      if(t)
      {
        if(t & WBENCHSCREEN) { P_CONST("WBENCHSCREEN"); t &= ~WBENCHSCREEN; if(t) P_CONST("|"); }
        if(t & PUBLICSCREEN) { P_CONST("PUBLICSCREEN"); t &= ~PUBLICSCREEN; if(t) P_CONST("|"); }
        if(t & CUSTOMSCREEN) { P_CONST("CUSTOMSCREEN"); t &= ~CUSTOMSCREEN; if(t) P_CONST("|"); }
        if(t & SHOWTITLE)    { P_CONST("SHOWTITLE");    t &= ~SHOWTITLE;    if(t) P_CONST("|"); }
        if(t & BEEPING)      { P_CONST("BEEPING");      t &= ~BEEPING;      if(t) P_CONST("|"); }
        if(t & CUSTOMBITMAP) { P_CONST("CUSTOMBITMAP"); t &= ~CUSTOMBITMAP; if(t) P_CONST("|"); }
        if(t & SCREENBEHIND) { P_CONST("SCREENBEHIND"); t &= ~SCREENBEHIND; if(t) P_CONST("|"); }
        if(t & SCREENQUIET)  { P_CONST("SCREENQUIET");  t &= ~SCREENQUIET;  if(t) P_CONST("|"); }
        if(t & SCREENHIRES)  { P_CONST("SCREENHIRES");  t &= ~SCREENHIRES;  if(t) P_CONST("|"); }
        if(t & NS_EXTENDED)  { P_CONST("NS_EXTENDED");  t &= ~NS_EXTENDED;  if(t) P_CONST("|"); }
        if(t & AUTOSCROLL)   { P_CONST("AUTOSCROLL");   t &= ~AUTOSCROLL;   if(t) P_CONST("|"); }
        if(t & PENSHARED)    { P_CONST("PENSHARED");    t &= ~PENSHARED;    if(t) P_CONST("|"); }
        if(t) P_NUMVAL(t);
      }
      else P_CONST("NULL");
    }
    END_FIELD("dd_NewWindow.Type");

    /**/

    BEGIN_FIELD;
      if(dd->dd_CurrentX == NO_ICON_POSITION)
        P_CONST("NO_ICON_POSITION");
      else
        P_NUMVAL(dd->dd_CurrentX);
    END_FIELD("dd_CurrentX");

    BEGIN_FIELD;
      if(dd->dd_CurrentY == NO_ICON_POSITION)
        P_CONST("NO_ICON_POSITION");
      else
        P_NUMVAL(dd->dd_CurrentY);
    END_FIELD("dd_CurrentY");

    BEGIN_FIELD;
      P_NUMVAL(dd->dd_Flags);
    END_FIELD("dd_Flags");

    BEGIN_FIELD;
      P_NUMVAL(dd->dd_ViewModes);
    END_FIELD("dd_ViewModes");

  END_STRUCT;

};


void p_ImageData(struct Image *i, char *name)
{
  WORD w,h,d;
  UWORD *p= i->ImageData;

  pout("\nUWORD %s_data[] = {\n",name);

  for(d=0; d<i->Depth; d++)
  {
    if(i->PlanePick & (1L << d))
    {
      pout("\n\t/* plane %d */\n\n",d);

      for(h=0; h<i->Height; h++)
      {
        pout("\t");
        for(w=0; w< (i->Width + 15)/16; w++)
        {
          pout("0x%04x, ", (UWORD)(*p));
          ++p;
        }
        pout("\n");
      }
    }
    else pout("\n\t/* plane %d is set to %d by %s.PlaneOnOff */\n\n",d,
      ( (i->PlaneOnOff & (1L<<d)) >> d ),name);
  }
  pout("};\n");
}


void p_Image(struct Image *i, char *name)
{
  if(i->ImageData)
    p_ImageData(i,name);

  BEGIN_STRUCT("Image", name);

    BEGIN_FIELD;
      P_NUMVAL(i->LeftEdge);
    END_FIELD("LeftEdge");

    BEGIN_FIELD;
      P_NUMVAL(i->TopEdge);
    END_FIELD("TopEdge");

    BEGIN_FIELD;
      P_NUMVAL(i->Width);
    END_FIELD("Width");

    BEGIN_FIELD;
      P_NUMVAL(i->Height);
    END_FIELD("Height");

    BEGIN_FIELD;
      P_NUMVAL(i->Depth);
    END_FIELD("Depth");

    BEGIN_FIELD;
      if(i->ImageData)
        pout("%s_data",name);
      else
        P_CONST("NULL");
    END_FIELD("ImageData");

    BEGIN_FIELD;
      P_NUMVAL(i->PlanePick);
      if( i->PlanePick & ~((1L << i->Depth) -1L) )
      {
        pout(" /* illegal */");
        warn("illegal value %d for Image.PlanePick (depth=%d)",i->PlanePick,i->Depth);
      }
    END_FIELD("PlanePick");

    BEGIN_FIELD;
      P_NUMVAL(i->PlaneOnOff);
    END_FIELD("PlaneOnOff");

    BEGIN_FIELD;
      P_CONST("NULL");
      if(i->NextImage)
      {
        pout(" /* 0x%lx */", i->NextImage);
        oops("Image.NextImage",i->NextImage);
      }
    END_FIELD("NextImage");

  END_STRUCT;
}


void p_ToolTypes(char **tt, char *name)
{

  pout("\nchar *%s[] = %s", name, tt ? "{\n" : "(char **)NULL");

  if(tt)
  {
    while(*tt)
    {
      pout("\t\"%s\",\n",*tt++);
    }
    pout("\tNULL\n}");
  }
  pout(";\n");
}


void p_DiskObject(struct DiskObject *icon, char *name)
{
  BEGIN_STRUCT("DiskObject", name);

    BEGIN_FIELD;
      if(icon->do_Magic == WB_DISKMAGIC)
        P_CONST("WB_DISKMAGIC");
      else
        P_NUMVAL(icon->do_Magic);
    END_FIELD("do_Magic");

    BEGIN_FIELD;
      if(icon->do_Version == WB_DISKVERSION)
        P_CONST("WB_DISKVERSION");
      else
        P_NUMVAL(WB_DISKVERSION);
    END_FIELD("do_Version");

    /* do_Gadget */
    {
      struct Gadget *g= &icon->do_Gadget;

      BEGIN_FIELD;
        P_CONST("NULL");
        if(g->NextGadget)
        {
          pout(" /* 0x%lx */",g->NextGadget);
          oops("DiskObject.do_Gadget.NextGadget",g->NextGadget);
        }
      END_FIELD("do_Gadget.NextGadget");

      BEGIN_FIELD;
        P_NUMVAL(g->LeftEdge);
      END_FIELD("do_Gadget.LeftEdge");

      BEGIN_FIELD;
        P_NUMVAL(g->TopEdge);
      END_FIELD("do_Gadget.TopEdge");

      BEGIN_FIELD;
        P_NUMVAL(g->Width);
      END_FIELD("do_Gadget.Width");

      BEGIN_FIELD;
        P_NUMVAL(g->Height);
      END_FIELD("do_Gadget.Height");

      BEGIN_FIELD;
      {
        UWORD f= g->Flags;

        if(f)
        {
          /* <workbench/workbench.h> */
          if(f & GADGBACKFILL)      { P_CONST("GADGBACKFILL");      f &= ~GADGBACKFILL;      if(f) P_CONST("|"); }
          /* <intuition/intuition.h> */
          /*if(f & GFLG_GADGHIGHBITS) { P_CONST("GFLG_GADGHIGHBITS"); f &= ~GFLG_GADGHIGHBITS; if(f) P_CONST("|"); }*/
          if(f & GFLG_GADGHCOMP)    { P_CONST("GFLG_GADGHCOMP");    f &= ~GFLG_GADGHCOMP;    if(f) P_CONST("|"); }
          if(f & GFLG_GADGHBOX)     { P_CONST("GFLG_GADGHBOX");     f &= ~GFLG_GADGHBOX;     if(f) P_CONST("|"); }
          if(f & GFLG_GADGHIMAGE)   { P_CONST("GFLG_GADGHIMAGE");   f &= ~GFLG_GADGHIMAGE;   if(f) P_CONST("|"); }
          if(f & GFLG_GADGHNONE)    { P_CONST("GFLG_GADGHNONE");    f &= ~GFLG_GADGHNONE;    if(f) P_CONST("|"); }
          if(f & GFLG_GADGIMAGE)    { P_CONST("GFLG_GADGIMAGE");    f &= ~GFLG_GADGIMAGE;    if(f) P_CONST("|"); }
          if(f & GFLG_RELBOTTOM)    { P_CONST("GFLG_RELBOTTOM");    f &= ~GFLG_RELBOTTOM;    if(f) P_CONST("|"); }
          if(f & GFLG_RELRIGHT)     { P_CONST("GFLG_RELRIGHT");     f &= ~GFLG_RELRIGHT;     if(f) P_CONST("|"); }
          if(f & GFLG_RELWIDTH)     { P_CONST("GFLG_RELWIDTH");     f &= ~GFLG_RELWIDTH;     if(f) P_CONST("|"); }
          if(f & GFLG_RELHEIGHT)    { P_CONST("GFLG_RELHEIGHT");    f &= ~GFLG_RELHEIGHT;    if(f) P_CONST("|"); }
          if(f & GFLG_RELSPECIAL)   { P_CONST("GFLG_RELSPECIAL");   f &= ~GFLG_RELSPECIAL;   if(f) P_CONST("|"); }
          if(f & GFLG_SELECTED)     { P_CONST("GFLG_SELECTED");     f &= ~GFLG_SELECTED;     if(f) P_CONST("|"); }
          if(f & GFLG_DISABLED)     { P_CONST("GFLG_DISABLED");     f &= ~GFLG_DISABLED;     if(f) P_CONST("|"); }
          if(f & GFLG_LABELMASK)    { P_CONST("GFLG_LABELMASK");    f &= ~GFLG_LABELMASK;    if(f) P_CONST("|"); }
          if(f & GFLG_LABELITEXT)   { P_CONST("GFLG_LABELITEXT");   f &= ~GFLG_LABELITEXT;   if(f) P_CONST("|"); }
          if(f & GFLG_LABELSTRING)  { P_CONST("GFLG_LABELSTRING");  f &= ~GFLG_LABELSTRING;  if(f) P_CONST("|"); }
          if(f & GFLG_LABELIMAGE)   { P_CONST("GFLG_LABELIMAGE");   f &= ~GFLG_LABELIMAGE;   if(f) P_CONST("|"); }
          if(f & GFLG_TABCYCLE)     { P_CONST("GFLG_TABCYCLE");     f &= ~GFLG_TABCYCLE;     if(f) P_CONST("|"); }
          if(f & GFLG_STRINGEXTEND) { P_CONST("GFLG_STRINGEXTEND"); f &= ~GFLG_STRINGEXTEND; if(f) P_CONST("|"); }
          if(f & GFLG_IMAGEDISABLE) { P_CONST("GFLG_IMAGEDISABLE"); f &= ~GFLG_IMAGEDISABLE; if(f) P_CONST("|"); }
          if(f & GFLG_EXTENDED)     { P_CONST("GFLG_EXTENDED");     f &= ~GFLG_EXTENDED;     if(f) P_CONST("|"); }
          if(f) P_NUMVAL(f);
        }
        else P_CONST("NULL");
      }
      END_FIELD("do_Gadget.Flags");

      BEGIN_FIELD;
      {
        UWORD a= g->Activation;

        if(a)
        {
          if(a & GFLG_LABELITEXT)   { P_CONST("GFLG_LABELITEXT");   a &= ~GFLG_LABELITEXT;   if(a) P_CONST("|"); }
          if(a & GACT_RELVERIFY)    { P_CONST("GACT_RELVERIFY");    a &= ~GACT_RELVERIFY;    if(a) P_CONST("|"); }
          if(a & GACT_IMMEDIATE)    { P_CONST("GACT_IMMEDIATE");    a &= ~GACT_IMMEDIATE;    if(a) P_CONST("|"); }
          if(a & GACT_ENDGADGET)    { P_CONST("GACT_ENDGADGET");    a &= ~GACT_ENDGADGET;    if(a) P_CONST("|"); }
          if(a & GACT_FOLLOWMOUSE)  { P_CONST("GACT_FOLLOWMOUSE");  a &= ~GACT_FOLLOWMOUSE;  if(a) P_CONST("|"); }
          if(a & GACT_RIGHTBORDER)  { P_CONST("GACT_RIGHTBORDER");  a &= ~GACT_RIGHTBORDER;  if(a) P_CONST("|"); }
          if(a & GACT_LEFTBORDER)   { P_CONST("GACT_LEFTBORDER");   a &= ~GACT_LEFTBORDER;   if(a) P_CONST("|"); }
          if(a & GACT_TOPBORDER)    { P_CONST("GACT_TOPBORDER");    a &= ~GACT_TOPBORDER;    if(a) P_CONST("|"); }
          if(a & GACT_BOTTOMBORDER) { P_CONST("GACT_BOTTOMBORDER"); a &= ~GACT_BOTTOMBORDER; if(a) P_CONST("|"); }
          if(a & GACT_BORDERSNIFF)  { P_CONST("GACT_BORDERSNIFF");  a &= ~GACT_BORDERSNIFF;  if(a) P_CONST("|"); }
          if(a & GACT_TOGGLESELECT) { P_CONST("GACT_TOGGLESELECT"); a &= ~GACT_TOGGLESELECT; if(a) P_CONST("|"); }
          if(a & GACT_BOOLEXTEND)   { P_CONST("GACT_BOOLEXTEND");   a &= ~GACT_BOOLEXTEND;   if(a) P_CONST("|"); }
          if(a & GACT_STRINGLEFT)   { P_CONST("GACT_STRINGLEFT");   a &= ~GACT_STRINGLEFT;   if(a) P_CONST("|"); }
          if(a & GACT_STRINGCENTER) { P_CONST("GACT_STRINGCENTER"); a &= ~GACT_STRINGCENTER; if(a) P_CONST("|"); }
          if(a & GACT_STRINGRIGHT)  { P_CONST("GACT_STRINGRIGHT");  a &= ~GACT_STRINGRIGHT;  if(a) P_CONST("|"); }
          if(a & GACT_LONGINT)      { P_CONST("GACT_LONGINT");      a &= ~GACT_LONGINT;      if(a) P_CONST("|"); }
          if(a & GACT_ALTKEYMAP)    { P_CONST("GACT_ALTKEYMAP");    a &= ~GACT_ALTKEYMAP;    if(a) P_CONST("|"); }
          if(a & GACT_STRINGEXTEND) { P_CONST("GACT_STRINGEXTEND"); a &= ~GACT_STRINGEXTEND; if(a) P_CONST("|"); }
          if(a & GACT_ACTIVEGADGET) { P_CONST("GACT_ACTIVEGADGET"); a &= ~GACT_ACTIVEGADGET; if(a) P_CONST("|"); }
          if(a & GACT_ACTIVEGADGET) { P_CONST("GACT_ACTIVEGADGET"); a &= ~GACT_ACTIVEGADGET; if(a) P_CONST("|"); }
          if(a & GACT_ACTIVEGADGET) { P_CONST("GACT_ACTIVEGADGET"); a &= ~GACT_ACTIVEGADGET; if(a) P_CONST("|"); }
          if(a) P_NUMVAL(a);
        }
        else P_CONST("NULL");
      }
      END_FIELD("do_Gadget.Activation");

      BEGIN_FIELD;
      {
        UWORD t= g->GadgetType;

        if(t)
        {
          if(t & GTYP_GADGETTYPE)   { P_CONST("GTYP_GADGETTYPE");   t &= ~GTYP_GADGETTYPE;   if(t) P_CONST("|"); }
          if(t & GTYP_SYSGADGET)    { P_CONST("GTYP_SYSGADGET");    t &= ~GTYP_SYSGADGET;    if(t) P_CONST("|"); }
          if(t & GTYP_SCRGADGET)    { P_CONST("GTYP_SCRGADGET");    t &= ~GTYP_SCRGADGET;    if(t) P_CONST("|"); }
          if(t & GTYP_GZZGADGET)    { P_CONST("GTYP_GZZGADGET");    t &= ~GTYP_GZZGADGET;    if(t) P_CONST("|"); }
          if(t & GTYP_REQGADGET)    { P_CONST("GTYP_REQGADGET");    t &= ~GTYP_REQGADGET;    if(t) P_CONST("|"); }
          if(t & GTYP_SIZING)       { P_CONST("GTYP_SIZING");       t &= ~GTYP_SIZING;       if(t) P_CONST("|"); }
          if(t & GTYP_WDRAGGING)    { P_CONST("GTYP_WDRAGGING");    t &= ~GTYP_WDRAGGING;    if(t) P_CONST("|"); }
          if(t & GTYP_SDRAGGING)    { P_CONST("GTYP_SDRAGGING");    t &= ~GTYP_SDRAGGING;    if(t) P_CONST("|"); }
          if(t & GTYP_WUPFRONT)     { P_CONST("GTYP_WUPFRONT");     t &= ~GTYP_WUPFRONT;     if(t) P_CONST("|"); }
          if(t & GTYP_SUPFRONT)     { P_CONST("GTYP_SUPFRONT");     t &= ~GTYP_SUPFRONT;     if(t) P_CONST("|"); }
          if(t & GTYP_WDOWNBACK)    { P_CONST("GTYP_WDOWNBACK");    t &= ~GTYP_WDOWNBACK;    if(t) P_CONST("|"); }
          if(t & GTYP_SDOWNBACK)    { P_CONST("GTYP_SDOWNBACK");    t &= ~GTYP_SDOWNBACK;    if(t) P_CONST("|"); }
          if(t & GTYP_CLOSE)        { P_CONST("GTYP_CLOSE");        t &= ~GTYP_CLOSE;        if(t) P_CONST("|"); }
          if(t & GTYP_BOOLGADGET)   { P_CONST("GTYP_BOOLGADGET");   t &= ~GTYP_BOOLGADGET;   if(t) P_CONST("|"); }
          if(t & GTYP_GADGET0002)   { P_CONST("GTYP_GADGET0002");   t &= ~GTYP_GADGET0002;   if(t) P_CONST("|"); }
          if(t & GTYP_PROPGADGET)   { P_CONST("GTYP_PROPGADGET");   t &= ~GTYP_PROPGADGET;   if(t) P_CONST("|"); }
          if(t & GTYP_STRGADGET)    { P_CONST("GTYP_STRGADGET");    t &= ~GTYP_STRGADGET;    if(t) P_CONST("|"); }
          if(t & GTYP_CUSTOMGADGET) { P_CONST("GTYP_CUSTOMGADGET"); t &= ~GTYP_CUSTOMGADGET; if(t) P_CONST("|"); }
          if(t & GTYP_GTYPEMASK)    { P_CONST("GTYP_GTYPEMASK");    t &= ~GTYP_GTYPEMASK;    if(t) P_CONST("|"); }
          if(t) P_NUMVAL(t);
        }
        else P_CONST("NULL");
      }
      END_FIELD("do_Gadget.GadgetType");

      BEGIN_FIELD;
        if(g->GadgetRender)
          P_CONST("(APTR)&" GADGETRENDER_NAME);
        else
          P_CONST("NULL");
      END_FIELD("do_Gadget.GadgetRender");

      BEGIN_FIELD;
        if(g->SelectRender)
          P_CONST("(APTR)&" SELECTRENDER_NAME);
        else
          P_CONST("NULL");
      END_FIELD("do_Gadget.SelectRender");

      BEGIN_FIELD;
        P_CONST("NULL");
        if(g->GadgetText)
        {
          pout(" /* 0x%lx */",g->GadgetText);
          oops("DiskObject.do_Gadget.GadgetText",g->GadgetText);
        }
      END_FIELD("do_Gadget.GadgetText");

      BEGIN_FIELD;
        P_NUMVAL(g->MutualExclude);
      END_FIELD("do_Gadget.MutualExclude");

      BEGIN_FIELD;
        P_CONST("NULL");
        if(g->SpecialInfo)
        {
          pout(" /* 0x%lx */",g->SpecialInfo);
          oops("DiskObject.do_Gadget.SpecialInfo",g->SpecialInfo);
        }
      END_FIELD("do_Gadget.SpecialInfo");

      BEGIN_FIELD;
        P_NUMVAL(g->GadgetID);
      END_FIELD("do_Gadget.GadgetID");

      BEGIN_FIELD;
      {
        LONG ud= (LONG)g->UserData;
        LONG dr= ud & WB_DISKREVISIONMASK;

        pout("(APTR)");

        if(ud != dr)
        {
          P_NUMVAL(ud);
          if(dr) P_CONST("|");
        }
        if(dr == WB_DISKREVISION)
          P_CONST("WB_DISKREVISION");
        else
          P_NUMVAL(dr);
      }
      END_FIELD("do_Gadget.UserData");
    }

    BEGIN_FIELD;
      switch(icon->do_Type)
      {
        case WBDISK:     P_CONST("WBDISK");       break;
        case WBDRAWER:   P_CONST("WBDRAWER");     break;
        case WBTOOL:     P_CONST("WBTOOL");       break;
        case WBPROJECT:  P_CONST("WBPROJECT");    break;
        case WBGARBAGE:  P_CONST("WBGARBAGE");    break;
        case WBDEVICE:   P_CONST("WBDEVICE");     break;
        case WBKICK:     P_CONST("WBKICK");       break;
        case WBAPPICON:  P_CONST("WBAPPICON");    break;
        default:         P_NUMVAL(icon->do_Type); break;
      }
    END_FIELD("do_Type");

    BEGIN_FIELD;
      P_STRVAL(icon->do_DefaultTool);
    END_FIELD("do_DefaultTool");

    BEGIN_FIELD;
      if(icon->do_ToolTypes)
        P_CONST("&" TTARRAY_NAME "[0]");
      else
        P_CONST("NULL");
    END_FIELD("do_ToolTypes");

    BEGIN_FIELD;
      if(icon->do_CurrentX == NO_ICON_POSITION)
        P_CONST("NO_ICON_POSITION");
      else
        P_NUMVAL(icon->do_CurrentX);
    END_FIELD("do_CurrentX");

    BEGIN_FIELD;
      if(icon->do_CurrentY == NO_ICON_POSITION)
        P_CONST("NO_ICON_POSITION");
      else
        P_NUMVAL(icon->do_CurrentY);
    END_FIELD("do_CurrentY");

    BEGIN_FIELD;
      if(icon->do_DrawerData)
        P_CONST("&" DRAWERDATA_NAME);
      else
        P_CONST("NULL");
    END_FIELD("do_DrawerData");

    BEGIN_FIELD;
      P_STRVAL(icon->do_ToolWindow);
    END_FIELD("do_ToolWindow");

    BEGIN_FIELD;
      P_NUMVAL(icon->do_StackSize);
    END_FIELD("do_StackSize");

  END_STRUCT;
}


/*** MAIN ***/


int main(int argc, char **argv)
{
  struct RDArgs *a;
  LONG args[3] = { 0,0,0 };  /* args array */
  int rc= RETURN_OK;

  whoami= *argv;
  fout= stdout;

  if( a= ReadArgs("NAME/A,QUIET/S,TO/K", args, NULL) )
  {
    if( iname= (char *)malloc(strlen((char *)args[0])+1) )
    {
      strcpy(iname, (char *)args[0]); /* now we may use warn() */

      if( IconBase= (struct IconBase *)OpenLibrary(ICONNAME,36L) )
      {
        struct DiskObject *icon= GetDiskObject(iname);

        if(!icon)
        {
          int x= strlen(iname) - 5;
          if(x>0 && !stricmp(&(iname[x]),".info"))
          {
            iname[x]= '\0';
            icon= GetDiskObject(iname);
          }
        }

        if(icon)
        {
          if(args[2])
          {
            fout= fopen((char *)args[2],"w");

            if(!fout)
            {
              PrintFault(rc= IoErr(), (STRPTR)args[2]);
              fprintf(stderr,"%s: Unable to open output file.\n",whoami);
            }
          }

          if(fout)
          {
            quiet= args[1]; /* now warn() might be a no-op */

            BEGIN_CODE(iname);
            {
              struct Gadget *g= &icon->do_Gadget;

              if(g->Flags & GFLG_GADGIMAGE)
              {
                if(g->GadgetRender)
                  p_Image(g->GadgetRender, GADGETRENDER_NAME);

                if(g->SelectRender)
                {
                  if(g->Flags & GFLG_GADGHIMAGE == 0)
                    warn("warning: no GFLG_GADGHIMAGE for SelectRender image");

                  p_Image(g->SelectRender, SELECTRENDER_NAME);
                }
                else if(g->Flags & GFLG_GADGHIMAGE)
                  warn("warning: No SelectRender image for GFLG_GADGHIMAGE");
              }
              else warn("warning: unset GFLG_GADGIMAGE in DiskObject.do_Gadget.Flags");

              if(icon->do_ToolTypes)
                p_ToolTypes(icon->do_ToolTypes, TTARRAY_NAME);

              if(icon->do_DrawerData)
                p_DrawerData(icon->do_DrawerData, DRAWERDATA_NAME);

              p_DiskObject(icon, DISKOBJECT_NAME);
            }
            END_CODE;

            if(fout != stdout)
              fclose(fout);
          }

          FreeDiskObject(icon);
        }
        else /* !icon */
        {
          rc= IoErr();
          warn("GetDiskObject() failed");
        }
        CloseLibrary((struct Library *)IconBase);
      }
      else /* !IconBase */
      {
        warn("You need %s V36+",ICONNAME);
        rc= RETURN_ERROR;
      }
      free(iname);
    }
    else /* !iname -> don't use warn() */
    {
      fprintf(stderr,"%s: no memory!\n", argv[0]);
      rc= ERROR_NO_FREE_STORE;
    }
    FreeArgs(a);
  }
  else /* !ReadArgs() */
  {
    if(argc == 1)
      display_version_information();

    if(argc <= 3)
      printf("%s: required argument missing\n",whoami);
    else
      printf("%s: wrong number of arguments\n",whoami);

    rc= RETURN_FAIL;
  }

  exit(rc);
}
