/*	demo.c
	Shows how to use the Madhouse-interface with a C-like language.

   Instructions to compile the program:
	- Perhaps your compiler doesn't like <pragma/...>, then use another
	  name for this directory.
	- This program can be compiled without problems with MaxonC++ v3.
	  For other compilers, you might have to change something.
*/

#include <dos/dos.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <pragma/graphics_lib.h>
#include <pragma/intuition_lib.h>
#include <pragma/exec_lib.h>
#include <pragma/dos_lib.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#define ABNC 0x40
#define ABC  0x80


/* Prototypes */
void write_stopblank();
void read_prefs();
void write_error( char *str );


/* Variables */
char text[40];
short color, scroll;
time_t start;
short duration_sec=0;
struct Library *IntuitionBase = NULL;
struct Library *GfxBase = NULL;
struct Screen *scr = NULL;
struct Window *win = NULL;
struct Message *msg = NULL;
USHORT DemoPalette[] = {
	0x0000, 0x0FFF
};
struct TextAttr topaz8 = {
	"topaz.font",
	8,
	0,
	0
};

/***************************************************************************
***                          open_all()
***                  Opens all things we need.
***************************************************************************/

BOOL open_all()
{
	IntuitionBase = OpenLibrary("intuition.library",37);
	if( !IntuitionBase ) return FALSE;
	GfxBase = OpenLibrary("graphics.library",37);
	if( !GfxBase ) return FALSE;

	/* Open a standard LowRes-screen. */
	scr = OpenScreenTags(NULL,
		  SA_Depth,         1,
		  SA_Width,         320,
        SA_Height,        256,
		  SA_Font,          &topaz8,
		  TAG_DONE);
	if(!scr) return FALSE;
	
	/* Set the colors of the mouse-pointer to the background-colors. */
	SetRGB4( &scr->ViewPort,17,0,0,0);
	SetRGB4( &scr->ViewPort,18,0,0,0);
	SetRGB4( &scr->ViewPort,19,0,0,0);
	
	win = OpenWindowTags(NULL,
			 WA_AutoAdjust,    TRUE,
			 WA_NoCareRefresh, TRUE,
			 WA_CustomScreen,  scr,
			 WA_Flags,         WFLG_RMBTRAP,
			 WA_Borderless,    TRUE,
			 WA_Activate,      TRUE,
			 WA_IDCMP,			 IDCMP_MOUSEBUTTONS+IDCMP_RAWKEY,
			 TAG_DONE );
	if( !win ) return FALSE;
	
	LoadRGB4( &scr->ViewPort, DemoPalette, 2 );
	
	return TRUE;
}

/***************************************************************************
***                          close_all()
***                 Closes all things we needed.
***************************************************************************/

void close_all()
{
	/* This brings the screen behind all others and should avoid some
	   stupid effects when closing screen with 68000-Amigas. */
	if( scr )
		ScreenToBack( scr );
	
	/* If something went wrong, we should tell this Madhouse. But mustn't
	   write more then one lines in the errors-file. So we use this nice
		if-construct: */
	if( !IntuitionBase ) write_error( "No intuition.lib V37!" );
	else {
		if( !GfxBase ) write_error( "No graphics.lib V37!" );
		else {
			if( !scr ) write_error( "Out of memory: Couldn't open screen.");
			else {
				if( !win ) write_error( "Out of memory: Couldn't open window.");
			}
		}
	}
	
	/* Now we close all what we could open. */
	if( win ) CloseWindow( win );
	if( scr ) CloseScreen( scr );
	if( GfxBase ) CloseLibrary( GfxBase );
	if( IntuitionBase ) CloseLibrary( IntuitionBase );
}

/***************************************************************************
***                          main()
***                Here the real blanker begins.
***************************************************************************/

void main()
{
	BOOL quit = FALSE;
	BOOL user_quit = FALSE;
	short ypos = 20;
	short direction = 1;
	short oldy;
	
	/* First read the settings for our blanker and the duration-value.*/
	read_prefs();
	
	/* Now we start our stop-watch. */
	start = time(NULL);
	
	/* Open screen and window. */
	if(open_all()) {
		
		/* Color-parameter: set the right color. */
		switch( color ) {
			case 0:
				SetRGB4( &scr->ViewPort, 1, 15,0,0 );
				break;
			case 1:
				SetRGB4( &scr->ViewPort, 1, 15,15,0 );
				break;
			case 2:
				SetRGB4( &scr->ViewPort, 1, 0,0,15 );
		}
		
		/* Text-parameter: write the text. */
		SetAPen( win->RPort, 1 );
		Move( win->RPort, 5, ypos );
		Text( win->RPort, text, ( strlen(text) > 38 ? 38 : strlen(text)) );
		
		/* Main-Loop. */
		while( !quit ) {
			
			/* If the user selected Scroll, scroll the text. */
			if( scroll ) {
				oldy = ypos;
				ypos += direction;
				if( (ypos > 220)  ||  (ypos < 20) ) direction *= -1;
				
				ClipBlit(win->RPort, 5, oldy-10, win->RPort, 5, ypos-10, 310, 20, ABNC | ABC );
				/* Minterms ABNC | ABC -> copy the rectangle without modifications. */
			}
			
			/* Mousbutton or key? */
			if( msg = GetMsg(win->UserPort) ) {
				quit = TRUE;
				user_quit = TRUE;
				ReplyMsg( msg );
			}
			
			/* When 'Change Blanker' is activated ( duration_sec is not 0 )
			   AND we blanked (one second) longer as we are allowed to
				( difftime(time(NULL),start) > time_counter ) then quit. */
			if( duration_sec && difftime(time(NULL),start) > duration_sec )
				quit = TRUE;
			
			
			WaitTOF();
		}
		
	}
	
	/* Close our stuff and -perhaps- write the error. */
	close_all();
	
	/* If the user stopped our Blanker, we have to inform Madhouse about
	   this, otherwise it would perhaps (if 'Change Blanker' is activated)
	   start a new blanker. */
	
	if( user_quit )
		write_stopblank();
	
	/* And finished! */
}


/***************************************************************************
***                                                                      ***
***              Functions for the communication with Madhouse           ***
***                                                                      ***
***************************************************************************/

/* Some global variables: */

char bu[1500];        /* The buffer bu[] includes the whole prefs-file. */
short bu_seek = 0;    /* bu_seek is the read-offset of bu[]. We need this
                         variable to see where we have to read the next
                         parameter. */

/* First some useful functions: */

/***************************************************************************
***                          read_next_digit()
***              Reads the next parameter out of our prefs-file.
***                   The next parameter must be a number.
***************************************************************************/

long read_next_digit()
{
	short number_cnt = 0;
	char number[50];
	
	while( bu[bu_seek] != (char) 0x0D ) {
		number[number_cnt] = bu[bu_seek];
		bu_seek++;
		number_cnt++;
	}
	number[number_cnt] = (char) 0x00;

	/*  Overjump the (0x0D)(0x0A)
	 *  (Madhouse places these sequences between the lines.)   */
	bu_seek+=2;
	
	return strtol( number, 0, 10 );
}

/***************************************************************************
***                          read_next_string()
***              Reads the next parameter out of our prefs-file.
***                   The next parameter must be a string.
***************************************************************************/

void read_next_string( char *string, short maxlen )
{
	short text_cnt = 0;
	
	/* A Madhouse-Text begins begins with a "$", so we jump over the first
	   char. */
	bu_seek++;
	
	
	while( (bu[bu_seek] != (char) 0x0D)  &&  (text_cnt < maxlen)  ) {
		string[text_cnt] = bu[bu_seek];
		bu_seek++;
		text_cnt++;
	}
	
	string[text_cnt] = (char) 0x00;
	/* Now we have the text in string[]. */
	
	
	/*
	 *  Jump over the (0x0D)(0x0A)
	 */
	
	bu_seek+=2;
}




/***************************************************************************
***                             read_prefs()
***                        Reads the preferences.
***************************************************************************/

void read_prefs()
{
	short text_cnt = 0;
	short number_cnt = 0;
	BPTR f = NULL;
	
	f = Open( "RAM:Madhouse_Storage/prefs", MODE_OLDFILE );
	if (f) {
		Read( f, bu, sizeof( bu ) );
		
		/* Now, bu[] has a contents like this:
		   "$Hello, this is a text(0x0D)(0x0A)2(0x0D)(0x0A)0(0x0D)(0x0A)
			5(0x0D)(0x0A)RAM:Madhouse_Storage(0x0D)(0x0A)".
		   (0x0D) and (0x0A) are between every line.
		   Hello,... is our first parameter, 2 our second, 0 our third,
			5 the duration in minutes and RAM:.. a path to our directory,
			if we need data from it.
			All Madhouse-strings begin with a "$".
		   We will put the first parameter in text[], the second in color,
			the duration in duration_sec and the path is not needed. */
		
		/*
		 *   First parameter (Text)
		 */
		 
		read_next_string( text, 40 );
		
		/*
		 *  Second parameter (Color)
		 */
		
		color = read_next_digit();
		
		/*
		 *  Third parameter (Scroll)
		 */
		
		scroll = read_next_digit();
		
		/*
		 *  Duration-Parameter.
		 */
		
		duration_sec = read_next_digit() *  60; /*Minutes -> Seconds*/
		
		Close( f );
	} else {
		/* The Blanker was not started by Madhouse. Quit here.*/
		exit(0);
	}
}		

/***************************************************************************
***                           write_stopblank()
***           Must be used if the user aborted the blanker himself.
***************************************************************************/

void write_stopblank()
{
	/* Just create a new empty file to inform Madhouse that the user has
	   aborted the blanker. */
	
	BPTR f;
	f = Open( "RAM:Madhouse_Storage/stopblank", MODE_NEWFILE );
	if( f )
		Close( f );
}

/***************************************************************************
***                           write_error()
***      Tells Madhouse that an error occurred - can only be used ONCE!
***************************************************************************/

void write_error( char *str )
{
	BPTR f;
	char eol_marker = 0x0D;
	
	f = Open( "RAM:Madhouse_Storage/errors", MODE_READWRITE );
	if( f ) {
		Seek( f, 0, OFFSET_END );
		Write( f, str, strlen(str) );
		Write( f, &eol_marker, 1 );
		Close( f );
	} 
}




