/**************************************************************************
 * OBJMXUD.C - Turn a normal object into an XUSERDEF object.
 *
 *	Whenever a library routine wants to supply a custom drawing routine
 *	for a standard GEM object, it calls this to fill in an XUSERDEF
 *	and attach it to the original object.  The difference between an
 *	XUSERDEF object and a regular USERDEF object is the contents of the
 *	USERBLK structure attached to the object.  A regular USERBLK contains
 *	a pointer to the drawing routine followed by a longword of anything
 *	the application wants.	For an XUSERBLK, the ap-specific longword is
 *	a pointer to the XUSERBLK itself, and then there are more fields,
 *	which contain the original ob_type and the original _Ob_spec, the
 *	parent tree and object to which the XUSERBLK is attached, and any
 *	other data you might want to add following the predefined fields.
 *	(When adding other fields after the predefined ones, pass a non-zero
 *	xub_size parm to indicate how much extra data is there.)
 *
 *	All this smoke-and-mirrors lets us transform a standard GEM object
 *	into a new custom type without losing the information from the
 *	original object.  Other library routines (rsc_gstrings, for example)
 *	know how to cope with XUSERBLK objects.
 *
 *	Note that we properly cope with INDIRECT objects (as always), and
 *	we preserve any extended type info in the original object; we only
 *	change the low-order byte when plugging in the G_USERDEF ob_type.
 *************************************************************************/

#include "gemfintl.h"

void xob_transform(ptree, obj, pblk, pdraw, ptouch, xub_size)
	OBJECT			*ptree;
	short			obj;
	XUSERBLK		*pblk;
	XUB_DRAWFUNC	*pdraw;
	XUB_TOUCHFUNC	*ptouch;
	long			xub_size;
{
	_Ob_spec_t	*pspec;
	OBJECT		*pobj;

	pobj  = &ptree[obj];
	pspec = OBPSPEC(pobj);

	pblk->ub_draw	  = pdraw;
	pblk->ub_touch	  = ptouch;
	pblk->ub_self	  = pblk;
	pblk->ub_size	  = (xub_size == 0) ? sizeof(XUSERBLK) : xub_size;
	pblk->parent_tree = ptree;
	pblk->parent_obj  = obj;

	pblk->ob_type	  = OBGTYPE(pobj);
	pobj->ob_type	  = OBXTYPE(pobj) | G_USERDEF;

	pblk->ob_spec	  = *pspec;
	*pspec			  = (_Ob_spec_t)pblk;

	if (ptouch != NULL) {
		pobj->ob_flags |= TOUCHEXIT;
	}

}


/*----------------------------------------------------------------------------
 * This is properly called via the macro XUBPTR(); for internal use only.
 *--------------------------------------------------------------------------*/

void * _GetXub(pobj)
	OBJECT *pobj;
{
	XUSERBLK   *xub;

	xub = (XUSERBLK *)OBVSPEC(pobj);
	if (OBGTYPE(pobj) == G_USERDEF && xub->ub_self == xub) {
		return xub;
	}

	return NULL;
}
