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

    File:    Error3.c
    Author:  Copyright  1995 Julian Smith
    Version: 1.00 (07 Sep 1995)
    Purpose: High-level error dispatching.
*/


#include "Desk.Error2.h"
#include "Desk.LinkList.h"
#include "Desk.DeskMem.h"
#include "Desk.Debug.h"


/*static Desk_linklist_header	functionhandlers	= { NULL, NULL };*/
static Desk_linklist_header	typehandlers		= { NULL, NULL };
static Desk_linklist_header	mischandlers		= { NULL, NULL };

/*
typedef struct	{
	Desk_linklist_header	header;
	Desk_error2_fnptr	function;
	Desk_error3_handler	handler;
	void		*reference;
	}
	Desk_functionhandler_block;
*/
typedef struct	{
	Desk_linklist_header	header;
	Desk_error2_type	type;
	Desk_error3_handler	handler;
	void		*reference;
	}
	Desk_typehandler_block;

typedef struct	{
	Desk_linklist_header	header;
	Desk_error3_handler	handler;
	void		*reference;
	}
	Desk_mischandler_block;
	
/*
void	Desk_Error3_ClaimFunction( Desk_error2_fnptr function, Desk_error3_handler handler, void* reference)
{
Desk_functionhandler_block	*block = Desk_DeskMem_MallocType( Desk_functionhandler_block);
block->function	= function;
block->handler	= handler;
block->reference= reference;
Desk_LinkList_AddToHead( &functionhandlers, &block->header);
}
*/

void	Desk_Error3_ClaimType( Desk_error2_type type, Desk_error3_handler handler, void* reference)
{
Desk_typehandler_block	*block = Desk_DeskMem_MallocType( Desk_typehandler_block);
block->type	= type;
block->handler	= handler;
block->reference= reference;
Desk_LinkList_AddToHead( &typehandlers, &block->header);
}

void	Desk_Error3_ClaimMisc( Desk_error3_handler handler, void* reference)
{
Desk_mischandler_block	*block = Desk_DeskMem_MallocType( Desk_mischandler_block);
block->handler	= handler;
block->reference= reference;
Desk_LinkList_AddToHead( &mischandlers, &block->header);
}

/*
void	Desk_Error3_ReleaseFunction( Desk_error2_fnptr function, Desk_error3_handler handler, void* reference)
{
Desk_functionhandler_block*	block;

for	(
	block = Desk_LinkList_FirstItem( &functionhandlers);
	block;
	block = Desk_LinkList_NextItem( &block->header)
	)
	{
	if ( block->function==function && block->handler==handler && block->reference==reference)
		{
		Desk_LinkList_Unlink( &functionhandlers, &block->header);
		Desk_DeskMem_Free( block);
		return;
		}
	}

Desk_Error_ReportFatal( 1, "Desk_Error3_ReleaseFunction couldn't find handler");
}
*/

	
void	Desk_Error3_ReleaseType( Desk_error2_type type, Desk_error3_handler handler, void* reference)
{
Desk_typehandler_block*	block;

for	(
	block = Desk_LinkList_FirstItem( &typehandlers);
	block;
	block = Desk_LinkList_NextItem( &block->header)
	)
	{
	if ( block->type==type && block->handler==handler && block->reference==reference)
		{
		Desk_LinkList_Unlink( &typehandlers, &block->header);
		Desk_DeskMem_Free( block);
		return;
		}
	}

Desk_Debug_Printf( "Desk_Error3_ReleaseFunction couldn't find handler");
}



void	Desk_Error3_ReleaseMisc( Desk_error3_handler handler, void* reference)
{
Desk_mischandler_block*	block;

for	(
	block = Desk_LinkList_FirstItem( &mischandlers);
	block;
	block = Desk_LinkList_NextItem( &block->header)
	)
	{
	if ( block->handler==handler && block->reference==reference)
		{
		Desk_LinkList_Unlink( &mischandlers, &block->header);
		Desk_DeskMem_Free( block);
		return;
		}
	}

Desk_Debug_Printf( "Desk_Error3_ReleaseFunction couldn't find handler");
}




	


Desk_error2_block*	Desk_Error3__Dispatch( Desk_error2_block* error, void* reference)
{
/*Desk_functionhandler_block*	functionblock;*/
Desk_typehandler_block*	typeblock;
Desk_mischandler_block*	miscblock;

Desk_UNUSED( reference);

if ( error->type==Desk_error2_type_NONE)	return Desk_error2_HANDLED;
/*
for	(
	functionblock = Desk_LinkList_FirstItem( &functionhandlers);
	functionblock;
	functionblock = Desk_LinkList_NextItem( &functionblock->header)
	)
	{
	if ( error->function==functionblock->function)	{
		if	( 
			functionblock->handler( 
				error, 
				functionblock->reference
				) 
			== Desk_error2_HANDLED
			)
			return Desk_error2_HANDLED;
		}
	}
*/
for	(
	typeblock = Desk_LinkList_FirstItem( &typehandlers);
	typeblock;
	typeblock = Desk_LinkList_NextItem( &typeblock->header)
	)
	{
	if ( error->type==typeblock->type)	{
		if	( 
			typeblock->handler( 
				error, 
				typeblock->reference
				) 
			== Desk_error2_HANDLED
			)
			return Desk_error2_HANDLED;
		}
	}

for	(
	miscblock = Desk_LinkList_FirstItem( &mischandlers);
	miscblock;
	miscblock = Desk_LinkList_NextItem( &miscblock->header)
	)
	{
	if	( 
		miscblock->handler( 
			error, 
			miscblock->reference
			) 
		== Desk_error2_HANDLED
		)
		return Desk_error2_HANDLED;
	}

return error;
}







