/*
 * 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/gadgetclass.h>
#include <libraries/gadtools.h>
#include <libraries/asl.h>
#include <graphics/text.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/dos_protos.h>
#include <clib/diskfont_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/utility_protos.h>
#include <clib/asl_protos.h>
#include <clib/alib_protos.h>

#include <stdio.h>

#include "Text.h"
#include "Text_rev.h"
#include "/defs.h"
#include "/utility.h"

struct tPrefObject {
	UBYTE text[128];
	UBYTE fName[64];
	UBYTE Speed;
	UBYTE State;
	UBYTE Cycle;
	struct TextAttr Font;
};

struct	tPrefObject	nP;

VOID blank( VOID );

STATIC	const	UBYTE	VersTag[] = VERSTAG;
extern	struct	Task	**Task;
extern		ULONG   Depth, Mode;
extern		UBYTE   *prefData;

VOID setTextPrefs( VOID )
{
        GT_SetGadgetAttrs( TextGadgets[GD_SPEED], TextWnd, 0L, GTSL_Level, nP.Speed, 0L );
	GT_SetGadgetAttrs( TextGadgets[GD_FTXT], TextWnd, 0L, GTTX_Text, nP.fName, 0L );
	if( nP.State ) GT_SetGadgetAttrs( TextGadgets[GD_FONT], TextWnd, 0L, GA_Disabled, TRUE, 0L );
	else GT_SetGadgetAttrs( TextGadgets[GD_FONT], TextWnd, 0L, GA_Disabled, FALSE, 0L );
	GT_SetGadgetAttrs( TextGadgets[GD_FSIZE], TextWnd, 0L, GTNM_Number, nP.Font.ta_YSize, 0L );
	GT_SetGadgetAttrs( TextGadgets[GD_TXT], TextWnd, 0L, GTST_String, nP.text, 0L );
	GT_SetGadgetAttrs( TextGadgets[GD_SWITCH], TextWnd, 0L, GTCY_Active, nP.State, 0L );
	GT_SetGadgetAttrs( TextGadgets[GD_CYCLE], TextWnd, 0L, GTCY_Active, nP.Cycle, 0L );
}

int OKClicked( VOID )
{
	CopyMem( &nP, prefData, sizeof( struct tPrefObject ));
	return( QUIT );
}

int TESTClicked( VOID )
{
	*Task = FindTask( 0L );
	blank();
	return( CONTINUE );
}

int CANCELClicked( VOID )
{
	return( QUIT );
}

int SPEEDClicked( VOID )
{
	nP.Speed = TextMsg.Code;
	return( CONTINUE );
}

int SWITCHClicked( VOID )
{
	nP.State = TextMsg.Code;
	setTextPrefs();
	return( CONTINUE );
}

int CYCLEClicked( VOID )
{
	nP.Cycle = TextMsg.Code;
	return( CONTINUE );
}

int FONTClicked( VOID )
{
	struct FontRequester *fReq;

	if( fReq = ( struct FontRequester * )AllocAslRequestTags( ASL_FontRequest, ASL_FontName, (ULONG)nP.fName,
		ASL_FontHeight, nP.Font.ta_YSize, ASL_MaxHeight, 100, TAG_DONE )) {
		if( AslRequestTags( fReq, ASLFO_Window, TextWnd, ASLFO_SleepWindow, TRUE, ASLFO_TitleText,
			(ULONG)"Please choose a font...", 0L )) {
			CopyMem( fReq->fo_Attr.ta_Name, nP.fName, 31 );
			nP.Font.ta_YSize = fReq->fo_Attr.ta_YSize;
		}
		FreeAslRequest( fReq );
	}
	setTextPrefs();
	return( CONTINUE );
}

int TXTClicked( VOID )
{
	CopyMem( (( struct StringInfo * )( TextGadgets[GD_TXT] )->SpecialInfo )->Buffer, nP.text, 128 );
	return( CONTINUE );
}

int TextVanillaKey( VOID )
{
	switch( TextMsg.Code ) {
	case 'o':
		return( OKClicked() );
	case 't':
		return( TESTClicked() );
	case 'c':
		return( CANCELClicked() );
	case 'f':
		return( FONTClicked());
	case 's':
		GT_SetGadgetAttrs( TextGadgets[GD_SPEED], TextWnd, 0L, GTSL_Level, ++(nP.Speed) > 50 ?
			nP.Speed = 50 : nP.Speed, 0L );
		return( CONTINUE );
	case 'S':
		GT_SetGadgetAttrs( TextGadgets[GD_SPEED], TextWnd, 0L, GTSL_Level, --(nP.Speed) < 1 ?
			nP.Speed = 1 : nP.Speed, 0L );
		return( CONTINUE );
	default:
		return( CONTINUE );
	}
}

VOID prefs( LONG command )
{
	switch( command ) {
	case STARTUP:
		CopyMem( prefData, &nP, sizeof( struct tPrefObject ));
		nP.Font.ta_Name = nP.fName;
		if( !SetupScreen() ) {
			if( !OpenTextWindow()) setTextPrefs();
			CloseDownScreen();
		}
		break;
	case IDCMP:
		if( HandleTextIDCMP() != QUIT ) break;
	case KILL:
		CloseTextWindow();
	}
}

LONG winSig( VOID )
{
	return( TextWnd ? ( 1L << TextWnd->UserPort->mp_SigBit ) : 0L );
}

VOID blank( VOID )
{
	struct	TextFont	*font;
	struct	tPrefObject	*tP;
	struct	Screen		*TextScr;
	UBYTE	vals[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4,
		3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
	UBYTE	scrText[128], c1 = 0, c2 = 14, c3 = 28, *ptr;
	ULONG	x = 2, y, Wid, Hei, len, numc, base, count;
	LONG	dx = 1, dy = 1, delay, cycle = 0;
	FILE	*textFile;

	if( TextWnd ) tP = &nP;
	else tP = ( struct tPrefObject * )prefData;

	if( tP->State ) {
		if( textFile = fopen( tP->text, "r" )) {
			fscanf( textFile, "%lu", &count );
			numc = VBeamPos()%(count+1);
			while((( fgetc( textFile ) == '\n' )?++cycle:cycle ) < numc );
			fscanf( textFile, "%s %d ", tP->fName, &delay );
			tP->Font.ta_YSize = (WORD)delay;
			fgets( scrText, 128, textFile );
			for( ptr = scrText; ptr[0]; ++ptr );
			(--ptr)[0] = 0;
			fclose( textFile );
		} else sprintf( scrText, "Could not open: %s", tP->text );
	} else CopyMem( tP->text, scrText, 128 );

	tP->Font.ta_Name = tP->fName;
	font = OpenDiskFont( &( tP->Font ));
	base = font->tf_Baseline;

	TextScr = OpenScreenTags( 0l, SA_DisplayID, Mode, SA_Depth, 1, SA_Quiet, TRUE, SA_Overscan, OSCAN_STANDARD,
		SA_Font, &( tP->Font ), TAG_DONE );

	Wid = TextScr->Width;
	Hei = TextScr->Height;

	for( ptr = scrText; ptr[0]; ++ptr );
	numc = ptr-scrText;
	while(( len = TextLength( &(TextScr->RastPort), scrText, numc )) >= Wid-5 ) numc--;

	y = VBeamPos()%( Hei - tP->Font.ta_YSize );

	SetRGB4( &(TextScr->ViewPort), 0, 0L, 0L, 0L );
	switch( tP->Cycle ) {
	case 0:
		SetRGB4( &(TextScr->ViewPort), 1, vals[c1], vals[c2], vals[c3] );
		break;
	case 1:
		SetRGB4( &(TextScr->ViewPort), 1, VBeamPos()%15 + 1, VBeamPos()%15 + 1, VBeamPos()%15 + 1 );
		break;
	case 2:
		SetRGB4( &(TextScr->ViewPort), 1, 15, 15, 15 );
		break;
	case 3:
		setCopperList( Hei, 1, &( TextScr->ViewPort ));
		break;
	}		

	SetAPen( &(TextScr->RastPort), 1 );
	Move( &(TextScr->RastPort), x, y + base );
	Text( &(TextScr->RastPort), scrText, numc );

	delay = 51 - tP->Speed;

	while(!( SetSignal( 0L, 0L )&SIGBREAKF_CTRL_C )) {
		if(!( ++count%delay )) {
			if( !tP->Cycle && !(count%(10*delay))) SetRGB4( &(TextScr->ViewPort), 1, vals[c1 = ++c1%42],
				vals[c2 = ++c2%42], vals[c3 = ++c3%42] );
			ScrollRaster( &(TextScr->RastPort), dx, dy, x-1, y-1, x+1+len, y+1+tP->Font.ta_YSize );
			x -= dx; y -= dy;
			if( x < 2 ) dx = -1;
			else if( x > Wid-len-2 ) dx = 1;
			if( y < 2 ) dy = -1;
			else if( y > Hei-tP->Font.ta_YSize-2 ) dy = 1;
		}
	}
	SetSignal( 0L, SIGBREAKF_CTRL_C );

	if( font ) CloseFont( font );
	CloseScreen( TextScr );
}

VOID defaults( struct bMessage *Msg )
{
	static struct tPrefObject tPO = { "Every dog should have a boy.", "topaz.font", 10, 0, 0 };

	tPO.Font.ta_YSize = 11;
	tPO.Font.ta_Style = FS_NORMAL;
	tPO.Font.ta_Flags = FPB_ROMFONT;

	Msg->bm_Dep = 1;
	Msg->bm_Mod = INVALID_ID;

	Msg->bm_Info = "Bouncing Text Module";
	Msg->bm_Data = ( UBYTE * )( &tPO );
}
