/*
 * genobject.h --
 *
 *	Main include file for the GenObject package.
 *
 * The GenObject package enables extension writers to create extensions
 * based on Tcl_Obj objects in a uniform manner. The package takes care
 * of many mundane details such as keeping track of when an instance is
 * no longer referenced by the user program, associating the internal
 * representation with each instance, and maintaining extension private
 * data. Tcl_Obj objects based on GenObject can be used safely as either
 * arguments or commands without loss of internal representation, or, as
 * it is known, "shimmering".
 *
 * In the meantime, Paul Duffin has released the source code for Feather.
 * I haven't had time to check it out yet. It surely does some of the same
 * things GenObject does, and I intend for GenObject to be compatible with
 * whatever Feather eventually becomes, if the Feather developers want
 * this also. We shall see. :)
 *
 * Enjoy using GenObject!
 *
 * Jacob Levy
 * (jyl@best.com)
 *
 * Copyright (c) 2000-2003 JYL Software, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE, EVEN IF
 * JYL SOFTWARE INC. IS MADE AWARE OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef	__GENOBJECT_H__
#define	__GENOBJECT_H__

#include <string.h>
#include <stdlib.h>

#include "tcl.h"

/*
 * Each extension based on GenObject provides an instance of the 
 * GenObject_Extension structure with some information about the specific
 * extension, including some function pointers. This structure is as follows:
 *
 * typedef struct GO_Extension {
 *    char *		name;
 *    unsigned int	namelen;
 *    void 		(*cleanup)(Tcl_Interp *interp, void *data,
 *				   struct GO_Extension *extPtr);
 *    int		(*invoke)(Tcl_Interp *interp, char *name, void *data,
 *				  int objc, Tcl_Obj *CONST objv[],
 *				  struct GO_Extension *extPtr);
 *    int		(*configure)(Tcl_Interp *interp,
 *				     int objc, Tcl_Obj *CONST objv[],
 *				     struct GO_Extension *extPtr);
 *    void *		extensionData;
 * } GO_Extension;
 *
 * The "cleanup" routine is invoked when no more references remain to this
 * instance. Its job is to clean up state associated with this instance. The
 * GenObject package automatically maintains reference counts for each
 * instance and invokes the "cleanup" routine of an instance's extension
 * structure when the reference count for that instance goes to zero.
 *
 * The "invoke" routine is invoked when an instance is used as a command.
 * It returns a Tcl result indicating success or failure, and leaves its
 * result in the given interpreter's object result.
 *
 * The "configure" routine is invoked when "genobj::configure <thisext> .."
 * is called with the name under which this extension is registered. This
 * allows an extension to set or retrieve global extension specific
 * parameters. This routine also returns a Tcl result and leaves its
 * result in the given interpreter's object result.
 *
 * All routine pointers can be NULL. For "invoke" and "configure", if the
 * routine pointer is NULL, when that operation is invoked, the GenObject
 * package simulates a TCL_ERROR result and sets the interpreter result
 * to a string explaining the error condition.
 *
 * The "extensionData" field allows the extension to maintain global per
 * extension data. This data is accessible to all routines above through
 * the supplied GO_Extension * argument.
 */

typedef struct GO_Extension {
    char *		name;
    unsigned int	namelen;
    void 		(*cleanup)(Tcl_Interp *interp, void *data,
				   struct GO_Extension *extPtr);
    int			(*invoke)(Tcl_Interp *interp, char *name, void *data,
				  int objc, Tcl_Obj *CONST objv[],
				  struct GO_Extension *extPtr);
    int			(*configure)(Tcl_Interp *interp,
				     int objc, Tcl_Obj *CONST objv[],
				     struct GO_Extension *extPtr);
    void *		extensionData;
} GO_Extension;

/*
 * The following structure represents that data associated with each
 * instance of some GenObject extension.
 *
 * typedef struct GO_InternalRep {
 *    char *		name;
 *    Tcl_Command	cmdToken;
 *    Tcl_Interp *	interp;
 *    GO_Extension *	extension;
 *    void *		data;
 *    int		refcount;
 * } GO_InternalRep;
 *
 * Each instance is associated with a structure of this form:
 *
 * Each instance stores a pointer to the string representation of the
 * Tcl object.
 * Each instance is associated with a Tcl command token.
 * Each instance is created in the context of a specific Tcl interpreter.
 * Each instance may be associated with a Tcl command.
 * Each instance has a specific extension type.
 * Each instance can maintain some private data.
 * Each instance maintains its own reference count. CAUTION: DO NOT CHANGE
 * the value of this field or the GenObject package may operate incorrectly.
 * This field is correctly maintained internally by GenObject and applications
 * should NOT CHANGE the value of this field directly under any circumstance.
 */

typedef struct GO_InternalRep {
    char *		name;
    Tcl_Command		cmdToken;
    Tcl_Interp *	interp;
    GO_Extension *	extension;
    void *		data;
    int			refcount;
    int			destroyed;
} GO_InternalRep;

/*
 * Define annotation for export on Win32 systems:
 */

#ifndef	GENOBJ_DLL
# if defined(_WIN32) && !defined(GENOBJ_STATIC)
#  ifdef DEF_GENOBJ_DLL
#    define GENOBJ_DLL		__declspec(dllexport)
#  else
#    define GENOBJ_DLL		__declspec(dllimport)
#  endif
# else
#  define GENOBJ_DLL
# endif
#endif

/*
 * Declare the exported functions:
 */

#ifdef __cplusplus
extern "C" {
#endif
extern GENOBJ_DLL int		Genobj_Init(Tcl_Interp *interp);
extern GENOBJ_DLL int		Genobj_SafeInit(Tcl_Interp *interp);

extern GENOBJ_DLL Tcl_Obj *	GO_MakeGenObject(GO_Extension *extPtr,
						 void *data,
						 Tcl_Interp *interp);

extern GENOBJ_DLL void *	GO_GetInternalRep(Tcl_Obj *objPtr,
						  GO_Extension *extPtr);
extern GENOBJ_DLL void *	GO_GetUncheckedInternalRep(Tcl_Obj *objPtr);
#ifdef __cplusplus
}
#endif

#endif	/* __GENOBJECT_H__ */
