/* $Filename:    ReportPlus/Source/rp.c
 * $VER:         Report+ 4.51
 * $Description: Multi-function utility
 *
 * © Copyright 2001 James R. Jacobs. Freely distributable.
 *        _
 *       //      -=AMIGA=-
 *      //
 * _   //
 * \\ //
 *  \X/

#INCLUDES -------------------------------------------------------------- */

// #include <assert.h>

#include <exec/types.h>
#include <exec/alerts.h>
#include <exec/nodes.h>
#include <exec/memory.h>
#include <pragmas/exec_pragmas.h>
#include <clib/exec_protos.h>
#include <exec/execbase.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <graphics/displayinfo.h>
#include <libraries/gadtools.h>
#include <workbench/workbench.h> /* struct DiskObject */
#include <libraries/asl.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <dos/dosextens.h>
#include <gadgets/listbrowser.h>
#include <pragmas/listbrowser_pragmas.h>
#include <graphics/gels.h>
#include <graphics/gfxmacros.h>
#include <utility/tagitem.h>

// boing ball
#define ID_BORDER 0
#define ID_BNG    3
#define ANFS      ANFRACSIZE
#define BNFS      (ANFRACSIZE-2)
#define CNFS      (ANFRACSIZE-2)
#define RBMDEPTH  4

#include "animtools.h"
#include "animtools_proto.h"
#include "anim_images.h"

#include <stdio.h>          /* FILE, printf() */
#include <stdlib.h>         /* EXIT_SUCCESS, EXIT_FAILURE */

#include "amigan.h"

#define FUNCTIONS 12

#define PALMENUHEIGHT (126 + (FUNCTIONS * 8)) // page 0
#define PUBMENUHEIGHT (PALMENUHEIGHT + 28)

/*--------------------------------------------------------------*/
/* Structures for the boing ball and satellites.                */
/*--------------------------------------------------------------*/

NEWBOB newBoingBob =
{   NULL,               // initial image
    BNG3WWIDTH,         // WORD width
    BNG3HEIGHT,         // line height
    BNG3DEPTH,          // image depth
    0x3,                // plane pick
    0x0,                // plane on/off
    SAVEBACK | OVERLAY, // VSprite flags
    0,                  // dbuf (0=false)
    RBMDEPTH,           // raster depth
    32, 100,            // x, y position
    (1L<<ID_BORDER),    // hit mask
    (1L<<ID_BNG)        // me mask
};
NEWANIMSEQ newBoingSeq =
{   NULL, (WORD *)boing3Image, boing3XTranses, boing3YTranses,
    boing3Times, boing3CRoutines, 0, BNG3COUNT, 0,
};

NEWBOB newSatABob =
	{
	NULL, SATWWIDTH, SATHEIGHT, SATDEPTH,
        1,
        11,
	SAVEBACK | OVERLAY, 0, RBMDEPTH, 0,0, (1L<<ID_BORDER), (1L<<ID_BNG),
	};
NEWANIMSEQ newSatASeq =
	{
	NULL, (WORD *)satImage, satAXTranses, satAYTranses,
	satTimes, satACRoutines, 0, SATCOUNT, 1,
	};

NEWBOB newSatBBob =
	{
	NULL, SATWWIDTH, SATHEIGHT, SATDEPTH,
        12,
        0,
	SAVEBACK | OVERLAY, 0, RBMDEPTH, 0,0, (1L<<ID_BORDER), (1L<<ID_BNG),
	};
NEWANIMSEQ newSatBSeq =
	{
	NULL, (WORD *)satImage, satBXTranses, satBYTranses,
	satTimes, satBCRoutines, 0, SATCOUNT, 1,
	};
NEWBOB newSatCBob =
	{
	NULL, SATWWIDTH, SATHEIGHT, SATDEPTH,
        1,
        9,
	SAVEBACK | OVERLAY, 0, RBMDEPTH, 0,0, (1L<<ID_BORDER), (1L<<ID_BNG),
	};
NEWANIMSEQ newSatCSeq =
	{
	NULL, (WORD *)satImage, satCXTranses, satCYTranses,
	satTimes, satCCRoutines, 0, SATCOUNT, 1,
	};

// help|about...
MODULE struct AnimOb*   setupBoing(void);
MODULE struct GelsInfo* setupDisplay(void);
       WORD             bounceORoutine(struct AnimOb *anOb);
                        // this is an oroutine so parameters are fixed
MODULE WORD             goInFrontOfHead(struct AnimComp *aComp);
MODULE WORD             goBehindHead(struct AnimComp *aComp);

MODULE struct Window*   AboutWindowPtr = NULL;
MODULE struct GelsInfo  *gInfo;
MODULE struct AnimOb    *boingOb;
MODULE struct AnimOb    *animKey;

MODULE UWORD chip PalLogoData[754] =
{   /* Plane 0 */
    0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x8000,0x000F,
    0x1FFF,0xFC00,0x1FFF,0xFFFF,0xFFF0,0x0000,0x7FF0,0x007F,0xFFC0,0x007F,0xFFFF,0x8000,0x000F,
    0x1FFF,0xFFE0,0x1FFF,0xFFFF,0xFFFF,0xE007,0xFFFF,0xC07F,0xFFFF,0x807F,0xFFFF,0x8001,0xF00F,
    0x1FFF,0xFFF8,0x1FFF,0xFFDF,0xFFFF,0xF81F,0xFFFF,0xE07F,0xFFFF,0xE07F,0xFFFF,0x800F,0xF00F,
    0x1FE0,0x0FFC,0x1F80,0x001F,0xE07F,0xFC3F,0xC00F,0xF07F,0x81FF,0xF000,0x7FC0,0x000F,0xF00F,
    0x1FE0,0x03FC,0x1F80,0x001F,0xE003,0xFC7F,0x8007,0xF87F,0x800F,0xF000,0x7FC0,0x000F,0xF0FF,
    0x1FE0,0x03FC,0x1F00,0x401F,0xE003,0xFC7F,0x8007,0xF87F,0x800F,0xF000,0x7FC0,0x000F,0xE7FF,
    0x1FE0,0x07F8,0x1FFF,0x801F,0xE00F,0xF87F,0x8007,0xF87F,0x803F,0xE000,0x7FC0,0x000F,0xFFFF,
    0x1FE0,0x1FE0,0x1FFE,0x001F,0xE07F,0xE07F,0x8007,0xF87F,0x81FF,0x8000,0x7FC0,0x01FF,0xFF0F,
    0x1FFF,0xFF80,0x1FF8,0x001F,0xFFFF,0x807F,0x8007,0xF87F,0xFFFE,0x0000,0x7FC0,0x0FFF,0xF80F,
    0x1FFF,0xFE00,0x1F80,0x001F,0xFFFE,0x007F,0x8007,0xF07F,0xFFF8,0x0000,0x7FC0,0x0FEF,0xF00F,
    0x1FFF,0xFE00,0x1F80,0x001F,0xFFE0,0x003F,0xC00F,0xF07F,0xFFF8,0x0000,0x7FC0,0x1E0F,0xF00F,
    0x1FE0,0xFF00,0x1F80,0x001F,0xE000,0x001F,0xF03F,0xE07F,0x83FC,0x0000,0x7FC0,0x000F,0xF00F,
    0x1FE0,0x7F80,0x1FFF,0xFE1F,0xE000,0x0007,0xFFFF,0x807F,0x81FE,0x0000,0x7F80,0x000F,0xF00F,
    0x1FE0,0x3FC0,0x1FFF,0xF81F,0xE000,0x0007,0xFFFE,0x007F,0x80FF,0x0000,0x7E00,0x000F,0x000F,
    0x1FE0,0x1FE0,0x1FFF,0xE01F,0xE000,0x0000,0x7FE0,0x007F,0x807F,0x8000,0x7800,0x0000,0x000F,
    0x1FE0,0x0FF0,0x0000,0x001F,0xE000,0x0000,0x0000,0x007F,0x803F,0xC000,0x6000,0x0000,0x000F,
    0x1FE0,0x07F8,0x0000,0x001F,0xE000,0x0000,0x0000,0x007F,0x801F,0xE000,0x0000,0x0000,0x000F,
    0x7FE0,0x03FC,0x0000,0x007F,0xE000,0x0000,0x0000,0x01FF,0x800F,0xF000,0x0000,0x0000,0x000F,
    0x7FE0,0x01FE,0x0000,0x00FF,0xE000,0x0000,0x0000,0x01FF,0x8007,0xF800,0x0000,0x0000,0x000F,
    0x0000,0x00FF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0003,0xFC00,0x0000,0x0000,0x000F,
    0x0000,0x007F,0x8000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0001,0xFE00,0x0000,0x0000,0x000F,
    0x0000,0x003F,0xC000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFF00,0x0000,0x0000,0x000F,
    0x0000,0x001F,0xE000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7F80,0x0000,0x0000,0x000F,
    0x0000,0x000F,0xF0F0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3FC3,0xC000,0x0000,0x000F,
    0x0000,0x0007,0xFFF0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1FFF,0xC000,0x0000,0x000F,
    0x0000,0x0003,0xFFE0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0FFF,0x8000,0x0000,0x000F,
    0x0000,0x0000,0xFF80,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03FE,0x0000,0x0000,0x000F,
    0x0000,0x0000,0xFF00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03FC,0x0000,0x0000,0x000F,
    /* Plane 1 */
    0x3FFF,0xFC00,0x3FFF,0xFFFF,0xFFF0,0x0000,0x7FF0,0x00FF,0xFFC0,0x00FF,0xFFFF,0x0000,0x0000,
    0x3FFF,0xFF80,0x3FFF,0xFFFF,0xFFFE,0x0007,0xFFFF,0x00FF,0xFFFE,0x00FF,0xFFFF,0x0001,0xF000,
    0x3FFF,0xFFC0,0x3FFF,0xFFFF,0xFFFF,0xC01F,0xFFFF,0x00FF,0xFFFE,0x00FF,0xFFFF,0x001F,0xE000,
    0x3FC0,0x0FF0,0x3F00,0x003F,0xC07F,0xE03F,0xE07F,0xC0FF,0x01FF,0x8080,0x7F80,0x001F,0xE000,
    0x3FC0,0x07F8,0x3F00,0x003F,0xC007,0xF87F,0x801F,0xE0FF,0x001F,0xE000,0xFF80,0x001F,0xE0F0,
    0x3FC0,0x07F8,0x3F00,0x003F,0xC007,0xF8FF,0x000F,0xF0FF,0x001F,0xE000,0xFF80,0x001F,0xE7E0,
    0x3FC0,0x07F8,0x3FFF,0x803F,0xC00F,0xF8FF,0x000F,0xF0FF,0x001F,0xE000,0xFF80,0x001F,0xFFE0,
    0x3FC0,0x1FE0,0x3FFE,0x003F,0xC07F,0xE0FF,0x000F,0xF0FF,0x007F,0x8000,0xFF80,0x03FF,0xFF00,
    0x3FDF,0xFF80,0x3FF8,0x003F,0xDFFF,0x80FF,0x000F,0xF0FF,0x7FFE,0x0000,0xFF80,0x1FFF,0xF800,
    0x3FFF,0xFE00,0x3F00,0x003F,0xFFFE,0x00FF,0x000F,0xF0FF,0xFFF0,0x0000,0xFF80,0x1FFF,0xE000,
    0x3FFF,0xFC00,0x3F00,0x003F,0xFFE0,0x00FF,0x000F,0xE0FF,0xFFF0,0x0000,0xFF80,0x1E1F,0xE000,
    0x3FC1,0xFC00,0x3F00,0x003F,0xC000,0x007F,0x801F,0xE0FF,0x07F0,0x0000,0xFF80,0x001F,0xE000,
    0x3FC1,0xFE00,0x3F7F,0xFF3F,0xC000,0x003F,0xFFFF,0x80FF,0x07F8,0x0000,0xFF80,0x001F,0xE000,
    0x3FC0,0xFF00,0x3FFF,0xFC3F,0xC000,0x001F,0xFFFE,0x00FF,0x03FC,0x0000,0xFE00,0x001F,0x0000,
    0x3FC0,0x7F80,0x3FFF,0xF03F,0xC000,0x0000,0x7FE0,0x00FF,0x01FE,0x0000,0xF800,0x0010,0x0000,
    0x3FC0,0x3FC0,0x2000,0x003F,0xC000,0x0000,0x0000,0x00FF,0x00FF,0x0000,0xE000,0x0000,0x0000,
    0x3FC0,0x1FE0,0x0000,0x003F,0xC000,0x0000,0x0000,0x00FF,0x007F,0x8000,0x8000,0x0000,0x0000,
    0xFFC0,0x0FF0,0x0000,0x00FF,0xC000,0x0000,0x0000,0x03FF,0x003F,0xC000,0x0000,0x0000,0x0000,
    0xFFC0,0x07F8,0x0000,0x00FF,0xC000,0x0000,0x0000,0x03FF,0x001F,0xE000,0x0000,0x0000,0x0000,
    0x8000,0x03FC,0x0000,0x0000,0x0000,0x0000,0x0000,0x0200,0x000F,0xF000,0x0000,0x0000,0x0000,
    0x0000,0x01FE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0007,0xF800,0x0000,0x0000,0x0000,
    0x0000,0x00FF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0003,0xFC00,0x0000,0x0000,0x0000,
    0x0000,0x007F,0x8000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0001,0xFE00,0x0000,0x0000,0x0000,
    0x0000,0x003F,0xC1F0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFF03,0xC000,0x0000,0x0000,
    0x0000,0x001F,0xE1E0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7F8F,0x8000,0x0000,0x0000,
    0x0000,0x000F,0xF9E0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3FEF,0x8000,0x0000,0x0000,
    0x0000,0x0007,0xFFC0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1FFF,0x0000,0x0000,0x0000,
    0x0000,0x0001,0xFF00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07FC,0x0000,0x0000,0x0000,
    0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};
MODULE UWORD chip PubLogoData[1482] =
{   /* Plane 0 */
    0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x8000,0x0000,
    0x1FFF,0xF000,0x0000,0x0000,0x0000,0x0000,0x7FF0,0x007F,0xFFC0,0x007F,0xFFFF,0x8000,0x0000,
    0x1FFF,0xFE00,0x1FFF,0xFFFF,0xFFF0,0x0003,0xFFFE,0x007F,0xFFF8,0x007F,0xFFFF,0x8000,0x0000,
    0x1FFF,0xFFC0,0x1FFF,0xFFFF,0xFFFE,0x0007,0xFFFF,0x807F,0xFFFF,0x007F,0xFFFF,0x8000,0x1000,
    0x1FFF,0xFFE0,0x1FFF,0xFFFF,0xFFFF,0xE00F,0xFFFF,0xC07F,0xFFFF,0x807F,0xFFFF,0x8001,0xF000,
    0x1FFF,0xFFF0,0x1FFF,0xFFFF,0xFFFF,0xF01F,0xFFFF,0xE07F,0xFFFF,0xC07F,0xFFFF,0x800F,0xF000,
    0x1FFF,0xFFF8,0x1FFF,0xFFDF,0xFFFF,0xF81F,0xFFFF,0xE07F,0xFFFF,0xE07F,0xFFFF,0x800F,0xF000,
    0x1FE0,0x7FF8,0x1F80,0x001F,0xE07F,0xF83F,0xE01F,0xF07F,0x81FF,0xE000,0x7FC0,0x000F,0xF000,
    0x1FE0,0x0FFC,0x1F80,0x001F,0xE00F,0xFC3F,0xC00F,0xF07F,0x803F,0xF000,0x7FC0,0x000F,0xF000,
    0x1FE0,0x0FFC,0x1F80,0x001F,0xE00F,0xFC3F,0x800F,0xF07F,0x803F,0xF000,0x7FC0,0x000F,0xF000,
    0x1FE0,0x03FC,0x1F80,0x001F,0xE003,0xFC7F,0x8007,0xF87F,0x800F,0xF000,0x7FC0,0x000F,0xF010,
    0x1FE0,0x03FC,0x1F80,0x001F,0xE003,0xFC7F,0x8007,0xF87F,0x800F,0xF000,0x7FC0,0x000F,0xF0F0,
    0x1FE0,0x03FC,0x1FFF,0xE01F,0xE003,0xFC7F,0x8007,0xF87F,0x800F,0xF000,0x7FC0,0x000F,0xE7F0,
    0x1FE0,0x07F8,0x1FFF,0xC01F,0xE007,0xF87F,0x8007,0xF87F,0x801F,0xE000,0x7FC0,0x000F,0xFFF0,
    0x1FE0,0x0FF8,0x1FFF,0x801F,0xE00F,0xF87F,0x8007,0xF87F,0x803F,0xE000,0x7FC0,0x000F,0xFFF0,
    0x1FE0,0x1FF0,0x1FFF,0x001F,0xE01F,0xF07F,0x8007,0xF87F,0x807F,0xC000,0x7FC0,0x007F,0xFFC0,
    0x1FE0,0x7FE0,0x1FFE,0x001F,0xE07F,0xE07F,0x8007,0xF87F,0x81FF,0x8000,0x7FC0,0x03FF,0xFF00,
    0x1FFF,0xFFC0,0x1FFC,0x001F,0xFFFF,0xC07F,0x8007,0xF87F,0xFFFF,0x0000,0x7FC0,0x0FFF,0xF800,
    0x1FFF,0xFF80,0x1FF8,0x001F,0xFFFF,0x807F,0x8007,0xF87F,0xFFFE,0x0000,0x7FC0,0x0FFF,0xF000,
    0x1FFF,0xFF00,0x1F80,0x001F,0xFFFF,0x007F,0x8007,0xF87F,0xFFFC,0x0000,0x7FC0,0x0FFF,0xF000,
    0x1FFF,0xFE00,0x1F80,0x001F,0xFFFE,0x007F,0x8007,0xF07F,0xFFF8,0x0000,0x7FC0,0x0F8F,0xF000,
    0x1FFF,0xFE00,0x1F80,0x001F,0xFFFC,0x003F,0xC007,0xF07F,0xFFF8,0x0000,0x7FC0,0x0C0F,0xF000,
    0x1FFF,0xFE00,0x1F80,0x001F,0xFFE0,0x003F,0xC00F,0xF07F,0xFFF8,0x0000,0x7FC0,0x000F,0xF000,
    0x1FE1,0xFF00,0x1F80,0x001F,0xE000,0x003F,0xC01F,0xE07F,0x87FC,0x0000,0x7FC0,0x000F,0xF000,
    0x1FE0,0xFF00,0x1F80,0x001F,0xE000,0x001F,0xF03F,0xE07F,0x83FC,0x0000,0x7FC0,0x000F,0xF000,
    0x1FE0,0xFF80,0x1FFF,0xFF1F,0xE000,0x001F,0xFFFF,0xC07F,0x83FE,0x0000,0x7FC0,0x000F,0xF000,
    0x1FE0,0x7F80,0x1FFF,0xFE1F,0xE000,0x000F,0xFFFF,0x807F,0x81FE,0x0000,0x7F80,0x000F,0xF000,
    0x1FE0,0x7FC0,0x1FFF,0xFC1F,0xE000,0x000F,0xFFFF,0x007F,0x81FF,0x0000,0x7F00,0x000F,0xC000,
    0x1FE0,0x3FC0,0x1FFF,0xF81F,0xE000,0x0007,0xFFFE,0x007F,0x80FF,0x0000,0x7E00,0x000E,0x0000,
    0x1FE0,0x3FE0,0x1FFF,0xF01F,0xE000,0x0003,0xFFFC,0x007F,0x80FF,0x8000,0x7C00,0x0000,0x0000,
    0x1FE0,0x1FE0,0x1FFF,0xE01F,0xE000,0x0000,0x7FE0,0x007F,0x807F,0x8000,0x7800,0x0000,0x0000,
    0x1FE0,0x1FF0,0x0000,0x001F,0xE000,0x0000,0x0000,0x007F,0x807F,0xC000,0x7000,0x0000,0x0000,
    0x1FE0,0x0FF0,0x0000,0x001F,0xE000,0x0000,0x0000,0x007F,0x803F,0xC000,0x6000,0x0000,0x0000,
    0x1FE0,0x0FF8,0x0000,0x001F,0xE000,0x0000,0x0000,0x007F,0x803F,0xE000,0x4000,0x0000,0x0000,
    0x1FE0,0x07F8,0x0000,0x001F,0xE000,0x0000,0x0000,0x007F,0x801F,0xE000,0x0000,0x0000,0x0000,
    0x7FE0,0x07FC,0x0000,0x007F,0xE000,0x0000,0x0000,0x01FF,0x801F,0xF000,0x0000,0x0000,0x0000,
    0x7FE0,0x03FC,0x0000,0x007F,0xE000,0x0000,0x0000,0x01FF,0x800F,0xF000,0x0000,0x0000,0x0000,
    0x7FE0,0x03FE,0x0000,0x007F,0xE000,0x0000,0x0000,0x01FF,0x800F,0xF800,0x0000,0x0000,0x0000,
    0x7FE0,0x01FE,0x0000,0x00FF,0xE000,0x0000,0x0000,0x01FF,0x8007,0xF800,0x0000,0x0000,0x0000,
    0x0000,0x01FF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0007,0xFC00,0x0000,0x0000,0x0000,
    0x0000,0x00FF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0003,0xFC00,0x0000,0x0000,0x0000,
    0x0000,0x00FF,0x8000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0003,0xFE00,0x0000,0x0000,0x0000,
    0x0000,0x007F,0x8000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0001,0xFE00,0x0000,0x0000,0x0000,
    0x0000,0x007F,0xC000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0001,0xFF00,0x0000,0x0000,0x0000,
    0x0000,0x003F,0xC000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFF00,0x0000,0x0000,0x0000,
    0x0000,0x003F,0xE000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFF80,0x0000,0x0000,0x0000,
    0x0000,0x001F,0xE000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7F80,0x0000,0x0000,0x0000,
    0x0000,0x001F,0xF000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7FC0,0x0000,0x0000,0x0000,
    0x0000,0x000F,0xF0F0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3FC3,0xC000,0x0000,0x0000,
    0x0000,0x000F,0xF9F0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3FE7,0xC000,0x0000,0x0000,
    0x0000,0x0007,0xFFF0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1FFF,0xC000,0x0000,0x0000,
    0x0000,0x0003,0xFFE0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0FFF,0x8000,0x0000,0x0000,
    0x0000,0x0003,0xFFE0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0FFF,0x8000,0x0000,0x0000,
    0x0000,0x0001,0xFFC0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07FF,0x0000,0x0000,0x0000,
    0x0000,0x0000,0xFF80,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03FE,0x0000,0x0000,0x0000,
    0x0000,0x0000,0x3F00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x00FC,0x0000,0x0000,0x0000,
    0x0000,0x0000,0x3E00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x00F8,0x0000,0x0000,0x0000,
    /* Plane 1 */
    0x3FFF,0xF000,0x0000,0x0000,0x0000,0x0000,0x7FF0,0x00FF,0xFFC0,0x00FF,0xFFFF,0x0000,0x000F,
    0x3FFF,0xFE00,0x3FFF,0xFFFF,0xFFF0,0x0003,0xFFFE,0x00FF,0xFFF8,0x00FF,0xFFFF,0x0000,0x000F,
    0x3FFF,0xFF80,0x3FFF,0xFFFF,0xFFFE,0x0007,0xFFFF,0x00FF,0xFFFE,0x00FF,0xFFFF,0x0000,0x000F,
    0x3FFF,0xFF80,0x3FFF,0xFFFF,0xFFFF,0x800F,0xFFFF,0x00FF,0xFFFE,0x00FF,0xFFFF,0x0001,0xE00F,
    0x3FFF,0xFFC0,0x3FFF,0xFFFF,0xFFFF,0xC01F,0xFFFF,0x80FF,0xFFFF,0x00FF,0xFFFF,0x001F,0xE00F,
    0x3FFF,0xFFE0,0x3FFF,0xFFFF,0xFFFF,0xE03F,0xFFFF,0xC0FF,0xFFFF,0x80FF,0xFFFF,0x001F,0xE00F,
    0x3FC0,0x7FF0,0x3F00,0x003F,0xC07F,0xF03F,0xE07F,0xC0FF,0x01FF,0xC080,0x7F80,0x001F,0xE00F,
    0x3FC0,0x0FF0,0x3F00,0x003F,0xC00F,0xF07F,0xC07F,0xE0FF,0x003F,0xC000,0xFF80,0x001F,0xE00F,
    0x3FC0,0x07F8,0x3F00,0x003F,0xC007,0xF87F,0x801F,0xE0FF,0x001F,0xE000,0xFF80,0x001F,0xE00F,
    0x3FC0,0x07F8,0x3F00,0x003F,0xC007,0xF87F,0x001F,0xE0FF,0x001F,0xE000,0xFF80,0x001F,0xE00F,
    0x3FC0,0x07F8,0x3F00,0x003F,0xC007,0xF8FF,0x000F,0xF0FF,0x001F,0xE000,0xFF80,0x001F,0xE0EF,
    0x3FC0,0x07F8,0x3F7F,0xE03F,0xC007,0xF8FF,0x000F,0xF0FF,0x001F,0xE000,0xFF80,0x001F,0xE7EF,
    0x3FC0,0x07F8,0x3FFF,0xC03F,0xC007,0xF8FF,0x000F,0xF0FF,0x001F,0xE000,0xFF80,0x001F,0xFFEF,
    0x3FC0,0x0FF0,0x3FFF,0x803F,0xC00F,0xF0FF,0x000F,0xF0FF,0x003F,0xC000,0xFF80,0x001F,0xFFEF,
    0x3FC0,0x1FF0,0x3FFF,0x003F,0xC01F,0xF0FF,0x000F,0xF0FF,0x007F,0xC000,0xFF80,0x007F,0xFFCF,
    0x3FC0,0x7FE0,0x3FFE,0x003F,0xC07F,0xE0FF,0x000F,0xF0FF,0x01FF,0x8000,0xFF80,0x03FF,0xFF0F,
    0x3FDF,0xFFC0,0x3FFC,0x003F,0xDFFF,0xC0FF,0x000F,0xF0FF,0x7FFF,0x0000,0xFF80,0x1FFF,0xF80F,
    0x3FFF,0xFF80,0x3FF8,0x003F,0xFFFF,0x80FF,0x000F,0xF0FF,0xFFFE,0x0000,0xFF80,0x1FFF,0xE00F,
    0x3FFF,0xFF00,0x3F00,0x003F,0xFFFF,0x00FF,0x000F,0xF0FF,0xFFFC,0x0000,0xFF80,0x1FFF,0xE00F,
    0x3FFF,0xFE00,0x3F00,0x003F,0xFFFE,0x00FF,0x000F,0xF0FF,0xFFF8,0x0000,0xFF80,0x1F8F,0xE00F,
    0x3FFF,0xFC00,0x3F00,0x003F,0xFFFC,0x00FF,0x000F,0xE0FF,0xFFF0,0x0000,0xFF80,0x1C1F,0xE00F,
    0x3FFF,0xFC00,0x3F00,0x003F,0xFFE0,0x007F,0x800F,0xE0FF,0xFFF0,0x0000,0xFF80,0x101F,0xE00F,
    0x3FC1,0xFC00,0x3F00,0x003F,0xC000,0x007F,0x801F,0xE0FF,0x07F0,0x0000,0xFF80,0x001F,0xE00F,
    0x3FC3,0xFE00,0x3F00,0x003F,0xC000,0x007F,0xF03F,0xC0FF,0x0FF8,0x0000,0xFF80,0x001F,0xE00F,
    0x3FC1,0xFE00,0x3F7F,0xFF3F,0xC000,0x003F,0xFFFF,0xC0FF,0x07F8,0x0000,0xFF80,0x001F,0xE00F,
    0x3FC1,0xFF00,0x3FFF,0xFE3F,0xC000,0x003F,0xFFFF,0x80FF,0x07FC,0x0000,0xFF80,0x001F,0xE00F,
    0x3FC0,0xFF00,0x3FFF,0xFC3F,0xC000,0x001F,0xFFFF,0x00FF,0x03FC,0x0000,0xFF00,0x001F,0xC00F,
    0x3FC0,0xFF80,0x3FFF,0xF83F,0xC000,0x0007,0xFFFE,0x00FF,0x03FE,0x0000,0xFE00,0x001E,0x000F,
    0x3FC0,0x7F80,0x3FFF,0xF03F,0xC000,0x0003,0xFFFC,0x00FF,0x01FE,0x0000,0xFC00,0x0010,0x000F,
    0x3FC0,0x7FC0,0x3FFF,0xE03F,0xC000,0x0000,0x7FE0,0x00FF,0x01FF,0x0000,0xF800,0x0000,0x000F,
    0x3FC0,0x3FC0,0x2000,0x003F,0xC000,0x0000,0x0000,0x00FF,0x00FF,0x0000,0xF000,0x0000,0x000F,
    0x3FC0,0x3FE0,0x0000,0x003F,0xC000,0x0000,0x0000,0x00FF,0x00FF,0x8000,0xE000,0x0000,0x000F,
    0x3FC0,0x1FE0,0x0000,0x003F,0xC000,0x0000,0x0000,0x00FF,0x007F,0x8000,0xC000,0x0000,0x000F,
    0x3FC0,0x1FF0,0x0000,0x003F,0xC000,0x0000,0x0000,0x00FF,0x007F,0xC000,0x8000,0x0000,0x000F,
    0xFFC0,0x0FF0,0x0000,0x00FF,0xC000,0x0000,0x0000,0x03FF,0x003F,0xC000,0x0000,0x0000,0x000F,
    0xFFC0,0x0FF8,0x0000,0x00FF,0xC000,0x0000,0x0000,0x03FF,0x003F,0xE000,0x0000,0x0000,0x000F,
    0xFFC0,0x07F8,0x0000,0x00FF,0xC000,0x0000,0x0000,0x03FF,0x001F,0xE000,0x0000,0x0000,0x000F,
    0xFFC0,0x07FC,0x0000,0x00FF,0xC000,0x0000,0x0000,0x03FF,0x001F,0xF000,0x0000,0x0000,0x000F,
    0x8000,0x03FC,0x0000,0x0000,0x0000,0x0000,0x0000,0x0200,0x000F,0xF000,0x0000,0x0000,0x000F,
    0x0000,0x03FE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x000F,0xF800,0x0000,0x0000,0x000F,
    0x0000,0x01FE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0007,0xF800,0x0000,0x0000,0x000F,
    0x0000,0x01FF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0007,0xFC00,0x0000,0x0000,0x000F,
    0x0000,0x00FF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0003,0xFC00,0x0000,0x0000,0x000F,
    0x0000,0x00FF,0x8000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0003,0xFE00,0x0000,0x0000,0x000F,
    0x0000,0x007F,0x8000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0001,0xFE00,0x0000,0x0000,0x000F,
    0x0000,0x007F,0xC000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0001,0xFF00,0x0000,0x0000,0x000F,
    0x0000,0x003F,0xC000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFF00,0x0000,0x0000,0x000F,
    0x0000,0x003F,0xE0F0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFF83,0xC000,0x0000,0x000F,
    0x0000,0x001F,0xE1E0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7F87,0x8000,0x0000,0x000F,
    0x0000,0x001F,0xF3E0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7FCF,0x8000,0x0000,0x000F,
    0x0000,0x000F,0xFBE0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3FEF,0x8000,0x0000,0x000F,
    0x0000,0x0007,0xFFC0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1FFF,0x0000,0x0000,0x000F,
    0x0000,0x0007,0xFFC0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1FFF,0x0000,0x0000,0x000F,
    0x0000,0x0003,0xFF80,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0FFE,0x0000,0x0000,0x000F,
    0x0000,0x0001,0xFF00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07FC,0x0000,0x0000,0x000F,
    0x0000,0x0000,0xFE00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03F8,0x0000,0x0000,0x000F,
    0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x000F,
};
MODULE UWORD chip PalAboutData[66] =
{   0xFFFF,0xFFFF,0xFFF8,
    0xFDFF,0xC7FF,0xFFF8,
    0xE53F,0x83FF,0xFFF8,
    0xF8FF,0x01FF,0xFFF8,
    0xE53E,0x10FF,0xFBF8,
    0xFDFC,0x387F,0x9B38,
    0xFFF8,0x7C3F,0xE0F8,
    0xC3F0,0x0000,0x0018,
    0xE1E0,0x1F0F,0xE0F8,
    0xF0C3,0xE387,0x9B38,
    0xF807,0xFC43,0xFBF8,
    0xFC0F,0xFF81,0xFFF8,
    0xFE1F,0xFFF0,0xFFF8,
    0xFFFF,0xFFFF,0xFFF8,
    0xFFFF,0xFFFF,0xFFF8,
    0xF1C4,0x6C0E,0x39D8,
    0xEEDB,0x6BFD,0xDAD8,
    0xE0DB,0x6B8C,0x1B58,
    0xDF5F,0x6BEB,0xEB98,
    0xDF5F,0x6C0B,0xEBD8,
    0xFFFF,0xFFFF,0xFFF8,
    0xFFFF,0xFFFF,0xFFF8
};
MODULE UWORD chip PubAboutData[132] =
{   0xFFFF,0xFFFF,0xFFE0,
    0xFFFF,0xFFFF,0xFFE0,
    0xFFFF,0xFFFF,0xFFE0,
    0xFFFF,0xFFFF,0xFFE0,
    0xFBFF,0x8FFF,0xFFE0,
    0xFBFF,0x8FFF,0xFFE0,
    0xCA7F,0x07FF,0xFFE0,
    0xCA7F,0x07FF,0xFFE0,
    0xF1FE,0x03FF,0xFFE0,
    0xF1FE,0x03FF,0xFFE0,
    0xCA7C,0x21FF,0xF7E0,
    0xCA7C,0x21FF,0xF7E0,
    0xFBF8,0x70FF,0x3660,
    0xFBF8,0x70FF,0x3660,
    0xFFF0,0xF87F,0xC1E0,
    0xFFF0,0xF87F,0xC1E0,
    0x87E0,0x0000,0x0020,
    0x87E0,0x0000,0x0020,
    0xC3C0,0x3E1F,0xC1E0,
    0xC3C0,0x3E1F,0xC1E0,
    0xE187,0xC70F,0x3660,
    0xE187,0xC70F,0x3660,
    0xF00F,0xF887,0xF7E0,
    0xF00F,0xF887,0xF7E0,
    0xF81F,0xFF03,0xFFE0,
    0xF81F,0xFF03,0xFFE0,
    0xFC3F,0xFFE1,0xFFE0,
    0xFC3F,0xFFE1,0xFFE0,
    0xFFFF,0xFFFF,0xFFE0,
    0xFFFF,0xFFFF,0xFFE0,
    0xE1C8,0xDC38,0x6EE0,
    0xE1C8,0xDC38,0x6EE0,
    0xDDB6,0xDBF7,0x66E0,
    0xDDB6,0xDBF7,0x66E0,
    0xC1B6,0xDB30,0x6AE0,
    0xC1B6,0xDB30,0x6AE0,
    0xDDBE,0xDBB7,0x6CE0,
    0xDDBE,0xDBB7,0x6CE0,
    0xDDBE,0xD877,0x6EE0,
    0xDDBE,0xD877,0x6EE0,
    0xFFFF,0xFFFF,0xFFE0,
    0xFFFF,0xFFFF,0xFFE0,
    0xFFFF,0xFFFF,0xFFE0,
    0xFFFF,0xFFFF,0xFFE0
};

IMPORT ABOOL               certified;
IMPORT struct ReportStruct report;
IMPORT struct AminetStruct aminet;
IMPORT struct AGDBStruct   agdb;

AGLOBAL struct NewGadget Gadget =
{   0, 0,                                   /* left-x, top-y */
    0, 0,                                   /* width, height */
    0,                                      /* text */
    NULL,                                   /* font */
    NULL,                                   /* gadget ID */
    NULL,                                   /* flags */
    NULL,                                   /* visual info */
    NULL                                    /* user data */
};

#define ABOUTLINES      6
#define ABOUTSHADOW BLACK
#define ABOUTSHINE  WHITE
#define KICKSTARTX    168
#define KICKSTARTY     75
#define WORKBENCHX    168
#define WORKBENCHY     83

MODULE struct
{   WORD   x, y;
    STRPTR text;
} about[ABOUTLINES + 1] =
{   {80, 27,         TITLEBARTEXT,           },
    {80, 35,         "Saturday 28 April 2001"},
    {80, 43,         "© 2001 Amigan Software"},
    {80, 59,         "By James R. Jacobs"    },
    {80, KICKSTARTY, "Kickstart:"            },
    {80, WORKBENCHY, "Workbench:"            },
    {80, 106,        "Public Screen: RPLUS"  }
};
MODULE STRPTR FunctionOptions[FUNCTIONS + 1] =
{   "Bug report",
    "Aminet readme",
    "ACSE test",
    "Autodoc",
    "ID database",
    "IFF registry",
    "EOL/tab converter",
    "Path size report",
    "Battery RAM",
    "System file report",
    "_AGDB review",
    "_Icon processor",
    NULL
};
#define MENUENTRIES 13
MODULE struct NewMenu NewMenu[MENUENTRIES] =
{   { NM_TITLE, "Project",       0 , 0,               0, 0},
    {  NM_ITEM, "New",          "N", NM_ITEMDISABLED, 0, 0},
    {  NM_ITEM, "Open...",      "O", NM_ITEMDISABLED, 0, 0},
    {  NM_ITEM, NM_BARLABEL,     0 , 0,               0, 0},
    {  NM_ITEM, "Save",         "S", NM_ITEMDISABLED, 0, 0},
    {  NM_ITEM, "Save As...",   "O", NM_ITEMDISABLED, 0, 0},
    {  NM_ITEM, NM_BARLABEL,     0 , 0,               0, 0},
    {  NM_ITEM, "Quit Report+", "Q", 0,               0, 0},
    { NM_TITLE, "Help",          0 , 0,               0, 0},
    {  NM_ITEM, "Manual...",    "M", 0,               0, 0},
    {  NM_ITEM, NM_BARLABEL,     0 , 0,               0, 0},
    {  NM_ITEM, "About...",     "?", 0,               0, 0},
    {   NM_END, NULL,            0 , 0,               0, 0}
};

MODULE void clearkybd(void);
MODULE void helpabout(void);
MODULE void menu(void);
MODULE void parsewb(void);

AGLOBAL ULONG offset;
AGLOBAL TEXT  weekdaystring[LEN_DATSTRING],
              datestring[LEN_DATSTRING],
              timestring[LEN_DATSTRING];
AGLOBAL ABOOL done = FALSE;

int CXBRK(void) { return(0); }    /* Disable SAS/C Ctrl-C handling */
int chkabort(void) { return(0); } /* really */

IMPORT  struct EOLStruct        eol;
IMPORT  struct IconStruct       icon;
IMPORT  struct ExecBase*        SysBase;

AGLOBAL struct Library          *WindowBase      = NULL,
                                *LayoutBase      = NULL,
                                *ButtonBase      = NULL,
                                *TextEditorBase  = NULL,
                                *LabelBase       = NULL,
                                *ListBrowserBase = NULL;
AGLOBAL ABOOL                   pal              = FALSE,
                                fillwindows      = TRUE;
AGLOBAL TEXT                    asldir[VLONGFIELD + 1],
                                aslresult[VLONGFIELD + 1],
                                IOBuffer[LONGESTFIELD + 1],
                                globalname[VLONGFIELD + 1],
                                string[VLONGFIELD + 1];
AGLOBAL SBYTE                   page             = 0;
AGLOBAL SWORD                   y;
AGLOBAL ULONG                   elements, // for ReAction texteditor.gadget
                                wbval;
AGLOBAL APTR                    OldWindowPtr     = NULL;
AGLOBAL struct Process*         ProcessPtr       = NULL;
AGLOBAL struct Screen*          ScreenPtr        = NULL;
AGLOBAL struct Window*          MainWindowPtr    = NULL;
AGLOBAL struct Gadget*          MX101_OSVersion  = NULL;
AGLOBAL struct VisualInfo*      VisualInfoPtr    = NULL;
AGLOBAL struct ExAllData*       ead              = NULL;
AGLOBAL struct Gadget          *BU99_Left        = NULL,
                               *BU99_Right       = NULL,
                               *ST99_Output      = NULL,
                               *BU99_OutputASL   = NULL,
                               *CB99_Log         = NULL,
                               *BU99_Update      = NULL,
                               *BU99_Stop        = NULL,
                               *BU99_TextEditor  = NULL,
                               *GListPtr         = NULL,
                               *PrevGadPtr       = NULL;
AGLOBAL struct SharedStruct shared =
{   TRUE, 0,
    "", ""
};
AGLOBAL struct Menu*            MenuPtr          = NULL;
AGLOBAL ULONG                   fillcolour;

MODULE  WORD                    xsize, ysize;
MODULE  ULONG                   ksval;
MODULE  struct RDArgs*          ArgsPtr           = NULL;
MODULE  struct TextFont*        FontPtr           = NULL;
MODULE  struct Window          *BkgrndWindowPtr   = NULL;
MODULE  struct Gadget          *TE00_FunctionText[FUNCTIONS] =
        {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
                               *MX00_Function     = NULL,
                               *ST00_Editor       = NULL,
                               *BU00_EditorASL    = NULL;
MODULE  struct WBArg*           WBArg             = NULL;
MODULE  struct WBStartup*       WBMsg             = NULL;
MODULE  struct TextAttr         Topaz8 =
{	(STRPTR) "topaz.font", 8, FS_NORMAL, FPF_ROMFONT | FPF_DESIGNED
}, /* "topaz.font" is case-sensitive */ WormWars8 =
{	(STRPTR) "WormWars.font", 8, FS_NORMAL, FPF_DISKFONT | FPF_DESIGNED
};
MODULE  struct ASLBase*         ASLBase         = NULL;
MODULE  struct DiskFontBase*    DiskFontBase    = NULL;
MODULE  struct GadToolsBase*    GadToolsBase    = NULL;
MODULE  struct IntuitionBase*   IntuitionBase   = NULL;
MODULE  struct Library*         VersionBase     = NULL;
MODULE  struct Image
PalLogo =
{   0, 0,
    204, 29, 2,
    PalLogoData,
    0x3, BLACK,
    NULL
}, PubLogo =
{   0, 0,
    204, 57, 2,
    PubLogoData,
    0x3, BLACK,
    NULL
}, PalAbout =
{   0, 0,
    43, 22, 1,
    PalAboutData,
    0x4, 3,
    NULL
}, PubAbout =
{   0, 0,
    43, 44, 1,
    PubAboutData,
    0x1, 3,
    NULL
};
MODULE  struct EasyStruct       EasyStruct =
{   sizeof(struct EasyStruct),
    0,
    "Report+: Error",
    NULL,
    "Quit"
};

/* FUNCTIONS -------------------------------------------------------------- */

int main(int argc, char** argv)
{   UWORD Pens[10] =
    {   BLACK,     /* DETAILPEN        text in title bar */
        WHITE,     /* BLOCKPEN         fill title bar */
        BLACK,     /* TEXTPEN          regular text on BACKGROUNDPEN */
        WHITE,     /* SHINEPEN         bright edge */
        BLACK,     /* SHADOWPEN        dark edge */
        ORANGE,    /* FILLPEN          filling active window borders
                                       and selected gadgets */
        BLACK,     /* FILLTEXTPEN      text rendered over FILLPEN */
        LIGHTGREY, /* BACKGROUNDPEN    background colour */
        WHITE,     /* HIGHLIGHTTEXTPEN highlighted text on BACKGROUNDPEN */
        (UWORD) ~0
    };
    struct ColorSpec Colours[17] =
    {   /* colour   red   green     blue    description */
        {    0,     0x9,    0x8,    0xA},   /* GREY */
        {    1,     0x0,    0x0,    0x0},   /* BLACK */
        {    2,     0xF,    0xF,    0xF},   /* WHITE */
        {    3,     0xF,    0x7,    0x7},   /* RED */
        {    4,     0x6,    0x6,    0xF},   /* BLUE */          
        {    5,     0xC,    0xB,    0xD},   /* LIGHTGREY */
        {    6,     0xF,    0xA,    0x6},   /* ORANGE */
        {    7,     0xF,    0xF,    0x5},   /* YELLOW */
        {    8,     0xF,    0x2,    0x2},   // red
        {    9,     0xF,    0x8,    0x0},   // orange
        {   10,     0xF,    0xF,    0x0},   // yellow
        {   11,     0x5,    0xF,    0x5},   // green
        {   12,     0x5,    0x5,    0xF},   // blue (obsolete)
        {   13,     0x0,    0xF,    0xF},   // cyan (3rd-party)
        {   14,     0xB,    0xF,    0xB},   // LIGHTGREEN
        {   15,     0x9,    0x9,    0xF},   // sky blue
        {   -1,    NULL,   NULL,   NULL}
    };
    UWORD            i;
    SLONG            args[5] = { 0L, 0L, 0L, 0L, 0L };
    BPTR             OldDir;
    SLONG            number = 0;

    /* Start of program.

    version embedding into executable */

    if (0) /* that is, never */
        Printf("$VER: Report+ 4.51 (28.4.2001"); // is this always d.m.y format

    manuf_init(); // this needs to be here, before any possible cleanexit().

    if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 38L)))
    {   Printf("Report+: Need intuition.library V38+!\n");
        cleanexit(EXIT_FAILURE);
    }
    if ((ksval = SysBase->LibNode.lib_Version) < 38L)
    {   Printf("Report+: Need exec.library V38+!\n");
        cleanexit(EXIT_FAILURE);
    }

    autodoc_init();
    batt_init();

    /* From this point onwards, we can be sure we have Kickstart 2.1+... */

    if (!(VersionBase = (struct VersionBase *) OpenLibrary("version.library", 0L)))
        rq("Can't open version.library!");
    wbval = VersionBase->lib_Version;
    CloseLibrary(VersionBase);
    VersionBase = NULL;
    if (!(GadToolsBase = (struct GadToolsBase *) OpenLibrary("gadtools.library", 38L)))
        rq("Can't open GadTools.library V38+!");
    if (!(ASLBase = (struct ASLBase *) OpenLibrary("asl.library", 0L)))
        rq("Can't open ASL.library!");
    if (
        (!(DiskFontBase = (struct DiskFontBase *) OpenLibrary("diskfont.library", 0L)))
    ||  (!(FontPtr = (struct TextFont *) OpenDiskFont(&WormWars8)))
       )
        Gadget.ng_TextAttr = (struct TextAttr *) &Topaz8;
    else Gadget.ng_TextAttr = (struct TextAttr *) &WormWars8;

    if (wbval >= 44)
    {   if (!(ListBrowserBase = OpenLibrary("gadgets/listbrowser.gadget", 0)))
            rq("OpenLibrary(\"gadgets/listbrowser.gadget\") failed!");
    }

    report_init();
    newaminet(FALSE);
    newagdb(FALSE);
    // those must be done before we handle CLI arguments

    if (argc) /* started from CLI */
    {   if (!(ArgsPtr = ReadArgs
        (   "-P=PAL/S,-G=GREY/S,FUNCTION/N,ICONTYPE,FILE/F",
            (LONG *) args,
            NULL
	)))
        {   Printf
            (   "Usage: %s [-p=PAL] [-g=GREY] [[FUNCTION] <function> [ICONTYPE] [DISK|DRAWER|TOOL|PROJECT|TRASHCAN|DEVICE|KICKSTART|APPICON] [[FILE] <file(s)...>]\n",
                argv[0]
            );
            cleanexit(EXIT_FAILURE);
	}
        if (args[0])
            pal = TRUE;
        if (args[1])
            fillwindows = FALSE;
        if (args[2])
        {   number = (SLONG) (*((SLONG*) args[2]));
            if (number == 12 && wbval < 44)
            {   Printf("Report+: Icon converter requires OS3.5+!\n");
                cleanexit(EXIT_FAILURE);
            }
            if (number >= 1 && number <= FUNCTIONS)
            {   page = (number * 10) + 1;
                shared.function = number - 1;
            } else
            {   Printf("Report+: <function> must be 1-%ld!\n", FUNCTIONS);
                cleanexit(EXIT_FAILURE);
        }   }
        if (args[3])
        {   if (number == 12)
            {   if (!stricmp(args[3], "DISK"))
                {   icon.type = WBDISK - 1;
                } elif (!stricmp(args[3], "DRAWER"))
                {   icon.type = WBDRAWER - 1;
                } elif (!stricmp(args[3], "TOOL"))
                {   icon.type = WBTOOL - 1;
                } elif (!stricmp(args[3], "PROJECT"))
                {   icon.type = WBPROJECT - 1;
                } elif (!stricmp(args[3], "TRASHCAN"))
                {   icon.type = WBGARBAGE - 1;
                } elif (!stricmp(args[3], "DEVICE"))
                {   icon.type = WBDEVICE - 1;
                } elif (!stricmp(args[3], "KICKSTART"))
                {   icon.type = WBKICK - 1;
                } elif (!stricmp(args[3], "APPICON"))
                {   icon.type = WBAPPICON - 1;
                } else
                {   Printf("Report+: <icontype> must be DISK, DRAWER, TOOL, PROJECT, TRASHCAN, DEVICE, KICKSTART or APPICON!\n", argv[0]);
                    cleanexit(EXIT_FAILURE);
            }   }
            elif (args[4] == NULL)
            {   args[4] = args[3];
        }   }
        if (args[4])
        {   switch(number)
            {
            case 1:
                strcpy(report.output, args[4]);
                report.loaded = TRUE;
                loadreport();
            break;
            case 2:
                strcpy(aminet.output, args[4]);
                aminet.loaded = TRUE;
                loadaminet();
            break;
            case 7:
                strcpy( eol.pathname, args[4]);
                eol_do(FALSE);
                Printf("All done.\n");
                cleanexit(EXIT_SUCCESS);
            break;
            case 11:
                strcpy(  agdb.output, args[4]);
                agdb.loaded = TRUE;
                loadagdb();
            break;
            case 12:
                strcpy(icon.pathname, args[4]);
                icon_do(FALSE);
                Printf("All done.\n");
                cleanexit(EXIT_SUCCESS);
            break;
            default:
                Printf("Report+: <function> must be 1, 2, 7, 11 or 12 for this!\n");
                cleanexit(EXIT_FAILURE);
            break;
    }   }   }
    else /* started from WB */
    {   WBMsg = (struct WBStartup *) argv;
        WBArg = WBMsg->sm_ArgList; /* head of the arg list */
        for (i = 0; i < WBMsg->sm_NumArgs; i++, WBArg++)
        {   if (WBArg->wa_Lock)
            {   /* something that does not support locks */
                parsewb();
            } else
            {   /* lock supported; change to the proper directory */
                OldDir = CurrentDir(WBArg->wa_Lock);
                parsewb();
                CurrentDir(OldDir);
            }
            if (i == 1)
                ; /* we were started from a project icon, which is
                currently unsupported */
    }   }

    ProcessPtr = (struct Process *) FindTask(NULL);
    strcpy(asldir, "PROGDIR:");

    if (pal)
    {   xsize = 640;
        ysize = 256;
    } else
    {   /* RKM Libraries, p. 59-61: */
        if (!(ScreenPtr = LockPubScreen(NULL)))
            rq("Can't lock default public screen!");
        if (GetVPModeID(&(ScreenPtr->ViewPort)) == INVALID_ID)
            rq("Invalid default public screen mode ID!");
        xsize = ScreenPtr->Width;
        ysize = ScreenPtr->Height;
        UnlockPubScreen(NULL, ScreenPtr);
        ScreenPtr = NULL;
    }

    /* PREPARE DISPLAY -----------------------------------------------

    screen */

    if (pal)
    {   if (!(ScreenPtr = (struct Screen *) OpenScreenTags(NULL,
            SA_Width,        xsize,
            SA_Height,       ysize,
            SA_Depth,        4,
            SA_DisplayID,    HIRES_KEY | PAL_MONITOR_ID,
            SA_Title,        TITLEBARTEXT,
            SA_Colors,       Colours,
            SA_Font,         Gadget.ng_TextAttr,
            SA_Pens,         Pens,
            SA_DetailPen,    BLACK,
            SA_BlockPen,     WHITE,
            SA_AutoScroll,   TRUE,
            SA_PubName,      "RPLUS",
            TAG_DONE
        )))
            rq("Can't open custom PAL screen!");
        if (!(BkgrndWindowPtr = (struct Window *) OpenWindowTags(NULL,
            WA_Top,          12,
            WA_Width,        xsize,
            WA_Height,       ysize - 12,
            WA_IDCMP,        NULL,
            WA_Gadgets,      NULL,
            WA_CustomScreen, ScreenPtr,
            WA_Activate,     FALSE,
            WA_Title,        NULL,
            WA_Borderless,   TRUE,
            WA_Backdrop,     TRUE,
            TAG_DONE
        )))
            rq("Can't open backdrop window!");
        SetAPen(BkgrndWindowPtr->RPort, LIGHTGREEN);
        RectFill(BkgrndWindowPtr->RPort, 0, 0, xsize, ysize - 12);
        PubScreenStatus(ScreenPtr, 0); // take the screen public
    }

    files_init();
    double_init();

    if (shared.editor[0] == 0)
        if (GetVar("EDITOR", shared.editor, LONGFIELD, NULL) == -1)
            strcpy(shared.editor, "SYS:Tools/MEmacs");

    while(1)
    {   if (page == 11)
            report1();
        elif (page == 12)
            sender();
        elif (page == 13)
            config();
        elif (page == 21)
            aminet1();
        elif (page == 31)
            acse1();
        elif (page == 32)
            acse2();
        elif (page == 33)
            acse3();
        elif (page == 41)
            autodoc1();
        elif (page == 51)
        {   manuf0();
            manuf_exit();
        } elif (page == 61)
            iff1();
        elif (page == 71)
            eol1();
        elif (page == 72)
            eol2();
        elif (page == 81)
            size1();
        elif (page == 91)
            batt1();
        elif (page == 101)
            files1();
        elif (page == 111)
            agdb1();
        elif (page == 121)
        {   icon1();
        } elif (page == 122)
        {   icon2();
        } else
        {   // assert(page == 0);
            menu();
}   }   }

MODULE void menu(void)
{   /* PAGE 0 ************************************************************* */

    SWORD menuheight;
    ULONG i;
    TEXT  tempstring[5];

    certified = FALSE;
    if (pal)
        menuheight = PALMENUHEIGHT;
    else menuheight = PUBMENUHEIGHT;

    navigate();

    /* function labels: 1_2: */
    tempstring[3] = ':';
    tempstring[4] = 0;
    for (i = 1; i <= FUNCTIONS; i++)
    {   if (i < 10)
        {   strcpy(tempstring, " _#:");
            tempstring[2] = '0' + i;
        } elif (i == 10)
        {   strcpy(tempstring, "1_0:");
        } elif (i == 12)
        {   strcpy(tempstring, "12:");
        } else
        {   // assert(i == 11);
            strcpy(tempstring, "11:");
        }
        setgadget(38, menuheight - 64 - (FUNCTIONS * 8) + ((i - 1) * 9), 24, 8, tempstring, PLACETEXT_RIGHT);
        TE00_FunctionText[i - 1] = PrevGadPtr = (struct Gadget *) CreateGadget
        (   TEXT_KIND,
	    PrevGadPtr,
            &Gadget,
            GT_Underscore, '_',
            TAG_DONE
        );
    }
    /* function */
    setgadget(100, menuheight - 65 - (FUNCTIONS * 8), 0, 0, NULL, PLACETEXT_RIGHT); // -8 for each extra function
    MX00_Function = PrevGadPtr = (struct Gadget *) CreateGadget
    (   MX_KIND,
	PrevGadPtr,
	&Gadget,
	GTMX_Labels, &FunctionOptions,
        GTMX_Active, shared.function,
	GT_Underscore, '_',
	TAG_DONE
    );
    
    if (shared.editor[0] == 0)
        if (GetVar("EDITOR", shared.editor, LONGFIELD, NULL) == -1)
            strcpy(shared.editor, "SYS:Tools/MEmacs");
    setgadget(146, menuheight - 42, 180, 12, "_Editor pathname:", NULL);
    ST00_Editor = PrevGadPtr = (struct Gadget *) CreateGadget
    (   STRING_KIND,
	PrevGadPtr,
	&Gadget,
        GTST_String, &(shared.editor),
	GTST_MaxChars, LONGFIELD,
	GA_TabCycle, TRUE,
        GT_Underscore, '_',
        GA_Disabled, FALSE,
        TAG_DONE
    );
    setgadget(328, menuheight - 42, 28, 12, "_...", NULL);
    BU00_EditorASL = PrevGadPtr = (struct Gadget *) CreateGadget
    (   BUTTON_KIND,
	PrevGadPtr,
	&Gadget,
        GT_Underscore, '_',
        GA_Disabled, FALSE,
        TAG_DONE
    );

    newwindow
    (   366, menuheight,
        "Report+: Main Menu",
        BUTTONIDCMP | MXIDCMP | STRINGIDCMP
    );
    if (pal)
        DrawImage(MainWindowPtr->RPort, &PalLogo, 81, 20);
    else DrawImage(MainWindowPtr->RPort, &PubLogo, 81, 20);

    if (wbval >= 44)
    {   GT_SetGadgetAttrs(ST00_Editor,    MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
        GT_SetGadgetAttrs(BU00_EditorASL, MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
    }
    loop();
    strcpy
    (   shared.editor,
        ((struct StringInfo *) ST00_Editor->SpecialInfo)->Buffer
    );
    closewindow();
}

AGLOBAL void cleanexit(SBYTE rc)
{   /* ASL requesters are assumed to be already closed.

    iffparse.library is never opened or closed. Spooky :-) */

    manuf_exit();

    // help|about...
    if (AboutWindowPtr)
    {   if (pal)
            unboingball();
        CloseWindow(AboutWindowPtr);
        AboutWindowPtr = NULL;
    }
    // all
    if (LabelBase)
    {   CloseLibrary(LabelBase);
        LabelBase = NULL;
    }
    if (TextEditorBase)
    {   CloseLibrary(TextEditorBase);
        TextEditorBase = NULL;
    }
    if (ButtonBase)
    {   CloseLibrary(ButtonBase);
        ButtonBase = NULL;
    }
    if (LayoutBase)
    {   CloseLibrary(LayoutBase);
        LayoutBase = NULL;
    }
    if (WindowBase)
    {   CloseLibrary(WindowBase);
        WindowBase = NULL;
    }

    // function 10
    if (ListBrowserBase)
    {   clearlblist();
        CloseLibrary(ListBrowserBase);
        ListBrowserBase = NULL;
    }

    // all
    if (!pal && ScreenPtr)
    {   UnlockPubScreen(NULL, ScreenPtr);
        ScreenPtr = NULL;
    }
    if (OldWindowPtr)
    {   ProcessPtr->pr_WindowPtr = OldWindowPtr;
        OldWindowPtr = NULL;
    }
    if (MainWindowPtr)
        closewindow(); // this sets appropriate pointers to NULL

    /* Remember that you can't fool around with the list whilst the
    gadget is still using it. */

    report_exit();
    size_exit();
    aminet_exit();

    // all
    if (pal)
    {   if (BkgrndWindowPtr)
        {   CloseWindow(BkgrndWindowPtr);
            BkgrndWindowPtr = NULL;
        }
        if (ScreenPtr)
        {   if (!CloseScreen(ScreenPtr))
            {   DisplayBeep(ScreenPtr);
            }
            // Can't close screen, due to visitor windows. Yet we MUST
            // exit the program, of course - either the user has demanded
            // it, or the program has hit an error. So we leave the
            // screen open and shut down everything else, including the
            // program.
            ScreenPtr = NULL;
    }   }

    acse_exit();
    files_exit();

    if (FontPtr)
    {   CloseFont(FontPtr);
        FontPtr = NULL;
    }
    if (DiskFontBase)
    {   CloseLibrary((struct Library *) DiskFontBase);
        DiskFontBase = NULL;
    }
    if (ASLBase)
        CloseLibrary((struct Library *) ASLBase);
    if (GadToolsBase)
        CloseLibrary((struct Library *) GadToolsBase);
    if (ArgsPtr)
        FreeArgs(ArgsPtr);
    if (IntuitionBase)
    {   OpenWorkBench();
        CloseLibrary((struct Library *) IntuitionBase);
        IntuitionBase = NULL;
    }
    exit(rc); /* End of program. */
}

MODULE void clearkybd(void)
{   struct IntuiMessage* MsgPtr;

    while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
        GT_ReplyIMsg(MsgPtr);
}

AGLOBAL void FreeNameNodes(struct List* ListPtr)
{   /* RKM Libraries, p. 496:
	
    "Free the entire list, including the header. The header is not
    updated as the list is freed. This function demonstrates how to
    avoid referencing freed memory when deallocating nodes." */

    struct NameNode *WorkNodePtr, *NextNodePtr;
	
    WorkNodePtr = (struct NameNode *) (ListPtr->lh_Head); /* first node */
    while (NextNodePtr = (struct NameNode *) (WorkNodePtr->nn_Node.ln_Succ))
    {   FreeMem(WorkNodePtr, sizeof(struct NameNode));
        WorkNodePtr = NextNodePtr;
}   }

AGLOBAL void gadtools(void)
{   if (!pal)
    {   if (!(ScreenPtr = LockPubScreen(NULL)))
            rq("Can't lock default public screen!");
    }
    if (!(Gadget.ng_VisualInfo = VisualInfoPtr = (struct VisualInfo *) GetVisualInfo(ScreenPtr, TAG_DONE)))
        rq("Can't get GadTools visual info!");
    if (!pal)
    {   UnlockPubScreen(NULL, ScreenPtr);
        ScreenPtr = NULL;
    }
    if (pal)
    {   if (!(MenuPtr = (struct Menu *) CreateMenus(NewMenu, GTMN_FrontPen, BLACK, TAG_DONE)))
            rq("Can't create menus!");
    } else
    {   if (!(MenuPtr = (struct Menu *) CreateMenus(NewMenu, TAG_DONE)))
            rq("Can't create menus!");
    }
    if (!(LayoutMenus(MenuPtr, VisualInfoPtr, GTMN_NewLookMenus, TRUE, TAG_DONE)))
        rq("Can't lay out menus!");
    GListPtr = NULL; // that needs doing for the CreateContext() call
    if (!(PrevGadPtr = (struct Gadget *) CreateContext(&GListPtr)))
        rq("Can't create GadTools context!");
}

AGLOBAL void verynewwindow(SWORD width, SWORD height, STRPTR title, ULONG idcmp)
{   gadtools();

    if (pal)
    {   if (!(MainWindowPtr = (struct Window *) OpenWindowTags(NULL,
            WA_Left,         (xsize / 2) - (width / 2),          
            WA_Top,          12 + ((ysize - 12) / 2) - (height / 2),
            WA_Width,        width,
            WA_Height,       height,
            WA_IDCMP,        IDCMP_CLOSEWINDOW | IDCMP_MENUPICK | IDCMP_REFRESHWINDOW
                             | IDCMP_MOUSEBUTTONS | IDCMP_INTUITICKS | IDCMP_VANILLAKEY
                             | IDCMP_RAWKEY | idcmp,
            WA_Gadgets,      NULL,
            WA_CustomScreen, ScreenPtr,
            WA_Activate,     TRUE,
            WA_Title,        title,
            WA_DragBar,      TRUE,
            WA_DepthGadget,  TRUE,
            WA_CloseGadget,  TRUE,
            WA_SmartRefresh, TRUE,
            TAG_DONE)))
            rq("Can't open main window!");

        /* redirection of AmigaDOS system requesters */
        OldWindowPtr = ProcessPtr->pr_WindowPtr;
        ProcessPtr->pr_WindowPtr = (APTR) MainWindowPtr;
    } else
    {   if (!(ScreenPtr = LockPubScreen(NULL)))
            rq("Can't lock default public screen!");
        /* open the window on the public screen */
        if (!(MainWindowPtr = (struct Window*) OpenWindowTags(NULL,
                WA_Left,         (xsize / 2) - (width / 2),
                WA_Top,          12 + ((ysize - 12) / 2) - (height / 2),
                WA_Width,        width,
                WA_Height,       height,
                WA_IDCMP,
                IDCMP_CLOSEWINDOW | IDCMP_MENUPICK | IDCMP_REFRESHWINDOW
                | IDCMP_MOUSEBUTTONS | IDCMP_INTUITICKS | IDCMP_VANILLAKEY
                | IDCMP_RAWKEY | idcmp,
                WA_Gadgets,      NULL,
                WA_PubScreen,    ScreenPtr,
                WA_Activate,     TRUE,
                WA_Title,        title,
                WA_DragBar,      TRUE,
                WA_DepthGadget,  TRUE,
                WA_CloseGadget,  TRUE,
                WA_SmartRefresh, TRUE,
                WA_NewLookMenus, TRUE,
                TAG_DONE)))
            rq("Can't open main window!");
        UnlockPubScreen(NULL, ScreenPtr);
        ScreenPtr = NULL;
    }
    SetMenuStrip(MainWindowPtr, MenuPtr);

    if (fillwindows)
    {   getfillcolour();
        SetAPen
        (   MainWindowPtr->RPort,
            fillcolour
        );
        RectFill(MainWindowPtr->RPort, 4, 11, width - 5, height - 3);
    }

    navigate();
}

AGLOBAL void newwindow(SWORD width, SWORD height, STRPTR title, ULONG idcmp)
{   if (pal)
    {   if (!(MainWindowPtr = (struct Window *) OpenWindowTags(NULL,
            WA_Left,         (xsize / 2) - (width / 2),          
            WA_Top,          12 + ((ysize - 12) / 2) - (height / 2),
            WA_Width,        width,
            WA_Height,       height,
            WA_IDCMP,        IDCMP_CLOSEWINDOW | IDCMP_MENUPICK | IDCMP_REFRESHWINDOW
                             | IDCMP_MOUSEBUTTONS | IDCMP_INTUITICKS | IDCMP_VANILLAKEY
                             | IDCMP_RAWKEY | idcmp,
            WA_Gadgets,      GListPtr,
            WA_CustomScreen, ScreenPtr,
            WA_Activate,     TRUE,
            WA_Title,        title,
            WA_DragBar,      TRUE,
            WA_DepthGadget,  TRUE,
            WA_CloseGadget,  TRUE,
            WA_SmartRefresh, TRUE,
            TAG_DONE)))
            rq("Can't open main window!");

        /* redirection of AmigaDOS system requesters */
        OldWindowPtr = ProcessPtr->pr_WindowPtr;
        ProcessPtr->pr_WindowPtr = (APTR) MainWindowPtr;
    } else
    {   if (!(ScreenPtr = LockPubScreen(NULL)))
            rq("Can't lock default public screen!");
        /* open the window on the public screen */
        if (!(MainWindowPtr = (struct Window*) OpenWindowTags(NULL,
                WA_Left,         (xsize / 2) - (width / 2),
                WA_Top,          12 + ((ysize - 12) / 2) - (height / 2),
                WA_Width,        width,
                WA_Height,       height,
                WA_IDCMP,
                IDCMP_CLOSEWINDOW | IDCMP_MENUPICK | IDCMP_REFRESHWINDOW
                | IDCMP_MOUSEBUTTONS | IDCMP_INTUITICKS | IDCMP_VANILLAKEY
                | IDCMP_RAWKEY | idcmp,
                WA_Gadgets,      GListPtr,
                WA_PubScreen,    ScreenPtr,
                WA_Activate,     TRUE,
                WA_Title,        title,
                WA_DragBar,      TRUE,
                WA_DepthGadget,  TRUE,
                WA_CloseGadget,  TRUE,
                WA_SmartRefresh, TRUE,
                WA_NewLookMenus, TRUE,
                TAG_DONE)))
            rq("Can't open main window!");
        UnlockPubScreen(NULL, ScreenPtr);
        ScreenPtr = NULL;
    }
    SetMenuStrip(MainWindowPtr, MenuPtr);
    GT_RefreshWindow(MainWindowPtr, NULL);
}

MODULE void helpabout(void)
{   SBYTE line;
    TEXT  ks[5], wb[5];

    OffMenu(MainWindowPtr, FULLMENUNUM(MN_HELP, IN_ABOUT, NOSUB));
    switch(ksval)
    {
    case 38:
        strcpy(ks, "2.1 ");
    break;
    case 39:
        strcpy(ks, "3.0 ");
    break;
    case 40:
        strcpy(ks, "3.1 ");
    break;
    default:
        strcpy(ks, "4.0+");
    break;
    }
    switch(wbval)
    {
    break;
    case 38:
        strcpy(wb, "2.1 ");
    break;
    case 39:
        strcpy(wb, "3.0 ");
    break;
    case 40:
    case 41:
    case 42:
    case 43:
        strcpy(wb, "3.1 ");
    break;
    case 44:
        strcpy(wb, "3.5 ");
    break;
    case 45:
        strcpy(wb, "3.9 ");
    break;
    default:
        strcpy(wb, "4.0+");
    break;
    }

    if (pal)
    {   if (!(AboutWindowPtr = (struct Window *) OpenWindowTags(NULL,
        WA_Left,          (xsize / 2) - (ABOUTXPIXEL / 2),
        WA_Top,           12 + ((ysize - 12) / 2) - (ABOUTYPALPIXEL / 2),
        WA_Width,         ABOUTXPIXEL,
        WA_Height,        ABOUTYPALPIXEL,
        WA_IDCMP,         IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
        WA_Title,         "About Report+",
        WA_Gadgets,       NULL,
        WA_CustomScreen,  ScreenPtr,
        WA_DragBar,       TRUE,
        WA_CloseGadget,   TRUE,
        WA_NoCareRefresh, TRUE,
        WA_Activate,      TRUE,
	TAG_DONE)))
            rq("Can't open About... window!");

        SetAPen(AboutWindowPtr->RPort, LIGHTGREY);
        RectFill(AboutWindowPtr->RPort, 8, 13, ABOUTXPIXEL - 9, ABOUTYPALPIXEL - 5);
	SetAPen(AboutWindowPtr->RPort, ABOUTSHADOW);
        Move(AboutWindowPtr->RPort, 7, ABOUTYPALPIXEL - 4);
	Draw(AboutWindowPtr->RPort, 7, 12);
	Draw(AboutWindowPtr->RPort, ABOUTXPIXEL - 8, 12);
	SetAPen(AboutWindowPtr->RPort, ABOUTSHINE);
        Draw(AboutWindowPtr->RPort, ABOUTXPIXEL - 8, ABOUTYPALPIXEL - 4);
        Draw(AboutWindowPtr->RPort, 8, ABOUTYPALPIXEL - 4);
    } else
    {   if (!(AboutWindowPtr = (struct Window *) OpenWindowTags(NULL,
        WA_Left,                (xsize / 2) - (ABOUTXPIXEL / 2),
        WA_Top,                 12 + ((ysize - 12) / 2) - (ABOUTYPUBPIXEL / 2),
        WA_Width,               ABOUTXPIXEL,
        WA_Height,              ABOUTYPUBPIXEL,
        WA_IDCMP,               IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
        WA_Title,               "About Report+",
        WA_Gadgets,             NULL,
        WA_PubScreen,           ScreenPtr,
        WA_DragBar,             TRUE,
	WA_CloseGadget,		TRUE,
	WA_NoCareRefresh,	TRUE,
	WA_Activate,		TRUE,
	TAG_DONE)))
            rq("Can't open About... window!");
    }

    SetDrMd(AboutWindowPtr->RPort, JAM1);

    SetAPen(AboutWindowPtr->RPort, BLACK);
    for (line = 0; line <= ABOUTLINES; line++)
    {   if (pal || line < ABOUTLINES)
        {   Move(AboutWindowPtr->RPort, about[line].x, about[line].y);
            Text(AboutWindowPtr->RPort, about[line].text, (SBYTE) strlen(about[line].text));
    }   }

    Move(AboutWindowPtr->RPort, KICKSTARTX, KICKSTARTY);
    Text(AboutWindowPtr->RPort, ks, 4);
    Move(AboutWindowPtr->RPort, WORKBENCHX, WORKBENCHY);
    Text(AboutWindowPtr->RPort, wb, 4);

    if (pal)
    {   DrawBevelBox(AboutWindowPtr->RPort, 19, 21, 45, 23, GT_VisualInfo, VisualInfoPtr, GTBB_Recessed, TRUE, TAG_DONE);
        DrawImage(AboutWindowPtr->RPort, &PalAbout, 20, 22);
    } else
    {   DrawBevelBox(AboutWindowPtr->RPort, 19, 21, 45, 46, GT_VisualInfo, VisualInfoPtr, GTBB_Recessed, TRUE, TAG_DONE);
        DrawImage(AboutWindowPtr->RPort, &PubAbout, 20, 22);
    }

    if (pal)
        boingball();
}

AGLOBAL void closewindow(void)
{   if (MainWindowPtr)
    {   clearkybd();
        ClearMenuStrip(MainWindowPtr);
        CloseWindow(MainWindowPtr);
        MainWindowPtr = NULL;
    }
    if (GListPtr)
    {   FreeGadgets(GListPtr);
        GListPtr = NULL;
    }
    if (MenuPtr)
    {   FreeMenus(MenuPtr);
        MenuPtr = NULL;
    }
    if (VisualInfoPtr)
    {   FreeVisualInfo(VisualInfoPtr);
        VisualInfoPtr = NULL;
}   }

AGLOBAL void asl(void)
{   struct FileRequester* ASLRqPtr;

    if (!(ASLRqPtr = AllocAslRequestTags(ASL_FileRequest, ASL_Pattern, "~(#?.info)", ASL_Window, MainWindowPtr, TAG_DONE)))
        rq("Can't create ASL request!");
    if
    (   AslRequestTags(ASLRqPtr, ASL_Dir, asldir, ASL_Hail, "Report+ file selector", ASL_FuncFlags, FILF_PATGAD, TAG_DONE)
     && *(ASLRqPtr->rf_File) != 0
    )
    {   strcpy(asldir, ASLRqPtr->rf_Dir);
        strcpy(aslresult, ASLRqPtr->rf_Dir);
        if (!AddPart(aslresult, ASLRqPtr->rf_File, VLONGFIELD))
            rq("Can't add filename to pathname!");
    } else
    {   strcpy(asldir, "");
        strcpy(aslresult, "");
    }
    FreeAslRequest(ASLRqPtr);
}

AGLOBAL void loop(void)
{   AUTO SWORD                oldpage = page;
    AUTO struct Gadget*       addr;
    AUTO struct IntuiMessage* MsgPtr;
    AUTO UWORD                code, qual;
    AUTO ULONG                class;
    AUTO SWORD                mousex, mousey;

    /* i must be signed, and at least 16 bits wide. */

    done = FALSE;
    while (page == oldpage && (!done))
    {   if (AboutWindowPtr)
        {   if (pal)
            {   DrawGels();
            } else
            {   Wait((1L <<  MainWindowPtr->UserPort->mp_SigBit) |
                     (1L << AboutWindowPtr->UserPort->mp_SigBit));
            }
            if (aboutloop())
            {   if (pal)
                    unboingball();
                CloseWindow(AboutWindowPtr);
                AboutWindowPtr = NULL;
                OnMenu(MainWindowPtr, FULLMENUNUM(MN_HELP, IN_ABOUT, NOSUB));
        }   }
        else
        {   Wait(1L <<  MainWindowPtr->UserPort->mp_SigBit);
        }
        while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
        {   class  = MsgPtr->Class;                       
            code   = MsgPtr->Code;
            addr   = MsgPtr->IAddress;
            qual   = MsgPtr->Qualifier;
            mousex = MsgPtr->MouseX;
            mousey = MsgPtr->MouseY;
            GT_ReplyIMsg(MsgPtr);
            switch(class)
            {
            case IDCMP_MENUPICK:
                handlemenus(code);
            break;
            case IDCMP_CLOSEWINDOW:
                cleanexit(EXIT_SUCCESS);
            break;
            case IDCMP_REFRESHWINDOW:
                GT_BeginRefresh(MainWindowPtr);
                GT_EndRefresh(MainWindowPtr, TRUE);
            break;
            default:
                if (class == IDCMP_RAWKEY && code == SCAN_HELP)
                {   helpabout();
                } elif (page == 0)
                {   if (class == IDCMP_GADGETDOWN)
                    {   /* radio gadgets */
                        if (addr == MX00_Function)
                        {   shared.function = code;
                            if (wbval < 44 && code == 11)
                            {   GT_SetGadgetAttrs
                                (   BU99_Right,
                                    MainWindowPtr,
                                    NULL,
                                    GA_Disabled, TRUE,
                                    TAG_DONE
                                );
                            } else
                            {   GT_SetGadgetAttrs
                                (   BU99_Right,
                                    MainWindowPtr,
                                    NULL,
                                    GA_Disabled, FALSE,
                                    TAG_DONE
                                );
                    }   }   }
                    elif (class == IDCMP_GADGETUP)
                    {   /* buttons, listviews, checkboxes */
                        if (addr == BU99_Right)
                        {   page = 11 + (shared.function * 10);
                        } elif (BU00_EditorASL)
                        {   asl();
                            GT_SetGadgetAttrs
                            (   ST00_Editor,
                                MainWindowPtr,
                                NULL,
                                GTST_String, aslresult,
                                TAG_DONE
                            );
                    }   }
                    elif (class == IDCMP_RAWKEY)
                    {   if (code == SCAN_UP && shared.function > 0)
                        {   if (qual & IEQUALIFIER_CONTROL)
                                shared.function = 0;
                            else shared.function--;
                            GT_SetGadgetAttrs
                            (   MX00_Function,
                                MainWindowPtr,
                                NULL,
                                GTMX_Active, shared.function,
                                TAG_DONE
                            );
                            if (shared.function == 11 && wbval < 44)
                            {   GT_SetGadgetAttrs
                                (   BU99_Right,
                                    MainWindowPtr,
                                    NULL,
                                    GA_Disabled, TRUE,
                                    TAG_DONE
                                );
                            } else
                            {   GT_SetGadgetAttrs
                                (   BU99_Right,
                                    MainWindowPtr,
                                    NULL,
                                    GA_Disabled, FALSE,
                                    TAG_DONE
                                );
                        }   }
                        elif (code == SCAN_DOWN && shared.function < FUNCTIONS - 1)
                        {   if (qual & IEQUALIFIER_CONTROL)
                            {   shared.function = FUNCTIONS - 1;
                            } else shared.function++;
                            GT_SetGadgetAttrs
                            (   MX00_Function,
                                MainWindowPtr,
                                NULL,
                                GTMX_Active, shared.function,
                                TAG_DONE
                            );
                            if (shared.function == 11 && wbval < 44)
                            {   GT_SetGadgetAttrs
                                (   BU99_Right,
                                    MainWindowPtr,
                                    NULL,
                                    GA_Disabled, TRUE,
                                    TAG_DONE
                                );
                            } else
                            {   GT_SetGadgetAttrs
                                (   BU99_Right,
                                    MainWindowPtr,
                                    NULL,
                                    GA_Disabled, FALSE,
                                    TAG_DONE
                                );
                    }   }   }
                    elif (class == IDCMP_VANILLAKEY)
                    {   code = toupper(code);
                        if (code == '`' && ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT)))
                        {   decrypt();
                        } elif (code == ESCAPE)
                        {   cleanexit(EXIT_SUCCESS);
                        } elif (code >= '0' && code <= '9')
                        {   if (code == '0')
                                shared.function = 9;
                            else shared.function = code - '1';
                            GT_SetGadgetAttrs
                            (   MX00_Function,
                                MainWindowPtr,
                                NULL,
                                GTMX_Active, shared.function,
                                TAG_DONE
                            );
                        } elif (code == 'A')
                        {   shared.function = 10;
                            GT_SetGadgetAttrs
                            (   MX00_Function,
                                MainWindowPtr,
                                NULL,
                                GTMX_Active, shared.function,
                                TAG_DONE
                            );
                        } elif (code == 'I' && wbval >= 44)
                        {   shared.function = 11;
                            GT_SetGadgetAttrs
                            (   MX00_Function,
                                MainWindowPtr,
                                NULL,
                                GTMX_Active, shared.function,
                                TAG_DONE
                            );
                        } elif (code == '.')
                        {   asl();
                            GT_SetGadgetAttrs
                            (   ST00_Editor,
                                MainWindowPtr,
                                NULL,
                                GTST_String, aslresult,
                                TAG_DONE
                            );
                        } elif (code == 'E')
                        {   ActivateGadget(ST00_Editor, MainWindowPtr, NULL);
                        } elif (code == 'B' || (wbval >= 44 && code == CR))
                        {   page = (shared.function * 10) + 11;
                }   }   }
                elif (page >= 11 && page <= 14)
                    report_loop(class, addr, code, qual);
                elif (page >= 21 && page <= 22)
                    aminet_loop(class, addr, code);
                elif (page >= 31 && page <= 33)
                    acse_loop(class, addr, code);
                elif (page >= 41 && page <= 42)
                    autodoc_loop(class, addr, code);
                elif (page == 51)
                    manuf_loop(class, addr, code);
                elif (page == 61)
                    iff_loop(class, addr, code, qual);
                elif (page >= 71 && page <= 72)
                    eol_loop(class, addr, code, qual);
                elif (page == 81)
                    size_loop(class, addr, code, qual);
                elif (page == 91)
                    batt_loop(class, addr, code, qual, mousex, mousey);
                elif (page == 101)
                    files_loop(class, addr, code, qual);
                elif (page == 111)
                {   agdb_loop(class, addr, code);
                } elif (page >= 121 && page <= 122)
                {   icon_loop(class, addr, code, qual);
                }
            break;
}   }   }   }

AGLOBAL void navigate(void)
{   ABOOL create = TRUE;

    gadtools();

    /* BU99_Right is created first, as all windows use it. Therefore all
    windows can safely call AddGList(), etc. with the BU99_Right argument. */

    /* next */
    switch(page)
    {
    case 0:
        if (pal)
            setgadget(        10, PALMENUHEIGHT - 16,                   346, 12, "_Begin",   NULL);
        else setgadget(       10, PUBMENUHEIGHT - 16,                   346, 12, "_Begin",   NULL);
    break;
    case 11:
        setgadget(            10,  REPORTHEIGHT - 16,      REPORTWIDTH - 20, 12, "Menu",     NULL);
    break;
    case 12:
        setgadget(            10,  SENDERHEIGHT - 16,      SENDERWIDTH - 20, 12, "Done",     NULL);
    break;
    case 13:
        setgadget(            10,  CONFIGHEIGHT - 16,      CONFIGWIDTH - 20, 12, "Done",     NULL);
    break;
    case 21:                                                                                
        setgadget(            10,  AMINETHEIGHT - 16,      AMINETWIDTH - 20, 12, "Menu",     NULL);
    break;
    case 31:
        setgadget(            10,   ACSE1HEIGHT - 16,       ACSE1WIDTH - 20, 12, "Menu",     NULL);
    break;
    case 32:
        if (certified)
            setgadget(        10,   ACSE2HEIGHT - 16,       ACSE2WIDTH - 20, 12, "Finish",   NULL);
        else                                                                                 
            setgadget(        10,   ACSE2HEIGHT - 16,       ACSE2WIDTH - 20, 12, "Menu",     NULL);
    break;
    case 33:
        setgadget(            10,   ACSE3HEIGHT - 16,       ACSE3WIDTH - 20, 12, "Menu",     NULL);
    break;
    case 41:
        setgadget(            10, AUTODOCHEIGHT - 16,     AUTODOCWIDTH - 20, 12, "Menu",     NULL);
    break;
    case 51:
        setgadget(            10,  MANUF1HEIGHT - 16,      MANUF1WIDTH - 20, 12, "Menu",     NULL);
    break;
    case 61:
        setgadget(            10,    IFF1HEIGHT - 16,        IFF1WIDTH - 20, 12, "Menu",     NULL);
    break;
    case 71:
        setgadget( EOL1WIDTH / 2,    EOL1HEIGHT - 16,  (EOL1WIDTH / 2) - 10, 12, "_Convert", NULL);
    break;
    case 72:
        setgadget(            10,    EOL2HEIGHT - 16,  (EOL2WIDTH / 2) - 20, 12, "Menu",     NULL);
    break;
    case 81:
        setgadget(            10,   SIZE1HEIGHT - 16,       SIZE1WIDTH - 20, 12, "Menu",     NULL);
    break;
    case 91:
        setgadget(            10,   BATT1HEIGHT - 16,       BATT1WIDTH - 20, 12, "Menu",     NULL);
    break;
    case 101:
        setgadget(            10,  FILES1HEIGHT - 16,      FILES1WIDTH - 20, 12, "Menu",     NULL);
    break;
    case 111:
        setgadget(            10,    AGDBHEIGHT - 16,        AGDBWIDTH - 20, 12, "Menu",     NULL);
    break;
    case 121:
        setgadget(ICON1WIDTH / 2,   ICON1HEIGHT - 16, (ICON1WIDTH / 2) - 10, 12, "Pro_cess", NULL);
    break;
    case 122:
        setgadget(            10,   ICON2HEIGHT - 16,       ICON2WIDTH - 20, 12, "Menu",     NULL);
    break;
    default:
    break;
    }
    BU99_Right = PrevGadPtr = (struct Gadget *) CreateGadget
    (   BUTTON_KIND,
        PrevGadPtr,
        &Gadget,
        GT_Underscore, '_',
        TAG_DONE
    );

    /* previous */
    switch(page)
    {
    case 71:
        setgadget(10,     EOL1HEIGHT - 16,  (EOL1WIDTH / 2) - 10, 12, "Menu",     NULL);
    break;
    case 121:
        setgadget(10,    ICON1HEIGHT - 16, (ICON1WIDTH / 2) - 10, 12, "Menu",     NULL);
    break;
    default:
        create = FALSE;
    break;
    }
    if (create)
    {   BU99_Left = PrevGadPtr = (struct Gadget *) CreateGadget
        (   BUTTON_KIND,
            PrevGadPtr,
            &Gadget,
            GT_Underscore, '_',
            TAG_DONE
        );
}   }

AGLOBAL void setgadget(WORD leftx, WORD topy, WORD width, WORD height,
STRPTR text, ULONG flags)
{   Gadget.ng_LeftEdge   = leftx;
    Gadget.ng_TopEdge    = topy;
    Gadget.ng_Width      = width;
    Gadget.ng_Height     = height;
    Gadget.ng_GadgetText = text;
    Gadget.ng_Flags      = flags;
}

AGLOBAL ABOOL readin(STRPTR pathname)
{   BPTR FileHandle;

    if (!(FileHandle = (BPTR) Open(pathname, MODE_OLDFILE)))
        return FALSE;
    if (Read(FileHandle, IOBuffer, 4096) == -1)
    // the whole bug report must be < 4K
    {   Close(FileHandle);
        return FALSE;
    }
    Close(FileHandle);
    return TRUE;
}

AGLOBAL void writeout(STRPTR pathname)
{   BPTR FileHandle;

    if (!(FileHandle = (BPTR) Open(pathname, MODE_NEWFILE)))
        rq("Can't open file for writing!");
    if (Write(FileHandle, IOBuffer, strlen(IOBuffer)) == -1)
    {   Close(FileHandle);
        rq("Can't write to file!");
    }
    Close(FileHandle);
}

AGLOBAL void say(STRPTR sentence, UBYTE colour)
{   SWORD width;
    ULONG black,
          skyblue = 0, // to avoid spurious warnings
          white;

    if (page == 72)
    {   width = EOL2WIDTH;
    } elif (page == 31)
    {   width = ACSE1WIDTH;
    } elif (page == 32)
    {   width = ACSE2WIDTH;
    } elif (page == 122)
    {   width = ICON2WIDTH;
    } else
    {   // assert(page == 33);
        width = ACSE3WIDTH;
    }

/*  There are 4 possible `looks' of Report+:

    default  light blue window fills, medium grey gadgets
    GREY     medium grey window fills, medium grey gadgets
    PAL      light blue window fills, light and dark grey gadgets
    PAL GREY dark grey window fills, light and dark grey gadgets

    The GREY flag has no effect on the look of gadgets.
    The PAL  flag has no effect on window fills.

    This routine dosn't do RectFill()s, nor does it preserve pens.
    DrawMode is set to JAM2 on exit. */

    lockscreen();
    black = FindColor
    (   ScreenPtr->ViewPort.ColorMap,
        0x00000000, // red
        0x00000000, // green
        0x00000000, // blue
        -1
    );
    if (fillwindows)
    {   skyblue = FindColor
        (   ScreenPtr->ViewPort.ColorMap,
            0x99999999, // red
            0x99999999, // green
            0xFFFFFFFF, // blue
            -1
        );
    }
    unlockscreen();

    SetAPen(MainWindowPtr->RPort, black);
    if (fillwindows)
    {   SetBPen(MainWindowPtr->RPort, skyblue);
    }

    Move
    (   MainWindowPtr->RPort,
        (width / 2) - (strlen(sentence) * 4),
        y
    );
    Text
    (   MainWindowPtr->RPort,
        sentence,
        strlen(sentence)
    );
    if (colour == WHITE)
    {   lockscreen();
        white = FindColor
        (   ScreenPtr->ViewPort.ColorMap,
            0xFFFFFFFF, // red
            0xFFFFFFFF, // green
            0xFFFFFFFF, // blue
            -1
        );
        unlockscreen();
        SetAPen(MainWindowPtr->RPort, white);
        SetDrMd(MainWindowPtr->RPort, JAM1);
        Move
	(   MainWindowPtr->RPort,
	    (width / 2) - (strlen(sentence) * 4) - 1,
	    y - 1
	);
        Text
	(   MainWindowPtr->RPort,
	    sentence,
	    strlen(sentence)
        );
    }
    y += 16;
    SetDrMd(MainWindowPtr->RPort, JAM2);
}

AGLOBAL void launcheditor(void)
{   GT_SetGadgetAttrs
    (   BU99_Right,
        MainWindowPtr, NULL,
        GA_Disabled, TRUE,
        TAG_DONE
    );
    if (wbval <= 43)
    {   ClearMenuStrip(MainWindowPtr);

        strcpy(string, shared.editor);
	strcat(string, " ");
	strcat
        (   string,
            shared.output
	);
	if (!Execute(string, NULL, NULL))
            rq("Can't launch editor!");
    } else
    {   textedit();
    }
    GT_SetGadgetAttrs
    (   BU99_Right,
        MainWindowPtr, NULL,
        GA_Disabled, FALSE,
        TAG_DONE
    );
}

AGLOBAL void rq(STRPTR text)
{   EasyStruct.es_TextFormat = text;
    EasyRequest(MainWindowPtr, &EasyStruct, NULL);

    cleanexit(EXIT_FAILURE);
}

AGLOBAL void readordie(STRPTR pathname)
{   BPTR FileHandle;

    if (!(FileHandle = (BPTR) Open(pathname, MODE_OLDFILE)))
        rq("Can't open file for reading!");
    if (Read(FileHandle, IOBuffer, LONGESTFIELD) == -1)
    {   Close(FileHandle);
        rq("Can't read file!");
    }
    if (!Close(FileHandle))
        rq("Can't close file for reading!");
}

MODULE void parsewb(void)
{   struct DiskObject* DiskObject;
    char**             ToolArray;
    char*              s;

    if ((*WBArg->wa_Name) && (DiskObject = GetDiskObject(WBArg->wa_Name)))
    {   ToolArray = (char **) DiskObject->do_ToolTypes;

        if (s = (char *) FindToolType(ToolArray, "PAL"))
            pal = TRUE;
        if (s = (char *) FindToolType(ToolArray, "GREY"))
            fillwindows = FALSE;
        if (s = (char *) FindToolType(ToolArray, "ICONTYPE"))
        {   if (MatchToolValue(s, "DISK"))
            {   icon.type = WBDISK - 1;
            } elif (MatchToolValue(s, "DRAWER"))
            {   icon.type = WBDRAWER - 1;
            } elif (MatchToolValue(s, "TOOL"))
            {   icon.type = WBTOOL - 1;
            } elif (MatchToolValue(s, "PROJECT"))
            {   icon.type = WBPROJECT - 1;
            } elif (MatchToolValue(s, "TRASHCAN"))
            {   icon.type = WBGARBAGE - 1;
            } elif (MatchToolValue(s, "DEVICE"))
            {   icon.type = WBDEVICE - 1;
            } elif (MatchToolValue(s, "KICKSTART"))
            {   icon.type = WBAPPICON - 1;
            } elif (MatchToolValue(s, "APPICON"))
            {   icon.type = WBAPPICON - 1;
        }   }
        if (s = (char *) FindToolType(ToolArray, "FUNCTION"))
        {   if (MatchToolValue(s, "1"))
                page = 11;
            elif (MatchToolValue(s, "2"))
                page = 21;
            elif (MatchToolValue(s, "3"))
                page = 31;
            elif (MatchToolValue(s, "4"))
                page = 41;
            elif (MatchToolValue(s, "5"))
                page = 51;
            elif (MatchToolValue(s, "6"))
                page = 61;
            elif (MatchToolValue(s, "7"))
                page = 71;
            elif (MatchToolValue(s, "8"))
                page = 81;
            elif (MatchToolValue(s, "9"))
                page = 91;
            elif (MatchToolValue(s, "10"))
                page = 101;
            elif (MatchToolValue(s, "11"))
            {   page = 111;
            } elif (MatchToolValue(s, "12"))
            {   page = 121;
        }   }
        FreeDiskObject(DiskObject);
}   }

AGLOBAL ULONG checkbreak(void)
{   struct IntuiMessage* MsgPtr;
    struct Gadget*       addr;
    ULONG                class;
    UWORD                code;

    while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
    {   class  = MsgPtr->Class;
        code   = MsgPtr->Code;
        addr   = MsgPtr->IAddress;
        GT_ReplyIMsg((struct IntuiMessage *) MsgPtr);
        switch(class)
        {
        case IDCMP_CLOSEWINDOW:
            return(2);
        break;
        case IDCMP_GADGETUP:
            if (addr == BU99_Stop)
                return(1);
        break;
        case IDCMP_VANILLAKEY:
            if (code == ESCAPE)
                return(1);
        break;
        case IDCMP_REFRESHWINDOW:
            GT_BeginRefresh(MainWindowPtr);
            GT_EndRefresh(MainWindowPtr, TRUE);
        break;
        default:
        break;
    }   }
    return(0);
}

AGLOBAL void dirasl(void)
{   struct FileRequester* ASLRqPtr;

    if (!(ASLRqPtr = AllocAslRequestTags(ASL_FileRequest, ASL_Pattern, "~(#?.info)", ASL_Window, MainWindowPtr, ASL_ExtFlags1, FIL1F_NOFILES, TAG_DONE)))
        rq("Can't create ASL request!");
    if (AslRequestTags(ASLRqPtr, ASL_Dir, asldir, ASL_Hail, "Report+ path selector", ASL_FuncFlags, FILF_PATGAD, TAG_DONE))
        if (aslresult[0])
            strcpy(aslresult, ASLRqPtr->rf_Dir);
    if (ASLRqPtr)
        FreeAslRequest(ASLRqPtr);
}

AGLOBAL void getdate(void)
{   struct DateTime DateTime;

    DateTime.dat_Format  = FORMAT_DOS;
    DateTime.dat_Flags   = NULL;
    DateTime.dat_StrDay  = weekdaystring;
    DateTime.dat_StrDate = datestring;
    DateTime.dat_StrTime = timestring;

    DateStamp(&(DateTime.dat_Stamp));
    if (!DateToStr(&DateTime))
        rq("Can't convert date!");
}

AGLOBAL void AddNameToTail(struct List* ListPtr, STRPTR name)
{   /* RKM Libraries, p. 496:
	
    "Allocate a NameNode structure, copy the given name into the
    structure, then add it [to] the...list." */

    struct NameNode* NameNodePtr;

    if (!(NameNodePtr = AllocMem(sizeof(struct NameNode), MEMF_CLEAR)))
        rq("Out of memory!");
    strcpy(NameNodePtr->nn_Data, name);
    NameNodePtr->nn_Node.ln_Name = NameNodePtr->nn_Data;
    NameNodePtr->nn_Node.ln_Type = NT_USER;
    NameNodePtr->nn_Node.ln_Pri  = 0;
    AddTail((struct List *) ListPtr, (struct Node *) NameNodePtr);
}

AGLOBAL void append(STRPTR pathname)
{   BPTR FileHandle;

    if (!(FileHandle = (BPTR) Open(pathname, MODE_READWRITE)))
        rq("Can't open file for appending!");
    Seek(FileHandle, 0, OFFSET_END);
    if (Write(FileHandle, IOBuffer, strlen(IOBuffer)) == -1)
    {   Close(FileHandle);
        rq("Can't append to file!");
    }
    if (!Close(FileHandle))
        rq("Can't close appended file!");
}

AGLOBAL ABOOL aboutloop(void)
{   struct IntuiMessage* MsgPtr;
    ABOOL                done = FALSE;
    UWORD                code, qual;
    ULONG                class;

    // processes any outstanding messages for the About... window.
    // returns TRUE if user wants to exit, FALSE otherwise.

    while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(AboutWindowPtr->UserPort))
    {   class = MsgPtr->Class;
        code  = MsgPtr->Code;
        qual  = MsgPtr->Qualifier;
        GT_ReplyIMsg(MsgPtr);

        if (class == CLOSEWINDOW)
            done = TRUE;
        elif (class == IDCMP_RAWKEY)
        {   if ((!(qual & IEQUALIFIER_REPEAT)) && code < KEYUP && (code < FIRSTQUALIFIER || code > LASTQUALIFIER))
                done = TRUE;
    }   }
    return(done);
}

MODULE struct GelsInfo* setupDisplay(void)
{   struct GelsInfo* gInfo;

    /* set up the gels system.
    ** 0x03 says: when you allocate sprites for me, don't ever use
    ** sprites zero or one. This guarantees that sprite zero, the
    ** intuition pointer, stays intact. Remember sprite one shares
    ** colors with sprite zero. */

    if (NULL != (gInfo = setupGelSys(AboutWindowPtr->RPort, 0x03)))
       return(gInfo);
    else rq("Can't set up GEL system!");
}

AGLOBAL VOID DrawGels(void)
{   Animate(&animKey, AboutWindowPtr->RPort);

    SortGList(AboutWindowPtr->RPort);   /* Put the list in order. */
    DoCollision(AboutWindowPtr->RPort); /* Collision routines may called now */
    SortGList(AboutWindowPtr->RPort);   /* Put the list in order. */

    /* Draw 'em. */
    DrawGList(AboutWindowPtr->RPort, ViewPortAddress(AboutWindowPtr));

    WaitTOF();
}

/*--------------------------------------------------------------
** setupBoing() - allocate and initialize an object that will
** display as a boing ball with orbiting sattellites.
**
** this is an animation object with four animation sequences
** (boing and three satellites). Note that the satellites all share the
** same single image data.
**
** return NULL on failure.
*/
MODULE struct AnimOb* setupBoing(void)
{   struct AnimOb*   bngOb;
    struct AnimComp* bngComp;
    struct AnimComp* satAComp;
    struct AnimComp* satBComp;
    struct AnimComp* satCComp;

    // Firstly, we allocate and initialize an AnimOb structure, then we
    // call makeSeq() for the main ball and for each satellite.

    if (NULL != (bngOb = AllocMem((LONG)sizeof(struct AnimOb), MEMF_CLEAR)))
    {   bngOb->NextOb           = NULL;
	bngOb->PrevOb		= NULL;
	bngOb->Clock		= 0;
        bngOb->AnY              = ( 97 << ANFRACSIZE);
        bngOb->AnX              = (  3 << ANFRACSIZE);
	bngOb->AnOldY		= bngOb->AnY;
	bngOb->AnOldX		= bngOb->AnX;
        bngOb->YVel             = 0;
        bngOb->XVel             = 1 << ANFRACSIZE;
	bngOb->YAccel		= 0;
	bngOb->XAccel		= 0;
	bngOb->RingYTrans	= BNG3RINGY << ANFRACSIZE;
	bngOb->RingXTrans	= BNG3RINGX << ANFRACSIZE;
	bngOb->AnimORoutine	= bounceORoutine;
	bngOb->AUserExt		= 0;

        newBoingBob.nb_DBuf     = 0;
        newBoingSeq.nas_HeadOb  = bngOb;

        satACRoutines[4]        = goInFrontOfHead;
        satACRoutines[12]       = goBehindHead;
        satBCRoutines[8]        = goInFrontOfHead;
        satBCRoutines[0]        = goBehindHead;
        satCCRoutines[4]        = goInFrontOfHead;
        satCCRoutines[12]       = goBehindHead;

        newSatABob.nb_DBuf      = 0;
        newSatBBob.nb_DBuf      = 0;
        newSatCBob.nb_DBuf      = 0;
        newSatASeq.nas_HeadOb   = bngOb;
        newSatBSeq.nas_HeadOb   = bngOb;
        newSatCSeq.nas_HeadOb   = bngOb;

	if (NULL != (bngComp = makeSeq(&newBoingBob, &newBoingSeq)))
        {   bngComp->Flags |= RINGTRIGGER;
            bngOb->HeadComp = bngComp;

            if (NULL != (satAComp = makeSeq(&newSatABob, &newSatASeq)))
            {   bngComp->AnimBob->Before = satAComp->AnimBob;
                satAComp->AnimBob->After = bngComp->AnimBob;

                if (NULL != (satBComp = makeSeq(&newSatBBob, &newSatBSeq)))
                {   satAComp->AnimBob->Before = satBComp->AnimBob;
                    satBComp->AnimBob->After = satAComp->AnimBob;

                    if (NULL != (satCComp = makeSeq(&newSatCBob, &newSatCSeq)))
                    {   satBComp->AnimBob->Before = satCComp->AnimBob;
                        satCComp->AnimBob->After = satBComp->AnimBob;

                        bngComp->NextComp  = satAComp;
                        bngComp->PrevComp  = NULL;

                        satAComp->NextComp = satBComp;
                        satAComp->PrevComp = bngComp;

                        satBComp->NextComp = satCComp;
                        satBComp->PrevComp = satAComp;

                        satCComp->NextComp = NULL;
                        satCComp->PrevComp = satBComp;

                        return(bngOb);
                    }
                    freeSeq(satBComp,RBMDEPTH);
                }
                freeSeq(satAComp,RBMDEPTH);
            }
            freeSeq(bngComp,RBMDEPTH);
        }
	FreeMem(bngOb, (LONG)sizeof(struct AnimOb));
    }
    return(NULL);
}

/*------------------------------------------------------
** This ORoutine makes the Object Bounce off Borders. */

WORD bounceORoutine(struct AnimOb* anOb)
{   SHORT X = anOb->AnX >> ANFRACSIZE;

    if (((X                                                     < 3              ) && (anOb->XVel < 0)) ||
        ((X + (anOb->HeadComp->AnimBob->BobVSprite->Width << 4) > ABOUTXPIXEL - 3) && (anOb->XVel > 0)))
       {   anOb->XVel = -(anOb->XVel);
       }

    return(0);
}

/*--------------------------------------------------------------
** This CRoutine rearranges Bob Before and After pointers in a
** way that makes the Component passed look like it is in front
** of its' head component.
** 
** Used for Boing satelittes.
** 
** So that they go in front of AND behind the boing ball.
*/
MODULE WORD goInFrontOfHead(struct AnimComp *aComp)
{
/* close up hole */
if (aComp->AnimBob->Before != NULL)
	aComp->AnimBob->Before->After = aComp->AnimBob->After;
if (aComp->AnimBob->After != NULL)
	aComp->AnimBob->After->Before = aComp->AnimBob->Before;

/* reinsert */
aComp->AnimBob->Before = aComp->HeadOb->HeadComp->AnimBob->Before;
aComp->AnimBob->After = aComp->HeadOb->HeadComp->AnimBob;
if (aComp->AnimBob->Before != NULL)
	aComp->AnimBob->Before->After = aComp->AnimBob;
aComp->HeadOb->HeadComp->AnimBob->Before = aComp->AnimBob;

return(0);
}

/*--------------------------------------------------------------
** This CRoutine rearranges Bob Before and After pointers in a
** way that makes the Component passed look like it is behind
** its' head component.
*/
MODULE WORD goBehindHead(struct AnimComp *aComp)
{
if (aComp->AnimBob->Before != NULL)
	aComp->AnimBob->Before->After = aComp->AnimBob->After;
if (aComp->AnimBob->After != NULL)
	aComp->AnimBob->After->Before = aComp->AnimBob->Before;

aComp->AnimBob->After = aComp->HeadOb->HeadComp->AnimBob->After;
aComp->AnimBob->Before = aComp->HeadOb->HeadComp->AnimBob;
if (aComp->AnimBob->After != NULL)
	aComp->AnimBob->After->Before = aComp->AnimBob;
aComp->HeadOb->HeadComp->AnimBob->After = aComp->AnimBob;

return(0);
}

AGLOBAL void boingball(void)
{   if (NULL != (gInfo = setupDisplay()))
    {   InitAnimate(&animKey);

        if (NULL != (boingOb = setupBoing()))
            AddAnimOb(boingOb, &animKey, AboutWindowPtr->RPort);
}   }
AGLOBAL void unboingball(void)
{   freeOb(boingOb, RBMDEPTH);
    cleanupGelSys(gInfo, AboutWindowPtr->RPort);
}

AGLOBAL void double_init(void)
{   if (!(ead = AllocMem(2048, MEMF_CLEAR | MEMF_PUBLIC)))
    {   rq("Out of memory!");
}   }

AGLOBAL void fliplog(ABOOL keyboard)
{   if (keyboard)
    {   if (CB99_Log->Flags & GFLG_SELECTED)
        {   shared.log = FALSE;
        } else
        {   shared.log = TRUE;
    }   }
    else
    {   if (CB99_Log->Flags & GFLG_SELECTED)
        {   shared.log = TRUE;
        } else
        {   shared.log = FALSE;
    }   }

    if (!shared.log)
    {   GT_SetGadgetAttrs
        (   ST99_Output,
            MainWindowPtr, NULL,
            GA_Disabled, TRUE,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   BU99_OutputASL,
            MainWindowPtr, NULL,
            GA_Disabled, TRUE,
            TAG_DONE
        );
    } else
    {   GT_SetGadgetAttrs
        (   ST99_Output,
            MainWindowPtr, NULL,
            GA_Disabled, FALSE,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   BU99_OutputASL,
            MainWindowPtr, NULL,
            GA_Disabled, FALSE,
            TAG_DONE
        );
    }
    GT_SetGadgetAttrs
    (   CB99_Log,
        MainWindowPtr, NULL,
        GTCB_Checked, shared.log,
        TAG_DONE
    );
}

AGLOBAL void outputasl(void)
{   asl();
    GT_SetGadgetAttrs
    (   ST99_Output,
        MainWindowPtr,
        NULL,
        GTST_String, aslresult,
        TAG_DONE
    );
}
AGLOBAL void outputstring(void)
{   strcpy
    (   shared.output,
        ((struct StringInfo *) ST99_Output->SpecialInfo)->Buffer
    );
}
AGLOBAL void drawgadgets(WORD gadgets)
{   if (!PrevGadPtr)
        rq("Can't create GadTools gadgets!");
    AddGList(MainWindowPtr, BU99_Right, (UWORD) ~0, gadgets, NULL);
    RefreshGList(BU99_Right, MainWindowPtr, NULL, -1);
    GT_RefreshWindow(MainWindowPtr, NULL);
}

AGLOBAL void parse(STRPTR terminator)
{   ABOOL done = FALSE;
    ULONG suboffset;

    suboffset = offset;
    while (!done)
    {   string[offset - suboffset] = IOBuffer[offset];
        if (!(strncmp(&(IOBuffer[offset]), terminator, strlen(terminator))))
        {   string[offset - suboffset] = 0;
            offset += strlen(terminator);
            done = TRUE;
        } elif (offset > strlen(IOBuffer))
        {   /* failure */
            string[0] = 0;
            done = TRUE;
        } else offset++;
}   }

AGLOBAL void parsetoend(void)
{   ABOOL done      = FALSE;
    ULONG suboffset = 0;

    while (!done)
    {   string[suboffset] = IOBuffer[offset];
        if (offset > strlen(IOBuffer))
        {   /* EOF */
            string[suboffset] = 0;
            done = TRUE;
        } else
        {   offset++;
            suboffset++;
}   }   }

AGLOBAL void saveasl(STRPTR message)
{   struct FileRequester* ASLRqPtr;
    TEXT                  tempstring[VLONGFIELD + 1];

    strcpy(tempstring, "Report+: ");
    strcat(tempstring, message);

    if (!(ASLRqPtr = AllocAslRequestTags(ASL_FileRequest, ASL_Pattern, "~(#?.info)", ASL_Window, MainWindowPtr, TAG_DONE)))
        rq("Can't create ASL request!");
    if
    (   AslRequestTags(ASLRqPtr, ASL_Dir, asldir, ASL_Hail, tempstring, ASL_FuncFlags, FILF_PATGAD | FILF_SAVE, TAG_DONE)
     && *(ASLRqPtr->rf_File) != 0
    )
    {   strcpy(asldir, ASLRqPtr->rf_Dir);
        strcpy(aslresult, ASLRqPtr->rf_Dir);
        if (!AddPart(aslresult, ASLRqPtr->rf_File, VLONGFIELD))
            rq("Can't add filename to pathname!");
    } else
    {   strcpy(asldir, "");
        strcpy(aslresult, "");
    }
    if (ASLRqPtr) // will always be true
        FreeAslRequest(ASLRqPtr);
}

AGLOBAL void handlemenus(UWORD code)
{   // AUTO struct MenuItem* ItemPtr;
       AUTO struct Lock*     LockPtr;

    if (code != MENUNULL) // while (code != MENUNULL)
    {   // ItemPtr = ItemAddress(MenuPtr, code);
        switch (MENUNUM(code))
        {
        case MN_PROJECT:
            switch (ITEMNUM(code))
            {
            case IN_NEW:
                if (page == 11)
                    newreport(TRUE);
                elif (page == 21)
                    newaminet(TRUE);
                elif (page == 41)
                    newautodoc(TRUE);
                elif (page == 111)
                    newagdb(TRUE);
            break;
            case IN_OPEN:
                if (page == 11)
                    openreport();
                elif (page == 21)
                    openaminet();
                elif (page == 41)
                    openautodoc();
                elif (page == 111)
                    openagdb();
            break;
            case IN_SAVE:
                if (page == 11)
                    savereport(FALSE);
                elif (page == 21)
                    saveaminet(FALSE);
                elif (page == 41)
                    saveautodoc(FALSE);
                elif (page == 111)
                    saveagdb(FALSE);
            break;
            case IN_SAVEAS:
                if (page == 11)
                    savereport(TRUE);
                elif (page == 21)
                    saveaminet(TRUE);
                elif (page == 41)
                    saveautodoc(TRUE);
                elif (page == 111)
                    saveagdb(TRUE);
            break;
            case IN_QUIT:
                cleanexit(EXIT_SUCCESS);
            break;
            default:
            break;
            }
        break;
        case MN_HELP:
            switch (ITEMNUM(code))
            {
            case IN_ABOUT:
                helpabout();
            break;
            case IN_MANUAL:
                GetProgramDir(); /* never UnLock() the returned lock */
                if (SystemTagList
                (   "SYS:Utilities/MultiView ReportPlus.guide",
                    (struct TagItem const *) (SYS_Input,  LockPtr,
                    SYS_Output, NULL,
                    SYS_Asynch, TRUE,
                    TAG_DONE)
                ) == -1)
                    DisplayBeep(ScreenPtr);
                elif (pal)
                    ScreenToFront(ScreenPtr);
            break;
            default:
            break;
            }
        break;
        default:
        break;
        }
        /* Doing things the above way disables multi-selection,
        but prevents `endless selection'.
        code = ItemPtr->NextSelect; */
}   }

AGLOBAL void lockscreen(void)
{   if (!pal)
    {   if (!(ScreenPtr = LockPubScreen(NULL)))
            rq("Can't lock default public screen!");
}   }
AGLOBAL void unlockscreen(void)
{   if (!pal && ScreenPtr)
    {   UnlockPubScreen(NULL, ScreenPtr);
        ScreenPtr = NULL;
}   }

AGLOBAL void getfillcolour(void)
{   if (fillwindows)
    {   lockscreen();
        fillcolour = FindColor
        (   ScreenPtr->ViewPort.ColorMap,
            0x99999999, // red
            0x99999999, // green
            0xFFFFFFFF, // blue
           -1
        );
        unlockscreen();
    } else fillcolour = 0;
}
