/************************************************************************

	form*Z by auto*des*sys, Inc.
	Copyright (c) 1989-2004 auto*des*sys, Inc.  All rights reserved.

	File:			x_rndr_plugin.c
	Author:			auto*des*sys, Inc.
	Created on:		02/03/04
	Description:	X-Renderer plugin engine file.  Registers this plugin
	                with formZ, and acquires necessary fsets from formZ
	                to use throughout code, among other managerial tasks.

*************************************************************************/

/* this plugin's header */

#include "x_rndr.h"

/* formZ plugin header (required in file defining plugin entry point) */

#include "fz_plugin_glue_api.h"


/* function set provided by formZ. */
const fzpl_fset_glue_fset* _fset_glue;

/* formZ provided function sets to hold on to */
fz_ffmt_fset			_ffmt_funcs;
fz_fzrt_file_fset		_file_funcs;
fz_fuim_fset			_fuim_funcs;
fz_fzrt_base_fset		_base_funcs;
fz_fzrt_graf_fset		_grph_funcs;
fz_lite_fset			_lite_funcs;
fz_math_fset			_math_funcs;
fz_fzrt_mem_fset		_mem_funcs;
fz_objt_attr_fset		_model_attr_funcs;
fz_model_fset			_model_funcs;
fz_proj_fset			_proj_funcs;
fz_rmtl_fset			_rmtl_funcs;
fz_rndr_mngr_fset		_rndr_funcs;
fz_type_fset			_type_funcs;
fz_view_fset			_view_funcs;
fz_iost_fset			_iost_funcs;
fz_expt_vect_fset		_expt_funcs;
fz_tmap_fset			_tmap_funcs;
fz_symb_model_fset		_sym_funcs;
fz_layr_fset			_layr_funcs;
fz_wind_fset			_wind_funcs;

/* ids assigned at run-time */
fzrt_unsigned_int		_x_rndr_plugin_runtime_id;
	
/* localization */
fzrt_fzr_ref_td		_rsrc_ref;
char				_progress_bar_text[STRING_SIZE];


/* generic plugin functions */
static fzrt_error_td	x_rndr_acquire_fsets();
static void				x_rndr_release_fsets();
static fzrt_error_td	x_rndr_check_config(const fzpl_fset_glue_fset* const fset_glue, const fzpl_host_config_td* const hostConfig);
static fzrt_error_td	x_rndr_register_plugins(const fzpl_fset_glue_fset* const fset_glue, const fzpl_host_config_td* const hostConfig);
static fzrt_error_td	x_rndr_finit(const fzpl_fset_glue_fset* const fset_glue);

/* required plugin entry point function */
FZPL_PLUGIN_FUNC(fzrt_error_td)	fz_plugin_entry(const fzpl_fset_glue_fset* const fset_glue, fzpl_command_td cmd, const fzpl_host_config_td* const hostConfig);




/************************************************************************
						Plugin Error String Callback
*************************************************************************/

/************************************************************************
	x_rndr_error_str
		Given an error id, returns to formZ the error message string
		associated with this error, retrieved from the resource file.
		Also, displays the error message on the screen.
*************************************************************************/
static fzrt_boolean x_rndr_error_str(fzrt_int err, char *str, short str_len)
/************************************************************************/
{
	char msg[STRING_SIZE];

	_base_funcs.fzrt_fzr_get_string(_rsrc_ref, X_ERROR_STRINGS, err, msg);
	strncpy(str, msg, str_len);

	return TRUE;
}

/************************************************************************
							Plugin Functions
*************************************************************************/

/************************************************************************
	x_rndr_check_config
		A first pass check to see if the plugin can be loaded.  It does
		the following:
			Acquires formZ function sets.
			Checks licensing.
			Informs formZ if this plugin is dependent on
				function sets from other plugins.
			Opens localization resource file and loads strings.
*************************************************************************/
static fzrt_error_td x_rndr_check_config(const fzpl_fset_glue_fset* const fset_glue, const fzpl_host_config_td* const hostConfig)
/************************************************************************/
{
	fzrt_error_td err = FZRT_NOERR;
	/* resource file variables */
	fzrt_floc_ptr floc;

	/* assign the plugin fset pointer that formZ provides to our copy */
	_fset_glue = fset_glue;

	/* Make sure required application defined function sets are available */
	/* Release the function sets at unload. */

	err = x_rndr_acquire_fsets();
	
	/* IF NEEDED: Check licensing */
	
	/* IF NEEDED: Tell the plugin manager what plugins these plugins are dependent on  */

	/* Make sure the plugin's resource file is available and load it  */
	if (err == FZRT_NOERR)
	{
		/* initialize file locator structure */
		err = _file_funcs.fzrt_file_floc_init(&floc);
		if (err == FZRT_NOERR)
		{
			/* get location of this plugin */
			err = fset_glue->fzpl_plugin_file_get_floc(floc);
			
			if(err == FZRT_NOERR)
			{
				/* open resource file eg. x_rndr.ENU.fzr */
				err = _base_funcs.fzrt_fzr_open(floc, "x_rndr", &_rsrc_ref);
			}
			
			/* throw away floc */
			_file_funcs.fzrt_file_floc_finit(&floc);
		}
	}
	
	if (err != FZRT_NOERR)
	{
		x_rndr_release_fsets();
	}

	return err;
}

/************************************************************************
	x_rndr_acquire_fsets
		Acquires formZ function sets.
*************************************************************************/
static fzrt_error_td x_rndr_acquire_fsets(void)
/************************************************************************/
{
	fzrt_error_td err = FZRT_NOERR;

	err = _fset_glue->fzpl_fset_acquire( FZ_FFMT_FSET_TYPE,
								   FZ_FFMT_FSET_VERSION,
								   FZRT_UUID_NULL,
								   FZPL_TYPE_STRING(fz_ffmt_fset),
								   sizeof(_ffmt_funcs),
								   (fzpl_fset_td*)&_ffmt_funcs );

	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_FZRT_FILE_FSET_TYPE,
									   FZ_FZRT_FILE_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_fzrt_file_fset),
									   sizeof(_file_funcs),
									   (fzpl_fset_td*)&_file_funcs );
	}

	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_FUIM_FSET_TYPE,
									   FZ_FUIM_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_fuim_fset),
									   sizeof(_fuim_funcs),
									   (fzpl_fset_td*)&_fuim_funcs );
	}

	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_FZRT_BASE_FSET_TYPE,
									   FZ_FZRT_BASE_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_fzrt_base_fset),
									   sizeof(_base_funcs),
									   (fzpl_fset_td*)&_base_funcs );
	}
	
	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_FZRT_GRAF_FSET_TYPE,
									   FZ_FZRT_GRAF_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_fzrt_graf_fset),
									   sizeof(_grph_funcs),
									   (fzpl_fset_td*)&_grph_funcs );
	}
	
	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_LITE_FSET_TYPE,
									   FZ_LITE_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_lite_fset),
									   sizeof(_lite_funcs),
									   (fzpl_fset_td*)&_lite_funcs );
	}

	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_FZRT_MEM_FSET_TYPE,
									   FZ_FZRT_MEM_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_fzrt_mem_fset),
									   sizeof(_mem_funcs),
									   (fzpl_fset_td*)&_mem_funcs );
	}
	
	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_MATH_FSET_TYPE,
									   FZ_MATH_FSET_VERSION,
									   FZRT_UUID_NULL,
						 			   FZPL_TYPE_STRING(fz_math_fset),
						 			   sizeof(_math_funcs),
						 			   (fzpl_fset_td*)&_math_funcs );
	}
	
	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_OBJT_ATTR_FSET_TYPE,
									   FZ_OBJT_ATTR_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_objt_attr_fset),
									   sizeof(_model_attr_funcs),
									   (fzpl_fset_td*)&_model_attr_funcs );
	}

	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_MODEL_FSET_TYPE,
									   FZ_MODEL_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_model_fset),
									   sizeof(_model_funcs),
									   (fzpl_fset_td*)&_model_funcs );
	}
	
	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_PROJ_FSET_TYPE,
									   FZ_PROJ_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_proj_fset),
									   sizeof(_proj_funcs),
									   (fzpl_fset_td*)&_proj_funcs );
	}

	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_RMTL_FSET_TYPE,
									   FZ_RMTL_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_rmtl_fset),
									   sizeof(_rmtl_funcs),
									   (fzpl_fset_td*)&_rmtl_funcs );
	}
	
	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_RNDR_MNGR_FSET_TYPE,
									   FZ_RNDR_MNGR_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_rndr_mngr_fset),
									   sizeof(_rndr_funcs),
									   (fzpl_fset_td*)&_rndr_funcs );
	}

	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_TYPE_FSET_TYPE,
									   FZ_TYPE_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_type_fset),
									   sizeof(_type_funcs),
									   (fzpl_fset_td*)&_type_funcs );
	}

	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_VIEW_FSET_TYPE,
									   FZ_VIEW_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_view_fset),
									   sizeof(_view_funcs),
									   (fzpl_fset_td*)&_view_funcs );
	}

	if (err == FZRT_NOERR)	
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_IOST_FSET_TYPE,
									   FZ_IOST_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_iost_fset),
									   sizeof(_iost_funcs),
									   (fzpl_fset_td*)&_iost_funcs );
	}

	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_EXPT_VECT_FSET_TYPE,
									   FZ_EXPT_VECT_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_expt_vect_fset),
									   sizeof(_expt_funcs),
									   (fzpl_fset_td*)&_expt_funcs );
	}

	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_TMAP_FSET_TYPE,
									   FZ_TMAP_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_tmap_fset),
									   sizeof(_tmap_funcs),
									   (fzpl_fset_td*)&_tmap_funcs );
	}

	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_SYMB_MODEL_FSET_TYPE,
									   FZ_SYMB_MODEL_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_symb_model_fset),
									   sizeof(_sym_funcs),
									   (fzpl_fset_td*)&_sym_funcs );
	}

	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_LAYR_FSET_TYPE,
									   FZ_LAYR_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_layr_fset),
									   sizeof(_layr_funcs),
									   (fzpl_fset_td*)&_layr_funcs );
	}

	if (err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_WIND_FSET_TYPE,
									   FZ_WIND_FSET_VERSION,
									   FZRT_UUID_NULL,
									   FZPL_TYPE_STRING(fz_wind_fset),
									   sizeof(_wind_funcs),
									   (fzpl_fset_td*)&_wind_funcs );
	}

	return err;
}

/************************************************************************
	x_rndr_release_fsets
		Releases all function sets used from formZ.
*************************************************************************/
static void x_rndr_release_fsets()
/************************************************************************/
{
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_view_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_type_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_rndr_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_rmtl_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_proj_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_model_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_model_attr_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_mem_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_math_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_iost_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_lite_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_grph_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_base_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_fuim_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_file_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_ffmt_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_expt_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_tmap_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_sym_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_layr_funcs );
	_fset_glue->fzpl_fset_release( (fzpl_fset_td*)&_wind_funcs );
}




/************************************************************************
	x_rndr_register_plugins
		Registers plugins and their associated function sets.
*************************************************************************/
static fzrt_error_td x_rndr_register_plugins(const fzpl_fset_glue_fset* const fset_glue, const fzpl_host_config_td* const hostConfig)
/************************************************************************/
{
	fzrt_error_td	err = FZRT_NOERR;
	char			str[FZPL_NAME_SIZE];


	/* register a renderer plugin */
	_base_funcs.fzrt_fzr_get_string(_rsrc_ref, X_RNDR_STRINGS, X_RNDR_NAME_STR, str);
	err = fset_glue->fzpl_plugin_register( X_RNDR_PLUGIN_UUID,
									 str,
									 X_RNDR_PLUGIN_VERSION,
									 X_RNDR_PLUGIN_VENDOR,
									 X_RNDR_PLUGIN_URL,
									 FZ_RNDR_EXTS_TYPE,
									 FZ_RNDR_EXTS_VERSION,
									 x_rndr_error_str,
									 0,
									 NULL,
									 &_x_rndr_plugin_runtime_id);
	if (err == FZRT_NOERR)
	{
		/* register a renderer fset for the plugin with matching runtime id. */
		err = fset_glue->fzpl_plugin_add_fset( _x_rndr_plugin_runtime_id,
										 FZ_RNDR_CBAK_FSET_TYPE,
										 FZ_RNDR_CBAK_FSET_VERSION,
										 FZ_RNDR_CBAK_FSET_NAME,
										 FZPL_TYPE_STRING(fz_rndr_cbak_fset),
										 sizeof(fz_rndr_cbak_fset),
										 x_vctr_fill_rndr_fset,
										 FALSE);
			
		if (err == FZRT_NOERR)
		{
			/* register a renderer fset for the plugin with matching runtime id. */
			err = fset_glue->fzpl_plugin_add_fset( _x_rndr_plugin_runtime_id,
											 FZ_RNDR_CBAK_FSET_TYPE,
											 FZ_RNDR_CBAK_FSET_VERSION,
											 FZ_RNDR_CBAK_FSET_NAME,
											 FZPL_TYPE_STRING(fz_rndr_cbak_fset),
											 sizeof(fz_rndr_cbak_fset),
											 x_pixel_fill_rndr_fset,
											 FALSE);
		}
		
		if (err == FZRT_NOERR)
		{
			/* register a surface style fset for the plugin with matching runtime id. */
			err = fset_glue->fzpl_plugin_add_fset( _x_rndr_plugin_runtime_id,
											 FZ_SREP_CBAK_FSET_TYPE,
											 FZ_SREP_CBAK_FSET_VERSION,
											 FZ_SREP_CBAK_FSET_NAME,
											 FZPL_TYPE_STRING(fz_srep_cbak_fset),
											 sizeof(fz_srep_cbak_fset),
											 x_pixel_fill_srep_fset,
											 FALSE);
		}

		if (err == FZRT_NOERR)
		{
			/* register a notification fset for the plugin with matching runtime id. */
			err = fset_glue->fzpl_plugin_add_fset( _x_rndr_plugin_runtime_id,
											 FZ_NOTF_CBAK_FSET_TYPE,
											 FZ_NOTF_CBAK_FSET_VERSION,
											 FZ_NOTF_CBAK_FSET_NAME,
											 FZPL_TYPE_STRING(fz_notf_cbak_fset),
											 sizeof(fz_notf_cbak_fset),
											 x_pixel_fill_notf_fset,
											 FALSE);
		}

		if (err == FZRT_NOERR)
		{
			err = _fset_glue->fzpl_plugin_add_fset( _x_rndr_plugin_runtime_id,
				FZ_LIGHT_REP_CBAK_FSET_TYPE,
				FZ_LIGHT_REP_CBAK_FSET_VERSION,
				FZ_LIGHT_REP_CBAK_FSET_NAME,
				FZPL_TYPE_STRING(fz_light_rep_cbak_fset),
				sizeof(fz_light_rep_cbak_fset),
				x_pixel_fill_lrep_fset,
				FALSE);
		}
										 
	}

	if (err != FZRT_NOERR)
	{
		x_rndr_finit(fset_glue);
	}

	return err;
}

/************************************************************************
	x_rndr_finit
		Unregisters plugins.  Closes resource file.  Releases
		function sets.
*************************************************************************/
static fzrt_error_td x_rndr_finit(const fzpl_fset_glue_fset* const fset_glue)
/************************************************************************/
{
	fzrt_error_td err = FZRT_NOERR;

	err = fset_glue->fzpl_plugin_unregister(_x_rndr_plugin_runtime_id);
		
	if (err == FZRT_NOERR)
		err = _base_funcs.fzrt_fzr_close(_rsrc_ref);

	x_rndr_release_fsets();

	return err;
}

/************************************************************************
						Required Plugin Functions
*************************************************************************/

/************************************************************************
	fz_plugin_entry
		The main entry point for a formZ plugin.
*************************************************************************/
FZPL_PLUGIN_FUNC(fzrt_error_td) fz_plugin_entry(const fzpl_fset_glue_fset* const fset_glue, fzpl_command_td cmd, const fzpl_host_config_td* const hostConfig)
/************************************************************************/
{
	fzrt_error_td err = FZRT_NOERR;

	switch (cmd)
	{
		case FZPL_PLUGIN_CHECK:
			err = x_rndr_check_config(fset_glue, hostConfig);
		break;
		
		case FZPL_PLUGIN_INITIALIZE:
			err = x_rndr_register_plugins(fset_glue, hostConfig);
		break;
		
		case FZPL_PLUGIN_EXIT:
			err = x_rndr_finit(fset_glue);
		break;
	}
	
	return (err);
}
