#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <libraries/gadtools.h>
#include <libraries/iffparse.h>
#include <graphics/gfx.h>
#include <dos/dos.h>
#include <dos/datetime.h>

#include <clib/alib_protos.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/iffparse_protos.h>
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>

#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "rp.h"

#define BYTESPERLINE 12 // how many bytes to print per line

#define ITEMS 255
MODULE struct
{   TEXT   name[5];
    ULONG  bytes;
    UBYTE* DataPtr;
} contents[ITEMS + 1];

#define FORMS         89

#define CD             1
#define OBSOLETE       2
#define PRIVATE        4
#define PROPOSAL       8
#define RESERVED      16
#define RKM           32
#define STANDARD      64
#define UNREGISTERED 128

#define LIST1LINES    25

#define IFFXCHARS     17

MODULE void iffquery(void);
MODULE void PrintTopChunk(void);
MODULE void readiff(void);
MODULE void tellchunk(UWORD which);
MODULE void chunkdesc(STRPTR desc, ABOOL isknown);
MODULE void binarize(UBYTE data);
MODULE void hexalize(UBYTE data);
MODULE ULONG getulong(UBYTE* start);
MODULE SLONG getslong(UBYTE* start);
MODULE ULONG getuword(UBYTE* start);
MODULE SLONG getsword(UBYTE* start);
MODULE SLONG getsbyte(UBYTE* start);
MODULE void writeiffgadgets(void);
MODULE void dotextattr(UBYTE* offset);
MODULE void docountry(UBYTE* offset);
MODULE void tellchunk(UWORD which);

/* Text error messages for possible IFFERR_#? returns from various IFF
 * routines. To get the index into this array, take your IFFERR code,
 * negate it, and subtract one.
 * idx = -error - 1;
 */
STRPTR errormsgs[] =
{   "End of file (not an error).",
    "End of context (not an error).",
    "No lexical scope.",
    "Insufficient memory.",
    "Stream read error.",
    "Stream write error.",
    "Stream seek error.",
    "File is corrupt.",
    "IFF syntax error.",
    "Not an IFF file.",
    "Required call-back hook missing.",
    "Return to client. You should never see this."
};

// from rp.c
IMPORT ABOOL              fillwindows;
IMPORT SBYTE              page;
IMPORT struct NewGadget   Gadget;
IMPORT struct Gadget     *BU99_Right,
                         *PrevGadPtr;
IMPORT struct Window*     MainWindowPtr;
IMPORT struct VisualInfo* VisualInfoPtr;
IMPORT TEXT               aslresult[VLONGFIELD + 1],
                          weekdaystring[LEN_DATSTRING],
                          datestring[LEN_DATSTRING],
                          timestring[LEN_DATSTRING],
                          IOBuffer[LONGESTFIELD + 1];
IMPORT ULONG              fillcolour;
IMPORT WORD               yoffset;

MODULE ABOOL             known, first;
MODULE struct IFFHandle* IFFHandle             = NULL;
MODULE struct List       List1,
                         List2;
MODULE ABOOL             List1Nodes            = FALSE,
                         List2Nodes            = FALSE;
MODULE struct Gadget  *TE61_Contributor        = NULL,
                      *CB61_CD                 = NULL,
                      *CB61_Obsolete           = NULL,
                      *TE61_FORMDesc           = NULL,
                      *ST61_FORMID             = NULL,
                      *CB61_Private            = NULL,
                      *CB61_Proposal           = NULL,
                      *CB61_Reserved           = NULL,
                      *CB61_RKM                = NULL,
                      *CB61_Standard           = NULL,
                      *CB61_Unregistered       = NULL,
                      *CB61_Raw                = NULL,
                      *TE61_Status             = NULL,
                      *ST61_Pathname           = NULL,
                      *BU61_PathnameASL        = NULL,
                      *LV61_List1              = NULL,
                      *LV61_List2              = NULL,
                      *TE61_ChunkDesc          = NULL;
MODULE TEXT  queryform[5] = "",
             tempstring1[VLONGFIELD + 1],
             tempstring2[13];
MODULE ULONG items      = 0, // value of this is actual number of items allocated
             list1lines = 0;
MODULE UWORD selectedform  = 0,
             selectedchunk = 0;

AGLOBAL struct IFFStruct iff;

MODULE struct
{   UBYTE  flags;
    TEXT   name[5];
    STRPTR desc;
    STRPTR contributor;
} form[FORMS + 1] =
{   STANDARD | RKM | CD,      "8SVX", "EA IFF 85 8-bit sound sample form",                    "EA/CBM",
    RKM | CD,                 "AIFF", "Audio 1-32 bit samples",                               "Apple",
    RKM | CD,                 "ACBM", "Amiga Contiguous Bitmap",                              "CBM",
    UNREGISTERED,             "AHAM", "?",                                                    "?",
    RKM | CD,                 "ANBM", "ANimated BitMap form",                                 "EA",
    RKM | CD,                 "ANIM", "Cel ANIMation form",                                   "Sparta/Aegis",
    PROPOSAL,                 "ARC ", "ARChive format",                                       "?",
    UNREGISTERED,             "ARES", "?",                                                    "?",
    RESERVED,                 "ATXT", "Temporarily reserved",                                 "?",
    PRIVATE,                  "AVCF", "AmigaVision Flow",                                     "CBM",
    NULL,                     "BANK", "Soundquest Editor/Librarian MIDI Sysex dump",          "?",
    NULL,                     "BBSD", "BBS Database",                                         "Phalanx Software",
    PRIVATE,                  "C100", "?",                                                    "Cloanto",
    STANDARD,                 "CAT ", "EA IFF 85 group identifier",                           "EA/CBM",
    PROPOSAL,                 "CELP", "Compressed ZyXEL voice data",                          "?",
    RESERVED,                 "CHBM", "Chunky bitmap",                                        "Eric Lavitsky",
    NULL,                     "CLIP", "CAT CLIP to hold various formats in clipboard",        "CBM",
    PROPOSAL | CD,            "CMUS", "Common MUsical Score",                                 "Talin (David Joiner)",
    NULL,                     "CPFM", "Cloanto Personal FontMaker",                           "Cloanto",
    NULL,                     "DCCL", "DCTV paint clip",                                      "?",
    NULL,                     "DCPA", "DCTV paint palette",                                   "?",
    NULL,                     "DCTV", "DCTV raw picture file",                                "?",
    PRIVATE,                  "DECK", "Inovatronics CanDo",                                   "Innovatronics",
    CD,                       "DEEP", "Chunky pixel image files (used in TV Paint)",          "Amiga Centre Scotland",
    RKM | CD,                 "DR2D", "2D object standard format",                            "Ross Cunniff & John Orr",
    RESERVED,                 "DRAW", "?",                                                    "Jim Bayless",
    CD,                       "DTYP", "DataTYPes identification",                             "Amiga, Inc.",
    PROPOSAL | CD,            "EXEC", "Executable (loadseg-able) code",                       "Chris Ludwig",
    RKM | CD,                 "FANT", "Fantavision movie format",                             "Broderbund",
    OBSOLETE | PRIVATE,       "FAX3", "Facsimile image",                                      "GPSoftware",
    CD,                       "FAXX", "Facsimile image",                                      "Atlantis Design Group",
    RESERVED,                 "FIGR", "Deluxe Video",                                         "EA",
    NULL,                     "FILM", "LIST FILM - stores ILBMs with interleaved 8SVX audio", "?",
    RESERVED,                 "FNTR", "Raster font",                                          "EA",
    RESERVED,                 "FNTV", "Vector font",                                          "EA",
    STANDARD,                 "FORM", "Group identifier",                                     "EA/CBM",
    STANDARD | RKM,           "FTXT", "Formatted TeXT",                                       "EA/CBM",
    PROPOSAL | PRIVATE,       "GRYP", "Byteplane storage",                                    "?",
    RESERVED,                 "GSCR", "General music SCoRe",                                  "EA",
    PROPOSAL | PRIVATE,       "GUI ", "User interface storage",                               "?",
    RKM | CD,                 "HEAD", "Flow idea processor",                                  "New Horizons Software",
    STANDARD | RKM | CD,      "ILBM", "EA IFF 85 raster bitmap form",                         "EA/CBM",
    RESERVED,                 "IOBJ", "?",                                                    "Seven Seas Software",
    RESERVED,                 "IODK", "?",                                                    "Merging Technologies",
    RESERVED,                 "ITRF", "?",                                                    "?",
    RESERVED,                 "JMOV", "?",                                                    "Merging Technologies",
    STANDARD,                 "LIST", "EA IFF 85 group identifier",                           "EA/CBM",
    RESERVED,                 "MFAX", "Facsimile?",                                           "TKR GmbH & Co.",
    NULL,                     "MIDI", "MIDI?",                                                "Circum Design",
    PRIVATE,                  "MOVI", "LIST MOVIe?",                                          "?",
    PRIVATE,                  "MSCX", "Music-X format",                                       "?",
    RESERVED,                 "MSMP", "Temporarily reserved",                                 "?",
    RKM | CD,                 "MTRX", "Numerical data storage (MathVision)",                  "Seven Seas Software",
    NULL,                     "NSEQ", "Numerical sequence",                                   "Stockhausen GmbH",
    PROPOSAL | CD,            "OB3D", "Standard 3D object",                                   "?",
    RKM | CD,                 "PGTB", "ProGram TraceBack",                                    "SAS Institute",
    RESERVED,                 "PICS", "Macintosh picture",                                    "EA",
    RESERVED | OBSOLETE,      "PLBM", "?",                                                    "EA",
    RESERVED | PROPOSAL | CD, "PMBC", "24-bit accurate images",                               "Black Belt Systems",
    RESERVED | PRIVATE,       "PREF", "User preferences data",                                "CBM",
    STANDARD,                 "PROP", "Group identifier",                                     "EA/CBM",
    RKM | CD,                 "PRSP", "DPaint IV perspective move form",                      "EA",
    NULL,                     "PTCH", "Patch file",                                           "SAS Institute",
    RESERVED,                 "PTXT", "Temporarily reserved",                                 "?",
    NULL,                     "RGB4", "4-bit RGB",                                            "?",
    RKM | CD,                 "RGB8", "RGB image (Turbo Silver)",                             "Impulse",
    RKM | CD,                 "RGBN", "RGB image (Turbo Silver)",                             "Impulse",
    RESERVED,                 "RGBX", "Temporarily reserved",                                 "?",
    PRIVATE,                  "ROXN", "Animation",                                            "?",
    RKM | CD,                 "SAMP", "SAMPled sound",                                        "Jim Fiore & Jeff Glatt",
    PRIVATE,                  "SC3D", "SCene format (Sculpt-3D)",                             "?",
    PRIVATE,                  "SHAK", "SHAKespeare format",                                   "?",
    RESERVED | PRIVATE,       "SHO1", "?",                                                    "Gary Bonham",
    RESERVED | PRIVATE,       "SHOW", "?",                                                    "Gary Bonham",
    STANDARD | RKM,           "SMUS", "Simple MUsic Score",                                   "EA/CBM",
    CD,                       "SPLT", "File SPLiTting system",                                "ASDG",
    RESERVED,                 "SSRE", "?",                                                    "Merging Technologies",
    UNREGISTERED,             "SWRT", "?",                                                    "?",
    NULL,                     "SYTH", "SoundQuest Master Librarian MIDI System driver",       "?",
    RESERVED,                 "TCDE", "?",                                                    "Merging Technologies",
    RKM | CD,                 "TDDD", "3D rendering data (Turbo Silver)",                     "Impulse",
    UNREGISTERED,             "TERM", "?",                                                    "?",
    CD,                       "TMUI", "ToolMaker User Interface",                             "Michael Erwin",
    CD,                       "TREE", "Arbitrary data structures as trees (or nested lists)", "Stefan Reisner",
    CD | PROPOSAL,            "TRKR", "TRacKeR style music module",                           "Full Tilt Entertainment",
    RESERVED,                 "USCR", "Uhuru SCoRe",                                          "EA",
    RESERVED,                 "UVOX", "Uhuru Macintosh VOiXe",                                "EA",
    PRIVATE,                  "VDEO", "Deluxe ViDEO",                                         "EA",
    RKM | CD,                 "WORD", "ProWrite document",                                    "New Horizons Software",
    CD,                       "YUVN", "For storage of Y:U:V image data",                      "MacroSystem"
};

AGLOBAL void iff1(void)
{   verynewwindow
    (   IFF1WIDTH, IFF1HEIGHT + yoffset,
        "Report+: IFF Registry",
        BUTTONIDCMP | STRINGIDCMP | LISTVIEWIDCMP
    );
    if (fillwindows)
    {   SetAPen(MainWindowPtr->RPort, 0);
        RectFill(MainWindowPtr->RPort,  10, yoffset + 122,  10 + 160, yoffset + 122 + 204 - 1); // LV61_List1
        RectFill(MainWindowPtr->RPort, 180, yoffset + 122, 180 + 450, yoffset + 122 + 204 - 1); // LV61_List2
        RectFill(MainWindowPtr->RPort, 130, yoffset +  20, 130 + 334, yoffset +  20 +  12    ); // TE61_FORMDesc
        RectFill(MainWindowPtr->RPort, 130, yoffset +  32, 130 + 334, yoffset +  32 +  12    ); // TE61_Contributor
        RectFill(MainWindowPtr->RPort, 130, yoffset +  44, 130 + 334, yoffset +  44 +  12    ); // TE61_ChunkDesc
        RectFill(MainWindowPtr->RPort, 130, yoffset + 338, 130 + 350, yoffset + 338 +  12    ); // TE61_Status
    }

    /* FORM ID */
    setgadget(130, yoffset + 8, 56, 12, "_FORM ID:", NULL);
    ST61_FORMID = PrevGadPtr = (struct Gadget *) CreateGadget
    (   STRING_KIND,
        PrevGadPtr,
        &Gadget,
        GTST_String, queryform,
        GTST_MaxChars, 4,
        GA_TabCycle, TRUE,
        GA_Immediate, TRUE,
        GT_Underscore, '_',
        STRINGA_ReplaceMode, TRUE,
        TAG_DONE
    );
    /* FORM description */
    setgadget(130, yoffset + 20, 334, 12, "Description:", NULL);
    TE61_FORMDesc = PrevGadPtr = (struct Gadget *) CreateGadget
    (   TEXT_KIND,
        PrevGadPtr,
        &Gadget,
        GTTX_Text, "-",
        GTTX_Border, TRUE,
        TAG_DONE
    );
    /* contributor name */
    setgadget(130, yoffset + 32, 334, 12, "Contributor:", NULL);
    TE61_Contributor = PrevGadPtr = (struct Gadget *) CreateGadget
    (   TEXT_KIND,
        PrevGadPtr,
        &Gadget,
        GTTX_Text, "-",
        GTTX_Border, TRUE,
        TAG_DONE
    );
    /* chunk description */
    setgadget(130, yoffset + 44, 334, 12, "Chunk info:", NULL);
    TE61_ChunkDesc = PrevGadPtr = (struct Gadget *) CreateGadget
    (   TEXT_KIND,
        PrevGadPtr,
        &Gadget,
        GTTX_Text, "-",
        GTTX_Border, TRUE,
        TAG_DONE
    );

    /* flags */
    setgadget(596, yoffset + 32, 0, 0, "Obsolete:", NULL);
    CB61_Obsolete = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CHECKBOX_KIND,
        PrevGadPtr,
        &Gadget,
        GA_Disabled, TRUE,
        GTCB_Checked, iff.obsolete,
        TAG_DONE
    );
    setgadget(596, yoffset + 44, 0, 0, "Private:", NULL);
    CB61_Private = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CHECKBOX_KIND,
        PrevGadPtr,
        &Gadget,
        GA_Disabled, TRUE,
        GTCB_Checked, iff.private,
        TAG_DONE
    );
    setgadget(596, yoffset + 56, 0, 0, "Proposal:", NULL);
    CB61_Proposal = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CHECKBOX_KIND,
        PrevGadPtr,
        &Gadget,
        GA_Disabled, TRUE,
        GTCB_Checked, iff.proposal,
        TAG_DONE
    );
    setgadget(596, yoffset + 68, 0, 0, "Reserved:", NULL);
    CB61_Reserved = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CHECKBOX_KIND,
        PrevGadPtr,
        &Gadget,
        GA_Disabled, TRUE,
        GTCB_Checked, iff.reserved,
        TAG_DONE
    );
    setgadget(596, yoffset + 80, 0, 0, "Standard:", NULL);
    CB61_Standard = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CHECKBOX_KIND,
        PrevGadPtr,
        &Gadget,
        GA_Disabled, TRUE,
        GTCB_Checked, iff.standard,
        TAG_DONE
    );
    setgadget(596, yoffset + 92, 0, 0, "Unregistered:", NULL);
    CB61_Unregistered = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CHECKBOX_KIND,
        PrevGadPtr,
        &Gadget,
        GA_Disabled, TRUE,
        GTCB_Checked, iff.unregistered,
        TAG_DONE
    );

    setgadget(596, yoffset + 350, 0, 0, "RKM:", NULL);
    CB61_RKM = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CHECKBOX_KIND,
        PrevGadPtr,
        &Gadget,
        GA_Disabled, TRUE,
        GTCB_Checked, iff.rkm,
        TAG_DONE
    );
    setgadget(596, yoffset + 362, 0, 0, "ADCD 2.1:", NULL);
    CB61_CD = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CHECKBOX_KIND,
        PrevGadPtr,
        &Gadget,
        GA_Disabled, TRUE,
        GTCB_Checked, iff.cd,
        TAG_DONE
    );

    setgadget( 10, yoffset + 122, 160, 204, "Chunks:", NULL);
    LV61_List1 = PrevGadPtr = (struct Gadget *) CreateGadget
    (   LISTVIEW_KIND,
        PrevGadPtr,
        &Gadget,
        GTLV_Labels, NULL,
        GTLV_ShowSelected, NULL,
        TAG_DONE
    );
    setgadget(180, yoffset + 122, 450, 204, "Chunk contents:", NULL);
    LV61_List2 = PrevGadPtr = (struct Gadget *) CreateGadget
    (   LISTVIEW_KIND,
        PrevGadPtr,
        &Gadget,
        GTLV_Labels, NULL,
        TAG_DONE
    );

    /* status */
    setgadget(130, yoffset + 338, 350, 12, "Status:", NULL);
    TE61_Status = PrevGadPtr = (struct Gadget *) CreateGadget
    (   TEXT_KIND,
        PrevGadPtr,
        &Gadget,
        GTTX_Text, "Ready.",
        GTTX_Border, TRUE,
        TAG_DONE
    );

    /* pathname */
    setgadget(130, yoffset + 350, 320, 12, "_Pathname:", NULL);
    ST61_Pathname = PrevGadPtr = (struct Gadget *) CreateGadget
    (   STRING_KIND,
        PrevGadPtr,
        &Gadget,
        GTST_String, iff.pathname,
        GTST_MaxChars, VLONGFIELD,
        GA_TabCycle, TRUE,
        GA_Immediate, TRUE,
        GT_Underscore, '_',
        TAG_DONE
    );

    /* pathname... */
    setgadget(452, yoffset + 350, 28, 12, "_...", NULL);
    BU61_PathnameASL = PrevGadPtr = (struct Gadget *) CreateGadget
    (   BUTTON_KIND,
        PrevGadPtr,
        &Gadget,
        GT_Underscore, '_',
        TAG_DONE
    );

    setgadget(130, yoffset + 68, 0, 0, "_Raw view only?", PLACETEXT_RIGHT);
    CB61_Raw = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CHECKBOX_KIND,
        PrevGadPtr,
        &Gadget,
        GTCB_Checked, iff.raw,
        GT_Underscore, '_',
        TAG_DONE
    );

    drawgadgets((UWORD) ~0);

    SetDrMd(MainWindowPtr->RPort, JAM2);
    SetAPen(MainWindowPtr->RPort, BLACK);
    if (fillwindows)
    {   getfillcolour();
        SetBPen(MainWindowPtr->RPort, fillcolour);
    }

    DrawBevelBox(MainWindowPtr->RPort, 474, yoffset + 20, 156, 18 + (12 * 6), GT_VisualInfo, VisualInfoPtr, GTBB_Recessed, TRUE, TAG_END);
    Move(MainWindowPtr->RPort, 474 + (156 / 2) - ((15 * FONTX) / 2), yoffset +  20 + (FONTY / 2) - 1);
    Text(MainWindowPtr->RPort, "Official Status", 15);

    DrawBevelBox(MainWindowPtr->RPort, 490, yoffset + 338, 140, 18 + (12 * 2), GT_VisualInfo, VisualInfoPtr, GTBB_Recessed, TRUE, TAG_END);
    Move(MainWindowPtr->RPort, 560             - ((13 * FONTX) / 2), yoffset + 338 + (FONTY / 2) - 1);
    Text(MainWindowPtr->RPort, "Documentation", 13);

    if (iff.pathname[0])
    {   readiff();
    } elif (queryform[0])
    {   iffquery();
    }
    ActivateGadget(ST61_Pathname, MainWindowPtr, NULL);
    loop();
    strcpy
    (   queryform,
        ((struct StringInfo *) ST61_FORMID->SpecialInfo)->Buffer
    );
    strcpy
    (   iff.pathname,
        ((struct StringInfo *) ST61_Pathname->SpecialInfo)->Buffer
    );
    closewindow();
}

AGLOBAL void iff_loop(ULONG class, struct Gadget* addr, UWORD code, UWORD qual)
{   if (class == IDCMP_RAWKEY)
    {   if (qual & IEQUALIFIER_CONTROL)
        {   if (code == SCAN_UP)
            {   GT_SetGadgetAttrs
                (   LV61_List1,
                    MainWindowPtr,
                    NULL,
                    GTLV_Top, 0,
                    TAG_DONE
                );
            } elif (code == SCAN_DOWN)
            {   if (list1lines > LIST1LINES)
                {   GT_SetGadgetAttrs
                    (   LV61_List1,
                        MainWindowPtr,
                        NULL,
                        GTLV_Top, list1lines - LIST1LINES,
                        TAG_DONE
                    );
    }   }   }   }
    elif (class == IDCMP_VANILLAKEY)
    {   code = toupper(code);
        if (code == ESCAPE)
            page = 0;
        elif (code == 'F')
            ActivateGadget(ST61_FORMID, MainWindowPtr, NULL);
        elif (code == 'P')
            ActivateGadget(ST61_Pathname, MainWindowPtr, NULL);
        elif (code == 'R')
        {   if (iff.raw)
            {   iff.raw = FALSE;
            } else iff.raw = TRUE;
            GT_SetGadgetAttrs
            (   CB61_Raw,
                MainWindowPtr,
                NULL,
                GTCB_Checked, iff.raw,
                TAG_DONE
            );
            if (selectedchunk && known)
            {   tellchunk(selectedchunk);
        }   }
        elif (code == '.')
        {   if (asl("~(#?.info)"))
            {   strcpy(iff.pathname, aslresult);
                GT_SetGadgetAttrs
                (   ST61_Pathname,
                    MainWindowPtr,
                    NULL,
                    GTST_String, iff.pathname,
                    TAG_DONE
                );
                readiff();
    }   }   }
    elif (class == IDCMP_GADGETUP)
    {   /* IDCMP_GADGETUP is sent by the string gadget
        when the user presses RETURN, ENTER, Help, Tab
        or Shift-Tab inside the string gadget. */
        
        if (addr == BU99_Right)
            page = 0;
        elif (addr == CB61_Raw)
        {   if (CB61_Raw->Flags & GFLG_SELECTED)
            {   iff.raw = TRUE;
            } else iff.raw = FALSE;
            GT_SetGadgetAttrs
            (   CB61_Raw,
                MainWindowPtr, NULL,
                GTCB_Checked, iff.raw,
                TAG_DONE
            );
            if (selectedchunk && known)
            {   tellchunk(selectedchunk);
        }   }
        elif (addr == ST61_Pathname)
	{   strcpy
            (   iff.pathname,
                ((struct StringInfo *) ST61_Pathname->SpecialInfo)->Buffer
	    );
            readiff();
        } elif (addr == ST61_FORMID)
        {   strcpy
            (   queryform,
                ((struct StringInfo *) ST61_FORMID->SpecialInfo)->Buffer
	    );
            iff.pathname[0] = 0;
            GT_SetGadgetAttrs
            (   ST61_Pathname,
                MainWindowPtr,
                NULL,
                GTST_String, iff.pathname,
                TAG_DONE
            );
            GT_SetGadgetAttrs
            (   TE61_Status,
                MainWindowPtr,
                NULL,
                GTTX_Text, "Ready.",
                TAG_DONE
            );
            iffquery();
        } elif (addr == BU61_PathnameASL)
        {   if (asl("~(#?.info)"))
            {   strcpy(iff.pathname, aslresult);
                GT_SetGadgetAttrs
                (   ST61_Pathname,
                    MainWindowPtr,
                    NULL,
                    GTST_String, iff.pathname,
                    TAG_DONE
                );
                readiff();
        }   }
        elif (addr == LV61_List1)
        {   selectedchunk = code + 1;
            tellchunk(selectedchunk);
}   }   }

MODULE void iffquery(void)
{   ULONG i;

    /* Make any corrections to input now, to make it
    easier to search the database. */
    for (i = 0; i <= 3; i++)
        if (queryform[i] >= 97 && queryform[i] <= 122)
            queryform[i] -= 32;
        elif (queryform[i] == 0)
            queryform[i] = ' ';
    queryform[4] = 0;
    GT_SetGadgetAttrs
    (   ST61_FORMID,
        MainWindowPtr,
        NULL,
        GTTX_Text, queryform,
        TAG_DONE
    );
    selectedform = (UWORD) -1;
    for (i = 0; i <= FORMS; i++)
    if
    (   queryform[0] == form[i].name[0]
     && queryform[1] == form[i].name[1]
     && queryform[2] == form[i].name[2]
     && queryform[3] == form[i].name[3]
    )
    {   selectedform = i;
        break;
    }
    selectedchunk = 0;
    if (selectedform == (UWORD) -1)
    {   iff.cd           =
        iff.rkm          =
        iff.private      =
        iff.proposal     =
        iff.obsolete     =
        iff.reserved     =
        iff.standard     =
        iff.unregistered = FALSE;
        GT_SetGadgetAttrs
        (   TE61_FORMDesc,
            MainWindowPtr,
            NULL,
            GTTX_Text, "-",
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   TE61_Contributor,
            MainWindowPtr,
            NULL,
            GTTX_Text, "-",
            TAG_DONE
        );
    } else
    {   iff.cd           = form[selectedform].flags & CD;
        iff.rkm          = form[selectedform].flags & RKM;
        iff.private      = form[selectedform].flags & PRIVATE;
        iff.proposal     = form[selectedform].flags & PROPOSAL;
        iff.obsolete     = form[selectedform].flags & OBSOLETE;
        iff.reserved     = form[selectedform].flags & RESERVED;
        iff.standard     = form[selectedform].flags & STANDARD;
        iff.unregistered = form[selectedform].flags & UNREGISTERED;
        GT_SetGadgetAttrs
        (   TE61_FORMDesc,
            MainWindowPtr,
            NULL,
            GTTX_Text, form[selectedform].desc,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   TE61_Contributor,
            MainWindowPtr,
            NULL,
            GTTX_Text, form[selectedform].contributor,
            TAG_DONE
        );
    }

    writeiffgadgets();

    GT_SetGadgetAttrs
    (   LV61_List1,
        MainWindowPtr,
        NULL,
        GTLV_Labels, (UWORD) ~0,
        TAG_DONE
    );
    if (List1Nodes)
    {   FreeNameNodes(&List1);
        List1Nodes = FALSE;
    }
    NewList(&List1);
    GT_SetGadgetAttrs
    (   LV61_List1,
        MainWindowPtr,
        NULL,
        GTLV_Labels, &List1,
        GTLV_Selected, (UWORD) ~0,
        TAG_DONE
    );

    GT_SetGadgetAttrs
    (   LV61_List2,
        MainWindowPtr,
        NULL,
        GTLV_Labels, (UWORD) ~0,
        TAG_DONE
    );
    if (List2Nodes)
    {   FreeNameNodes(&List2);
        List2Nodes = FALSE;
    }
    NewList(&List2);
    GT_SetGadgetAttrs
    (   LV61_List2,
        MainWindowPtr,
        NULL,
        GTLV_Labels, &List2,
        GTLV_Selected, (UWORD) ~0,
        TAG_DONE
    );

    for (i = 0; i < items; i++)
    {   if (contents[i].DataPtr)
        {   FreeMem(contents[i].DataPtr, contents[i].bytes);
            contents[i].DataPtr = NULL;
    }   }
    items = 0;
}

MODULE void readiff(void)
{   LONG error;

    list1lines = 0;

    iffquery();

    /* Allocate IFF_File structure. */
    if (!(IFFHandle = AllocIFF()))
    {   DisplayBeep(NULL);
        GT_SetGadgetAttrs
        (   TE61_Status,
            MainWindowPtr,
            NULL,
            GTTX_Text, "AllocIFF() failed!",
            TAG_DONE
        );
        goto bye;
    }

    first = TRUE;

    /* Set up IFF_File for AmigaDOS I/O.  */
    if (!(IFFHandle->iff_Stream = Open(iff.pathname, MODE_OLDFILE)))
    {   DisplayBeep(NULL);
        GT_SetGadgetAttrs
        (   TE61_Status,
            MainWindowPtr,
            NULL,
            GTTX_Text, "Can't open file!",
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   TE61_FORMDesc,
            MainWindowPtr,
            NULL,
            GTTX_Text, "-",
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   TE61_Contributor,
            MainWindowPtr,
            NULL,
            GTTX_Text, "-",
            TAG_DONE
        );
        queryform[0]     = 0;
        iff.obsolete     =
        iff.private      =
        iff.proposal     =
        iff.reserved     =
        iff.standard     =
        iff.unregistered =
        iff.rkm          =
        iff.cd           = FALSE;
        writeiffgadgets();
        goto bye;
    }
    InitIFFasDOS(IFFHandle);

    /* Start the IFF transaction. */
    if (error = OpenIFF(IFFHandle, IFFF_READ))
    {   DisplayBeep(NULL);
        GT_SetGadgetAttrs
        (   TE61_Status,
            MainWindowPtr,
            NULL,
            GTTX_Text, "OpenIFF() failed!",
            TAG_DONE
        );
        goto bye;
    }

    while (1)
    {   /* IFFPARSE_RAWSTEP permits us to have precision monitoring of the
         * parsing process, which is necessary if we wish to print the
         * structure of an IFF file.
         *   ParseIFF() with _RAWSTEP will return the following things for
         * the following reasons:
         *
         * Return code:                 Reason:
         * 0                            Entered new context.
         * IFFERR_EOC                   About to leave a context.
         * IFFERR_EOF                   Encountered end-of-file.
         * <anything else>              A parsing error.
         */
        error = ParseIFF(IFFHandle, IFFPARSE_RAWSTEP);

        /*
         * Since we're only interested in when we enter a context, we
         * "discard" end-of-context (_EOC) events.
         */
        if (error == IFFERR_EOC)
            continue;
        elif (error)
        {   // Leave the loop if there is any other error.
            break;
        }

        /* If we get here, error was zero. Print out the current state of
         * affairs. */
        PrintTopChunk();
    }

    /* If error was IFFERR_EOF, then the parser encountered the end of
     * the file without problems. Otherwise, we print a diagnostic.
     */
    if (error == IFFERR_EOF)
    {   GT_SetGadgetAttrs
        (   TE61_Status,
            MainWindowPtr,
            NULL,
            GTTX_Text, "Done.",
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   LV61_List1,
            MainWindowPtr,
            NULL,
            GTLV_Labels, &List1,
            GTLV_Selected, (UWORD) ~0,
            TAG_DONE
        );
    } else
    {   GT_SetGadgetAttrs
        (   TE61_Status,
            MainWindowPtr,
            NULL,
            GTTX_Text, errormsgs[-error - 1],
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   LV61_List1,
            MainWindowPtr,
            NULL,
            GTLV_Labels, NULL,
            TAG_DONE
        );
    }

bye:
    if (IFFHandle)
    {   /* Terminate the IFF transaction with the stream. Free all
         * associated structures. */
        CloseIFF(IFFHandle);
        // Close the stream itself.
        if (IFFHandle->iff_Stream)
        {   Close(IFFHandle->iff_Stream);
        }
        // Free the IFF_File structure itself.
        FreeIFF(IFFHandle);
        IFFHandle = NULL;
}   }

AGLOBAL void iff_exit(void)
{   ULONG i;

    if (IFFHandle)
    {   /* Terminate the IFF transaction with the stream. Free all
         * associated structures. */
        CloseIFF(IFFHandle);
        // Close the stream itself.
        if (IFFHandle->iff_Stream)
        {   Close(IFFHandle->iff_Stream);
        }
        // Free the IFF_File structure itself.
        FreeIFF(IFFHandle);
        IFFHandle = NULL;
    }

    if (List2Nodes)
    {   FreeNameNodes(&List2);
        List2Nodes = FALSE;
    }
    if (List1Nodes)
    {   FreeNameNodes(&List1);
        List1Nodes = NULL;
    }
    for (i = 0; i < items; i++)
    {   if (contents[i].DataPtr)
        {   FreeMem(contents[i].DataPtr, contents[i].bytes);
            contents[i].DataPtr = NULL;
    }   }
    items = 0;
}

MODULE void PrintTopChunk(void)
{   struct ContextNode* top;
    short               i;
    char                idbuf[5];
    ULONG               length;

    /* Get a pointer to the context node describing the current context. */
    if (!(top = CurrentChunk(IFFHandle)))
        return;

    /* Print spaces equivalent to the current nesting depth of chunks
     * processed so far.
     *   This will cause nested chunks to be printed out indented. */

    tempstring1[0] = 0;
    if (IFFHandle->iff_Depth > 2)
    {   for (i = IFFHandle->iff_Depth - 2; i--; )
           strcat(tempstring1, " ");
    }
    strcpy(contents[items].name, IDtoStr(top->cn_ID, idbuf));
    contents[items].DataPtr = NULL;

    /* Print out the current chunk's ID and size. */
    strcat(tempstring1, IDtoStr(top->cn_ID, idbuf));
    stcl_d(tempstring2, top->cn_Size);

    length = IFFXCHARS - strlen(tempstring1) - strlen(tempstring2);
    for (i = 1; i <= length; i++)
    {   strcat(tempstring1, " ");
    }
    strcat(tempstring1, tempstring2);

    /* Print the current chunk's type, with a newline. */
    AddNameToTail(&List1, tempstring1);
    list1lines++;
    List1Nodes = TRUE;

    if (!strcmp(IDtoStr(top->cn_ID, idbuf), "FORM"))
    {   if (first)
        {   first = FALSE;
            strcpy(queryform, IDtoStr(top->cn_Type, idbuf));
            iffquery();
    }   }
    else
    {   contents[items].bytes = top->cn_Size;
        if (!(contents[items].DataPtr = AllocMem(contents[items].bytes, MEMF_CLEAR)))
        {   rq("Out of memory!");
        }
        if (ReadChunkBytes(IFFHandle, contents[items].DataPtr, contents[items].bytes) < 0)
        {   rq("ReadChunkBytes() failed!");
    }   }

    items++;
    if (items > ITEMS)
    {   rq("Too many chunks!");
}   }

MODULE void tellchunk(UWORD which)
{   SLONG           svalue;
    ULONG           i, j, uvalue, length, markers, currentpos;
    struct DateTime DateTime;

    if (which == (UWORD) ~0)
    {   return;
    }

    GT_SetGadgetAttrs
    (   LV61_List2,
        MainWindowPtr,
        NULL,
        GTLV_Labels, (UWORD) ~0,
        TAG_DONE
    );
    if (List2Nodes)
    {   FreeNameNodes(&List2);
        List2Nodes = FALSE;
    }
    NewList(&List2);

    known = FALSE;
    List2Nodes = TRUE;
    /* Although it is possible that this function will return with an
    empty List2, remember that it is harmless to call FreeNameNodes on
    a valid, empty List (ie. one which has had NewList() called). */

    if (!stricmp(contents[which].name, "FORM"))
    {   chunkdesc("-", TRUE);
    } elif (!stricmp(contents[which].name, "(c) "))
    {   chunkdesc("© Copyright", TRUE);

        if (!iff.raw)
        {   strcpy(tempstring1, "© Copyright:        ");
            strcat(tempstring1, contents[which].DataPtr);
            AddNameToTail(&List2, tempstring1);
    }   }
    elif (!stricmp(contents[which].name, "AUTH"))
    {   chunkdesc("Author", TRUE);

        if (!iff.raw)
        {   strcpy(tempstring1, "Author:             ");
            strcat(tempstring1, contents[which].DataPtr);
            AddNameToTail(&List2, tempstring1);
    }   }
    elif (!stricmp(contents[which].name, "ANNO"))
    {   chunkdesc("Annotation", TRUE);

        if (!iff.raw)
        {   strcpy(tempstring1, "Annotation:         ");
            strcat(tempstring1, contents[which].DataPtr);
            AddNameToTail(&List2, tempstring1);
    }   }
    elif (!stricmp(contents[which].name, "NAME"))
    {   chunkdesc("Name", TRUE);

        if (!iff.raw)
        {   strcpy(tempstring1, "Name:               ");
            strcat(tempstring1, contents[which].DataPtr);
            AddNameToTail(&List2, tempstring1);
    }   }
    elif (!stricmp(contents[which].name, "FVER"))
    {   chunkdesc("AmigaDOS version string", TRUE);

        if (!iff.raw)
        {   strcpy(tempstring1, "Version:            ");
            // bytes 0-5 are "$VER: "
            strcat(tempstring1, &contents[which].DataPtr[6]);
            AddNameToTail(&List2, tempstring1);
    }   }
    elif
    (   (!stricmp(queryform, "FTXT") || !stricmp(queryform, "WORD"))
     && !stricmp(contents[which].name, "FSCC")
    )
    {   chunkdesc("Font/style/colour change", TRUE);

        if (!iff.raw)
        {
        strcpy(tempstring1, "Location:            ");
        uvalue = getuword(contents[which].DataPtr); // UWORD
        stcl_d(tempstring2, uvalue);
        strcat(tempstring1, tempstring2);
        AddNameToTail(&List2, tempstring1);

        strcpy(tempstring1, "Font number:         ");
        uvalue = contents[which].DataPtr[2]; // UBYTE
        stcl_d(tempstring2, uvalue);
        strcat(tempstring1, tempstring2);
        AddNameToTail(&List2, tempstring1);

        strcat(tempstring1, " Style:");
        AddNameToTail(&List2, tempstring1);

        strcat(tempstring1, " Underlined?         ");
        if (contents[which].DataPtr[3] & 1)
        {   strcat(tempstring1, "Yes");
        } else strcat(tempstring1, "No");
        AddNameToTail(&List2, tempstring1);

        strcat(tempstring1, " Bold?               ");
        if (contents[which].DataPtr[3] & 2)
        {   strcat(tempstring1, "Yes");
        } else strcat(tempstring1, "No");
        AddNameToTail(&List2, tempstring1);

        strcat(tempstring1, " Italic?             ");
        if (contents[which].DataPtr[3] & 4)
        {   strcat(tempstring1, "Yes");
        } else strcat(tempstring1, "No");
        AddNameToTail(&List2, tempstring1);

            strcat(tempstring1, " Extended?           ");
            if (contents[which].DataPtr[3] & 8)
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            AddNameToTail(&List2, tempstring1);

            strcat(tempstring1, " ColourFont?         ");
            if (contents[which].DataPtr[3] & 64)
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            AddNameToTail(&List2, tempstring1);

            strcat(tempstring1, " Tagged?             ");
            if (contents[which].DataPtr[3] & 128)
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Miscellaneous style: ");
            if (contents[which].DataPtr[4] == 0)
            {   strcat(tempstring1, "None");
            } elif (contents[which].DataPtr[4] == 1)
            {   strcat(tempstring1, "Superscript");
            } elif (contents[which].DataPtr[4] == 2)
            {   strcat(tempstring1, "Subscript");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Colour:              ");
            uvalue = contents[which].DataPtr[5]; // UBYTE
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);
    }   }
    elif (!strcmp(queryform, "FTXT"))
    {   if (!strcmp(contents[which].name, "FONS"))
        {   chunkdesc("Font specifier", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "ID number:          ");
            stcl_d(tempstring2, contents[which].DataPtr[0]);
            strcat(tempstring1, tempstring2);
            if (contents[which].DataPtr[0] > 9)
            {   strcat(tempstring1, " (invalid)");
            }
            AddNameToTail(&List2, tempstring1);

            // Next is a pad byte ([1]).

            strcpy(tempstring1, "Proportional?       ");
            uvalue = contents[which].DataPtr[2];
            if (uvalue == 0)
            {   strcat(tempstring1, "Unknown");
            } elif (uvalue == 1)
            {   strcat(tempstring1, "No");
            } elif (uvalue == 2)
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "?"); // not the same as `Unknown', of course!
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Serifs?             ");
            uvalue = contents[which].DataPtr[3];
            if (uvalue == 0)
            {   strcat(tempstring1, "Unknown");
            } elif (uvalue == 1)
            {   strcat(tempstring1, "No");
            } elif (uvalue == 2)
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "?"); // not the same as `Unknown', of course!
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Font name:          ");
            strcat(tempstring1, &(contents[which].DataPtr[4]));
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "CHRS"))
        {   chunkdesc("Stream of text", FALSE);
    }   }
    elif (!strcmp(queryform, "PREF"))
    {   if (!strcmp(contents[which].name, "ICTL"))
        {   chunkdesc("IControl preferences", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Verify timeout:         ");
            uvalue = getuword(&(contents[which].DataPtr[16]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Meta drag mouse event:  ");
            svalue = getsword(&(contents[which].DataPtr[18]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            AddNameToTail(&List2, "Flags:");
            uvalue = getulong(&(contents[which].DataPtr[20]));

            strcpy(tempstring1, " Coerce colours?        ");
            if (uvalue & 1) // ICF_COERCE_COLORS
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Coerce interlace?      ");
            if (uvalue & 2) // ICF_COERCE_LACE
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " String gadget filter?  ");
            if (uvalue & 4) // ICF_STRGAD_FILTER
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Menu snap?             ");
            if (uvalue & 8) // ICF_MENUSNAP
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Mode promotion?        ");
            if (uvalue & 16) // ICF_MODEPROMOTE
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Square ratio?          "); // this one is new for OS3.9
            if (uvalue & 32) // ICF_SQUARE_RATIO
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            AddNameToTail(&List2, tempstring1);

            AddNameToTail(&List2, "Command keys:");

            strcat(tempstring1, " Workbench to front:    ");
            stcl_d(tempstring2, contents[which].DataPtr[24]);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcat(tempstring1, " Front screen to back:  ");
            stcl_d(tempstring2, contents[which].DataPtr[25]);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcat(tempstring1, " Requester TRUE:        ");
            stcl_d(tempstring2, contents[which].DataPtr[26]);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcat(tempstring1, " Requester FALSE:       ");
            stcl_d(tempstring2, contents[which].DataPtr[27]);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "SERL"))
        {   chunkdesc("Serial preferences", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Unit 0 mapping:         ");
            uvalue = getulong(&(contents[which].DataPtr[12]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Baud rate:              ");
            uvalue = getulong(&(contents[which].DataPtr[16]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " bps");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Input buffer size:      ");
            uvalue = getulong(&(contents[which].DataPtr[20]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            if (uvalue > 65536)
            {   strcat(tempstring1, "!");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Output buffer size:     ");
            uvalue = getulong(&(contents[which].DataPtr[24]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            if (uvalue > 65536)
            {   strcat(tempstring1, "!");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Input handshaking:      ");
            if (contents[which].DataPtr[28] == 0)
            {   strcat(tempstring1, "0 (XON)");  // HSHAKE_XON
            } elif (contents[which].DataPtr[28] == 1)
            {   strcat(tempstring1, "1 (RTS)");  // HSHAKE_RTS
            } elif (contents[which].DataPtr[28] == 2)
            {   strcat(tempstring1, "2 (None)"); // HSHAKE_NONE
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Output handshaking:     ");
            if (contents[which].DataPtr[29] == 0)
            {   strcat(tempstring1, "0 (XON)");  // HSHAKE_XON
            } elif (contents[which].DataPtr[29] == 1)
            {   strcat(tempstring1, "1 (RTS)");  // HSHAKE_RTS
            } elif (contents[which].DataPtr[29] == 2)
            {   strcat(tempstring1, "2 (None)"); // HSHAKE_NONE
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Parity:                 ");
            if (contents[which].DataPtr[30] == 0)
            {   strcat(tempstring1, "0 (None)");  // PARITY_NONE
            } elif (contents[which].DataPtr[30] == 1)
            {   strcat(tempstring1, "1 (Even)");  // PARITY_EVEN
            } elif (contents[which].DataPtr[30] == 2)
            {   strcat(tempstring1, "2 (Odd)");   // PARITY_ODD
            } elif (contents[which].DataPtr[30] == 3)
            {   strcat(tempstring1, "3 (Mark)");  // PARITY_MARK
            } elif (contents[which].DataPtr[30] == 4)
            {   strcat(tempstring1, "4 (Space)"); // PARITY_SPACE
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "I/O bits per character: ");
            stcl_d(tempstring2, contents[which].DataPtr[31]);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Stop bits:              ");
            stcl_d(tempstring2, contents[which].DataPtr[32]);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "ASL "))
        {   chunkdesc("ASL preferences", TRUE);

            // 16 reserved bytes at start

            if (!iff.raw)
            {   strcpy(tempstring1, "Sort by:                ");
                if (contents[which].DataPtr[16] == 0)
                {   strcat(tempstring1, "0 (name)");
                } elif (contents[which].DataPtr[16] == 1)
                {   strcat(tempstring1, "1 (date)");
                } elif (contents[which].DataPtr[16] == 2)
                {   strcat(tempstring1, "2 (size)");
                } else
                {   strcat(tempstring1, "?");
                }
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Sort drawers:           ");
                if (contents[which].DataPtr[17] == 0)
                {   strcat(tempstring1, "0 (first)");
                } elif (contents[which].DataPtr[17] == 1)
                {   strcat(tempstring1, "1 (mix)");
                } elif (contents[which].DataPtr[17] == 2)
                {   strcat(tempstring1, "2 (last)");
                } else
                {   strcat(tempstring1, "?");
                }
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Sort order:             ");
                if (contents[which].DataPtr[18] == 0)
                {   strcat(tempstring1, "0 (ascending)");
                } elif (contents[which].DataPtr[18] == 1)
                {   strcat(tempstring1, "1 (descending)");
                } else
                {   strcat(tempstring1, "?");
                }
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Override?               ");
                if (contents[which].DataPtr[19] & 64)
                {   strcat(tempstring1, "Yes");
                } else
                {   strcat(tempstring1, "No");
                }
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Relative?               ");
                if (contents[which].DataPtr[19] & 16)
                {   strcat(tempstring1, "Yes");
                } else
                {   strcat(tempstring1, "No");
                }
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Position:               ");
                if (contents[which].DataPtr[19] % 16 == 0)
                {   strcat(tempstring1, "0 (default)");
                } elif (contents[which].DataPtr[19] % 16 == 1)
                {   strcat(tempstring1, "1 (center in window)");
                } elif (contents[which].DataPtr[19] % 16 == 2)
                {   strcat(tempstring1, "2 (center on screen)");
                } elif (contents[which].DataPtr[19] % 16 == 3)
                {   strcat(tempstring1, "3 (top left of window)");
                } elif (contents[which].DataPtr[19] % 16 == 4)
                {   strcat(tempstring1, "4 (top left of screen)");
                } elif (contents[which].DataPtr[19] % 16 == 5)
                {   strcat(tempstring1, "5 (mouse pointer)");
                } else
                {   strcat(tempstring1, "?");
                }
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Left edge:              ");
                svalue = getsword(&(contents[which].DataPtr[20]));
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Top edge:               ");
                svalue = getsword(&(contents[which].DataPtr[22]));
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Relative width:         ");
                stcl_d(tempstring2, contents[which].DataPtr[24]);
                strcat(tempstring1, tempstring2);
                if (contents[which].DataPtr[24] < 25 || contents[which].DataPtr[24] > 100)
                {   strcat(tempstring1, "!");
                }
                strcat(tempstring1, "%");
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Relative height:        ");
                stcl_d(tempstring2, contents[which].DataPtr[25]);
                strcat(tempstring1, tempstring2);
                if (contents[which].DataPtr[25] < 25 || contents[which].DataPtr[25] > 100)
                {   strcat(tempstring1, "!");
                }
                strcat(tempstring1, "%");
                AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "FONT"))
        {   chunkdesc("Font preferences", TRUE);

            // 14 reserved bytes at start

        if (!iff.raw)
        {
            strcpy(tempstring1, "Type:                   ");
            uvalue = getuword(&(contents[which].DataPtr[14]));
            if (uvalue == 0)
            {   strcat(tempstring1, "0 (Workbench)");
            } elif (uvalue == 1)
            {   strcat(tempstring1, "1 (system)");
            } elif (uvalue == 2)
            {   strcat(tempstring1, "2 (screen)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Front pen:              ");
            stcl_d(tempstring2, contents[which].DataPtr[16]);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Back pen:               ");
            stcl_d(tempstring2, contents[which].DataPtr[17]);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Draw mode:              ");
            if (contents[which].DataPtr[18] == 0) // JAM1
            {   strcat(tempstring1, "0 (JAM1)");
            } elif (contents[which].DataPtr[18] == 1) // JAM2
            {   strcat(tempstring1, "1 (JAM2)");
            } elif (contents[which].DataPtr[18] == 2) // COMPLEMENT
            {   strcat(tempstring1, "2 (complement)");
            } elif (contents[which].DataPtr[18] == 3) // INVERSVID
            {   strcat(tempstring1, "3 (inverse video)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            /* Now we have an undocumented pad byte, necessary for
            structure alignment purposes. */

            AddNameToTail(&List2, "Text attributes:");

            dotextattr(&contents[which].DataPtr[20]);

            strcpy(tempstring1, "Name:                   ");
            strcat(tempstring1, &(contents[which].DataPtr[28]));
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "INPT"))
        {   chunkdesc("Input preferences", TRUE);

            // The first 16 bytes are a keymap, currently ignored

        if (!iff.raw)
        {
            strcpy(tempstring1, "Pointer sensitivity:    ");
            uvalue = getuword(&(contents[which].DataPtr[16]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " ticks");
            AddNameToTail(&List2, tempstring1);

            AddNameToTail(&List2, "Double-click interval:");

            strcpy(tempstring1, " Seconds:               ");
            uvalue = getulong(&(contents[which].DataPtr[18]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Microseconds:          ");
            uvalue = getulong(&(contents[which].DataPtr[22]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            AddNameToTail(&List2, "Key repeat delay:");

            strcpy(tempstring1, " Seconds:               ");
            uvalue = getulong(&(contents[which].DataPtr[26]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Microseconds:          ");
            uvalue = getulong(&(contents[which].DataPtr[30]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            AddNameToTail(&List2, "Key repeat speed:");

            strcpy(tempstring1, " Seconds:               ");
            uvalue = getulong(&(contents[which].DataPtr[34]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Microseconds:          ");
            uvalue = getulong(&(contents[which].DataPtr[38]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Mouse acceleration:     ");
            svalue = getsword(&(contents[which].DataPtr[42]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "OSCN"))
        {   chunkdesc("Overscan preferences", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Magic?                  ");
            uvalue = getulong(&(contents[which].DataPtr[4]));
            if (uvalue == 0xFEDCBA89) // OSCAN_MAGIC
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Horizontal start:       ");
            uvalue = getuword(&(contents[which].DataPtr[8]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Horizontal stop:        ");
            uvalue = getuword(&(contents[which].DataPtr[10]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Vertical start:         ");
            uvalue = getuword(&(contents[which].DataPtr[12]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Vertical stop:          ");
            uvalue = getuword(&(contents[which].DataPtr[14]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "DisplayID:              ");
            uvalue = getulong(&(contents[which].DataPtr[16]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "View offset:            ");
            svalue = getsword(&(contents[which].DataPtr[20]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, ",");
            svalue = getsword(&(contents[which].DataPtr[22]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Text overscan size:     ");
            svalue = getsword(&(contents[which].DataPtr[24]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, ",");
            svalue = getsword(&(contents[which].DataPtr[26]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            AddNameToTail(&List2, "Standard overscan size:");

            strcpy(tempstring1, " Top-left corner:       ");
            svalue = getsword(&(contents[which].DataPtr[28]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, ",");
            svalue = getsword(&(contents[which].DataPtr[30]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Bottom-right corner:   ");
            svalue = getsword(&(contents[which].DataPtr[32]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, ",");
            svalue = getsword(&(contents[which].DataPtr[34]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "SCRM"))
        {   chunkdesc("Screen mode preferences", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "DisplayID:              ");
            uvalue = getulong(&(contents[which].DataPtr[16]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Screen width:           ");
            uvalue = getuword(&(contents[which].DataPtr[20]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Screen height:          ");
            uvalue = getuword(&(contents[which].DataPtr[22]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Screen depth:           ");
            uvalue = getuword(&(contents[which].DataPtr[24]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Autoscroll?             ");
            uvalue = getuword(&(contents[which].DataPtr[26]));
            if (uvalue & 1) // SMB_AUTOSCROLL
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "PSPD"))
        {   chunkdesc("PostScript printer preferences", TRUE);

        if (!iff.raw)
        {   AddNameToTail(&List2, "Global attributes:");

            strcpy(tempstring1, " Driver mode:           ");
            if (contents[which].DataPtr[16] == 0) // DM_POSTSCRIPT
            {   strcat(tempstring1, "0 (PostScript)");
            } elif (contents[which].DataPtr[16] == 1) // DM_PASSTHROUGH
            {   strcat(tempstring1, "1 (pass through)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Paper format:          ");
            if (contents[which].DataPtr[17] == 0) // PF_USLETTER
            {   strcat(tempstring1, "0 (US Letter)");
            } elif (contents[which].DataPtr[17] == 1) // PF_USLEGAL
            {   strcat(tempstring1, "1 (US Legal)");
            } elif (contents[which].DataPtr[17] == 2) // PF_A4
            {   strcat(tempstring1, "2 (A4)");
            } elif (contents[which].DataPtr[17] == 3) // PF_CUSTOM
            {   strcat(tempstring1, "3 (custom)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            // now two reserved bytes

            strcpy(tempstring1, " Copies:                ");
            svalue = getslong(&(contents[which].DataPtr[20]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Paper width:           ");
            svalue = getslong(&(contents[which].DataPtr[24]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " millipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Paper height:          ");
            svalue = getslong(&(contents[which].DataPtr[28]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " millipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Horizontal DPI:        ");
            svalue = getslong(&(contents[which].DataPtr[32]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " millipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Vertical DPI:          ");
            svalue = getslong(&(contents[which].DataPtr[36]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " millipoints");
            AddNameToTail(&List2, tempstring1);

            AddNameToTail(&List2, "Text options:");

            strcpy(tempstring1, " Font:                  ");
            if (contents[which].DataPtr[40] == 0)
            {   strcat(tempstring1, "0 (Courier)");
            } elif (contents[which].DataPtr[40] == 1)
            {   strcat(tempstring1, "1 (Times)");
            } elif (contents[which].DataPtr[40] == 2)
            {   strcat(tempstring1, "2 (Helvetica)");
            } elif (contents[which].DataPtr[40] == 3)
            {   strcat(tempstring1, "3 (Helvetica Narrow)");
            } elif (contents[which].DataPtr[40] == 4)
            {   strcat(tempstring1, "4 (Avant Garde)");
            } elif (contents[which].DataPtr[40] == 5)
            {   strcat(tempstring1, "5 (Bookman)");
            } elif (contents[which].DataPtr[40] == 6)
            {   strcat(tempstring1, "6 (New Century)");
            } elif (contents[which].DataPtr[40] == 7)
            {   strcat(tempstring1, "7 (Palantino)");
            } elif (contents[which].DataPtr[40] == 8)
            {   strcat(tempstring1, "8 (Zapf Chancery)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Pitch:                 ");
            if (contents[which].DataPtr[41] == 0)
            {   strcat(tempstring1, "0 (normal)");
            } elif (contents[which].DataPtr[41] == 1)
            {   strcat(tempstring1, "1 (compressed)");
            } elif (contents[which].DataPtr[41] == 2)
            {   strcat(tempstring1, "2 (expanded)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Orientation:           ");
            if (contents[which].DataPtr[42] == 0) // ORIENT_PORTRAIT
            {   strcat(tempstring1, "0 (portrait)");
            } elif (contents[which].DataPtr[42] == 1) // ORIENT_LANDSCAPE
            {   strcat(tempstring1, "1 (landscape)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Tab stops:             ");
            if (contents[which].DataPtr[43] == 0) // TAB_4
            {   strcat(tempstring1, "0 (4 characters)");
            } elif (contents[which].DataPtr[43] == 1) // TAB_8
            {   strcat(tempstring1, "1 (8 characters)");
            } elif (contents[which].DataPtr[43] == 2) // TAB_QUART
            {   strcat(tempstring1, "2 (quarter-inch)");
            } elif (contents[which].DataPtr[43] == 3) // TAB_HALF
            {   strcat(tempstring1, "3 (half-inch)");
            } elif (contents[which].DataPtr[43] == 4) // TAB_INCH
            {   strcat(tempstring1, "4 (inch)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            // now eight reserved bytes

            AddNameToTail(&List2, "Text dimensions:");

            strcpy(tempstring1, " Left margin:           ");
            svalue = getslong(&(contents[which].DataPtr[52]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " millipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Right margin:          ");
            svalue = getslong(&(contents[which].DataPtr[56]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " millipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Top margin:            ");
            svalue = getslong(&(contents[which].DataPtr[60]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " millipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Bottom margin:         ");
            svalue = getslong(&(contents[which].DataPtr[64]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " millipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Font size:             ");
            svalue = getslong(&(contents[which].DataPtr[68]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " millipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Leading:               ");
            svalue = getslong(&(contents[which].DataPtr[72]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " millipoints");
            AddNameToTail(&List2, tempstring1);

            // now eight reserved bytes

            AddNameToTail(&List2, "Graphics options:");

            strcpy(tempstring1, " Left edge:             ");
            svalue = getslong(&(contents[which].DataPtr[80]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " millipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Top edge:              ");
            svalue = getslong(&(contents[which].DataPtr[84]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " millipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Width:                 ");
            svalue = getslong(&(contents[which].DataPtr[88]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " millipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Height:                ");
            svalue = getslong(&(contents[which].DataPtr[92]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " millipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Image:                 ");
            if (contents[which].DataPtr[96] == 0) // IM_POSITIVE
            {   strcat(tempstring1, "0 (positive)");
            } elif (contents[which].DataPtr[96] == 1) // IM_NEGATIVE
            {   strcat(tempstring1, "1 (negative)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Shading:               ");
            if (contents[which].DataPtr[97] == 0) // SHAD_BW
            {   strcat(tempstring1, "0 (black and white)");
            } elif (contents[which].DataPtr[97] == 1) // SHAD_GREYSCALE
            {   strcat(tempstring1, "1 (greyscale)");
            } elif (contents[which].DataPtr[97] == 2) // SHAD_COLOR
            {   strcat(tempstring1, "2 (colour)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Dithering:             ");
            if (contents[which].DataPtr[98] == 0) // DITH_DEFAULT
            {   strcat(tempstring1, "0 (default)");
            } elif (contents[which].DataPtr[98] == 1) // DITH_DOTTY
            {   strcat(tempstring1, "1 (dotty)");
            } elif (contents[which].DataPtr[98] == 2) // DITH_VERT
            {   strcat(tempstring1, "2 (vertical)");
            } elif (contents[which].DataPtr[98] == 3) // DITH_HORIZ
            {   strcat(tempstring1, "3 (horizontal)");
            } elif (contents[which].DataPtr[98] == 4) // DITH_DIAG
            {   strcat(tempstring1, "4 (diagonal)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            // now nine reserved bytes

            AddNameToTail(&List2, "Graphics scaling:");

            strcpy(tempstring1, " Aspect:                ");
            if (contents[which].DataPtr[108] == 0) // ASP_HORIZ
            {   strcat(tempstring1, "0 (horizontal)");
            } elif (contents[which].DataPtr[108] == 1) // ASP_VERT
            {   strcat(tempstring1, "1 (vertical)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Scaling type:          ");
            if (contents[which].DataPtr[109] == 0) // ST_ASPECT_ASIS
            {   strcat(tempstring1, "0 (aspect as is)");
            } elif (contents[which].DataPtr[109] == 1) // ST_ASPECT_WIDE
            {   strcat(tempstring1, "1 (aspect wide)");
            } elif (contents[which].DataPtr[109] == 2) // ST_ASPECT_TALL
            {   strcat(tempstring1, "2 (aspect tall)");
            } elif (contents[which].DataPtr[109] == 3) // ST_ASPECT_BOTH
            {   strcat(tempstring1, "3 (aspect both)");
            } elif (contents[which].DataPtr[109] == 4) // ST_FITS_WIDE
            {   strcat(tempstring1, "4 (fits wide)");
            } elif (contents[which].DataPtr[109] == 5) // ST_FITS_TALL
            {   strcat(tempstring1, "5 (fits tall)");
            } elif (contents[which].DataPtr[109] == 6) // ST_FITS_BOTH
            {   strcat(tempstring1, "6 (fits both)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            // now one reserved byte

            strcpy(tempstring1, " Centering:             ");
            if (contents[which].DataPtr[111] == 0) // CENT_NONE
            {   strcat(tempstring1, "0 (none)");
            } elif (contents[which].DataPtr[111] == 1) // CENT_HORIZ
            {   strcat(tempstring1, "1 (horizontal)");
            } elif (contents[which].DataPtr[111] == 2) // CENT_VERT
            {   strcat(tempstring1, "2 (vertical)");
            } elif (contents[which].DataPtr[111] == 3) // CENT_BOTH
            {   strcat(tempstring1, "3 (both)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "PGFX"))
        {   chunkdesc("Printer graphics preferences", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Aspect:                 ");
            uvalue = getuword(&(contents[which].DataPtr[16]));
            if (uvalue == 0) // PA_HORIZONTAL
            {   strcat(tempstring1, "0 (horizontal)");
            } elif (uvalue == 1) // PA_VERTICAL
            {   strcat(tempstring1, "1 (vertical)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Shading:                ");
            uvalue = getuword(&(contents[which].DataPtr[18]));
            if (uvalue == 0) // PS_BW
            {   strcat(tempstring1, "0 (black and white)");
            } elif (uvalue == 1) // PS_GREYSCALE
            {   strcat(tempstring1, "1 (greyscale 1)");
            } elif (uvalue == 2) // PS_COLOR
            {   strcat(tempstring1, "2 (colour)");
            } elif (uvalue == 3) // PS_GREY_SCALE2
            {   strcat(tempstring1, "3 (greyscale 2)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Image:                  ");
            uvalue = getuword(&(contents[which].DataPtr[20]));
            if (uvalue == 0) // PI_POSITIVE
            {   strcat(tempstring1, "0 (positive)");
            } elif (uvalue == 1) // PI_NEGATIVE
            {   strcat(tempstring1, "1 (negative)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Threshold:              ");
            svalue = getsword(&(contents[which].DataPtr[22]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            AddNameToTail(&List2, "Colour correction:");

            strcpy(tempstring1, " Red?                   ");
            if (contents[which].DataPtr[24] & 1) // PCCF_RED
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Green?                 ");
            if (contents[which].DataPtr[24] & 2) // PCCF_GREEN
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Blue?                  ");
            if (contents[which].DataPtr[24] & 4) // PCCF_BLUE
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Dimensions:             ");
            if (contents[which].DataPtr[25] == 0) // PD_IGNORE
            {   strcat(tempstring1, "0 (ignore)");
            } elif (contents[which].DataPtr[25] == 1) // PD_BOUNDED
            {   strcat(tempstring1, "1 (bounded)");
            } elif (contents[which].DataPtr[25] == 2) // PD_ABSOLUTE
            {   strcat(tempstring1, "2 (absolute)");
            } elif (contents[which].DataPtr[25] == 3) // PD_PIXEL
            {   strcat(tempstring1, "3 (printer pixels)");
            } elif (contents[which].DataPtr[25] == 4) // PD_MULTIPLY
            {   strcat(tempstring1, "4 (multiply)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Dithering:              ");
            if (contents[which].DataPtr[26] == 0) // PD_ORDERED
            {   strcat(tempstring1, "0 (ordered)");
            } elif (contents[which].DataPtr[26] == 1) // PD_HALFTONE
            {   strcat(tempstring1, "1 (halftone)");
            } elif (contents[which].DataPtr[26] == 2) // PD_FLOYD
            {   strcat(tempstring1, "2 (Floyd-Steinberg)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Flags:");
            uvalue = getuword(&(contents[which].DataPtr[27]));

            strcpy(tempstring1, " Centre image?          ");
            if (uvalue & 1) // PGFF_CENTER_IMAGE
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Integer scaling?       ");
            if (uvalue & 2) // PGFF_INTEGER_SCALING
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Antialiasing?          ");
            if (uvalue & 4) // PGFF_ANTI_ALIAS
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Print density:          ");
            stcl_d(tempstring2, contents[which].DataPtr[29]);
            strcat(tempstring1, tempstring2);
            if (contents[which].DataPtr[29] < 1 || contents[which].DataPtr[29] > 7)
            {   strcat(tempstring1, "!");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Maximum width:          ");
            uvalue = getuword(&(contents[which].DataPtr[30]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Maximum height:         ");
            uvalue = getuword(&(contents[which].DataPtr[32]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Offset:                 ");
            stcl_d(tempstring2, contents[which].DataPtr[34]);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, ",");
            stcl_d(tempstring2, contents[which].DataPtr[35]);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "PTXT"))
        {   chunkdesc("Printer text preferences", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Driver filename:        ");
            strcat(tempstring1, &(contents[which].DataPtr[16]));
            // 32-character field, so it doesn't need truncation
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Port:                   ");
            if (contents[which].DataPtr[48] == 0) // PP_PARALLEL
            {   strcat(tempstring1, "0 (parallel)");
            } elif (contents[which].DataPtr[48] == 1) // PP_SERIAL
            {   strcat(tempstring1, "1 (serial)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Paper type:             ");
            uvalue = getuword(&(contents[which].DataPtr[49]));
            if (uvalue == 0) // PT_FANFOLD
            {   strcat(tempstring1, "0 (fanfold)");
            } elif (uvalue == 1) // PP_SINGLE
            {   strcat(tempstring1, "1 (single sheet)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Paper size:             ");
            uvalue = getuword(&(contents[which].DataPtr[51]));
            if (uvalue == 0) // PS_US_LETTER
            {   strcat(tempstring1, "0 (US Letter)");
            } elif (uvalue == 1) // PS_US_LEGAL
            {   strcat(tempstring1, "1 (US Legal)");
            } elif (uvalue == 2) // PS_N_TRACTOR
            {   strcat(tempstring1, "2 (narrow tractor)");
            } elif (uvalue == 3) // PS_W_TRACTOR
            {   strcat(tempstring1, "3 (wide tractor)");
            } elif (uvalue == 4) // PS_CUSTOM
            {   strcat(tempstring1, "4 (custom)");
            } elif (uvalue == 5) // PS_EURO_A0
            {   strcat(tempstring1, "5 (A0: 841x1189mm)");
            } elif (uvalue == 6) // PS_EURO_A1
            {   strcat(tempstring1, "6 (A1: 594x841mm)");
            } elif (uvalue == 7) // PS_EURO_A2
            {   strcat(tempstring1, "7 (A2: 420x594mm)");
            } elif (uvalue == 8) // PS_EURO_A3
            {   strcat(tempstring1, "8 (A3: 297x420mm)");
            } elif (uvalue == 9) // PS_EURO_A4
            {   strcat(tempstring1, "9 (A4: 210x297mm)");
            } elif (uvalue == 10) // PS_EURO_A5
            {   strcat(tempstring1, "10 (A5: 148x210mm)");
            } elif (uvalue == 11) // PS_EURO_A6
            {   strcat(tempstring1, "11 (A6: 105x148mm)");
            } elif (uvalue == 12) // PS_EURO_A7
            {   strcat(tempstring1, "12 (A7: 74x105mm)");
            } elif (uvalue == 13) // PS_EURO_A8
            {   strcat(tempstring1, "13 (A8: 52x74mm)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Paper length:           ");
            uvalue = getuword(&(contents[which].DataPtr[53]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " lines");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Pitch:                  ");
            uvalue = getuword(&(contents[which].DataPtr[55]));
            if (uvalue == 0) // PP_PICA
            {   strcat(tempstring1, "0 (pica)");
            } elif (uvalue == 1) // PP_ELITE
            {   strcat(tempstring1, "1 (elite)");
            } elif (uvalue == 2) // PP_FINE
            {   strcat(tempstring1, "2 (fine)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Spacing:                ");
            uvalue = getuword(&(contents[which].DataPtr[57]));
            if (uvalue == 0) // PS_SIX_LPI
            {   strcat(tempstring1, "0 (6 lines per inch)");
            } elif (uvalue == 1) // PS_EIGHT_LPI
            {   strcat(tempstring1, "1 (8 lines per inch)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Left margin:            ");
            uvalue = getuword(&(contents[which].DataPtr[59]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Right margin:           ");
            uvalue = getuword(&(contents[which].DataPtr[61]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Quality:                ");
            uvalue = getuword(&(contents[which].DataPtr[63]));
            if (uvalue == 0) // PQ_DRAFT
            {   strcat(tempstring1, "0 (draft)");
            } elif (uvalue == 1) // PQ_LETTER
            {   strcat(tempstring1, "1 (letter)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "SOND"))
        {   chunkdesc("Sound preferences", TRUE);

            // 16 reserved bytes at start

        if (!iff.raw)
        {
            strcpy(tempstring1, "Flash display?          ");
            uvalue = getuword(&contents[which].DataPtr[16]); // BOOL
            if (uvalue)
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Make sounds?            ");
            uvalue = getuword(&contents[which].DataPtr[18]); // BOOL
            if (uvalue)
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Type of sound:          ");
            uvalue = getuword(&contents[which].DataPtr[20]); // uword
            if (uvalue == 0) // SPTYPE_BEEP
            {   strcat(tempstring1, "Beep");
            } elif (uvalue == 1) // SPTYPE_SAMPLE
            {   strcat(tempstring1, "Sample");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Volume:                 ");
            uvalue = getuword(&contents[which].DataPtr[22]); // uword
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            if (uvalue > 64)
            {   strcat(tempstring1, "!");
            }
            strcat(tempstring1, "/64");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Period:                 ");
            uvalue = getuword(&contents[which].DataPtr[24]); // uword
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            if (uvalue < 127 || uvalue > 2500)
            {   strcat(tempstring1, "!");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Beep length:            ");
            uvalue = getuword(&contents[which].DataPtr[26]); // uword
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Sample filename:        ");
            strcat(tempstring1, &contents[which].DataPtr[28]); // 256 chars
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "PTRN"))
        {   chunkdesc("Workbench pattern preferences", TRUE);

            // 16 reserved bytes at start

        if (!iff.raw)
        {
            strcpy(tempstring1, "Which pattern?          ");
            uvalue = getuword(&contents[which].DataPtr[16]); // UWORD
            if (uvalue == 0) // WBP_ROOT
            {   strcat(tempstring1, "9 (Workbench)");
            } elif (uvalue == 1) // WBP_DRAWER
            {   strcat(tempstring1, "1 (window)");
            } elif (uvalue == 2) // WBP_SCREEN
            {   strcat(tempstring1, "2 (screen)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            uvalue = getuword(&contents[which].DataPtr[18]); // UWORD

            strcpy(tempstring1, "Data contains pattern?  ");
            if (uvalue & 1) // WBPF_PATTERN
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Remap pattern?          ");
            if (uvalue & 16) // WBPF_NOREMAP
            {   strcat(tempstring1, "No");
            } else
            {   strcat(tempstring1, "Yes");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Dither quality:         ");
            if (uvalue & 768) // these comparisons are order-dependent
            {   strcat(tempstring1, "Best");
            } elif (uvalue & 512)
            {   strcat(tempstring1, "Good");
            } elif (uvalue & 256)
            {   strcat(tempstring1, "Poor");
            } else
            {   strcat(tempstring1, "Default");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Colour quality:         ");
            if (uvalue & 3072) // these comparisons are order-dependent
            {   strcat(tempstring1, "Best");
            } elif (uvalue & 2048)
            {   strcat(tempstring1, "Good");
            } elif (uvalue & 1024)
            {   strcat(tempstring1, "Poor");
            } else
            {   strcat(tempstring1, "Default");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Layout:                 ");
            if (uvalue & 12288) // these comparisons are order-dependent
            {   strcat(tempstring1, "Scale well");
            } elif (uvalue & 8192)
            {   strcat(tempstring1, "Scale");
            } elif (uvalue & 4096)
            {   strcat(tempstring1, "Centre");
            } else
            {   strcat(tempstring1, "Tile");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Revision:               ");  // BYTE
            stcl_d(tempstring2, contents[which].DataPtr[20]);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Pattern depth:          ");  // BYTE
            stcl_d(tempstring2, contents[which].DataPtr[21]);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Data length:            ");  // UWORD
            uvalue = getuword(&contents[which].DataPtr[22]);
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "PNTR"))
        {   chunkdesc("Pointer preferences", TRUE);

            // 16 reserved bytes at start

        if (!iff.raw)
        {
            strcpy(tempstring1, "Which pointer?          ");
            uvalue = getuword(&contents[which].DataPtr[16]); // UWORD
            if (uvalue == 0)
            {   strcat(tempstring1, "Normal");
            } elif (uvalue == 1)
            {   strcat(tempstring1, "Busy");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Horizontal size:        ");
            uvalue = getuword(&contents[which].DataPtr[18]); // UWORD
            if (uvalue == 0) // POINTERXRESN_DEFAULT
            {   strcat(tempstring1, "0 (default)");
            } elif (uvalue == 1) // POINTERXRESN_140NS
            {   strcat(tempstring1, "1 (140ns)");
            } elif (uvalue == 2) // POINTERXRESN_70NS
            {   strcat(tempstring1, "2 (70ns)");
            } elif (uvalue == 3) // POINTERXRESN_35NS
            {   strcat(tempstring1, "3 (35ns)");
            } elif (uvalue == 4) // POINTERXRESN_SCREENRES
            {   strcat(tempstring1, "4 (screen)");
            } elif (uvalue == 5) // POINTERXRESN_LORES
            {   strcat(tempstring1, "5 (low resolution)");
            } elif (uvalue == 6) // POINTERXRESN_HIRES
            {   strcat(tempstring1, "6 (high resolution)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Width:                  ");
            uvalue = getuword(&contents[which].DataPtr[20]); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " pixels");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Height:                 ");
            uvalue = getuword(&contents[which].DataPtr[22]); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " pixels");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Depth:                  ");
            uvalue = getuword(&contents[which].DataPtr[24]); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " planes");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Vertical size:          ");
            uvalue = getuword(&contents[which].DataPtr[26]); // UWORD
            if (uvalue == 0) // POINTERYRESN_DEFAULT
            {   strcat(tempstring1, "0 (default)");
            } elif (uvalue == 1) // POINTERYRESN_HIGH
            {   strcat(tempstring1, "1 (high non-aspect)");
            } elif (uvalue == 2) // POINTERYRESN_HIGHASPECT
            {   strcat(tempstring1, "2 (high aspect)");
            } elif (uvalue == 3) // POINTERYRESN_SCREENRES
            {   strcat(tempstring1, "3 (screen non-aspect)");
            } elif (uvalue == 4) // POINTERYRESN_SCREENRESASPECT
            {   strcat(tempstring1, "4 (screen aspect)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Hotspot coordinates:    ");
            uvalue = getuword(&contents[which].DataPtr[28]); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, ",");
            uvalue = getuword(&contents[which].DataPtr[30]); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "PALT")) // ignored
        {   chunkdesc("Palette preferences", FALSE);
        } elif (!strcmp(contents[which].name, "AHIG"))
        {   chunkdesc("AHI global preferences", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "Debug level:            ");
                uvalue = getuword(contents[which].DataPtr); // UWORD
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                if (uvalue == 0)
                {   strcat(tempstring1, " (none)");
                } elif (uvalue == 1)
                {   strcat(tempstring1, " (low)");
                } elif (uvalue == 2)
                {   strcat(tempstring1, " (high)");
                } elif (uvalue == 3)
                {   strcat(tempstring1, " (all)");
                } else
                {   strcat(tempstring1, " (?)");
                }
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Disable surround sound? ");
                uvalue = getuword(&contents[which].DataPtr[2]); // BOOL
                if (uvalue)
                {   strcat(tempstring1, "Yes");
                } else
                {   strcat(tempstring1, "No");
                }
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Disable echo?           ");
                uvalue = getuword(&contents[which].DataPtr[4]); // BOOL
                if (uvalue)
                {   strcat(tempstring1, "Yes");
                } else
                {   strcat(tempstring1, "No");
                }
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Fast echo?              ");
                uvalue = getuword(&contents[which].DataPtr[6]); // BOOL
                if (uvalue)
                {   strcat(tempstring1, "Yes");
                } else
                {   strcat(tempstring1, "No");
                }
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Maximum CPU usage:      ");
                svalue = getslong(&(contents[which].DataPtr[8]));
                svalue /= 1024; // LONG (Fixed)
                stcl_d(tempstring2, svalue);
                strcat(tempstring1, tempstring2);
                strcat(tempstring1, "/64");
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Clip master volume?     ");
                uvalue = getuword(&contents[which].DataPtr[12]); // BOOL
                if (uvalue)
                {   strcat(tempstring1, "Yes");
                } else
                {   strcat(tempstring1, "No");
                }
                AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "AHIU"))
        {   chunkdesc("AHI unit preferences", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "Unit:                   ");
                stcl_d(tempstring2, contents[which].DataPtr[0]); // UBYTE
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);

                // byte 1 is a pad byte

                strcpy(tempstring1, "Channels:               ");
                uvalue = getuword(&contents[which].DataPtr[2]); // UWORD
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Audio mode:             ");
                uvalue = getuword(&contents[which].DataPtr[4]); // ULONG
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1); // perhaps this can be interpreted?

                strcpy(tempstring1, "Frequency:              ");
                uvalue = getuword(&contents[which].DataPtr[8]); // ULONG
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Monitor volume:         ");
                svalue = getslong(&(contents[which].DataPtr[12]));
                svalue /= 1024; // LONG (Fixed)
                stcl_d(tempstring2, svalue);
                strcat(tempstring1, tempstring2);
                strcat(tempstring1, "/64");
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Input gain:             ");
                svalue = getslong(&(contents[which].DataPtr[16]));
                svalue /= 1024; // LONG (Fixed)
                stcl_d(tempstring2, svalue);
                strcat(tempstring1, tempstring2);
                strcat(tempstring1, "/64");
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Output volume:          ");
                svalue = getslong(&(contents[which].DataPtr[20]));
                svalue /= 1024; // LONG (Fixed)
                stcl_d(tempstring2, svalue);
                strcat(tempstring1, tempstring2);
                strcat(tempstring1, "/64");
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Input:                  ");
                uvalue = getuword(&contents[which].DataPtr[24]); // ULONG
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1); // perhaps this can be interpreted?

                strcpy(tempstring1, "Output:                 ");
                uvalue = getuword(&contents[which].DataPtr[28]); // ULONG
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1); // perhaps this can be interpreted?
        }   }
        elif (!strcmp(contents[which].name, "WBNC"))
        {   chunkdesc("Workbench preferences", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Default stack size:     ");
            uvalue = getulong(contents[which].DataPtr); // ULONG
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " bytes");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Type restart time:      ");
            uvalue = getulong(&contents[which].DataPtr[4]); // ULONG
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " seconds");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Icon precision:         ");
            uvalue = getulong(&contents[which].DataPtr[8]); // ULONG
            if (uvalue == (ULONG) -1) // PRECISION_EXACT
            {   strcat(tempstring1, "-1 (exact)");
            } elif (uvalue == 0) // PRECISION_IMAGE
            {   strcat(tempstring1, "0 (image)");
            } elif (uvalue == 16) // PRECISION_ICON
            {   strcat(tempstring1, "16 (icon)");
            } elif (uvalue == 32) // PRECISION_GUI
            {   strcat(tempstring1, "32 (GUI)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Emboss rectangle:       ");

            strcpy(tempstring1, " Top-left corner:       ");
            svalue = getsword(&contents[which].DataPtr[12]); // WORD
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, ",");
            svalue = getuword(&contents[which].DataPtr[14]); // WORD
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Bottom-right corner:   ");
            svalue = getsword(&contents[which].DataPtr[16]); // WORD
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, ",");
            svalue = getuword(&contents[which].DataPtr[18]); // WORD
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Borderless?             ");
            uvalue = getuword(&contents[which].DataPtr[20]); // BOOL
            if (uvalue)
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Max. filename length:   ");
            svalue = getslong(&contents[which].DataPtr[22]); // LONG
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " characters");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "NewIcons support?       ");
            uvalue = getuword(&contents[which].DataPtr[26]); // BOOL
            if (uvalue)
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "ColourIcons support?    ");
            uvalue = getuword(&contents[which].DataPtr[28]); // BOOL
            if (uvalue)
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            // remainder of these are new for OS3.9

            if (contents[which].bytes > 30)
            {   strcpy(tempstring1, "Image memory type:      ");
                uvalue = getulong(&contents[which].DataPtr[30]); // ULONG
                if (uvalue == 1)
                {   strcat(tempstring1, "Other memory");
                } elif (uvalue == 2)
                {   strcat(tempstring1, "Graphics (chip) memory");
                } else
                {   strcat(tempstring1, "?");
                }
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Lock pens?              ");
                uvalue = getuword(&contents[which].DataPtr[34]); // BOOL
                if (uvalue)
                {   strcat(tempstring1, "Yes");
                } else
                {   strcat(tempstring1, "No");
                }
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Title bar?              "); // this is inverted
                uvalue = getuword(&contents[which].DataPtr[36]); // BOOL
                if (uvalue)
                {   strcat(tempstring1, "No");
                } else
                {   strcat(tempstring1, "Yes");
                }
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Volume gauge?           "); // this is inverted
                uvalue = getuword(&contents[which].DataPtr[38]); // BOOL
                if (uvalue)
                {   strcat(tempstring1, "No");
                } else
                {   strcat(tempstring1, "Yes");
                }
                AddNameToTail(&List2, tempstring1);
        }   }   }
        elif (!strcmp(contents[which].name, "WBHD"))
        {   chunkdesc("Workbench hidden device preferences", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "Name:                   ");
                strcat(tempstring1, contents[which].DataPtr);
                AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "LCLE"))
        {   chunkdesc("Locale preferences", TRUE);

            // 16 reserved bytes at start

        if (!iff.raw)
        {
            strcpy(tempstring1, "Country code:           ");
            strcpy(tempstring1, &contents[which].DataPtr[16]); // 16 chars
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Preferred languages:    ");
            strcpy(tempstring1, &contents[which].DataPtr[16]); // 16 chars
            AddNameToTail(&List2, tempstring1);

            for (i = 1; i <= 10; i++)
            {   strcpy(tempstring1, " ");
                if (i < 10)
                {   strcat(tempstring1, " ");
                }
                stcl_d(tempstring2, i);
                strcat(tempstring1, tempstring2);
                strcpy(tempstring1, ":                    ");
                strcat(tempstring1, &contents[which].DataPtr[48 + ((i - 1) * 30)]); // 10 entries of 30 chars each
                AddNameToTail(&List2, tempstring1);
            }

            strcpy(tempstring1, "Time from GMT:          ");
            svalue = getslong(&contents[which].DataPtr[348]); // LONG
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " minutes");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Flags:                  ");
            uvalue = getulong(&contents[which].DataPtr[352]); // ULONG
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            docountry(&contents[which].DataPtr[356]);
        }   }
        elif (!strcmp(contents[which].name, "CTRY"))
        {   chunkdesc("Country preferences", TRUE);

            if (!iff.raw)
            {   docountry(contents[which].DataPtr);
        }   }
        elif (!strcmp(contents[which].name, "RACT"))
        {   chunkdesc("ReAction preferences", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Bevel type:             "); // UWORD
            uvalue = getuword(contents[which].DataPtr);
            if (uvalue == 0) // BVT_GT
            {   strcat(tempstring1, "0 (GadTools 2:1)");
            } elif (uvalue == 1) // BVT_THIN
            {   strcat(tempstring1, "1 (ReAction 1:1)");
            } elif (uvalue == 2) // BVT_THICK
            {   strcat(tempstring1, "2 (ReAction 2:1)");
            } elif (uvalue == 3) // BVT_THIN
            {   strcat(tempstring1, "3 (XEN 2:1)");
            } elif (uvalue == 4) // BVT_THIN
            {   strcat(tempstring1, "4 (XEN 1:1)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Glyph type:             "); // UWORD
            uvalue = getuword(&contents[which].DataPtr[2]);
            if (uvalue == 0) // GLT_GT
            {   strcat(tempstring1, "0 (GadTools)");
            } elif (uvalue == 1) // GLT_FLAT
            {   strcat(tempstring1, "1 (Flat)");
            } elif (uvalue == 2) // GLT_3D
            {   strcat(tempstring1, "2 (3D)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Layout spacing:         "); // UWORD
            uvalue = getuword(&contents[which].DataPtr[4]);
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "3D Proportional?        ");
            uvalue = getuword(&contents[which].DataPtr[6]); // BOOL
            if (uvalue)
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Label pen:              "); // UWORD
            uvalue = getuword(&contents[which].DataPtr[8]);
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Label placement:        "); // UWORD
            uvalue = getuword(&contents[which].DataPtr[10]);
            /* This has been reverse-engineered
            using the ReAction preferences editor */
            if (uvalue == 0)
            {   strcat(tempstring1, "0 (centre)");
            } elif (uvalue == 1)
            {   strcat(tempstring1, "1 (left)");
            } elif (uvalue == 2)
            {   strcat(tempstring1, "2 (right)");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "3D Label?               ");
            uvalue = getuword(&contents[which].DataPtr[12]); // BOOL
            if (uvalue)
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Refreshing Method:      ");
            uvalue = getuword(&contents[which].DataPtr[14]); // BOOL
            if (uvalue)
            {   strcat(tempstring1, "Simple");
            } else
            {   strcat(tempstring1, "Smart");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "3D Look?                ");
            uvalue = getuword(&contents[which].DataPtr[16]); // BOOL
            if (uvalue)
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            AddNameToTail(&List2, "Fallback font:");
            dotextattr(&contents[which].DataPtr[18]); // struct TextAttr (8 bytes)
            AddNameToTail(&List2, "Label font:");
            dotextattr(&contents[which].DataPtr[26]); // struct TextAttr (8 bytes)

            strcpy(tempstring1, "Fallback font name:     ");
            strcat(tempstring1, &contents[which].DataPtr[34]); // 128 UBYTEs
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Label font name:        ");
            strcat(tempstring1, &contents[which].DataPtr[162]); // 128 UBYTEs
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Backdrop pattern:       ");
            strcat(tempstring1, &contents[which].DataPtr[290]); // 256 UBYTEs
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "PRHD"))
        {   chunkdesc("Preferences header", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Version:                ");
            stcl_d(tempstring2, contents[which].DataPtr[0]);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);
                               
            strcpy(tempstring1, "Type:                   ");
            stcl_d(tempstring2, contents[which].DataPtr[1]);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Flags:                  ");
            uvalue = getuword(&(contents[which].DataPtr[2]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);
    }   }   }
    elif (!strcmp(queryform, "SMUS"))
    {   if (!strcmp(contents[which].name, "SHDR"))
        {   chunkdesc("Global information for the score", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Tempo:              ");
            uvalue = getuword(contents[which].DataPtr);
            uvalue = uvalue / 128;
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " bpm");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Volume:             ");
            uvalue = contents[which].DataPtr[2];
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, "/127");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Tracks:             ");
            uvalue = contents[which].DataPtr[3];
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "INS1"))
        {   chunkdesc("Identifies an instrument to use", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Register number:    ");
            stcl_d(tempstring2, contents[which].DataPtr[0]); // UBYTE
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Reference type:     ");
            if (contents[which].DataPtr[1] == 0) // UBYTE
            {   strcat(tempstring1, "Find by name");
            } elif (contents[which].DataPtr[1] == 1)
            {   strcat(tempstring1, "Find on MIDI");
            } else strcat(tempstring1, "?");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "MIDI channel:       ");
            if (contents[which].DataPtr[1] == 1) // if find on MIDI
            {   stcl_d(tempstring2, contents[which].DataPtr[2]); // UBYTE
                strcat(tempstring1, tempstring2);
            } else strcat(tempstring1, "n/a");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "MIDI preset:        ");
            if (contents[which].DataPtr[1] == 1) // if find on MIDI
            {   stcl_d(tempstring2, contents[which].DataPtr[3]); // UBYTE
                strcat(tempstring1, tempstring2);
            } else strcat(tempstring1, "n/a");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Instrument name:    ");
            strcat(tempstring1, (STRPTR) contents[which].DataPtr + 4); // STRPTR
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "TRAK"))
        {   chunkdesc("Linear stream of events", FALSE);
        } elif (!strcmp(contents[which].name, "INST"))
        {   chunkdesc("Obsolete; use INS1 instead", FALSE);
        } elif (!stricmp(contents[which].name, "IRev")) // this could also perhaps be IREV
        {   chunkdesc("Instant Music private chunk", FALSE);
        } elif (!strcmp(contents[which].name, "BIAS"))
        {   chunkdesc("Instant Music private chunk", FALSE);
    }   }
    elif (!strcmp(queryform, "HEAD"))
    {   if (!strcmp(contents[which].name, "NEST"))
        {   chunkdesc("Nesting level", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "Nesting level:      ");
                uvalue = getuword(contents[which].DataPtr);
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "TEXT"))
        {   chunkdesc("Heading text", FALSE);
    }   }
    elif (!strcmp(queryform, "WORD"))
    {   if (!strcmp(contents[which].name, "FONT"))
        {   chunkdesc("Font name/number table", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Number:             ");
            uvalue = contents[which].DataPtr[0]; // UBYTE
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Size:               ");
            uvalue = getuword(&contents[which].DataPtr[1]);
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Name:               ");
            strcat(tempstring1, &contents[which].DataPtr[3]);
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "COLR"))
        {   chunkdesc("Colour translation table", TRUE);

            if (!iff.raw)
            {   for (i = 0; i <= 7; i++)
                {   strcpy(tempstring1, "Colour ");
                    stcl_d(tempstring2, i);
                    strcat(tempstring1, tempstring2);
                    strcat(tempstring1, ":           ");
                    uvalue = contents[which].DataPtr[i]; // UBYTE
                    stcl_d(tempstring2, uvalue);
                    strcat(tempstring1, tempstring2);
                    AddNameToTail(&List2, tempstring1);
        }   }   }
        elif (!strcmp(contents[which].name, "DOC "))
        {   chunkdesc("Begin document section", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "Starting page:      ");
                uvalue = getuword(contents[which].DataPtr);
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Numbering style:    ");
                if (contents[which].DataPtr[2] == 0)
                {   strcat(tempstring1, "1, 2, 3...");
                } elif (contents[which].DataPtr[2] == 1)
                {   strcat(tempstring1, "I, II, III...");
                } elif (contents[which].DataPtr[2] == 2)
                {   strcat(tempstring1, "i, ii, iii...");
                } elif (contents[which].DataPtr[2] == 3)
                {   strcat(tempstring1, "A, B, C...");
                } elif (contents[which].DataPtr[2] == 4)
                {   strcat(tempstring1, "a, b, c...");
                } else
                {   strcat(tempstring1, "?");
                }
                AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "HEAD"))
        {   chunkdesc("Begin header section", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "Page type:           ");
                if (contents[which].DataPtr[0] == 0)
                {   strcat(tempstring1, "None");
                } elif (contents[which].DataPtr[0] == 1)
                {   strcat(tempstring1, "Left");
                } elif (contents[which].DataPtr[0] == 2)
                {   strcat(tempstring1, "Right");
                } elif (contents[which].DataPtr[0] == 3)
                {   strcat(tempstring1, "Both");
                } else strcat(tempstring1, "?");
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "First page?          ");
                if (contents[which].DataPtr[1] == 0)
                {   strcat(tempstring1, "No");
                } else strcat(tempstring1, "Yes");
                AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "FOOT"))
        {   chunkdesc("Begin footer section", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "Page type:           ");
                if (contents[which].DataPtr[0] == 0)
                {   strcat(tempstring1, "None");
                } elif (contents[which].DataPtr[0] == 1)
                {   strcat(tempstring1, "Left");
                } elif (contents[which].DataPtr[0] == 2)
                {   strcat(tempstring1, "Right");
                } elif (contents[which].DataPtr[0] == 3)
                {   strcat(tempstring1, "Both");
                } else strcat(tempstring1, "?");
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "First page?          ");
                if (contents[which].DataPtr[1] == 0)
                {   strcat(tempstring1, "No");
                } else strcat(tempstring1, "Yes");
                AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "PCTS"))
        {   chunkdesc("Begin picture section", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "Bitplanes:           ");
                uvalue = contents[which].DataPtr[0]; // UBYTE
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "PARA"))
        {   chunkdesc("New paragraph format", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Left indent:         ");
            uvalue = getuword(contents[which].DataPtr); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " decipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Left margin:         ");
            uvalue = getuword(&(contents[which].DataPtr[2])); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " decipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Right margin:        ");
            uvalue = getuword(&(contents[which].DataPtr[4])); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " decipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Line spacing:        ");
            if (contents[which].DataPtr[6] == 0)
            {   strcat(tempstring1, "Single");
            } elif (contents[which].DataPtr[6] == 16)
            {   strcat(tempstring1, "Double");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Justification:       ");
            if (contents[which].DataPtr[7] == 0)
            {   strcat(tempstring1, "Left");
            } elif (contents[which].DataPtr[7] == 1)
            {   strcat(tempstring1, "Centre");
            } elif (contents[which].DataPtr[7] == 2)
            {   strcat(tempstring1, "Right");
            } elif (contents[which].DataPtr[7] == 3)
            {   strcat(tempstring1, "Full");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Font number:         ");
            uvalue = contents[which].DataPtr[8]; // UBYTE
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcat(tempstring1, " Style:");
            AddNameToTail(&List2, tempstring1);

            strcat(tempstring1, " Underlined?         ");
            if (contents[which].DataPtr[9] & 1)
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            AddNameToTail(&List2, tempstring1);

            strcat(tempstring1, " Bold?               ");
            if (contents[which].DataPtr[9] & 2)
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            AddNameToTail(&List2, tempstring1);

            strcat(tempstring1, " Italic?             ");
            if (contents[which].DataPtr[9] & 4)
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            AddNameToTail(&List2, tempstring1);

            strcat(tempstring1, " Extended?           ");
            if (contents[which].DataPtr[9] & 8)
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            AddNameToTail(&List2, tempstring1);

            strcat(tempstring1, " ColourFont?         ");
            if (contents[which].DataPtr[9] & 64)
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            AddNameToTail(&List2, tempstring1);

            strcat(tempstring1, " Tagged?             ");
            if (contents[which].DataPtr[9] & 128)
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Miscellaneous style: ");
            if (contents[which].DataPtr[10] == 0)
            {   strcat(tempstring1, "None");
            } elif (contents[which].DataPtr[10] == 1)
            {   strcat(tempstring1, "Superscript");
            } elif (contents[which].DataPtr[10] == 2)
            {   strcat(tempstring1, "Subscript");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Colour:              ");
            uvalue = contents[which].DataPtr[11]; // UBYTE
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "TABS"))
        {   chunkdesc("New tab stop types/locations", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Position:            ");
            uvalue = getuword(contents[which].DataPtr); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " decipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Type:                ");
            if (contents[which].DataPtr[2] == 0)
            {   strcat(tempstring1, "Left");
            } elif (contents[which].DataPtr[2] == 1)
            {   strcat(tempstring1, "Centre");
            } elif (contents[which].DataPtr[2] == 2)
            {   strcat(tempstring1, "Right");
            } elif (contents[which].DataPtr[2] == 3)
            {   strcat(tempstring1, "Decimal");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "PAGE"))
        {   chunkdesc("Page break", FALSE);
        } elif (!strcmp(contents[which].name, "TEXT"))
        {   chunkdesc("Paragraph text", FALSE);
        } elif (!strcmp(contents[which].name, "PINF"))
        {   chunkdesc("Picture info", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Width:               ");
            uvalue = getuword(contents[which].DataPtr); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Height:              ");
            uvalue = getuword(&(contents[which].DataPtr[2])); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Page:                ");
            uvalue = getuword(&(contents[which].DataPtr[4])); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "X-position:          ");
            uvalue = getuword(&(contents[which].DataPtr[6])); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " decipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Y-position:          ");
            uvalue = getuword(&(contents[which].DataPtr[8])); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " decipoints");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Masking:            ");
            if (contents[which].DataPtr[10] == 0)
            {   strcat(tempstring1, "0 (Opaque)");
            } elif (contents[which].DataPtr[10] == 1)
            {   strcat(tempstring1, "1 (Mask plane)");
            } elif (contents[which].DataPtr[10] == 2)
            {   strcat(tempstring1, "2 (Transparent colour)");
            } elif (contents[which].DataPtr[10] == 3)
            {   strcat(tempstring1, "3 (Lasso)");
            } else strcat(tempstring1, "?");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Compression:        ");
            if (contents[which].DataPtr[11] == 0)
            {   strcat(tempstring1, "None");
            } elif (contents[which].DataPtr[11] == 1)
            {   strcat(tempstring1, "Byte run encoding");
            } else strcat(tempstring1, "?");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Transparent colour: ");
            if (contents[which].DataPtr[12] != 2
             && contents[which].DataPtr[12] != 3)
            {   strcat(tempstring1, "n/a");
            } else
            {   stcl_d(tempstring2, (256 * contents[which].DataPtr[12])
                                  +        contents[which].DataPtr[13]);
                strcat(tempstring1, tempstring2);
            }
            AddNameToTail(&List2, tempstring1);
    }   }   }
    elif (!strcmp(queryform, "AIFF"))
    {   if (!strcmp(contents[which].name, "MIDI"))
        {   chunkdesc("Stores MIDI data", FALSE);
        } elif (!strcmp(contents[which].name, "MARK"))
        {   chunkdesc("Points to positions in the sound data", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Markers:             ");
            svalue = getsword(contents[which].DataPtr);
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            if (svalue < 0)
            {   strcat(tempstring1, "!");
            }
            AddNameToTail(&List2, tempstring1);
            markers = svalue;
            if (markers > 0)
            {   currentpos = 2;
                for (i = 1; i <= markers; i++)
                {   strcpy(tempstring1, "Marker ");
                    stcl_d(tempstring2, i);
                    strcat(tempstring1, tempstring2);
                    strcat(tempstring1, ":");
                    AddNameToTail(&List2, tempstring1);

                    strcpy(tempstring1, " ID:                 ");
                    svalue = getsword(&(contents[which].name[currentpos]));
                    stcl_d(tempstring2, svalue);
                    strcat(tempstring1, tempstring2);
                    if (svalue < 1)
                    {   strcat(tempstring1, "!");
                    }
                    AddNameToTail(&List2, tempstring1);
                    currentpos += 2;

                    strcpy(tempstring1, " Position:           ");
                    uvalue = getulong(&(contents[which].name[currentpos]));
                    stcl_d(tempstring2, uvalue);
                    strcat(tempstring1, tempstring2);
                    AddNameToTail(&List2, tempstring1);
                    currentpos += 4;

                    strcpy(tempstring1, " Name:               ");
                    uvalue = contents[which].name[currentpos++];
                    // the number of characters in the string
                    if (uvalue < MEDFIELD)
                    {   strncat(tempstring1, &(contents[which].name[currentpos]), uvalue);
                    } else
                    {   strncat(tempstring1, &(contents[which].name[currentpos]), MEDFIELD);
                    }
                    AddNameToTail(&List2, tempstring1);
                    currentpos += uvalue;
                    if (uvalue % 2)
                    {   currentpos++; // skip pad byte, if appropriate
        }   }   }   }   }
        elif (!strcmp(contents[which].name, "AESD"))
        {   chunkdesc("Pertinent to autio recording devices", FALSE);
        } elif (!strcmp(contents[which].name, "COMT"))
        {   chunkdesc("Stores comments", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Comments:            ");
            svalue = getsword(contents[which].DataPtr);
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            if (svalue < 0)
            {   strcat(tempstring1, "!");
            }
            AddNameToTail(&List2, tempstring1);

            // we could have a 'comments' variable, but we just reuse
            // the 'markers' variable.
            markers = svalue;
            if (markers > 0)
            {   currentpos = 2;
                for (i = 1; i <= markers; i++)
                {   strcpy(tempstring1, "Comment ");
                    stcl_d(tempstring2, i);
                    strcat(tempstring1, tempstring2);
                    strcat(tempstring1, ":");
                    AddNameToTail(&List2, tempstring1);

                    strcpy(tempstring1, " Created on:         ");
                    uvalue = getulong(&(contents[which].DataPtr[currentpos]));
                    DateTime.dat_Stamp.ds_Days   =   uvalue / 86400;             // days since 1/1/78
                    DateTime.dat_Stamp.ds_Minute =  (uvalue % 86400) / 60;       // minutes in day
                    DateTime.dat_Stamp.ds_Tick   = ((uvalue % 86400) % 60) * 50; // ticks in minute
                    DateTime.dat_Format          = FORMAT_DOS;
                    DateTime.dat_Flags           = DTF_SUBST;
                    DateTime.dat_StrDay          = weekdaystring;
                    DateTime.dat_StrDate         = datestring;
                    DateTime.dat_StrTime         = timestring;
                    if (!DateToStr(&DateTime))
                    {   rq("DateToStr() failed!");
                    }
                    strcat(tempstring1, timestring);
                    strcat(tempstring1, " ");
                    strcat(tempstring1, weekdaystring);
                    strcat(tempstring1, " ");
                    strcat(tempstring1, datestring);
                    AddNameToTail(&List2, tempstring1);
                    currentpos += 4;

                    strcpy(tempstring1, " Marker ID:          ");
                    svalue = getsword(&(contents[which].DataPtr[currentpos]));
                    stcl_d(tempstring2, svalue);
                    strcat(tempstring1, tempstring2);
                    if (svalue < 1)
                    {    strcat(tempstring1, "!");
                    }
                    AddNameToTail(&List2, tempstring1);
                    currentpos += 2;

                    strcpy(tempstring1, " Comment:            ");
                    uvalue = getuword(&(contents[which].DataPtr[currentpos]));
                    // the number of characters in the string
                    currentpos += 2;
                    if (uvalue < MEDFIELD)
                    {   strncat(tempstring1, &(contents[which].name[currentpos]), uvalue);
                    } else
                    {   strncat(tempstring1, &(contents[which].name[currentpos]), MEDFIELD);
                    }
                    AddNameToTail(&List2, tempstring1);
                    currentpos += uvalue;
                    if (uvalue % 2)
                    {   currentpos++; // skip pad byte, if appropriate
        }   }   }   }   }
        elif (!strcmp(contents[which].name, "COMM"))
        {   chunkdesc("Fundamental parameters for the sampled sound", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Channels:            ");
            svalue = getsword(contents[which].DataPtr);
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            if (svalue == 1)
            {   strcat(tempstring1, " (mono)");
            } elif (svalue == 2)
            {   strcat(tempstring1, " (stereo)");
            } elif (svalue > 2)
            {   strcat(tempstring1, " (surround)");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Sample frames:       ");
            uvalue = getulong(&(contents[which].DataPtr[2]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Sample quality:      ");
            svalue = getsword(&(contents[which].DataPtr[6]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, "-bit");
            AddNameToTail(&List2, tempstring1);

            /* This is an 80-bit IEEE 754 Apple-style (SANE) floating
            point number (not yet implemented):
                 79 Sign
              64:78 Exponent
               0:63 Mantissa */
            strcpy(tempstring1, "Playback rate:       -");
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "APPL"))
        {   chunkdesc("Application-specific data", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "Application:         ");
                strcat(tempstring1, contents[which].DataPtr);
                if (!strcmp(tempstring1, "pdos"))
                {   strcat(tempstring1, " (Apple II)");
                }
                AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "SSND"))
        {   chunkdesc("The actual sample frames", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "Offset:              ");
                uvalue = getulong(contents[which].DataPtr);
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Block size:          ");
                uvalue = getulong(&(contents[which].DataPtr[4]));
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "INST"))
        {   chunkdesc("Instrument chunk", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Base note:           ");
            svalue = getsbyte(&(contents[which].DataPtr[0]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            if (svalue < 0 || svalue > 127)
                strcat(tempstring1, "!");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Detune:              ");
            svalue = getsbyte(&(contents[which].DataPtr[1]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            if (svalue < -50 || svalue > 50)
                strcat(tempstring1, "!");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Low note:            ");
            svalue = getsbyte(&(contents[which].DataPtr[2]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            if (svalue < 0 || svalue > 127)
                strcat(tempstring1, "!");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "High note:           ");
            svalue = getsbyte(&(contents[which].DataPtr[3]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            if (svalue < 0 || svalue > 127)
                strcat(tempstring1, "!");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Low velocity:        ");
            svalue = getsbyte(&(contents[which].DataPtr[4]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            if (svalue < 1 || svalue > 127)
                strcat(tempstring1, "!");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "High velocity:       ");
            svalue = getsbyte(&(contents[which].DataPtr[5]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            if (svalue < 1 || svalue > 127)
                strcat(tempstring1, "!");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Gain:                ");
            svalue = getsword(&(contents[which].DataPtr[6]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Sustain loop:");
            svalue = getsword(&(contents[which].DataPtr[8]));
            if (svalue == 0)
            {   strcpy(tempstring1, " No looping");
            } elif (svalue == 1)
            {   strcpy(tempstring1, " Forwards looping");
            } elif (svalue == 2)
            {   strcpy(tempstring1, " Forwards/backwards looping");
            } else
            {   strcpy(tempstring1, " ?");
            }
            AddNameToTail(&List2, tempstring1);
            strcpy(tempstring1, " Begin loop:         ");
            svalue = getsword(&(contents[which].DataPtr[10]));
            stcl_d(tempstring1, svalue);
            AddNameToTail(&List2, tempstring1);
            strcpy(tempstring1, " End loop:           ");
            svalue = getsword(&(contents[which].DataPtr[12]));
            stcl_d(tempstring1, svalue);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Release loop:        ");

            svalue = getsword(&(contents[which].DataPtr[14]));
            if (svalue == 0)
            {   strcpy(tempstring1, " No looping");
            } elif (svalue == 1)
            {   strcpy(tempstring1, " Forwards looping");
            } elif (svalue == 2)
            {   strcpy(tempstring1, " Forwards/backwards looping");
            } else
            {   strcpy(tempstring1, " ?");
            }
            AddNameToTail(&List2, tempstring1);
            strcpy(tempstring1, " Begin loop:         ");
            svalue = getsword(&(contents[which].DataPtr[16]));
            stcl_d(tempstring1, svalue);
            AddNameToTail(&List2, tempstring1);
            strcpy(tempstring1, " End loop:           ");
            svalue = getsword(&(contents[which].DataPtr[18]));
            stcl_d(tempstring1, svalue);
            AddNameToTail(&List2, tempstring1);
    }   }   }
    elif (!strcmp(queryform, "8SVX"))
    {   if (!strcmp(contents[which].name, "ATAK"))
        {   chunkdesc("Gives attack amplitude contour (envelope)", FALSE);
        } elif (!strcmp(contents[which].name, "RLSE"))
        {   chunkdesc("Gives release amplitude contour (envelope)", FALSE);
        } elif (!strcmp(contents[which].name, "BODY"))
        {   chunkdesc("Sound data chunk", FALSE);
        } elif (!strcmp(contents[which].name, "FADE"))
        {   chunkdesc("Fade away to silence", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "Fade start:          ");
                uvalue = getulong(contents[which].DataPtr);
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "SEQN"))
        {   chunkdesc("Multiple loop sequencing", TRUE);

        if (!iff.raw)
        {
            currentpos = 0;
            while (currentpos < contents[which].bytes)
            {   strcpy(tempstring1, "Loop start:          ");
                uvalue = getulong(&(contents[which].DataPtr[currentpos]));
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                if (uvalue % 4)
                {   strcat(tempstring1, "!");
                }
                AddNameToTail(&List2, tempstring1);
                currentpos += 4;

                strcpy(tempstring1, "Loop end:            ");
                uvalue = getulong(&(contents[which].DataPtr[currentpos]));
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                if (uvalue % 4)
                {   strcat(tempstring1, "!");
                }
                AddNameToTail(&List2, tempstring1);
                currentpos += 4;
        }   }   }
        elif (!strcmp(contents[which].name, "CHAN"))
        {   chunkdesc("Specified channel, or combination of channels", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "Channel:             ");
                svalue = getslong(contents[which].DataPtr);
                if (svalue == 2)
                {   strcat(tempstring1, "Left");
                } elif (svalue == 4)
                {   strcat(tempstring1, "Right");
                } elif (svalue == 6)
                {   strcat(tempstring1, "Stereo (both)");
                } else strcat(tempstring1, "?");
                AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "PAN "))
        {   chunkdesc("Stereo sound using a single array of data", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "Sound position:      ");
                svalue = getslong(contents[which].DataPtr);
                stcl_d(tempstring2, svalue);
                strcat(tempstring1, tempstring2);
                strcat(tempstring1, "/65536 ");
                if (svalue < 32768)
                {    strcat(tempstring1, "(left)");
                } elif (svalue > 32678)
                {    strcat(tempstring1, "(right)");
                } else
                {    // assert(svalue == 32678);
                     strcat(tempstring1, "(centre)");
                }
                AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "VHDR"))
        {   chunkdesc("Playback parameters for the sampled waveforms", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "1-shot samples:      ");
                uvalue = getulong(contents[which].DataPtr);
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Repeat samples:      ");
                uvalue = getulong(&(contents[which].DataPtr[4]));
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Samples per cycle:   ");
                uvalue = getulong(&(contents[which].DataPtr[8]));
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Sampling rate:       ");
                uvalue = getuword(&(contents[which].DataPtr[12]));
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Octaves:             ");
                uvalue = contents[which].DataPtr[14]; // UBYTE
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Compression:         "); // UBYTE
                if (contents[which].DataPtr[15] == 0)
                {   strcat(tempstring1, "None");
                } elif (contents[which].DataPtr[15] == 1)
                {   strcat(tempstring1, "Fibonacci-delta encoding");
                } else strcat(tempstring1, "?");
                AddNameToTail(&List2, tempstring1);

                strcpy(tempstring1, "Volume:              ");
                svalue = getslong(&(contents[which].DataPtr[16]));
                svalue /= 1024; // LONG (Fixed)
                stcl_d(tempstring2, svalue);
                strcat(tempstring1, tempstring2);
                strcat(tempstring1, "/64");
                AddNameToTail(&List2, tempstring1);
    }   }   }
    elif (!strcmp(queryform, "ILBM") || !strcmp(queryform, "ABCM") || !strcmp(queryform, "ANIM"))
    {   if (!strcmp(contents[which].name, "CAMG"))
        {   chunkdesc("Amiga display mode of a picture", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "ModeID:             $");
                hexalize(contents[which].DataPtr[0]);
                hexalize(contents[which].DataPtr[1]);
                hexalize(contents[which].DataPtr[2]);
                hexalize(contents[which].DataPtr[3]);
                AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(queryform, "ANIM") && !strcmp(contents[which].name, "ANHD"))
        {   chunkdesc("Animation header", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Compression method:     ");
            if (contents[which].DataPtr[0] == 0)
            {   strcat(tempstring1, "0 (set directly)");
            } elif (contents[which].DataPtr[0] == 1)
            {   strcat(tempstring1, "1 (XOR ILBM)");
            } elif (contents[which].DataPtr[0] == 2)
            {   strcat(tempstring1, "2 (long delta)");
            } elif (contents[which].DataPtr[0] == 3)
            {   strcat(tempstring1, "3 (short delta)");
            } elif (contents[which].DataPtr[0] == 4)
            {   strcat(tempstring1, "4 (short/long delta)");
            } elif (contents[which].DataPtr[0] == 5)
            {   strcat(tempstring1, "5 (byte vertical delta)");
            } elif (contents[which].DataPtr[0] == 6)
            {   strcat(tempstring1, "6 (stereo op 5)");
            } elif (contents[which].DataPtr[0] == 74) // not a typo
            {   strcat(tempstring1, "7 (Eric Graham)");
            } else
            {   strcat(tempstring1, "?");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Mask:                   %");
            binarize(contents[which].DataPtr[1]);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Entire width:           ");
            uvalue = getuword(&contents[which].DataPtr[2]); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " pixels");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Entire height:          ");
            uvalue = getuword(&contents[which].DataPtr[4]); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " pixels");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Width:                  ");
            svalue = getsword(&contents[which].DataPtr[6]); // WORD
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " pixels");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Height:                 ");
            svalue = getsword(&contents[which].DataPtr[8]); // WORD
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " pixels");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Absolute time:          ");
            uvalue = getulong(&contents[which].DataPtr[10]); // ULONG
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, "/60 of a second");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Relative time:          ");
            uvalue = getulong(&contents[which].DataPtr[14]); // ULONG
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, "/60 of a second");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Interleave:             ");
            if (contents[which].DataPtr[18] == 0)
            {   strcat(tempstring1, "0 (2 frames back)");
            } else
            {   stcl_d(tempstring2, contents[which].DataPtr[18]);
                strcat(tempstring1, tempstring2);
                strcat(tempstring1, " frames back");
            }
            AddNameToTail(&List2, tempstring1);

            // now a pad byte (19)

            strcpy(tempstring1, "Flags:");
            uvalue = getulong(&contents[which].DataPtr[20]); // ULONG

            strcpy(tempstring1, " Data length:           ");
            if (uvalue & 1)
            {   strcat(tempstring1, "Long");
            } else
            {   strcat(tempstring1, "Short");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Set/XOR:               ");
            if (uvalue & 2)
            {   strcat(tempstring1, "Set");
            } else
            {   strcat(tempstring1, "XOR");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Info:                  ");
            if (uvalue & 4)
            {   strcat(tempstring1, "One info list for all planes");
            } else
            {   strcat(tempstring1, "Separate info for each plane");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Run length encoded?    ");
            if (uvalue & 8)
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Encoding:              ");
            if (uvalue & 16)
            {   strcat(tempstring1, "Vertical");
            } else
            {   strcat(tempstring1, "Horizontal");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, " Info offsets:          ");
            if (uvalue & 32)
            {   strcat(tempstring1, "Short");
            } else
            {   strcat(tempstring1, "Long");
            }
            AddNameToTail(&List2, tempstring1);

            // now 16 reserved bytes
        }   }
        elif (!strcmp(queryform, "ANIM") && !strcmp(contents[which].name, "DLTA"))
        {   chunkdesc("Delta compression data", FALSE);
        } elif (!strcmp(contents[which].name, "DPI "))
        {   chunkdesc("Dots per inch", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "Dots per inch:      ");
                // There are 20 characters in the first column.
                uvalue = getuword(contents[which].DataPtr);
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                strcat(tempstring1, "x");
                uvalue = getuword(&(contents[which].DataPtr[2]));
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "CMAP"))
        {   chunkdesc("Colour map data", FALSE);
        } elif (!strcmp(contents[which].name, "BODY"))
        {   chunkdesc("Image data chunk", FALSE);
        } elif (!strcmp(contents[which].name, "EPSF"))
        {   chunkdesc("Encapsulated PostScript representation of image", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Left X:             ");
            svalue = getsword(contents[which].DataPtr);
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Top Y:              ");
            svalue = getsword(&(contents[which].DataPtr[2]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Right X:            ");
            svalue = getsword(&(contents[which].DataPtr[4]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Bottom Y:           ");
            svalue = getsword(&(contents[which].DataPtr[6]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "DEST"))
        {   chunkdesc("Scatter bitplanes into a deeper destination image", TRUE);

        if (!iff.raw)
        {
            strcpy(tempstring1, "Source bitplanes:   ");
            stcl_d(tempstring2, contents[which].DataPtr[0]);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            // next (1) is a pad byte.

            strcpy(tempstring1, "PlanePick:          %"); // UWORD
            binarize(contents[which].DataPtr[2]);
            binarize(contents[which].DataPtr[3]);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "PlaneOnOff:         %"); // UWORD
            binarize(contents[which].DataPtr[4]);
            binarize(contents[which].DataPtr[5]);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "PlaneMask:          %"); // UWORD
            binarize(contents[which].DataPtr[6]);
            binarize(contents[which].DataPtr[7]);
            AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "GRAB"))
        {   chunkdesc("Locates a hotspot, when used as a pointer or brush", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "Hotspot:            ");
                svalue = getsword(contents[which].DataPtr);
                stcl_d(tempstring2, svalue);
                strcat(tempstring1, tempstring2);
                strcat(tempstring1, ",");
                svalue = getsword(&(contents[which].DataPtr[2]));
                stcl_d(tempstring2, svalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "SPRT"))
        {   chunkdesc("This image is intended as a sprite", TRUE);

            if (!iff.raw)
            {   strcpy(tempstring1, "Precedence:         ");
                uvalue = getuword(contents[which].DataPtr);

                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                AddNameToTail(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "BMHD"))
        {   /* UWORD w, h;               0-1, 2-3
            WORD  x, y;                  4-5, 6-7
            UBYTE nPlanes;               8
            UBYTE Masking;               9
            UBYTE Compression;           10
            UBYTE pad;                   11
            UWORD transparentColour;     12-13
            UBYTE xAspect, yAspect;      14, 15
            WORD  pageWidth, pageHeight; 16-17, 18-19 */

            chunkdesc("Data necessary to understand the BODY chunk", TRUE);

            if (!iff.raw)
            {
            strcpy(tempstring1, "Image size:         ");
            stcl_d(tempstring2, (256 * contents[which].DataPtr[0])
                              +        contents[which].DataPtr[1]); // UWORD
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, "x");
            stcl_d(tempstring2, (256 * contents[which].DataPtr[2])
                              +        contents[which].DataPtr[3]); // UWORD
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Position:           ");
            stcl_d(tempstring2, (256 * contents[which].DataPtr[4])
                              +        contents[which].DataPtr[5]); // WORD
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, ",");
            stcl_d(tempstring2, (256 * contents[which].DataPtr[6])
                              +        contents[which].DataPtr[7]); // WORD
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Bitplanes:          ");
            stcl_d(tempstring2, (LONG) contents[which].DataPtr[8]);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);
            // tell number of colours to user?

            strcpy(tempstring1, "Masking:            ");
            if (contents[which].DataPtr[9] == 0)
            {   strcat(tempstring1, "0 (Opaque)");
            } elif (contents[which].DataPtr[9] == 1)
            {   strcat(tempstring1, "1 (Mask plane)");
            } elif (contents[which].DataPtr[9] == 2)
            {   strcat(tempstring1, "2 (Transparent colour)");
            } elif (contents[which].DataPtr[9] == 3)
            {   strcat(tempstring1, "3 (Lasso)");
            } else strcat(tempstring1, "?");
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Compression:        ");
            if (contents[which].DataPtr[10] == 0)
            {   strcat(tempstring1, "None");
            } elif (contents[which].DataPtr[10] == 1)
            {   strcat(tempstring1, "Byte run encoding");
            } else strcat(tempstring1, "?");
            AddNameToTail(&List2, tempstring1);

            // Next (11) is a pad byte.

            strcpy(tempstring1, "Transparent colour: ");
            if (contents[which].DataPtr[9] != 2
             && contents[which].DataPtr[9] != 3)
            {   strcat(tempstring1, "n/a");
            } else
            {   stcl_d(tempstring2, (256 * contents[which].DataPtr[12])
                                  +        contents[which].DataPtr[13]);
                strcat(tempstring1, tempstring2);
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Aspect ratio:       ");
            stcl_d(tempstring2, (UBYTE) contents[which].DataPtr[14]);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, ":");
            stcl_d(tempstring2, (UBYTE) contents[which].DataPtr[15]);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "Page size:          ");
            stcl_d(tempstring2, (256 * contents[which].DataPtr[16])
                              +        contents[which].DataPtr[17]); // WORD
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, "x");
            stcl_d(tempstring2, (256 * contents[which].DataPtr[18])
                              +        contents[which].DataPtr[19]); // WORD
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);
    }   }   }

    if (!known || iff.raw)
    {   for (i = 0; i < contents[which].bytes; i += BYTESPERLINE)
        {   strcpy(tempstring1, "$");

            hexalize(i / 16777216); // do 1st byte
            j = i % 16777216;       // remove 1st byte
            hexalize(j / 65536);    // do 2nd byte
            j %= 65536;             // remove 2nd byte
            hexalize(j / 256);      // do 3rd byte
            hexalize(j % 256);      // do 4th byte

            strcat(tempstring1, ": ");
            for (j = 0; j < BYTESPERLINE; j++)
            {   if (contents[which].bytes > i + j)
                {   hexalize(contents[which].DataPtr[i + j]);
                } else
                {   strcat(tempstring1, "##");
                }
                if (j % 2)
                {   strcat(tempstring1, " ");
            }   }
            for (j = 0; j < BYTESPERLINE; j++)
            {   if (contents[which].bytes > i + j)
                {   if (contents[which].DataPtr[i + j] < ' ') // if an unprintable character
                    {   strcat(tempstring1, ".");
                    } else
                    {   length = strlen(tempstring1);
                        tempstring1[length] = contents[which].DataPtr[i + j];
                        tempstring1[length + 1] = 0;
                }   }
                else
                {   strcat(tempstring1, "#");
            }   }
            AddNameToTail(&List2, tempstring1);
    }   }
    if (!known)
    {   chunkdesc("?", FALSE);
    }

    GT_SetGadgetAttrs
    (   LV61_List2,
        MainWindowPtr,
        NULL,
        GTLV_Labels, &List2,
        TAG_DONE
    );
}

MODULE void chunkdesc(STRPTR desc, ABOOL isknown)
{   GT_SetGadgetAttrs
    (   TE61_ChunkDesc,
        MainWindowPtr,
        NULL,
        GTTX_Text, desc,
        TAG_DONE
    );
    known = isknown;
}

MODULE void binarize(UBYTE data)
{   SLONG i; // must be signed

    for (i = 7; i >= 0; i--)
    {   if (data & (1 << i))
        {   strcat(tempstring1, "1");
        } else
        {   strcat(tempstring1, "0");
}   }   }

MODULE void hexalize(UBYTE data)
{   // Converts an unsigned byte into a hexadecimal string

    // do the high byte
    if (data / 16 >= 10)
    {   tempstring2[0] = (data / 16) - 10 + 'A'; // must be done in this order to prevent overflow during calculation of the value
    } else
    {   tempstring2[0] = (data / 16) + '0';
    }

    // now the low byte
    if (data % 16 >= 10)
    {   tempstring2[1] = (data % 16) - 10 + 'A';
    } else
    {   tempstring2[1] = (data % 16) + '0';
    }
    tempstring2[2] = 0;
    strcat(tempstring1, tempstring2);
}

MODULE ULONG getulong(UBYTE* start)
{   return (ULONG) ((16777216 * *(start    ))
                  + (   65536 * *(start + 1))
                  + (     256 * *(start + 2))
                  +             *(start + 3));
}
MODULE SLONG getslong(UBYTE* start)
{   return (SLONG) ((16777216 * *(start    ))
                  + (   65536 * *(start + 1))
                  + (     256 * *(start + 2))
                  +             *(start + 3));
}
MODULE ULONG getuword(UBYTE* start)
{   return (ULONG) ((     256 * *(start    ))
                  +             *(start + 1));
}
MODULE SLONG getsword(UBYTE* start)
{   return (SLONG) ((     256 * *(start    ))
                  +             *(start + 1));
}
MODULE SLONG getsbyte(UBYTE* start)
{   return (SBYTE) (*start);
}

MODULE void writeiffgadgets(void)
{   // update the gadgets according to variables

    GT_SetGadgetAttrs
    (   CB61_CD,
        MainWindowPtr,
        NULL,
        GTCB_Checked, iff.cd,
        TAG_DONE
    );
    GT_SetGadgetAttrs
    (   CB61_RKM,
        MainWindowPtr,
        NULL,
        GTCB_Checked, iff.rkm,
        TAG_DONE
    );
    GT_SetGadgetAttrs
    (   CB61_Obsolete,
        MainWindowPtr,
        NULL,
        GTCB_Checked, iff.obsolete,
        TAG_DONE
    );
    GT_SetGadgetAttrs
    (   CB61_Private,
        MainWindowPtr,
        NULL,
        GTCB_Checked, iff.private,
        TAG_DONE
    );
    GT_SetGadgetAttrs
    (   CB61_Proposal,
        MainWindowPtr,
        NULL,
        GTCB_Checked, iff.proposal,
        TAG_DONE
    );
    GT_SetGadgetAttrs
    (   CB61_Reserved,
        MainWindowPtr,
        NULL,
        GTCB_Checked, iff.reserved,
        TAG_DONE
    );
    GT_SetGadgetAttrs
    (   CB61_Standard,
        MainWindowPtr,
        NULL,
        GTCB_Checked, iff.standard,
        TAG_DONE
    );
    GT_SetGadgetAttrs
    (   CB61_Unregistered,
        MainWindowPtr,
        NULL,
        GTCB_Checked, iff.unregistered,
        TAG_DONE
    );
    GT_SetGadgetAttrs
    (   ST61_FORMID,
        MainWindowPtr,
        NULL,
        GTST_String, queryform,
        TAG_DONE
    );
    chunkdesc("-", FALSE);
}

MODULE void dotextattr(UBYTE* offset)
{   ULONG uvalue;

    // handles TextAttr structure (8 bytes)
    // name pointer is ignored

            strcpy(tempstring1, " Height:                ");
            uvalue = getuword(offset + 4);
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            AddNameToTail(&List2, tempstring1);

            AddNameToTail(&List2, " Style:");

            strcpy(tempstring1, "  Underlined?           ");
            if ((*(offset + 6)) &   1) // FSF_UNDERLINED
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "  Bold?                 ");
            if (*(offset + 6) &   2) // FSF_BOLD
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "  Italic?               ");
            if (*(offset + 6) &   4) // FSF_UNDERLINED
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "  Extended?             ");
            if (*(offset + 6) &   8) // FSF_EXTENDED
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "  Colour font?          ");
            if (*(offset + 6) &  64) // FSF_COLORFONT
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "  Tagged?               ");
            if (*(offset + 6) & 128) // FSF_TAGGED
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            AddNameToTail(&List2, " Flags:");

            strcpy(tempstring1, "  ROM font?             ");
            if (*(offset + 7) &   1) // FPF_ROMFONT
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "  Disk font?            ");
            if (*(offset + 7) &   2) // FPF_DISKFONT
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "  Reversed?             ");
            if (*(offset + 7) &   4) // FPF_REVPATH
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

            strcpy(tempstring1, "  HiRes non-interlaced? ");
            if (*(offset + 7) &   8) // FPF_TALLDOT
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, "  LoRes interlaced?     ");
    if (*(offset + 7) &  16) // FPF_WIDEDOT
    {   strcat(tempstring1, "Yes");
    } else
    {   strcat(tempstring1, "No");
    }
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, "  Proportional?         ");
    if (*(offset + 7) &  32) // FPF_PROPORTIONAL
    {   strcat(tempstring1, "Yes");
    } else
    {   strcat(tempstring1, "No");
    }
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, "  Designed?             ");
    if (*(offset + 7) &  64) // FPF_DESIGNED
    {   strcat(tempstring1, "Yes");
    } else
    {   strcat(tempstring1, "No");
    }
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, "  Removed?              ");
    if (*(offset + 7) & 128) // FPF_REMOVED
    {   strcat(tempstring1, "Yes!");
    } else
    {   strcat(tempstring1, "No");
    }
    AddNameToTail(&List2, tempstring1);
}

MODULE void docountry(UBYTE* offset)
{   ULONG uvalue;

    // handles CountryPrefs structure (8 bytes)

    // 16 reserved bytes at start

    strcpy(tempstring1, "Country code:           ");
    uvalue = getulong(offset + 16); // ULONG
    stcl_d(tempstring2, uvalue);
    strcat(tempstring1, tempstring2);
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, "Telephone code:         ");
    uvalue = getulong(offset + 20); // ULONG
    stcl_d(tempstring2, uvalue);
    strcat(tempstring1, tempstring2);
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, "Measuring system:       ");
    if (*(offset + 24) == 0) // MS_ISO
    {   strcat(tempstring1, "0 (Metric)");
    } elif (*(offset + 24) == 1) // MS_AMERICAN
    {   strcat(tempstring1, "1 (American)");
    } elif (*(offset + 24) == 2) // MS_IMPERIAL
    {   strcat(tempstring1, "2 (Imperial)");
    } elif (*(offset + 24) == 3) // MS_BRITISH
    {   strcat(tempstring1, "3 (British)");
    } else
    {   strcat(tempstring1, "?");
    }
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, "Long date/time format:  ");
    strcat(tempstring1, offset + 25); // 80 chars
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, "Long date format:       ");
    strcat(tempstring1, offset + 105); // 40 chars
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, "Long time format:       ");
    strcat(tempstring1, offset + 145); // 40 chars
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, "Short date/time format: ");
    strcat(tempstring1, offset + 185); // 80 chars
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, "Short date format:      ");
    strcat(tempstring1, offset + 225); // 40 chars
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, "Short time format:      ");
    strcat(tempstring1, offset + 265); // 40 chars
    AddNameToTail(&List2, tempstring1);

    AddNameToTail(&List2, "Numeric values:");

    strcpy(tempstring1, " Decimal point:         ");
    strcat(tempstring1, offset + 305); // 10 chars
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, " Intgr group separator: ");
    strcat(tempstring1, offset + 315); // 10 chars
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, " Frac. group separator: ");
    strcat(tempstring1, offset + 325); // 10 chars
    AddNameToTail(&List2, tempstring1);

    /* Integer group size (10 chars) and
       Fractional group size (10 chars): not strings (currently skipped */

    AddNameToTail(&List2, "General monetary values:");

    strcpy(tempstring1, " Decimal point:         ");
    strcat(tempstring1, offset + 355); // 10 chars
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, " Intgr group separator: ");
    strcat(tempstring1, offset + 365); // 10 chars
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, " Frac. group separator: ");
    strcat(tempstring1, offset + 375); // 10 chars
    AddNameToTail(&List2, tempstring1);

    /* Integer group size (10 chars) and
       Fractional group size (10 chars): not strings (currently skipped */

    AddNameToTail(&List2, " Digits after decimal point:");

    strcpy(tempstring1, "  Intranational:        ");
    stcl_d(tempstring2, *(offset + 405));
    strcat(tempstring1, tempstring2);
    AddNameToTail(&List2, tempstring1);
    strcpy(tempstring1, "  International:        ");
    stcl_d(tempstring2, *(offset + 406));
    strcat(tempstring1, tempstring2);
    AddNameToTail(&List2, tempstring1);

    AddNameToTail(&List2, "Currency symbols:");

    strcpy(tempstring1, " Large amounts symbol:  ");
    strcat(tempstring1, offset + 407); // 10 chars
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, " Small amounts symbol:  ");
    strcat(tempstring1, offset + 417); // 10 chars
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, " ISO 4217 code:         ");
    strcat(tempstring1, offset + 427); // 10 chars
    AddNameToTail(&List2, tempstring1);

    AddNameToTail(&List2, "Positive monetary values:");

    strcpy(tempstring1, " Positive sign:         ");
    strcat(tempstring1, offset + 437); // 10 chars
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, " Space next to sign?    ");
    if (*(offset + 447) == 0) // SS_NOSPACE
    {   strcat(tempstring1, "No");
    } elif (*(offset + 447) == 1) // SS_SPACE
    {   strcat(tempstring1, "Yes");
    } else strcat(tempstring1, "?");
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, " Positive sign pos.:    ");
    if (*(offset + 448) == 0) // SP_PARENS
    {   strcat(tempstring1, "0 (parentheses around amount and symbol)");
    } elif (*(offset + 448) == 1) // SP_PREC_ALL
    {   strcat(tempstring1, "1 (sign is before amount and symbol)");
    } elif (*(offset + 448) == 2) // SP_SUCC_ALL
    {   strcat(tempstring1, "2 (sign is after amount and symbol)");
    } elif (*(offset + 448) == 3) // SP_PREC_CURR
    {   strcat(tempstring1, "3 (sign is before symbol)");
    } elif (*(offset + 448) == 4) // SP_SUCC_CURR
    {   strcat(tempstring1, "4 (sign is after symbol)");
    } else
    {   strcat(tempstring1, "?");
    }
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, " Currency symbol pos.:  ");
    if (*(offset + 449) == 0) // CSP_PRECEDES
    {   strcat(tempstring1, "0 (symbol is before amount)");
    } elif (*(offset + 449) == 1) // CSP_SUCCEEDS
    {   strcat(tempstring1, "1 (symbol is after amount)");
    } else
    {   strcat(tempstring1, "?");
    }
    AddNameToTail(&List2, tempstring1);

    AddNameToTail(&List2, "Negative monetary values:");

    strcpy(tempstring1, " Negative sign:         ");
    strcat(tempstring1, offset + 450); // 10 chars
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, " Space next to sign?    ");
    if (*(offset + 460) == 0) // SS_NOSPACE
    {   strcat(tempstring1, "No");
    } elif (*(offset + 460) == 1) // SS_SPACE
    {   strcat(tempstring1, "Yes");
    } else strcat(tempstring1, "?");
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, " Negative sign pos.:    ");
    if (*(offset + 461) == 0) // SP_PARENS
    {   strcat(tempstring1, "0 (parentheses around amount and symbol)");
    } elif (*(offset + 461) == 1) // SP_PREC_ALL
    {   strcat(tempstring1, "1 (sign is before amount and symbol)");
    } elif (*(offset + 461) == 2) // SP_SUCC_ALL
    {   strcat(tempstring1, "2 (sign is after amount and symbol)");
    } elif (*(offset + 461) == 3) // SP_PREC_CURR
    {   strcat(tempstring1, "3 (sign is before symbol)");
    } elif (*(offset + 461) == 4) // SP_SUCC_CURR
    {   strcat(tempstring1, "4 (sign is after symbol)");
    } else
    {   strcat(tempstring1, "?");
    }
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, " Currency symbol pos.:  ");
    if (*(offset + 462) == 0) // CSP_PRECEDES
    {   strcat(tempstring1, "0 (symbol is before amount)");
    } elif (*(offset + 462) == 1) // CSP_SUCCEEDS
    {   strcat(tempstring1, "1 (symbol is after amount)");
    } else
    {   strcat(tempstring1, "?");
    }
    AddNameToTail(&List2, tempstring1);

    strcpy(tempstring1, "First day of the week:  ");
    if (*(offset + 463) == 0)
    {   strcat(tempstring1, "0 (Sunday)");
    } elif (*(offset + 463) == 1)
    {   strcat(tempstring1, "1 (Monday)");
    } elif (*(offset + 463) == 2)
    {   strcat(tempstring1, "2 (Tuesday)");
    } elif (*(offset + 463) == 3)
    {   strcat(tempstring1, "3 (Wednesday)");
    } elif (*(offset + 463) == 4)
    {   strcat(tempstring1, "4 (Thursday)");
    } elif (*(offset + 463) == 5)
    {   strcat(tempstring1, "5 (Friday)");
    } elif (*(offset + 463) == 6)
    {   strcat(tempstring1, "6 (Saturday)");
    } else
    {   strcat(tempstring1, "?");
    }
    AddNameToTail(&List2, tempstring1);
}

AGLOBAL void iff_init(void)
{   iff.raw = FALSE;
}

AGLOBAL void iff_die(void)
{   IOBuffer[19] = (UBYTE) iff.raw;
}

AGLOBAL void iff_config(void)
{   iff.raw = (ABOOL) IOBuffer[19];
}

