/*
 ******************************************************************************
 *
 *	ParcPlace Systems, Inc.
 *	Copyright (c) 1990, ParcPlace Systems, Inc. USA   All rights reserved.
 *
 ****************************************************************************
 *
 *	File:	array.H
 *
 *	Functions(s):
 *
 *	Description:
 *		OI_array class header
 *
 *	RCSid = "$Id: array.H,v 4.7.1.2 1993/08/04 03:44:25 toml Exp $"
 *
 ****************************************************************************
 */

#ifndef OI_array_H
#define OI_array_H

#ifndef OI_defs_H
#include <OI/defs.H>
#endif /* OI_defs_H */

#define OI_ARRAY_INCREMENT 4

/**********************************************************************
 * These defines allow backward compatibility with the 3.x library
 **********************************************************************/
#define OIU_array			OI_array
#define OIU_char_array			OI_char_array
#define OIU_long_array			OI_long_array
#define OIU_quark_array			OI_quark_array
#define OIU_pointer_array		OI_pointer_array
#define OIU_quark_pointer		OI_quark_pointer
#define OIU_quark_pointer_array		OI_quark_pointer_array

	class	OI_array	{
		protected:
			unsigned short	elsiz;		/* element size */
			unsigned short	cnt;		/* how many elements we have in the array */
			unsigned short	siz;		/* size of the array */
			unsigned short	incr;		/* amount to increment by. */
			void		*array;
		public:
					OI_array(const unsigned int, const unsigned short = OI_ARRAY_INCREMENT);
		virtual			~OI_array();
			void		check_for_overflow(const unsigned int = 1);
			void		clone_adjust(OI_array *);
			unsigned int	num_elements()				{ return(cnt); }
			unsigned short	increment()				{ return(incr); }
			void		set_increment(const unsigned short i)	{incr = i;}
		virtual	void		set_num_elements(unsigned int);
		virtual	void		void_element(const unsigned int);
	};


	class OI_char_array : public OI_array {
		public:
					OI_char_array()	: OI_array(sizeof(char)) {}
					OI_char_array(const unsigned short i) : OI_array(sizeof(char), i) {}
					~OI_char_array();
			unsigned int	append(const char);
			unsigned int	append(const char *, const int = -1);
			OI_char_array	*clone();
			long		element(const unsigned int i)		{ return ((char)((char *)array)[i]); }
			char		*head()					{ return ((char *)array); }
			int		look_for(const char);
		virtual	void		set_num_elements(unsigned int);
	};


	class OI_long_array : public OI_array {
		public:
					OI_long_array()	: OI_array(sizeof(long)) {}
					OI_long_array(const unsigned short i) : OI_array(sizeof(long), i) {}
					~OI_long_array();
			unsigned int	append(const long);
			OI_long_array	*clone();
			long		element(const unsigned int i)		{ return ((long)((long *)array)[i]); }
			long		*head()					{ return ((long *)array); }
			int		look_for(const long);
	};


	class OI_quark_array : public OI_long_array {
		protected:
		public:
					OI_quark_array() : OI_long_array() {}
					OI_quark_array(const unsigned short i) : OI_long_array(i) {}
					~OI_quark_array();
			unsigned int	append(const XrmQuark);
			OI_quark_array	*clone()				{ return ((OI_quark_array *)OI_long_array::clone()); }
			XrmQuark	element(const unsigned int i)		{ return ((XrmQuark)OI_long_array::element(i)); }
			XrmQuark	*head()					{ return ((XrmQuark *)OI_long_array::head()); }
			int		look_for(const XrmQuark);
			void		remove(const XrmQuark);
	};

	class OI_atom_array : public OI_quark_array {
		protected:
		public:
					OI_atom_array() : OI_quark_array() {}
					OI_atom_array(const unsigned short i) : OI_quark_array(i) {}
					~OI_atom_array();
			unsigned int	append(const Atom a)			{ return (OI_quark_array::append((XrmQuark)a)); }
			OI_atom_array	*clone()				{ return ((OI_atom_array *)OI_quark_array::clone()); }
			Atom		element(const unsigned int i)		{ return ((Atom)OI_quark_array::element(i)); }
			Atom		*head()					{ return ((Atom *)OI_quark_array::head()); }
			int		look_for(const Atom a)			{ return ((Atom)OI_quark_array::look_for((XrmQuark)a)); }
			void		remove(const Atom a)			{ OI_quark_array::remove((XrmQuark)a); }
	};

	class OI_lw_quark_array : public OI_callback  {
		protected:
			XrmQuark	*array;
		public:
					OI_lw_quark_array()			{ array = NULL; }
			virtual		~OI_lw_quark_array();
			unsigned int	append(const XrmQuark);
			OI_lw_quark_array *clone();
			XrmQuark	element(const unsigned int i)		{ return (array[i]); }
			XrmQuark	*head()					{ return (array); }
			int		look_for(const XrmQuark);
			unsigned int	num_elements();
			void		remove(const XrmQuark);
	};

	class OI_pointer_array : public OI_array {
		public:
					OI_pointer_array() : OI_array(sizeof(void *)) {}
					OI_pointer_array(const unsigned short i) : OI_array(sizeof(void *), i) {}
					~OI_pointer_array();
			unsigned int	append(const void *);
			OI_pointer_array *clone();
			void		*element(const unsigned int i)		{ return ((void *)((void **)array)[i]); }
			void		**head()				{ return ((void **)array); }
			int		look_for(const void *);
			void		remove(const void *);
 			void		exchange(unsigned int, unsigned int);
	};

#define	OI_QP_CAN_FREE		0x80000000
#define	OI_QP_CAN_DELETE	0x40000000
#define OI_QP_MASK		(OI_QP_CAN_FREE | OI_QP_CAN_DELETE)


//
//	Warning:
//
//		If you do allow_delete, then the pointer ***MUST*** be derived from OI_callback.
//	If it isn't, then the deletion routine will break.  We put this requirement in because
// 	the dtors weren't getting called when something was deleted.  C++ was calling the void *
//	dtor, which is just free().
//
	class OI_quark_pointer {
			unsigned long	qrk;
			void		*ptr;
		public:
					OI_quark_pointer(XrmQuark q, void *p)	{ qrk = (unsigned long)q; ptr = p; }
					~OI_quark_pointer();
			XrmQuark	quark()					{ return (((XrmQuark)(qrk & ~OI_QP_MASK))); }
			void		*pointer()				{ return (ptr); }
			void		set_pointer(void *p)			{ ptr = p; }
			void		allow_delete()				{ qrk |= OI_QP_CAN_DELETE; }	//  See Warning above.
			void		allow_free()				{ qrk |= OI_QP_CAN_FREE; }
			void		disallow_delete()			{ qrk &= ~OI_QP_CAN_DELETE; }	//  See Warning above.
			void		disallow_free()				{ qrk &= ~OI_QP_CAN_FREE; }
			int		is_delete()				{ return (qrk & OI_QP_CAN_DELETE); }
			int		is_free()				{ return (qrk & OI_QP_CAN_FREE); }
	};


	class OI_quark_pointer_array : public OI_pointer_array {
		protected:
		public:
					OI_quark_pointer_array() : OI_pointer_array() {}
					OI_quark_pointer_array(const unsigned short i) : OI_pointer_array(i) {}
					~OI_quark_pointer_array();
			unsigned int	append(OI_quark_pointer *);
			OI_quark_pointer_array	*clone()			{ return (NULL); }
			OI_quark_pointer *element(const unsigned int i)	{ return ((OI_quark_pointer*)OI_pointer_array::element(i)); }
			OI_quark_pointer *head()				{ return ((OI_quark_pointer*)OI_pointer_array::head()); }
			int		look_for(const XrmQuark);
			void		remove(const XrmQuark);
	};

#endif /* OI_array_H */
