/* Auto: make "CCEXTRA=-wq -qf"
 */

#include "Snap.h"

IMPORT BOOL Kick36;

IMPORT LONGBITS startsignal, insertsignal, cancelsignal;
IMPORT LONGBITS donesignal, movesignal, clicksignal;
IMPORT LONGBITS timersignal, initsignal, cwsignal, ticksignal;
IMPORT ULONG startsignum, insertsignum, cancelsignum;
IMPORT ULONG donesignum, movesignum, clicksignum;
IMPORT ULONG initsignum, cwsignum, ticksignum;

/* program */
IMPORT struct SnapRsrc *SnapRsrc;
IMPORT struct Task *MyTask;

/* Snap state machine */
IMPORT WORD action;
IMPORT WORD state;

/* clipboard */
IMPORT struct IOClipReq *ClipReq;
IMPORT struct MsgPort *ClipPort;

/* timer device */
IMPORT struct MsgPort *TimerPort;
IMPORT struct timerequest MyTR;

/* input device */
IMPORT struct MsgPort *inputDevPort;
IMPORT struct Interrupt handlerStuff;
IMPORT struct IOStdReq *inputRequestBlock;

IMPORT UBYTE *CharData;

/* console */
IMPORT struct MsgPort *ConPort;
IMPORT struct IOStdReq *ConIOR;
IMPORT struct KeyMap keymap;

/* windows */
#ifdef SNAPGFX
IMPORT struct MsgPort *Sharedport;
IMPORT SHORT Sharedrefs;

#endif	/* SNAPGFX */

/* libraries */
IMPORT struct IntuitionBase *IntuitionBase;
IMPORT struct GfxBase *GfxBase;
IMPORT struct Library *LayersBase;
IMPORT struct Library *DiskfontBase;
IMPORT struct Library *IconBase;

#ifdef SNAPGFX
#ifdef REQLIB
IMPORT struct ReqBase *ReqBase;

#endif	/* REQLIB */
#ifdef ASLLIB
IMPORT struct Library *AslBase;

#endif	/* ASLLIB */
#endif	/* SNAPGFX */

/* graphics */
IMPORT struct RastPort TempRp;
IMPORT struct BitMap TempBM;
IMPORT UBYTE *TempRaster;

#ifdef SNAPGFX
#ifdef REQLIB
IMPORT struct ReqFileRequester *NameFR;

#endif	/* REQLIB */
#ifdef ASLLIB
#define SetTag( t,i,v) { ( t).ti_Tag = i; ( t).ti_Data = ( ULONG)( v); }
IMPORT struct FileRequester *AslNameFR;

#endif	/* ASLLIB */

IMPORT struct Image ActiveDiskImage;
IMPORT struct Image InactiveDiskImage;
IMPORT struct Image SelDiskImage;
IMPORT struct Image ActiveClipImage;
IMPORT struct Image InactiveClipImage;
IMPORT struct Image SelClipImage;
IMPORT struct Gadget DiskGad;
IMPORT struct Gadget ClipGad;

UWORD DiskImData36[ 144] =
{
    /* Inactive */
	0x0000, 0x0000,
	0x0000, 0x4000,
	0x07f8, 0x4000,
	0x0408, 0x4000,
	0x05E8, 0x4000,
	0x0408, 0x4000,
	0x07F8, 0x4000,
	0x0618, 0x4000,
	0x0698, 0x4000,
	0x0698, 0x4000,
	0x0000, 0x4000,
	0x7FFF, 0xC000,

	0xFFFF, 0xC000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,

    /* Active */
	0x0000, 0x0000,
	0x7FFF, 0xC000,
	0x7FFF, 0xC000,
	0x7C0F, 0xC000,
	0x7DEF, 0xC000,
	0x7C0F, 0xC000,
	0x7FFF, 0xC000,
	0x7E1F, 0xC000,
	0x7E9F, 0xC000,
	0x7E9F, 0xC000,
	0x7FFF, 0xC000,
	0x7FFF, 0xC000,

	0xFFFF, 0xC000,
	0xFFFF, 0x8000,
	0xF807, 0x8000,
	0xFBF7, 0x8000,
	0xFA17, 0x8000,
	0xFBF7, 0x8000,
	0xF807, 0x8000,
	0xF9E7, 0x8000,
	0xF967, 0x8000,
	0xF967, 0x8000,
	0xFFFF, 0x8000,
	0x8000, 0x0000,

    /* Selected */
	0xFFFF, 0xC000,
	0xFFFF, 0x8000,
	0xFFFF, 0x8000,
	0xFC0F, 0x8000,
	0xFDEF, 0x8000,
	0xFC0F, 0x8000,
	0xFFFF, 0x8000,
	0xFE1F, 0x8000,
	0xFE9F, 0x8000,
	0xFE9F, 0x8000,
	0xFFFF, 0x8000,
	0x8000, 0x0000,

	0x0000, 0x0000,
	0x7FFF, 0xC000,
	0x7807, 0xC000,
	0x7BF7, 0xC000,
	0x7A17, 0xC000,
	0x7BF7, 0xC000,
	0x7807, 0xC000,
	0x79E7, 0xC000,
	0x7967, 0xC000,
	0x7967, 0xC000,
	0x7FFF, 0xC000,
	0x7FFF, 0xC000
};

UWORD DiskImData[ 13] =
{
    /* BitPlane 0 */
	0xFFFF,
	0xFFFF,
	0xFFFF,
	0xF00F,
	0xF7EF,
	0xF42F,
	0xF7EF,
	0xF00F,
	0xF3CF,
	0xF2CF,
	0xF2CF,
	0xFFFF,
	0xFFFF
};

UWORD ClipImData36[ 156] =
{
    /* Inactive */
	0x0000, 0x0000,
	0x0000, 0x4000,
	0x0C00, 0x4000,
	0x120E, 0x4000,
	0x1A38, 0x4000,
	0x0EE0, 0x4000,
	0x0380, 0x4000,
	0x0EE0, 0x4000,
	0x1A38, 0x4000,
	0x120E, 0x4000,
	0x0C00, 0x4000,
	0x0000, 0x4000,
	0x7FFF, 0xC000,

	0xFFFF, 0xC000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,
	0x8000, 0x0000,

    /* Active */
	0x0000, 0x0000,
	0x7FFF, 0xC000,
	0x7FFF, 0xC000,
	0x7FFF, 0xC000,
	0x7FFF, 0xC000,
	0x7FFF, 0xC000,
	0x7FFF, 0xC000,
	0x7FFF, 0xC000,
	0x7FFF, 0xC000,
	0x7FFF, 0xC000,
	0x7FFF, 0xC000,
	0x7FFF, 0xC000,
	0x7FFF, 0xC000,

	0xFFFF, 0xC000,
	0xFFFF, 0x8000,
	0xF3FF, 0x8000,
	0xEDF1, 0x8000,
	0xE5C7, 0x8000,
	0xF11F, 0x8000,
	0xFC7F, 0x8000,
	0xF11F, 0x8000,
	0xE5C7, 0x8000,
	0xEDF1, 0x8000,
	0xF3FF, 0x8000,
	0xFFFF, 0x8000,
	0x8000, 0x0000,

    /* Selected */
	0xFFFF, 0xC000,
	0xFFFF, 0x8000,
	0xFFFF, 0x8000,
	0xFFFF, 0x8000,
	0xFFFF, 0x8000,
	0xFFFF, 0x8000,
	0xFFFF, 0x8000,
	0xFFFF, 0x8000,
	0xFFFF, 0x8000,
	0xFFFF, 0x8000,
	0xFFFF, 0x8000,
	0xFFFF, 0x8000,
	0x8000, 0x0000,

	0x0000, 0x0000,
	0x7FFF, 0xC000,
	0x73FF, 0xC000,
	0x6DF1, 0xC000,
	0x65C7, 0xC000,
	0x711F, 0xC000,
	0x7C7F, 0xC000,
	0x711F, 0xC000,
	0x65C7, 0xC000,
	0x6DF1, 0xC000,
	0x73FF, 0xC000,
	0x7FFF, 0xC000,
	0x7FFF, 0xC000
};

UWORD ClipImData[ 14] =
{
    /* BitPlane 0 */
	0xFFFF,
	0xFFFF,
	0xE7FF,
	0xDBE3,
	0xCB8F,
	0xE23F,
	0xF8FF,
	0xE23F,
	0xCB8F,
	0xDBE3,
	0xE7FF,
	0xFFFF,
	0xFFFF,
	0xFFFF
};

#endif	/* SNAPGFX */

VOID CloseStuff( )
{
	SafeRestore( );
	if ( SnapRsrc)
	{
		KILLLIST( &SnapRsrc->CachedWindows, struct CacheWindow);

		if ( SnapRsrc->AlternateFont)
		{
			CloseFont( SnapRsrc->AlternateFont);
		}
	}
#ifdef SNAPGFX
	if ( InactiveDiskImage.ImageData)
	{
		FreeMem( InactiveDiskImage.ImageData,
		      Kick36 ? sizeof ( DiskImData36) : sizeof ( DiskImData));
	}
	if ( InactiveClipImage.ImageData)
	{
		FreeMem( InactiveClipImage.ImageData,
		      Kick36 ? sizeof ( ClipImData36) : sizeof ( ClipImData));
	}
#endif	/* SNAPGFX */
	if ( TempRaster)
		FreeRaster( TempRaster, 16L, CHEIGHT);
	if ( CharData)
		FreeRaster( CharData, 16L, 256L * CHEIGHT);
	if ( inputRequestBlock)
	{
		if ( inputRequestBlock->io_Device)
		{
			inputRequestBlock->io_Command = IND_REMHANDLER;		/* Remove handler */
			inputRequestBlock->io_Data = ( APTR) & handlerStuff;
			DoIO( ( struct IORequest *)inputRequestBlock);
			CloseDevice( ( struct IORequest *)inputRequestBlock);
		}
		DeleteExtIO( ( struct IORequest *)inputRequestBlock);
	}
	if ( inputDevPort)
		DeletePort( inputDevPort);
	if ( TimerPort)
	{
		DeletePort( TimerPort);
		CloseDevice( ( struct IORequest *)&MyTR);
	}
	if ( ConIOR)
	{
		CloseDevice( ( struct IORequest *)ConIOR);
		DeleteExtIO( ( struct IORequest *)ConIOR);
	}
	if ( ConPort)
		DeletePort( ConPort);
	if ( ClipReq)
	{
		if ( ClipReq->io_Device)
		{
			CloseDevice( ( struct IORequest *)ClipReq);
		}
		DeleteExtIO( ( struct IORequest *)ClipReq);
	}
	if ( ClipPort)
		DeletePort( ClipPort);
	if ( startsignum != -1)
		FreeSignal( startsignum);
	if ( donesignum != -1)
		FreeSignal( donesignum);
	if ( cancelsignum != -1)
		FreeSignal( cancelsignum);
	if ( movesignum != -1)
		FreeSignal( movesignum);
	if ( insertsignum != -1)
		FreeSignal( insertsignum);
	if ( clicksignum != -1)
		FreeSignal( clicksignum);
	if ( initsignum != -1)
		FreeSignal( initsignum);
	if ( cwsignum != -1)
		FreeSignal( cwsignum);
	if ( ticksignum != -1)
		FreeSignal( ticksignum);
	if ( SnapRsrc)
	{
		RemResource( ( struct MiscResource *)SnapRsrc);
		Kill( SnapRsrc);
	}
#ifdef SNAPGFX
#ifdef ASLLIB
	if ( AslBase && AslNameFR)
		FreeFileRequest( AslNameFR);
#endif	/* ASLLIB */
#ifdef REQLIB
	if ( ReqBase && NameFR)
		Delete( NameFR);
#endif	/* REQLIB */
#endif	/* SNAPGFX */
}

VOID CloseLibs( )
{
#ifdef SNAPGFX
#ifdef ASLLIB
	if ( AslBase)
		CloseLibrary( AslBase);
#endif	/* ASLLIB */
#ifdef REQLIB
	if ( ReqBase)
		CloseLibrary( ( struct Library *)ReqBase);
#endif	/* REQLIB */
#endif	/* SNAPGFX */
	if ( IconBase)
		CloseLibrary( IconBase);
	if ( DiskfontBase)
		CloseLibrary( ( struct Library *)DiskfontBase);
	if ( IntuitionBase)
		CloseLibrary( ( struct Library *)IntuitionBase);
	if ( GfxBase)
		CloseLibrary( ( struct Library *)GfxBase);
	if ( LayersBase)
		CloseLibrary( ( struct Library *)LayersBase);
}

WORD OpenLibs( )
{
	/* libraries */

	if ( !( GfxBase = ( struct GfxBase *)OpenLibrary( "graphics.library", 0L)))
		return 0;
	if ( !( IntuitionBase = ( struct IntuitionBase *)OpenLibrary( "intuition.library", 0L)))
		return 0;
	if ( !( LayersBase = OpenLibrary( "layers.library", 0L)))
		return 0;
	DiskfontBase = OpenLibrary( "diskfont.library", 0L);
	IconBase = OpenLibrary( ICONNAME, 0L);
#ifdef SNAPGFX
#ifdef REQLIB
	ReqBase = ( struct ReqBase *)OpenLibrary( "req.library", 0L);
#endif	/* REQLIB */
#ifdef ASLLIB
	AslBase = OpenLibrary( AslName, 0L);
#endif	/* ASLLIB */
#endif
	return 1;
}

WORD OpenStuff( )
{
	action = noaction;
	state = waiting;
	inputRequestBlock = NULL;

#ifdef SNAPGFX
	Sharedrefs = 0;
	Sharedport = NULL;
#endif	/* SNAPGFX */

	/* Set up everything we need. */

#ifdef SNAPGFX
#ifdef REQLIB
	if ( ReqBase)
	{
		NameFR = Create( ReqFileRequester);
	}
#endif	/* REQLIB */
#ifdef ASLLIB
	if ( AslBase)
	{
		struct TagItem FRTags[ 4];

		SetTag( FRTags[ 0], ASL_Hail, "Save Picture As...");
		SetTag( FRTags[ 1], ASL_Dir, "t:");
		SetTag( FRTags[ 2], ASL_File, "Snap.pic");
		SetTag( FRTags[ 3], TAG_END, NULL);
		AslNameFR = AllocAslRequest( ASL_FileRequest, FRTags);
	}
#endif	/* ASLLIB */
#endif	/* SNAPGFX */

	/* signals */

	if ( ( startsignum = AllocSignal( -1L)) == -1L)
		return 0;
	if ( ( insertsignum = AllocSignal( -1L)) == -1L)
		return 0;
	if ( ( cancelsignum = AllocSignal( -1L)) == -1L)
		return 0;
	if ( ( donesignum = AllocSignal( -1L)) == -1L)
		return 0;
	if ( ( movesignum = AllocSignal( -1L)) == -1L)
		return 0;
	if ( ( clicksignum = AllocSignal( -1L)) == -1L)
		return 0;
	if ( ( initsignum = AllocSignal( -1L)) == -1L)
		return 0;
	if ( ( cwsignum = AllocSignal( -1L)) == -1L)
		return 0;
	if ( ( ticksignum = AllocSignal( -1L)) == -1L)
		return 0;
	MyTask = FindTask( NULL);	/* Find myself to Signal me.  */
	startsignal = 1L << startsignum;	/* No good to use bit numbers */
	insertsignal = 1L << insertsignum;
	cancelsignal = 1L << cancelsignum;
	donesignal = 1L << donesignum;
	movesignal = 1L << movesignum;
	clicksignal = 1L << clicksignum;
	initsignal = 1L << initsignum;
	cwsignal = 1L << cwsignum;
	ticksignal = 1L << ticksignum;

	/* clipboard device */

	if ( !( ClipPort = CreatePort( 0L, 0L)))
		return 0;
	if ( !( ClipReq = ( struct IOClipReq *)CreateExtIO( ClipPort, ( LONG) sizeof ( *ClipReq))))
		return 0;
	if ( OpenDevice( "clipboard.device", 0L, ( struct IORequest *)ClipReq, 0L))
		return 0;
	ClipReq->io_ClipID = 0L;

	/* console device */

	if ( !( ConPort = CreatePort( 0L, 0L)))
		return 0;
	if ( !( ConIOR = ( struct IOStdReq *)CreateExtIO( ConPort, ( LONG) sizeof ( struct IOStdReq))))
		 return 0;

	if ( OpenDevice( "console.device", -1L, ( struct IORequest *)ConIOR, 0L))
		return 0;

	/* timer device */
	if ( !( TimerPort = CreatePort( NULL, 0L)))
		return 0;
	timersignal = 1L << TimerPort->mp_SigBit;
	if ( OpenDevice( TIMERNAME, UNIT_VBLANK, ( struct IORequest *)&MyTR, 0))
		return 0;
	MyTR.tr_node.io_Message.mn_ReplyPort = TimerPort;
	MyTR.tr_node.io_Error = 0;

	/* input device */

	if ( !( inputDevPort = CreatePort( 0L, 0L)))
		return 0;
	if ( !( inputRequestBlock = ( struct IOStdReq *)CreateExtIO( inputDevPort, ( LONG) sizeof ( struct IOStdReq))))
		 return 0;

	if ( OpenDevice( "input.device", 0L, ( struct IORequest *)inputRequestBlock, 0L))
		return 0;

	/* input handler */

	handlerStuff.is_Data = ( APTR) 0x534E4150;	/* Set up for installation of */
	handlerStuff.is_Code = (void (* )())myhandler;	/* myhandler. */
	handlerStuff.is_Node.ln_Pri = SnapRsrc->Priority;
	/* Ahead of intuition, please */
	handlerStuff.is_Node.ln_Name = "Snap Input Handler";

	inputRequestBlock->io_Command = IND_ADDHANDLER;
	inputRequestBlock->io_Data = ( APTR) & handlerStuff;

	DoIO( ( struct IORequest *)inputRequestBlock);	/* Add me. */


	/* Aligned font bitmap to use when matching */

	if ( !( CharData = AllocRaster( 16L, 256L * CHEIGHT)))
	{
		return 0;
	}

	/* temporary raster */

	if ( !( TempRaster = AllocRaster( 16L, CHEIGHT)))
		return 0;
	InitRastPort( &TempRp);	/* Init RastPort used for */
	InitBitMap( &TempBM, 1L, 16L, CHEIGHT);	/* Locating position of   */
	TempBM.Planes[ 0] = TempRaster;	/* first character.       */
	TempRp.BitMap = &TempBM;

#ifdef SNAPGFX
	{
		WORD i;
		UWORD *DiskImageData;
		UWORD *ClipImageData;
		LONG DiskImageSize;
		LONG ClipImageSize;

		if ( Kick36)
		{
			ActiveDiskImage = SelDiskImage = InactiveDiskImage;
			ActiveClipImage = SelClipImage = InactiveClipImage;
			DiskImageData = DiskImData36;
			ClipImageData = ClipImData36;
			DiskImageSize = sizeof ( DiskImData36);
			ClipImageSize = sizeof ( ClipImData36);
			DiskGad.Flags |= GADGHIMAGE;
			ClipGad.Flags |= GADGHIMAGE;
		}
		else
		{
			InactiveDiskImage = SelDiskImage = ActiveDiskImage;
			InactiveClipImage = SelClipImage = ActiveClipImage;
			DiskImageData = DiskImData;
			ClipImageData = ClipImData;
			DiskImageSize = sizeof ( DiskImData);
			ClipImageSize = sizeof ( ClipImData);
			DiskGad.Flags |= GADGHCOMP;
			ClipGad.Flags |= GADGHCOMP;
		}
		if ( !( InactiveDiskImage.ImageData = AllocMem( DiskImageSize, MEMF_CHIP)))
		{
			return 0;
		}
		ActiveDiskImage.ImageData = &InactiveDiskImage.ImageData[ Kick36 ? 48 : 0];
		SelDiskImage.ImageData = &InactiveDiskImage.ImageData[ Kick36 ? 96 : 0];
		for ( i = 0; i < ( DiskImageSize / sizeof ( UWORD)); i++)
		{
			InactiveDiskImage.ImageData[ i] = DiskImageData[ i];
		}
		if ( !( InactiveClipImage.ImageData = AllocMem( ClipImageSize, MEMF_CHIP)))
		{
			return 0;
		}
		ActiveClipImage.ImageData = &InactiveClipImage.ImageData[ Kick36 ? 52 : 0];
		SelClipImage.ImageData = &InactiveClipImage.ImageData[ Kick36 ? 104 : 0];
		for ( i = 0; i < ( ClipImageSize / sizeof ( UWORD)); i++)
		{
			InactiveClipImage.ImageData[ i] = ClipImageData[ i];
		}
	}
#endif	/* SNAPGFX */

	return 1;
}
