#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <libraries/gadtools.h>
#include <dos/dos.h>

#include <stdlib.h>
#include "amigan.h"

MODULE ULONG               offset;
IMPORT ULONG               elements; // for ReAction texteditor.gadget
IMPORT STRPTR              textBuffer[MAXELEMENTS + 1];
IMPORT TEXT                aslresult[MEDFIELD + 1];
IMPORT TEXT                weekdaystring[10],
                           datestring[10],
                           timestring[9];
IMPORT struct SharedStruct shared;
IMPORT struct NewGadget    Gadget;
IMPORT struct Gadget      *BU99_Left,
                          *BU99_Right,
                          *ST99_Output,
                          *BU99_OutputASL,
                          *GListPtr,
                          *PrevGadPtr;
IMPORT ULONG               wbval;
IMPORT TEXT                IOBuffer[LONGESTFIELD + 1];
IMPORT SBYTE               page;
IMPORT ABOOL               certified;

#define SUBSYSTEMS 127

MODULE TEXT                string[VLONGFIELD + 1];
MODULE struct List*        SubsystemListPtr = NULL;
MODULE struct
{   TEXT    friendly[33], unfriendly[33];
} subsystems[SUBSYSTEMS + 1] =
{       {       "Worm Wars",                    "wormwars"        },
        {       "Workbench",                    "workbench"       },
        {       "Wack",                         "wack"            },
        {       "utility.library",              "utility.library" },
        {       "Utilities/ programs",          "util.command"    },
        {       "User manuals",                 "userdocs"        },
        {       "Unsure",                       ""                },
        {       "UNIX",                         "unix"            },
        {       "trackdisk.device",             "trackdisk"       },
        {       "Tools/ programs",              "tools"           },
        {       "ToolMaker",                    "toolmaker"       },
        {       "timer.device",                 "timer.device"    },
        {       "TCP/IP",                       "as225"           },
        {       "System/ programs",             "system.command"  },
        {       "Startup",                      "startup"         },
        {       "Shell",                        "shell"           },
        {       "serial.device",                "serial.device"   },
        {       "SCSI.device",                  "scsi.device"     },
        {       "Scripts",                      "script"          },
        {       "SANA-2",                       "sana2"           },
        {       "ROMWack",                      "wack"            },
        {       "ROM Kernel Manuals",           "rkm"             },
        {       "Resources",                    "resource"        },
        {       "Report+",                      "report+"         },
        {       "realtime",                     "realtime"        },
        {       "ramlib",                       "ramlib"          },
        {       "RAM-Handler",                  "ram-handler"     },
        {       "QUEUE-Handler",                "queue-handler"   },
        {       "Printer drivers",              "printer.driver"  },
        {       "printer.device",               "printer.device"  },
        {       "Preferences",                  "preferences"     },
        {       "potgo.resource",               "potgo.resource"  },
        {       "PORT-Handler",                 "port-handler"    },
        {       "PCMCIA",                       "creditcard"      },
        {       "parallel.device",              "parallel.device" },
        {       "nonvolatile",                  "nonvolatile"     },
        {       "MultiView",                    "multiview"       },
        {       "Monitors",                     "monitors"        },
        {       "MicroEMACS",                   "microemacs"      },
        {       "Maths: IEEE Dbl Prcsn",        "mathieeedoub"    },
        {       "Maths: IEEE Sngl Prcsn",       "mathieeesing"    },
        {       "Maths: IEEE",                  "mathieee"        },
        {       "Maths: FFP",                   "mathffp"         },
        {       "lowlevel.library",             "lowlevel"        },
        {       "locale.library",               "locale.library"  },
        {       "layers.library",               "layers"          },
        {       "Keymaps",                      "keymaps"         },
        {       "keymap.library",               "keymap"          },
        {       "Keyboard",                     "keyboard"        },
        {       "IPrefs",                       "iprefs"          },
        {       "Intuition.library",            "intuition"       },
        {       "IntelliFont",                  "fountain"        },
        {       "Installer",                    "installer"       },
        {       "input.device",                 "input.device"    },
        {       "IFFParse.library",             "iffparse"        },
        {       "IDE.device",                   "ide.device"      },
        {       "IconEdit",                     "iconedit"        },
        {       "icon.library",                 "icon.library"    },
        {       "HDToolBox",                    "hdtoolbox"       },
        {       "HDBackup",                     "hdbackup"        },
        {       "Hardware",                     "hardware"        },
        {       "Graphics",                     "graphics"        },
        {       "Genlock",                      "genlock"         },
        {       "gameport.device",              "gameport"        },
        {       "GadTools.library",             "gadtools"        },
        {       "gadget.classes",               "gadget.classes"  },
        {       "Fountain",                     "fountain"        },
        {       "Fonts",                        "fonts"           },
        {       "filesystem",                   "filesystem"      },
        {       "filesystem.resource",          "filesysres"      },
        {       "expansion.library",            "expansion"       },
        {       "Exec.library",                 "exec"            },
        {       "Envoy",                        "envoy"           },
        {       "Early Startup Control",        "bootmenu"        },
        {       "DOS.library",                  "dos.library"     },
        {       "diskfont.library",             "diskfont"        },
        {       "disk.resource",                "disk.resource"   },
        {       "Developer support",            "devsupport"      },
        {       "debug.lib",                    "debug.lib"       },
        {       "Datatypes",                    "datatypes"       },
        {       "Custom chipset",               "custom.chips"    },
        {       "console.device",               "console.device"  },
        {       "CON-Handler",                  "con-handler"     },
        {       "Commodities",                  "commodities"     },
        {       "clipboard.device",             "clipboard"       },
        {       "CLI",                          "shell"           },
        {       "CIA.resource",                 "cia.resource"    },
        {       "cdui",                         "cdui"            },
        {       "CDTV.device",                  "cdtv.device"     },
        {       "CDTV",                         "cdtv"            },
        {       "C: programs",                  "cdos.command"    },
        {       "CDFileSystem",                 "cdfilesystem"    },
        {       "CD.device",                    "cd.device"       },
        {       "CD32 hardware",                "cdgs"            },
        {       "bullet.library",               "bullet"          },
        {       "BRU",                          "bru"             },
        {       "BridgeBoard",                  "bridgeboard"     },
        {       "Bootstrap",                    "strap"           },
        {       "Battery-backed memory",        "battmem"         },
        {       "Battery-backed clock",         "battclock"       },
        {       "AUTOCONFIG",                   "autoconfig"      },
        {       "audio.device",                 "audio.device"    },
        {       "ASL.library",                  "asl.library"     },
        {       "AS225",                        "as225"           },
        {       "Art",                          "art"             },
        {       "ARexx",                        "arexx"           },
        {       "AppShell",                     "appshell"        },
        {       "AmigaVision",                  "amigavision"     },
        {       "AmigaTerm",                    "amigaterm"       },
        {       "AmigaGuide",                   "amigaguide"      },
        {       "amiga.lib",                    "amiga.lib"       },
        {       "ALink",                        "alink"           },
        {       "AGA chipset",                  "aa.chips"        },
        {       "AmigaBASIC",                   "AmigaBasic"      },
        {       "A4091",                        "A4091"           },
        {       "A3000",                        "A3000"           },
        {       "A2630",                        "A2630"           },
        {       "A2620",                        "A2620"           },
        {       "A2410",                        "A2410"           },
        {       "A2300",                        "A2300"           },
        {       "A2232",                        "A2232"           },
        {       "A2091",                        "A2091"           },
        {       "A2090A",                       "A2090.A2090A"    },
        {       "A2090",                        "A2090.A2090A"    },
        {       "A2065",                        "A2065"           },
        {       "A2013",                        "A2013"           },
        {       "A590",                         "A2091.A590"      },
        {       "3D Look",                      "new.look"        }
};

MODULE void refreshpv(void);
MODULE void parse(STRPTR terminator);
MODULE void AddNameToHead(struct List* ListPtr, STRPTR name);

AGLOBAL struct ReportStruct report =
{   1, 0, 0, 1, 4, 0, 0, 0,
    "2", "0", "", "", "", "", "", "", "", "",
    "", "", "", "", "", "", "", "", "", "", "", "", "",
};

MODULE STRPTR RadioOptions1[4] =
{	(STRPTR) "System Software or Hardware Bug Report",
 	(STRPTR) "Third Party Product Compatibility Report",
 	(STRPTR) "Enhancement Request",
	NULL
};
MODULE STRPTR RadioOptions2[4] =
{	(STRPTR) "Crashes, hangs or corrupts data",
	(STRPTR) "Behaves incorrectly",
	(STRPTR) "Cosmetic problem",
	NULL
};
MODULE STRPTR RadioOptions3[5] =
{	(STRPTR) "Crashes, hangs or corrupts data",
	(STRPTR) "Behaves incorrectly",
	(STRPTR) "Cosmetic problem",
	(STRPTR) "Works correctly",
	NULL
};
MODULE STRPTR AgnusOptions[6] =
{	(STRPTR) "AGA",
	(STRPTR) "ECS PAL",
	(STRPTR) "ECS NTSC",
	(STRPTR) "OCS PAL",
	(STRPTR) "OCS NTSC",
	NULL
};
MODULE STRPTR DeniseOptions[4] =
{	(STRPTR) "AGA",
	(STRPTR) "ECS",
	(STRPTR) "OCS",
	NULL
};
#define CPUS 5
MODULE STRPTR CPUOptions[CPUS + 2] =
{	(STRPTR) "68000",
	(STRPTR) "68020",
	(STRPTR) "68030",
	(STRPTR) "68040",
	(STRPTR) "68060",
	(STRPTR) "PowerPC",
	NULL
};
#define MODELS 13
MODULE STRPTR ModelOptions[MODELS + 2] =
{	(STRPTR) "A500",
	(STRPTR) "A500+",
	(STRPTR) "A600",
	(STRPTR) "A1000",
	(STRPTR) "A1200",
	(STRPTR) "A1500",
	(STRPTR) "A2000",
	(STRPTR) "A2500",
	(STRPTR) "A3000",
	(STRPTR) "A4000",
	(STRPTR) "CDTV",
	(STRPTR) "CD32",
	(STRPTR) "DraCo",
	(STRPTR) "Emulator",
	NULL
};
IMPORT struct Window*  MainWindowPtr;
IMPORT struct Gadget  *MX11_Type               = NULL,
                      *ST11_Summary            = NULL,
                      *BU12_PathnameASL        = NULL,
                      *LV12_Subsystem          = NULL,
                      *MX12_Severity           = NULL,
                      *ST12_Debug              = NULL,
                      *ST12_KS                 = NULL,
                      *ST12_WB                 = NULL,
                      *ST12_Pathname           = NULL,
                      *ST12_Version            = NULL,
                      *TE12_3rdLabel           = NULL,
                      *ST12_3rdName            = NULL,
                      *ST12_3rdVer             = NULL,
                      *ST12_3rdManuf           = NULL,
                      *ST13_Company            = NULL,
                      *ST13_Developer          = NULL,
                      *ST13_EMail              = NULL,
                      *ST13_FirstName          = NULL,
                      *ST13_LastName           = NULL,
                      *ST13_Phone              = NULL,
                      *MX14_Model              = NULL,
                      *TE14_ModelText          = NULL,
                      *MX14_Agnus              = NULL,
                      *TE14_AgnusText          = NULL,
                      *MX14_CPU                = NULL,
                      *TE14_CPUText            = NULL,
                      *MX14_Denise             = NULL,
                      *TE14_DeniseText         = NULL,
                      *IN14_Floppies           = NULL,
                      *ST14_Chip               = NULL,
                      *TE14_ChipText           = NULL,
                      *ST14_Fast               = NULL,
                      *TE14_FastText           = NULL,
                      *ST14_Hard               = NULL,
                      *ST14_Expansion          = NULL;

AGLOBAL void report1(void)
{   /* PAGE 11 ************************************************************ */

    navigate();

    /* type */
    setgadget(152, 50, 0, 0, NULL, PLACETEXT_RIGHT);
    MX11_Type = PrevGadPtr = (struct Gadget *) CreateGadget
    (   MX_KIND,
        PrevGadPtr,
        &Gadget,
        GTMX_Labels, &RadioOptions1,
        GTMX_Active, report.type,
        TAG_DONE
    );

    /* summary */
    setgadget(64, 30, 512, 12, "_Summary:", PLACETEXT_ABOVE);
    ST11_Summary = PrevGadPtr = (struct Gadget *) CreateGadget
    (   STRING_KIND,
        PrevGadPtr,
        &Gadget,
        STRINGA_Justification, GACT_STRINGCENTER,
        GTST_String, &(report.subject),
        GTST_MaxChars, LONGFIELD,
        GA_TabCycle, TRUE,
        GT_Underscore, '_',
        TAG_DONE
    );

    /* output */
    if (!(shared.output[0]))
        strcpy(shared.output, "RAM:Report.txt");
    setgadget(242, 88, 240, 12, "_Output pathname:", NULL);
    ST99_Output = PrevGadPtr = (struct Gadget *) CreateGadget
    (   STRING_KIND,
        PrevGadPtr,
        &Gadget,
        GTST_String, &(shared.output),
        GTST_MaxChars, LONGFIELD,
        GA_TabCycle, TRUE,
        GT_Underscore, '_',
        TAG_DONE
    );
    /* output... */
    setgadget(484, 88, 28, 12, "_...", NULL);
    BU99_OutputASL = PrevGadPtr = (struct Gadget *) CreateGadget
    (   BUTTON_KIND,
        PrevGadPtr,
        &Gadget,
        GT_Underscore, '_',
        TAG_DONE
    );

    newwindow
    (   640, REPORT1HEIGHT,
        "Report+: Report Details 1",
        BUTTONIDCMP | MXIDCMP | STRINGIDCMP
    );
    ActivateGadget(ST11_Summary, MainWindowPtr, NULL);

    loop();
    strcpy
    (   report.subject,
        ((struct StringInfo *) ST11_Summary->SpecialInfo)->Buffer
    );
    strcpy
    (   shared.output,
        ((struct StringInfo *) ST99_Output->SpecialInfo)->Buffer
    );
    closewindow();
}

AGLOBAL void report2(void)
{  /* PAGE 12 ************************************************************ */

    navigate();

    if (report.type == BUG || report.type == ENH)
    {   setgadget(16, 28, 174, 130, "Subsystem:", NULL);
        LV12_Subsystem = PrevGadPtr = (struct Gadget *) CreateGadget
        (   LISTVIEW_KIND,
            PrevGadPtr,
            &Gadget,
            GTLV_Labels, SubsystemListPtr,
            GTLV_ShowSelected, NULL,
            GTLV_Selected, report.subsystem,
            GT_Underscore, '_',
            TAG_DONE
        );
    } else /* assumes report.type == COM */
    {   /* 3rd party product */
        setgadget(160, 27, 100, 1, "3rd Party Product:", PLACETEXT_ABOVE);
        TE12_3rdLabel = PrevGadPtr = (struct Gadget *) CreateGadget
        (   TEXT_KIND,
            PrevGadPtr,
            &Gadget,
            TAG_DONE
        );
        /* 3rd party product name */
        setgadget(160, 28, 100, 12, "N_ame:", NULL);
        ST12_3rdName = PrevGadPtr = (struct Gadget *) CreateGadget
        (   STRING_KIND,
            PrevGadPtr,
            &Gadget,
            GTST_String, &(report.thirdname),
            GTST_MaxChars, MEDFIELD,
            GA_TabCycle, TRUE,
            GT_Underscore, '_',
            TAG_DONE
        );
        /* 3rd party product version */
        setgadget(160, 40, 100, 12, "_Version:", NULL);
        ST12_3rdVer = PrevGadPtr = (struct Gadget *) CreateGadget
        (   STRING_KIND,
            PrevGadPtr,
            &Gadget,
            GTST_String, &(report.thirdver),
            GTST_MaxChars, MEDFIELD,
            GA_TabCycle, TRUE,
            GT_Underscore, '_',
            TAG_DONE
        );
        /* 3rd party product manufacturer */
        setgadget(160, 52, 100, 12, "_Manufacturer:", NULL);
        ST12_3rdManuf = PrevGadPtr = (struct Gadget *) CreateGadget
        (   STRING_KIND,
            PrevGadPtr,
            &Gadget,
            GTST_String, &(report.thirdmanuf),
            GTST_MaxChars, MEDFIELD,
            GA_TabCycle, TRUE,
            GT_Underscore, '_',
            TAG_DONE
        );
    }

    if (report.type == BUG || report.type == COM)
    {   /* debug tools and wedges */
        setgadget(400, 69, 196, 12, "_Debug tools and wedges:", NULL);
        ST12_Debug = PrevGadPtr = (struct Gadget *) CreateGadget
        (   STRING_KIND,
            PrevGadPtr,
            &Gadget,
            GTST_String, &(report.debug),
            GTST_MaxChars, LONGFIELD,
            GA_TabCycle, TRUE,
            GT_Underscore, '_',
            TAG_DONE
        );
        /* classification */
        setgadget(308, 24, 0, 0, NULL, PLACETEXT_RIGHT);
        if (report.type == BUG)
        {   if (report.severity == 3)
            {   report.severity = 0;
            }
            MX12_Severity = PrevGadPtr = (struct Gadget *) CreateGadget
            (   MX_KIND,
                PrevGadPtr,
                &Gadget,
                GTMX_Labels, &RadioOptions2,
                GTMX_Active, report.severity,
                TAG_DONE
            );
            /* program version */
            setgadget(400, 131, 196, 12, "Program pathname:", NULL);
            ST12_Pathname = PrevGadPtr = (struct Gadget *) CreateGadget
            (   STRING_KIND,
                PrevGadPtr,
                &Gadget,
                GTST_String, &(report.pp),
                GTST_MaxChars, LONGFIELD,
                GA_TabCycle, TRUE,
                TAG_DONE
            );
            /* program... */
            setgadget(598, 131, 28, 12, "...", NULL);
            BU12_PathnameASL = PrevGadPtr = (struct Gadget *) CreateGadget
            (   BUTTON_KIND,
                PrevGadPtr,
                &Gadget,
                TAG_DONE
            );
            setgadget(400, 143, 196, 12, "Program version:", NULL);
            ST12_Version = PrevGadPtr = (struct Gadget *) CreateGadget
            (   STRING_KIND,
                PrevGadPtr,
                &Gadget,
                GTST_String, &(report.pv),
                GTST_MaxChars, LONGFIELD,
                GA_TabCycle, TRUE,
                TAG_DONE
            );
        } else /* assumes (report.type == COM) */
        {   MX12_Severity = PrevGadPtr = (struct Gadget *) CreateGadget
            (   MX_KIND,
                PrevGadPtr,
                &Gadget,
                GTMX_Labels, &RadioOptions3,
                GTMX_Active, report.severity,
                TAG_DONE
            );
	}

        /* kickstart version */
        if (report.ks[0] == 0)
            if (GetVar("Kickstart", &(report.ks), 6, NULL) == -1)
                report.ks[0] = 0;
        setgadget(400, 93, 60, 12, "_Kickstart version:", NULL);
        ST12_KS = PrevGadPtr = (struct Gadget *) CreateGadget
        (   STRING_KIND,
            PrevGadPtr,
            &Gadget,
            GTST_String, &(report.ks),
            GTST_MaxChars, 6,
            GA_TabCycle, TRUE,
            STRINGA_Justification, GACT_STRINGRIGHT,
            TAG_DONE
        );

        /* workbench version */
        if (report.wb[0] == 0)
            if (GetVar("Workbench", &(report.wb), 6, NULL) == -1)
                report.wb[0] = 0;
        setgadget(400, 105, 60, 12, "_Workbench version:", NULL);
        ST12_WB = PrevGadPtr = (struct Gadget *) CreateGadget
        (   STRING_KIND,
            PrevGadPtr,
            &Gadget,
            GTST_String, &(report.wb),
            GTST_MaxChars, 6,
            GA_TabCycle, TRUE,
            STRINGA_Justification, GACT_STRINGRIGHT,
            TAG_DONE
        );
    }

    newwindow
    (   640, REPORT2HEIGHT,
        "Report+: Report Details 2",
        BUTTONIDCMP | LISTVIEWIDCMP | MXIDCMP | STRINGIDCMP
    );
    if (report.type != ENH)
        ActivateGadget(ST12_KS, MainWindowPtr, NULL);

    loop();
    if (report.type == COM)
    {   strcpy
        (   report.thirdver,
            ((struct StringInfo *) ST12_3rdVer->SpecialInfo)->Buffer
        );
        strcpy
        (   report.thirdname,
            ((struct StringInfo *) ST12_3rdName->SpecialInfo)->Buffer
        );
        strcpy
        (   report.thirdmanuf,
            ((struct StringInfo *) ST12_3rdManuf->SpecialInfo)->Buffer
        );
    } elif (report.type == BUG)
    {   strcpy
        (   report.pp,
            ((struct StringInfo *) ST12_Pathname->SpecialInfo)->Buffer
        );
        strcpy
        (   report.pv,
            ((struct StringInfo *) ST12_Version->SpecialInfo)->Buffer
        );
    }
    if (report.type != ENH)
    {   strcpy
        (   report.ks,
            ((struct StringInfo *) ST12_KS->SpecialInfo)->Buffer
        );
        strcpy
        (   report.wb,
            ((struct StringInfo *) ST12_WB->SpecialInfo)->Buffer
        );
        strcpy
        (   report.debug,
            ((struct StringInfo *) ST12_Debug->SpecialInfo)->Buffer
        );
    }
    closewindow();
}

AGLOBAL void report3(void)
{   navigate();
    newwindow
    (   640, REPORT3HEIGHT,
        "Report+: Finished Bug Report",
        BUTTONIDCMP
    );

/*      # Subject: <subject><LF>
        # Type: bug|compat|enhancement<LF>
1,3     # Subsystem: <subsystem><LF>
2       # ProductName: <name> (vers=<version>)
2       # ProductInfo: :<manufacturer>:
        # Severity: a|b|c|ok|e
1       # Release: KS=<version>,WB=<version>,Program=<version>
2       # Release: KS=<version>,WB=<version>
        # Date: <weekday> dd-Mon-yy hh:mm:ss
        # Refer: <refer>
        # Path: <path>
        # ReferID: <referid>
        # Config: <config>
1,2a-c	### BRIEF BUG DESCRIPTION:
1,2a-c	### BUG GENERATION PROCEDURE OR EXAMPLE:
1,2     ### ALSO RUNNING:
        <debug>
1,2     ### IF THIS WORKS DIFFERENTLY ON OTHER VERSIONS OR HARDWARE,
        EXPLAIN:
2a-c	### WHAT DEVELOPER IS DOING IN THAT AREA OF SW OR HW:	
1,2a-c	### RELATED PROBLEMS:
3       ### ENHANCEMENT REQUEST: */

    if (wbval >= 44)
        launcheditor();

	strcpy(IOBuffer, "# Subject: ");
	strcat(IOBuffer, report.subject);
	strcat(IOBuffer, "\n# Type: ");
	if (report.type == BUG)
		strcat(IOBuffer, "bug");
	elif (report.type == COM)
		strcat(IOBuffer, "compat");
	else /* assumes (report.type == ENH) */
		strcat(IOBuffer, "enhancement");
	strcat(IOBuffer, "\n");
	if (report.type == BUG || report.type == ENH)
	{	strcat(IOBuffer, "# Subsystem: ");
		strcat(IOBuffer, subsystems[SUBSYSTEMS - report.subsystem].unfriendly);
		strcat(IOBuffer, "\n");
	} else
	{	strcat(IOBuffer, "# ProductName: ");
		strcat(IOBuffer, report.thirdname);
		strcat(IOBuffer, " (vers=");
		strcat(IOBuffer, report.thirdver);
		strcat(IOBuffer, ")\n# ProductInfo: :");
		strcat(IOBuffer, report.thirdmanuf);
		strcat(IOBuffer, ":\n");
	}
	strcat(IOBuffer, "# Severity: ");
	if (report.type == ENH)
		strcat(IOBuffer, "e");
	elif (report.severity == 0)
		strcat(IOBuffer, "a");
	elif (report.severity == 1)
		strcat(IOBuffer, "b");
	elif (report.severity == 2)
		strcat(IOBuffer, "c");
	else /* assumes report.severity == 3 */
		strcat(IOBuffer, "ok");
	strcat(IOBuffer, "\n");
	if (report.type == BUG || report.type == COM)
	{	strcat(IOBuffer, "# Release: KS=");
		strcat(IOBuffer, report.ks);
		strcat(IOBuffer, ",WB=");
		strcat(IOBuffer, report.wb);
		if (report.type == BUG)
		{	strcat(IOBuffer, ",Program=");
			strcat(IOBuffer, report.pv);
		}
		strcat(IOBuffer, "\n");
	}

        getdate();
        strcat(IOBuffer, "# Date: ");
	strcat(IOBuffer, weekdaystring);
	strcat(IOBuffer, " ");
	strcat(IOBuffer, datestring);
	strcat(IOBuffer, " ");
	strcat(IOBuffer, timestring);
	strcat(IOBuffer, "\n");
	strcat(IOBuffer, report.refer);
	strcat(IOBuffer, report.path);
	strcat(IOBuffer, report.referid);
	strcat(IOBuffer, report.config);
        strcat(IOBuffer, "\n");
	if (report.type == BUG || (report.type == COM && report.severity != 3))
        {   strcat
            (   IOBuffer,
                "### BRIEF BUG DESCRIPTION:\n"
            );
            if (wbval >= 44)
                strcat(IOBuffer, textBuffer[0]);
            strcat
            (   IOBuffer,
                "\n\n### BUG GENERATION PROCEDURE OR EXAMPLE:\n"
            );
            if (wbval >= 44)
                strcat(IOBuffer, textBuffer[1]);
            strcat(IOBuffer, "\n\n");
	}
	if (report.type == BUG || report.type == COM)
        {   strcat(IOBuffer, "### ALSO RUNNING:\n");
            strcat(IOBuffer, report.debug);
            strcat
            (   IOBuffer,
                "\n\n### IF THIS WORKS DIFFERENTLY ON "
                "OTHER VERSIONS OR HARDWARE, EXPLAIN:\n"
            );
            if (wbval >= 44)
                if (report.type == COM && report.severity == 3)
                    strcat(IOBuffer, textBuffer[0]);
                else strcat(IOBuffer, textBuffer[2]);
            strcat(IOBuffer, "\n\n");
	}
	if (report.type == COM && report.severity != 3)
        {   strcat
            (   IOBuffer,
                "### WHAT DEVELOPER IS DOING IN THAT AREA OF HW OR SW:\n"
            );
            if (wbval >= 44)
                strcat(IOBuffer, textBuffer[3]);
            strcat(IOBuffer, "\n\n");
	}
	if (report.type == BUG || (report.type == COM && report.severity != 3))
        {   strcat(IOBuffer, "### RELATED PROBLEMS:\n");
            if (wbval >= 44)
                if (report.type == BUG)
                    strcat(IOBuffer, textBuffer[3]);
                else strcat(IOBuffer, textBuffer[4]);
            strcat(IOBuffer, "\n\n");
        } elif (report.type == ENH)
        {   strcat(IOBuffer, "### ENHANCEMENT REQUEST:\n");
            if (wbval >= 44)
                strcat(IOBuffer, textBuffer[0]);
            strcat(IOBuffer, "\n\n");
        }

    if (wbval >= 44)
        report_exit();
    writeout(shared.output);
    if (wbval <= 43)
        launcheditor();

    strcpy(string, "Completed report is ");
    strcat(string, shared.output);
    strcat(string, ".");
    say(string, WHITE);
    strcpy(string, "EMail to: ");
    if
    (   stricmp(subsystems[report.subsystem].unfriendly, "wormwars")
     || stricmp(subsystems[report.subsystem].unfriendly, "report+")
    )
        strcat(string, "amigansoftware@altavista.com");
    else strcat(string, "aos35sup@haage-partner.com");
    say(string, WHITE);

    loop();
    closewindow();
}

AGLOBAL void report_loop(ULONG class, struct Gadget* addr, UWORD code)
{   if (page == 11)
    {   if (class == IDCMP_VANILLAKEY)
        {   code = toupper(code);
            if (code == ESCAPE)
            {   page = 0;
            } elif (code == 'N')
            {   page = 12;
            } elif (code == 'O')
            {   ActivateGadget(ST99_Output, MainWindowPtr, NULL);
            } elif (code == '.')
            {   asl();
                GT_SetGadgetAttrs
                (   ST99_Output,
                    MainWindowPtr,
                    NULL,
                    GTST_String, aslresult,
                    TAG_DONE
                );
            } elif (code == 'S')
            {   ActivateGadget(ST11_Summary, MainWindowPtr, NULL);
        }   }
        elif (class == IDCMP_GADGETUP)
        {   if (addr == BU99_Right)
            {   page = 12;
            } elif (addr == BU99_Left)
            {   page = 0;
            } elif (addr == BU99_OutputASL)
            {   asl();
                GT_SetGadgetAttrs
                (   ST99_Output,
                    MainWindowPtr,
                    NULL,
                    GTST_String, aslresult,
                    TAG_DONE
                );
        }   }
        elif (class == IDCMP_GADGETDOWN)
        {   if (addr == MX11_Type)
            {   report.type = code;
    }   }   }
    elif (page == 12)
    {   if (class == IDCMP_VANILLAKEY)
        {   code = toupper(code);
            if (code == ESCAPE)
            {   page = 11;
            } elif (code == 'N')
            {   page = 13;
            } elif ((report.type == BUG || report.type == COM) && code == 'K')
            {   ActivateGadget(ST12_KS, MainWindowPtr, NULL);
            } elif ((report.type == BUG || report.type == COM) && code == 'W')
            {   ActivateGadget(ST12_WB, MainWindowPtr, NULL);
            } elif ((report.type == BUG || report.type == COM) && code == 'D')
            {   ActivateGadget(ST12_Debug, MainWindowPtr, NULL);
            } elif (report.type == COM && code == 'A')
            {   ActivateGadget(ST12_3rdName, MainWindowPtr, NULL);
            } elif (report.type == COM && code == 'V')
            {   ActivateGadget(ST12_3rdVer, MainWindowPtr, NULL);
            } elif (report.type == COM && code == 'M')
            {   ActivateGadget(ST12_3rdManuf, MainWindowPtr, NULL);
        }   }
        elif (class == IDCMP_GADGETUP)
        {   if (addr == BU99_Right)
            {   page = 13;
            } elif (addr == BU99_Left)
            {   page = 11;
            } elif (report.type == BUG && addr == ST12_Pathname)
            {   refreshpv();
            } elif (report.type == BUG && addr == BU12_PathnameASL)
            {   asl();
                GT_SetGadgetAttrs
                (   ST12_Pathname,
                    MainWindowPtr,
                    NULL,
                    GTST_String, aslresult,
                    TAG_DONE
                );
                refreshpv();
            } elif (report.type != COM && addr == LV12_Subsystem)
            {   /* code is the position within the list.
                The list goes backwards, ie. Z-A. */
                report.subsystem = code;
        }   }
        elif (class == IDCMP_GADGETDOWN)
        {   if (addr == MX12_Severity)
            {   report.severity = code;
    }   }   }
    elif (page == 13)
    {   if (class == IDCMP_GADGETUP)
        {   if (addr == BU99_Right)
            {   if (certified)
                    page = 33;
                else page = 14;
            } elif (addr == BU99_Left)
            {   /* if called from ACSE, this gadget still exists,
                but is ghosted. */
                page = 12;
        }   }
        elif (class == IDCMP_VANILLAKEY)
        {   code = toupper(code);
            if (code == ESCAPE)
            {   page = 12;
            } elif (code == 'N')
            {   if (certified)
                    page = 33;
                else page = 14;
            } elif (code == 'F')
            {   ActivateGadget(ST13_FirstName, MainWindowPtr, NULL);
            } elif (code == 'L')
            {   ActivateGadget(ST13_LastName, MainWindowPtr, NULL);
            } elif (code == 'C')
            {   ActivateGadget(ST13_Company, MainWindowPtr, NULL);
            } elif (code == 'D')
            {   ActivateGadget(ST13_Developer, MainWindowPtr, NULL);
            } elif (code == 'P')
            {   ActivateGadget(ST13_Phone, MainWindowPtr, NULL);
            } elif (code == 'E')
            {   ActivateGadget(ST13_EMail, MainWindowPtr, NULL);
    }   }   }
    elif (page == 14)
    {   if (class == IDCMP_VANILLAKEY)
        {   code = toupper(code);
            if (code == 'F')
            {   page = 15;
            } elif (code == ESCAPE)
            {   page = 13;
            } elif (code == 'A')
            {   if ((code & IEQUALIFIER_LSHIFT) || (code & IEQUALIFIER_RSHIFT))
                {   if (report.agnus == 0)
                        report.agnus = 5;
                    else report.agnus--;
                } else
                {   if (report.agnus == 5)
                        report.agnus = 0;
                    else report.agnus++;
                }
                if (report.agnus == 0)
                    report.denise = 0;
                elif (report.agnus == 1 || report.agnus == 2)
                    report.denise = 1;
                else
                {   /* assert(report.agnus == 3 || report.agnus == 4); */
                    report.denise = 2;
                }
                GT_SetGadgetAttrs
                (   MX14_Agnus,
                    MainWindowPtr,
                    NULL,
                    GTMX_Active, report.agnus,
                    TAG_DONE
                );
                GT_SetGadgetAttrs
                (   MX14_Denise,
                    MainWindowPtr,
                    NULL,
                    GTMX_Active, report.denise,
                    TAG_DONE
                );
            } elif (code == 'C')
            {   ActivateGadget(ST14_Chip, MainWindowPtr, NULL);
            } elif (code == 'E')
            {   ActivateGadget(ST14_Expansion, MainWindowPtr, NULL);
            } elif (code == 'H')
            {   ActivateGadget(ST14_Hard, MainWindowPtr, NULL);
            } elif (code == 'L')
            {   if ((code & IEQUALIFIER_LSHIFT) || (code & IEQUALIFIER_RSHIFT))
                {   if (report.denise == 0)
                        report.denise = 3;
                    else report.denise--;
                } else
                {   if (report.denise == 3)
                        report.denise = 0;
                    else report.denise++;
                }
                GT_SetGadgetAttrs
                (   MX14_Denise,
                    MainWindowPtr,
                    NULL,
                    GTMX_Active, report.denise,
                    TAG_DONE
                );
            } elif (code == 'M')
            {   if ((code & IEQUALIFIER_LSHIFT) || (code & IEQUALIFIER_RSHIFT))
                {   if (report.model == 0)
                        report.model = MODELS;
                    else report.model--;
                } else
                {   if (report.model == CPUS)
                        report.model = 0;
                    else report.model++;
                }
                GT_SetGadgetAttrs
                (   MX14_Model,
                    MainWindowPtr,
                    NULL,
                    GTMX_Active, report.model,
                    TAG_DONE
                );
            } elif (code == 'N')
            {   ActivateGadget(IN14_Floppies, MainWindowPtr, NULL);
            } elif (code == 'P')
            {   if ((code & IEQUALIFIER_LSHIFT) || (code & IEQUALIFIER_RSHIFT))
                {   if (report.cpu == 0)
                        report.cpu = CPUS;
                    else report.cpu--;
                } else
                {   if (report.cpu == CPUS)
                        report.cpu = 0;
                    else report.cpu++;
                }
                GT_SetGadgetAttrs
                (   MX14_CPU,
                    MainWindowPtr,
                    NULL,
                    GTMX_Active, report.cpu,
                    TAG_DONE
                );
            } elif (code == 'S')
            {   ActivateGadget(ST14_Fast, MainWindowPtr, NULL);
        }   }
        elif (class == IDCMP_GADGETUP)
        {   if (addr == BU99_Right)
                page = 15;
            elif (addr == BU99_Left)
                page = 13;
        } elif (class == IDCMP_GADGETDOWN)
        {   if (addr == MX14_Model)
                report.model = code;
            elif (addr == MX14_CPU)
                report.cpu = code;
            elif (addr == MX14_Denise)
                report.denise = code;
            elif (addr == MX14_Agnus)
            {   report.agnus = code;
                if (code == 0)
                    report.denise = 0;
                elif (code == 1 || code == 2)
                    report.denise = 1;
                else
                {   /* assert(code == 3 || code == 4); */
                    report.denise = 2;
                }
                GT_SetGadgetAttrs
                (   MX14_Denise,
                    MainWindowPtr,
                    NULL,
                    GTMX_Active, report.denise,
                    TAG_DONE
                );
    }   }   }
    elif (page == 15)
    {   if (class == IDCMP_GADGETUP)
        {   if (addr == BU99_Right)
            {   page = 0;
        }   }
        elif (class == IDCMP_VANILLAKEY)
        {   if (code == ESCAPE)
            {   page = 0;
}   }   }   }

MODULE void refreshpv(void)
{	UBYTE	i;
	BPTR	FileHandle;

	strcpy(string, "C:Version ");
	strcat
	(	string,
                ((struct StringInfo *) ST12_Pathname->SpecialInfo)->Buffer
	);
        if (!(FileHandle = (BPTR) Open("T:ReportPlus.temp", MODE_NEWFILE)))
		rq("Can't open T:ReportPlus.temp for writing!");
	if (!Execute(string, NULL, FileHandle))
		rq("Can't execute C:Version!");
	if (!Close(FileHandle))
		rq("Can't close T:ReportPlus.temp for writing!");

        readordie("T:ReportPlus.temp");

	DeleteFile("T:ReportPlus.temp"); /* returns FALSE for failure */
	for (i = 0; i <= MEDFIELD; i++)
            if (IOBuffer[i] == LF)
            {   IOBuffer[i] = 0;
                break;
            }
	GT_SetGadgetAttrs
        (       ST12_Version,
		MainWindowPtr,
		NULL,
		GTST_String, IOBuffer,
		TAG_DONE
	);
}

AGLOBAL void report_exit(void)
{   ULONG i;

    for (i = 0; i <= elements; i++)
        if (textBuffer[i])
        {   FreeVec((APTR) textBuffer[i]);
            textBuffer[i] = NULL;
        }
    if (SubsystemListPtr)
    {   FreeNameNodes(SubsystemListPtr);
        FreeMem(SubsystemListPtr, sizeof(struct List));
        SubsystemListPtr = NULL;
}   }

AGLOBAL void report_init(void)
{   ULONG i;

    if (!(SubsystemListPtr = AllocMem(sizeof(struct List), MEMF_CLEAR)))
        rq("Out of memory!");
    NewList(SubsystemListPtr);
    for (i = 0; i <= SUBSYSTEMS; i++)
        AddNameToHead(SubsystemListPtr, subsystems[i].friendly);

    for (i = 0; i <= MAXELEMENTS; i++)
        textBuffer[i] = NULL;
}

AGLOBAL void sender(void)
{   /* PAGE 13 *************************************************************/

    navigate();
	
    if (readin("S:Report.sender"))
    {   /*  # Refer: <last>,<first> (<company> ,phone <phone>)<LF>
            # Path: <email><LF>
            # ReferID: <developer><LF> */

		offset = 0;
		parse("# Refer: ");
		parse(",");
                strcpy(report.lastname, string);
		parse(" (");
		strcpy(report.firstname, string);
		parse(" ,phone ");
		strcpy(report.company, string);
		parse(")\n# Path: ");
		strcpy(report.phone, string);
		parse("\n# ReferID: ");
		strcpy(report.email, string);
		parse("\n");
                strcpy(report.developer, string);
	}

	/* first name */
        setgadget(326, 22, 128, 12, "_First name:", NULL);
        ST13_FirstName = PrevGadPtr = (struct Gadget *) CreateGadget
	(	STRING_KIND,
		PrevGadPtr,
		&Gadget,
		GTST_String, &(report.firstname),
		GTST_MaxChars, MEDFIELD,
		GA_TabCycle, TRUE,
                GT_Underscore, '_',
		TAG_DONE
	);

	/* last name */
        setgadget(326, 34, 128, 12, "_Last name:", NULL);
        ST13_LastName = PrevGadPtr = (struct Gadget *) CreateGadget
	(	STRING_KIND,
		PrevGadPtr,
		&Gadget,
		GTST_String, &(report.lastname),
		GTST_MaxChars, MEDFIELD,
		GA_TabCycle, TRUE,
                GT_Underscore, '_',
		TAG_DONE
	);

	/* company name */
        setgadget(326, 46, 128, 12, "_Company:", NULL);
        ST13_Company = PrevGadPtr = (struct Gadget *) CreateGadget
	(	STRING_KIND,
		PrevGadPtr,
		&Gadget,
		GTST_String, &(report.company),
		GTST_MaxChars, MEDFIELD,
		GA_TabCycle, TRUE,
                GT_Underscore, '_',
		TAG_DONE
	);

	/* phone */
        setgadget(326, 58, 128, 12, "_Phone number:", NULL);
        ST13_Phone = PrevGadPtr = (struct Gadget *) CreateGadget
	(	STRING_KIND,
		PrevGadPtr,
		&Gadget,
		GTST_String, &(report.phone),
		GTST_MaxChars, MEDFIELD,
		GA_TabCycle, TRUE,
                GT_Underscore, '_',
		TAG_DONE
	);

	/* developer number */
        setgadget(326, 70, 128, 12, "_Developer number:", NULL);
        ST13_Developer = PrevGadPtr = (struct Gadget *) CreateGadget
        (       STRING_KIND,
		PrevGadPtr,
		&Gadget,
                GTST_String, &(report.developer),
                GTST_MaxChars, LONGFIELD,
		GA_TabCycle, TRUE,
                GT_Underscore, '_',
		TAG_DONE
	);

	/* email */
        setgadget(326, 82, 256, 12, "_EMail:", NULL);
        ST13_EMail = PrevGadPtr = (struct Gadget *) CreateGadget
	(	STRING_KIND,
		PrevGadPtr,
		&Gadget,
		GTST_String, &(report.email),
		GTST_MaxChars, MEDFIELD,
		GA_TabCycle, TRUE,
                GT_Underscore, '_',
		TAG_DONE
	);

	newwindow
        (       640, SENDERHEIGHT,
		"Report+: Sender Details",
		BUTTONIDCMP | STRINGIDCMP
	);
        ActivateGadget(ST13_FirstName, MainWindowPtr, NULL);
	loop();

	/* write out S:Report.sender

	# Refer: <last>,<first> (<company> ,phone <phone>)<LF>
	# Path: <email><LF>
	# ReferID: <developer><LF> */

	strcpy(report.refer, "# Refer: ");
	strcat
	(	report.refer,
                ((struct StringInfo *) ST13_LastName->SpecialInfo)->Buffer
	);
	strcat(report.refer, ",");
	strcat
	(	report.refer,
                ((struct StringInfo *) ST13_FirstName->SpecialInfo)->Buffer
	);
	strcat(report.refer, " (");
	strcat
	(	report.refer,
                ((struct StringInfo *) ST13_Company->SpecialInfo)->Buffer
	);
	strcat(report.refer, " ,phone ");
	strcat
	(	report.refer,
                ((struct StringInfo *) ST13_Phone->SpecialInfo)->Buffer
	);
	strcat(report.refer, ")\n");

	strcpy(report.path, "# Path: ");
	strcat
	(	report.path,
                ((struct StringInfo *) ST13_EMail->SpecialInfo)->Buffer
	);
	strcat(report.path, "\n");

	strcpy(report.referid, "# ReferID: ");
	stcl_d
	(	string,
                ((struct StringInfo *) ST13_Developer->SpecialInfo)->Buffer
	);
	strcat(report.referid, string);
	strcat(report.referid, "\n");

	strcpy(IOBuffer, report.refer);
	strcat(IOBuffer, report.path);
	strcat(IOBuffer, report.referid);

        writeout("S:Report.sender");
	closewindow();
}

AGLOBAL void config(void)
{   /* PAGE 14 ************************************************************** */

    UBYTE i;
	
    navigate();

    if (readin("S:Report.config"))
    {   /*  # Config: <model>,<cpu>,A=AA|ECS-pal|ECS|old-pal|old,
            D=AA|ECS|old,RAM=<chip>megC/<fast>megF,TD=<floppies>,
            HD=<controller>,<cards><LF> */

        offset = 0;
        parse("# Config: ");

		parse(",");
		report.model = 4;
		for (i = 0; i <= MODELS; i++)
			if (!stricmp(string, ModelOptions[i]))
				report.model = i;

		parse(",A=");
		report.cpu = 1;
		for (i = 0; i <= CPUS; i++)
			if (!stricmp(string, CPUOptions[i]))
				report.cpu = i;

		parse(",D=");
		if (!stricmp(string, "AA"))
			report.agnus = 0;
		elif (!stricmp(string, "ECS-pal"))
			report.agnus = 1;
		elif (!stricmp(string, "ECS"))
			report.agnus = 2;
		elif (!stricmp(string, "old-pal"))
			report.agnus = 3;
		else /* if (!stricmp(string, "old")) */
			report.agnus = 4;

		parse(",RAM=");
		if (!stricmp(string, "AA"))
			report.denise = 0;
		elif (!stricmp(string, "ECS"))
			report.denise = 1;
		else /* if (!stricmp(string, "old")) */
			report.denise = 2;

		parse("megC/");
		strcpy(report.chipram, string);

		parse("megF,TD=");
		strcpy(report.fastram, string);

		parse(",HD=");
		report.floppies = atol(string);

		parse(",");
		strcpy(report.hard, string);

		parse("\n");
		strcpy(report.expansion, string);
	}

    /* These formal coordinates of these text gadgets must not overlap any
    other gadgets, otherwise any such overlapped gadgets will not be
    selectable, with the mouse at least. This definitely applies to radio
    and string gadgets, and most likely other types. */

        /* model */
        setgadget(64, 30, 100, 0, "_Model:", PLACETEXT_ABOVE);
        TE14_ModelText = PrevGadPtr = (struct Gadget *) CreateGadget
        (   TEXT_KIND,
            PrevGadPtr,
            &Gadget,
            TAG_DONE
	);
	setgadget(64, 30, 0, 0, NULL, PLACETEXT_RIGHT);
        MX14_Model = PrevGadPtr = (struct Gadget *) CreateGadget
        (   MX_KIND,
            PrevGadPtr,
            &Gadget,
            GTMX_Labels, &ModelOptions,
            GTMX_Active, report.model,
            TAG_DONE
	);

    /* Agnus */
    setgadget(192, 30, 100, 0, "_Agnus/Alice Type:", PLACETEXT_ABOVE);
        TE14_AgnusText = PrevGadPtr = (struct Gadget *) CreateGadget
	(	TEXT_KIND,
		PrevGadPtr,
		&Gadget,
		TAG_DONE
	);
	setgadget(192, 30, 0, 0, NULL, PLACETEXT_RIGHT);
        MX14_Agnus = PrevGadPtr = (struct Gadget *) CreateGadget
	(	MX_KIND,
		PrevGadPtr,
		&Gadget,
		GTMX_Labels, &AgnusOptions,
		GTMX_Active, report.agnus,
		TAG_DONE
	);

        /* Denise */
        setgadget(384, 30, 100, 0, "Denise/_Lisa Type:", PLACETEXT_ABOVE);
        TE14_DeniseText = PrevGadPtr = (struct Gadget *) CreateGadget
	(	TEXT_KIND,
		PrevGadPtr,
		&Gadget,
		TAG_DONE
	);
	setgadget(384, 30, 0, 0, NULL, PLACETEXT_RIGHT);
        MX14_Denise = PrevGadPtr = (struct Gadget *) CreateGadget
	(	MX_KIND,
		PrevGadPtr,
		&Gadget,
		GTMX_Labels, &DeniseOptions,
		GTMX_Active, report.denise,
		TAG_DONE
	);

    /* CPU */
    setgadget(512, 30, 100, 0, "_Processor:", PLACETEXT_ABOVE);
    TE14_CPUText = PrevGadPtr = (struct Gadget *) CreateGadget
    (   TEXT_KIND,
        PrevGadPtr,
        &Gadget,
        TAG_DONE
    );
    setgadget(512, 30, 0, 0, NULL, PLACETEXT_RIGHT);
    MX14_CPU = PrevGadPtr = (struct Gadget *) CreateGadget
    (   MX_KIND,
        PrevGadPtr,
        &Gadget,
        GTMX_Labels, &CPUOptions,
        GTMX_Active, report.cpu,
        TAG_DONE
    );

    /* chip RAM */
    setgadget(465, 98, 1, 12, "Mb", PLACETEXT_RIGHT);
    TE14_ChipText = PrevGadPtr = (struct Gadget *) CreateGadget
    (   TEXT_KIND,
        PrevGadPtr,
        &Gadget,
        TAG_DONE
    );
    setgadget(400, 98, 64, 12, "_Chip RAM:", NULL);
    ST14_Chip = PrevGadPtr = (struct Gadget *) CreateGadget
    (   STRING_KIND,
        PrevGadPtr,
        &Gadget,
        GTST_String, &(report.chipram),
        GTST_MaxChars, 4,
        GA_TabCycle, TRUE,
        TAG_DONE
    );

    // slow/fast RAM
    setgadget(465, 110, 1, 12, "Mb", PLACETEXT_RIGHT);
    TE14_FastText = PrevGadPtr = (struct Gadget *) CreateGadget
    (   TEXT_KIND,
        PrevGadPtr,
        &Gadget,
        TAG_DONE
    );
    setgadget(400, 110, 64, 12, "_Slow/fast RAM:", NULL);
    ST14_Fast = PrevGadPtr = (struct Gadget *) CreateGadget
    (   STRING_KIND,
        PrevGadPtr,
        &Gadget,
        GTST_String, &(report.fastram),
        GTST_MaxChars, 4,
        GA_TabCycle, TRUE,
        TAG_DONE
    );

	/* floppies */
        setgadget(400, 122, 64, 12, "_Number of floppies:", NULL);
        IN14_Floppies = PrevGadPtr = (struct Gadget *) CreateGadget
	(	INTEGER_KIND,
		PrevGadPtr,
		&Gadget,
		GTIN_Number, report.floppies,
		GA_TabCycle, TRUE,
		TAG_DONE
	);

	/* hard disk controller */
        setgadget(400, 134, 128, 12, "_Hard disk controller:", NULL);
        ST14_Hard = PrevGadPtr = (struct Gadget *) CreateGadget
	(	STRING_KIND,
		PrevGadPtr,
		&Gadget,
		GTST_String, &(report.hard),
		GTST_MaxChars, MEDFIELD,
		GA_TabCycle, TRUE,
		TAG_DONE
	);

	/* expansion cards */
        setgadget(400, 146, 228, 12, "_Expansion cards:", NULL);
        ST14_Expansion = PrevGadPtr = (struct Gadget *) CreateGadget
	(	STRING_KIND,
		PrevGadPtr,
		&Gadget,
		GTST_String, &(report.expansion),
		GTST_MaxChars, LONGFIELD,
		GA_TabCycle, TRUE,
		TAG_DONE
	);

	newwindow
        (   640, CONFIGHEIGHT,
            "Report+: Configuration Details",
            BUTTONIDCMP | STRINGIDCMP | MXIDCMP
	);
        ActivateGadget(ST14_Chip, MainWindowPtr, NULL);
	loop();

        strcpy(report.chipram,   ((struct StringInfo *) ST14_Chip->SpecialInfo)->Buffer);
        strcpy(report.fastram,   ((struct StringInfo *) ST14_Fast->SpecialInfo)->Buffer);
        strcpy(report.hard,      ((struct StringInfo *) ST14_Hard->SpecialInfo)->Buffer);
        report.floppies        = ((struct StringInfo *) IN14_Floppies->SpecialInfo)->LongInt;
        strcpy(report.expansion, ((struct StringInfo *) ST14_Expansion->SpecialInfo)->Buffer);

	strcpy(report.config, "# Config: ");
	strcpy(string, ModelOptions[report.model]);
	strlwr(string);
	strcat(report.config, string);
	strcat(report.config, ",");
	strcpy(string, CPUOptions[report.cpu]);
	strlwr(string);
	strcat(report.config, string);
	strcat(report.config, ",A=");
	switch(report.agnus)
	{
	case 0:
            strcat(report.config, "AA");
	break;
	case 1:
            strcat(report.config, "ECS-pal");
	break;
	case 2:
            strcat(report.config, "ECS");
	break;
	case 3:
            strcat(report.config, "old-pal");
	break;
	default:
            strcat(report.config, "old");
	break;
	}
	strcat(report.config, ",D=");
	switch(report.denise)
	{
	case 0:
            strcat(report.config, "AA");
	break;
	case 1:
            strcat(report.config, "ECS");
	break;
	default:
            strcat(report.config, "old");
	break;
	}
	strcat(report.config, ",RAM=");
	strcat(report.config, report.chipram);
	strcat(report.config, "megC/");
	strcat(report.config, report.fastram);
	strcat(report.config, "megF,TD=");
	stcl_d(string, report.floppies);
	strcat(report.config, string);
	strcat(report.config, ",HD=");
	strcat(report.config, report.hard);
	strcat(report.config, ",");
	strcat(report.config, report.expansion);
	strcat(report.config, "\n");

	strcpy(IOBuffer, report.config);
        writeout("S:Report.config");
	closewindow();
}

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

MODULE void AddNameToHead(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("Can't allocate memory for list node!");
	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;
	AddHead((struct List *) ListPtr, (struct Node *) NameNodePtr);
}

