;/*
sc RESOPT DATA=NEAR UCHAR CONSTLIB STREQ NMINC IGNORE=73 Fortune.c DBG=LINE
slink from LIB:c.o Fortune.o to //Clients/Fortune LIB LIB:sc.lib LIB:amiga.lib /lib/client.lib SC SD NOICONS
;sc RESOPT DATA=NEAR UCHAR CONSTLIB STREQ NMINC STRMERGE NOSTKCHK NOSTDIO OPTIMIZE OPTSIZE IGNORE=73 Fortune.c
;slink from LIB:c.o Fortune.o to //Clients/Fortune LIB LIB:sc.lib LIB:amiga.lib /lib/client.lib SC SD NOICONS STRIPDEBUG
delete Fortune.o
quit

 Fortune 1.1  (Client for BServer)

 Copyright © 1995 by Stefano Reksten of 3AM - The Three Amigos!!!
 All rights reserved.
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <graphics/text.h>
#include <graphics/rastport.h>
#include <utility/tagitem.h>

#include <clib/alib_protos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/diskfont.h>
#include <string.h>

#include "/include/client.h"
#include "/include/bitmap/bitmap_pragmas.h"

char *ver = "$VER: Fortune 1.1 "__AMIGADATE__;

char *defaultcookie = "Amiga#rules#!!!";

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *DiskfontBase, *BitMapBase;
struct DisplayIDInformation *dinfo;
struct Rectangle *rect;

struct TextAttr tattr = { "diamond.font", 20, 0, FPF_DISKFONT };
struct TextFont *newfont;
struct Screen *scr;
struct BitMap *tbm;
struct RastPort *rp;
struct IntuiText iFortune = { 1, 0, JAM1, 0, 0, NULL, NULL, NULL };

UWORD maxstrlen = 0;

int tot_strings = 1, max_strings;
STRPTR strings[10];
char buffer[1024];
WORD swidth, sheight, xcrd, ycrd;
UWORD fontheight;
UBYTE brightness;

struct TagItem scrtags[] = {
	{ SA_DisplayID, NULL, },
	{ SA_Left, NULL },
	{ SA_Width, NULL },
	{ SA_Height, NULL },
	{ SA_Top, 0 },
	{ SA_Depth, 1 },
	{ SA_Overscan, OSCAN_TEXT },
	{ SA_Quiet, TRUE },
	{ TAG_END } };


UBYTE RGBComp( void )
{ return (UBYTE)(5 + RangeRand( 10 ) * brightness / 100); }

void ChangeFirstColor( void )
{ SetRGB4( &(scr->ViewPort), 1, RGBComp(), RGBComp(), RGBComp() ); }


void DrawScroller( void )
{
UWORD twidth;
int n;
BOOL success = FALSE;

twidth = strlen( buffer );
for ( n = 0; n < twidth; n++ )
	if ( buffer[n] == '\t' || buffer[n] == '\n' )
		buffer[n] = ' ';

iFortune.IText = buffer;
twidth = IntuiTextLength( &iFortune ) + 1;

if ( tbm = CreateBitMap( twidth, tattr.ta_YSize, 1 ) )
	{
	if ( rp = AllocVec( sizeof(struct RastPort), MEMF_ANY|MEMF_CLEAR ) )
		{
		InitRastPort( rp );
		rp->BitMap = tbm;

		SetAPen( rp, 1 );
		PrintIText( rp, &iFortune, 0, 0 );

		if ( scr = OpenScreenTagList( NULL, scrtags ) )
			{
			register struct ViewPort *vp = &(scr->ViewPort);
			register struct RastPort *rp = &(scr->RastPort);

			SpritesOff();

			SetRGB4( vp, 0, 0, 0, 0 );
			ChangeFirstColor();

			fontheight = ( newfont ? newfont->tf_YSize : rp->Font->tf_YSize );
			xcrd = twidth - 1;
			ycrd = RangeRand( scr->Height - fontheight - 1 );

			while( STILL_BLANKING )
				{
				if ( ++xcrd == twidth )
					{
					xcrd = - ( swidth - 1 );
					ycrd = RangeRand( sheight - fontheight - 1 );
					ChangeFirstColor();
					}

				WaitTOF();
				if ( xcrd < 0 )
					BltBitMap( tbm, 0, 0,
						scr->RastPort.BitMap, - xcrd, ycrd,
						swidth + xcrd > twidth ? twidth : swidth + xcrd, fontheight, 0xC0, 0xFF, NULL );
				else
					BltBitMap( tbm, xcrd, 0,
						scr->RastPort.BitMap, 0, ycrd,
						twidth - xcrd > swidth ? swidth : twidth - xcrd, fontheight, 0xC0, 0xFF, NULL );
				}

			CloseScreen( scr );
			SpritesOn();
			}
		FreeVec( rp );
		}
	DisposeBitMap( tbm );
	}

if ( !success )
	SendClientMsg( ACTION_FAILED );
}


void PrintMyFortune( int colorpen )
{
register int n;

iFortune.FrontPen = colorpen;
for ( n = 0; n < tot_strings; n++ )
	{
	iFortune.IText = strings[n];
	PrintIText( &scr->RastPort, &iFortune, xcrd + (maxstrlen-IntuiTextLength(&iFortune))>>1, ycrd + n * (fontheight+4) );
	}
}


void DrawText( void )
{
STRPTR string;
int delay = 199;
int n, m;

string = buffer;
strings[0] = string;
while ( *string )
	{
	if ( *string == '#' )
		{
		*string = 0;
		string++;
		if ( tot_strings < 10 )
			{
			strings[tot_strings] = string;
			tot_strings++;
			}
		else break;
		}
	string++;
	}

for ( n = 0; n < tot_strings; n++ )
	{
	register UWORD il, strn;

	iFortune.IText = strings[n];
	while ( (il = IntuiTextLength( &iFortune )) > swidth )
		{
		m = strlen( strings[n] ) >> 1;
		while ( m && strings[n][m] != ' ' )
			m--;
		if ( m == 0 )
			{
			m = strlen( strings[n] ) - 1;
			do { strings[n][m--] = 0; }
			while ( m && IntuiTextLength( &iFortune ) > swidth );
			}
		else
			{
			for ( strn = tot_strings; strn > n; strn-- )
				strings[strn] = strings[strn-1];
			strings[n+1] = &strings[n][m] + 1;
			strings[n][m] = 0;
			tot_strings++;
			}
		}
	if ( il > maxstrlen )
		maxstrlen = il;
	}

if ( maxstrlen > swidth )
	{
	tot_strings = 1;
	strings[0] = "BServer :-)";
	iFortune.IText = strings[0];
	maxstrlen = IntuiTextLength( &iFortune );
	}

if ( scr = OpenScreenTagList( NULL, scrtags ) )
	{
	register struct ViewPort *vp = &(scr->ViewPort);
	register struct RastPort *rp = &(scr->RastPort);

	SpritesOff();

	SetRGB4( vp, 0, 0, 0, 0 );
	ChangeFirstColor();

	fontheight = ( newfont ? newfont->tf_YSize : rp->Font->tf_YSize );
	max_strings = sheight / (fontheight + 4);
	if ( max_strings < tot_strings )
		tot_strings = max_strings;

	while( STILL_BLANKING )
		{
		WaitTOF();

		if ( ++delay == 200 )
			{
			delay = 0;
			WaitTOF();
			PrintMyFortune( 0 );
			xcrd = RangeRand( swidth - maxstrlen );
			ycrd = RangeRand( sheight - tot_strings * (fontheight + 4) );
			ChangeFirstColor();
			WaitTOF();
			PrintMyFortune( 1 );
			}
		}

	CloseScreen( scr );
	SpritesOn();
	}
else
	SendClientMsg( ACTION_FAILED );
}


void __main( void )
{
char buff[40], filebuff[256];
extern int atoi( const char * );
ULONG s, m;
BOOL scroll = FALSE;

if ( IntuitionBase = (struct IntuitionBase *)OpenLibrary( "intuition.library", 37L ) )
	{
	if ( GfxBase = (struct GfxBase *)OpenLibrary( "graphics.library", 37L ) )
		{
		if ( BitMapBase = OpenLibrary( "bitmap.library", 0L ) )
			{
			if ( dinfo = OpenCommunication() )
				{
				CurrentTime( &s, &m );

				if ( GetArgString( dinfo->di_Args, "FONTHEIGHT", buff ) )
					tattr.ta_YSize = atoi( buff );
				if ( GetArgString( dinfo->di_Args, "FONTNAME", buff ) )
					tattr.ta_Name = buff;
				if ( Check4String( dinfo->di_Args, "SCROLL" ) )
					scroll = TRUE;

				buffer[0] = 0;
				if ( !GetArgString( dinfo->di_Args, "TEXT", buffer ) )
					{
					/* get a cookie */
					char *mptr;
					BPTR b;
					struct FileInfoBlock fib;
					ULONG pos, pos2;

					if ( !GetArgString( dinfo->di_Args, "FILE", filebuff ) )
						strcpy( filebuff, "MISC/Fortune.data" );

					buffer[0] = 0;
					if ( b = Lock( filebuff, ACCESS_READ ) )
						{
						Examine( b, &fib );
						UnLock( b );

						if ( mptr = AllocVec( fib.fib_Size, MEMF_ANY ) )
							{
							b = Open( filebuff, MODE_OLDFILE );
							Read( b, mptr, fib.fib_Size );
							Close( b );
							pos = m % fib.fib_Size;
							while ( mptr[pos] != 164 && pos )
								pos--;
							pos++;
							pos2 = pos;
							while ( mptr[pos2] != '¤' && pos2 < fib.fib_Size )
								{
								if ( mptr[pos2] == '\n' && !scroll )
									mptr[pos2] = '#';
								pos2++;
								}
							mptr[pos2] = 0;
							strncpy( buffer, mptr + pos + 1, pos2 - pos - 1 );
							FreeVec( mptr );
							}
						}
					}
				if ( !buffer[0] )
					strcpy( buffer, defaultcookie );


				if ( DiskfontBase = OpenLibrary( "diskfont.library", 37L ) )
					{
					if ( newfont = OpenDiskFont( &tattr ) )
						{
						tattr.ta_Flags = newfont->tf_Flags;
						iFortune.ITextFont = &tattr;
						}
					}

				iFortune.ITextFont = &tattr;

				rect = GETTXTOSCANRECT(dinfo);
				swidth = RECTANGLEWIDTH(rect);
				sheight = RECTANGLEHEIGHT(rect);
				brightness = GETBRIGHTNESS(dinfo);
				scrtags[0].ti_Data = DISPLAYID( dinfo );
				scrtags[1].ti_Data = (RECTANGLEWIDTH(rect) - swidth)>>1;
				scrtags[2].ti_Data = swidth;
				scrtags[3].ti_Data = sheight;

				if ( scroll )
					DrawScroller();
				else
					DrawText();

				if ( DiskfontBase )
					{
					if ( newfont )
						CloseFont( newfont );
					CloseLibrary( DiskfontBase );
					}

				CloseCommunication( dinfo );
				}
			CloseLibrary( BitMapBase );
			}
		CloseLibrary( (struct Library *)GfxBase );
		}
	CloseLibrary( (struct Library *)IntuitionBase );
	}
}
