/*---------------------------------------------------------------------
 *
 *
 *             Copyright (c) 1992, 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.
 *---------------------------------------------------------------------
 * swidget.c: the runtime swidget class.   
 *-------------------------------------------------------------------*/
/*

.VERSION
 090818		last modfif 
*/


/*--- include files ---*/
#include <string.h>
#include <UxLib.h>
#include "UxLibP.h"
#include <resload.h>
#include "version.h"

/*--- macro symbolic constants ---*/

#define LIST_BLOCK	10

/*--- macro functions ---*/

/*--- types ---*/

/*--- external functions ---*/

/*--- external variables ---*/

/*--- global variables ---*/

/*--- file global variables ---*/
M_FILE_VERSION("$Header")

void UxSwidgetFreeArgs();

extern int UxStrEqual();
extern void UxFreeXValue();


/*--- forward declaration of static functions ---*/

/*--------------------------------------------------------------------------
NAME: 	UxCreateSwidget
	UxCreateDialogSwidget

INPUT:		char *name, WidgetClass cls, swidget parent

RETURN:		swidget
DESCRIPTION:	Create a swidget instance.
		CreateDialogSwidget differs only in setting the Dialog flag,
		so that the implicit shell for the widget is a Dialog shell.

CREATION:	25 May 1989
LAST REV:	June 92	fix...	-- remove components 
--------------------------------------------------------------------------*/

swidget UxCreateSwidget(name, cls, parent)
	char		*name;
	WidgetClass	cls;
	swidget		parent;
{
	swidget	sw = (swidget) UxMalloc(sizeof(UxShadowWidget_t));

	sw->Self 	= sw;
	sw->Parent  	= parent;

	sw->Name 	= UxCopyString(name);
	sw->WClass 	= cls;
	sw->Context	= parent ? parent->Context : 0;
	sw->ItsWidget   = 0;

	sw->Values 	= 0;
	sw->NumValues 	= 0;

	sw->UpdateFlag	=  1;
	sw->DefaultShell = 0;
	sw->Flags 	= 0;
	sw->IfClassCode = -1;

	sw->Accelerators = 0;
	sw->Translations = 0;

	return sw;
}

swidget UxCreateDialogSwidget(name, cls, parent)
	char		*name;
	WidgetClass	cls;
	swidget		parent;
{
	swidget sw = UxCreateSwidget(name, cls, parent);
	UxSwidgetSetFlag(sw, UXDIALOG_FLAG);
	return sw;
}

/*--------------------------------------------------------------------------
NAME:	UxFreeSwidget
INPUT:		swidget sw
RETURN:
DESCRIPTION:	free the specified swidget
LAST REV:	Apr 93	fix4133	-- Set Self to NULL for UxIsValidSwidget.
--------------------------------------------------------------------------*/
void UxFreeSwidget(sw)
	swidget sw;
{
	UxSwidgetFreeArgs(sw);
	UxFree(sw->Name);
	UxFree(sw->Values);
	UxFree(sw->Accelerators);
	UxFree(sw->Translations);

	sw->Self = 0;	/* For subsequent UxIsValidSwidget. */
	UxFree(sw);
}

/*-----------------------------------------------------------------------------
NAME:		int UxIsSwidget
INPUT:		swidget
RETURN:         integer (1 or 0)
DESCRIPTION:    given swidget check if it is defined or not.
LAST REV:	March 93    fix3963	Name change.
-----------------------------------------------------------------------------*/

int     UxIsSwidget(sw)
	swidget  sw;
{
	return ( sw && ! memcmp( sw, &sw,  sizeof(swidget)) );
}

/*--------------------------------------------------------------------------
NAME: 	UxGetContext
INPUT:		swidget sw
RETURN:		void*
DESCRIPTION:	return the swidget's context pointer
CREATION:	25 May 1989
LAST REV:	March 93    fix3963	UxIsSwidget now called.
--------------------------------------------------------------------------*/
void *UxGetContext(sw)
	swidget sw;
{
	if (UxIsSwidget(sw))
		return sw->Context;
	return 0;
}

/*--------------------------------------------------------------------------
NAME:	UxGetWidget
INPUT:		swidget sw
RETURN:		Widget
DESCRIPTION:	Return the swidget's widget
CREATION:	25 May 1989
LAST REV:	March 93    fix3963	UxIsSwidget now called.
--------------------------------------------------------------------------*/
Widget UxGetWidget(sw)
	swidget sw;
{
	if (UxIsSwidget(sw))
		return sw->ItsWidget;
	return (Widget)0;
}

/*--------------------------------------------------------------------------
NAME:	UxPutContext
INPUT:		swidget sw, void *ctx
RETURN:
DESCRIPTION:	Set the swidget's context pointer.
CREATION:	25 May 1989
LAST REV:	March 93    fix3963	UxIsSwidget now called.
--------------------------------------------------------------------------*/
void UxPutContext(sw, ctx)
	swidget sw;
	void *ctx;
{
	if (UxIsSwidget(sw))
		sw->Context = ctx;
}

/*--------------------------------------------------------------------------
NAME:  UxPutWidget
INPUT:		swidget sw, Widget w
RETURN:
DESCRIPTION:	Set the swidget's widget
CREATION:	25 May 1989
LAST REV:	March 93    fix3963	UxIsSwidget now called.
--------------------------------------------------------------------------*/
void UxPutWidget(sw, w)
	swidget sw;
	Widget w;
{
	if (UxIsSwidget(sw))
		sw->ItsWidget = w;
}

/*--------------------------------------------------------------------------
NAME:	UxGetName
INPUT:		swidget sw
RETURN:		pointer to char
DESCRIPTION:	return the swidget's name
CREATION:	25 May 1989
LAST REV:	March 93    fix3963	UxIsSwidget now called.
--------------------------------------------------------------------------*/
char    *UxGetName(sw)
	swidget sw;
{
	if (UxIsSwidget(sw))
		return sw->Name;

	return 0;
}

/*--------------------------------------------------------------------------
NAME:	UxGetParent
INPUT:		swidget sw
RETURN:		swidget
DESCRIPTION:	Return the swidget's parent
CREATION:	25 May 1989
LAST REV:	March 93    fix3963	UxIsSwidget now called.
--------------------------------------------------------------------------*/
swidget  UxGetParent(sw)
	swidget sw; 
{
	if (UxIsSwidget(sw))
		return sw->Parent;

	return 0;
}


/*--------------------------------------------------------------------------
NAME:	UxGetClass
INPUT:		swidget sw;
RETURN:		WidgetClass
DESCRIPTION:	Return the swidget's widget class
CREATION:	25 May 1989
LAST REV:	March 93    fix3963	UxIsSwidget now called.
--------------------------------------------------------------------------*/
WidgetClass  UxGetClass(sw)
	swidget sw; 
{

	if (UxIsSwidget(sw))
		return sw->WClass;

	return 0;
}

/*--------------------------------------------------------------------------
NAME:	UxGetIfClassCode
INPUT:		swidget sw;
RETURN:		int
DESCRIPTION:	Return the swidget's interface class code.
CREATION:	25 May 1992
LAST REV:	March 93    fix3963	UxIsSwidget now called.
--------------------------------------------------------------------------*/
int  UxGetIfClassCode(sw)
	swidget sw; 
{
	if (UxIsSwidget(sw))
		return(sw->IfClassCode);

	return(-1);		/* convention - means none specified */
}

/*--------------------------------------------------------------------------
NAME:	UxPutClassCode
INPUT:		swidget sw;
DESCRIPTION:	Set the swidget's interface class code.
CREATION:	25 May 1992
LAST REV:	March 93    fix3963	UxIsSwidget now called.
--------------------------------------------------------------------------*/
void  UxPutClassCode(sw, cid)
	swidget sw; 
	int	cid;
{
	if (UxIsSwidget(sw))
		sw->IfClassCode = cid;
}

/*--------------------------------------------------------------------------
NAME:	UxPutTranslations
INPUT:		swidget sw, char* tr
RETURN:
DESCRIPTION:	Set the swidget's translation property
		Translations are not set via the Values list;
		if the Widget is not present, the put will do nothing.
CREATION:	25 May 1989
LAST REV:	March 93    fix3963	UxIsSwidget now called.
--------------------------------------------------------------------------*/
void    UxPutTranslations(sw, tr)
	swidget sw;
	char    *tr;
{
	if (UxIsSwidget(sw))
	{
           if (sw->ItsWidget)
	   {
	      UxAddTranslations(sw, tr);
	      return;
	   }	
	   sw->Translations = UxCopyString(tr);
  	}
}

/*--------------------------------------------------------------------------
NAME:	UxPutAccelerators
INPUT:		swidget sw, char* ac
RETURN:
DESCRIPTION:	Set the swidget (or widget) accelerator property  
		Accelerators are not set via the Values list;
		if the Widget is not present, the put will do nothing.
CREATION:	23  Nov. 1989
LAST REV:	March 93    fix3963	UxIsSwidget now called.
--------------------------------------------------------------------------*/
void    UxPutAccelerators(sw, ac)
	swidget sw;
	char    *ac ;
{
	if (UxIsSwidget(sw))
	{
           if (sw->ItsWidget)
	   {
	      UxAddAccelerators(sw, ac);
	      return;
	   }	
	   sw->Accelerators = UxCopyString(ac);
  	}
}

/*--------------------------------------------------------------------------
NAME:	UxGetAccelerators
INPUT:		swidget sw
RETURN:         char *
DESCRIPTION:    return the swidget's accelerators string.
CREATION:	23  Nov. 1989
LAST REV:	March 93    fix3963	UxIsSwidget now called.
--------------------------------------------------------------------------*/
char  	*UxGetAccelerators(sw)
	swidget   sw;
{
	if (UxIsSwidget(sw))
		return sw->Accelerators;
	return 0;
}

/*--------------------------------------------------------------------------
NAME:	UxGetTranslations
INPUT:		swidget sw
RETURN:         pointer to char
DESCRIPTION:	Return the swidget's translations string.
CREATION:	25 May 1989
LAST REV:	March 93    fix3963	UxIsSwidget now called.
--------------------------------------------------------------------------*/
char  	*UxGetTranslations(sw)
	swidget   sw;
{
	if (UxIsSwidget(sw))
		return sw->Translations;
	return 0;
}


#ifdef MOTIF_WIDGETS
#include <Xm/DialogS.h>
#include <Xm/MenuShell.h>
#endif

/*----------------------------------------------------------------------
 * NAME:	<UxPutDefaultShell>
 * DESCRIPTION:	<Put shellclass name to swidget.>
 * PARAMETERS: 
 *	swidget sw	I
 *	char*   c	I	class name
 * RETURN:	none
 * EXT REFS:	UxShellNameList, AppShellIndex, OverrideShellIndex,
 *		applicationShellWidgetClass, overrideShellWidgetClass,
 *		TopLevelShellIndex, topLevelShellWidgetClass,
 *		TransientShellIndex, transientShellWidgetClass,
 *		DialogShellIndex, xmDialogShellWidgetClass,
 *		MenuShellIndex, xmMenuShellWidgetClass
 * EXT EFFECTS:	
 * ASSUMPTIONS:
 * REVISIONS:	10, Oct. 1989		created
 *		March 93    	fix3963	UxIsSwidget now called.
 *		09/03/93	fix3968	renamed class to c
 *--------------------------------------------------------------------*/
void UxPutDefaultShell(sw,  c)
	swidget sw;
	char *c;
{
    if (UxIsSwidget(sw))
    {
        if (UxStrEqual(c, UxShellNameList[AppShellIndex])) 
	    sw->DefaultShell = applicationShellWidgetClass;

        else if (UxStrEqual(c, UxShellNameList[OverrideShellIndex]))
	    sw->DefaultShell = overrideShellWidgetClass;

        else if (UxStrEqual(c, UxShellNameList[TopLevelShellIndex]))
	    sw->DefaultShell = topLevelShellWidgetClass;

        else if (UxStrEqual(c, UxShellNameList[TransientShellIndex]))
	    sw->DefaultShell = transientShellWidgetClass;

#ifdef MOTIF_WIDGETS
        else if (UxStrEqual(c, UxShellNameList[DialogShellIndex]))
	    sw->DefaultShell = xmDialogShellWidgetClass;

        else if (UxStrEqual(c, UxShellNameList[MenuShellIndex]))
	    sw->DefaultShell = xmMenuShellWidgetClass;
#endif

   }

}

/*--------------------------------------------------------------------------
NAME:	UxGetDefaultShell 
INPUT:		swidget sw;
RETURN: 
DESCRIPTION:    return the defaultShell value 
CREATION:	10, Oct. 1989 
LAST REV:	March 93    fix3963	UxIsSwidget now called.
--------------------------------------------------------------------------*/
WidgetClass UxGetDefaultShell (sw)
	swidget sw;
{
    
	if (UxIsSwidget(sw))
		return sw->DefaultShell;

        return 0;
}

/*--------------------------------------------------------------------------
NAME:	UxSwidgetSetFlag
INPUT:		swidget sw;
		int	mask;		- mask specifying flag to be set
RETURN: 
DESCRIPTION:    sets the flags bit spedified in the mask 
CREATION:	1, Aug. 1990  (see bug866)
LAST REV:	March 93    fix3963	UxIsSwidget now called.
--------------------------------------------------------------------------*/
void	UxSwidgetSetFlag(sw, mask)
	swidget sw;
	int	mask;
{
	if (UxIsSwidget(sw))
		sw->Flags = sw->Flags | mask;
}

/*--------------------------------------------------------------------------
NAME:	UxSwidgetUnsetFlag
INPUT:		swidget sw;
		int	mask;		- specifies bit to unset
RETURN: 
DESCRIPTION:    unsets the flags bit spedified in mask 
CREATION:	1, Aug. 1990  (see bug866)
LAST REV:	March 93    fix3963	UxIsSwidget now called.
--------------------------------------------------------------------------*/
void	UxSwidgetUnsetFlag(sw, mask)
	swidget sw; 
	int	mask;
{
	if (UxIsSwidget(sw))
		sw->Flags = sw->Flags & ~mask;
}

/*--------------------------------------------------------------------------
NAME:	UxSwidgetGetFlag
INPUT:		swidget sw;
		int	mask;		- specifies bit to get
RETURN: 
DESCRIPTION:    gets the flags bit spedified in mask 
CREATION:	1, Aug. 1990  (see bug866)
LAST REV:	March 93    fix3963	UxIsSwidget now called.
--------------------------------------------------------------------------*/
int	UxSwidgetGetFlag (sw, mask)
	swidget sw;
	int	mask;
{
    	if (UxIsSwidget(sw))
		return (sw->Flags & mask ? 1 : 0);
	return 0;
}

/*--------------------------------------------------------------------------
NAME:	UxSwidgetSetWinGroupFlag
INPUT:		swidget sw;
RETURN: 
DESCRIPTION:    sets the window group flag 
CREATION:	1, Aug. 1990   (see bug866)
LAST REV:	May 92	fix3571	-- swidget type is a pointer.
--------------------------------------------------------------------------*/
void	UxSwidgetSetWinGroupFlag (sw)
	swidget sw;
{
	UxSwidgetSetFlag(sw, UXWIN_GROUP_FLAG);
}

/*--------------------------------------------------------------------------
NAME:	UxSwidgetGetWinGroupFlag
INPUT:		swidget sw;
RETURN: 
DESCRIPTION:    gets the window group flag 
CREATION:	1, Aug. 1990   (see bug866)
LAST REV:	May 92	fix3571	-- swidget type is a pointer.
--------------------------------------------------------------------------*/
int	UxSwidgetGetWinGroupFlag (sw)
	swidget sw;
{
	return UxSwidgetGetFlag(sw, UXWIN_GROUP_FLAG);
}

/*--------------------------------------------------------------------------
NAME:	UxSwidgetUnsetWinGroupFlag 
INPUT:		swidget sw;
RETURN: 
DESCRIPTION:    unsets the window group flag 
CREATION:	1, Aug. 1990   (see bug866)
LAST REV:	May 92	fix3571	-- swidget type is a pointer.
--------------------------------------------------------------------------*/
void	UxSwidgetUnsetWinGroupFlag (sw)
	swidget sw;
{
	UxSwidgetSetFlag(sw, UXWIN_GROUP_FLAG);
}

/*--------------------------------------------------------------------------
NAME:	UxGetCreateManaged 
INPUT:		swidget sw;
RETURN: 
DESCRIPTION:    gets the createManaged flag
CREATION:	15 April 1991	bugfix 2170
LAST REV:	May 92	fix3571	-- swidget type is a pointer.
--------------------------------------------------------------------------*/
char*	UxGetCreateManaged (sw)
	swidget sw;
{
	/** Create managed is true by default, 
	 ** unless the create_unmanaged flag has been set.
	 **/

	if (UxSwidgetGetFlag (sw, UXCREATE_UNMANAGED_FLAG)) 
	{
		return "false";
	}
	else
	{	
		return "true";
	}
}

/*--------------------------------------------------------------------------
NAME:	UxPutCreateManaged
INPUT:		swidget sw;
		char    *cm;
RETURN: 
DESCRIPTION:    sets the create unmanaged flag according to whether
		'cm' is "true" or "false".
		
CREATION:	15 April 1991	bugfix 2170
LAST REV:	May 92	fix3571	-- swidget type is a pointer.
--------------------------------------------------------------------------*/
void	UxPutCreateManaged(sw,  cm)
	swidget sw;
	char    *cm;
{
	if (UxStrEqual(cm, "false")) {
		UxSwidgetSetFlag (sw,  UXCREATE_UNMANAGED_FLAG);
	} else {
		UxSwidgetUnsetFlag (sw,  UXCREATE_UNMANAGED_FLAG);
	}
}

/*--------------------------------------------------------------------------
NAME:	UxFindValue
INPUT:		swidget sw		-swidget 
		char *prop		-resource
		XtArgVal *value		-output value	
RETURN:		True of False
DESCRIPTION:	give a swidget and a resource, find the Xt value if available
		in the swidget resource list.
CREATION:	Nov 19/91 	fix3186
LAST REV:	May 92	fix3571	-- swidget type is a pointer.
---------------------------------------------------------------------------*/
int	UxFindValue (sw, prop, value)
	swidget  sw;
	char	 *prop;
	XtArgVal *value;
{
	int i;

	for (i = 0; i < sw->NumValues; i++)
	{
		if (UxStrEqual (prop, sw->Values[i].name))
		{
			*value =  sw->Values[i].value;
			return True;
		}
	}
	return False;
}


/*--------------------------------------------------------------------------
NAME:	UxSwidgetFreeArgs
INPUT:		swidget w		-swidget 
DESCRIPTION:	
		Free the Values array of  the swidget.

CREATION:	Nov 19/91 	fix3186
LAST REV:	May 92	fix3571	-- swidget type is a pointer.
---------------------------------------------------------------------------*/
void	UxSwidgetFreeArgs (sw)
	swidget  sw;
{
	int i;

	for (i = 0; i < sw->NumValues; i++)
	{
		UxFreeXValue(sw, sw->Values[i].name,  sw->Values[i].value); 
		UxFree(sw->Values[i].name);
	}
	UxFree(sw->Values);
	sw->Values = 0;
	sw->NumValues = 0;
}


/*------------------------------------------------------------------------
 * NAME:  UxSwidgetAddNamedValue
 * INPUT:
 *		swidget sw;
 *		char    *prop;	-- name of resource 
 *		XtArgVal val;	-- value to save
 * DESCRIPTION:
 *	Saves a resource on the swidget's  Values list
 *	(so that it can be sent through XtSetValues when
 *	the swidget is next updated).
 *
 * LAST REV:	May 92	fix3571	-- swidget type is a pointer.
 *------------------------------------------------------------------------*/

void UxSwidgetAddNamedValue(sw, prop, val)
	swidget sw;
	char*	prop;
	XtArgVal  val;
{
	/*-------------------------------------------
	 * Grow by a block whenever the list length
	 * reaches a multiple of the block size.
	 *-------------------------------------------*/

	if (sw->NumValues % LIST_BLOCK == 0)
	{
		sw->Values = (ArgList) UxRealloc(sw->Values, 
			       sizeof(Arg) * (sw->NumValues + LIST_BLOCK));
	}

	sw->Values[sw->NumValues].name = UxCopyString(prop);
	sw->Values[sw->NumValues].value = val;
	sw->NumValues++;
}

/*------------------------------------------------------------------------
 * NAME:  UxSwidgetPropSet
 * INPUT:
 *		swidget sw;
 *		char    *prop;	-- name of resource 
 * RETURNS: 0/1		-- 1 iff a  value for the named resource has been
 *			   saved on the swidget's values list.
 * DESCRIPTION:
 *	Simply searches the Values list for the given name.
 *
 * LAST REV:	May 92	fix3571	-- swidget type is a pointer.
 *------------------------------------------------------------------------*/
int UxSwidgetPropSet (sw, prop)
	swidget sw;
	char*   prop;
{
	int i;

	for (i = 0; i < sw->NumValues; i++)
	{
		if (UxStrEqual(sw->Values[i].name, prop))
			return 1;
	}
	return 0;
}

/*------------------------------------------------------------------------
 * NAME:  UxSwidgetGetProp
 * INPUT:
 *		swidget sw;
 *		char    *prop;	-- name of resource 
 * RETURNS: XtArgVal		-- value of saved resource, or 0.
 * DESCRIPTION:
 *	If a value for the named resource has been saved in the swidget's
 *	Values list, then that saved value is returned.
 * LAST REV:	May 92	fix3571	-- swidget type is a pointer.
 *------------------------------------------------------------------------*/
XtArgVal UxSwidgetGetProp (sw, prop)
	swidget sw;
	char*    prop;
{
	XtArgVal val = 0;

	UxFindValue(sw, prop, &val);
	return val;
}

/*------------------------------------------------------------------------
 * NAME:	UxNewContext
 *	<Allocate a context structure>
 * INPUT:	size 	-- of the desired structure
 *		isSubclass	-- nonzero if the requester is a subclass,
 *				   requiring that the result also be
 *				   returned for the base.
 * RETURNS:	Pointer to a data area of (at least) the desired size.
 *------------------------------------------------------------------------*/

void*	UxNewContext (size, isSubclass)
	size_t size;
	int    isSubclass;
{
	static void* LastSubclassResult = 0;
	static int   LastResultSize = 0;

	void * result;

	if (LastSubclassResult) {
		result = LastSubclassResult;
	} else {
		result = UxMalloc(size);
	}

	if (isSubclass) {
		LastSubclassResult = result;
		if (LastResultSize  < size) {
			LastResultSize   = size;
		}
	} else {
		LastSubclassResult = 0;
		LastResultSize     = 0;
	}

	return (result);
}
/*--- end of file ---*/
