/*
 * Copyright (c) 1993 Michael D. Bayne.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 * the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *    following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
 *    following disclaimer in the documentation and/or other materials provided with the distribution.
 *
 * 3. All advertising materials mentioning features or use of this software must display the following
 *    acknowledgement:
 *
 *       This product includes software developed by Michael D. Bayne.
 *
 * 4. My name may not be used to endorse or promote products derived from this software without specific prior
 *    written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY MICHAEL D. BAYNE ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL MICHAEL D. BAYNE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <exec/types.h>
#include <exec/memory.h>

#include <dos/dos.h>

#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <intuition/intuitionbase.h>

#include <graphics/gfxmacros.h>
#include <graphics/copper.h>
#include <graphics/videocontrol.h>

#include <hardware/custom.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/dos_protos.h>

extern struct IntuitionBase *IntuitionBase;
extern struct Custom far custom;

struct	BitMap		*newMap;

VOID setCopperList( ULONG height, ULONG color, struct ViewPort *vp )
{
	#define NUMCOLORS 45

	struct	UCopList	*uCopList;
	struct	TagItem	uCopTags[] = { { VTAG_USERCLIP_SET, 0L }, { VTAG_END_CM, 0L } };
	register	USHORT	i, index = VBeamPos()%NUMCOLORS, spc;
        UWORD	spectrum[] = {  0x0F00, 0x0E10, 0x0D20, 0x0C30, 0x0B40, 0x0A50, 0x0960, 0x0870, 0x0780, 0x0690,
				0x05A0, 0x04B0, 0x03C0, 0x02D0, 0x01E0, 0x00F0, 0x00E1, 0x00D2, 0x00C3, 0x00B4,
				0x00A5, 0x0096, 0x0087, 0x0078, 0x0069, 0x005A, 0x004B, 0x003C, 0x002D, 0x001E,
				0x000F, 0x010E, 0x020D, 0x030C, 0x040B, 0x050A, 0x0609, 0x0708, 0x0807, 0x0906,
				0x0A05, 0x0B04, 0x0C03, 0x0D02, 0x0E01 };
    
	if( uCopList = ( struct UCopList * )AllocMem( sizeof( struct UCopList ), MEMF_PUBLIC|MEMF_CLEAR )) {

		spc = height/NUMCOLORS;

		CINIT( uCopList, NUMCOLORS );

		for( i = 0; i<NUMCOLORS; ++i ) {
			CWAIT( uCopList, i*spc, 0 );
			CMOVE( uCopList, custom.color[color], spectrum[(i+index)%NUMCOLORS] );
		}

		CEND( uCopList );

		Forbid();
		vp->UCopIns = uCopList;
		Permit();

		VideoControl( vp->ColorMap, uCopTags );

		RethinkDisplay();
	}
}

ULONG getTopScreenMode( void )
{
	BPTR lock;
	struct	Screen	*pubScr;
	ULONG scrMode;

	lock = LockIBase( 0 );
	pubScr = IntuitionBase->FirstScreen;
	scrMode = GetVPModeID( &(pubScr->ViewPort));
	UnlockIBase( lock );
	return( scrMode );
}

ULONG getTopScreenDepth( void )
{
	BPTR lock;
	struct	Screen	*pubScr;
	struct	DrawInfo *dri;
	ULONG sDep = 0;

	lock = LockIBase( 0 );
	pubScr = IntuitionBase->FirstScreen;
	if( dri = GetScreenDrawInfo( pubScr )) {
		sDep = dri->dri_Depth;
		FreeScreenDrawInfo( pubScr, dri );
	}
	UnlockIBase( lock );
	return( sDep );
}

struct Screen *cloneTopScreen( void )
{
	struct	Screen *Scr, *nScr = 0L;
	struct	DrawInfo *dri;
	BPTR	lock;
	ULONG	sMod, sDep, i, Wid, Hei, offx, offy;
	UWORD	*cols;
	UBYTE	*allocated = ( UBYTE * )1;

	/* Lock IntuitionBase so nothing goes away while we're playing with it */
	lock = LockIBase( 0 );

	/* Grab the first screen and get its attributes */
	Scr = IntuitionBase->FirstScreen;
	sMod = GetVPModeID( &(Scr->ViewPort)); /* Screen Mode ID */
	offx = Scr->LeftEdge; 
	offy = Scr->TopEdge;
	Wid = Scr->Width;
	Hei = Scr->Height;
	if( dri = GetScreenDrawInfo( Scr )) sDep = dri->dri_Depth;
	if( cols = AllocMem( sizeof( WORD ) * ( 1L<<sDep ), MEMF_CLEAR ))
		for( i = 0; i < (1L<<sDep); ++i )
			cols[i] = GetRGB4( Scr->ViewPort.ColorMap, i );
	if( newMap = AllocVec( sizeof( struct BitMap ), MEMF_CLEAR|MEMF_PUBLIC )) {
		InitBitMap( newMap, sDep, Wid, Hei );
		for( i = 0; ( i < sDep && allocated ); ++i ) {
			allocated = ( newMap->Planes[i] = AllocRaster( Wid, Hei ));
			if( allocated ) CopyMem( Scr->BitMap.Planes[i], newMap->Planes[i],
				newMap->BytesPerRow * newMap->Rows );
		}
		if( allocated == NULL ) {
			for( i = 0; i < sDep; ++i ) if( newMap->Planes[i] )
				FreeRaster( newMap->Planes[i], Wid, Hei );
			newMap = NULL;
		}
	}

	UnlockIBase( lock );

	if( sMod != INVALID_ID ) {
		if( nScr = OpenScreenTags( NULL, SA_Width, Wid, SA_Height, Hei, SA_Depth, sDep, SA_Overscan,
			OSCAN_MAX, SA_DisplayID, sMod, SA_Pens, (ULONG)dri->dri_Pens, SA_Behind, TRUE, SA_BitMap,
			(ULONG)newMap, SA_Quiet, TRUE )) {
			LoadRGB4( &(nScr->ViewPort), cols, 1L << sDep );
			MoveScreen( nScr, offx, offy<0?offy:0 );
			ScreenToFront( nScr );
		}
	}
	if( cols ) FreeMem( cols, ( 1L << sDep ) * sizeof( UWORD ));
	if( dri ) FreeScreenDrawInfo( Scr, dri );
	return( nScr );
}

void closeTopScreen( struct Screen *Scr )
{
	ULONG i, Wid, Hei;

	Wid = Scr->Width;
	Hei = Scr->Height;
	CloseScreen( Scr );
	for( i = 0; i < 8; ++i )
		if( newMap->Planes[i] ) FreeRaster( newMap->Planes[i], Wid, Hei );
	FreeVec( newMap );
}

ULONG fadeScreen( struct Screen *Screen, ULONG delay )
{
	UWORD	col, i, go = 1;

	while( go ) {
		go = 0;
		for( i = 0; i < (1L << Screen->BitMap.Depth); ++i ) {
			if( SetSignal( 0L, SIGBREAKF_CTRL_C ) & SIGBREAKF_CTRL_C ) break;
			if( col = GetRGB4( Screen->ViewPort.ColorMap, i )) go = 1;
			SetRGB4( &(Screen->ViewPort), i,
				((col & 0x0F00)>>8)?((col & 0x0F00)>>8)-1:0,
				((col & 0x00F0)>>4)?((col & 0x00F0)>>4)-1:0,
				(col & 0x000F)?(col & 0x000F)-1:0 );
		}
		if( i == (1L<<Screen->BitMap.Depth)) Delay( delay );
		else return( FALSE );
	}
	return( TRUE );
}
