#include <exec/types.h>
#include <exec/memory.h>
#include <proto/exec.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <proto/intuition.h>
#include <libraries/gadtools.h>
#include <proto/gadtools.h>
#include <dos/dos.h>
#include <proto/dos.h>
#include <graphics/gfx.h>
#include <clib/graphics_protos.h>

#include <clib/alib_protos.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "rp.h"

#define ALL_REACTION_CLASSES
#include <reaction/reaction.h>
#include <clib/texteditor_protos.h>
#include <gadgets/texteditor.h>
#include <pragmas/texteditor_pragmas.h>

#define SUBSYSTEMS   127
#define CPUS           4
#define MODELS        13
#define MAXELEMENTS_1  4 // counting from 0

MODULE void refreshpv(void);
MODULE void updatereportgadgets(void);
MODULE void readreportgadgets(void);
MODULE ULONG Hook1Func(struct Hook *h, VOID *o, VOID *msg);
MODULE void updateemail(void);

AGLOBAL struct ReportStruct report;

MODULE struct Gadget*  report_gadgets[GIDS_1 + 1];
MODULE ABOOL           SubsystemNodes          = FALSE;
MODULE struct List     SubsystemList;
MODULE struct Gadget  *CY11_Type               = NULL,
                      *ST11_Summary            = NULL,
                      *BU11_PathnameASL        = NULL,
                      *LV11_Subsystem          = NULL,
                      *CY11_Severity           = NULL,
                      *ST11_Debug              = NULL,
                      *ST11_KS                 = NULL,
                      *ST11_WB                 = NULL,
                      *ST11_Pathname           = NULL,
                      *ST11_Version            = NULL,
                      *TE11_3rdLabel           = NULL,
                      *ST11_3rdName            = NULL,
                      *ST11_3rdVer             = NULL,
                      *ST11_3rdManuf           = NULL,
                      *BU11_Sender             = NULL,
                      *BU11_Config             = NULL,
                      *TE11_EMailTo            = NULL,

                      *ST12_Company            = NULL,
                      *ST12_Developer          = NULL,
                      *ST12_EMail              = NULL,
                      *ST12_FirstName          = NULL,
                      *ST12_LastName           = NULL,
                      *ST12_Phone              = NULL,

                      *MX13_Model              = NULL,
                      *TE13_ModelText          = NULL,
                      *MX13_Agnus              = NULL,
                      *TE13_AgnusText          = NULL,
                      *MX13_CPU                = NULL,
                      *TE13_CPUText            = NULL,
                      *IN13_Floppies           = NULL,
                      *ST13_Chip               = NULL,
                      *TE13_ChipText           = NULL,
                      *ST13_Fast               = NULL,
                      *TE13_FastText           = NULL,
                      *ST13_Hard               = NULL,
                      *ST13_Expansion          = NULL;
MODULE struct
{   STRPTR friendly;
    STRPTR unfriendly;
} subsystems[SUBSYSTEMS + 1] =
{   {"3D Look",                "new.look"        },
    {"A590",                   "A2091.A590"      },
    {"A2013",                  "A2013"           },
    {"A2065",                  "A2065"           },
    {"A2090",                  "A2090.A2090A"    },
    {"A2090A",                 "A2090.A2090A"    },
    {"A2091",                  "A2091"           },
    {"A2232",                  "A2232"           },
    {"A2300",                  "A2300"           },
    {"A2410",                  "A2410"           },
    {"A2620",                  "A2620"           },
    {"A2630",                  "A2630"           },
    {"A3000",                  "A3000"           },
    {"A4091",                  "A4091"           },
    {"AmigaBASIC",             "AmigaBasic"      },
    {"AGA chipset",            "aa.chips"        },
    {"ALink",                  "alink"           },
    {"amiga.lib",              "amiga.lib"       },
    {"AmigaGuide",             "amigaguide"      },
    {"AmigaTerm",              "amigaterm"       },
    {"AmigaVision",            "amigavision"     },
    {"AppShell",               "appshell"        },
    {"ARexx",                  "arexx"           },
    {"Art",                    "art"             },
    {"AS225",                  "as225"           },
    {"ASL.library",            "asl.library"     },
    {"audio.device",           "audio.device"    },
    {"AUTOCONFIG",             "autoconfig"      },
    {"Battery-backed clock",   "battclock"       },
    {"Battery-backed memory",  "battmem"         },
    {"Bootstrap",              "strap"           },
    {"BridgeBoard",            "bridgeboard"     },
    {"BRU",                    "bru"             },
    {"bullet.library",         "bullet"          },
    {"C: programs",            "cdos.command"    },
    {"CD.device",              "cd.device"       },
    {"CD32 hardware",          "cdgs"            },
    {"CDFileSystem",           "cdfilesystem"    },
    {"CDTV",                   "cdtv"            },
    {"CDTV.device",            "cdtv.device"     },
    {"cdui",                   "cdui"            },
    {"CIA.resource",           "cia.resource"    },
    {"CLI",                    "shell"           },
    {"clipboard.device",       "clipboard"       },
    {"Commodities",            "commodities"     },
    {"CON-Handler",            "con-handler"     },
    {"console.device",         "console.device"  },
    {"Custom chipset",         "custom.chips"    },
    {"Datatypes",              "datatypes"       },
    {"debug.lib",              "debug.lib"       },
    {"Developer support",      "devsupport"      },
    {"disk.resource",          "disk.resource"   },
    {"diskfont.library",       "diskfont"        },
    {"DOS.library",            "dos.library"     },
    {"Early Startup Control",  "bootmenu"        },
    {"Envoy",                  "envoy"           },
    {"Exec.library",           "exec"            },
    {"expansion.library",      "expansion"       },
    {"filesystem",             "filesystem"      },
    {"filesystem.resource",    "filesysres"      },
    {"Fonts",                  "fonts"           },
    {"Fountain",               "fountain"        },
    {"gadget.classes",         "gadget.classes"  },
    {"GadTools.library",       "gadtools"        },
    {"gameport.device",        "gameport"        },
    {"Genlock",                "genlock"         },
    {"Graphics",               "graphics"        },
    {"Hardware",               "hardware"        },
    {"HDBackup",               "hdbackup"        },
    {"HDToolBox",              "hdtoolbox"       },
    {"icon.library",           "icon.library"    },
    {"IconEdit",               "iconedit"        },
    {"IDE.device",             "ide.device"      },
    {"IFFParse.library",       "iffparse"        },
    {"input.device",           "input.device"    },
    {"Installer",              "installer"       },
    {"IntelliFont",            "fountain"        },
    {"Intuition.library",      "intuition"       },
    {"IPrefs",                 "iprefs"          },
    {"Keyboard",               "keyboard"        },
    {"keymap.library",         "keymap"          },
    {"Keymaps",                "keymaps"         },
    {"layers.library",         "layers"          },
    {"locale.library",         "locale.library"  },
    {"lowlevel.library",       "lowlevel"        },
    {"Maths: FFP",             "mathffp"         },
    {"Maths: IEEE Double Precision", "mathieeedoub"    },
    {"Maths: IEEE Single Precision", "mathieeesing"    },
    {"Maths: IEEE",            "mathieee"        },
    {"MicroEMACS",             "microemacs"      },
    {"Monitors",               "monitors"        },
    {"MultiView",              "multiview"       },
    {"nonvolatile",            "nonvolatile"     },
    {"parallel.device",        "parallel.device" },
    {"PCMCIA",                 "creditcard"      },
    {"PORT-Handler",           "port-handler"    },
    {"potgo.resource",         "potgo.resource"  },
    {"Preferences",            "preferences"     },
    {"Printer drivers",        "printer.driver"  },
    {"printer.device",         "printer.device"  },
    {"QUEUE-Handler",          "queue-handler"   },
    {"RAM-Handler",            "ram-handler"     },
    {"ramlib",                 "ramlib"          },
    {"realtime",               "realtime"        },
    {"Report+",                "report+"         },
    {"Resources",              "resource"        },
    {"ROM Kernel Manuals",     "rkm"             },
    {"ROMWack",                "wack"            },
    {"SANA-2",                 "sana2"           },
    {"Scripts",                "script"          },
    {"SCSI.device",            "scsi.device"     },
    {"serial.device",          "serial.device"   },
    {"Shell",                  "shell"           },
    {"Startup",                "startup"         },
    {"System/ programs",       "system.command"  },
    {"TCP/IP",                 "as225"           },
    {"timer.device",           "timer.device"    },
    {"ToolMaker",              "toolmaker"       },
    {"Tools/ programs",        "tools"           },
    {"trackdisk.device",       "trackdisk"       },
    {"UNIX",                   "unix"            },
    {"Unsure",                 ""                },
    {"User manuals",           "userdocs"        },
    {"Utilities/ programs",    "util.command"    },
    {"utility.library",        "utility.library" },
    {"Wack",                   "wack"            },
    {"Workbench",              "workbench"       },
    {"Worm Wars",              "wormwars"        }
};
MODULE STRPTR TypeOptions[4] =
{   "System Software/Hardware Bug",
    "3rd Party Product Compatibility",
    "Enhancement Request",
    NULL
};
MODULE STRPTR SeverityOptions[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 CPUOptions[CPUS + 2] =
{   (STRPTR) "68020",
    (STRPTR) "68030",
    (STRPTR) "68040",
    (STRPTR) "68060",
    (STRPTR) "PowerPC",
    NULL
};
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 ULONG               offset;
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_Right,
                          *BU99_TextEditor,
                          *GListPtr,
                          *PrevGadPtr;
IMPORT TEXT                IOBuffer[LONGESTFIELD + 1];
IMPORT SBYTE               page;
IMPORT ABOOL               certified, fillwindows;
IMPORT TEXT                string[VLONGFIELD + 1];
IMPORT struct Window*      MainWindowPtr;
IMPORT struct Menu*        MenuPtr;
IMPORT struct Screen*      ScreenPtr;
IMPORT struct Library*     TextEditorBase;
IMPORT Object*             WinObject[FUNCTIONS + 1];

/* report.textfield[] are:
   0: brief bug description
   1: bug generation procedure or example
   2: if this works differently on other versions or hardware, explain
   3: what developer is doing in that area of HW or SW
   4: related problems
   5: enhancement request */

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

    verynewwindow
    (   REPORTWIDTH, REPORTHEIGHT,
        "Report+: Report Details (Page 1 of 2)",
        BUTTONIDCMP | LISTVIEWIDCMP | STRINGIDCMP | CYCLEIDCMP
    );
    if (fillwindows)
    {   SetAPen(MainWindowPtr->RPort, 0);
        RectFill(MainWindowPtr->RPort,  10, 144,  10 + 238, 144 + 87 - 4); // LV11_Subsystem
        RectFill(MainWindowPtr->RPort, 182,  32, 182 + 312,  32 + 12);     // TE11_EMailTo
    }
    OnMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_NEW,    NOSUB));
    OnMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_OPEN,   NOSUB));
    OnMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVE,   NOSUB));
    OnMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVEAS, NOSUB));

    /* summary */
    setgadget(182, 20, 448, 12, "_Summary:", PLACETEXT_LEFT);
    ST11_Summary = PrevGadPtr = (struct Gadget *) CreateGadget
    (   STRING_KIND,
        PrevGadPtr,
        &Gadget,
        STRINGA_Justification, GACT_STRINGLEFT,
        GTST_String, &(report.summary),
        GTST_MaxChars, LONGFIELD,
        GA_TabCycle, TRUE,
        GT_Underscore, '_',
        TAG_DONE
    );
    /* email to */
    setgadget(182, 32, 312, 12, "EMail to:", PLACETEXT_LEFT);
    TE11_EMailTo = PrevGadPtr = (struct Gadget *) CreateGadget
    (   TEXT_KIND,
        PrevGadPtr,
        &Gadget,
        GTTX_Border, TRUE,
        TAG_DONE
    );

    /* sender... */
    setgadget(10,  86, 140, 12, "Sende_r...", NULL);
    BU11_Sender = PrevGadPtr = (struct Gadget *) CreateGadget
    (   BUTTON_KIND,
        PrevGadPtr,
        &Gadget,
        GT_Underscore, '_',
        TAG_DONE
    );
    /* configuration... */
    setgadget(10,  98, 140, 12, "Confi_guration...", NULL);
    BU11_Config = PrevGadPtr = (struct Gadget *) CreateGadget
    (   BUTTON_KIND,
        PrevGadPtr,
        &Gadget,
        GT_Underscore, '_',
        TAG_DONE
    );
    /* text editor... */
    setgadget(10, 110, 140, 12, "_Other page...", NULL);
    BU99_TextEditor = PrevGadPtr = (struct Gadget *) CreateGadget
    (   BUTTON_KIND,
        PrevGadPtr,
        &Gadget,
        GT_Underscore, '_',
        TAG_DONE
    );

    /* type */
    setgadget(100, 54, 284, 12, "_Type:", PLACETEXT_LEFT);
    CY11_Type = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CYCLE_KIND,
        PrevGadPtr,
        &Gadget,
        GTCY_Labels, TypeOptions,
        GTCY_Active, report.type,
        GT_Underscore, '_',
        TAG_DONE
    );

    /* classification */
    setgadget(100, 66, 284, 12, "Sever_ity:", PLACETEXT_LEFT);
    CY11_Severity = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CYCLE_KIND,
        PrevGadPtr,
        &Gadget,
        GTCY_Labels, SeverityOptions,
        GTCY_Active, report.severity,
        GT_Underscore, '_',
        TAG_DONE
    );

    setgadget(10, 144, 238, 87, "Subsystem:", NULL);
    LV11_Subsystem = PrevGadPtr = (struct Gadget *) CreateGadget
    (   LISTVIEW_KIND,
        PrevGadPtr,
        &Gadget,
        GTLV_Labels, &SubsystemList,
        GTLV_ShowSelected, NULL,
        GTLV_Selected, report.subsystem,
        GT_Underscore, '_',
        TAG_DONE
    );

    /* 3rd party product */
    setgadget(422, 190, 100, 1, "3rd Party Product:", PLACETEXT_ABOVE);
    TE11_3rdLabel = PrevGadPtr = (struct Gadget *) CreateGadget
    (   TEXT_KIND,
        PrevGadPtr,
        &Gadget,
        TAG_DONE
    );
    /* 3rd party product name */
    setgadget(400, 190, 200, 12, "N_ame:", NULL);
    ST11_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(400, 202, 100, 12, "_Version:", NULL);
    ST11_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(400, 214, 200, 12, "_Manufacturer:", NULL);
    ST11_3rdManuf = PrevGadPtr = (struct Gadget *) CreateGadget
    (   STRING_KIND,
        PrevGadPtr,
        &Gadget,
        GTST_String, &(report.thirdmanuf),
        GTST_MaxChars, MEDFIELD,
        GA_TabCycle, TRUE,
        GT_Underscore, '_',
        TAG_DONE
    );

    /* debug tools and wedges */
    setgadget(400, 78, 196, 12, "_Debug tools and wedges:", PLACETEXT_ABOVE);
    ST11_Debug = PrevGadPtr = (struct Gadget *) CreateGadget
    (   STRING_KIND,
        PrevGadPtr,
        &Gadget,
        STRINGA_Justification, GACT_STRINGLEFT,
        GTST_String, &(report.debug),
        GTST_MaxChars, LONGFIELD,
        GA_TabCycle, TRUE,
        GT_Underscore, '_',
        TAG_DONE
    );

    /* kickstart version */
    if (report.ks[0] == 0)
        if (GetVar("Kickstart", report.ks, 6, NULL) == -1)
            report.ks[0] = 0;
    setgadget(400, 102, 60, 12, "_Kickstart version:", NULL);
    ST11_KS = PrevGadPtr = (struct Gadget *) CreateGadget
    (   STRING_KIND,
        PrevGadPtr,
        &Gadget,
        GTST_String, &(report.ks),
        GTST_MaxChars, 6,
        GA_TabCycle, TRUE,
        GT_Underscore, '_',
        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, 114, 60, 12, "_Workbench version:", NULL);
    ST11_WB = PrevGadPtr = (struct Gadget *) CreateGadget
    (   STRING_KIND,
        PrevGadPtr,
        &Gadget,
        GTST_String, &(report.wb),
        GTST_MaxChars, 6,
        GA_TabCycle, TRUE,
        GT_Underscore, '_',
        STRINGA_Justification, GACT_STRINGRIGHT,
        TAG_DONE
    );

    /* program pathname */
    setgadget(400, 138, 196, 12, "P_rogram pathname:", NULL);
    ST11_Pathname = PrevGadPtr = (struct Gadget *) CreateGadget
    (   STRING_KIND,
        PrevGadPtr,
        &Gadget,
        GTST_String, &(report.pp),
        GTST_MaxChars, LONGFIELD,
        GA_TabCycle, TRUE,
        GT_Underscore, '_',
        TAG_DONE
    );
    /* program... */
    setgadget(598, 138, 28, 12, "...", NULL);
    BU11_PathnameASL = PrevGadPtr = (struct Gadget *) CreateGadget
    (   BUTTON_KIND,
        PrevGadPtr,
        &Gadget,
        GT_Underscore, '_',
        TAG_DONE
    );
    /* program version */
    setgadget(400, 150, 196, 12, "Program v_ersion:", NULL);
    ST11_Version = PrevGadPtr = (struct Gadget *) CreateGadget
    (   STRING_KIND,
        PrevGadPtr,
        &Gadget,
        GTST_String, &(report.pv),
        GTST_MaxChars, LONGFIELD,
        GA_TabCycle, TRUE,
        GT_Underscore, '_',
        TAG_DONE
    );

    drawgadgets((UWORD) ~0);

    updatereportgadgets(); // we do need this here, so that gadgets are
                           // ghosted as appropriate
    ActivateGadget(ST11_Summary, MainWindowPtr, NULL);

    loop();
    readreportgadgets();
    closewindow();
}

MODULE void readreportgadgets(void)
{   strcpy
    (   report.summary,
        ((struct StringInfo *) ST11_Summary->SpecialInfo)->Buffer
    );
    if (report.type == COM)
    {   strcpy
        (   report.thirdver,
            ((struct StringInfo *) ST11_3rdVer->SpecialInfo)->Buffer
        );
        strcpy
        (   report.thirdname,
            ((struct StringInfo *) ST11_3rdName->SpecialInfo)->Buffer
        );
        strcpy
        (   report.thirdmanuf,
            ((struct StringInfo *) ST11_3rdManuf->SpecialInfo)->Buffer
        );
    } elif (report.type == BUG)
    {   strcpy
        (   report.pp,
            ((struct StringInfo *) ST11_Pathname->SpecialInfo)->Buffer
        );
        strcpy
        (   report.pv,
            ((struct StringInfo *) ST11_Version->SpecialInfo)->Buffer
        );
    }
    if (report.type != ENH)
    {   strcpy
        (   report.ks,
            ((struct StringInfo *) ST11_KS->SpecialInfo)->Buffer
        );
        strcpy
        (   report.wb,
            ((struct StringInfo *) ST11_WB->SpecialInfo)->Buffer
        );
        strcpy
        (   report.debug,
            ((struct StringInfo *) ST11_Debug->SpecialInfo)->Buffer
        );
}   }

AGLOBAL void savereport(ABOOL saveas)
{ /*    # 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: */

    readreportgadgets();

    strcpy(IOBuffer, "# Subject: ");
    strcat(IOBuffer, report.summary);
    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[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"
        );
        strcat(IOBuffer, report.textfield[0]);
        strcat
        (   IOBuffer,
            "\n\n### BUG GENERATION PROCEDURE OR EXAMPLE:\n"
	);
        strcat(IOBuffer, report.textfield[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"
        );
        strcat(IOBuffer, report.textfield[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"
        );
        strcat(IOBuffer, report.textfield[3]);
        strcat(IOBuffer, "\n\n");
    }
    if (report.type == BUG || (report.type == COM && report.severity != 3))
    {   strcat(IOBuffer, "### RELATED PROBLEMS:\n");
        strcat(IOBuffer, report.textfield[4]);
        strcat(IOBuffer, "\n\n");
    } elif (report.type == ENH)
    {   strcat(IOBuffer, "### ENHANCEMENT REQUEST:\n");
        strcat(IOBuffer, report.textfield[5]);
        strcat(IOBuffer, "\n\n");
    }

    if (!report.output[0] || saveas) // if we need a filename
    {   if (saveasl("Save Bug Report", "~(#?.info)"))
        {   strcpy(report.output, aslresult);
            writeout(report.output);
    }   }
    else
    {   writeout(report.output);
}   }
    
AGLOBAL void report_ra_loop(ULONG gid)
{   switch(gid)
    {
    case GID_1_BU1:
        page = 11;
    break;
    case GID_1_BU2:
        page = 0;
    break;
    default:
    break;
}   }

AGLOBAL void report_gt_loop(ULONG class, struct Gadget* addr, UWORD code, UWORD qual)
{   if (page == 11)
    {   if (class == IDCMP_RAWKEY && report.type != COM)
        {   if (qual & IEQUALIFIER_CONTROL)
            {   if (code == SCAN_UP)
                {   GT_SetGadgetAttrs
                    (   LV11_Subsystem,
                        MainWindowPtr,
                        NULL,
                        GTLV_Top, 0,
                        TAG_DONE
                    );
                } elif (code == SCAN_DOWN)
                {   GT_SetGadgetAttrs
                    (   LV11_Subsystem,
                        MainWindowPtr,
                        NULL,
                        GTLV_Top, SUBSYSTEMS - 10 + 1,
                        // this must change according to height of listview
                        TAG_DONE
                    );
        }   }   }
        elif (class == IDCMP_VANILLAKEY)
        {   code = toupper(code);
            if (code == ESCAPE)
            {   page = 0;
            } elif (code == 'N')
            {   page = 12;
            } elif (code == 'T')
            {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
                {   if (report.type == 0)
                    {   report.type = 2;
                    } else report.type--;
                } else
                {   if (report.type == 2)
                    {   report.type = 0;
                    } else report.type++;
                }
                updatereportgadgets();
            } elif (code == 'S')
            {   ActivateGadget(ST11_Summary, MainWindowPtr, NULL);
            } elif (code == 'O')
            {   page = 14;
            } elif (code == 'R')
            {   page = 12;
            } elif (code == 'G')
            {   page = 13;
            } elif (report.type != ENH)
            {   if (code == 'K')
                {   ActivateGadget(ST11_KS, MainWindowPtr, NULL);
                } elif (code == 'W')
                {   ActivateGadget(ST11_WB, MainWindowPtr, NULL);
                } elif (code == 'D')
                {   ActivateGadget(ST11_Debug, MainWindowPtr, NULL);
                } elif (code == 'I')
                {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
                    {   if (report.severity == 0)
                        {   report.severity = 3;
                        } else report.severity--;
                    } else
                    {   if (report.severity == 3)
                        {   report.severity = 0;
                        } else report.severity++;
                    }
                    if (report.type == BUG && report.severity == 3)
                    {   report.severity = 0;
                    }
                    GT_SetGadgetAttrs
                    (   CY11_Severity,
                        MainWindowPtr,
                        NULL,
                        GTCY_Active, report.severity,
                        TAG_DONE
                    );
                } elif (report.type == BUG)
                {   if (code == 'P')
                    {   ActivateGadget(ST11_Pathname, MainWindowPtr, NULL);
                    } elif (code == 'E')
                    {   ActivateGadget(ST11_Version, MainWindowPtr, NULL);
                }   }
                else
                {   // assert(report.type == COM);
                    if (code == 'A')
                    {   ActivateGadget(ST11_3rdName, MainWindowPtr, NULL);
                    } elif (code == 'V')
                    {   ActivateGadget(ST11_3rdVer, MainWindowPtr, NULL);
                    } elif (code == 'M')
                    {   ActivateGadget(ST11_3rdManuf, MainWindowPtr, NULL);
        }   }   }   }
        elif (class == IDCMP_GADGETUP)
        {   if (addr == BU99_Right)
            {   page = 0;
            } elif (addr == BU11_Sender)
            {   page = 12;
            } elif (addr == BU11_Config)
            {   page = 13;
            } elif (addr == BU99_TextEditor)
            {   page = 14;
            } elif (addr == CY11_Type)
            {   report.type = code;
                updatereportgadgets();
            } elif (report.type != COM && addr == LV11_Subsystem)
            {   // code is the position within the list.
                report.subsystem = code;
                updateemail();
            } elif (report.type != ENH)
            {   if (addr == CY11_Severity)
                {   report.severity = code;
                    if (report.type == BUG && report.severity == 3)
                    {   report.severity = 0;
                        GT_SetGadgetAttrs
                        (   CY11_Severity,
                            MainWindowPtr,
                            NULL,
                            GTCY_Active, report.severity,
                            TAG_DONE
                        );
                }   }
                elif (report.type == BUG)
                {   if (addr == ST11_Pathname)
                    {   refreshpv();
                    } elif (addr == BU11_PathnameASL)
                    {   if (asl("~(#?.info)"))
                        {   GT_SetGadgetAttrs
                            (   ST11_Pathname,
                                MainWindowPtr,
                                NULL,
                                GTST_String, aslresult,
                                TAG_DONE
                            );
                            refreshpv();
    }   }   }   }   }   }
    elif (page == 12)
    {   if (class == IDCMP_GADGETUP)
        {   if (addr == BU99_Right)
            {   if (certified)
                    page = 33;
                else page = 11;
        }   }
        elif (class == IDCMP_VANILLAKEY)
        {   code = toupper(code);
            if (code == ESCAPE)
            {   if (certified)
                    page = 33;
                else page = 11;
            } elif (code == 'F')
            {   ActivateGadget(ST12_FirstName, MainWindowPtr, NULL);
            } elif (code == 'L')
            {   ActivateGadget(ST12_LastName,  MainWindowPtr, NULL);
            } elif (code == 'C')
            {   ActivateGadget(ST12_Company,   MainWindowPtr, NULL);
            } elif (code == 'D')
            {   ActivateGadget(ST12_Developer, MainWindowPtr, NULL);
            } elif (code == 'P')
            {   ActivateGadget(ST12_Phone,     MainWindowPtr, NULL);
            } elif (code == 'E')
            {   ActivateGadget(ST12_EMail,     MainWindowPtr, NULL);
    }   }   }
    elif (page == 13)
    {   if (class == IDCMP_VANILLAKEY)
        {   code = toupper(code);
            if (code == ESCAPE)
            {   page = 11;
            } elif (code == 'I')
            {   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++;
                }
                GT_SetGadgetAttrs
                (   MX13_Agnus,
                    MainWindowPtr,
                    NULL,
                    GTMX_Active, report.agnus,
                    TAG_DONE
                );
            } elif (code == 'C')
            {   ActivateGadget(ST13_Chip, MainWindowPtr, NULL);
            } elif (code == 'E')
            {   ActivateGadget(ST13_Expansion, MainWindowPtr, NULL);
            } elif (code == 'H')
            {   ActivateGadget(ST13_Hard, MainWindowPtr, NULL);
            } 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
                (   MX13_Model,
                    MainWindowPtr,
                    NULL,
                    GTMX_Active, report.model,
                    TAG_DONE
                );
            } elif (code == 'N')
            {   ActivateGadget(IN13_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
                (   MX13_CPU,
                    MainWindowPtr,
                    NULL,
                    GTMX_Active, report.cpu,
                    TAG_DONE
                );
            } elif (code == 'S')
            {   ActivateGadget(ST13_Fast, MainWindowPtr, NULL);
        }   }
        elif (class == IDCMP_GADGETUP)
        {   if (addr == BU99_Right)
                page = 11;
            elif (addr == IN13_Floppies)
            {   report.floppies = ((struct StringInfo *) IN13_Floppies->SpecialInfo)->LongInt;
                if (report.floppies < 0)
                {   report.floppies = 0;
                    GT_SetGadgetAttrs
                    (   IN13_Floppies,
                        MainWindowPtr,
                        NULL,
                        GTIN_Number, report.floppies,
                        TAG_DONE
                    );
                } elif (report.floppies > 3)
                {   report.floppies = 3;
                    GT_SetGadgetAttrs
                    (   IN13_Floppies,
                        MainWindowPtr,
                        NULL,
                        GTIN_Number, report.floppies,
                        TAG_DONE
                    );
        }   }   }
        elif (class == IDCMP_GADGETDOWN)
        {   if (addr == MX13_Model)
                report.model = code;
            elif (addr == MX13_CPU)
                report.cpu = code;
            elif (addr == MX13_Agnus)
            {   report.agnus = code;
}   }   }   }

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

        strcpy(string, "Version ");
	strcat
	(   string,
            ((struct StringInfo *) ST11_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 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
        (   ST11_Version,
	    MainWindowPtr,
	    NULL,
	    GTST_String, IOBuffer,
	    TAG_DONE
	);
}

AGLOBAL void report_die(void)
{   if (SubsystemNodes)
    {   FreeNameNodes(&SubsystemList);
        SubsystemNodes = FALSE;
}   }

AGLOBAL void report_init(void)
{   ULONG i;

    NewList(&SubsystemList);
    for (i = 0; i <= SUBSYSTEMS; i++)
        AddNameToTail(&SubsystemList, subsystems[i].friendly);
    SubsystemNodes = TRUE;

    newreport(FALSE);
}

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

    verynewwindow
    (   SENDERWIDTH, SENDERHEIGHT,
        "Report+: Sender Details",
        BUTTONIDCMP | STRINGIDCMP
    );

    if ((!report.loaded) && 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(166, 22, 256, 12, "_First name:", NULL);
    ST12_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(166, 34, 256, 12, "_Last name:", NULL);
    ST12_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(166, 46, 256, 12, "_Company:", NULL);
    ST12_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(166, 58, 256, 12, "_Phone number:", NULL);
    ST12_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(166, 70, 256, 12, "_Developer number:", NULL);
    ST12_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(166, 82, 256, 12, "_EMail:", NULL);
    ST12_EMail = PrevGadPtr = (struct Gadget *) CreateGadget
    (	STRING_KIND,
	PrevGadPtr,
	&Gadget,
	GTST_String, &(report.email),
	GTST_MaxChars, MEDFIELD,
	GA_TabCycle, TRUE,
        GT_Underscore, '_',
	TAG_DONE
    );

    /* There are 14 gadgets:
       BU99_Right
       BU99_TextEditor
       ST12_FirstName (2 subgadgets)
       ST12_LastName (2 subgadgets)
       ST12_Company (2 subgadgets)
       ST12_Phone (2 subgadgets)
       ST12_Developer (2 subgadgets)
       ST12_EMail (2 subgadgets) */
    drawgadgets(14);

    ActivateGadget(ST12_FirstName, MainWindowPtr, NULL);
    loop();

    if (!report.loaded)
    {   /* 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 *) ST12_LastName->SpecialInfo)->Buffer
        );
        strcat(report.refer, ",");
        strcat
        (   report.refer,
            ((struct StringInfo *) ST12_FirstName->SpecialInfo)->Buffer
        );
        strcat(report.refer, " (");
        strcat
        (   report.refer,
            ((struct StringInfo *) ST12_Company->SpecialInfo)->Buffer
        );
        strcat(report.refer, " ,phone ");
        strcat
        (   report.refer,
            ((struct StringInfo *) ST12_Phone->SpecialInfo)->Buffer
        );
        strcat(report.refer, ")\n");

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

        strcpy(report.referid, "# ReferID: ");
        strcat
        (   report.referid,
            ((struct StringInfo *) ST12_Developer->SpecialInfo)->Buffer
        );
        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 13 ************************************************************** */
    
    UBYTE i;
    	
    verynewwindow
    (   CONFIGWIDTH, CONFIGHEIGHT,
        "Report+: Configuration Details",
        BUTTONIDCMP | STRINGIDCMP | MXIDCMP
    );
    
    /* This only cares about the configuration-information parts of the
       bug report. */
    if ((!report.loaded) && 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;
                break; // for speed
	}   }
        parse(",A=");
        report.cpu = 0;
	for (i = 0; i <= CPUS; i++)
	{   if (!stricmp(string, CPUOptions[i]))
	    {   report.cpu = i;
                break; // for speed
        }   }

	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=");
        // We will have here "AA", "ECS" or "old", but we don't use this.

	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(24, 40, 6 * FONTX, 0, "_Model:", PLACETEXT_ABOVE);
    TE13_ModelText = PrevGadPtr = (struct Gadget *) CreateGadget
    (   TEXT_KIND,
        PrevGadPtr,
        &Gadget,
        GT_Underscore, '_',
        TAG_DONE
    );
    setgadget(24, 40, 0, 0, NULL, PLACETEXT_RIGHT);
    MX13_Model = PrevGadPtr = (struct Gadget *) CreateGadget
    (   MX_KIND,
        PrevGadPtr,
        &Gadget,
        GTMX_Labels, &ModelOptions,
        GTMX_Active, report.model,
        TAG_DONE
    );

    /* Agnus */
    setgadget(160, 40, 13 * FONTX, 0, "Ch_ipset Type:", PLACETEXT_ABOVE);
    TE13_AgnusText = PrevGadPtr = (struct Gadget *) CreateGadget
    (   TEXT_KIND,
	PrevGadPtr,
	&Gadget,
        GT_Underscore, '_',
        TAG_DONE
    );
    setgadget(160, 40, 0, 0, NULL, PLACETEXT_RIGHT);
    MX13_Agnus = PrevGadPtr = (struct Gadget *) CreateGadget
    (   MX_KIND,
	PrevGadPtr,
	&Gadget,
	GTMX_Labels, &AgnusOptions,
	GTMX_Active, report.agnus,
	TAG_DONE
    );

    /* CPU */
    setgadget(160, 120, 10 * FONTX, 0, "_Processor:", PLACETEXT_ABOVE);
    // extra spaces ensure consistent centring
    TE13_CPUText = PrevGadPtr = (struct Gadget *) CreateGadget
    (   TEXT_KIND,
        PrevGadPtr,
        &Gadget,
        GT_Underscore, '_',
        TAG_DONE
    );
    setgadget(160, 120, 0, 0, NULL, PLACETEXT_RIGHT);
    MX13_CPU = PrevGadPtr = (struct Gadget *) CreateGadget
    (   MX_KIND,
        PrevGadPtr,
        &Gadget,
        GTMX_Labels, &CPUOptions,
        GTMX_Active, report.cpu,
        TAG_DONE
    );

    /* chip RAM */
    setgadget(246, 184, 1, 12, "Mb", PLACETEXT_RIGHT);
    TE13_ChipText = PrevGadPtr = (struct Gadget *) CreateGadget
    (   TEXT_KIND,
        PrevGadPtr,
        &Gadget,
        TAG_DONE
    );
    setgadget(188, 184, 64, 12, "_Chip RAM:", NULL);
    ST13_Chip = PrevGadPtr = (struct Gadget *) CreateGadget
    (   STRING_KIND,
        PrevGadPtr,
        &Gadget,
        GTST_String, &(report.chipram),
        GTST_MaxChars, 4,
        GA_TabCycle, TRUE,
        GT_Underscore, '_',
        TAG_DONE
    );

    // slow/fast RAM
    setgadget(246, 196, 1, 12, "Mb", PLACETEXT_RIGHT);
    TE13_FastText = PrevGadPtr = (struct Gadget *) CreateGadget
    (   TEXT_KIND,
        PrevGadPtr,
        &Gadget,
        TAG_DONE
    );
    setgadget(188, 196, 64, 12, "_Slow/fast RAM:", NULL);
    ST13_Fast = PrevGadPtr = (struct Gadget *) CreateGadget
    (   STRING_KIND,
        PrevGadPtr,
        &Gadget,
        GTST_String, &(report.fastram),
        GTST_MaxChars, 4,
        GA_TabCycle, TRUE,
        GT_Underscore, '_',
        TAG_DONE
    );

    /* floppies */
    setgadget(188, 208, 64, 12, "_Number of floppies:", NULL);
    IN13_Floppies = PrevGadPtr = (struct Gadget *) CreateGadget
    (   INTEGER_KIND,
	PrevGadPtr,
	&Gadget,
	GTIN_Number, report.floppies,
	GA_TabCycle, TRUE,
        GT_Underscore, '_',
	TAG_DONE
    );

    /* hard disk controller */
    setgadget(188, 220, 120, 12, "_Hard disk controller:", NULL);
    ST13_Hard = PrevGadPtr = (struct Gadget *) CreateGadget
    (	STRING_KIND,
	PrevGadPtr,
	&Gadget,
	GTST_String, &(report.hard),
	GTST_MaxChars, MEDFIELD,
	GA_TabCycle, TRUE,
        GT_Underscore, '_',
	TAG_DONE
    );

    /* expansion cards */
    setgadget(188, 232, 120, 12, "_Expansion cards:", NULL);
    ST13_Expansion = PrevGadPtr = (struct Gadget *) CreateGadget
    (   STRING_KIND,
        PrevGadPtr,
        &Gadget,
	GTST_String, &(report.expansion),
	GTST_MaxChars, LONGFIELD,
	GA_TabCycle, TRUE,
        GT_Underscore, '_',
	TAG_DONE
    );

    drawgadgets(42);
    ActivateGadget(ST13_Chip, MainWindowPtr, NULL);
    loop();

    strcpy(report.chipram,   ((struct StringInfo *) ST13_Chip->SpecialInfo)->Buffer);
    strcpy(report.fastram,   ((struct StringInfo *) ST13_Fast->SpecialInfo)->Buffer);
    strcpy(report.hard,      ((struct StringInfo *) ST13_Hard->SpecialInfo)->Buffer);
    report.floppies        = ((struct StringInfo *) IN13_Floppies->SpecialInfo)->LongInt;
    if (report.floppies < 0)
    {   report.floppies = 0;
    } elif (report.floppies > 3)
    {   report.floppies = 3;
    }
    strcpy(report.expansion, ((struct StringInfo *) ST13_Expansion->SpecialInfo)->Buffer);

    if (!report.loaded)
    {   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,D=AA");
        break;
        case 1:
            strcat(report.config, "ECS-pal,D=ECS");
        break;
        case 2:
            strcat(report.config, "ECS,D=ECS");
        break;
        case 3:
            strcat(report.config, "old-pal,D=old");
        break;
        default:
            strcat(report.config, "old,D=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 updatereportgadgets(void)
{   // the following command is only needed when New or Open... is the
    // cause of the update.
    GT_SetGadgetAttrs
    (   ST11_Summary,
        MainWindowPtr,
        NULL,
        GTST_String, &(report.summary),
        TAG_DONE
    );

    if (report.type == BUG && report.severity == 3)
    {   report.severity = 0;
    }

    GT_SetGadgetAttrs
    (   CY11_Type,
        MainWindowPtr,
        NULL,
        GTCY_Active, report.type,
        TAG_DONE
    );
    GT_SetGadgetAttrs
    (   LV11_Subsystem,
        MainWindowPtr,
        NULL,
        GTLV_Selected, report.subsystem,
        TAG_DONE
    );

    updateemail();

    if (report.type == BUG)
    {   GT_SetGadgetAttrs
        (   ST11_Pathname,
            MainWindowPtr,
            NULL,
            GTST_String, report.pp,
            GA_Disabled, FALSE,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   BU11_PathnameASL,
            MainWindowPtr,
            NULL,
            GA_Disabled, FALSE,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   ST11_Version,
            MainWindowPtr,
            NULL,
            GTST_String, report.pv,
            GA_Disabled, FALSE,
            TAG_DONE
        );
    } else
    {   GT_SetGadgetAttrs
        (   ST11_Pathname,
            MainWindowPtr,
            NULL,
            GTST_String, report.pp,
            GA_Disabled, TRUE,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   BU11_PathnameASL,
            MainWindowPtr,
            NULL,
            GA_Disabled, TRUE,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   ST11_Version,
            MainWindowPtr,
            NULL,
            GTST_String, report.pv,
            GA_Disabled, TRUE,
            TAG_DONE
        );
    }
    if (report.type == COM)
    {   GT_SetGadgetAttrs
        (   LV11_Subsystem,
            MainWindowPtr,
            NULL,
            GA_Disabled, TRUE,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   ST11_3rdName,
            MainWindowPtr,
            NULL,
            GTST_String, report.thirdname,
            GA_Disabled, FALSE,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   ST11_3rdVer,
            MainWindowPtr,
            NULL,
            GTST_String, report.thirdver,
            GA_Disabled, FALSE,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   ST11_3rdManuf,
            MainWindowPtr,
            NULL,
            GTST_String, report.thirdmanuf,
            GA_Disabled, FALSE,
            TAG_DONE
        );
    } else
    {   GT_SetGadgetAttrs
        (   LV11_Subsystem,
            MainWindowPtr,
            NULL,
            GA_Disabled, FALSE,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   ST11_3rdName,
            MainWindowPtr,
            NULL,
            GTST_String, report.thirdname,
            GA_Disabled, TRUE,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   ST11_3rdVer,
            MainWindowPtr,
            NULL,
            GTST_String, report.thirdver,
            GA_Disabled, TRUE,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   ST11_3rdManuf,
            MainWindowPtr,
            NULL,
            GTST_String, report.thirdmanuf,
            GA_Disabled, TRUE,
            TAG_DONE
        );
    }
    if (report.type == ENH)
    {   GT_SetGadgetAttrs
        (   ST11_Debug,
            MainWindowPtr,
            NULL,
            GTST_String, report.debug,
            GA_Disabled, TRUE,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   CY11_Severity,
            MainWindowPtr,
            NULL,
            GA_Disabled, TRUE,
            GTCY_Active, report.severity,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   ST11_KS,
            MainWindowPtr,
            NULL,
            GTST_String, report.ks,
            GA_Disabled, TRUE,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   ST11_WB,
            MainWindowPtr,
            NULL,
            GTST_String, report.wb,
            GA_Disabled, TRUE,
            TAG_DONE
        );
    } else
    {   GT_SetGadgetAttrs
        (   ST11_Debug,
            MainWindowPtr,
            NULL,
            GTST_String, report.debug,
            GA_Disabled, FALSE,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   CY11_Severity,
            MainWindowPtr,
            NULL,
            GA_Disabled, FALSE,
            GTCY_Active, report.severity,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   ST11_KS,
            MainWindowPtr,
            NULL,
            GTST_String, report.ks,
            GA_Disabled, FALSE,
            TAG_DONE
        );
        GT_SetGadgetAttrs
        (   ST11_WB,
            MainWindowPtr,
            NULL,
            GTST_String, report.wb,
            GA_Disabled, FALSE,
            TAG_DONE
        );
}   }

AGLOBAL void newreport(ABOOL display)
{   ULONG i;

    report.floppies  = 1;
    report.agnus     = 0;
    report.cpu       = 2;
    report.model     = 4;
    report.type      = 0;
    report.severity  = 0;
    report.subsystem = 0;
    strcpy(report.chipram,    "2");
    strcpy(report.fastram,    "6");
    strcpy(report.hard,       "");
    strcpy(report.debug,      "");
    strcpy(report.developer,  "");
    strcpy(report.expansion,  "");
    strcpy(report.summary,    "");
    if (GetVar("Kickstart", report.ks, 6, NULL) == -1)
        report.ks[0] = 0;
    if (GetVar("Workbench", report.wb, 6, NULL) == -1)
        report.wb[0] = 0;
    strcpy(report.pv,         "");
    strcpy(report.pp,         "");
    strcpy(report.thirdname,  "");
    strcpy(report.thirdver,   "");
    strcpy(report.thirdmanuf, "");
    strcpy(report.lastname,   "");
    strcpy(report.firstname,  "");
    strcpy(report.company,    "");
    strcpy(report.phone,      "");
    strcpy(report.email,      "");
    strcpy(report.refer,      "");
    strcpy(report.referid,    "");
    strcpy(report.path,       "");
    strcpy(report.config,     "");
    strcpy(report.output,     "");
    for (i = 0; i <= 5; i++)
    {   report.textfield[i][0] = 0;
    }
    report.loaded = FALSE;

    /* Quicker than strcpy(report.foo, ""); is report.foo[0] = 0;

    Consider linking bug report generator with ID database to
    automatically generate the list of expansion cards. */

    if (display)
    {   updatereportgadgets();
}   }

AGLOBAL void openreport(void)
{   if (asl("~(#?.info)"))
    {   strcpy(report.output, aslresult);
        loadreport();
        if (page == 11)
        {   updatereportgadgets();
}   }   }

AGLOBAL void loadreport(void)
{   ULONG i;

    /* parse() returns when it has moved along and found the specified
       `ending string'. The contents, since last parse(), before the
       `ending string' are returned in string. */

    if (readin(report.output))
    {   report.loaded = TRUE;

        offset = 0;
        parse("# Subject: ");           // skip '# Subject: '
        parse("\n# Type: ");            // goto end of '\n# Type: '
        strcpy(report.summary, string);
        parse("\n# ");
        if (!strcmp(string, "bug"))
        {   report.type = BUG;
        } elif (!strcmp(string, "compat"))
        {   report.type = COM;
        } elif (!strcmp(string, "enhancement"))
        {   report.type = ENH;
        }
        if (report.type != COM)
        {   parse("Subsystem: ");
            parse("\n");
            for (i = 0; i <= SUBSYSTEMS; i++)
            {   if (!strcmp(string, subsystems[i].unfriendly))
                {   report.subsystem = i;
                    break;
        }   }   }
        else
        {   parse("ProductName: ");
            parse(" (vers=");
            strcpy(report.thirdname,  string);
            parse(")\n# ProductInfo: :");
            strcpy(report.thirdver,   string);
            parse(":\n");
            strcpy(report.thirdmanuf, string);
        }
        parse("# Severity: ");
        parse("\n# ");
        if (!strcmp(string, "a"))
        {   report.severity = 0;
        } elif (!strcmp(string, "b"))
        {   report.severity = 1;
        } elif (!strcmp(string, "c"))
        {   report.severity = 2;
        } elif (!strcmp(string, "ok"))
        {   report.severity = 3;
        } elif (!strcmp(string, "e"))
        {   report.type     = ENH;
        }

        if (report.type != ENH)
        {   parse("Release: KS=");
            parse(",WB=");
            strcpy(report.ks, string);
            if (report.type == BUG)
            {   parse(",Program=");
                strcpy(report.wb, string);
                parse("\n");
                strcpy(report.pv, string);
            } else
            {   // assert(report.type == COM);
                parse("\n");
                strcpy(report.wb, string);
                report.pv[0] = 0;
            }
        } else report.pv[0] = 0;
        parse("# Date: ");

        // now sender fields
        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);

        // now config fields
        parse("# Config: ");
	parse(",");
	report.model = 4;
	for (i = 0; i <= MODELS; i++)
	{   if (!stricmp(string, ModelOptions[i]))
	    {   report.model = i;
                break; // for speed
	}   }
        parse(",A=");
        report.cpu = 0;
	for (i = 0; i <= CPUS; i++)
	{   if (!stricmp(string, CPUOptions[i]))
	    {   report.cpu = i;
                break; // for speed
        }   }

	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=");
        // We will have here "AA", "ECS" or "old", but we don't use this.

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

        report.pp[0] = 0;

        if (report.type == BUG)
        {   parse("### BRIEF BUG DESCRIPTION:\n");
            parse("\n### BUG GENERATION PROCEDURE OR EXAMPLE:\n");
            strcpy(report.textfield[0], string);     // bug description
            parse("\n### ALSO RUNNING:\n");
            strcpy(report.textfield[1], string);     // bug procedure
            parse("\n### IF THIS WORKS DIFFERENTLY ON OTHER VERSIONS "
                  "OR HARDWARE, EXPLAIN:\n");
            strcpy(report.debug, string);            // also running
            parse("\n### RELATED PROBLEMS:\n");
            strcpy(report.textfield[2], string);     // explain differently
            parsetoend();
            strcpy(report.textfield[3], string);     // related problems
        } elif (report.type == COM)
        {   if (report.severity != 3)
            {   parse("### BRIEF BUG DESCRIPTION:\n");
                parse("\n### BUG GENERATION PROCEDURE OR EXAMPLE:\n");
                strcpy(report.textfield[0], string); // bug description
                parse("\n### ALSO RUNNING:\n");
                strcpy(report.textfield[1], string); // bug procedure
                parse("\n### IF THIS WORKS DIFFERENTLY ON OTHER VERSIONS "
                      "OR HARDWARE, EXPLAIN:\n");
                strcpy(report.debug, string);        // also running
                parse("\n### WHAT DEVELOPER IS DOING IN THAT AREA OF SW "
                      "OR HW:\n");
                strcpy(report.textfield[2], string); // explain differently
                parse("\n### RELATED PROBLEMS:\n");
                strcpy(report.textfield[3], string); // what doing?
                parsetoend();
                strcpy(report.textfield[4], string); // related problems
            } else
            {   parse("### BRIEF BUG DESCRIPTION:\n");
                parse("\n### BUG GENERATION PROCEDURE OR EXAMPLE:\n");
                strcpy(report.textfield[0], string); // bug description
                parse("\n### WHAT DEVELOPER IS DOING IN THAT AREA OF SW "
                      "OR HW:\n");
                strcpy(report.textfield[1], string); // explain differently
                parse("\n### RELATED PROBLEMS:\n");
                strcpy(report.textfield[2], string); // what doing?
                parsetoend();
                strcpy(report.textfield[3], string); // related problems
        }   }
        else
        {   // assert(report.type == ENH);
            parse("### ENHANCEMENT REQUEST:\n");
            parsetoend();
            strcpy(report.textfield[0], string);
        }
        updatereportgadgets();
}   }

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

AGLOBAL void report2(void)
{   struct Hook    Hook1Struct;
    STRPTR         textBuffer[MAXELEMENTS_1 + 1];
    TEXT           GadTitle[MAXELEMENTS_1 + 1][VLONGFIELD + 1];
    ULONG          i, counter, elements;
    struct TagItem tag_texteditor[4] =
    { { GA_ID,                    NULL                  }, // ti_Data filled later
      { GA_RelVerify,             TRUE                  },
      { GA_TEXTEDITOR_ExportWrap, 75                    },
      { TAG_END,                  NULL                  }
    }, tag_subcaption[3] =
    { { LABEL_Text,               NULL                  }, // ti_Data filled later
      { LABEL_Justification,      LJ_CENTRE             },
      { TAG_END,                  NULL                  }
    }, tag_button[4] =
    { { GA_ID,                    GID_1_BU1             },
      { GA_RelVerify,             TRUE                  },
      { GA_Text,                  (ULONG) "_Other page" },
      { TAG_END,                  NULL                  }
    }, tag_supercaption[7] =
    { { LAYOUT_Orientation,       LAYOUT_ORIENT_VERT    },
      { LAYOUT_SpaceOuter,        TRUE                  },
      { LAYOUT_VertAlignment,     LALIGN_CENTER         },
      { LAYOUT_HorizAlignment,    LALIGN_CENTER         },
      { LAYOUT_BevelStyle,        BVS_NONE              },
      { LAYOUT_AddImage,          NULL                  }, // ti_Data filled later
      { TAG_END,                  NULL                  }
    }, tag_onlylayout[19] =
    { { LAYOUT_Orientation,       LAYOUT_ORIENT_VERT    },
      { LAYOUT_SpaceOuter,        TRUE                  },
      { LAYOUT_DeferLayout,       TRUE                  },
      { LAYOUT_AddChild,          NULL                  }, // ti_Data filled later
      { CHILD_WeightedHeight,     0                     },
      { LAYOUT_AddChild,          NULL                  }, // ti_Data filled later
      { LAYOUT_AddChild,          NULL                  }, // ti_Data filled later
      { CHILD_WeightedHeight,     0                     },
      { LAYOUT_AddChild,          NULL                  }, // ti_Data filled later
      { LAYOUT_AddChild,          NULL                  }, // ti_Data filled later
      { CHILD_WeightedHeight,     0                     },
      { LAYOUT_AddChild,          NULL                  }, // ti_Data filled later
      { LAYOUT_AddChild,          NULL                  }, // ti_Data filled later
      { CHILD_WeightedHeight,     0                     },
      { LAYOUT_AddChild,          NULL                  }, // ti_Data filled later
      { LAYOUT_AddChild,          NULL                  }, // ti_Data filled later
      { CHILD_WeightedHeight,     0                     },
      { LAYOUT_AddChild,          NULL                  }, // ti_Data filled later
      { TAG_END,                  NULL                  }
    }, tag_rootlayout[10] =
    { { LAYOUT_Orientation,    LAYOUT_ORIENT_VERT    },
      { LAYOUT_SpaceOuter,     TRUE                  },
      { LAYOUT_DeferLayout,    TRUE                  },
      { LAYOUT_AddChild,       NULL                  }, // ti_Data filled later
      { CHILD_WeightedHeight,  100,                  },
      { LAYOUT_AddChild,       NULL                  }, // ti_Data filled later
      { CHILD_WeightedHeight,  0                     },
      { LAYOUT_AddChild,       NULL                  }, // ti_Data filled later
      { CHILD_WeightedHeight,  0                     },
      { TAG_END,               NULL                  }
    }, tag_window[15] =
    { { WA_PubScreen,          NULL                                            }, // ti_Data filled later
      { WA_ScreenTitle,        (ULONG) "Report+"                               },
      { WA_Title,              (ULONG) "Report+: Report Details (Page 2 of 2)" },
      { WA_Activate,           TRUE                  },
      { WA_DepthGadget,        TRUE                  },
      { WA_DragBar,            TRUE                  },
      { WA_CloseGadget,        TRUE                  },
      { WA_SizeGadget,         TRUE                  },
      { WA_IDCMP,              IDCMP_RAWKEY          },
      { WINDOW_IDCMPHook,      NULL                  }, // ti_Data filled later
      { WINDOW_IDCMPHookBits,  IDCMP_RAWKEY          },
      { WINDOW_MenuStrip,      NULL                  }, // ti_Data filled later
      { WINDOW_Position,       WPOS_FULLSCREEN       },
      { WINDOW_ParentGroup,    NULL                  }, // ti_Data filled later
      { TAG_END,               NULL                  }
    };

    switch(report.type)
    {
    case BUG:
        strcpy(GadTitle[0], "Brief bug _description:");
        strcpy(GadTitle[1], "_Bug generation procedure or example:");
        strcpy(GadTitle[2], "_If this works differently on other versions or hardware, explain:");
        strcpy(GadTitle[3], "_Related problems:");
        elements = 3;
    break;
    case COM:
        if (report.severity == 3)
        {   strcpy(GadTitle[0], "_If this works differently on other versions or hardware, explain:");
            elements = 0;
        } else
        {   strcpy(GadTitle[0], "Brief bug _description:");
            strcpy(GadTitle[1], "_Bug generation procedure or example:");
            strcpy(GadTitle[2], "_If this works differently on other versions or hardware, explain:");
            strcpy(GadTitle[3], "_What developer is doing in that area of software or hardware:");
            strcpy(GadTitle[4], "_Related problems:");
            elements = 4;
        }
        break;
    case ENH:
        strcpy(GadTitle[0], "_Enhancement request:");
        elements = 0;
    break;
    default:
    break;
    }

    /* window
        root-layout
         only-layout
          super-caption
           sub-caption
          texteditor
         button
         button */

    counter = 3;
    for (i = 0; i <= elements; i++)
    {   tag_subcaption[0].ti_Data          = (ULONG) GadTitle[i];
        tag_texteditor[0].ti_Data          = GID_1_TE1 + i;
        tag_supercaption[5].ti_Data        = (ULONG) NewObjectA(LABEL_GetClass(),      NULL, tag_subcaption);
        tag_onlylayout[counter].ti_Data    = (ULONG) NewObjectA(LAYOUT_GetClass(),     NULL, tag_supercaption);
        counter += 2;
        tag_onlylayout[counter].ti_Data    =
        report_gadgets[GID_1_TE1 + i]      = (ULONG) NewObjectA(TEXTEDITOR_GetClass(), NULL, tag_texteditor);
        counter++;
    }
    tag_onlylayout[counter].ti_Tag         = TAG_END;

    tag_rootlayout[3].ti_Data   = (ULONG) NewObjectA(LAYOUT_GetClass(), NULL,            tag_onlylayout);
    tag_rootlayout[5].ti_Data   =
    report_gadgets[GID_1_BU1]   = (ULONG) NewObjectA(NULL,              "button.gadget", tag_button);
    tag_button[0].ti_Data       = GID_1_BU2;
    tag_button[2].ti_Data       = (ULONG) "Menu";
    tag_rootlayout[7].ti_Data   =
    report_gadgets[GID_1_BU2]   = (ULONG) NewObjectA(NULL,              "button.gadget", tag_button);
    tag_window[13].ti_Data      =
    report_gadgets[GID_1_LY1]   = (ULONG) NewObjectA(LAYOUT_GetClass(), NULL,            tag_rootlayout);

    InitHook(&Hook1Struct, Hook1Func, NULL);
    tag_window[9].ti_Data       = &Hook1Struct;
    lockscreen();
    tag_window[0].ti_Data       = (ULONG) ScreenPtr;
    gadtools();
    tag_window[11].ti_Data      = MenuPtr;
    WinObject[1]                = (ULONG) NewObjectA(WINDOW_GetClass(), NULL,             tag_window);
    unlockscreen();
    if (!WinObject[1]) // Object creation successful?
    {   rq("Can't create ReAction objects!");
    }
    openwindow();
    OnMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVE,   NOSUB));
    OnMenu(MainWindowPtr, FULLMENUNUM(MN_PROJECT, IN_SAVEAS, NOSUB));

    // Do any necessary imports.
    switch(report.type)
    {
    case BUG:
        SetGadgetAttrs
        (   report_gadgets[GID_1_TE1], MainWindowPtr, NULL,
            GA_TEXTEDITOR_Contents,    report.textfield[0]
        );
        SetGadgetAttrs
        (   report_gadgets[GID_1_TE2], MainWindowPtr, NULL,
            GA_TEXTEDITOR_Contents,    report.textfield[1]
        );
        SetGadgetAttrs
        (   report_gadgets[GID_1_TE3], MainWindowPtr, NULL,
            GA_TEXTEDITOR_Contents,    report.textfield[2]
        );
        SetGadgetAttrs
        (   report_gadgets[GID_1_TE4], MainWindowPtr, NULL,
            GA_TEXTEDITOR_Contents,    report.textfield[4]
        );
    break;
    case COM:
        if (report.severity == 3)
        {   SetGadgetAttrs
            (   report_gadgets[GID_1_TE1],         MainWindowPtr, NULL,
                GA_TEXTEDITOR_Contents,            report.textfield[2]
            ); // if this works differently...
        } else
        {   for (i = 0; i <= 4; i++)
            {   SetGadgetAttrs
                (   report_gadgets[GID_1_TE1 + i], MainWindowPtr, NULL,
                    GA_TEXTEDITOR_Contents,        report.textfield[i]
                );
        }   }
    break;
    case ENH:
        SetGadgetAttrs
        (   report_gadgets[GID_1_TE1], MainWindowPtr, NULL,
            GA_TEXTEDITOR_Contents,    report.textfield[5]
        ); // enhancement request
    break;
    default:
        ; // assert(0);
    break;
    }

    /* 0: brief bug description
       1: bug generation procedure or example
       2: if this works differently...
       3: what developer is doing...
       4: related problems
       5: enhancement request */

    ActivateLayoutGadget(report_gadgets[GID_1_LY1], MainWindowPtr, NULL, (Object) report_gadgets[GID_1_TE1]);
    loop();

    for (i = 0; i <= elements; i++)
    {   textBuffer[i] = (STRPTR) DoGadgetMethod(report_gadgets[GID_1_TE1 + i], MainWindowPtr, NULL, GM_TEXTEDITOR_ExportText, NULL);
    }
    switch(report.type)
    {
    case BUG:
        strcpy(report.textfield[0], textBuffer[0]); // brief bug description
        strcpy(report.textfield[1], textBuffer[1]); // bug generation procedure or example
        strcpy(report.textfield[2], textBuffer[2]); // if this works differently...
        strcpy(report.textfield[4], textBuffer[3]); // related problems
    break;
    case COM:
        if (report.severity == 3)
        {   strcpy(report.textfield[2], textBuffer[0]); // if this works differently...
        } else
        {   strcpy(report.textfield[0], textBuffer[0]); // brief bug description
            strcpy(report.textfield[1], textBuffer[1]); // bug generation procedure or example
            strcpy(report.textfield[2], textBuffer[2]); // if this works differently...
            strcpy(report.textfield[3], textBuffer[3]); // what developer is doing...
            strcpy(report.textfield[4], textBuffer[4]); // related problems
        }
    break;
    case ENH:
        strcpy(report.textfield[5], textBuffer[0]); // enhancement request
    break;
    default:
        ; // assert(0);
    break;
    }

    for (i = 0; i <= elements; i++)
    {   FreeVec((APTR) textBuffer[i]);
        textBuffer[i] = NULL;
    }
    closewindow();
}

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

    UWORD code, qual;

    geta4(); // wait till here before doing anything
    code = ((struct IntuiMessage *) msg)->Code;
    qual = ((struct IntuiMessage *) msg)->Qualifier;
    switch(code)
    {
    case SCAN_HELP:
        helpabout();
    break;
    case SCAN_ESCAPE:
        if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
        {   cleanexit(EXIT_SUCCESS);
        } else
        {   page = 0;
        }
    break;
    case SCAN_B:
        if (report.type == BUG || (report.type == COM && report.severity != 3))
        {   ActivateLayoutGadget(report_gadgets[GID_1_LY1], MainWindowPtr, NULL, (Object) report_gadgets[GID_1_TE2]);
        } // "_bug generation procedure or example", when present, is always GID_1_TE2.
    break;
    case SCAN_D:
        if (report.type == BUG || (report.type == COM && report.severity != 3))
        {   ActivateLayoutGadget(report_gadgets[GID_1_LY1], MainWindowPtr, NULL, (Object) report_gadgets[GID_1_TE1]);
        } // "brief bug _description", when present, is always GID_1_TE1.
    break;
    case SCAN_E:
        if (report.type == ENH)
        {   ActivateLayoutGadget(report_gadgets[GID_1_LY1], MainWindowPtr, NULL, (Object) report_gadgets[GID_1_TE1]);
        } // "_enhancement request", when present, is always GID_1_TE1.
    break;
    case SCAN_I:
        if (report.type == BUG || (report.type == COM && report.severity != 3))
        {   ActivateLayoutGadget(report_gadgets[GID_1_LY1], MainWindowPtr, NULL, (Object) report_gadgets[GID_1_TE3]);
        } elif (report.type == COM && report.severity == 3)
        {   ActivateLayoutGadget(report_gadgets[GID_1_LY1], MainWindowPtr, NULL, (Object) report_gadgets[GID_1_TE1]);
        }
    break;
    case SCAN_R:
        if (report.type == BUG)
        {   ActivateLayoutGadget(report_gadgets[GID_1_LY1], MainWindowPtr, NULL, (Object) report_gadgets[GID_1_TE4]);
        } elif (report.type == COM && report.severity != 3)
        {   ActivateLayoutGadget(report_gadgets[GID_1_LY1], MainWindowPtr, NULL, (Object) report_gadgets[GID_1_TE5]);
        }
    break;
    case SCAN_W:
        if (report.type == COM && report.severity != 3)
        {   ActivateLayoutGadget(report_gadgets[GID_1_LY1], MainWindowPtr, NULL, (Object) report_gadgets[GID_1_TE3]);
        } // "_what developer is doing...", when present, is always GID_1_TE4.
    break;
    default:
    break;
    }

    return(1);
}

MODULE void updateemail(void)
{   if
    (   (!stricmp(subsystems[report.subsystem].unfriendly, "wormwars"))
     || (!stricmp(subsystems[report.subsystem].unfriendly, "report+"))
    )
    {   GT_SetGadgetAttrs
        (   TE11_EMailTo,
            MainWindowPtr,
            NULL,
            GTTX_Text, "amigansoftware@altavista.com",
            TAG_DONE
        );
    } else
    {   GT_SetGadgetAttrs
        (   TE11_EMailTo,
            MainWindowPtr,
            NULL,
            GTTX_Text, "support@haage-partner.com",
            TAG_DONE
        );
}   }

