/*
 ******************************************************************************
 *
 *	ParcPlace Systems Inc.
 *	Copyright (c) 1990, ParcPlace Systems.	USA	All rights reserved.
 *
 ****************************************************************************
 *
 *	File:	cvt.H
 *
 *	Functions(s):
 *
 *	Description:
 *		Resource manager and converter
 *
 *	RCSid = "$Id: cvt.H,v 4.18.1.3 1993/08/12 15:37:58 toml Exp $"
 *
 ****************************************************************************
 */

/***********************************************************
Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.

			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 names of Digital or MIT not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.  

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

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

#ifndef OI_cvt_H
#define OI_cvt_H

#include <OI/callback.H>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xresource.h>
#include <stdlib.h>
#include <OI/util.H>

#define OI_CVT_HASH_SIZE	((unsigned)512)
#define OI_CVT_HASH_MASK	(OI_CVT_HASH_SIZE-1)

int	OI_CompareISOLatin1(const char*,const char*) ;

// class forward reference declarations
class	OI_rmgr;
class	OI_connection;
class	OI_quark_array;
class	OI_last_quark;

class	OI_cvt {
		int		cnt ;
		void		*valid_values ;
	const	char	* const	*valid_strings ;
	public:
				OI_cvt();
	virtual			~OI_cvt();
		int		count();
		void		*values();
inline	const	char	* const	*strings()			{ return(valid_strings); }
		void		set_values(void *, int);
		void		set_strings(const char * const *);
	virtual	OI_bool		convert(OI_connection *, XrmValue *, XrmValue *);
	virtual	OI_bool		unconvert(OI_connection *, XrmValue *, XrmValue *);
};
	
#define OI_offset(s,m) ((int)(&s->m)) - ((int)(s))

#ifdef TYPEDEF_MEMFN
typedef	void	(OI_resource_fn)(void *);
typedef	void	(OI_callback::OI_resource_memfn)(void *);
typedef	void*	(OI_resource_get_fn)();
typedef	void*	(OI_callback::OI_resource_get_memfn)();
#endif /* TYPEDEF_MEMFN */
typedef	void	(*OI_resource_fnp)(void *);
typedef	void	(OI_callback::*OI_resource_memfnp)(void *);
typedef	void*	(*OI_resource_get_fnp)();
typedef	void*	(OI_callback::*OI_resource_get_memfnp)();

#ifdef CPLUSPLUS20
#define OI_RESOURCE_MEMFN_CAST(mfn)	/*(OI_resource_memfnp)*/(mfn)
#define OI_RESOURCE_GET_MEMFN_CAST(mfn)	/*(OI_resource_get_memfnp)*/(mfn)
#else
#define OI_RESOURCE_MEMFN_CAST(mfn)	(OI_resource_memfnp)(mfn)
#define OI_RESOURCE_GET_MEMFN_CAST(mfn)	(OI_resource_get_memfnp)(mfn)
#endif

/* definitions of ctl_bits in OI_resource structure */
#define	OI_RM_GET_USE_DEFAULT		0x1		/* if no resource fetched, use default value (*default_addr) */
#define	OI_RM_PUT_USE_DEFAULT		0x2		/* if resource value not set from program and value matches default, don't write it out */
#define OI_RM_MDL_OL2D			0x4		/* resource applies to 2D OpenLook */
#define OI_RM_MDL_OL3D			0x8		/* resource applies to 3D OpenLook */
#define OI_RM_MDL_MOTIF			0x10		/* resource applies to Motif */
#define OI_RM_INHIBIT_WRITE		0x20		/* disable writing out a resource */
#define OI_RM_INHIBIT_TOP_LEVEL		0x40		/* disable writing out a resource if object is top level */
#define OI_RM_INHIBIT_EDIT		0x80		/* disable resource editing in UIB */
#define OI_RM_PUSH			0x100		/* push and use the next set of resources */
#define OI_RM_INTERNAL_INHERIT		0x200		/* if the object is internal, inherit the resource from the closest non-internal object */
#define OI_RM_COMPILED			0x400		/* This structure has been compiled */
#define OI_RM_MANDATORY_QUERY		0x800		/* Always is_write_resq this resource */
#define OI_RM_INHIBIT_INTERNAL_EDIT	0x1000		/* Don't allow editting when this object is an internal object */
#define OI_RM_OBSOLETE			0x2000		/* Resource is obsolete, spit out an error message if we fetched this resource */

#define OI_RM_MDL_ALL			(OI_RM_MDL_OL2D | OI_RM_MDL_OL3D | OI_RM_MDL_MOTIF)
#define OI_RM_MDL_ALL_3D		(OI_RM_MDL_OL3D | OI_RM_MDL_MOTIF)
#define OI_RM_MDL_ALL_2D		(OI_RM_MDL_OL2D)
#define OI_RM_MDL_OL			(OI_RM_MDL_OL2D | OI_RM_MDL_OL3D)

struct OI_resource {
const	char			*resource_name;  	/* Resource name                            */
const	char			*resource_class; 	/* Resource class                           */
const	char			*resource_type;  	/* Representation type desired              */
	unsigned int		resource_size;  	/* Size in bytes of representation          */
	unsigned int		resource_offset;	/* Offset from base to put resource value   */
const	char			*default_type; 	 	/* representation type of specified default */
const	void			*default_addr;  	 	/* Address of default resource              */
	OI_resource_memfnp	put_memfnp;		/* callback member function for resource fetched */
	OI_resource_fnp		put_fnp;		/* callback procedure for resource fetched */
	OI_resource_get_memfnp	get_memfnp;		/* callback member function to retrieve current value */
	OI_resource_get_fnp	get_fnp;		/* callback procedure to retrieve current value */
	unsigned long		ctl_bits;		/* control bits */

 public:
	void			compile();		/* compile to internal form */
	OI_bool			compiled()		{ return (((ctl_bits&OI_RM_COMPILED)?OI_YES:OI_NO)); }
	OI_bool			matches(XrmQuark);	/* OI_YES => this structure's name or class matches the one passed */
	void			set_resource_name(XrmQuark q)		{ compile(); resource_name = (char *)q; }
	void			set_resource_class(XrmQuark q)		{ compile(); resource_class = (char *)q; }
};

struct	OI_xrm_resource {
	XrmQuark		xrm_name;         	/* Resource name quark                */
	XrmQuark		xrm_class;        	/* Resource class quark               */
	XrmQuark		xrm_type;         	/* Resource representation type quark */
	unsigned int		xrm_size;         	/* Size in bytes of representation    */
	long int		xrm_offset;       	/* -offset-1                          */
	XrmQuark		xrm_default_type; 	/* Default representation type quark  */
	void			*xrm_default_addr; 	/* Default resource address           */
	OI_resource_memfnp	put_memfnp;		/* callback member function for resource being set */
	OI_resource_fnp		put_fnp;		/* callback procedure for resource being set */
	OI_resource_get_memfnp	get_memfnp;		/* callback member function for resource being gotten */
	OI_resource_get_fnp	get_fnp;		/* callback procedure for resource being gotten */
	unsigned long		ctl_bits;
};

class	OI_geometry : public OI_callback {
		unsigned long	msk ;			/* mask indicating which fields have been set and what they mean */
		long		x ;			/* x position or column number */
		long		y ;			/* y position or row number */
		OI_number	wid ;			/* width in pixels, characters, ... */
		OI_number	ht ;			/* height in pixels, lines, ... */
		OI_number	grav;			/* window gravity */
		char		*geom_str;		/* original geometry string */
 public:
				OI_geometry()		{ msk=0; x=y=0; wid=ht=0; geom_str=NULL; }
	virtual			~OI_geometry();
		OI_geometry	*clone();
		void		clear()			{ msk=0; }
		char		*geometry_string()	{ return (geom_str); }
		OI_number	gravity()		{ return(grav); }
		OI_number	height()		{ return(ht); }
		unsigned long	is_mask(unsigned long m) { return (msk & m); }
		void		and_mask(unsigned long m) { msk &= m; }
		void		or_mask(unsigned long m) { msk |= m; }
		long		loc_x()			{ return(x); }
		long		loc_y()			{ return(y); }
		unsigned long	mask()			{ return (msk); }
		void		set_column(OI_number c)	{ msk |= OIC_col; msk &= ~OIC_x; x = c; }
		void		set_row(OI_number r)	{ msk |= OIC_row; msk &= ~OIC_y; y = r; }
		void		set_x(long x_psn)	{ msk |= OIC_x; msk &= ~OIC_col; x = x_psn; }
		void		set_y(long y_psn)	{ msk |= OIC_y; msk &= ~OIC_row; y = y_psn; }
		void		set_height(OI_number h)	{ msk |= OIC_height; ht = h; }
		void		set_geometry_string(char *s)	{ if (geom_str) free( geom_str ); geom_str = s ? strdup( s ) : NULL; }
		void		set_gravity(OI_number g) { msk |= OIC_gravity; grav = g; }
		void		set_mask(unsigned long m) { msk = m; }
		void		set_width(OI_number w)	{ msk |= OIC_width; wid = w; }
		OI_number	width()			{ return(wid); }
};

class	OI_cvt_rec {
		OI_cvt_rec	*nxt;			/* the next record */
		XrmQuark	fq;			/* the from type */
		XrmQuark	tq;			/* the to type */
		OI_cvt		*cvtr;			/* the converter object */
public:
				OI_cvt_rec(OI_cvt_rec *, XrmQuark, XrmQuark, OI_cvt *);
				~OI_cvt_rec();
		OI_cvt_rec	*next()			{ return (nxt); }
		XrmQuark	from()			{ return (fq); }
		XrmQuark	to()			{ return (tq); }
		OI_bool		convert(OI_connection *r, XrmValue *f, XrmValue *t)	{ return(cvtr->convert(r, f, t)); }
		OI_bool		unconvert(OI_connection *r, XrmValue *f, XrmValue *t)	{ return(cvtr->unconvert(r, f, t)); }
	const	char	* const *strings()					{ return(cvtr->strings()); }
};

#define SEARCHLISTLEN 100
#define QUARK_INC 30

/* definitions for "flags" bits */
#define OI_RM_IN_GET_RESOURCES		0x01				/* we are currently in get_resources() */
#define OI_RM_DO_SEARCH			0x02				/* do search_resources() */
#define OI_RM_UIB_CONVERT		0x10				/* uib is calling this converter */
#define OI_RM_PRESERVE_RESOURCES	0x20				/* Don't refetch resources */

class	OI_rmgr {
protected:
		OI_connection	*con;					/* our connection to the server */

		OI_cvt_rec	**tab;					/* the converter table */
		XrmQuark	*class_quarks;				/* the class resource stack */
		XrmQuark	*name_quarks;				/* the instance resource stack */
		short		quark_cnt;				/* the number of quarks on the instance and class stacks */
		short		quark_cnt_save;				/* saved stack pointer */
		short		quark_max;				/* max space available on quark stacks */
		short		langq;					/* the language quark number */
		short		mdlq;					/* the model quark number */
		FILE		*debug;					/* debug file pointer */
		XrmHashTable    **search_lst;				/* resource search list */
		unsigned int    *search_lst_size;			/* size of the search list */
		unsigned int	num_search;				/* how many in the search list, should correspond to conp->num_database() */
		OI_quark_array	*specifics;				/* specific resources to fetch */
		OI_quark_array	*disabled;				/* specific resources to not fetch */
		OI_quark_array	*noinherit;				/* resources to not inherit from composit parent */
		unsigned	flags;					/* flag bits */
		OI_last_quark	*last_quarks;
		OI_xrm_resource	*cur_xrm;				/* Current xrm which is being fetched or written. */
public:
				OI_rmgr(OI_connection *);
				~OI_rmgr();
		OI_connection	*connection()				{ return (con); }
		void		allow_search_resources()		{ flags |= OI_RM_DO_SEARCH; }
		void		disallow_search_resources()		{ flags &= ~OI_RM_DO_SEARCH; }
		OI_bool		is_search_resources()			{ return (((OI_bool)(flags&OI_RM_DO_SEARCH)?OI_YES:OI_NO)); }

		void		allow_uib_convert()			{ flags |= OI_RM_UIB_CONVERT; }
		void		disallow_uib_convert()			{ flags &= ~OI_RM_UIB_CONVERT; }
		OI_bool		is_uib_convert()			{ return (((OI_bool)(flags&OI_RM_UIB_CONVERT)?OI_YES:OI_NO)); }

		void		allow_in_get_resources()		{ flags |= OI_RM_IN_GET_RESOURCES; }
		void		disallow_in_get_resources()		{ flags &= ~OI_RM_IN_GET_RESOURCES; }
		OI_bool		is_in_get_resources()			{ return (((OI_bool)(flags&OI_RM_IN_GET_RESOURCES)?OI_YES:OI_NO)); }

		void		allow_preserve_resources()		{ flags |= OI_RM_PRESERVE_RESOURCES; }
		void		disallow_preserve_resources()		{ flags &= ~OI_RM_PRESERVE_RESOURCES; }
		OI_bool		is_preserve_resources()			{ return (((OI_bool)(flags&OI_RM_PRESERVE_RESOURCES)?OI_YES:OI_NO)); }

		OI_cvt_rec	*table(unsigned i)			{ return (tab[i]); }
		unsigned 	hash_value(XrmQuark f, XrmQuark t)	{ return ((2*(f)+t)&OI_CVT_HASH_MASK); }
		OI_cvt_rec	*hash(XrmQuark f, XrmQuark t)		{ return (tab[hash_value(f,t)]); }
		void		addq(XrmQuark, XrmQuark, OI_cvt *);
		void		add(char *f, char *t, OI_cvt *v) ;
		void		set_languageq(XrmQuark n, XrmQuark c)	{ name_quarks[langq]=n; class_quarks[langq]=c; }
		void		set_language(char *n, char *c) ;
		void		mark_language_quark()			{ langq = quark_cnt; }
		short		model_position()			{ return (mdlq); }
		void		set_modelq(XrmQuark n, XrmQuark c)	{ name_quarks[mdlq]=n; class_quarks[mdlq]=c; }
		void		set_model(char *n, char *c) ;
		void		mark_model_quark()			{ mdlq = quark_cnt; }
		XrmQuark	language_nameq()			{ return (name_quarks[langq]); }
		XrmQuark	language_classq()			{ return (class_quarks[langq]); }
		char		*language_name()			{ return (XrmQuarkToString(language_nameq())); }
		char		*language_class()			{ return (XrmQuarkToString(language_classq())); }
		void		search_resources();
		char		*get_search_resourceq(XrmQuark, XrmQuark);
		char		*get_search_resource(char *n, char *c) ;
		void		get_resources(OI_resource*, unsigned, void *, XrmQuark * = NULL, OI_d_tech * = NULL);
		char		*get_resourceq(XrmQuark, XrmQuark);
		char		*get_resource(const char *n, const char *c) ;
		OI_bool		get_resource_cvtq(XrmQuark, XrmQuark, XrmQuark, void *);
		OI_bool		get_resource_cvt(const char *n, const char *c, const char *t, void *tv) ;
		OI_bool		get_search_resource_cvtq(XrmQuark, XrmQuark, XrmQuark, void *);
		void		write_resources(FILE *cfg_fp, XrmDatabase, OI_d_tech *, OI_resource *list, unsigned count, void *base);
		void		set_stack_ptr(short s)			{ quark_cnt=s; }
		short		stack_ptr()				{ return (quark_cnt); }
		void		save_stack_ptr()			{ quark_cnt_save = quark_cnt; }
		void		restore_stack_ptr()			{ quark_cnt = quark_cnt_save; }
		void		pushq(XrmQuark, XrmQuark);
		void		push(const char *n, const char *c) ;
		void		pop()					{ quark_cnt--; name_quarks[quark_cnt]=0;
										class_quarks[quark_cnt]=0; allow_search_resources();}
		void		insert(short, char *, char *);
		void		insertq(short, XrmQuark, XrmQuark);
		void		remove(short);
		OI_cvt_rec	*is_converter(char *, char *);
		OI_cvt_rec	*is_converterq(XrmQuark, XrmQuark);
		OI_bool		convertq(XrmQuark, void *, XrmQuark, void *);
		OI_bool		convertq(XrmQuark, XrmValue *, XrmQuark, XrmValue *);
		OI_bool		convert(const char *ft, void *fv, const char *tt, void *tv) ;
		OI_bool		convert(const char *ft, XrmValue *fv, const char *tt, XrmValue *tv) ;
		void		set_debug_filep(FILE *f)		{ debug = f; }
		void		set_debug_file(char *);
		void		debug_output(char *, char *, char *);
		FILE		*debug_file()				{ return (debug); }
//		XrmHashTable	*search_list()				{ return (search_lst); }
//		unsigned int	search_list_size()			{ return (search_lst_size); }
		OI_quark_array	*no_inherit_resources()			{ return (noinherit); }
		OI_quark_array	*specific_resources()			{ return (specifics); }
		OI_quark_array	*disabled_resources()			{ return (disabled); }
		void		extract_value(OI_d_tech*, void*, OI_xrm_resource*, XrmValue*);
		char		*resource_value(OI_d_tech*, XrmQuark);
		void		set_resource_value(OI_d_tech *, XrmQuark, const char*, OI_bool);
		void		set_resource_value(OI_d_tech *, void *, OI_xrm_resource*, XrmQuark, XrmValue*, OI_bool, OI_bool);
		void		save_search();
		void		restore_search();
		OI_xrm_resource	*current_resource()			{return(cur_xrm);}
};
		
extern		void		OI_init_rmgr();

#endif /* OI_cvt_H */
