/*---------------------------------------------------------------------
 * $Date: 2009-08-18 15:23:20 $             $Revision: 1.3 $
 *---------------------------------------------------------------------
 * 
 *
 *             Copyright (c) 1989, Visual Edge Software Ltd.
 *
 * ALL  RIGHTS  RESERVED.  Permission  to  use,  copy,  modify,  and
 * distribute  this  software  and its documentation for any purpose
 * and  without  fee  is  hereby  granted,  provided  that the above
 * copyright  notice  appear  in  all  copies  and  that  both  that
 * copyright  notice and this permission notice appear in supporting
 * documentation,  and that  the name of Visual Edge Software not be
 * used  in advertising  or publicity  pertaining to distribution of
 * the software without specific, written prior permission. The year
 * included in the notice is the year of the creation of the work.
 *-------------------------------------------------------------------*/
/*

.VERSION
 090813		last modif KB

*/

		
/*---------------------------------------------------------------------
   Routines to add utypes, xtypes and type converters
   Publically available from types.h are the macros:

	char *u_name()		-- Gives the name of a uimx type
	int u_size()		-- Gives the size of a uimx type
	int u_interp_type()	-- Gives the corresponding interpreter type
				   for a uimx type
	char *x_name()		-- Gives the name of an X type
	int x_size()		-- Gives the size of an X type

  CREATION:       May 11 1988  
----------------------------------------------------------------------*/

#include <stdio.h>
#include <string.h>
 
#include "types.h"
#include "valloc.h"

#define duplicate(s) (char *)strcpy(UxMalloc(strlen(s)+1), s)

/** Global counts **/

int UxXT_num_types = 0;
int UxUT_num_types = 0;
int UxXT_num_alloc = 0;
int UxUT_num_alloc = 0;

extern void UxInternalError();



/** Global tables **/

UIMX_conv 	**UxUimx_x = 0;
UIMXType 	**UxUIMX_types = 0;
XType 		**UxX_types = 0;
conversion 	*UxStr_conv = 0;

/* ---------------------------------------------------------------------------
NAME:		UxAdd_utype(name, size, interp_type)
INPUT:		char *name;		-- name of the new type
		int size;		-- size of the new type
		int interp_type;	-- how does the interpreter represent
					   this type?
RETURNS:	The index of the new type (i.e. the first index into UxUimx_x).
DESCRIPTION:	Add a new UIMX type to the type conversion mechanism.

eg:	UxAdd_utype("string", sizeof(char*), T_PNTR);

CREATION:       May 11 1988  
---------------------------------------------------------------------------*/
int	UxAdd_utype(name, size, interp_type)
char *name;
int size;
int interp_type;
{
	int i, j;

	if (UxUT_num_types % BLOCK_SIZE == 0) {
		UxUT_num_alloc = UxUT_num_types + BLOCK_SIZE;
		UxUIMX_types = (UIMXType**)UxRealloc(UxUIMX_types,
		    (UxUT_num_alloc) * sizeof(UIMXType*));
		UxUimx_x = (UIMX_conv**)UxRealloc(UxUimx_x,
		    (UxUT_num_alloc) * sizeof(UIMX_conv*));
		for (i = UxUT_num_types; i < UxUT_num_alloc; i++) {
			UxUimx_x[i] = (UIMX_conv*)UxMalloc(
			    UxXT_num_alloc*sizeof(UIMX_conv));
			for (j = 0; j < UxXT_num_alloc; j++)
				UxUimx_x[i][j] = 0;
		}
	}
		
	UxUIMX_types[UxUT_num_types] = 
	    (UIMXType*)UxMalloc(sizeof(UIMXType));
	u_name(UxUT_num_types) = duplicate(name);
	u_size(UxUT_num_types) = size;
	u_interp_type(UxUT_num_types) = interp_type;
	u_domain_type(UxUT_num_types) = NO_TYPE;
	return UxUT_num_types++;
}

/* ---------------------------------------------------------------------------
NAME:		UxAddXtype(name, size)
INPUT:		char *name;		-- name of the new type
		int size;		-- size of the new type
RETURNS:	The index of the new type (i.e. the second index into UxUimx_x).
DESCRIPTION:	Add a new X type to the type conversion mechanism.

eg:		UxAddXtype("Justify", sizeof(XtJustify));

CREATION:       May 11 1988  
REVISIONS:	Jan 14/91	bug2008
		-- now initializes UxStr_conv[].size to zero
---------------------------------------------------------------------------*/
int	UxAddXtype(name, size)
char *name;
int size;
{
	int i, j;

	if (UxXT_num_types % BLOCK_SIZE == 0) 
	{
		UxXT_num_alloc = UxXT_num_types + BLOCK_SIZE;

		UxX_types = (XType**)UxRealloc(UxX_types,
					    (UxXT_num_alloc) * sizeof(XType*));

		UxStr_conv = (conversion *)UxRealloc(UxStr_conv,
				    (UxXT_num_alloc) * sizeof(conversion));

		for (j = UxXT_num_types; j < UxXT_num_alloc; j++)
			UxStr_conv[j].size = 0;

		for (i = 0; i < UxUT_num_alloc; i++) 
		{
			UxUimx_x[i] = (UIMX_conv*)UxRealloc(UxUimx_x[i],
				    (UxXT_num_alloc) * sizeof(UIMX_conv));

			for (j = UxXT_num_types; j < UxXT_num_alloc; j++)
				UxUimx_x[i][j] = NULL;
		}
	}
		
	UxX_types[UxXT_num_types] = (XType*)UxMalloc(sizeof(XType));
	x_name(UxXT_num_types) = duplicate(name);
	x_size(UxXT_num_types) = size;
	x_domain_type(UxXT_num_types) = NO_TYPE;
	return UxXT_num_types++;
}

/* ---------------------------------------------------------------------------
NAME:		void UxAddConv(utypei, xtypei, conv)
INPUT:		int utypei, xtypei;	-- type indexes (see above)
		UIMX_conv conv;		-- the converter
RETURNS:	
DESCRIPTION:	Add a new type converter to the type conversion mechanism.

eg:		UxAddConv(UxUT_string,UxXT_Int,string_to_Int);
		UxAddConv(UxUT_string,UxXT_String,u_identity);

		Gives error message if overwriting previous convertor

CREATION:       May 11 1988  
---------------------------------------------------------------------------*/

void UxAddConv(utypei, xtypei, conv)
int utypei, xtypei;
UIMX_conv conv;
{
	/* First we do a sanity check on the indices */
	if (0 > utypei || utypei > UxUT_num_types ||
	    0 > xtypei || xtypei > UxXT_num_types)
		UxInternalError( __FILE__, __LINE__, "UxAddConv: Bad index\n");

	/* If a convertor function is already installed in the indicated slot,
	   this probably means that one of the indices is wrong */
	if ( UxUimx_x[utypei][xtypei] != NULL )
	{
		UxInternalError( __FILE__, __LINE__,
				"UxAddConv: already installed(ut=%d, xt=%d)\n",
				 utypei, xtypei );
	}

	UxUimx_x[utypei][xtypei] = conv;
}

/* ---------------------------------------------------------------------------
NAME:		void UxAdd_values(x_or_uimx, type, num_values, values)
INPUT:		int x_or_uimx;	-- is this a UIMX_TYPE or an X_TYPE
		int type;	-- which type?
		int num_values;	-- how many possible values are there
		char **values;	-- a list of these values (in string format)
RETURNS:	
DESCRIPTION:	specify the allowable values for instances of this type
		
eg:	static char *justify_values[] = {"left", "center", "right"};
	UxAdd_values(X_TYPE, XT_Justify, 3, justify_values);

CREATION:       May 13 1988  
---------------------------------------------------------------------------*/
void UxAdd_values(x_or_uimx, type, num_values, values)
int x_or_uimx;
int type;
int num_values;
char **values;
{
	int i;

	if (x_or_uimx == UIMX_TYPE) {
		u_domain_type(type) = VALUES;
		u_num_values(type) = num_values;
		u_values(type) = (char **)UxMalloc(num_values * sizeof(char*));
		for (i = 0; i < num_values; i++)
			u_values(type)[i] = duplicate(values[i]);
	}
	else {
		x_domain_type(type) = VALUES;
		x_num_values(type) = num_values;
		x_values(type) = (char **)UxMalloc(num_values * sizeof(char*));
		for (i = 0; i < num_values; i++)
			x_values(type)[i] = duplicate(values[i]);
	}
}


/***************************************************************************
NAME:		UxAddXValues(type, uvals, xvals, size)
INPUT:		int		type	: the UxXT_ type
		char		**uvals	: array of possible uimx values
		unsigned char	*xvals	: array of corresponding Xt values
		int		size	: number of elements in arrays
OUTPUT:		---
RETURN:		void
DESCRIPTION:	Registers the two given arrays of values in UxStr_conv[].
		Gives error message if overwriting previous values.

EXT REFERENCES: UxStr_conv[]
EXT EFFECTS:	UxStr_conv[]

REVISIONS:	Jan 14/91	bug2008
---------------------------------------------------------------------------*/

void UxAddXValues(type, uvals, xvals, size)
	int 		type;
	char 		**uvals;
	unsigned char 	*xvals;
	int 		size;
{
	if ( UxStr_conv[type].size != 0 )
	{
		/* A set of values has already been installed
		   - this probably means a bad 'type' index is being used */
		UxInternalError( __FILE__, __LINE__,
				"UxAddXValues: Bad index (%d)\n", type );
	}

	UxStr_conv[type].strings = uvals;
	UxStr_conv[type].values = xvals;
	UxStr_conv[type].size = size;
}

