#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <libraries/iffparse.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/iffparse_protos.h>
#include <clib/dos_protos.h>

#define ALL_REACTION_CLASSES
#define ALL_REACTION_MACROS
#include <reaction/reaction.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 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 SBYTE              page;
IMPORT struct Window*     MainWindowPtr;
IMPORT struct TextAttr    Topaz8;
IMPORT TEXT               aslresult[VLONGFIELD + 1],
                          weekdaystring[LEN_DATSTRING],
                          datestring[LEN_DATSTRING],
                          timestring[LEN_DATSTRING],
                          IOBuffer[LONGESTFIELD + 1];
IMPORT Object*            WinObject[FUNCTIONS + 1]; // note that WindowObject is a reserved macro
IMPORT struct Menu*       MenuPtr;
IMPORT struct Screen*     ScreenPtr;

MODULE ABOOL             known, first;
MODULE struct IFFHandle* IFFHandle             = NULL;
MODULE struct List       List1,
                         List2;
MODULE TEXT  queryform[5] = "",
             tempstring1[VLONGFIELD + 1],
             tempstring2[13];
MODULE ULONG items        = 0; // value of this is actual number of items allocated
MODULE UWORD selectedform  = 0,
             selectedchunk = 0;
MODULE struct Gadget*    iff_gadgets[GIDS_6 + 1];
    
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",                                 "?",
    PRIVATE,                  "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)
{   struct Hook Hook6Struct;
    STRPTR      stringptr;

    InitHook(&Hook6Struct, Hook6Func, NULL);

    /* Create the window object. */
    lockscreen();

if (!(WinObject[6] =
NewObject
(   WINDOW_GetClass(),                    NULL,
    WA_PubScreen,                         ScreenPtr,
    WA_ScreenTitle,                       "Report+",
    WA_Title,                             "Report+: IFF FORM Viewer",
    WA_Activate,                          TRUE,
    WA_DepthGadget,                       TRUE,
    WA_DragBar,                           TRUE,
    WA_CloseGadget,                       TRUE,
    WA_SizeGadget,                        TRUE,
    WA_IDCMP,                             IDCMP_RAWKEY,
    WINDOW_IDCMPHook,                     &Hook6Struct,
    WINDOW_IDCMPHookBits,                 IDCMP_RAWKEY,
    WINDOW_MenuStrip,                     MenuPtr,
    WINDOW_Position,                      WPOS_CENTERSCREEN,
    WINDOW_ParentGroup,                   iff_gadgets[GID_6_LY1] =
    NewObject
    (   LAYOUT_GetClass(),                NULL,
        LAYOUT_Orientation,               LAYOUT_ORIENT_VERT,
        LAYOUT_SpaceOuter,                TRUE,
        LAYOUT_DeferLayout,               TRUE,
        LAYOUT_AddChild,
        NewObject
        (   LAYOUT_GetClass(),            NULL,
            LAYOUT_Orientation,           LAYOUT_ORIENT_HORIZ,
            LAYOUT_SpaceOuter,            TRUE,
            LAYOUT_DeferLayout,           TRUE,
            LAYOUT_BevelStyle,            BVS_NONE,
            LAYOUT_AddChild,
            NewObject
            (   LAYOUT_GetClass(),        NULL,
                LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
                LAYOUT_SpaceOuter,        TRUE,
                LAYOUT_VertAlignment,     LALIGN_CENTER,
                LAYOUT_BevelStyle,        BVS_NONE,
                LAYOUT_AddChild,
                NewObject
                (   LAYOUT_GetClass(),    NULL,
                    LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
                    LAYOUT_SpaceOuter,    TRUE,
                    LAYOUT_HorizAlignment,LALIGN_RIGHT,
                    LAYOUT_BevelStyle,    BVS_NONE,
                    LAYOUT_AddImage,
                    NewObject
                    (   LABEL_GetClass(),     NULL,
                        LABEL_Text,           "_FORM ID:",
                        LABEL_Justification,  LJ_RIGHT,
                    TAG_END),
                TAG_END),
                LAYOUT_AddChild,
                NewObject
                (   LAYOUT_GetClass(),        NULL,
                    LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
                    LAYOUT_SpaceOuter,        TRUE,
                    LAYOUT_HorizAlignment,    LALIGN_RIGHT,
                    LAYOUT_BevelStyle,        BVS_NONE,
                    LAYOUT_AddImage,
                    NewObject
                    (   LABEL_GetClass(),     NULL,
                        LABEL_Text,           "Description:",
                        LABEL_Justification,  LJ_RIGHT,
                    TAG_END),
                TAG_END),
                LAYOUT_AddChild,
                NewObject
                (   LAYOUT_GetClass(),        NULL,
                    LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
                    LAYOUT_SpaceOuter,        TRUE,
                    LAYOUT_HorizAlignment,    LALIGN_RIGHT,
                    LAYOUT_BevelStyle,        BVS_NONE,
                    LAYOUT_AddImage,
                    NewObject
                    (   LABEL_GetClass(),     NULL,
                        LABEL_Text,           "Contributor:",
                        LABEL_Justification,  LJ_RIGHT,
                    TAG_END),
                TAG_END),
                LAYOUT_AddChild,
                NewObject
                (   LAYOUT_GetClass(),        NULL,
                    LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
                    LAYOUT_SpaceOuter,        TRUE,
                    LAYOUT_HorizAlignment,    LALIGN_RIGHT,
                    LAYOUT_BevelStyle,        BVS_NONE,
                    LAYOUT_AddImage,
                    NewObject
                    (   LABEL_GetClass(),     NULL,
                        LABEL_Text,           "Chunk info:",
                        LABEL_Justification,  LJ_RIGHT,
                    TAG_END),
                TAG_END),
                LAYOUT_AddChild,
                NewObject
                (   LAYOUT_GetClass(),        NULL,
                    LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
                    LAYOUT_SpaceOuter,        TRUE,
                    LAYOUT_HorizAlignment,    LALIGN_RIGHT,
                    LAYOUT_BevelStyle,        BVS_NONE,
                    LAYOUT_AddImage,
                    NewObject
                    (   LABEL_GetClass(),     NULL,
                        LABEL_Text,           "_Pathname:",
                        LABEL_Justification,  LJ_RIGHT,
                    TAG_END),
                TAG_END),
                LAYOUT_AddChild,
                NewObject
                (   LAYOUT_GetClass(),        NULL,
                    LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
                    LAYOUT_SpaceOuter,        TRUE,
                    LAYOUT_HorizAlignment,    LALIGN_RIGHT,
                    LAYOUT_BevelStyle,        BVS_NONE,
                    LAYOUT_AddImage,
                    NewObject
                    (   LABEL_GetClass(),     NULL,
                        LABEL_Text,           "Status:",
                        LABEL_Justification,  LJ_RIGHT,
                    TAG_END),
                TAG_END),
            TAG_END),
            CHILD_WeightedWidth,      0,
            LAYOUT_AddChild,
            NewObject
            (   LAYOUT_GetClass(),        NULL,
                LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
                LAYOUT_SpaceOuter,        TRUE,
                LAYOUT_VertAlignment,     LALIGN_CENTER,
                LAYOUT_HorizAlignment,    LALIGN_CENTER,
                LAYOUT_BevelStyle,        BVS_NONE,
                LAYOUT_AddChild,
                NewObject
                (   LAYOUT_GetClass(),    NULL,
                    LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
                    LAYOUT_SpaceOuter,    TRUE,
                    LAYOUT_VertAlignment, LALIGN_CENTER,
                    LAYOUT_HorizAlignment,LALIGN_LEFT,
                    LAYOUT_BevelStyle,    BVS_NONE,
                    LAYOUT_AddChild,          iff_gadgets[GID_6_ST1] =
                    NewObject
                    (   STRING_GetClass(),    NULL,
                        GA_ID,                GID_6_ST1,
                        GA_TabCycle,          TRUE,
                        GA_RelVerify,         TRUE,
                        STRINGA_TextVal,      queryform,
                        STRINGA_ReplaceMode,  TRUE,
                        STRINGA_MinVisible,   4,
                        STRINGA_MaxChars,     4 + 1,
                    TAG_END),
                    CHILD_WeightedWidth,      50,
                    LAYOUT_AddChild,          iff_gadgets[GID_6_CB1] =
                    NewObject
                    (   CHECKBOX_GetClass(),  NULL,
                        GA_ID,                GID_6_CB1,
                        GA_RelVerify,         TRUE,
                        GA_Text,              "_Raw view only?",
                        GA_Selected,          (BOOL) iff.raw,
                    TAG_END),
                    CHILD_WeightedWidth,      50,
                TAG_END),    
                LAYOUT_AddChild,          iff_gadgets[GID_6_ST2] =
                NewObject
                (   STRING_GetClass(),    NULL,
                    GA_ID,                GID_6_ST2,
                    GA_ReadOnly,          TRUE,
                    STRINGA_TextVal,      "-",
                    STRINGA_MinVisible,   20,
                TAG_END),
                LAYOUT_AddChild,          iff_gadgets[GID_6_ST3] =
                NewObject
                (   STRING_GetClass(),    NULL,
                    GA_ID,                GID_6_ST3,
                    GA_ReadOnly,          TRUE,
                    STRINGA_TextVal,      "-",
                    STRINGA_MinVisible,   20,
                TAG_END),
                LAYOUT_AddChild,          iff_gadgets[GID_6_ST4] =
                NewObject
                (   STRING_GetClass(),    NULL,
                    GA_ID,                GID_6_ST4,
                    GA_ReadOnly,          TRUE,
                    STRINGA_TextVal,      "-",
                    STRINGA_MinVisible,   20,
                TAG_END),
                LAYOUT_AddChild,
                NewObject
                (   LAYOUT_GetClass(),    NULL,
                    LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
                    LAYOUT_SpaceOuter,    TRUE,
                    LAYOUT_VertAlignment, LALIGN_CENTER,
                    LAYOUT_HorizAlignment,LALIGN_LEFT,
                    LAYOUT_BevelStyle,    BVS_NONE,
                    LAYOUT_AddChild,          iff_gadgets[GID_6_ST6] =
                    NewObject
                    (   STRING_GetClass(),    NULL,
                        GA_ID,                GID_6_ST6,
                        GA_RelVerify,         TRUE,
                        GA_TabCycle,          TRUE,
                        STRINGA_TextVal,      iff.pathname,
                        STRINGA_MinVisible,   20,
                        STRINGA_MaxChars,     PATHNAMEFIELD,
                    TAG_END),
                    LAYOUT_AddChild,      iff_gadgets[GID_6_BU1] =
                    NewObject
                    (   NULL,             "button.gadget",
                        GA_ID,            GID_6_BU1,
                        GA_RelVerify,     TRUE,
                        BUTTON_AutoButton,BAG_POPFILE,
                    TAG_END),
                    CHILD_WeightedWidth,  0,
                TAG_END),
                CHILD_WeightedHeight,     0,
                LAYOUT_AddChild,          iff_gadgets[GID_6_ST5] =
                NewObject
                (   STRING_GetClass(),    NULL,
                    GA_ID,                GID_6_ST5,
                    GA_ReadOnly,          TRUE,
                    STRINGA_TextVal,      "Ready.",
                    STRINGA_MinVisible,   20,
                TAG_END),
            TAG_END),
        TAG_END),
        CHILD_WeightedHeight,         0,
        LAYOUT_AddChild,
        NewObject
        (   LAYOUT_GetClass(),        NULL,
            LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
            LAYOUT_SpaceOuter,        TRUE,
            LAYOUT_HorizAlignment,    LALIGN_CENTER,
            LAYOUT_BevelStyle,        BVS_NONE,
            LAYOUT_AddChild,
            NewObject
            (   LAYOUT_GetClass(),        NULL,
                LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
                LAYOUT_SpaceOuter,        TRUE,
                LAYOUT_HorizAlignment,    LALIGN_CENTER,
                LAYOUT_BevelStyle,        BVS_NONE,
                LAYOUT_AddImage,
                NewObject
                (   LABEL_GetClass(),     NULL,
                    LABEL_Text,           "Chunks:",
                    LABEL_Justification,  LJ_CENTER,
                TAG_END),
                CHILD_WeightedHeight,     0,
                LAYOUT_AddChild,          iff_gadgets[GID_6_LB1] =
                NewObject
                (   LISTBROWSER_GetClass(),NULL,
                    GA_ID,                 GID_6_LB1,
                    GA_RelVerify,          TRUE,
                    GA_TextAttr,           &Topaz8,
                    LISTBROWSER_Labels,    (ULONG) &List1,
                TAG_END),
            TAG_END),
            CHILD_WeightedWidth,           25,
            CHILD_MinWidth,               172,
            LAYOUT_AddChild,
            NewObject
            (   LAYOUT_GetClass(),        NULL,
                LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
                LAYOUT_SpaceOuter,        TRUE,
                LAYOUT_HorizAlignment,    LALIGN_CENTER,
                LAYOUT_BevelStyle,        BVS_NONE,
                LAYOUT_AddImage,
                NewObject
                (   LABEL_GetClass(),     NULL,
                    LABEL_Text,           "Chunk contents:",
                    LABEL_Justification,  LJ_CENTER,
                TAG_END),
                CHILD_WeightedHeight,     0,
                LAYOUT_AddChild,          iff_gadgets[GID_6_LB2] =
                NewObject
                (   LISTBROWSER_GetClass(),NULL,
                    GA_ID,                 GID_6_LB2,
                    GA_RelVerify,          TRUE,
                    GA_TextAttr,           &Topaz8,
                    LISTBROWSER_Labels,    (ULONG) &List2,
                TAG_END),
            TAG_END),
        TAG_END),
        CHILD_WeightedHeight,          100,
        CHILD_MinHeight,               128,
        LAYOUT_AddChild,
        NewObject
        (   LAYOUT_GetClass(),        NULL,
            LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
            LAYOUT_SpaceOuter,        TRUE,
            LAYOUT_HorizAlignment,    LALIGN_RIGHT,
            LAYOUT_BevelStyle,        BVS_FIELD,
            LAYOUT_AddChild,
            NewObject
            (   LAYOUT_GetClass(),        NULL,
                LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
                LAYOUT_SpaceOuter,        TRUE,
                LAYOUT_HorizAlignment,    LALIGN_RIGHT,
                LAYOUT_BevelStyle,        BVS_NONE,
                LAYOUT_AddImage,
                NewObject
                (   LABEL_GetClass(),     NULL,
                    LABEL_Text,           "",
                TAG_END),
                CHILD_WeightedHeight,     50,
                LAYOUT_AddImage,
                NewObject
                (   LABEL_GetClass(),     NULL,
                    LABEL_Text,           "Status:",
                    LABEL_Justification,  LJ_RIGHT,
                TAG_END),
                CHILD_WeightedHeight,     0,
                LAYOUT_AddImage,
                NewObject
                (   LABEL_GetClass(),     NULL,
                    LABEL_Text,           "",
                TAG_END),
                CHILD_WeightedHeight,     50,
            TAG_END),
            CHILD_WeightedWidth,          20,
            LAYOUT_AddChild,
            NewObject
            (   LAYOUT_GetClass(),        NULL,
                LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
                LAYOUT_SpaceOuter,        TRUE,
                LAYOUT_HorizAlignment,    LALIGN_RIGHT,
                LAYOUT_BevelStyle,        BVS_NONE,
                LAYOUT_AddChild,
                NewObject
                (   LAYOUT_GetClass(),        NULL,
                    LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
                    LAYOUT_SpaceOuter,        TRUE,
                    LAYOUT_HorizAlignment,    LALIGN_RIGHT,
                    LAYOUT_BevelStyle,        BVS_NONE,
                    LAYOUT_AddChild,
                    NewObject
                    (   LAYOUT_GetClass(),        NULL,
                        LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
                        LAYOUT_SpaceOuter,        TRUE,
                        LAYOUT_HorizAlignment,    LALIGN_RIGHT,
                        LAYOUT_BevelStyle,        BVS_NONE,
                        LAYOUT_AddChild,          iff_gadgets[GID_6_CB2] =
                        NewObject
                        (   CHECKBOX_GetClass(),  NULL,
                            GA_ID,                GID_6_CB2,
                            GA_Disabled,          TRUE,
                            GA_Text,              "Obsolete?",
                            GA_Selected,          (BOOL) iff.obsolete,
                        TAG_END),
                        CHILD_WeightedWidth,      33,
                        LAYOUT_AddChild,          iff_gadgets[GID_6_CB3] =
                        NewObject
                        (   CHECKBOX_GetClass(),  NULL,
                            GA_ID,                GID_6_CB3,
                            GA_Disabled,          TRUE,
                            GA_Text,              "Private?",
                            GA_Selected,          (BOOL) iff.private,
                        TAG_END),
                        CHILD_WeightedWidth,      33,
                        LAYOUT_AddChild,          iff_gadgets[GID_6_CB4] =
                        NewObject
                        (   CHECKBOX_GetClass(),  NULL,
                            GA_ID,                GID_6_CB4,
                            GA_Disabled,          TRUE,
                            GA_Text,              "Proposal?",
                            GA_Selected,          (BOOL) iff.proposal,
                        TAG_END),
                        CHILD_WeightedWidth,      34,
                    TAG_END),
                    LAYOUT_AddChild,
                    NewObject
                    (   LAYOUT_GetClass(),        NULL,
                        LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
                        LAYOUT_SpaceOuter,        TRUE,
                        LAYOUT_HorizAlignment,    LALIGN_RIGHT,
                        LAYOUT_BevelStyle,        BVS_NONE,
                        LAYOUT_AddChild,          iff_gadgets[GID_6_CB5] =
                        NewObject
                        (   CHECKBOX_GetClass(),  NULL,
                            GA_ID,                GID_6_CB5,
                            GA_Disabled,          TRUE,
                            GA_Text,              "Reserved?",
                            GA_Selected,          (BOOL) iff.reserved,
                        TAG_END),
                        CHILD_WeightedWidth,      33,
                        LAYOUT_AddChild,          iff_gadgets[GID_6_CB6] =
                        NewObject
                        (   CHECKBOX_GetClass(),  NULL,
                            GA_ID,                GID_6_CB6,
                            GA_Disabled,          TRUE,
                            GA_Text,              "Standard?",
                            GA_Selected,          (BOOL) iff.standard,
                        TAG_END),
                        CHILD_WeightedWidth,      33,
                        LAYOUT_AddChild,          iff_gadgets[GID_6_CB7] =
                        NewObject
                        (   CHECKBOX_GetClass(),  NULL,
                            GA_ID,                GID_6_CB7,
                            GA_Disabled,          TRUE,
                            GA_Text,              "Unregistered?",
                            GA_Selected,          (BOOL) iff.unregistered,
                        TAG_END),
                        CHILD_WeightedWidth,      34,
                    TAG_END),
                TAG_END),
            TAG_END),
            CHILD_WeightedWidth,                  80,
        TAG_END),
        CHILD_WeightedHeight,         0,
        LAYOUT_AddChild,
        NewObject
        (   LAYOUT_GetClass(),        NULL,
            LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
            LAYOUT_SpaceOuter,        TRUE,
            LAYOUT_HorizAlignment,    LALIGN_RIGHT,
            LAYOUT_BevelStyle,        BVS_FIELD,
            LAYOUT_AddChild,
            NewObject
            (   LAYOUT_GetClass(),        NULL,
                LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
                LAYOUT_SpaceOuter,        TRUE,
                LAYOUT_HorizAlignment,    LALIGN_RIGHT,
                LAYOUT_VertAlignment,     LALIGN_CENTER,
                LAYOUT_BevelStyle,        BVS_NONE,
                LAYOUT_AddChild,
                NewObject
                (   LAYOUT_GetClass(),        NULL,
                    LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
                    LAYOUT_SpaceOuter,        TRUE,
                    LAYOUT_HorizAlignment,    LALIGN_RIGHT,
                    LAYOUT_VertAlignment,     LALIGN_CENTER,
                    LAYOUT_BevelStyle,        BVS_NONE,
                    LAYOUT_AddImage,
                    NewObject
                    (   LABEL_GetClass(),     NULL,
                        LABEL_Text,           "Documents:",
                        LABEL_Justification,  LJ_RIGHT,
                    TAG_END),
                    CHILD_WeightedHeight,     0,
                TAG_END),
            TAG_END),
            CHILD_WeightedWidth,          20,
            LAYOUT_AddChild,
            NewObject
            (   LAYOUT_GetClass(),        NULL,
                LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
                LAYOUT_SpaceOuter,        TRUE,
                LAYOUT_HorizAlignment,    LALIGN_RIGHT,
                LAYOUT_BevelStyle,        BVS_NONE,
                LAYOUT_AddChild,
                NewObject
                (   LAYOUT_GetClass(),        NULL,
                    LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
                    LAYOUT_SpaceOuter,        TRUE,
                    LAYOUT_HorizAlignment,    LALIGN_RIGHT,
                    LAYOUT_BevelStyle,        BVS_NONE,
                    LAYOUT_AddChild,
                    NewObject
                    (   LAYOUT_GetClass(),        NULL,
                        LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
                        LAYOUT_SpaceOuter,        TRUE,
                        LAYOUT_HorizAlignment,    LALIGN_RIGHT,
                        LAYOUT_BevelStyle,        BVS_NONE,
                        LAYOUT_AddChild,          iff_gadgets[GID_6_CB8] =
                        NewObject
                        (   CHECKBOX_GetClass(),  NULL,
                            GA_ID,                GID_6_CB8,
                            GA_Disabled,          TRUE,
                            GA_Text,              "RKM?",
                            GA_Selected,          (BOOL) iff.rkm,
                        TAG_END),
                        CHILD_WeightedWidth,      33,
                        LAYOUT_AddChild,          iff_gadgets[GID_6_CB9] =
                        NewObject
                        (   CHECKBOX_GetClass(),  NULL,
                            GA_ID,                GID_6_CB9,
                            GA_Disabled,          TRUE,
                            GA_Text,              "ADCD 2.1?",
                            GA_Selected,          (BOOL) iff.cd,
                        TAG_END),
                        CHILD_WeightedWidth,       33,
                        LAYOUT_AddImage,           NewObject
                        (   LABEL_GetClass(),      NULL,
                            LABEL_Text,            "",
                        TAG_END),
                        CHILD_WeightedWidth,       34,
                    TAG_END),
                TAG_END),
            TAG_END),
            CHILD_WeightedWidth,           80,
        TAG_END),
        CHILD_WeightedHeight,              0,
    TAG_END),
TAG_END)))
{   rq("Can't create ReAction gadgets!");
}
unlockscreen();
openwindow();

    if (iff.pathname[0])
    {   readiff();
    } elif (queryform[0])
    {   iffquery();
    }

    ActivateLayoutGadget(iff_gadgets[GID_6_LY1], MainWindowPtr, NULL, (Object) iff_gadgets[GID_6_ST6]);

    loop();

    if (!(GetAttr
    (   STRINGA_TextVal, iff_gadgets[GID_6_ST1], (ULONG *) &stringptr
    )))
    {   rq("Unsupported inquiry!"); // should never happen
    }
    strcpy(queryform, stringptr);

    if (!(GetAttr
    (   STRINGA_TextVal, iff_gadgets[GID_6_ST6], (ULONG *) &stringptr
    )))
    {   rq("Unsupported inquiry!"); // should never happen
    }
    strcpy(iff.pathname, stringptr);

    closewindow();
    // now that the window is closed we can free lists
    iff_exit();
}

AGLOBAL void iff_loop(ULONG gid)
{   STRPTR stringptr;
    ULONG  code;

    switch(gid)
    {
    case GID_6_CB1:
        if (!(GetAttr
        (   GA_Selected, iff_gadgets[GID_6_CB1], (ULONG *) &iff.raw
        )))
        {   rq("Unsupported inquiry!"); // should never happen
        }
        if (selectedchunk && known)
        {   tellchunk(selectedchunk);
        }
    break;
    case GID_6_ST1:
        if (!(GetAttr
        (   STRINGA_TextVal, iff_gadgets[GID_6_ST1], (ULONG *) &stringptr
        )))
        {   rq("Unsupported inquiry!"); // should never happen
        }
        strcpy(queryform, stringptr);

        iff.pathname[0] = 0;
        SetGadgetAttrs
        (   iff_gadgets[GID_6_ST6],
            MainWindowPtr, NULL,
            STRINGA_TextVal, iff.pathname,
            TAG_END
        );
        SetGadgetAttrs
        (   iff_gadgets[GID_6_ST5],
            MainWindowPtr, NULL,
            STRINGA_TextVal, "Ready.",
            TAG_END
        );
        iffquery();
    break;
    case GID_6_ST6:
        if (!(GetAttr
        (   STRINGA_TextVal, iff_gadgets[GID_6_ST6], (ULONG *) &stringptr
        )))
        {   rq("Unsupported inquiry!"); // should never happen
        }
        strcpy(iff.pathname, stringptr);
        readiff();
    break;
    case GID_6_BU1:
        if (asl("~(#?.info)"))
        {   strcpy(iff.pathname, aslresult);
            SetGadgetAttrs
            (   iff_gadgets[GID_6_ST6],
                MainWindowPtr, NULL,
                STRINGA_TextVal, iff.pathname,
                TAG_END
            );
            readiff();
        }
    break;
    case GID_6_LB1:
        /* code is the position within the list, starting from 0. */

        if (!(GetAttr
        (   LISTBROWSER_Selected, iff_gadgets[GID_6_LB1], (ULONG *) &code
        )))
        {   rq("Unsupported inquiry!"); // should never happen
        }
        selectedchunk = code + 1;
        tellchunk(selectedchunk);
    break;
    default:
    break;
}   }

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;

    SetGadgetAttrs
    (   iff_gadgets[GID_6_ST1],
        MainWindowPtr, NULL,
        STRINGA_TextVal, queryform,
        TAG_END
    );

    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;

        SetGadgetAttrs
        (   iff_gadgets[GID_6_ST2],
            MainWindowPtr, NULL,
            STRINGA_TextVal, "-",
            TAG_END
        );
        SetGadgetAttrs
        (   iff_gadgets[GID_6_ST3],
            MainWindowPtr, NULL,
            STRINGA_TextVal, "-",
            TAG_END
        );
    } 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;

        SetGadgetAttrs
        (   iff_gadgets[GID_6_ST2],
            MainWindowPtr, NULL,
            STRINGA_TextVal, form[selectedform].desc,
            TAG_END
        );
        SetGadgetAttrs
        (   iff_gadgets[GID_6_ST3],
            MainWindowPtr, NULL,
            STRINGA_TextVal, form[selectedform].contributor,
            TAG_END
        );
    }

    writeiffgadgets();

    SetGadgetAttrs
    (   iff_gadgets[GID_6_LB1],
        MainWindowPtr, NULL,
        LISTBROWSER_Labels, NULL, // detach it
        TAG_END
    );
    clearreactionlist(&List1);

    SetGadgetAttrs
    (   iff_gadgets[GID_6_LB2],
        MainWindowPtr, NULL,
        LISTBROWSER_Labels, NULL, // detach it
        TAG_END
    );
    clearreactionlist(&List2);

    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;

    iffquery();

    /* Allocate IFF_File structure. */
    if (!(IFFHandle = AllocIFF()))
    {   DisplayBeep(NULL);
        SetGadgetAttrs
        (   iff_gadgets[GID_6_ST5],
            MainWindowPtr, NULL,
            STRINGA_TextVal, "AllocIFF() failed!",
            TAG_END
        );

        goto bye;
    }

    first = TRUE;

    /* Set up IFF_File for AmigaDOS I/O.  */
    if (!(IFFHandle->iff_Stream = Open(iff.pathname, MODE_OLDFILE)))
    {   DisplayBeep(NULL);
        SetGadgetAttrs
        (   iff_gadgets[GID_6_ST5],
            MainWindowPtr, NULL,
            STRINGA_TextVal, "Can't open file!",
            TAG_END
        );
        SetGadgetAttrs
        (   iff_gadgets[GID_6_ST2],
            MainWindowPtr, NULL,
            STRINGA_TextVal, "-",
            TAG_END
        );
        SetGadgetAttrs
        (   iff_gadgets[GID_6_ST3],
            MainWindowPtr, NULL,
            STRINGA_TextVal, "-",
            TAG_END
        );

        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);
        SetGadgetAttrs
        (   iff_gadgets[GID_6_ST5],
            MainWindowPtr, NULL,
            STRINGA_TextVal, "OpenIFF() failed!",
            TAG_END
        );
        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)
    {   SetGadgetAttrs
        (   iff_gadgets[GID_6_ST5],
            MainWindowPtr, NULL,
            STRINGA_TextVal, "Ready.",
            TAG_END
        );
        SetGadgetAttrs
        (   iff_gadgets[GID_6_LB1],
            MainWindowPtr, NULL,
            LISTBROWSER_Labels, &List1,
            TAG_END
        );
    } else
    {   SetGadgetAttrs
        (   iff_gadgets[GID_6_ST5],
            MainWindowPtr, NULL,
            STRINGA_TextVal, errormsgs[-error - 1],
            TAG_END
        );
        SetGadgetAttrs
        (   iff_gadgets[GID_6_LB1],
            MainWindowPtr, NULL,
            LISTBROWSER_Labels, NULL, // detach it
            TAG_END
        );
    }

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;
    }

    clearreactionlist(&List2);
    clearreactionlist(&List1);

    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. */
    addreactionnode(&List1, tempstring1);

    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;
    }

    SetGadgetAttrs
    (   iff_gadgets[GID_6_LB2],
        MainWindowPtr, NULL,
        LISTBROWSER_Labels, NULL, // detach it
        TAG_END
    );
    clearreactionlist(&List2);
    known = FALSE;

    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);
            addreactionnode(&List2, tempstring1);
    }   }
    elif (!stricmp(contents[which].name, "AUTH"))
    {   chunkdesc("Author", TRUE);

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

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

        if (!iff.raw)
        {   strcpy(tempstring1, "Name:               ");
            strcat(tempstring1, contents[which].DataPtr);
            addreactionnode(&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]);
            addreactionnode(&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);
        addreactionnode(&List2, tempstring1);

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

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

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

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

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

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

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

            strcat(tempstring1, " Tagged?             ");
            if (contents[which].DataPtr[3] & 128)
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            addreactionnode(&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, "?");
            }
            addreactionnode(&List2, tempstring1);

            strcpy(tempstring1, "Colour:              ");
            uvalue = contents[which].DataPtr[5]; // UBYTE
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            addreactionnode(&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)");
            }
            addreactionnode(&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!
            addreactionnode(&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!
            addreactionnode(&List2, tempstring1);

            strcpy(tempstring1, "Font name:          ");
            strcat(tempstring1, &(contents[which].DataPtr[4]));
            addreactionnode(&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);
            addreactionnode(&List2, tempstring1);

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

            addreactionnode(&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");
            addreactionnode(&List2, tempstring1);

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

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

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

            strcpy(tempstring1, " Mode promotion?        ");
            if (uvalue & 16) // ICF_MODEPROMOTE
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            addreactionnode(&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");
            addreactionnode(&List2, tempstring1);

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

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

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

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

            strcat(tempstring1, " Requester FALSE:       ");
            stcl_d(tempstring2, contents[which].DataPtr[27]);
            strcat(tempstring1, tempstring2);
            addreactionnode(&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);
            addreactionnode(&List2, tempstring1);

            strcpy(tempstring1, "Baud rate:              ");
            uvalue = getulong(&(contents[which].DataPtr[16]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " bps");
            addreactionnode(&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, "!");
            }
            addreactionnode(&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, "!");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&List2, tempstring1);

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

            strcpy(tempstring1, "Stop bits:              ");
            stcl_d(tempstring2, contents[which].DataPtr[32]);
            strcat(tempstring1, tempstring2);
            addreactionnode(&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, "?");
                }
                addreactionnode(&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, "?");
                }
                addreactionnode(&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, "?");
                }
                addreactionnode(&List2, tempstring1);

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

                strcpy(tempstring1, "Relative?               ");
                if (contents[which].DataPtr[19] & 16)
                {   strcat(tempstring1, "Yes");
                } else
                {   strcat(tempstring1, "No");
                }
                addreactionnode(&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, "?");
                }
                addreactionnode(&List2, tempstring1);

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

                strcpy(tempstring1, "Top edge:               ");
                svalue = getsword(&(contents[which].DataPtr[22]));
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                addreactionnode(&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, "%");
                addreactionnode(&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, "%");
                addreactionnode(&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, "?");
            }
            addreactionnode(&List2, tempstring1);

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

            strcpy(tempstring1, "Back pen:               ");
            stcl_d(tempstring2, contents[which].DataPtr[17]);
            strcat(tempstring1, tempstring2);
            addreactionnode(&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, "?");
            }
            addreactionnode(&List2, tempstring1);

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

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

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

            strcpy(tempstring1, "Name:                   ");
            strcat(tempstring1, &(contents[which].DataPtr[28]));
            addreactionnode(&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");
            addreactionnode(&List2, tempstring1);

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

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

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

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

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

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

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

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

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

            strcpy(tempstring1, "Mouse acceleration:     ");
            svalue = getsword(&(contents[which].DataPtr[42]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            addreactionnode(&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");
            }
            addreactionnode(&List2, tempstring1);

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

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

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

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

            strcpy(tempstring1, "DisplayID:              ");
            uvalue = getulong(&(contents[which].DataPtr[16]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            addreactionnode(&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);
            addreactionnode(&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);
            addreactionnode(&List2, tempstring1);

            addreactionnode(&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);
            addreactionnode(&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);
            addreactionnode(&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);
            addreactionnode(&List2, tempstring1);

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

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

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

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

        if (!iff.raw)
        {   addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&List2, tempstring1);

            // now two reserved bytes

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

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

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

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

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

            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&List2, tempstring1);

            // now eight reserved bytes

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

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

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

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

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

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

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

            // now eight reserved bytes

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

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

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

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

            strcpy(tempstring1, " Height:                ");
            svalue = getslong(&(contents[which].DataPtr[92]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " millipoints");
            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&List2, tempstring1);

            // now nine reserved bytes

            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&List2, tempstring1);

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

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

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

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

            strcpy(tempstring1, " Blue?                  ");
            if (contents[which].DataPtr[24] & 4) // PCCF_BLUE
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&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");
            }
            addreactionnode(&List2, tempstring1);

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

            strcpy(tempstring1, " Antialiasing?          ");
            if (uvalue & 4) // PGFF_ANTI_ALIAS
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            addreactionnode(&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, "!");
            }
            addreactionnode(&List2, tempstring1);

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

            strcpy(tempstring1, "Maximum height:         ");
            uvalue = getuword(&(contents[which].DataPtr[32]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            addreactionnode(&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);
            addreactionnode(&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
            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&List2, tempstring1);

            strcpy(tempstring1, "Paper length:           ");
            uvalue = getuword(&(contents[which].DataPtr[53]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " lines");
            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&List2, tempstring1);

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

            strcpy(tempstring1, "Right margin:           ");
            uvalue = getuword(&(contents[which].DataPtr[61]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            addreactionnode(&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, "?");
            }
            addreactionnode(&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");
            }
            addreactionnode(&List2, tempstring1);

            strcpy(tempstring1, "Make sounds?            ");
            uvalue = getuword(&contents[which].DataPtr[18]); // BOOL
            if (uvalue)
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            addreactionnode(&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");
            }
            addreactionnode(&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");
            addreactionnode(&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, "!");
            }
            addreactionnode(&List2, tempstring1);

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

            strcpy(tempstring1, "Sample filename:        ");
            strcat(tempstring1, &contents[which].DataPtr[28]); // 256 chars
            addreactionnode(&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, "?");
            }
            addreactionnode(&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");
            }
            addreactionnode(&List2, tempstring1);

            strcpy(tempstring1, "Remap pattern?          ");
            if (uvalue & 16) // WBPF_NOREMAP
            {   strcat(tempstring1, "No");
            } else
            {   strcat(tempstring1, "Yes");
            }
            addreactionnode(&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");
            }
            addreactionnode(&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");
            }
            addreactionnode(&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");
            }
            addreactionnode(&List2, tempstring1);

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

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

            strcpy(tempstring1, "Data length:            ");  // UWORD
            uvalue = getuword(&contents[which].DataPtr[22]);
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&List2, tempstring1);

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

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

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

            strcpy(tempstring1, "Depth:                  ");
            uvalue = getuword(&contents[which].DataPtr[24]); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " planes");
            addreactionnode(&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, "?");
            }
            addreactionnode(&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);
            addreactionnode(&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, " (?)");
                }
                addreactionnode(&List2, tempstring1);

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

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

                strcpy(tempstring1, "Fast echo?              ");
                uvalue = getuword(&contents[which].DataPtr[6]); // BOOL
                if (uvalue)
                {   strcat(tempstring1, "Yes");
                } else
                {   strcat(tempstring1, "No");
                }
                addreactionnode(&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");
                addreactionnode(&List2, tempstring1);

                strcpy(tempstring1, "Clip master volume?     ");
                uvalue = getuword(&contents[which].DataPtr[12]); // BOOL
                if (uvalue)
                {   strcat(tempstring1, "Yes");
                } else
                {   strcat(tempstring1, "No");
                }
                addreactionnode(&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);
                addreactionnode(&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);
                addreactionnode(&List2, tempstring1);

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

                strcpy(tempstring1, "Frequency:              ");
                uvalue = getuword(&contents[which].DataPtr[8]); // ULONG
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                addreactionnode(&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");
                addreactionnode(&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");
                addreactionnode(&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");
                addreactionnode(&List2, tempstring1);

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

                strcpy(tempstring1, "Output:                 ");
                uvalue = getuword(&contents[which].DataPtr[28]); // ULONG
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                addreactionnode(&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");
            addreactionnode(&List2, tempstring1);

            strcpy(tempstring1, "Type restart time:      ");
            uvalue = getulong(&contents[which].DataPtr[4]); // ULONG
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " seconds");
            addreactionnode(&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, "?");
            }
            addreactionnode(&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);
            addreactionnode(&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);
            addreactionnode(&List2, tempstring1);

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

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

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

            strcpy(tempstring1, "ColourIcons support?    ");
            uvalue = getuword(&contents[which].DataPtr[28]); // BOOL
            if (uvalue)
            {   strcat(tempstring1, "Yes");
            } else
            {   strcat(tempstring1, "No");
            }
            addreactionnode(&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, "?");
                }
                addreactionnode(&List2, tempstring1);

                strcpy(tempstring1, "Lock pens?              ");
                uvalue = getuword(&contents[which].DataPtr[34]); // BOOL
                if (uvalue)
                {   strcat(tempstring1, "Yes");
                } else
                {   strcat(tempstring1, "No");
                }
                addreactionnode(&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");
                }
                addreactionnode(&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");
                }
                addreactionnode(&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);
                addreactionnode(&List2, tempstring1);
        }   }
        elif (!strcmp(contents[which].name, "LCLE"))
        {   chunkdesc("Locale preferences", TRUE);

            // 16 reserved bytes at start

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

            strcpy(tempstring1, "Preferred languages:    ");
            addreactionnode(&List2, tempstring1);

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

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

            strcpy(tempstring1, "Flags:                  ");
            uvalue = getulong(&contents[which].DataPtr[352]); // ULONG
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&List2, tempstring1);

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

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

            strcpy(tempstring1, "Label pen:              "); // UWORD
            uvalue = getuword(&contents[which].DataPtr[8]);
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            addreactionnode(&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)");
            }
            addreactionnode(&List2, tempstring1);

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

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

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

            addreactionnode(&List2, "Fallback font:");
            dotextattr(&contents[which].DataPtr[18]); // struct TextAttr (8 bytes)
            addreactionnode(&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
            addreactionnode(&List2, tempstring1);

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

            strcpy(tempstring1, "Backdrop pattern:       ");
            strcat(tempstring1, &contents[which].DataPtr[290]); // 256 UBYTEs
            addreactionnode(&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);
            addreactionnode(&List2, tempstring1);
                               
            strcpy(tempstring1, "Type:                   ");
            stcl_d(tempstring2, contents[which].DataPtr[1]);
            strcat(tempstring1, tempstring2);
            addreactionnode(&List2, tempstring1);

            strcpy(tempstring1, "Flags:                  ");
            uvalue = getuword(&(contents[which].DataPtr[2]));
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            addreactionnode(&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");
            addreactionnode(&List2, tempstring1);

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

            strcpy(tempstring1, "Tracks:             ");
            uvalue = contents[which].DataPtr[3];
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            addreactionnode(&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);
            addreactionnode(&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, "?");
            addreactionnode(&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");
            addreactionnode(&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");
            addreactionnode(&List2, tempstring1);

            strcpy(tempstring1, "Instrument name:    ");
            strcat(tempstring1, (STRPTR) contents[which].DataPtr + 4); // STRPTR
            addreactionnode(&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);
                addreactionnode(&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);
            addreactionnode(&List2, tempstring1);

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

            strcpy(tempstring1, "Name:               ");
            strcat(tempstring1, &contents[which].DataPtr[3]);
            addreactionnode(&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);
                    addreactionnode(&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);
                addreactionnode(&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, "?");
                }
                addreactionnode(&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, "?");
                addreactionnode(&List2, tempstring1);

                strcpy(tempstring1, "First page?          ");
                if (contents[which].DataPtr[1] == 0)
                {   strcat(tempstring1, "No");
                } else strcat(tempstring1, "Yes");
                addreactionnode(&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, "?");
                addreactionnode(&List2, tempstring1);

                strcpy(tempstring1, "First page?          ");
                if (contents[which].DataPtr[1] == 0)
                {   strcat(tempstring1, "No");
                } else strcat(tempstring1, "Yes");
                addreactionnode(&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);
                addreactionnode(&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");
            addreactionnode(&List2, tempstring1);

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

            strcpy(tempstring1, "Right margin:        ");
            uvalue = getuword(&(contents[which].DataPtr[4])); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " decipoints");
            addreactionnode(&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, "?");
            }
            addreactionnode(&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, "?");
            }
            addreactionnode(&List2, tempstring1);

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

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

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

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

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

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

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

            strcat(tempstring1, " Tagged?             ");
            if (contents[which].DataPtr[9] & 128)
            {   strcat(tempstring1, "Yes");
            } else strcat(tempstring1, "No");
            addreactionnode(&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, "?");
            }
            addreactionnode(&List2, tempstring1);

            strcpy(tempstring1, "Colour:              ");
            uvalue = contents[which].DataPtr[11]; // UBYTE
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            addreactionnode(&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");
            addreactionnode(&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, "?");
            }
            addreactionnode(&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);
            addreactionnode(&List2, tempstring1);

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

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

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

            strcpy(tempstring1, "Y-position:          ");
            uvalue = getuword(&(contents[which].DataPtr[8])); // UWORD
            stcl_d(tempstring2, uvalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " decipoints");
            addreactionnode(&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, "?");
            addreactionnode(&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, "?");
            addreactionnode(&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);
            }
            addreactionnode(&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, "!");
            }
            addreactionnode(&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, ":");
                    addreactionnode(&List2, tempstring1);

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

                    strcpy(tempstring1, " Position:           ");
                    uvalue = getulong(&(contents[which].name[currentpos]));
                    stcl_d(tempstring2, uvalue);
                    strcat(tempstring1, tempstring2);
                    addreactionnode(&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);
                    }
                    addreactionnode(&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, "!");
            }
            addreactionnode(&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, ":");
                    addreactionnode(&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);
                    addreactionnode(&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, "!");
                    }
                    addreactionnode(&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);
                    }
                    addreactionnode(&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)");
            }
            addreactionnode(&List2, tempstring1);

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

            strcpy(tempstring1, "Sample quality:      ");
            svalue = getsword(&(contents[which].DataPtr[6]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, "-bit");
            addreactionnode(&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:       -");
            addreactionnode(&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)");
                }
                addreactionnode(&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);
                addreactionnode(&List2, tempstring1);

                strcpy(tempstring1, "Block size:          ");
                uvalue = getulong(&(contents[which].DataPtr[4]));
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                addreactionnode(&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, "!");
            addreactionnode(&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, "!");
            addreactionnode(&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, "!");
            addreactionnode(&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, "!");
            addreactionnode(&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, "!");
            addreactionnode(&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, "!");
            addreactionnode(&List2, tempstring1);

            strcpy(tempstring1, "Gain:                ");
            svalue = getsword(&(contents[which].DataPtr[6]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            addreactionnode(&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, " ?");
            }
            addreactionnode(&List2, tempstring1);
            strcpy(tempstring1, " Begin loop:         ");
            svalue = getsword(&(contents[which].DataPtr[10]));
            stcl_d(tempstring1, svalue);
            addreactionnode(&List2, tempstring1);
            strcpy(tempstring1, " End loop:           ");
            svalue = getsword(&(contents[which].DataPtr[12]));
            stcl_d(tempstring1, svalue);
            addreactionnode(&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, " ?");
            }
            addreactionnode(&List2, tempstring1);
            strcpy(tempstring1, " Begin loop:         ");
            svalue = getsword(&(contents[which].DataPtr[16]));
            stcl_d(tempstring1, svalue);
            addreactionnode(&List2, tempstring1);
            strcpy(tempstring1, " End loop:           ");
            svalue = getsword(&(contents[which].DataPtr[18]));
            stcl_d(tempstring1, svalue);
            addreactionnode(&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);
                addreactionnode(&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, "!");
                }
                addreactionnode(&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, "!");
                }
                addreactionnode(&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, "?");
                addreactionnode(&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)");
                }
                addreactionnode(&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);
                addreactionnode(&List2, tempstring1);

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

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

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

                strcpy(tempstring1, "Octaves:             ");
                uvalue = contents[which].DataPtr[14]; // UBYTE
                stcl_d(tempstring2, uvalue);
                strcat(tempstring1, tempstring2);
                addreactionnode(&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, "?");
                addreactionnode(&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");
                addreactionnode(&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]);
                addreactionnode(&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, "?");
            }
            addreactionnode(&List2, tempstring1);

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

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

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

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

            strcpy(tempstring1, "Height:                 ");
            svalue = getsword(&contents[which].DataPtr[8]); // WORD
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            strcat(tempstring1, " pixels");
            addreactionnode(&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");
            addreactionnode(&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");
            addreactionnode(&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");
            }
            addreactionnode(&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");
            }
            addreactionnode(&List2, tempstring1);

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

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

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

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

            strcpy(tempstring1, " Info offsets:          ");
            if (uvalue & 32)
            {   strcat(tempstring1, "Short");
            } else
            {   strcat(tempstring1, "Long");
            }
            addreactionnode(&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);
                addreactionnode(&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);
            addreactionnode(&List2, tempstring1);

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

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

            strcpy(tempstring1, "Bottom Y:           ");
            svalue = getsword(&(contents[which].DataPtr[6]));
            stcl_d(tempstring2, svalue);
            strcat(tempstring1, tempstring2);
            addreactionnode(&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);
            addreactionnode(&List2, tempstring1);

            // next (1) is a pad byte.

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

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

            strcpy(tempstring1, "PlaneMask:          %"); // UWORD
            binarize(contents[which].DataPtr[6]);
            binarize(contents[which].DataPtr[7]);
            addreactionnode(&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);
                addreactionnode(&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);
                addreactionnode(&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);
            addreactionnode(&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);
            addreactionnode(&List2, tempstring1);

            strcpy(tempstring1, "Bitplanes:          ");
            stcl_d(tempstring2, (LONG) contents[which].DataPtr[8]);
            strcat(tempstring1, tempstring2);
            addreactionnode(&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, "?");
            addreactionnode(&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, "?");
            addreactionnode(&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);
            }
            addreactionnode(&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);
            addreactionnode(&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);
            addreactionnode(&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, "#");
            }   }
            addreactionnode(&List2, tempstring1);
    }   }
    if (!known)
    {   chunkdesc("?", FALSE);
    }

    SetGadgetAttrs
    (   iff_gadgets[GID_6_LB2],
        MainWindowPtr, NULL,
        LISTBROWSER_Labels, &List2,
        TAG_END
    );
}

MODULE void chunkdesc(STRPTR desc, ABOOL isknown)
{   SetGadgetAttrs
    (   iff_gadgets[GID_6_ST4],
        MainWindowPtr, NULL,
        STRINGA_TextVal, desc,
        TAG_END
    );
    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

    SetGadgetAttrs
    (   iff_gadgets[GID_6_CB2], MainWindowPtr, NULL,
        GA_Selected, iff.obsolete,
    TAG_END);
    RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB2], MainWindowPtr, NULL);
    SetGadgetAttrs
    (   iff_gadgets[GID_6_CB3], MainWindowPtr, NULL,
        GA_Selected, iff.private,
    TAG_END);
    RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB3], MainWindowPtr, NULL);
    SetGadgetAttrs
    (   iff_gadgets[GID_6_CB4], MainWindowPtr, NULL,
        GA_Selected, iff.proposal,
    TAG_END);
    RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB4], MainWindowPtr, NULL);
    SetGadgetAttrs
    (   iff_gadgets[GID_6_CB5], MainWindowPtr, NULL,
        GA_Selected, iff.reserved,
    TAG_END);
    RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB5], MainWindowPtr, NULL);
    SetGadgetAttrs
    (   iff_gadgets[GID_6_CB6], MainWindowPtr, NULL,
        GA_Selected, iff.standard,
    TAG_END);
    RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB6], MainWindowPtr, NULL);
    SetGadgetAttrs
    (   iff_gadgets[GID_6_CB7], MainWindowPtr, NULL,
        GA_Selected, iff.unregistered,
    TAG_END);
    RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB7], MainWindowPtr, NULL);
    SetGadgetAttrs
    (   iff_gadgets[GID_6_CB8], MainWindowPtr, NULL,
        GA_Selected, iff.rkm,
    TAG_END);
    RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB8], MainWindowPtr, NULL);
    SetGadgetAttrs
    (   iff_gadgets[GID_6_CB9], MainWindowPtr, NULL,
        GA_Selected, iff.cd,
    TAG_END);
    RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB9], MainWindowPtr, NULL);
    SetGadgetAttrs
    (   iff_gadgets[GID_6_ST1],
        MainWindowPtr, NULL,
        STRINGA_TextVal, queryform,
        TAG_END
    );
    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);
            addreactionnode(&List2, tempstring1);

            addreactionnode(&List2, " Style:");

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

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

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

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

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

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

            addreactionnode(&List2, " Flags:");

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

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

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

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

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

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

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

    strcpy(tempstring1, "  Removed?              ");
    if (*(offset + 7) & 128) // FPF_REMOVED
    {   strcat(tempstring1, "Yes!");
    } else
    {   strcat(tempstring1, "No");
    }
    addreactionnode(&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);
    addreactionnode(&List2, tempstring1);

    strcpy(tempstring1, "Telephone code:         ");
    uvalue = getulong(offset + 20); // ULONG
    stcl_d(tempstring2, uvalue);
    strcat(tempstring1, tempstring2);
    addreactionnode(&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, "?");
    }
    addreactionnode(&List2, tempstring1);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    strcpy(tempstring1, "  Intranational:        ");
    stcl_d(tempstring2, (ULONG) ((UBYTE) *(offset + 445)));
    strcat(tempstring1, tempstring2);
    addreactionnode(&List2, tempstring1);
    strcpy(tempstring1, "  International:        ");
    stcl_d(tempstring2, (ULONG) ((UBYTE) *(offset + 446)));
    strcat(tempstring1, tempstring2);
    addreactionnode(&List2, tempstring1);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    NewList(&List1);
    NewList(&List2);
}

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

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

AGLOBAL ULONG Hook6Func(struct Hook *h, VOID *o, VOID *msg)
{   /* "When the hook is called, the data argument points to the 
    window object and message argument to the IntuiMessage." */

    UWORD code, qual;
    ULONG scroll = 0;

    geta4(); // wait till here before doing anything

    code = ((struct IntuiMessage *) msg)->Code;
    qual = ((struct IntuiMessage *) msg)->Qualifier;

    switch(code)
    {
    case SCAN_HELP:
        helpabout();
    break;
    case SCAN_ESCAPE:
        if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
        {   cleanexit(EXIT_SUCCESS);
        } else page = 0;
    break;
    case SCAN_UP:
        if (qual & IEQUALIFIER_CONTROL)
        {   scroll = LBP_TOP;
        } elif (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
        {   scroll = LBP_PAGEUP;
        } else scroll = LBP_LINEUP;
    break;
    case SCAN_DOWN:
        if (qual & IEQUALIFIER_CONTROL)
        {   scroll = LBP_BOTTOM;
        } elif (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
        {   scroll = LBP_PAGEDOWN;
        } else scroll = LBP_LINEDOWN;
    break;
    case SCAN_PERIOD:
        if (asl("~(#?.info)"))
        {   strcpy(iff.pathname, aslresult);

            SetGadgetAttrs
            (   iff_gadgets[GID_6_ST6], MainWindowPtr, NULL,
                STRINGA_TextVal, iff.pathname,
                TAG_END
            ); // we don't know how many files in advance...

            readiff();
        }
    break;
    case SCAN_F:
        ActivateLayoutGadget(iff_gadgets[GID_6_LY1], MainWindowPtr, NULL, (Object) iff_gadgets[GID_6_ST1]);
    break;
    case SCAN_P:
        ActivateLayoutGadget(iff_gadgets[GID_6_LY1], MainWindowPtr, NULL, (Object) iff_gadgets[GID_6_ST6]);
    break;
    case SCAN_R:
        // the gadget is handled automatically by the system, all we need
        // to do is update our internal record of the state of the gadget
        if (!(GetAttr
        (   GA_Selected, iff_gadgets[GID_6_CB1], (ULONG *) &iff.raw
        )))
        {   rq("Unsupported inquiry!"); // should never happen
        }
        if (selectedchunk && known)
        {   tellchunk(selectedchunk);
        }
    break;
    default:
    break;
    }

    if (code == SCAN_UP || code == SCAN_DOWN)
    {   SetGadgetAttrs
        (   iff_gadgets[GID_6_LB2],       // pointer to gadget
            MainWindowPtr,                // pointer to window (not window object!)
            NULL,                         // pointer to requester
            LISTBROWSER_Position, scroll, // tags
            TAG_DONE                      // done
        );
    }

    return(1);
}
