/************************************************************************
*                       Prism - THE Amiga ANSI Animator			*
*                              By: Colin Vernon                         *
*			 Prism 1.00 - October 15, 1989			*
*  lc -ma -cu Prism.c							*
*  blink lib:cback.o Prism.o LIB lib:lcm.lib lib:lc.lib lib:amiga.lib   *
************************************************************************/
#include "stdio.h"
#include "stdlib.h"
#include "exec/types.h"
#include "exec/memory.h"
#include "intuition/intuition.h"
#include "graphics/sprite.h"
#include "proto/dos.h"
#include "dos.h"
#include "libraries/diskfont.h"

#define MAXHEIGHT 24
#define MAXWIDTH 80
#define MINHEIGHT 1
#define MINWIDTH 1
#define MAXCHARSETS 12
#define SPACE 0x20
#define BACKSPACE 0x08
#define LINEFEED 0x0a
#define FORMFEED 0x0c
#define RETURN 0x0d
#define TAB 0x09
#define CURSOR_UP 'A'
#define CURSOR_DOWN 'B'
#define CURSOR_RIGHT 'C'
#define CURSOR_LEFT 'D'
#define ESC 0x1b
#define MAXINPUTLEN 80

struct ANSI 
{ 
     struct ANSI *next;
     struct ANSI *previous;
     short x;
     short y;
     short fcolour;
     short bcolour;
     UBYTE letter;
     UBYTE attr;
};
/***** End Of Header *****/
static unsigned char Titlebar[] = "Prism 1.10 By Colin Vernon";
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
ULONG *DiskfontBase;
struct Screen *WorkScreen;
struct Window *WorkWindow;
struct Window *Gads;
struct Window *ReqWindow;
struct IntuiMessage *message;
struct IOStdReq ioStdReq;
struct Device *ConsoleDevice = NULL;
struct SimpleSprite Cursor;

void OpenLibs(), CloseLibs();
ULONG OpenDevice();
SHORT RawKeyConvert();
/************************** Sprite Defs *********************************/
UWORD Cursor_Data[] = 
{
	0,0,
	0xf000, 0xf000,
	0x0000, 0x0000,
	0x0000, 0x0000,
	0x0000, 0x0000,
	0x0000, 0x0000,
	0x0000, 0x0000,
	0x0000, 0x0000,
	0xf000, 0xf000,
	0,0
};
UWORD Blank_Data[] =
{
	0,0,
	0x0000, 0x0000,	0x0000, 0x0000,	0x0000, 0x0000,	0x0000, 0x0000,
	0x0000, 0x0000,	0x0000, 0x0000,	0x0000, 0x0000,	0x0000, 0x0000,
	0,0
};
WORD Spr1;
UWORD *ChipCursor, *ChipBlank, *Helping;
/*************************** Gadget Definitions **************************/
struct IntuiText Colour15 ={0,15,JAM2,0,0,NULL," 15 ",NULL,};
struct IntuiText Colour14 ={0,14,JAM2,0,0,NULL," 14 ",NULL,};
struct IntuiText Colour13 ={0,13,JAM2,0,0,NULL," 13 ",NULL,};
struct IntuiText Colour12 ={0,12,JAM2,0,0,NULL," 12 ",NULL,};
struct IntuiText Colour11 ={0,11,JAM2,0,0,NULL," 11 ",NULL,};
struct IntuiText Colour10 ={0,10,JAM2,0,0,NULL," 10 ",NULL,};
struct IntuiText Colour9 ={0,9,JAM2,0,0,NULL,"  9 ",NULL,};
struct IntuiText Colour8 ={0,8,JAM2,0,0,NULL,"  8 ",NULL,};
struct IntuiText Colour7 ={0,7,JAM2,0,0,NULL,"  7 ",NULL,};
struct IntuiText Colour6 ={0,6,JAM2,0,0,NULL,"  6 ",NULL,};
struct IntuiText Colour5 ={0,5,JAM2,0,0,NULL,"  5 ",NULL,};
struct IntuiText Colour4 ={0,4,JAM2,0,0,NULL,"  4 ",NULL,};
struct IntuiText Colour3 ={0,3,JAM2,0,0,NULL,"  3 ",NULL,};
struct IntuiText Colour2 ={0,2,JAM2,0,0,NULL,"  2 ",NULL,};
struct IntuiText Colour1 ={0,1,JAM2,0,0,NULL,"  1 ",NULL,};
struct IntuiText Colour0 ={1,0,JAM2,0,0,NULL,"  0 ",NULL,};

struct IntuiText ForeBackText =
{
	15,0,JAM2,2,6,NULL,(UBYTE *)"Fore/Back",NULL
};
struct Gadget ForeBackGadget =
{
	NULL,560,10,76,19,
	GADGHCOMP | SELECTED,RELVERIFY,BOOLGADGET,
	NULL,NULL,&ForeBackText,0,NULL,17,NULL
};
struct Gadget SelColour15 =
{
    &ForeBackGadget,512,11,32,8,
    GADGHCOMP,RELVERIFY | GADGIMMEDIATE,BOOLGADGET,
    NULL,NULL,&Colour15,0,NULL,16,NULL
};

struct Gadget SelColour14 =
{
    &SelColour15,478,11,32,8,
    GADGHCOMP,RELVERIFY | GADGIMMEDIATE,BOOLGADGET,
    NULL,NULL,&Colour14,0,NULL,15,NULL
};

struct Gadget SelColour13 =
{
    &SelColour14,444,11,32,8,
    GADGHCOMP,RELVERIFY | GADGIMMEDIATE,BOOLGADGET,
    NULL,NULL,&Colour13,0,NULL,14,NULL
};

struct Gadget SelColour12 =
{
    &SelColour13,410,11,32,8,
    GADGHCOMP,RELVERIFY | GADGIMMEDIATE,BOOLGADGET,
    NULL,NULL,&Colour12,0,NULL,13,NULL
};

struct Gadget SelColour11 =
{
    &SelColour12,376,11,32,8,
    GADGHCOMP,RELVERIFY | GADGIMMEDIATE,BOOLGADGET,
    NULL,NULL,&Colour11,0,NULL,12,NULL
};

struct Gadget SelColour10 =
{
    &SelColour11,342,11,32,8,
    GADGHCOMP,RELVERIFY | GADGIMMEDIATE,BOOLGADGET,
    NULL,NULL,&Colour10,0,NULL,11,NULL
};

struct Gadget SelColour9 =
{
    &SelColour10,308,11,32,8,
    GADGHCOMP,RELVERIFY | GADGIMMEDIATE,BOOLGADGET,
    NULL,NULL,&Colour9,0,NULL,10,NULL
};

struct Gadget SelColour8 =
{
    &SelColour9,274,11,32,8,
    GADGHCOMP,RELVERIFY | GADGIMMEDIATE,BOOLGADGET,
    NULL,NULL,&Colour8,0,NULL,9,NULL
};

struct Gadget SelColour7 =
{
    &SelColour8,240,11,32,8,
    GADGHCOMP,RELVERIFY | GADGIMMEDIATE,BOOLGADGET,
    NULL,NULL,&Colour7,0,NULL,8,NULL
};

struct Gadget SelColour6 =
{
    &SelColour7,206,11,32,8,
    GADGHCOMP,RELVERIFY | GADGIMMEDIATE,BOOLGADGET,
    NULL,NULL,&Colour6,0,NULL,7,NULL
};

struct Gadget SelColour5 =
{
    &SelColour6,172,11,32,8,
    GADGHCOMP,RELVERIFY | GADGIMMEDIATE,BOOLGADGET,
    NULL,NULL,&Colour5,0,NULL,6,NULL
};

struct Gadget SelColour4 =
{
    &SelColour5,138,11,32,8,
    GADGHCOMP,RELVERIFY | GADGIMMEDIATE,BOOLGADGET,
    NULL,NULL,&Colour4,0,NULL,5,NULL
};

struct Gadget SelColour3 =
{
    &SelColour4,104,11,32,8,
    GADGHCOMP,RELVERIFY | GADGIMMEDIATE,BOOLGADGET,
    NULL,NULL,&Colour3,0,NULL,4,NULL
};

struct Gadget SelColour2 =
{
    &SelColour3,70,11,32,8,
    GADGHCOMP,RELVERIFY | GADGIMMEDIATE,BOOLGADGET,
    NULL,NULL,&Colour2,0,NULL,3,NULL
};

struct Gadget SelColour1 =
{
    &SelColour2,36,11,32,8, 
    GADGHCOMP,RELVERIFY | GADGIMMEDIATE,BOOLGADGET,
    NULL,NULL,&Colour1,0,NULL,2,NULL
};

struct Gadget SelColour0 =
{
    &SelColour1,    /* NextGadget */
    2,11,32,8,  /* LeftEdge, TopEdge, Width, Height*/
    GADGHCOMP,  /* Flags */
    RELVERIFY | GADGIMMEDIATE,   /* Activation */
    BOOLGADGET,     /* Gadget Type */
    NULL, /* Gadget Render */
    NULL,       /* Select Render */
    &Colour0,       /* GadgetText */
    0,          /* MutualExclude */
    NULL,       /* SpecialInfo */
    1,          /* GadgetID */
    NULL        /* UserData */
};
/************************** Requester Definitions ************************/
/***** The About Requester *****/
struct IntuiText AboutProg7Text =
{
    4,7,JAM2,30,59,NULL,"version.",NULL
};
struct IntuiText AboutProg6Text =
{
    4,7,JAM2,30,50,NULL,
    "so no registration fee is required for a fully working",
    &AboutProg7Text
};
struct IntuiText AboutProg5Text =
{
    4,7,JAM2,30,41,NULL,
    "are not modified.  This version of Prism is public domain",
    &AboutProg6Text
};
struct IntuiText AboutProg4Text =
{
    4,7,JAM2,30,32,NULL,
    "distributed as long as the original files in the archive",
    &AboutProg5Text
};
struct IntuiText AboutProg3Text =
{
    4,7,JAM2,30,23,NULL,
    "Prism is an ANSI animator for the Amiga.  It can be",
    &AboutProg4Text
};
struct IntuiText AboutProgText =
{
    1,7,JAM1,205,9,NULL,"Prism by Colin Vernon",&AboutProg3Text
};
/***** The File Requester *****/
unsigned char PathBuffer[512] = "";
unsigned char FileBuffer[33] = "Unnamed.ans";
unsigned char UndoBuffer[512];
UBYTE FileStr[8][33];
WORD RenderB[4];
struct Gadget ReqFiles[8];
struct IntuiText FileStInfo[8];
struct StringInfo PathInfo =
{
    &PathBuffer[0],&UndoBuffer[0],
    0,511,0,0,0,0,0,0,NULL,0,NULL
};
struct StringInfo FileInfo =
{
    &FileBuffer[0], &UndoBuffer[0],
    0,31,0,0,0,0,0,0,NULL,0,NULL
};
struct IntuiText GenStrInfo =
{
    7,0,JAM2,0,0,NULL,NULL,NULL
};
struct PropInfo SlideInfo =
{
    AUTOKNOB | FREEVERT, 0x0000, 0x0000, 0x0800, 0x0800, 0,0,0,0,0,0
};
SHORT StringPairs[] =
{
    0,0,241,0,241,9,0,9,0,0
};
SHORT SelectPairs[] =
{
    0,0,61,0,61,11,0,11,0,0,
};

struct Border StringBorder =
{
    -1,-1,3,0,JAM1,5,StringPairs,NULL,
};
struct Border SelectBorder =
{
    0,0,3,0,JAM1,5,SelectPairs,NULL,
};
struct IntuiText ParentText =
{
    7,0,JAM2,6,2,NULL,"Parent",NULL,
};
struct IntuiText PathText =
{
    7,0,JAM2,-58,0,NULL,"Drawer",NULL,
};
struct IntuiText FileText =
{
    7,0,JAM2,-42,0,NULL,"File",NULL,
};
struct IntuiText CancelText =
{
    7,0,JAM2,6,2,NULL,"Cancel",NULL,
};
struct IntuiText OKText =
{
    7,0,JAM2,22,2,NULL,"OK",NULL,
};
struct Gadget FileNameGadget =
{
    NULL,20,120,240,8,
    GADGHCOMP, RELVERIFY, BOOLGADGET,
    NULL, NULL, NULL,
    NULL, NULL, 0, NULL
};
struct Gadget Parent =
{
    &ReqFiles[0],135,125,62,12,
    GADGHCOMP, RELVERIFY, BOOLGADGET,
    (APTR)&SelectBorder, NULL, &ParentText,
    NULL,NULL,6,NULL
};
struct Gadget Slide =
{
    &Parent,293,32,15,73,
    GADGHCOMP, RELVERIFY, PROPGADGET,
    (APTR)RenderB,NULL,NULL,
    NULL,(APTR)&SlideInfo,5,NULL
};
struct Gadget Path =
{
    &Slide,65,20,240,8,
    GADGHCOMP, RELVERIFY, STRGADGET,
    (APTR)&StringBorder,NULL,&PathText,
    NULL,(APTR)&PathInfo,4,NULL
};
struct Gadget File =
{
    &Path,65,110,240,8,
    GADGHCOMP, RELVERIFY, STRGADGET,
    (APTR)&StringBorder,NULL,&FileText,
    NULL,(APTR)&FileInfo,3,NULL
};
struct Gadget Cancel =
{
    &File,240,125,62,12,
    GADGHCOMP,RELVERIFY, BOOLGADGET,
    (APTR)&SelectBorder,NULL,&CancelText,
    NULL,NULL,1,NULL
};
struct Gadget OK =
{
    &Cancel,30,125,62,12,
    GADGHCOMP, RELVERIFY, BOOLGADGET,
    (APTR)&SelectBorder,NULL,&OKText,
    NULL,NULL,2,NULL
};

/***** The Requester Window *****/
struct NewWindow RequesterWindow =
{
    135,50,370,100,0,7,
    GADGETUP,
    SIMPLE_REFRESH | ACTIVATE,NULL,NULL,NULL,NULL,NULL,0,0,0,0,
    CUSTOMSCREEN,
};
/***** The True Requester Definition *****/
struct Requester FileSelectBox;
/*************************************************************************/
struct TextAttr WorkFont =
{
	(STRPTR)"IBM.font",
	8,
	FS_NORMAL,
	FPF_DISKFONT | FPF_ROMFONT
};
struct TextAttr DisplayFont =
{
	(STRPTR)"topaz.font", TOPAZ_EIGHTY, FS_NORMAL, FPF_ROMFONT
};
struct NewScreen FirstWorkScreen =
{
	0,-1,		/* LeftEdge, TopEdge	*/
	640,202,	/* Width, Height	*/
	4,		/* Depth		*/
	4,7,		/* DetailPen, BlockPen	*/
	HIRES | SPRITES,/* ViewModes		*/
	CUSTOMSCREEN,	/* Type		    	*/
	&DisplayFont,	/* Font               	*/
	Titlebar,
	NULL,		/* Gadgets		*/
	NULL,		/* CustonBitMap	    	*/
};

struct NewWindow FirstWorkWindow =
{
	0,10,		/* LeftEdge, TopEdge	*/
	640,192,	/* Width, Height	*/
	4,7,		/* DetailPen, BlockPen	*/
	MOUSEBUTTONS |	/* IDCMP Flags		*/
	RAWKEY |
	MENUPICK,
	SMART_REFRESH |	/* Flags		*/
	ACTIVATE |
	BORDERLESS |
	GIMMEZEROZERO,
	NULL,           /* First Gadget         */
	NULL,		/* CheckMark	    	*/
	NULL,		/* Window Title		*/
	NULL,		/* Screen		*/
	NULL,		/* BitMap		*/
	0,0,		/* Min Width, Height	*/
	0,0,		/* Max Width, Height	*/
	CUSTOMSCREEN,	/* Type		        */
};

struct NewWindow GadgetWindow =
{
	0,170,
	640,30,
	4,7,
	GADGETUP | ACTIVEWINDOW,
	SMART_REFRESH | WINDOWDRAG,
	&SelColour0,
	NULL,
	"Gadget Box",
	NULL,
	NULL,
	0,0,
	0,0,
	CUSTOMSCREEN
};

struct InputEvent inputEvent =
{
    0,IECLASS_RAWKEY,0,0,0
};
UWORD AtrColours[16] =
{
	0x000,0xf00,0x3f1,0xfe0,0x00f,0xf0c,0x2cd,0xddd,
	0x444,0x800,0x281,0x870,0x008,0x806,0x177,0x888
};
/**************************** Menu Definition **************************/
struct IntuiText FourplanesText =
{
	4,7,JAM2,18,1,&DisplayFont,"16 Colors",NULL
};
struct IntuiText ThreeplanesText =
{
	4,7,JAM2,18,1,&DisplayFont,"8 Colors",NULL
};
struct IntuiText TwoplanesText =
{
	4,7,JAM2,18,1,&DisplayFont,"4 Colors",NULL
};
struct IntuiText ColorsText =
{
	4,7,JAM2,0,1,&DisplayFont,"Colors",NULL
};
struct IntuiText QuitText =
{
    4,7,JAM2,0,1,&DisplayFont,"Quit",NULL
};
struct IntuiText AppendText =
{
    4,7,JAM2,0,1,&DisplayFont,"Append",NULL
};
struct IntuiText SaveText =
{
    4,7,JAM2,0,1,&DisplayFont,"Save",NULL
};
struct IntuiText LoadText =
{
    4,7,JAM2,0,1,&DisplayFont,"Load",NULL
};
struct IntuiText ClearText =
{
    4,7,JAM2,0,1,&DisplayFont,"Clear",NULL
};
struct IntuiText PlaybackText =
{
    4,7,JAM2,0,1,&DisplayFont,"Playback",NULL
};
struct IntuiText AboutText =
{
    4,7,JAM2,0,1,&DisplayFont,"About",NULL
};
struct MenuItem Fourplanes =
{
	NULL,80,20,130,10,ITEMTEXT|ITEMENABLED|HIGHCOMP|COMMSEQ|
	CHECKIT|CHECKED,3,(APTR)&FourplanesText,NULL,'4',NULL,0
};
struct MenuItem Threeplanes =
{
	&Fourplanes,80,10,130,10,ITEMTEXT|ITEMENABLED|HIGHCOMP|COMMSEQ|
	CHECKIT,5,(APTR)&ThreeplanesText,NULL,'3',NULL,0
};
struct MenuItem Twoplanes =
{
	&Threeplanes,80,0,130,10,ITEMTEXT|ITEMENABLED|HIGHCOMP|COMMSEQ|
	CHECKIT,6,(APTR)&TwoplanesText,NULL,'2',NULL,0
};
struct MenuItem Colors =
{
	NULL,0,0,110,10,ITEMTEXT | ITEMENABLED | HIGHCOMP,0,
	(APTR)&ColorsText,NULL,0,&Twoplanes,0
};
struct MenuItem Quit =
{
    NULL,0,60,120,10,ITEMTEXT | ITEMENABLED | HIGHBOX | COMMSEQ,0,
    (APTR)&QuitText,NULL,'Q',NULL,0
};
struct MenuItem AppSave =
{
    NULL,80,10,60,10,ITEMTEXT | ITEMENABLED | HIGHCOMP,0,
    (APTR)&SaveText,NULL,0,NULL,0
};
struct MenuItem AppLoad =
{
    &AppSave,80,0,60,10,ITEMTEXT | ITEMENABLED | HIGHCOMP,0,
    (APTR)&LoadText,NULL,0,NULL,0
};
struct MenuItem Append =
{
    &Quit,0,50,120,10,ITEMTEXT | ITEMENABLED | HIGHCOMP,0,
    (APTR)&AppendText,NULL,0,&AppLoad,0
};
struct MenuItem Save =
{
    &Append,0,40,120,10,ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ,0,
    (APTR)&SaveText,NULL,'S',NULL,0
};
struct MenuItem Load =
{
    &Save,0,30,120,10,ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ,0,
    (APTR)&LoadText,NULL,'L',NULL,0
};
struct MenuItem Clear =
{
    &Load,0,20,120,10,ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ,0,
    (APTR)&ClearText,NULL,'C',NULL,0
};    
struct MenuItem Playback =
{
    &Clear,0,10,120,10,ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ,0,
    (APTR)&PlaybackText,NULL,'P',NULL,0
};
struct MenuItem About =
{
    &Playback,0,0,120,10,ITEMTEXT | ITEMENABLED | HIGHCOMP,0,
    (APTR)&AboutText,NULL,0,NULL,0
};
struct Menu Setup =
{
	NULL,
	100,0,100,10,
	MENUENABLED,
	"Setup",
	&Colors
};
struct Menu Project =
{
    &Setup,
    0, 0, 100, 10,
    MENUENABLED,
    "Project",
    &About
};
/**************************** External Variables ************************/
UBYTE Buffer[MAXINPUTLEN];
SHORT scanner;
struct ANSI storage = { NULL,NULL,-1,-1,-1,-1,NULL };
struct ANSI *sdlstptr, *lastptr, *middle, *front, *back;
struct TextFont *TFont;
SHORT conDevErr = FALSE;
int length = 0,position = 0;	/* used to display where editor is */
int cx = 1, cy = 1;		/* cursor co-ordinates */
static int maxlinelength = 255;
static int tabspacing = 8;
BOOL changes = FALSE;
static char funckey[MAXCHARSETS][8] =
{
    {0xb3, 0xc4, 0xc5, 0xc0, 0xd9, 0xda, 0xbf, 0xd8},
    {0xba, 0xcd, 0xce, 0xc8, 0xbc, 0xc9, 0xbb, 0xd7},
    {0xc1, 0xc2, 0xb4, 0xc3, 0xca, 0xcb, 0xb9, 0xcc},
    {0xbe, 0xd4, 0xb8, 0xd5, 0xbd, 0xd3, 0xb7, 0xd6},
    {0xd0, 0xd2, 0xb6, 0xc7, 0xcf, 0xd1, 0xb5, 0xc6},
    {0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xb0, 0xb1, 0xb2},
    {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7},
    {0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7},
    {0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef},
    {0xf0, 0xf1, 0xf2, 0xf3, 0xfe, 0xf6, 0xfd, 0xfb},
    {0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf},
    {0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfc}
};
long _stack = 10000;		/* my Load-And-Stay Resident stack size */
char *_procname = "Prism";	/* my proceedure name */
long _priority = 0;		/* A regular priority */
long _BackGroundIO = 0;		/* If this != 0, I can Write() to CLI but
				   I must Close(_Backstdout) when done */
extern BPTR _Backstdout;	/* CLI file handle */

struct IntuiText GeneralText =
{
    1,0,        /* FrontPen, BackPen */
    JAM2,       /* DrawMode */
    0,0,        /* LeftEdge, TopEdge */
    &WorkFont,  /* Font */
    Buffer,
    NULL
};
/************************************************************************
*                       And now.... THE BEGINNING!!            		*
************************************************************************/
main()
{
    ULONG MessageClass;
    USHORT code, qualifier;
    
    struct Message *GetMsg();
    char memusestr[81];		/* display position and length */
    int mx, my;			/* mouse co-ordinates */
    int fcolour = 7;		/* initialize fourground colour */
    int bcolour = 0;
    int tabplace, tempnum, memleft, jx, jy;
    short int presset = 0;
    BOOL mbuttons = FALSE, BGmode = FALSE, gadwinfront = TRUE;
    struct Gadget *GadgetPtr;
    USHORT GadgetID;
    
    FirstWorkScreen.Depth = 4;
    OpenLibs();
    lastptr = &storage;
    middle = lastptr;
    
    FOREVER
    {
	mx = (int) (WorkWindow->GZZMouseX)/8+1;
	my = (int) (WorkWindow->GZZMouseY)/8+1;
        if (cx >= MINWIDTH && cx <= MAXWIDTH && cy >= MINHEIGHT &&
	    cy <= MAXHEIGHT)
	{
	    jx = (cx-1)*8-2;
	    jy = (cy-1)*8+FirstWorkWindow.TopEdge;
	    MoveSprite(&WorkScreen->ViewPort,&Cursor,jx,jy);
	}

	if (message = (struct IntuiMessage *)GetMsg(WorkWindow->UserPort))
	{
	    MessageClass = message->Class;
	    code = message->Code;
            qualifier = message->Qualifier;
	    ReplyMsg(message);
            if (MessageClass & MOUSEBUTTONS)
            {
                switch(code)
                {
                    case SELECTDOWN :
                        mbuttons = TRUE;
                        break;
                                        
                    case SELECTUP :
                        mbuttons = FALSE;
                        break;
                }
            }
	    else switch (MessageClass)
	    {
                case RAWKEY :
                    if(!(code & IECODE_UP_PREFIX))
                    {
                        inputEvent.ie_Code = code;
                        inputEvent.ie_Qualifier = qualifier;
			scanner = RawKeyConvert(&inputEvent,Buffer,
			    MAXINPUTLEN,NULL);
                        Buffer[scanner] = NULL;
			if(Buffer[0]==0x9b && scanner>1)
			{
			    switch(Buffer[1])
			    {
				case CURSOR_UP :
                                cy--;
                                if(cy < MINHEIGHT)
                                   cy = MINHEIGHT;
				break;
				
				case CURSOR_DOWN :
                                cy++;
                                if(cy > MAXHEIGHT)
                                   cy = MAXHEIGHT;
				break;
				
				case CURSOR_LEFT :
				if(qualifier & IEQUALIFIER_CONTROL)
				{
				    if(middle != NULL && middle != &storage)
				    {
					back = middle;
					tempnum = 1;
					while(back != NULL && 
					      back != &storage &&
					      tempnum == 1)
					{
					    back=back->previous;
					    if(middle->x == back->x &&
					       middle->y == back->y)
					    {
						memusestr[0]=back->letter;
						memusestr[1]=NULL;
						ColourTextXY(WorkWindow,
						 memusestr,back->x,back->y,
						 back->fcolour,
						 back->bcolour);
						 tempnum = 0;
					    }
					}
					if(back==NULL || back==&storage)
					{
					    memusestr[0] = SPACE;
					    memusestr[1] = NULL;
					    ColourTextXY(WorkWindow,
					      memusestr,middle->x,
					      middle->y,1,0);
					}
					middle=middle->previous;
					if(middle != &storage)
					{
					    cx = middle->x;
					    cy = middle->y;
					}
					else
					{
					    cx = MINWIDTH;
					    cy = MINHEIGHT;
					} 
					--position;
				    }
				} 
				else
				{
				    cx--;
				    if(cx < MINWIDTH) cx = MINWIDTH;
				}
				break;
				
				case CURSOR_RIGHT :
				if(qualifier & IEQUALIFIER_CONTROL)
				{
				    if(middle != NULL)
				    {
					if(middle->next != NULL)
					{
					    middle=middle->next;
					    cx = middle->x; cy = middle->y;
					    ++position;
					}
					memusestr[0]=middle->letter;
					memusestr[1]=NULL;
					ColourTextXY(WorkWindow,memusestr,
					  middle->x,middle->y,
					  middle->fcolour,middle->bcolour);
				    }
				} 
				else
				{
				    cx++;
				    if(cx > MAXWIDTH) cx = MAXWIDTH;
				}
				break;
				
				default :
				if (scanner == 3 && Buffer[2] == '~')
				{
				    if (Buffer[1] == '?')
				    {
					if(gadwinfront)
					{
					    WindowToBack(Gads);
					    gadwinfront = FALSE;
					}
					else
					{
					    WindowToFront(Gads);
					    gadwinfront = TRUE;
					}
					break;
				    }
				    Buffer[2] = NULL;
				    tempnum = atoi(&Buffer[1]);
				    Buffer[2] = '~';
			    	    if(tempnum >= 0 && tempnum <= 7)
			    	    {
					Buffer[0] = funckey[presset][tempnum];
					Buffer[1] = NULL;
					scanner = 1;
			    	    }
				    if(tempnum == 8)
			    	    {
					++presset;
					if(presset > MAXCHARSETS-1)
					    presset = 0;
			     	    }
			    	    if(tempnum == 9)
			    	    {
					--presset;
					if(presset < 0)
				    	    presset = MAXCHARSETS-1;
			    	    }
				}
			    }
			}
                        if(scanner > 0 && Buffer[0] != 0x9b)
                        {
                            switch(Buffer[0])
                            {
                                case RETURN : 
                                    cx = MINWIDTH;
                                    cy++;
                                    if (cy > MAXHEIGHT)
                                        cy = MAXHEIGHT;
                                    break;
                                
                                case BACKSPACE :
                                    if (lastptr == &storage ||
					middle == &storage)
                                        break;
				    back = middle;
				    tempnum = 1;
				    while(back != NULL && back != &storage 
				    	&& tempnum == 1)
				    {
					back=back->previous;
					if(middle->x == back->x &&
					   middle->y == back->y)
					{
					    memusestr[0]=back->letter;
					    memusestr[1]=NULL;
					    ColourTextXY(WorkWindow,
					      memusestr,back->x,back->y,
					      back->fcolour,back->bcolour);
					    tempnum = 0;
					}
				    }
				    if(back==NULL || back==&storage)
				    {
					memusestr[0] = SPACE;
					memusestr[1] = NULL;
					ColourTextXY(WorkWindow,
					  memusestr,middle->x,middle->y,1,0);
				    }
				    if(middle->next == NULL)
				    {
					free((char *)lastptr);
                                	lastptr = sdlstptr;
                                	sdlstptr = sdlstptr->previous;
                                	lastptr->next = NULL;
					memusestr[0] = lastptr->letter;
					memusestr[1] = NULL;
					if(lastptr != &storage)
					{
					    ColourTextXY(WorkWindow,memusestr,
					      lastptr->x,lastptr->y,
					      lastptr->fcolour,lastptr->bcolour);
					    cx = lastptr->x; cy = lastptr->y;
					}
					middle = lastptr;
				    }
				    else
				    {
					for(back = middle, front = back->next;
					    front != NULL; back=back->next,
					    front = back->next)
					{
					    back->fcolour = front->fcolour;
					    back->bcolour = front->bcolour;
					    back->x = front->x;
					    back->y = front->y;
					    back->letter = front->letter;
					    back->attr = front->attr;
					}
					free((char *)lastptr);
                                	lastptr = sdlstptr;
                                	sdlstptr = sdlstptr->previous;
                                	lastptr->next = NULL;
					middle = middle->previous;
					memusestr[0] = middle->letter;
					memusestr[1] = NULL;
					if(middle != &storage)
					{
					    ColourTextXY(WorkWindow,memusestr,
						middle->x,middle->y,
						middle->fcolour,middle->bcolour);
					    cx = middle->x; cy = middle->y;
					}
				    }
                                    position--; length--; changes = TRUE;
                                    break;
                                    
                                case TAB :
                                    tabplace = cx;
				    tabplace += (tabspacing -
				    	((cx-1) % tabspacing));
                                    if(tabplace > MAXWIDTH)
                                    {
                                        tabplace = MINWIDTH;
                                        cy++;
                                        if(cy > MAXHEIGHT)
                                            cy = MAXHEIGHT;
                                    }
                                    cx = tabplace;
                                    break;
                                                    
                                default :
				for(tempnum = 0; tempnum < scanner;
				    tempnum++)
				{
                                    if (Buffer[tempnum] < 32 || 
					Buffer[tempnum] == 127) break;
                                    sdlstptr = lastptr;
                                    lastptr = (struct ANSI *)
                                        malloc(sizeof(struct ANSI));
                                    if (lastptr == NULL)
				    {
					lastptr = sdlstptr;
					sdlstptr = lastptr->previous;
                                        break;
				    }
				    sdlstptr->next = lastptr;
				    lastptr->previous = sdlstptr;
				    lastptr->next = NULL;
				    if (middle->next == lastptr)
				    {
                                	lastptr->letter = Buffer[tempnum];
                                	lastptr->x = cx;
                                	lastptr->y = cy;
                                	lastptr->fcolour = fcolour;
					lastptr->bcolour = bcolour;
					middle = lastptr;
				    } 
				    else
				    {
					middle = middle->next;
					for(back = lastptr,
					    front = back->previous;
					    back != middle;
					    back = back->previous,
					    front = back->previous)
					{
					    back->fcolour = front->fcolour;
					    back->bcolour = front->bcolour;
					    back->x = front->x;
					    back->y = front->y;
					    back->letter = front->letter;
					    back->attr = front->attr;
					}
                                	middle->letter = Buffer[tempnum];
                                	middle->x = cx;
                                	middle->y = cy;
                                	middle->fcolour = fcolour;
					middle->bcolour = bcolour;
				    }
                                    ColourTextXY(WorkWindow,
                                        Buffer,cx,cy,fcolour,bcolour);
                                    cx++;
                                    if(cx > MAXWIDTH)
                                    {
                                        cx = MINWIDTH; cy++;
                                        if (cy > MAXHEIGHT)
                                            cy=MAXHEIGHT;
                                    }
                                    position++; length++;
				    changes = TRUE;
				}
                                break;
                            }
                        }
                    }
                    break;

                case MENUPICK :
                    MenuAnalyse(code);
                    break;
	    }
	} 
	else
	{
	    sprintf(memusestr,"P:X=%2d Y=%2d",mx,my);
	    if(mx < 1 || my < 1)
	        sprintf(memusestr,"P:         ");
	    ColourText(Gads,memusestr,488,1,7,0);
	    sprintf(memusestr,"C:X=%2d Y=%2d",cx,cy);
	    ColourText(Gads,memusestr,380,1,7,0);
            sprintf(memusestr,"Pos: %5d  Len: %5d",position,length);
            ColourText(Gads,memusestr,2,1,7,0);
            sprintf(memusestr,"ForeC: %2d  BackC: %2d",fcolour,bcolour);
            ColourText(Gads,memusestr,200,1,fcolour,bcolour);
	    sprintf(memusestr,
	    	"Set:%2d F1=%c F2=%c F3=%c F4=%c F5=%c F6=%c F7=%c F8=%c",
		presset+1,funckey[presset][0],funckey[presset][1],
		funckey[presset][2],funckey[presset][3],
		funckey[presset][4],funckey[presset][5],
		funckey[presset][6],funckey[presset][7]);
	    ColourText(Gads,memusestr,3,20,7,0);
	    sprintf(memusestr,"Free Memory:%7d",memleft = AvailMem(0));
	    ColourText(Gads,memusestr,390,20,3,0);
	}
	if (message = (struct IntuiMessage *)
	    GetMsg(Gads->UserPort))
	{
	    MessageClass = message->Class;
	    code = message->Code;
            qualifier = message->Qualifier;
            GadgetPtr = (struct Gadget *) message->IAddress;
	    ReplyMsg(message);
            GadgetID = GadgetPtr->GadgetID;
            switch(MessageClass)
            {
                case GADGETUP :
		    if (GadgetID == 17)
		    {
		    	BGmode ^= TRUE;
			break;
		    }
		    if (BGmode == TRUE)
		    {
			if (GadgetID >= 1 && GadgetID <=8)
			{
			    bcolour = (int)GadgetID-1;
			    BGmode = FALSE;
			}
		    } else {
                    	if (GadgetID >= 1 && GadgetID <= 16)
                    	{
                            fcolour = (int)GadgetID - 1;
                    	}
		    }
                    break;
                    
		case ACTIVEWINDOW :
                    ActivateWindow(WorkWindow);
                    break;
            }
            ActivateWindow(WorkWindow);
        }
        if (mbuttons)
        {
            /**** Move the cursor to (mx,my) ****/;
            cx = mx;
            cy = my;
	    if (cx < MINWIDTH) cx = MINWIDTH;
	    if (cx > MAXWIDTH) cx = MAXWIDTH;
	    if (cy < MINHEIGHT) cy = MINHEIGHT;
	    if (cy > MAXHEIGHT) cy = MAXHEIGHT;
        }
    }
}
/************************************************************************
*                Now, for the Libraries that need to be opened	    	*
************************************************************************/
void OpenLibs()
{
    void *OpenLibrary();
    struct Window *OpenWindow();
    struct Screen *OpenScreen();
    int i;
	
    if(!(IntuitionBase = (struct IntuitionBase *)
	OpenLibrary("intuition.library", 0L)))
    {
	CloseLibs("Intuition Library cannot be found");
	exit(FALSE);
    }
    if(!(GfxBase = (struct GfxBase *)
	OpenLibrary("graphics.library", 0L)))
    {
	CloseLibs("Graphics Library cannot be found");
	exit(FALSE);
    }
    if((DiskfontBase = (ULONG*)
	OpenLibrary("diskfont.library",0))==NULL)
    {
	CloseLibs("Diskfont Library cannot be found");
	exit(FALSE);
    }
    if((TFont = (struct TextFont *) 
	OpenDiskFont(&WorkFont)) == NULL)
    {
	WorkFont.ta_Name = (STRPTR)"topaz.font";
	WorkFont.ta_YSize = TOPAZ_EIGHTY;
    }
    ChipCursor = (UWORD*)AllocMem(sizeof(Cursor_Data),MEMF_CLEAR|MEMF_CHIP);
    ChipBlank = (UWORD*)AllocMem(sizeof(Blank_Data),MEMF_CLEAR|MEMF_CHIP);
    if ((ChipCursor == 0) | (ChipBlank == 0)) CloseLibs("No chip memory");
    Helping = ChipCursor;
    for (i=0; i<(sizeof(Cursor_Data)/sizeof(UWORD));i++)
    {
	*Helping = Cursor_Data[i];
	Helping++;
    }
    for (i=0; i<(sizeof(Blank_Data)/sizeof(UWORD));i++)
    {
	*Helping = Blank_Data[i];
	Helping++;
    }
    Cursor.x = -1;
    Cursor.y = 36;
    Cursor.height = 8;
    Spr1 = GetSprite(&Cursor,-1);
    if(Spr1 == -1)
    {
	CloseLibs("Sprite cannot be displayed");
	exit(FALSE);
    }
    ChangeSprite(&WorkScreen->ViewPort,&Cursor,ChipCursor);

    OpenSAW();
    
    if (!(OpenDevice("console.device",-1L,&ioStdReq,0L)))
        ConsoleDevice = ioStdReq.io_Device;
    else 
	CloseLibs("Could not open console.device");
}
OpenSAW()
{
    struct ViewPort *vp;

    if(!(WorkScreen = (struct Screen *)
	OpenScreen(&FirstWorkScreen)))
    {
	CloseLibs("Screen cannot be opened");
	exit(FALSE);
    }
    vp = &WorkScreen->ViewPort;
    LoadRGB4(vp,AtrColours,16);
    RemakeDisplay();
    FirstWorkWindow.Screen = WorkScreen;
    if(!(WorkWindow = (struct Window *)	OpenWindow(&FirstWorkWindow)))
    {
	CloseLibs("Window cannot be opened");
	exit(FALSE);
    }
    GadgetWindow.Screen = WorkScreen;
    if(!(Gads = (struct Window *) OpenWindow(&GadgetWindow)))
    {
	CloseLibs("Gadget window cannot be opened");
	exit(FALSE);
    }
    SetMenuStrip(WorkWindow, &Project);
    return(0);
}
/************************************************************************
*       If Libraries have to be opened, then they have to be closed!	*
************************************************************************/
void CloseLibs(str)
char *str;
{
    int dummy=0, handle;
    
    FreeAllMem();
    if(Spr1 != -1)	FreeSprite(Spr1);
    if(ChipCursor != 0) FreeMem(ChipCursor,sizeof(Cursor_Data));
    if(ChipBlank != 0)	FreeMem(ChipBlank,sizeof(Blank_Data));
    CloseSAW();
    if(TFont)		CloseFont(TFont);
    if(DiskfontBase)	CloseLibrary(DiskfontBase);
    if(GfxBase)	        CloseLibrary(GfxBase);
    if(IntuitionBase)	CloseLibrary(IntuitionBase);
    if(str[0] != '~')
    {	
        handle = open("RAW:160/50/320/25/Prism",0,dummy);
        if (handle != -1)
        {
	    write(handle,str,strlen(str));
	    Delay(120L);
	    close(handle);
        }
    }
}
CloseSAW()
{
    if(Gads)	CloseWindow(Gads);
    if(WorkWindow)
    {
    	ClearMenuStrip(WorkWindow);
	CloseWindow(WorkWindow);
    }
    if(WorkScreen)	CloseScreen(WorkScreen);
    return(0);
}
/*************************************************************************
*                  The colour version of the Text routine                *
*************************************************************************/
ColourText(w_ptr,s,x,y,fc,bc)
struct Window *w_ptr;
char *s;
int x,y;
int fc,bc;
{
    GeneralText.FrontPen = (UBYTE) fc;
    GeneralText.BackPen = (UBYTE) bc;
    GeneralText.IText = (UBYTE *) s;
    PrintIText(w_ptr->RPort,&GeneralText,x,y);
    return(TRUE);
}
/*************************************************************************
*      X and Y now represent the row and column of TEXT and not bits     *
*************************************************************************/
ColourTextXY(w_ptr,s,x,y,fc,bc)
struct Window *w_ptr;
char *s;
int x,y;
int fc,bc;
{
    int ix,iy;
    
    GeneralText.FrontPen = (UBYTE) fc;
    GeneralText.BackPen = (UBYTE) bc;
    GeneralText.IText = (UBYTE *) s;

    if (x < MINWIDTH || x > MAXWIDTH || y < MINHEIGHT || y > MAXHEIGHT)
        return(FALSE);
    ix = (x-1)*8; /* to calculate distance by text size and not pixels */
    iy = (y-1)*8;
    
    PrintIText(w_ptr->RPort,&GeneralText,ix,iy);
    return(TRUE);
}
/*************************************************************************
*                         Free the used memory                           *
*************************************************************************/
FreeAllMem()
{
    struct IntuiText ClearingText =
    {
	4,7,JAM2,126,11,NULL,"Clearing Current ANSI.  Please Wait.",NULL
    };
    
    InitRequester(&FileSelectBox);
    FileSelectBox.LeftEdge = 50;
    FileSelectBox.TopEdge = 85;
    FileSelectBox.Width = 540;
    FileSelectBox.Height = 30;
    FileSelectBox.ReqText = &ClearingText;
    FileSelectBox.BackFill = 7;
    Request(&FileSelectBox, WorkWindow);
    for(lastptr=storage.next; lastptr != NULL; lastptr = lastptr->next)
    {
	free((char *)lastptr);
    }
    storage.next = NULL;
    lastptr = &storage;
    middle = lastptr;
    length = 0; position = 0;
    cx = MINWIDTH; cy = MINHEIGHT; changes = FALSE;
    EndRequest(&FileSelectBox, WorkWindow);
    return(TRUE);
}
/*************************************************************************
*               Attempt to playback what what stored in Memory           *
*************************************************************************/
PlayBack()
{
    char displaystr[2];
    char *LeftMouse = (char *)0xBFE001;
    
    position = length = 0;
    ClearWorkWindow();
    WindowToFront(WorkWindow);
    ChangeSprite(&WorkScreen->ViewPort,&Cursor,ChipBlank);
    Delay(30L);
    displaystr[1] = NULL;
    for(lastptr=storage.next; lastptr != NULL; lastptr = lastptr->next)
    {
        displaystr[0] = lastptr->letter;
        ColourTextXY(WorkWindow,displaystr,lastptr->x,lastptr->y,
            lastptr->fcolour,lastptr->bcolour);
	++position;++length;
	if((*LeftMouse & 0x40)==0x40) Delay(1L);
    }
    lastptr = sdlstptr->next;
    middle = lastptr;
    cx = middle->x; cy = middle->y;
    ChangeSprite(&WorkScreen->ViewPort,&Cursor,ChipCursor);
    WindowToBack(WorkWindow);
    return(TRUE);
}
/*************************************************************************
*                        Clear the WorkWindow                            *
*************************************************************************/
ClearWorkWindow()
{
    int i;
    static char blanker[] = "                                                                                ";
    
    for (i = 0; i <= 206; i += 8)
    {
        ColourText(WorkWindow,blanker,0,i,1,0);
    }
    return(TRUE);
}
/************************************************************************
*               Analyse which item was picked on the menu               *
************************************************************************/
MenuAnalyse(Menunumber)
USHORT Menunumber;
{
    USHORT Menu, MenuItem, SubItem;
    
    Menu = MENUNUM(Menunumber);
    MenuItem = ITEMNUM(Menunumber);
    SubItem = SUBNUM(Menunumber);
    switch(Menu)
    {
        case 0 :	/* The "Project" Menu */
            ProjectMenu(MenuItem,SubItem);
            break;
	    
	case 1 :	/* The "Setup" Menu */
	    SetupMenu(MenuItem,SubItem);
	    break;
    }
    return(TRUE);
}
ProjectMenu(MenuItem,SubItem)
USHORT MenuItem, SubItem;
{
    BOOL GetResponce;
    
    switch(MenuItem)
    {
        case 0 :    /* The "About" MenuItem */
            AboutReq();
            break;
            
        case 1 :    /* The "Playback" MenuItem */
            PlayBack();
            break;
            
        case 2 :    /* The "Clear" MenuItem */
	    GetResponce = AreYouSure("Clear Memory?");
	    if(GetResponce == TRUE)
	    {
		if(changes == TRUE)
		{
		    GetResponce = AreYouSure("Save with new changes?");
		    if(GetResponce == TRUE) SaveANSI(TRUE);
		}
		FreeAllMem();
		ClearWorkWindow();
	    }
            break;

        case 3 :    /* The "Load" MenuItem */
	    LoadANSI(TRUE);
            break;
	    
	case 4 :    /* The "Save" MenuItem */
	    SaveANSI(TRUE);
	    break;
	    
	case 5 :    /* The "Append" Submenu */
	    switch(SubItem)
	    {
		case 0 :	/* The "Append Load" SubItem */
		    LoadANSI(FALSE);
		    break;
		case 1 :	/* The "Append Save" SubItem */
		    SaveANSI(FALSE);
		    break;
	    }
	    break;

	case 6 :    /* The "Quit" MenuItem */
	    GetResponce = AreYouSure("Exit Prism?");
	    if(GetResponce == TRUE)
	    {
		if(changes == TRUE)
		{
		    GetResponce = AreYouSure("Save with new changes?");
		    if(GetResponce == TRUE) SaveANSI(TRUE);
		}
		CloseLibs("~");
		exit(TRUE);
	    }
	    break;
    }
    return(TRUE);
}
SetupMenu(MenuItem,SubItem)
USHORT MenuItem,SubItem;
{
    switch(MenuItem)
    {
	case 0 :	/* The "Colors" SubMenu */
	    SelColour3.NextGadget = &SelColour4;
	    SelColour7.NextGadget = &SelColour8;
	    switch(SubItem)
	    {
		case 0 :	/* The "2 Planes" SubItem */
		    CloseSAW();
		    FirstWorkScreen.Depth = 2;
		    SelColour3.NextGadget = &ForeBackGadget;
		    OpenSAW();
		    break;
		    
		case 1 :	/* The "3 Planes" SubItem */
		    CloseSAW();
		    FirstWorkScreen.Depth = 3;
		    SelColour7.NextGadget = &ForeBackGadget;
		    OpenSAW();
		    break;
		    
		case 2 :	/* The "4 Planes" SubItem */
		    CloseSAW();
		    FirstWorkScreen.Depth = 4;
		    OpenSAW();
		    break;
	    }
	    break;
    }
    return(TRUE);
}
/************************************************************************
*                     An "Are You Sure?" Requester                      *
************************************************************************/
AreYouSure(yousaidit)
char *yousaidit;
{
    BOOL Responce;
    
    struct IntuiText Really =
    {
        0,1,JAM1,40,5,NULL,NULL,NULL
    };
    struct IntuiText Yes =
    {
        0,1,JAM1,5,3,NULL,"YES",NULL
    };
    struct IntuiText No =
    {
        0,1,JAM1,5,3,NULL,"NO!",NULL
    };
    Really.IText = (UBYTE *)yousaidit;
    Responce = AutoRequest(WorkWindow,&Really,&Yes,&No,0,0,
	TextLength(WorkWindow->RPort,yousaidit,strlen(yousaidit))+100,50);
    return((int)Responce);
}
/*************************************************************************
*              The "Something Went Wrong" Requester Routine              *
*************************************************************************/
GenErrorReq(thecatch)
char *thecatch;
{
    BOOL Answer = FALSE;
    struct IntuiText SomethingText =
    {
        0,1,JAM2,15,8,NULL,NULL,NULL
    };
    struct IntuiText AlrightText =
    {
        0,1,JAM2,5,3,NULL,"OK?",NULL
    };
    SomethingText.IText = (UBYTE *)thecatch;
    Answer = AutoRequest(WorkWindow,&SomethingText,NULL,&AlrightText,0,0,
	TextLength(WorkWindow->RPort,thecatch,strlen(thecatch))+100,37);
    return((int)Answer);
}
/*************************************************************************
*                     The "About" Requester Routine                      *
*************************************************************************/
AboutReq()
{
    BOOL Answer = FALSE, Waiting;
    char *LeftMouse = (char *)0xBFE001;

    ChangeSprite(&WorkScreen->ViewPort,&Cursor,ChipBlank);
    RequesterWindow.LeftEdge = 41;
    RequesterWindow.TopEdge = 20;
    RequesterWindow.Width = 558;
    RequesterWindow.Height = 82;
    RequesterWindow.Title = NULL;
    RequesterWindow.Screen = WorkScreen;
    RequesterWindow.FirstGadget = NULL;
    InitRequester(&FileSelectBox);
    FileSelectBox.LeftEdge = 4;
    FileSelectBox.TopEdge = 2;
    FileSelectBox.Width = 550;
    FileSelectBox.Height = 90;
    FileSelectBox.ReqText = &AboutProgText;
    FileSelectBox.BackFill = 7;
    if(!(ReqWindow = (struct Window *) OpenWindow(&RequesterWindow)))
    {
	ChangeSprite(&WorkScreen->ViewPort,&Cursor,ChipCursor);
        return(FALSE);
    }
    Request(&FileSelectBox, ReqWindow);
    Waiting = TRUE;
    while(Waiting)
    {
	if(!((*LeftMouse & 0x40) == 0x40)) Waiting = FALSE;
    }
    EndRequest(&FileSelectBox, ReqWindow);
    if (ReqWindow)  CloseWindow(ReqWindow);
    ChangeSprite(&WorkScreen->ViewPort,&Cursor,ChipCursor);
    return((int)Answer);
}
/************************************************************************
*			   Load ANSI from Disk				*
************************************************************************/
LoadANSI(loadtype)
BOOL loadtype;
{
    FILE *ansiin;
    BOOL Answer;
    char ch;
    int cx = 1, cy = 1, fcolour = 1, bcolour = 0;
    int esclength, semicount, scanplace, actualnum, biggerbit;
    BOOL endofit;

    struct IntuiText LoadingText =
    {
	4,7,JAM2,122,11,NULL,"Loading ANSI from disk.  Please Wait.",NULL
    };
    ChangeSprite(&WorkScreen->ViewPort,&Cursor,ChipBlank);
    if(loadtype == TRUE)
	Answer = MakeFileReq("Load");
    else
	Answer = MakeFileReq("Append Load");
    if (Answer == FALSE) 
    {
	ChangeSprite(&WorkScreen->ViewPort,&Cursor,ChipCursor);
	return(FALSE);
    }
    if (!(ansiin = fopen(FileBuffer,"r")))
    {
        GenErrorReq("File can't open for read!");
	ChangeSprite(&WorkScreen->ViewPort,&Cursor,ChipCursor);
        return(FALSE);
    }
/***** Start Loading *****/
    if (loadtype == TRUE)
    {
	FreeAllMem();
	ClearWorkWindow();
    }
    InitRequester(&FileSelectBox);
    FileSelectBox.LeftEdge = 50;
    FileSelectBox.TopEdge = 85;
    FileSelectBox.Width = 540;
    FileSelectBox.Height = 30;
    FileSelectBox.ReqText = &LoadingText;
    FileSelectBox.BackFill = 7;
    Request(&FileSelectBox, WorkWindow);
    while((ch = getc(ansiin)) != EOF)
    {
	switch(ch)
	{
	    case ESC :
		esclength = semicount = 0;
		do {
		    ch = getc(ansiin);
		    Buffer[esclength] = ch;
		    esclength++;
		    if (ch == ';') ++semicount;
		   } while (ch == '[' || ch == ';' ||
			(ch >= '0' && ch <= '9'));
		Buffer[esclength] = NULL;
		switch(Buffer[esclength-1])
		{
		    case 'm':
			if (esclength == 3 && Buffer[1] == '0')
			{
			    fcolour = 1; bcolour = 0;
			    break;
			}
			else
			{
			    scanplace = 0; endofit = TRUE;
			    while(endofit)
			    {
				actualnum = numscan(Buffer,&scanplace);
				if (actualnum == -1) endofit = FALSE;
				switch(actualnum)
				{
				    case 0:
					biggerbit = 0;
					break;
					
				    case 1:
					biggerbit = 1;
					break;
					
				    case 30:
					if(biggerbit == 1) fcolour = 8;
					else fcolour = 0;
					break;
					
				    case 31:
				    	if(biggerbit == 1) fcolour = 9;
					else fcolour = 1;
					break;
					
				    case 32:
				    	if (biggerbit == 1) fcolour = 10;
					else fcolour = 2;
					break;
					
				    case 33:
				    	if (biggerbit == 1) fcolour = 11;
					else fcolour = 3;
					break;
					
				    case 34:
					if (biggerbit == 1) fcolour = 12;
					else fcolour = 4;
					break;
					
				    case 35:
					if (biggerbit == 1) fcolour = 13;
					else fcolour = 5;
					break;
					
				    case 36:
				    	if (biggerbit == 1) fcolour = 14;
					else fcolour = 6;
					break;
					
				    case 37:
				    	if (biggerbit == 1) fcolour = 15;
					else fcolour = 7;
					break;
					
				    case 40: bcolour = 0; break;
				    case 41: bcolour = 1; break;
				    case 42: bcolour = 2; break;
				    case 43: bcolour = 3; break;
				    case 44: bcolour = 4; break;
				    case 45: bcolour = 5; break;
				    case 46: bcolour = 6; break;
				    case 47: bcolour = 7; break;
				}
			    }
			}
			break;

		    case 'H':
			if(esclength == 2)
			{
			    cx = MINWIDTH; cy = MINHEIGHT;
			}
			else if(semicount == 1)
			{
			    scanplace = 0;
			    actualnum = numscan(Buffer,&scanplace);
			    if (actualnum >= MINHEIGHT && actualnum <=
				MAXHEIGHT) cy = actualnum;
			    actualnum = numscan(Buffer,&scanplace);
			    if (actualnum >= MINWIDTH && actualnum <=
				MAXWIDTH) cx = actualnum;
			}
			else if(semicount == 0 && esclength > 2)
			{
			    scanplace = 0;
			    actualnum = numscan(Buffer,&scanplace);
			    if (actualnum >= MINHEIGHT && actualnum <=
				MAXHEIGHT) cy = actualnum;
			    cx = MINWIDTH;
			}
			break;
			
		    case CURSOR_UP:
			scanplace = 0;
			actualnum = numscan(Buffer,&scanplace);
			if (actualnum == -1) cy--;
			else cy -= actualnum;
			if(cy < MINHEIGHT) cy = MINHEIGHT;
			break;

		    case CURSOR_DOWN:
			scanplace = 0;
			actualnum = numscan(Buffer,&scanplace);
			if (actualnum == -1) cy++;
			else cy += actualnum;
			if(cy > MAXHEIGHT) cy = MAXHEIGHT;
			break;

		    case CURSOR_RIGHT:
			scanplace = 0;
			actualnum = numscan(Buffer,&scanplace);
			if (actualnum == -1) cx++;
			else cx += actualnum;
			if(cx > MAXWIDTH) cx = MAXWIDTH;
			break;

		    case CURSOR_LEFT:
			scanplace = 0;
			actualnum = numscan(Buffer,&scanplace);
			if (actualnum == -1) cx--;
			else cx -= actualnum;
			if(cx < MINWIDTH) cx = MINWIDTH;
			break;
		}
		break;
	    
	    case LINEFEED : 
		cx = MINWIDTH;
		cy++;
		if (cy > MAXHEIGHT) cy = MAXHEIGHT;
		break;

	    default :
		if (ch < 32 || ch == 127) break;
		sdlstptr = lastptr;
		lastptr = (struct ANSI *) malloc(sizeof(struct ANSI));
		if (lastptr == NULL) break;
		middle = lastptr;
		sdlstptr->next = lastptr;
		lastptr->previous = sdlstptr;
		lastptr->next = NULL;
		lastptr->letter = ch;
		lastptr->x = cx;
		lastptr->y = cy;
		lastptr->fcolour = fcolour;
		lastptr->bcolour = bcolour;
		cx++;
		if(cx > MAXWIDTH)
		{
		    cx = MINWIDTH; cy++;
		    if (cy > MAXHEIGHT) cy=MAXHEIGHT;
		}
	}
    }    
    fclose(ansiin);
    EndRequest(&FileSelectBox, WorkWindow);
    PlayBack();
    ChangeSprite(&WorkScreen->ViewPort,&Cursor,ChipCursor);
    return(TRUE);
}
numscan(str,place)
char *str;
int *place;
{
    int num, holder;
    char convert[11];
    
    holder = *place;
    while(str[holder] < '0' || str[holder] > '9')
    {
	if(str[holder] == NULL)	return(-1);
	holder++;
    }
    num = atoi(&str[holder]);
    sprintf(convert,"%d",num);
    holder += strlen(convert);
    *place = holder;
    return(num);
}
/************************************************************************
*                           Save ANSI to disk                           *
************************************************************************/
SaveANSI(savetype)
BOOL savetype;
{
    FILE *ansiout;
    struct ANSI *behindptr;
    BOOL Answer;
    short int bit8;
    int truefcol, truebcol, linelength, xpos, ypos;
    char outputstr[41], endofline[41], savetypechr[2];
    
    struct IntuiText SavingText =
    {
	4,7,JAM2,134,11,NULL,"Saving ANSI to disk.  Please Wait.",NULL
    };
    ChangeSprite(&WorkScreen->ViewPort,&Cursor,ChipBlank);
    if(savetype == TRUE)
    {
	savetypechr[0] = 'w';
	savetypechr[1] = NULL;
	Answer = MakeFileReq("Save");
    }
    else
    {
	savetypechr[0] = 'a';
	savetypechr[1] = NULL;
	Answer = MakeFileReq("Append Save");
    }
    if (Answer == FALSE) 
    {
	ChangeSprite(&WorkScreen->ViewPort,&Cursor,ChipCursor);
	return(FALSE);
    }
    if (!(ansiout = fopen(FileBuffer,savetypechr)))
    {
        GenErrorReq("File can't open for write!");
	ChangeSprite(&WorkScreen->ViewPort,&Cursor,ChipCursor);
        return(FALSE);
    }
/***** Start Saving *****/
    InitRequester(&FileSelectBox);
    FileSelectBox.LeftEdge = 50;
    FileSelectBox.TopEdge = 85;
    FileSelectBox.Width = 540;
    FileSelectBox.Height = 30;
    FileSelectBox.ReqText = &SavingText;
    FileSelectBox.BackFill = 7;
    Request(&FileSelectBox, WorkWindow);
    fprintf(ansiout,"%c[0m%c[H%c[J",ESC,ESC,ESC);
    linelength = 10;
    for(lastptr=storage.next; lastptr != NULL; lastptr = lastptr->next)
    {
        behindptr = lastptr->previous;
	xpos = behindptr->x+1; ypos = behindptr->y;
	if(xpos > MAXWIDTH)
	{
	    xpos = MINWIDTH;
	    ypos++;
	    if(ypos > MAXHEIGHT) ypos = MAXHEIGHT;
	}    
/***** Check for colour changes *****/
        if((lastptr->fcolour != behindptr->fcolour) ||
		(lastptr->bcolour != behindptr->bcolour))
        {
	    truefcol = lastptr->fcolour;
	    truebcol = lastptr->bcolour;
	    if(behindptr->bcolour == lastptr->bcolour)
	    {
		if(FirstWorkScreen.Depth <= 3 && truefcol < 8)
		    sprintf(outputstr,"%c[3%dm",ESC,truefcol);
		else
		{
        	    if(truefcol&8) bit8 = 1; else bit8 = 0;
    		    sprintf(outputstr,"%c[%d;3%dm",ESC,bit8,truefcol&7);
		}
	    }
	    else if(behindptr->fcolour == lastptr->fcolour)
	    {
		sprintf(outputstr,"%c[4%dm",ESC,truebcol);
	    }
	    else
	    {
	    	if(FirstWorkScreen.Depth <= 3 && truefcol < 8)
		    sprintf(outputstr,"%c[3%d;4%dm",ESC,truefcol,truebcol);
		else
		{
        	if(truefcol&8) bit8 = 1; else bit8 = 0;
    		    sprintf(outputstr,"%c[%d;3%d;4%dm",ESC,bit8,truefcol&7,
			truebcol);
		}
	    }
            linelength += strlen(outputstr);
            if((linelength+1) >= maxlinelength)
            {
		sprintf(endofline,"%c%c[%d;%dH",RETURN,ESC,ypos,xpos);
                fprintf(ansiout,"%s",endofline);
                linelength = strlen(endofline);
		linelength += strlen(outputstr);
            }
            fprintf(ansiout,"%s",outputstr);
        }
/***** Check for position changes *****/
        if((lastptr->x != xpos) || (lastptr->y != ypos))
        {
	    if(xpos == lastptr->x && ypos > lastptr->y)
	    {
		if(ypos - lastptr->y == 1)
		    sprintf(outputstr,"%c[A",ESC);
		else
		    sprintf(outputstr,"%c[%dA",ESC,ypos - lastptr->y);
	    }
	    else if(xpos == lastptr->x && ypos < lastptr->y)
	    {
		if(lastptr->y - ypos == 1)
		    sprintf(outputstr,"%c[B",ESC);
		else
		    sprintf(outputstr,"%c[%dB",ESC,lastptr->y - ypos);
	    }
	    else if(xpos < lastptr->x && ypos == lastptr->y)
	    {
		if(lastptr->x - xpos == 1)
		    sprintf(outputstr,"%c[C",ESC);
		else
		    sprintf(outputstr,"%c[%dC",ESC,lastptr->x - xpos);
	    }
	    else if(xpos > lastptr->x && ypos == lastptr->y)
	    {
		if(xpos - lastptr->x == 1)
		    sprintf(outputstr,"%c[D",ESC);
		else
		    sprintf(outputstr,"%c[%dD",ESC,xpos - lastptr->x);
	    }
	    else
		sprintf(outputstr,"%c[%d;%dH",ESC,lastptr->y,lastptr->x);
	    linelength += strlen(outputstr);
	    if((linelength+1) >= maxlinelength)
	    {
		fprintf(ansiout,"%c",RETURN);
		sprintf(outputstr,"%c[%d;%dH",ESC,lastptr->y,lastptr->x);
		linelength = strlen(outputstr);
	    }
	    fprintf(ansiout,"%s",outputstr);
        }
/***** Print the actual character *****/
        if((linelength+1) >= maxlinelength)
        {
            fprintf(ansiout,"%c",RETURN);
            sprintf(outputstr,"%c[%d;%dH",ESC,lastptr->y,lastptr->x);
            fprintf(ansiout,"%s",outputstr);
            linelength = strlen(outputstr);
        }
        fprintf(ansiout,"%c",lastptr->letter);
        linelength++;
    }
    lastptr = sdlstptr->next;
    fclose(ansiout);
    changes = FALSE;
    EndRequest(&FileSelectBox, WorkWindow);
    ChangeSprite(&WorkScreen->ViewPort,&Cursor,ChipCursor);
    return(TRUE);
}
/************************************************************************
*			    Make File Requester				*
************************************************************************/
MakeFileReq(string)
char *string;
{
    int error, formula;
    struct Gadget *GadgetPtr;
    struct IntuiMessage *ReqMess;
    struct FILEINFO GetFilename;
    USHORT GadgetID;
    ULONG MessageClass;
    BOOL Waiton = TRUE, readdir = TRUE;
    char names[3000], *pointers[300], *showme;
    short int count=0;
    
    RequesterWindow.LeftEdge = 155;
    RequesterWindow.TopEdge = 25;
    RequesterWindow.Width = 330;
    RequesterWindow.Height = 147;
    RequesterWindow.Title = (UBYTE *)string;
    RequesterWindow.Screen = WorkScreen;
    RequesterWindow.FirstGadget = &OK;

    for (error=0; error<8; error++)
    {
	ReqFiles[error] = FileNameGadget;
	FileStInfo[error] = GenStrInfo;
	FileStInfo[error].IText = (UBYTE *)&FileStr[error];
	ReqFiles[error].TopEdge = 33 + error * 9;
	ReqFiles[error].GadgetID = 20 + error;
	ReqFiles[error].GadgetText = &FileStInfo[error];
	ReqFiles[error].NextGadget = &ReqFiles[error+1];
    }
    ReqFiles[7].NextGadget = NULL;
    
    if(!(ReqWindow = (struct Window *) OpenWindow(&RequesterWindow)))
        return(FALSE);
    if(error = chdir(PathBuffer))
	GenErrorReq("No directory!");
    while (Waiton)
    {
        if(ReqMess = (struct IntuiMessage *)
           GetMsg(ReqWindow->UserPort))
        {
	    MessageClass = ReqMess->Class;
	    GadgetPtr = (struct Gadget *) ReqMess->IAddress;
	    ReplyMsg(ReqMess);
	    GadgetID = GadgetPtr->GadgetID;
	    if (MessageClass == GADGETUP)
	    {
		if (GadgetID >= 20 && GadgetID <= 27)
		{
		    if(FileStr[GadgetID-20][0] != '»')
		    {
			error = strcmp(FileStr[GadgetID-20],FileBuffer);
			if(error)
			{
			    strcpy(FileBuffer,FileStr[GadgetID-20]);
			    RefreshGList(&File,ReqWindow,NULL,1);
			}
			else
			{
			    if (ReqWindow)  CloseWindow(ReqWindow);
			    return(TRUE);
			}
		    }
		    else
		    {
			chdir(&FileStr[GadgetID-20][1]);
			getcd(0,PathBuffer);
		        readdir = TRUE;
			count = 0;
		    }
		    RefreshGList(&Path,ReqWindow,NULL,1);
		}
		else switch(GadgetID)
		{
		    case 4:     /* The "Path" Gadget */
		    if(error = chdir(PathBuffer))
			GenErrorReq("No such directory!");
		    else
		    {
		        readdir = TRUE;
			count = 0;
		    }
		    break;

		    case 1:     /* The "Cancel" Gadget */
		    if (ReqWindow)  CloseWindow(ReqWindow);
		    return(FALSE);
		    break;
		    
		    case 2:	/* The "OK" Gadget */
		    Waiton = FALSE;
		    break;
		    
		    case 3:	/* The "File" Gadget */
		    Waiton = FALSE;
		    break;

		    case 5:	/* The "Slider" Gadget */
		    if(count > 8)
		    {
			formula = SlideInfo.VertPot/(65535/(count-8));
			showfiles(&pointers[formula],count);
		    }
		    break;
		    
		    case 6:	/* The "Parent" Gadget */
		    chdir("/");
		    getcd(0,PathBuffer);
		    RefreshGList(&Path,ReqWindow,NULL,1);
		    readdir = TRUE;
		    count = 0;
		}
	    }
        }
	if(readdir)
	{
	    if(count < 1)
	    {
		showme = &names[0];
		error = dfind(&GetFilename,"#?",1);
		if(error == 0)
		{
		    if(GetFilename.fib_DirEntryType > 0)
			showme = (char *)stpcpy(showme,"»");
		    showme = (char *)stpcpy(showme,&GetFilename.fib_FileName[0]);
		    showme++;
		    *(showme) = NULL;
		    count = strbpl(pointers,300,names);
		    SlideInfo.VertPot = 0;
		    SlideInfo.VertBody = 65535;
		    showfiles(pointers,count);
		    RefreshGList(&Slide,ReqWindow,NULL,1);
		}
		else 
		{
		    readdir = FALSE;
		    for(error = 0; error < sizeof(names); ++error)
			names[error] = NULL;
		    count = strbpl(pointers,300,names);
		    showfiles(pointers,count);
		}
	    }
	    else
	    {
		error = dnext(&GetFilename);
		if(error == 0 && (showme+32 < names+sizeof(names)))
		{
		    if(GetFilename.fib_DirEntryType > 0)
		    	showme = (char *)stpcpy(showme,"»");
		    showme = (char *)stpcpy(showme,&GetFilename.fib_FileName[0]);
		    ++count; ++showme;
		    *(showme) = NULL;
		    count = strbpl(pointers,300,names);
		    if (count > 8)
		    {
			SlideInfo.VertBody = (65535/count)*8;
			formula = SlideInfo.VertPot/(65535/(count-8));
			showfiles(&pointers[formula],count);
		    }
		    else
		    {
			SlideInfo.VertBody = 65535;
			showfiles(pointers,count);
		    }
		    RefreshGList(&Slide,ReqWindow,NULL);
		}
		else
		{
		    readdir = FALSE;
		    tqsort(pointers,count);
		    showfiles(pointers,count);
		    SlideInfo.VertPot = 0;
		    RefreshGList(&Slide,ReqWindow,NULL,1);
		}
	    }
	}
    }
    if (ReqWindow)  CloseWindow(ReqWindow);
    return(TRUE);
}
showfiles(strstuff,max)
char *strstuff[];
int max;
{
    int i;

    for(i = 0; i < 8; i++)
    {
	sprintf(FileStr[i],"%-30s","                              ");
	if(i > max)
	{
	    RefreshGList(&ReqFiles[i],ReqWindow,NULL,1);
	}
	else
	{
	    sprintf(FileStr[i],"%-30s",strstuff[i]);
	    RefreshGList(&ReqFiles[i],ReqWindow,NULL,1);
	    strcpy(FileStr[i],strstuff[i]);
	}
    }
    return(TRUE);
}