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

#include "Snap.h"

#include "proto/Misc.h"

#define SCREENTOP (screen->TopEdge << ((screen->ViewPort.Modes & LACE)? 0: 1))

IMPORT struct SnapRsrc *SnapRsrc;
IMPORT struct IntuitionBase *IntuitionBase;
IMPORT struct Library *DiskfontBase;

struct Screen *WhichScreen()
{
	REGISTER struct Screen *screen;
	REGISTER ULONG lock;

	lock = LockIBase(0);
	screen = IntuitionBase->FirstScreen;
	while (screen && IntuitionBase->MouseY < SCREENTOP)
	{
		screen = screen->NextScreen;
	}
	if (screen == NULL)
	{			/* Shouldn't happen */
		screen = IntuitionBase->ActiveScreen;
	}
	UnlockIBase(lock);
	return screen;
}

struct Window *WhichWindow(screen)
	struct Screen *screen;
{
	struct Layer *layer;

	layer = (struct Layer *)WhichLayer(&screen->LayerInfo,
			      (LONG) screen->MouseX, (LONG) screen->MouseY);
	if (layer)
	{
		return (struct Window *)layer->Window;
	}
	else
	{
		return NULL;
	}
}


static VOID FreePlanes( struct BitMap *bm, LONG width, LONG height)
{
	SHORT i;

	for (i = 0; i < bm->Depth; i++)
	{
		if (bm->Planes[i])
		{
			FreeRaster(bm->Planes[i], width, height);
			bm->Planes[ i] = NULL;
		}
	}
}

static BOOL AllocPlanes( struct BitMap *bm, LONG width, LONG height)
{
	WORD i;

	for (i = 0; i < bm->Depth; i++)
	{
		bm->Planes[i] = NULL;
	}
	for (i = 0; i < bm->Depth; i++)
	{
		if ( !( bm->Planes[i] = AllocRaster(width, height)))
		{
			FreePlanes( bm, width, height);
			return FALSE;
		}
		BltClear((char *)bm->Planes[i], RASSIZE(width, height), NULL);
	}
	return TRUE;
}

void Snp_FreeBitMap( struct BitMap *BitMap, ULONG Width, ULONG Height)
{
	if ( !BitMap)
		return;

	if ( IntuitionBase->LibNode.lib_Version < 39)
	{
		FreePlanes( BitMap, Width, Height);
		FreeVec( BitMap);

		return;
	}
	else
	{
		FreeBitMap( BitMap);
	}

}

struct BitMap *Snp_AllocBitMap( ULONG SizeX, ULONG SizeY, ULONG Depth, ULONG Flags, struct BitMap *FriendBitMap)
{
	if ( IntuitionBase->LibNode.lib_Version < 39)
	{
		struct BitMap *BitMap;

		if ( BitMap = AllocVec( sizeof( struct BitMap), MEMF_ANY))
		{
			InitBitMap( BitMap, Depth, SizeX, SizeY);
			if ( AllocPlanes( BitMap, SizeX, SizeY))
			{
				return BitMap;
			}
			FreeVec( BitMap);
			return NULL;
		}
	}
	else
	{
		return AllocBitMap( SizeX, SizeY, Depth, Flags, FriendBitMap);
	}
}

VOID CacheWindow(struct Window * Win,
		 LONG xoff, LONG yoff,
		 SHORT fw, SHORT fh,
		 struct TextFont * font)
{
	struct CacheWindow *cw;

	if (!(cw = Create(CacheWindow)))
	{
		return;
	}
	cw->Window = Win;
	cw->xoff = xoff;
	cw->yoff = yoff;
	cw->fw = fw;
	cw->fh = fh;
	cw->font = font;
	AddHead((struct List *)&SnapRsrc->CachedWindows, (struct Node *)cw);
	if (SnapRsrc->CacheSize > 0)
	{
		--SnapRsrc->CacheSize;
	}
	else
	{
		cw = (struct CacheWindow *)RemTail((struct List *)&SnapRsrc->CachedWindows);
		Kill(cw);
	}
}

VOID CacheSync(Font)
	struct TextFont *Font;
{
	struct CacheWindow *cw;
	struct CacheWindow *safe;

	SAFEMAPLIST(&SnapRsrc->CachedWindows, struct CacheWindow *, cw, safe)
	{
		if (cw->font == SnapRsrc->AlternateFont)
		{
			Remove((struct Node *)cw);
			Kill(cw);
		}
	}
}

struct CacheWindow *GetCachedWindow(Screen, Win)
	struct Screen *Screen;
	struct Window *Win;
{
	struct CacheWindow *cw;

	MAPLIST(&SnapRsrc->CachedWindows, struct CacheWindow *, cw)
	{
		if (cw->Window == Win)
		{
			LONG LockVal = LockIBase(0L);
			REGISTER struct Window *w = Screen->FirstWindow;

			while (w && w != Win)
			{
				w = w->NextWindow;
			}
			UnlockIBase(LockVal);
			if (!w)
			{
				return NULL;
			}
			Remove((struct Node *)cw);
			AddHead((struct List *)&SnapRsrc->CachedWindows, (struct Node *)cw);
			return cw;
		}
	}
	return NULL;
}

struct TextFont *SmartOpenFont(ta)
	struct TextAttr *ta;
{
	struct TextFont *MemF;
	struct TextFont *DskF = NULL;

	if ((MemF = OpenFont(ta)) && ta->ta_YSize == MemF->tf_YSize)
	{
		return MemF;
	}

	if (DiskfontBase)
	{
		DskF = OpenDiskFont(ta);
	}

	if (!MemF)
	{
		return DskF;
	}
	if (!DskF)
	{
		return MemF;
	}
	if (abs(ta->ta_YSize - MemF->tf_YSize) <=
	    abs(ta->ta_YSize - DskF->tf_YSize))
	{
		CloseFont(DskF);
		return MemF;
	}
	CloseFont(MemF);
	return DskF;
}


/*
	00000RGB
	0000000R
	000000R0
*/

UBYTE RGB4ToRR( ULONG RGB4)
{
	UBYTE R = ( RGB4 >> 8) & 0x0F;
	return (UBYTE)( R | ( R << 4));
}
UBYTE RGB4ToGG( ULONG RGB4)
{
	UBYTE R = ( RGB4 >> 4) & 0x0F;
	return (UBYTE)( R | ( R << 4));
}
UBYTE RGB4ToBB( ULONG RGB4)
{
	UBYTE R = ( RGB4 >> 0) & 0x0F;
	return (UBYTE)( R | ( R << 4));
}

UBYTE RGB32ToRGB8( ULONG RGB32)
{
	return (UBYTE)( RGB32 >> 24);
}

ULONG RGB8ToRGB32( UBYTE RGB8)
{
	return ( ( (ULONG)RGB8 << 24) | ( (ULONG)RGB8 << 16) | ( (ULONG)RGB8 << 8) | ( (ULONG)RGB8 << 0) );
}
