/*
    ####             #    #     # #
    #   #            #    #       #          The FreeWare C library for 
    #   #  ##   ###  #  # #     # ###             RISC OS machines
    #   # #  # #     # #  #     # #  #   ___________________________________
    #   # ####  ###  ##   #     # #  #                                      
    #   # #        # # #  #     # #  #    Please refer to the accompanying
    ####   ### ####  #  # ##### # ###    documentation for conditions of use
    ________________________________________________________________________

    File:    Font2.c
    Author:  Copyright  1995 Julian Smith
    Version: 1.01 (14 Nov 1995)
    Purpose: Mode-independant fonts.
    History: 1.00
             1.01 (14 Nov 1995) JS Made SDLS compatible,
*/



#include <stdlib.h>

#include "Desk.Error.h"
#include "Desk.Event.h"
#include "Desk.SWI.h"
#include "Desk.Debug.h"
#include "Desk.DeskMem.h"

#include "Desk.Font2.h"

#ifdef Desk_DeskLib_DEBUG
	int	Desk_font2_debuglevel = 0;
#endif


typedef struct Desk_font2__block	*Desk_font2__blockptr;

typedef struct Desk_font2__block	{
	Desk_font2_block	pub;
	Desk_font2__blockptr	next;
	int		usage;
	}
	Desk_font2__block;
/*
Users of Font2 only get to see the 'pub' part of this.
*/


static Desk_font2__block	*Desk_font2__first = NULL;
static Desk_bool		Desk_font2__initialised = Desk_bool_FALSE;


/*
Desk_font2_blocks are stored in a singly-linked list, which can only get
longer - if a block is no longer used, it is left with usage=0. When a
new block is required though, such unused blocks are reused (see
Desk_Font2__GetOrMakeBlankFont2Block.

*/ 


static Desk_font2__block	*Desk_Font2__MakeNewFont2Block( void)
{
Desk_font2__block	*f;

f = (Desk_font2__block *) Desk_DeskMem_XMalloc( sizeof( Desk_font2__block));
if ( !f)	return NULL;

f->usage = 0;

/* Add this Desk_font2_block to head of our list	*/
f->next		= Desk_font2__first;
Desk_font2__first	= f;

return f;
}



static Desk_font2__block	*Desk_Font2__GetOrMakeBlankFont2Block( void)
/*
Returns an unused Desk_font2_block. Will malloc one if no
unused ones are available
*/
{
Desk_font2__block	*f;

for ( f=Desk_font2__first; f; f=f->next)	{
	if ( f->usage==0)	return f;
	}

/* No unused blocks, so we make a new one	*/
return Desk_Font2__MakeNewFont2Block();
}


Desk_SDLS_PtrFn(
	static,
	Desk_bool,
	Desk_Font2__ModeChangeHandler( Desk_event_pollblock *event, void *reference)
	)
/*static Desk_bool	Desk_Font2__ModeChangeHandler( Desk_event_pollblock *event, void *reference)*/
{
int		j;
Desk_font2__block	*f;

Desk_UNUSED( reference);

if ( event->data.message.header.action != Desk_message_MODECHANGE)	return Desk_bool_FALSE;

/* Should check that the new mode has different eigs	*/

for ( f=Desk_font2__first; f; f=f->next)	{

	Desk_font_defn	defn;
	
	if ( f->usage==0)	continue;
	
	Desk_Font_ReadDefn( f->pub.handle, &defn);
	
	/* Lose all previous occurencies of this font...	*/
	for ( j=0; j<f->usage; j++)	{
		Desk_Font_LoseFont( f->pub.handle);
		}
	
	/* ... and find them again	*/
	for ( j=0; j<f->usage; j++)	{
		/*
		Each of these calls to Desk_Font_FindFont will put the
		same font handle into Desk_font2__fonts[i].handle
		*/
		Desk_Font_FindFont( 
			&f->pub.handle, 
			defn.name, 
			defn.xsize, 
			defn.ysize, 
			0, 	/* Current mode	*/
			0	/* Current mode	*/
			);
		}
	}

return Desk_bool_FALSE;
}




Desk_SDLS_PtrFn(
	static,
	void,
	Desk_Font2__ReleaseFontHandles( void)
	)
/*static void	Desk_Font2_ReleaseFontHandles( void)*/
{
Desk_font2__block	*f;

Desk_Debug_Printf( "Desk_Font2_ReleaseFontHandles called");

for ( f=Desk_font2__first; f; f=f->next)
	for ( ; f->usage; f->usage--)	Desk_Font_LoseFont( f->pub.handle);
}


void	Desk_Font2_Initialise( void)
{
if ( Desk_font2__initialised)	return;
Desk_Event_Claim( Desk_event_USERMESSAGE, Desk_event_ANY, Desk_event_ANY, Desk_SDLS_dllEntry( Desk_Font2__ModeChangeHandler), NULL);
atexit( Desk_SDLS_dllEntry( Desk_Font2__ReleaseFontHandles));
Desk_font2__initialised = Desk_bool_TRUE;
}





Desk_os_error	*Desk_Font2_ReclaimFont( Desk_font2_block **font2, const char *name, int sizex, int sizey)
{

if ( !Desk_font2__initialised)	Desk_Font2_Initialise();

if ( *font2)	Desk_Font2_ReleaseFont( font2);

return Desk_Font2_ClaimFont( font2, name, sizex, sizey);
}




static Desk_font2__block	*Desk_Font2__FindOrMakeFont2BlockForHandle( Desk_font_handle handle)
{
Desk_font2__block	*f;

for ( f=Desk_font2__first; f; f=f->next)	{
	if ( f->pub.handle==handle)	return f;
	}

/* Make a new Desk_font2_block	*/

f = Desk_Font2__GetOrMakeBlankFont2Block();
if ( !f)	return NULL;

f->pub.handle	= handle;
Desk_Font_ReadInfo( handle, &f->pub.info);

return f;
}





Desk_os_error	*Desk_Font2_ClaimFont( Desk_font2_block **font2, const char *name, int sizex, int sizey)
{
Desk_font_handle	handle;
Desk_font2__block	*f;

if ( !Desk_font2__initialised)	Desk_Font2_Initialise();

*font2 = NULL;

Desk_Font_FindFont( &handle, name, sizex, sizey, 0, 0);

f = Desk_Font2__FindOrMakeFont2BlockForHandle( handle);

f->usage++;

*font2 = &f->pub;

return NULL;

}




void	Desk_Font2_ReleaseFont( Desk_font2_block **font2)
{
Desk_font2__block	*f = (Desk_font2__block *) (*font2);

if ( *font2 == NULL)	return;

/* In case this font2 hasn't been used yet	*/

Desk_Font_LoseFont( (*font2)->handle);
f->usage--;
*font2 = NULL;
}





