/* : ai=0 bk=0 ts=8 */
#include "mm.h"

#define FREEPEN -1L           /* workbench screen default colors */
#define REQ_WINDOW_WIDTH 319L /* width of SFMem warning requester window */
#define REQ_WINDOW_HEIGHT 79L /* height of SFMem warning requester window */

#define SOK        0x001f     /* memory allocation control masks */
#define S1         0x0001
#define S2         0x0002
#define S4         0x0004
#define S8         0x0008
#define SA         0x0010
#define C1         0xfffe
#define C2         0xfffd
#define C4         0xfffb
#define C8         0xfff7
#define CA         0xffef
#define AARRRGH    20L

#define EXTENSION  16L         /* allocation request increment */

#define FRAGS FALSE                          /* frags mode control boolian */
#define WARPS TRUE		             /* warps mode control boolian */
#define EVENMASK 0x7ffffffe           /* used to prevent odd address traps */
#define CLIHEIGHT 200L                             /* window scaling stuff */
#define SIZEGAD 9L
#define DRAGBAR 10L
#define BORDER 2L
#define WINW 16L                                   /* initial window width */
#define WINH (long)(CLIHEIGHT - SIZEGAD - DRAGBAR)   /* initial win height */
#define MINH 81L                              /* shortest allowable window */
#define MAXH 576L                              /* longest allowable window */
#define BART 1L                               /* title bar F text location */
#define BARH (long)(WINH - SIZEGAD - DRAGBAR)                /* bar height */
#define BARS (long)(BARH + 1)        /* number of memory items to allocate */
#define BARB (long)(BARH + DRAGBAR - 1)        /* bottom of mercury column */
#define BARE (long)(BARB + BORDER)              /* bar end E text position */
#define BARW (long)(((WINW - (2 * BORDER)) / 3) - 1)  /* 3 memfragmometers */
#define LEFT BORDER                   /* SLOW : since we're syncopated, we */
#define MIDDLE (LEFT + BARW + 1)      /* SLOW-FAST : do it going from bar  */
#define RIGHT (MIDDLE + BARW + 1)     /* FAST :to bar at an irregular pace */
#define RTEXT - 4L        /* offset for three char E/F text from left edge */
#define STARTVAL 64L    /* start by getting enough storage for a few frags */

/* typedef short BOOL */        /* this is in include/exec/types.h */

struct IntuitionBase *IntuitionBase=NULL ;
struct Window *window ;
struct IntuiMessage *message;
/* struct IntuiMessage *GetMsg(); */        /* in functions.h */

struct GfxBase *GfxBase=NULL ;

struct IOStdReq *timermsg=NULL;
struct MsgPort *timerport=NULL;
ULONG  timerbit=NULL;


extern void InitProjItems();        /* this stuff is in the mminit section */
extern void InitSetupItems();
extern void InitPrioItems();
extern void InitChipItems();
extern void InitChipAItems();
extern void InitSFItems();
extern void InitSFAItems();
extern void InitFastItems();
extern void InitFastAItems();
extern void InitMenu();
extern void StartMenus();

BOOL p_mode = FRAGS;          /* preset frags mode = 0, warps mode = 1 */
                              /* note: mode preset used as request for */
                              /*       change to warps mode after the  */
                              /*       first pass with frags mode set! */
long p_rate = 2;              /* preset sample interval, secs see menu */
long p_priority = 0;          /* preset priority, range -128 to +127   */
                              /* note: pri greater than zero is risky! */
                              /* keep in mind AmigaDOS priorities:     */
                              /* input.device 20, FileSystem 10, and   */
                              /* trackdisk.device, CON: 5 also if MM   */
                              /* is started from a CLI without the Run */
                              /* then that CLI inherits MM's priority! */
long p_chip = 512;            /* preset chip mem size, kbytes see menu */
long p_chipa = 0;             /* preset chip mem address, kb  see menu */
long p_sf = 0;                /* preset slowfast mem size, kb see menu */
long p_sfa = 0x3000;          /* preset slowfast mem addr, kb see menu */
long p_fast = 0;              /* preset fast mem size, mbytes see menu */
long p_fasta = 2;             /* preset fast mem addr, mbytes see menu */

static BOOL mode;                    /* uninitialized for mode control */
static BOOL mmode;                   /* uninitialized for mode  menu */
static long delayval;                /* uninitialized for delay menu */
static long priority;                /* uninitialized for priority menu */
static long lastpri;                 /* uninitialized for priority incr */
static long cmemsize;                /* uninitialized for chip  menu */
static long cmembase;                /* uninitialized for chipa menu */
static long sfmemsize;               /* uninitialized for sf    menu */
static long sfmembase;               /* uninitialized for sfa   menu */
static long fmemsize;                /* uninitialized for fast  menu */
static long fmembase;                /* uninitialized for fasta menu */

static USHORT log ;                  /* memory allocation success flags */
static BOOL things_are_cool = TRUE ; /* tells when to close the window  */
static BOOL intsig = FALSE ;         /* intuition message detector */
static USHORT chgflag = TRUE ;       /* menu request to adjust columns */
static long chip[3], fast[3] ;       /* place to keep mem header pointers */
static ULONG  *chunkv ;              /* demand allocated for frag chunks */
static ULONG  *sizev ;               /* demand allocated for frag sizes */
static ULONG  *csum ;                /* a col's height worth of checksums */
static ULONG  *oldcsum ;             /* same height worth of old checksums */
static USHORT *cell;                 /* 1 cell per pixel height of mercury */
static long xl, xr ;                 /* used to Draw() memometer segments */
static long frags = STARTVAL ;       /* # of demand allocated frag items */
static long warps = BARS ;           /* # of demand allocated column items */
static long barh = BARH ;            /* EVEN #'d height of mercury column */
static long barb = BARB ;            /* bottom position of mercury column */

/* struct RastPort *rp ; */          /* wonder why we don't need this... ? */


static struct TextAttr myfont = {
   (STRPTR) "topaz.font",
   TOPAZ_EIGHTY,
   0,
   0
};
/* E newsize gadget refresh text */ 
static char ebuf[4] = " E " ;
static struct IntuiText e_text = { 
   BLUP, WHTP,
   JAM2, 
   0, BARE,
   &myfont,
   (UBYTE *)ebuf, 
   NULL 
};
/* F title refresh text */
static char fbuf[4] = " F " ;
static struct IntuiText f_text = {
   BLUP, WHTP,
   JAM2,
   0, BART,
   &myfont,
   (UBYTE *)fbuf,
   &e_text
};
static struct NewWindow newwindow = {
   0,                                        /* left edge */
   10,                                       /* top edge */
   WINW,                                     /* width */
   WINH,                                     /* height */
   0,                                        /* detail pen */
   1,                                        /* block pen */
   MENUPICK | NEWSIZE,                       /* messages */
/* WINDOWDEPTH | WINDOWCLOSE */              /* don't use these gads */
   WINDOWDRAG | WINDOWSIZING | SMART_REFRESH,   /* add a few gadgets */
   NULL,                                     /* no custom gadgets */
   NULL,                                     /* default checkmark */
   (UBYTE *)"F",                             /* title */
   NULL,                                     /* initialize this! */
   NULL,                                     /* use screen bitmap */
   WINW, MINH, WINW, MAXH,                   /* min and max sizes */
   WBENCHSCREEN } ;                          /* use workbench screen */

void initmenus()
{
   (void) InitProjItems();              /* Initialize the menu items */
   (void) InitSetupItems();
   (void) InitPrioItems();
   (void) InitChipItems();
   (void) InitChipAItems();
   (void) InitSFItems();
   (void) InitSFAItems();
   (void) InitFastItems();
   (void) InitFastAItems();
   (void) InitMenu();
   (void) StartMenus();
   }

void handle_MENUPICK( class, code )
unsigned long class;
unsigned int code;
{
    unsigned int menunum, itemnum, subnum;

    if (code == MENUNULL) return;

    menunum = MENUNUM( code );
    itemnum = ITEMNUM( code );
    subnum  = SUBNUM( code );
    chgflag = TRUE;
    switch( menunum ) {
        case 0:
        switch( itemnum ) {
            case 0:
            WindowToFront(window);
            break;

            case 1:
            WindowToBack(window);
            break;

            case 2:
            things_are_cool = FALSE;  /* Quit */
            break;
            } /* end of switch ( Project itemnum ) */
        break;

        case 1:
        switch( itemnum ) {
            case 0:
            switch( subnum ) {
                case 0:
                mode = FRAGS ;  /* Frags mode */
                break;

                case 1:
                mmode = TRUE ;  /* Warps request */
                break;
                /* end of switch ( Mode subnum ) */
                }
            break;       
            case 1:
            switch( subnum ) {
                case 0:
                delayval = 1;
                break;

                case 1:
                delayval = 2;
                break;

                case 2:
                delayval = 5;
                break;

                case 3:
                delayval = 10;
                break;
                /* end of switch ( Freq subnum ) */
                }
            break;       
            /* end of switch ( Setup itemnum ) */
            }
        break;

        case 2:
        switch( itemnum ) {
            case  0:
            priority = lastpri;
            break;

            case  1:
            priority = priority - 1;
            break;

            case  2:
            priority = priority + 1;
            break;

            case  3:
            priority = -99;
            lastpri = priority;
            break;

            case  4:
            priority = -75;
            lastpri = priority;
            break;

            case  5:
            priority = -50;
            lastpri = priority;
            break;

            case  6:
            priority = -25;
            lastpri = priority;
            break;

            case  7:
            priority = -20;
            lastpri = priority;
            break;

            case  8:
            priority = -15;
            lastpri = priority;
            break;

            case  9:
            priority = -10;
            lastpri = priority;
            break;

            case 10:
            priority =  -5;
            lastpri = priority;
            break;

            case 11:
            priority =   0;
            lastpri = priority;
            break;

            case 12:
            priority =   5;
            lastpri = priority;
            break;

            case 13:
            priority =  10;
            lastpri = priority;
            break;

            case 14:
            priority =  15;
            lastpri = priority;
            break;

            case 15:
            priority =  20;
            lastpri = priority;
            break;
            }
            /* end of switch ( Priority itemnum ) */
        break;

        case 3:
        switch( itemnum ) {
            case 0:
            cmemsize = 0x000000;
            break;

            case 1:
            cmemsize = 0x040000;
            break;

            case 2:
            cmemsize = 0x080000;
            break;

            case 3:
            cmemsize = 0x100000;
            break;

            case 4:
            cmemsize = 0x200000;
            break;
            }
            /* end of switch ( Chip Size itemnum ) */
        break;

        case 4:
        switch( itemnum ) {
            case 0:
            cmembase = 0x000000;
            break;

            case 1:
            cmembase = 0x040000;
            break;

            case 2:
            cmembase = 0x080000;
            break;

            case 3:
            cmembase = 0x100000;
            break;
            }
            /* end of switch ( Chip Addr itemnum ) */
        break;

        case 5:
        if (mode == WARPS)  mmode = TRUE ;
        switch( itemnum ) {
            case 0:
            sfmemsize = 0x000000;
            break;

            case 1:
            sfmemsize = 0x080000;
            break;

            case 2:
            sfmemsize = 0x100000;
            break;

            case 3:
            sfmemsize = 0x180000;
            break;
            }
            /* end of switch ( SF Size itemnum ) */
        break;

        case 6:
        if (mode == WARPS)  mmode = TRUE ;
        switch( itemnum ) {
            case 0:
            sfmembase = 0xc00000;
            break;

            case 1:
            sfmembase = 0xc80000;
            break;

            case 2:
            sfmembase = 0xd00000;
            break;

            case 3:
            sfmembase = 0xd80000;
            break;
            }
            /* end of switch ( SF Addr itemnum ) */
        break;

        case 7:
        switch( itemnum ) {
            case 0:
            fmemsize = 0x000000;
            break;

            case 1:
            fmemsize = 0x080000;
            break;

            case 2:
            fmemsize = 0x100000;
            break;

            case 3:
            fmemsize = 0x200000;
            break;

            case 4:
            fmemsize = 0x400000;
            break;

            case 5:
            fmemsize = 0x600000;
            break;

            case 6:
            fmemsize = 0x800000;
            break;
            }
            /* end of switch ( Fast Size itemnum ) */
        break;

        case 8:
        if (mode == WARPS)  mmode = TRUE ;
        switch( itemnum ) {
            case 0:
            fmembase = 0x200000;
            break;

            case 1:
            fmembase = 0x300000;
            break;

            case 2:
            fmembase = 0x400000;
            break;

            case 3:
            fmembase = 0x500000;
            break;

            case 4:
            fmembase = 0x600000;
            break;

            case 5:
            fmembase = 0x700000;
            break;

            case 6:
            fmembase = 0x800000;
            break;

            case 7:
            fmembase = 0x900000;
            break;
            }
            /* end of switch ( Fast Addr itemnum ) */
        break;
        }
        /* end of switch ( menunum ) */
}

void wrack_sploot() /* this subprogram cashes in the chips in bad times */
    {
    if (log != 0) {
        if (log & SA) {
            (void) FreeMem(oldcsum, (long)(sizeof(ULONG) * warps)) ;
            log = log & CA ;
            }
        if (log & S8) {
            (void) FreeMem(csum, (long)(sizeof(ULONG) * warps)) ;
            log = log & C8 ;
            }
        if (log & S4)  {
            (void) FreeMem(sizev, (long)(sizeof(long) * frags)) ;
            log = log & C4 ;
            }
        if (log & S2)  {
            (void) FreeMem(chunkv, (long)(sizeof(long) * frags)) ;
            log = log & C2 ;
            }
        if (log & S1) {
            (void) FreeMem(cell, (long)(sizeof(USHORT) * warps)) ;
            log = log & C1 ;
            }
        frags = 0;
        warps = 0;
        }
}

SetTimer(sec, micro, timermsg)
ULONG sec, micro;
struct IOStdReq *timermsg;
/* This routine simply sets the timer to interrupt us after secs.micros */
{
    timermsg->io_Command = TR_ADDREQUEST;    /* add a new timer request */
    timermsg->io_Actual = sec;    /* seconds */
    timermsg->io_Length = micro;    /* microseconds */
    SendIO(timermsg);   /* post a request to the timer */
}

void cleanup() {
    if (timerport) {
        Wait(timerbit);
        GetMsg(timerport);
        CloseDevice(timermsg);
        DeleteStdIO(timermsg);
        DeletePort(timerport);
        }
    if (GfxBase)        CloseLibrary(GfxBase) ;
    if (window)         CloseWindow(window) ;
    if (IntuitionBase)  CloseLibrary(IntuitionBase) ;
    wrack_sploot() ;
    exit(AARRRGH) ;
}

void inittimer() {
    if(!(timerport = (struct MsgPort *)CreatePort(0L, 0L)))cleanup();
    if(!(timermsg = (struct IOStdReq *)CreateStdIO(timerport)))cleanup();
    if (OpenDevice(TIMERNAME, UNIT_VBLANK, timermsg, 0L))cleanup();

    timerbit = 1L << timerport->mp_SigBit ;
    SetTimer(1L, 0L, timermsg); /* set for first message */
}

void handle_NEWSIZE() /* short term allocations cashed in then realloc'd */
    {                 /* when user hits gadget but doesn't resize window */
    if (log & SA)  {
        (void) FreeMem(oldcsum, (long)(sizeof(ULONG) * warps)) ;
        log = log & CA ;
        }
    if (log & S8)  {
        (void) FreeMem(csum, (long)(sizeof(ULONG) * warps)) ;
        log = log & C8 ;
        }
    if (log & S1)  {
        (void) FreeMem(cell, (long)(sizeof(USHORT) * warps)) ;
        log = log & C1 ;
    barh = window->Height - SIZEGAD - DRAGBAR ;  /* recalculate height */
    barb = window->Height - SIZEGAD - 1 ; /* get new bar base position */
    warps = barh + 1 ;       /* number of storage cells to be reserved */
    if ((cell = (USHORT *)AllocMem((long)sizeof(USHORT) * warps,
                                    MEMF_PUBLIC)) != 0L ) log = log | S1;
    if ((csum = (ULONG *)AllocMem((long)sizeof(ULONG) * warps,
                                    MEMF_PUBLIC)) != 0L ) log = log | S8;
    if ((oldcsum = (ULONG *)AllocMem((long)sizeof(ULONG) * warps,
                                    MEMF_PUBLIC)) != 0L ) log = log | SA;
    if (log != SOK)  {      /* bail out if we didn't get an allocation */
        wrack_sploot() ;
        things_are_cool = FALSE ;     /* tell _main that we're leaving */
        }
    e_text.TopEdge = barb + BORDER ;        /* set the E text position */
    }
}

void handle_MESSAGES()  {
    unsigned long class;
    unsigned int code, qual;

    /* Wait (1L << window->UserPort->mp_SigBit); this is rediculous! */
    while ((message=(struct IntuiMessage *)GetMsg(window->UserPort))
                                                                != 0L) {
        class = message->Class ;
        code = message->Code ;
        qual = message->Qualifier ;
        ReplyMsg ;
        switch( class ) {

            case NEWSIZE:
            intsig = TRUE ;                     /* resize when done here */
            break ;

            case MENUPICK:
            handle_MENUPICK( class, code ) ;    /* do menus ASAP */
            break ;
            }
        }
}

void memometer()                /* this subprogram draws the bar graphs */
    {
    long i;
    long y;

    (void) handle_MESSAGES() ;  /* go see if the user wants anything */
    i = 0 ;
    while ((i < barh) && (intsig == FALSE)) {
        y = barb - i ;
        SetAPen(window->RPort, (long)cell[i]);
        Move(window->RPort, xl, y);
        Draw(window->RPort, xr, y);
        i++ ;
        }
}

void shake()    /* this subprogram slings down the mercury column */
    {
    int i;

    for (i = 0; i < barh; i++)  {
        cell[i] = YELP ;
        }
}

void lockout()  /* this subprogram renders a whole column in border colors */
    {
    (void) handle_MESSAGES() ;        /* go see if the user wants anything */
    if (intsig == FALSE)  {
        SetAPen(window->RPort, WHTP) ;          /* set in the border color */
        RectFill(window->RPort, xl, (barb - barh + 1), xr, barb) ; /* fill */
        }
}

void updatewarps( wf, membase, memseg )  /* this subprogram finds changes */
short wf;
long membase, memseg ;
    {
    register long i ;
    register ULONG r ;
    register ULONG delta ;
    register ULONG *a ;

    if (memseg == 0) {
        (void) lockout() ;
        return ;
        }
    else (void) shake() ;

    delta = (ULONG)(memseg & EVENMASK) ;  /* try to avoid odd address trap */
    r = (ULONG)(membase & EVENMASK) ;     /* prefer wrong address to death */
    for (i = 0; i < barh; i++)  {
        csum[i] = 0 ;
        }
    for (i = 0; i < barh; i++)  {
        for (a = (ULONG *)r; a < (ULONG *)(r + delta); a++)  {
            csum[i] ^= *a ;
            }
        if (oldcsum[i] != 0)  cell[i] ^= GRNP ;       /* enters with pens  */
        if (csum[i] == oldcsum[i])  cell[i] &= GRNP ; /* all on, condition */
        if (csum[i] == 0)  cell[i] ^= CYNP ;          /* detected clears a */
        if (oldcsum[i] == 0xffffffff) cell[i] = CYNP ;/* pen; at the end a */
        if (csum[i] == 0xffffffff)  cell[i] = GRNP ;  /* logical true sets */
        oldcsum[i] = csum[i] ;                        /* a pen not yet set */
        r += delta ;
        }
    (void) memometer();
}

void updatescreen( wf, membase, memseg )
short wf;
long membase, memseg;
    {
    register long size ;
    register struct MemHeader *hdr ;
    register struct MemChunk *chunk ;
    extern struct ExecBase *SysBase ;
    register long *which ;                /* active memlist chunk pointer */
    register long newlimit ;  /* number of chunks, incl 1 null chunk, + 1 */
    register long newfrags ;  /* number of chunks, incl null chunks, + 1  */
    long newsize ;  /* size of next request for chunkv/sizev memory, + 1  */
    int i, j, k, l ;
    int length ;       /* length is number of chunks to be processed, + 1 */
    BOOL cf, nf ;      /* cf is "chip flag" nf is "null chunk found" flag */

    if (memseg == 0) {
        (void) lockout() ;
        return;
        }
    else (void) shake() ;

    for (i = 0; i < 3; i++) {
        chip[i] = 0;
        fast[i] = 0;
        }
    for (i = 0; i < frags; i++) {
        chunkv[i] = 0;
        sizev[i] = 0;
        }
    newfrags = 0 ;
    newlimit = 0 ;
    nf = FALSE;
    Forbid() ;
    hdr = (struct MemHeader *) SysBase->MemList.lh_Head ;
    while (hdr->mh_Node.ln_Succ) {
        if (hdr->mh_Attributes & MEMF_CHIP) {
            which = chip ;
            cf = TRUE;
            }
        else {
            which = fast ;
            cf = FALSE;
            }
        if (((cf == TRUE) && (wf == 0)) || ((cf == FALSE) && (wf > 0)))  {
            for (chunk = hdr->mh_First; chunk; chunk = chunk->mc_Next) {
                if (which[1] < frags)  chunkv[which[1]++] = (unsigned long)chunk ;
                size = chunk->mc_Bytes ;
                if (which[2] < frags)  sizev[which[2]++] = (unsigned long)size;
                *which += size ;
                if (nf == FALSE)  {
                    newlimit++ ;
                    if (chunkv[newfrags] == NULL)  {
                        nf = TRUE;
                        }
                    }
                newfrags++ ;
            }
        }
        hdr = (struct MemHeader *)hdr->mh_Node.ln_Succ ;
        }
    Permit() ;
    length = frags ;
    if (newlimit < frags)  length = newlimit ;
    for (i = 0; i < length; i++)  {
        chunkv[i] -= membase;   /* chunkv is now array offset from base   */
        sizev[i] += chunkv[i];  /* and sizev is now address of array top  */
        chunkv[i] = chunkv[i] / memseg;  /* this is the number of pixels  */
        sizev[i] = sizev[i] / memseg;       /* and this is the top pixel  */
        if (chunkv[i] < 0) chunkv[i] = 0 ;  /* we do some bounds checking */
        if (sizev[i] < 0) sizev[i] = 0 ;
        if (chunkv[i] >= barh) chunkv[i] = barh - 1 ;
        if (sizev[i] >= barh) sizev[i] = barh - 1 ;
        if (sizev[i] - chunkv[i] < 0)  sizev[i] = chunkv[i] ;
        j = chunkv[i] ; /* from now on it will be less confusing if */
        k = sizev[i] ;  /* we assign some variables for this stuff  */
        if (sizev[i] - chunkv[i] == 0)  {
            cell[j] &= BLUP ;
            }
        else  {
            for (l = j; l < k; l++)  {
                cell[l] &= BLKP ;
                }
            }
        }
    (void) memometer();
    newsize = frags ;
    while (newsize < newlimit)  {
        newsize += EXTENSION ;
        }
    if (newlimit > frags)  {
        (void) FreeMem(chunkv, (long)(sizeof(long) * frags));
        if ((chunkv = (unsigned long *)AllocMem((long)sizeof(long) * newsize,
                                        MEMF_PUBLIC)) == 0L )  {
            log = log & C2 ;
            }
        (void) FreeMem(sizev, (long)(sizeof(long) * frags));
        if ((sizev = (unsigned long *)AllocMem((long)sizeof(long) * newsize,
                                        MEMF_PUBLIC)) == 0L ) {
            (void) FreeMem(chunkv, (long)(sizeof(long) * newsize));
            log = log & C4 ;
            }
        if (log != SOK)  {
            wrack_sploot() ;
            things_are_cool = FALSE ;
            }
        else frags = newsize ;
        }
}

main() {
    static struct IntuiText bodyText0 =
        {BLUP, WHTP, JAM2, 58, 10, NULL, NULL, NULL};
    static struct IntuiText bodyText1 =
        {BLUP, WHTP, JAM2, 42, 20, NULL, NULL, NULL};
    static struct IntuiText bodyText2 =
        {BLUP, WHTP, JAM2, 50, 30, NULL, NULL, NULL};
    static struct IntuiText positiveText =
        {BLUP, WHTP, JAM2, 7, 3, NULL, NULL, NULL};
    static struct IntuiText negativeText =
        {BLUP, WHTP, JAM2, 7, 3, NULL, NULL, NULL};
    struct IntuiMessage *message;
    ULONG class;
    USHORT code;
    ULONG wakeupbits;
    long syspri;
    char *nptr;
    struct Task *mmtcb;
    char oldpri;
    int t;
    int i;
    USHORT colflags;     /* keeps track of column positions and counts */
    USHORT left;         /* left   column, left edge */
    USHORT middle;       /* middle column, left edge */
    USHORT right;        /* right  column, left edge */
    USHORT barw;         /* width of each mercury column */
    USHORT wf;           /* memometer window current column number */
    long cmemseg;
    long sfmemseg;
    long fmemseg;
    long membase;
    long memseg;
    long memsize;

    bodyText0.IText = (UBYTE *) "WARNING! CRASH POSSIBLE";
    bodyText1.IText = (UBYTE *) "MENU MEMORY SELECTIONS MUST";
    bodyText2.IText = (UBYTE *) "REFERENCE EXISTING MEMORY";
    bodyText0.NextText = &bodyText1;
    bodyText1.NextText = &bodyText2;
    positiveText.IText = (UBYTE *) "Risk It";
    negativeText.IText = (UBYTE *) "Retreat";

    log = 0 ;
    if ((cell = (USHORT *)AllocMem((long)sizeof(USHORT) * BARS,
                                        MEMF_PUBLIC)) != 0L ) log = log | S1;
    if ((chunkv = (ULONG *)AllocMem((long)sizeof(ULONG) * STARTVAL,
                                        MEMF_PUBLIC)) != 0L ) log = log | S2;
    if ((sizev = (ULONG *)AllocMem((long)sizeof(ULONG) * STARTVAL,
                                        MEMF_PUBLIC)) != 0L ) log = log | S4;
    if ((csum = (ULONG *)AllocMem((long)sizeof(ULONG) * BARS,
                                        MEMF_PUBLIC)) != 0L ) log = log | S8;
    if ((oldcsum = (ULONG *)AllocMem((long)sizeof(ULONG) * BARS,
                                        MEMF_PUBLIC)) != 0L ) log = log | SA;
    if (log != SOK)  {
        wrack_sploot() ;
        exit(AARRRGH) ;
        }
    if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary(
            "intuition.library",33L)) != NULL &&
            (window=OpenWindow(&newwindow)) != NULL)  {
        if ((GfxBase = (struct GfxBase *)OpenLibrary(
                "graphics.library", 0L)) != NULL)  { 
            (void) initmenus();
            /* rp = window->RPort ; */
            inittimer();
            wf = 0;
            mmode = FALSE ;
            mode = FRAGS ;
            delayval = p_rate ;
            priority = p_priority ;
            if (priority > 0)  priority = 0 ;
            lastpri = priority ;
            syspri = priority ;
            nptr = NULL ;
            mmtcb = FindTask( nptr ) ;
            oldpri = SetTaskPri( mmtcb, syspri ) ;
            cmemsize = p_chip << 10 ;
            cmembase = p_chipa << 10 ;
            sfmemsize = p_sf << 10 ;
            sfmembase = p_sfa << 10 ;
            if (p_fast >= 512)  fmemsize = p_fast << 10 ;
            else fmemsize = p_fast << 20 ;
            fmembase = p_fasta << 20 ;
            while (things_are_cool == TRUE) {
                if (chgflag != 0)  {
                    chgflag = 0 ;
                    colflags = 0 ;
                    if (cmemsize != 0)  colflags = colflags | (1 << 0) ;
                    if (sfmemsize != 0)  colflags = colflags | (1 << 1) ;
                    if (fmemsize != 0)  colflags = colflags | (1 << 2) ;
                    switch ( colflags ) {
                        case 0:
                        barw = (WINW - (2 * BORDER)) - 1 ;
                        left = LEFT ;
                        middle = 0 ;
                        right = 0 ;
                        f_text.FrontPen = ORNP ;
                        break ;

                        case 1:
                        barw = (WINW - (2 * BORDER)) - 1 ;
                        left = LEFT ;
                        middle = 0 ;
                        right = 0 ;
                        f_text.FrontPen = BLUP ;
                        break ;

                        case 2:
                        barw = (WINW - (2 * BORDER)) - 1 ;
                        left = 0 ;
                        middle = LEFT ;
                        right = 0 ;
                        f_text.FrontPen = CYNP ;
                        break ;

                        case 3:
                        barw = ((WINW - (2 * BORDER)) / 2 ) - 1 ;
                        left = LEFT ;
                        middle = (left + barw + 1) ;
                        right = 0 ;
                        f_text.FrontPen = BLUP ;
                        break ;

                        case 4:
                        barw = (WINW - (2 * BORDER)) - 1 ;
                        left = 0 ;
                        middle = 0;
                        right = LEFT ;
                        f_text.FrontPen = YELP ;
                        break ;

                        case 5:
                        barw = ((WINW - (2 * BORDER)) / 2 ) - 1 ;
                        left = LEFT ;
                        middle = 0 ;
                        right = (left + barw + 1) ;
                        f_text.FrontPen = CYNP ;
                        break ;

                        case 6:
                        barw = ((WINW - (2 * BORDER)) / 2 ) - 1 ;
                        left = 0 ;
                        middle = LEFT ;
                        right = (middle + barw + 1) ;
                        f_text.FrontPen = YELP ;
                        break ;

                        case 7:
                        barw = ((WINW - (2 * BORDER)) / 3 ) - 1 ;
                        left = LEFT ;
                        middle = (left + barw + 1) ;
                        right = (middle + barw + 1) ;
                        f_text.FrontPen = BLUP ;
                        break ;
                        }  /* end of switch ( colflags ) */
                    }  /* end of if ( chgflag ) */
                cmemseg = cmemsize / barh ;
                sfmemseg = sfmemsize / barh ;
                fmemseg = fmemsize / barh ;
                if (mmode == TRUE && ((sfmemsize != 0) ||
                                      (fmembase != 0x200000)))  {
                    /* Keep your eyes open here.  If we get a negative    */
                    /* response from the requester, that means either the */
                    /* user retreated, or a no-requester function such as */
                    /* noreq or KillReq has selected the negative option. */
                    /* If such functions select the positive option they  */
                    /* force acceptance of the crash risk with SFmemory.  */

                    mode = AutoRequest(window, &bodyText0, &positiveText,
                               &negativeText, 0L, 0L, 319L, 79L) ;
                    }
                if (mmode == TRUE && ((sfmemsize != 0) ||
                                      (fmembase != 0x200000)))  {
                    if (mode == FRAGS)  {      /* user Retreat select  */
                        sfmemseg = 0 ;         /* results in execution */
                        sfmemsize = 0 ;        /* of this code segment */
                        fmembase = 0x200000 ;  /* resetting internals  */
                        }
                    }
                switch ( wf ) {
                    case 0:
                    xl = left ;
                    membase = cmembase ;
                    memseg = cmemseg ;
                    memsize = cmemsize ;
                    break;

                    case 1:
                    xl = middle ;
                    membase = sfmembase ;
                    memseg = sfmemseg ;
                    memsize = sfmemsize ;
                    break;

                    case 2:
                    xl = right ;
                    membase = fmembase ;
                    memseg = fmemseg ;
                    memsize = fmemsize ;
                    break;
                    }  /* end of switch ( wf ) */
                xr = xl + barw ;
                if (mmode == TRUE)  {
                    mode = WARPS ;
                    mmode = FALSE ;
                    }
                if (xl != 0)  {
                    if (mode == WARPS)  {
                        (void) updatewarps( wf, membase, memseg ) ;
                        e_text.FrontPen = YELP ;
                        }
                    if (mode == FRAGS)  {
                        (void) updatescreen( wf, membase, memseg ) ;
                        e_text.FrontPen = BLUP ;
                        }
                    }
                if (intsig == TRUE)  {
                    handle_NEWSIZE() ;
                    intsig = FALSE ;
                    }
                if (syspri != priority)  {
                    syspri = priority ;
                    nptr = NULL;
                    mmtcb = FindTask( nptr ) ;
                    oldpri = SetTaskPri( mmtcb, syspri ) ;
                    }
                if (wf == 2)  {
                    PrintIText(window->RPort,&f_text,RTEXT,0L) ;
                    wakeupbits = Wait(timerbit) ;
                    if (wakeupbits & timerbit)  {
                        GetMsg(timerport);
                        SetTimer(delayval, 0L, timermsg);
                        }
                    }
                wf++ ;
                if (wf >= 3)  wf = 0 ;
                } /* end of while ( things_are_cool) */

            if (timerport) {
                Wait(timerbit);
                GetMsg(timerport);
                CloseDevice(timermsg);
                DeleteStdIO(timermsg);
                DeletePort(timerport);
                }

            if (GfxBase)    CloseLibrary(GfxBase) ;
            }
        if (window)         CloseWindow(window) ;
        if (IntuitionBase)  CloseLibrary(IntuitionBase) ;
        }
    wrack_sploot() ;
}

_cli_parse() {}
_wb_parse() {}
