/*---------------------------------------------------------------------
 * $Date: 2009-08-18 15:23:20 $             $Revision: 1.2 $
 *---------------------------------------------------------------------
 * 
 *
 *             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.
 *-------------------------------------------------------------------*/

/*-------------------------------------------------------------------
  DESCRIPTION:	Conversions between UIMX and X types.
		The conversion routines to go between X types and UIMX types
		are registered in a table :

			UxUimx_x[uimx_type][x_type]

		The indices are the values of the UxUT_ and UxXT_ variables
		which are initialized by UxUtype_init().
		This table is managed by routines in <types.h>.

		The general format for these conversion routines is:

		int <utype>_<xtype>(sw, udata, xdata, flag)
			swidget	sw	- swidget requesting the conversion
			<utype>	*udata	- input or output of uimx value
			<xtype> *xdata	- input or output of Xt value
			int     flag	- TO_UIMX to convert to uimx or
					  TO_X to convert to Xt.

		The conversions are performed generically by calling the
		function 'UxCallConverter()' with the appropriate arguments.
		Note: When the converter function is called from
                      UxCallConverter()
		there is a 5th argument which is the x_type, but most of the
		converters only have the above 4 arguments.


CREATION:	19 April 1988
REVISIONS:	5 July 1989
		-- added features to make it possible to compile with runtime
		library with no modification; added function for properties
		that have no resource converter in the X Toolkit
		30 Aug 1990
		-- added National Language Support
		11 Jan 1991
		-- moved enumerated-type resources to enum_type.c

.VERSION
 090818		last modif KB

-----------------------------------------------------------------------------*/

/*--- include files ---*/
#include "version.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* CG. Not needed and values.h does not exist on VMS
#include <values.h>
*/
#include <ctype.h>

#include <X11/StringDefs.h>
#include <X11/IntrinsicP.h>	/* needed for the def'n of WidgetClass */
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/Xatom.h>

#include <Xm/Xm.h>

/* We need to include the header files for all the widget classes
   in order to get the extern declarations of the widget-class pointers
   for use in string_WidgetClass() */
#include <Xm/ArrowB.h>
#include <Xm/ArrowBG.h>
#include <Xm/BulletinB.h>
#include <Xm/CascadeB.h>
#include <Xm/CascadeBG.h>
#include <Xm/Command.h>
#include <Xm/DrawingA.h>
#include <Xm/DrawnB.h>
#include <Xm/FileSB.h>
#include <Xm/Form.h>
#include <Xm/Frame.h>
#include <Xm/Label.h>
#include <Xm/LabelG.h>
#include <Xm/List.h>
#include <Xm/MainW.h>
#include <Xm/MessageB.h>
#include <Xm/PanedW.h>
#include <Xm/PushB.h>
#include <Xm/PushBG.h>
#include <Xm/RowColumn.h>
#include <Xm/Scale.h>
#include <Xm/ScrollBar.h>
#include <Xm/ScrolledW.h>
#include <Xm/SelectioB.h>
#include <Xm/SeparatoG.h>
#include <Xm/Separator.h>
#include <Xm/Text.h>
#include <Xm/TextF.h>
#include <Xm/ToggleB.h>
#include <Xm/ToggleBG.h>

#include "uxproto.h"

#ifndef	RUNTIME

#include "veos.h"
#include "prim.cl.h"
#include "swidget.h"
#include "text.cl.h"
#include "textF.cl.h"
#include "Ux.h"
#include "tkdefaults.h"
#include "ttapp.h"

#else

#include "UxLib.h"
#include "UxLibP.h"

#endif /* ! RUNTIME */

#include "utype.h"
#include "types.h"
#include "resload.h"
#include "vtypes.h"
#include "valloc.h"
#include "global.h"
#include "colors.h"
#include "uimx_cat.h"
#include "misc1_ds.h"


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

/*--- macro functions ---*/
/* X/OPEN message catalog macros. These will make the code more compact. */
#define CGETS(ms,ds_ms)                 UxCatGets(MC_MISC1,ms,ds_ms)

/*--- types ---*/

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

extern int UxStrEqual(), UxLoadPixmapFromPixmapOrBitmapFile();
extern int Ux_wcslen();
extern void UxSwidgetSetWinGroupFlag(), UxSwidgetUnsetWinGroupFlag();
extern void UxAddXValues(), UxAddUserDefXtypes();


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

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

/*--- file global variables ---*/
M_FILE_VERSION("$Header")
int UxConvertMaxStringTable = 10;
int UxRingBufferSize = 10;  /* size for converters rotating buffers */

/*--- forward declaration of static functions ---*/
static	int	string_XmStringTable
			UXPROTO((char*, swidget, char**, XmString**, int));

/*------------------------------------------------------------
 * COMMENT_BOX
 *-----------------------------------------------------------*/


/*-----------------------------------------------------------------------------
NAME:		static Boolean GetNextString(n, src, dst)
INPUT:		int	n;		- number of times called before
					  for this source string
		char	**src;		- input string
OUTPUT:		char	**dst;		- next component
RETURN:		Boolean			- false if at end of string
DESCRIPTION:	Extracts the next component (delimited by a comma or a NULL)
		from the src string and outputs it in the dst string.
CREATION:	HP			Jul 28/1990
REVISIONS:	1 August 1990	bugfix 865
		-- fixed bug where it could not catch an empty component 
		   at the end of the source string (e.g. "aa,bb,") by leaving
		   the comma to start the next component, and adding a special
	 	   case for the first component
-----------------------------------------------------------------------------*/

static	Boolean	GetNextString(n, src, dst)
int		n;
char		**src;
char		**dst;
{
	char *c;

	/* if we have hit the end of the src, we are done... */
	if (!**src)
	    return(False);

	/* skip the comma which separates entries later than the first
	 * from their successor 
	 */
	if ((n > 0) && (**src == ','))
	    (*src)++;

	/* skip leading white space... */
	while (**src && isspace(**src))
	    (*src)++;

	/* allocate space for the src and start copying.  This space
	 * needs to be freed after it is used...
	 */
	*dst = (char *) UxMalloc(strlen(*src) + 1);
	c = *dst;

	while (**src) {
	    /* look for quoted ','s... */
	    if ((**src == '\\') && (*((*src) + 1) == ',')) {
		*c++ = ',';
		(*src) += 2;
	    }
	    /* look for terminating (unquoted) ','s... */
	    else if (**src == ',') {
		*c = '\0';
		/* do not increment src pointer; the next component will    */
		/* start with a comma 					    */
		return(True);
	    }
	    /* otherwise it is a straight character... */
	    else {
		*c++ = *(*src)++;
	    }
	}

	/* we hit the end of the original src, so we need to null
	 * terminate our target...
	 */
	*c = '\0';

	return(True);
}

/******************************************************************************
NAME:		void _string_XmStringTable (args, num_args, from_val, to_val);
INPUT:		XrmValuePtr	args		- ignored
		Cardinal	*num_args	- ignored
		XrmValue	*from_val	- char string to convert from
		XrmValue	*to_val		- place to deposite table
RETURN:		nothing
DESCRIPTION:	Performs the resource conversion from char strings to
		XmStringTable's for list widgets.  Maintains a circular
		list of XmStringTables to allow them to survive until then
		are use.
CREATION:	HP			Jul 28/1990
REVISIONS:	1 August 1990	bugfix 865
		-- fixed bug where it could not catch an empty component 
		   at the end of the source string (e.g. "aa,bb,"); added
		   serial order parameter as first argument to GetNextString()
-----------------------------------------------------------------------------*/

static	void	_string_XmStringTable(args, num_args, from_val, to_val)
XrmValuePtr	args;
Cardinal	*num_args;
XrmValue	*from_val;
XrmValue	*to_val;
{
	static int MaxStringTable = 0;
	static XmStringTable *tableList = (XmStringTable *) 0;
	static int CurrentStringTable = 0;
	static Boolean StringTableFull = False;
	int max;
	int i;
	XmStringTable *tmpTableList = (XmStringTable *) 0;
	char *c;
	char *curr;

	/* the lower limit for string tables will be 10... */
	if (UxConvertMaxStringTable < 10)
	    UxConvertMaxStringTable = 10;

	if (MaxStringTable < UxConvertMaxStringTable) {
	    /* let's grow the table... */
	    tmpTableList = (XmStringTable *)
		    UxMalloc(UxConvertMaxStringTable * sizeof(*tableList));
	    if (StringTableFull) {
		/* The table is full, now that it isn't full anymore, we will
		 * need to reorder it.  CurrentStringTable points to the next
		 * one to use, which is also the next one to free, which is
		 * also the first one of the new list...
		 */
		for (i = 0; i < MaxStringTable; i++) {
		    tmpTableList[i] = tableList[(i +
			    CurrentStringTable) % MaxStringTable];
		}
		CurrentStringTable = MaxStringTable;
		StringTableFull = 0;
	    } else {
		/* The table is not full, so just copy the first
		 * CurrentStringTable entries...
		 */
		for (i = 0; i < CurrentStringTable; i++) {
		    tmpTableList[i] = tableList[i];
		}
	    }
	    if (tableList) {
		(void) UxFree(tableList);
	    }
	    tableList = tmpTableList;
	    MaxStringTable = UxConvertMaxStringTable;
	}

	/* do we need to free up this entry... */
	if (StringTableFull) {
	    for (i = 0; tableList[CurrentStringTable][i]; i++) {
		(void) XmStringFree(tableList[CurrentStringTable][i]);
	    }
	    (void) UxFree(tableList[CurrentStringTable]);
	}

	c = (char *) from_val->addr;
	max = 100;
	tableList[CurrentStringTable] =
		(XmStringTable) UxMalloc(max * sizeof(XmString));

	for (i = 0; GetNextString(i, &c, &curr); i++) {
	    if (i >= max) {
		max += 100;
		tableList[CurrentStringTable] =
			(XmStringTable) UxRealloc(tableList[CurrentStringTable],
			max * sizeof(XmString));
	    }
	    tableList[CurrentStringTable][i] =
		    XmStringCreateLtoR(curr, XmSTRING_DEFAULT_CHARSET);
	    UxFree(curr);
	}

	/* we need to the array with one extra element so that we can
	 * null terminate it... */
	tableList[CurrentStringTable] =
		(XmStringTable) UxRealloc(tableList[CurrentStringTable],
		(i + 1) * sizeof(XmString));

	/* null terminate the array... */
	tableList[CurrentStringTable][i] = (XmString) NULL;

	/* set up the return value... */
	to_val->addr = (caddr_t) &tableList[CurrentStringTable];
	to_val->size = sizeof(caddr_t);

	/* increment the CurrentStringTable... */
	(void) CurrentStringTable++;
	if (CurrentStringTable >= MaxStringTable) {
	    CurrentStringTable = 0;
	    StringTableFull = True;
	}
}

/* ------------------------------------------------------------------------*/

static	char * uSelectionArray[] = {
	"select_position", "select_whitespace", 
	"select_word", "select_line",
	"select_all" , "select_paragraph"
};
static	XmTextScanType xSelectionArray[] = {
	XmSELECT_POSITION, XmSELECT_WHITESPACE,
	XmSELECT_WORD, XmSELECT_LINE,
	XmSELECT_ALL, XmSELECT_PARAGRAPH
};

#ifndef	RUNTIME
int UxValuesOfSelectionArray(lst, n)
char ***lst;
int *n;
{
	static char *values[7] = {
		"",
		"   select_position",
		"   select_whitespace",
		"   select_word",
		"   select_line",
                "   select_all",
		"   select_paragraph"};

	static int  first_time = 1;

	if (first_time)
	{
		values[0] = UxCopyString(CGETS(MS_MISC_SELECTARRAY_ERR, 
					DS_MS_MISC_SELECTARRAY_ERR));
		first_time = 0;
	}

	*lst = values;
	*n = 6;
	return 0;
}

/******************************************************************************
 ==== GLOBAL =================================================================
*******************************************************************************
NAME:		int		UxValidateSelectionArray(rs, s)

INPUT:		rswidget	*rs		- text/textF widget
		char		*s		- selection array variable

RETURN:		ERROR / NO_ERROR

REVISIONS:	Jul 16/1990
		      - fixed logic of strtok loop
-----------------------------------------------------------------------------*/

int UxValidateSelectionArray(rs, s)
rswidget *rs;
char *s;
{
	char 	*c1;
	char 	*temp;
	int	d, count, n = XtNumber(uSelectionArray);
	text	*tx;
	textField	*tf;

	/* a null string is invalid */
	if (s == NULL)
	    return ERROR;

	/* determine the array count:	
	 *   if there is a value in the swidget, take it;
	 *   otherwise, use the default.
	 */
	d = UX_DEFAULT_SELECTION_ARRAY_COUNT;
	(void) UxFindValue (rs, UxGetRD_selectionArrayCount(rs), &d);

	/* an empty string is valid if the array count is 0 */
	if (!s[0])
	    return (d==0 ? NO_ERROR : ERROR);

	/* create temporary  copy of string to parse */
	temp = UxMalloc(strlen(s) + 1);
	(void) strcpy(temp, s);

	/* check that each element of the array is valid, and count them */
	c1 = strtok(temp, " ");
	count = 0;

	while(c1 != NULL)
	{
	    int i, match;

	    count++;
	    match = 0;
	    for (i=0; i<n; i++)
	    {
	        if (!strcmp(c1, uSelectionArray[i]))
	        {
		    match = 1;
		    break;
		}
	    }
	    if (!match)
	    {
		/* one of the items in the array is invalid */
		UxFree(temp);
		return ERROR;
	    }

	    c1= strtok(NULL, " ");
	}

	/* free the temporary copy */
	UxFree(temp);

	/* error occurs if array count is greater than the number of items */
	return (d>count ? ERROR : NO_ERROR);
}

int UxValuesOfSelectionArrayCount(lst, n)
char ***lst;
int *n;
{
	static char *values[1];
	static int  first_time = 1;

	if (first_time)
	{
		values[0] = UxCopyString(CGETS(MS_MISC_NUM_ELEM_SEL, 
					DS_MS_MISC_NUM_ELEM_SEL));
		first_time = 0;
	}

	*lst = values;
	*n = 1;
	return 0;
}

int UxValidateSelectionArrayCount(rs, d)
rswidget *rs;
int  d;
{
	char	*s;
	int	n;
	text	*tx;
	textField	*tf;

	/* a negative count value is always wrong */
        if (d < 0)
           return ERROR;

	/* determine the selection array string:			*/
	/*   if not used in the swidget, we use the default		*/
	/*   otherwise, we get the string from the swidget		*/

	s = UX_DEFAULT_SELECTION_ARRAY;
	(void) UxFindValue (rs, UxGetRD_selectionArray(rs), &s);

	if (s == NULL || !s[0])
	{
	    /* selectionArray string is empty or null, so count must be 0 */
	    n = 0;
	}
	else
	{
	    char *temp, *sp;
	    int	 i;

	    /* determine the number of items in the selection array string */
	    /* and compare to the selectionArrayCount value		   */

	    /* create temp copy of string to parse */
	    temp = UxMalloc(strlen(s) + 1);
	    (void) strcpy(temp, s);

	    /* count the items in the string */
	    n = 0;
	    sp = strtok(temp, " ");
	    do 
	    {
		n++;
	    } while (sp = strtok(NULL, " "));

	    /* free the temporary copy */
	    UxFree(temp);
	}

	/* error if array count is greater than # items in the array string */
	return (d > n ? ERROR : NO_ERROR);
}

#endif /* ! RUNTIME */

/* ------------------------------------------------------------------------*/

static int _utype, _xtype;

/******************************************************************************
NAME:		int		string_String(sw, udata, xdata, flag)
INPUT:		swidget		sw		- swidget
		char		**udata		- string representation
		XmString	**xdata		- Motif Menu Post string
		int		flag		- TO_UIMX or TO_X
RETURN:		ERROR/NO_ERROR

DESCRIPTION:	Converts between string and a String. 
		Xt-side	NULL	   is converted to ""
		UIM/X-side NULL    is NOT allowed

CREATION:	31 July 1991	(fix2773)

-----------------------------------------------------------------------------*/

static int string_String(sw, udata, xdata, flag)
swidget sw;
char **udata;
char **xdata;
int flag;
{
	if (flag == TO_UIMX)
	{
		if (*xdata)
		    *udata = *xdata;
		else
		    *udata = "";
	}
	else if (flag == TO_X)
	{
		if (*udata == NULL) 
		    return ERROR;

		*xdata = *udata;
	}
	else
	{
		UxStandardError(CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
		return ERROR;
	}
	return NO_ERROR;
}

/******************************************************************************
NAME:		int		string_StringOrNull(sw, udata, xdata, flag)
INPUT:		swidget		sw		- swidget
		char		**udata		- Uimx-side string
		XmString	**xdata		- Toolkit-side string
		int		flag		- TO_UIMX or TO_X
RETURN:		ERROR/NO_ERROR

DESCRIPTION:	Converts between string and a String. 
		UIM/X-side ""	is converted to NULL.
		Xt-side	   NULL	is converted to ""
		UIM/X-side NULL	is NOT allowed.

CREATION:	31 July 1991	(fix2773)
-----------------------------------------------------------------------------*/

static int string_StringOrNull(sw, udata, xdata, flag)
swidget sw;
char **udata;
char **xdata;
int flag;
{
	if (flag == TO_UIMX)
	{
		if (*xdata)
		    *udata = *xdata;
		else
		    *udata = "";
	}
	else if (flag == TO_X)
	{
		if (*udata == NULL) 
		    return ERROR;

		if (UxStrEqual (*udata, ""))
		    *xdata = (char *) NULL;
		else
		    *xdata = *udata;
	}
	else
	{
		UxStandardError(CGETS(MS_MISC_WRONG_FLAG, 
				      DS_MS_MISC_WRONG_FLAG));
		return ERROR;
	}
	return NO_ERROR;
}

/*******************************************************************/
static int convert(from_name, from_size, from_addr, to_name, to_addr)
char *from_name;
unsigned int from_size;
caddr_t from_addr;
char *to_name;
caddr_t to_addr;
{
	XrmValue from, to;

	from.size = from_size;
	from.addr = from_addr;
	XtConvert(UxTopLevel, from_name, &from, to_name, &to);

        /* check for conversion error... */
        if (to.addr == NULL)
        {
                return(ERROR);
        }

	/* convert 'unsigned char' and 'short' to 'int';
	   do not perform a memory copy */
	if (to.size == sizeof (unsigned char)
	    && strcmp (to_name, "Boolean") != 0)
	{
		* (int *) to_addr = * (unsigned char *) to.addr;
		return(NO_ERROR);
	}
	else if (to.size == sizeof (short))
	{
		* (int *) to_addr = * (short *) to.addr;
		return(NO_ERROR);
	}

	memcpy(to_addr, to.addr, to.size);
        return(NO_ERROR);
}

/*******************************************************************/
/* This function is probably not used any more and will have to be
   removed soon.  
   In UxUtype_init(), remove line that adds string_FontStruct() converter
   and lines that add types. (Dec. 01 1992)
*/
/*******************************************************************/
static int string_FontStruct(sw, udata, xdata, flag)
swidget sw;
char **udata;
XFontStruct **xdata;
int flag;
{
	if (flag == TO_UIMX)
	    *udata = "";
	else if (flag == TO_X)
	    return( convert(XtRString, strlen(*udata), *udata, 
				       x_name(UxXT_FontStruct), xdata));
	else {
	    UxStandardError(CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
	    return ERROR;
	}
	return NO_ERROR;
}

/*******************************************************************/
static int string_Pixel(sw, udata, xdata, flag)
swidget sw;
char **udata;
Pixel *xdata;
int flag;
{
	if (flag == TO_UIMX) 
	{
	    *udata = UxPixel_to_name(*xdata);
	}
	else if (flag == TO_X)
	{
	    /* Protect strlen from NULL */

	    if (*udata) {
	        return(convert(XtRString, strlen(*udata), *udata, 
			       x_name(UxXT_Pixel), xdata));
	    } else {
		return ERROR;
	    }

	} else {
	    UxStandardError(CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
	    return ERROR;
	}
	return NO_ERROR;
}

/*******************************************************************/
/*	Pixmap table						   */
/*******************************************************************/
static char **pixmap_names = (char **) 0;
static Pixmap *pixmaps = (Pixmap *) 0;
static int num_allocated = 0, num_used = 0;

static int store_pixmap(pixmap, name)
Pixmap pixmap;
char *name;
{
    int i;

    for (i = 0; i < num_used; i++) {
	if (pixmaps[i] == pixmap) {
	    if (strcmp(pixmap_names[i], name)) {
		UxFree(pixmap_names[i]);
		pixmap_names[i] = (char *) UxMalloc(strlen(name) + 1);
		strcpy(pixmap_names[i], name);
		return(NO_ERROR);
	    }
	    return(NO_ERROR);
	}
    }

    if (num_used == num_allocated) {
	num_allocated += 10;
	pixmap_names = (char **) UxRealloc(pixmap_names,
		num_allocated * sizeof(*pixmap_names));
	pixmaps = (Pixmap *) UxRealloc(pixmaps,
		num_allocated * sizeof(*pixmaps));
    }

    pixmaps[num_used] = pixmap;
    pixmap_names[num_used] = (char *) UxMalloc(strlen(name) + 1);
    strcpy(pixmap_names[num_used], name);
    num_used++;
   return(NO_ERROR);
}

static char
*get_pixmap(pixmap)
Pixmap pixmap;
{
    int i;

    for (i = 0; i < num_used; i++)
	if (pixmaps[i] == pixmap)
		return(pixmap_names[i]);

    return("");
}

/******************************************************************************
NAME:		int		string_Pixmap(sw, udata, xdata, flag)
		int		string_HighlightPixmap(sw, udata, xdata, flag)
     		int		string_TopShadowPixmap(sw, udata, xdata, flag)
     		int		string_BottomShadowPixmap(sw, udata, xdata, flag)
INPUT:		swidget		sw		- swidget
		char		**udata		- string representation
		XmString	**xdata		- Motif StringTable
		int		flag		- TO_UIMX or TO_X
RETURN:		ERROR/NO_ERROR
DESCRIPTION:	Uses the resource converter to convert between a pixmap name
		represented as a string and a Motif Pixmap
CREATION:	19 July 1990
LAST REV:	August 1, 1991		See bugfix 2857
		- Handle new BORDER pixmap case.
		- Removed code that obtained colors when widget did not
		  exist because this always returned "" which is not a
		  valid color.  If widget does not exist just use screen
		  black and white colors.
-----------------------------------------------------------------------------*/
#define PIXMAP         0
#define HIGHLIGHT      1
#define TOPSHADOW      2
#define BOTTOMSHADOW   3
#define BORDER	       4

static int string_XmPixmap UXPROTO((int, swidget, char**, Pixmap*, int));

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

static  int     string_Pixmap(sw, udata, xdata, flag)
        swidget sw;
        char    **udata;
        Pixmap  *xdata;
        int     flag;
{

#ifdef RUNTIME 
        if(UxIsShellClass(UxGetClass(sw))){
#else
        if(UxIsExplicitShell(sw)) {
#endif /* RUNTIME */

	     *xdata = XmUNSPECIFIED_PIXMAP;
	     return NO_ERROR;
	}
        return string_XmPixmap (PIXMAP, sw, udata, xdata, flag);
}

static  int     string_BorderPixmap(sw, udata, xdata, flag)
        swidget sw;
        char    **udata;
        Pixmap  *xdata;
        int     flag;
{
        return string_XmPixmap (BORDER, sw, udata, xdata, flag);
}

static  int     string_HighlightPixmap(sw, udata, xdata, flag)
        swidget sw;
        char    **udata;
        Pixmap  *xdata;
        int     flag;
{
        return string_XmPixmap (HIGHLIGHT, sw, udata, xdata, flag);
}

static  int     string_TopShadowPixmap(sw, udata, xdata, flag)
        swidget sw;
        char    **udata;
        Pixmap  *xdata;
        int     flag;
{
        return string_XmPixmap (TOPSHADOW, sw, udata, xdata, flag);
}

static  int     string_BottomShadowPixmap(sw, udata, xdata, flag)
        swidget sw;
        char    **udata;
        Pixmap  *xdata;
        int     flag;
{
        return string_XmPixmap (BOTTOMSHADOW, sw, udata, xdata, flag);
}

/* prop indicates how the foreground color will be chosen. 
   It is one of PIXMAP, HIGHLIGHT, BOTTOMSHADOW or TOPSHADOW */

static int string_XmPixmap(prop, sw, udata, xdata, flag)
       int      prop;
       swidget  sw;
       char     **udata;
       Pixmap   *xdata;
       int      flag;
{

	if (flag == TO_UIMX)
	    *udata = get_pixmap((Pixmap) *xdata);
	else if (flag == TO_X) {
	    char	*fname;
	    Screen	*screen;
	    Pixel       UxName_to_pixel();
	    Pixmap	pixmap;
	    char	*pixmap_name;
	    static char *unspecified_pixmap = "unspecified_pixmap";
	    int		rtrn;

	    pixmap_name = *udata;
	    /* deal with empty string... */
	    if (!pixmap_name || !*pixmap_name)
		pixmap_name = unspecified_pixmap;

	    /* skip leading whitespace... */
	    while (isspace(*pixmap_name))
		(void) pixmap_name++;

	    /* deal with blank string... */
	    if (!*pixmap_name)
		pixmap_name = unspecified_pixmap;
		
	    if (!strcmp(pixmap_name, unspecified_pixmap)) {
		/* set to unspecified (no) pixmap... */
		*xdata = XmUNSPECIFIED_PIXMAP;
	    } 
	    else {
		Widget wid;
		Pixel fore, back;

		fname = UxExpandBitmapFilename(pixmap_name);

		if (fname == NULL)
		    fname = pixmap_name;

		screen= XtScreen(UxTopLevel);

#ifdef  RUNTIME
		wid = UxGetWidget(sw);
		if ( (wid) && (XmIsGadget(wid)))
			wid = UxGetWidget(UxGetParent(sw));
#else
		if (!UxIsGadget(sw))
			wid = UxGetWidget(sw);
		else
			wid = UxGetWidget(UxGetParent(sw));
#endif /* RUNTIME */

		if (wid) {
			char	*fg_resource;
			Arg	args[2];
			int	n = 0;

		        switch (prop) {
			     case PIXMAP:
				  fg_resource = XmNforeground;
				  break;
		             case HIGHLIGHT:
				  fg_resource = XmNhighlightColor;
				  break;
			     case TOPSHADOW:
				  fg_resource = XmNtopShadowColor;
				  break;
			     case BOTTOMSHADOW:
				  fg_resource = XmNbottomShadowColor;
				  break;
			     case BORDER:
				  fg_resource = XmNborderColor;
				  break;
			     default:
				  fg_resource = XmNforeground;
				  break;
			}
			XtSetArg(args[n], fg_resource, &fore); n++;
		  	XtSetArg(args[n], XmNbackground, &back); n++;
		  	XtGetValues(wid, args, n);
			rtrn = UxLoadPixmapFromPixmapOrBitmapFile(sw,fname,&pixmap,0,0,fore,back);
	    	}
	    	else {
		        rtrn = UxLoadPixmapFromPixmapOrBitmapFile(sw,fname,&pixmap,0,0,
					     BlackPixel(UxDisplay, UxScreen),
					     WhitePixel(UxDisplay, UxScreen));
		}

		/* check for successful return... */
		if (rtrn == ERROR) {
		     UxStandardError (CGETS( MS_MISC_NO_MATCH,
					DS_MS_MISC_NO_MATCH));
		     return ERROR;
		}
		*xdata= pixmap;
		store_pixmap(pixmap, pixmap_name);
	    }

	} 
	else {
	      UxStandardError(CGETS(MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
	      return ERROR;
	}
	return NO_ERROR;
}

/*******************************************************************/
static int string_bitmap(sw, udata, xdata, flag)
swidget sw;
char **udata;
Pixmap *xdata;
int flag;
{
    if (flag == TO_UIMX)
       *udata = get_pixmap((Pixmap) *xdata);
    else if (flag == TO_X)
    {
	int 	x;
	char	*fname;
	Window	rw;
	unsigned int	width, height;
	int	screen;
	Pixmap	pmap;


	fname = UxExpandBitmapFilename(*udata);
        if (fname == NULL) 
        {

            *xdata = (Pixmap)NULL;
            return NO_ERROR;
        }

	screen = DefaultScreen(UxDisplay);
	rw = RootWindow(UxDisplay, screen);

	if (XReadBitmapFile(UxDisplay,
			    rw, fname, &width, &height,
			    &pmap, &x, &x) != BitmapSuccess)
	    return(ERROR);

	*xdata = pmap;
        store_pixmap(pmap, *udata);
    }
    return(NO_ERROR);
}

/******************************************************************************
NAME:		int		string_Pointer (sw, udata, xdata, flag)
INPUT:		swidget		sw		- swidget
		char		**udata		- uimx value address
		caddr_t		*xdata		- x value address
		int		flag		- TO_UIMX or TO_X
RETURN:		ERROR/NO_ERROR
DESCRIPTION:	Converts char* <--> caddr_t representations.
-----------------------------------------------------------------------------*/

static	int	string_Pointer(sw, udata, xdata, flag)
swidget sw;
char	**udata;
caddr_t *xdata;
int	flag;
{
	if (flag == TO_UIMX) {
		*udata = (char*) *xdata;
	} else if (flag == TO_X) {
		*xdata = (caddr_t) *udata;
	} else {
		UxStandardError(CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
		return ERROR;
	}
	return NO_ERROR;
}

/******************************************************************************
NAME:           int             string_ValueWcs (sw, udata, xdata, flag)
INPUT:          swidget         sw              - swidget
                char            **udata         - string representation
                wchar_t         **xdata         - ANSI C wide character string
                int             flag            - TO_UIMX or TO_X
RETURN:         ERROR/NO_ERROR
DESCRIPTION:    Performs a conversion from/to multibyte strings to/from wide
                character strings.
		Xt-side	NULL	   remains NULL on UIM/X side
		UIM/X-side NULL    is allowed (remains NULL on Xt side)

CREATION:       fix3805		Jan 2/1992
LAST REVISION:	February 22, 1993	Rewrite converter so that only standard
					functionality of ANSI wide character
					string functions are used.
					(Use Ux_wcslen() defined in str.c)
		Sept 93		fix4491 sun4 MB_CUR_MAX workaround.
-----------------------------------------------------------------------------*/

static int string_ValueWcs(sw, udata, xdata, flag)
swidget sw;
char **udata;
wchar_t **xdata;
int flag;
{
        static char **RotatingBuffer;
        static int BufferIndex = -1;
	char *buffer;

	if (flag == TO_UIMX)
	{
		if (*xdata == NULL)
			*udata = NULL;
		else
		{

			int next_size = Ux_wcslen(*xdata);

#ifdef sun4
			buffer = UxMalloc(next_size * (MB_CUR_MAX > 0 ? MB_CUR_MAX : 1) + 1);
#else
			buffer = UxMalloc(next_size * MB_CUR_MAX + 1);
#endif /* sun4 */

			if (wcstombs(buffer, *xdata, next_size + 1) < 0) {
				UxFree(buffer);
				*udata = NULL;
				return ERROR;
			}
			UxUpdateRotatingBuffer
			(&BufferIndex, &RotatingBuffer, buffer, UxFree);
			*udata = RotatingBuffer[BufferIndex];
		}
	}
	else if (flag == TO_X)
	{
		if (*udata == NULL)
			*xdata = NULL;
		else
		{
			int next_size = strlen(*udata);

			buffer = UxMalloc((next_size + 1) * sizeof(wchar_t));

			if (mbstowcs((wchar_t *)buffer, *udata, next_size + 1)
			    < 0) {
				UxFree(buffer);
				*xdata = NULL;
				return ERROR;
			}
			*xdata = (wchar_t *)buffer;
		}
	}
	else
	{
		UxStandardError
		(CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
		return ERROR;
	}
	return NO_ERROR;
}

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

static int string_Widget(sw, udata, xdata, flag)
swidget sw;
char **udata;
Widget *xdata;
int flag;
{
	int	isswidget;
	
  	if (flag == TO_UIMX)
	{
	    if (*xdata)
		*udata = XtName( *xdata );
	    else
		*udata = "";
	}
  	else if (flag == TO_X) 
	{
	    swidget	rs;

	    if (*udata == NULL)
		    return ERROR;
	    
	    isswidget = UxIsSwidget((swidget) *udata);
	    if ( ! isswidget && UxStrEqual (*udata, "")) {
		*xdata = NULL;
	    } else {
		rs = isswidget ? * (swidget*) udata 
			       : UxNameToSwidget (sw,*udata);   

#ifdef RUNTIME
    	        *xdata = rs ? UxGetWidget(rs) : NULL;
#else 
    	        *xdata = rs ? UxGetWidget(UxGetUserSwidget(rs)) : NULL;
#endif
		if (*xdata == NULL)
		    return ERROR;
	    }
  	} 
	else 
	{
    	    UxStandardError(CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
    	    return ERROR;
  	}
  	return NO_ERROR;
}

static int string_Window (sw, udata, xdata, flag)
swidget sw;
char	**udata;
Window	*xdata;
int	flag;
{
	Widget	w = NULL;

	if (flag == TO_UIMX)
	{
#ifdef RUNTIME
		w  = UxWindowToWidget(*xdata);
#else
		rswidget	*rs, *UxWindowToSwidget();

		rs = UxWindowToSwidget (*xdata);
		if ( rs != NULL )
			w = (Widget) UxGetWidget (rs);
#endif /* RUNTIME */

		if ( w != NULL )
			*udata = XtName( w );
		else
			*udata = "";
	}
	else if (flag == TO_X)
	{
		if (*udata == NULL || **udata == '\0') 
		{
			/* 
			 * Handle the default case. Note that string_Window
			 * converter is only used for the WindowGroup 
			 * resource.
			 */
			*xdata = XtUnspecifiedWindowGroup;
			return (NO_ERROR);
		} 
		else if (NO_ERROR == string_Widget (sw, udata, &w, flag)
		    && w != NULL)
		{
#ifdef RUNTIME
			/* set the window group flag if widget pointing
			   to itself  (see bug866) */

			char	*sw_name, *UxGetName();

			if((sw_name = UxGetName(sw)) &&
			(strcmp(sw_name,*udata) == 0))
				UxSwidgetSetWinGroupFlag(sw);
			else
				UxSwidgetUnsetWinGroupFlag(sw);
#endif /* RUNTIME */

			*xdata = XtWindow (w);
		}
		else
			return ERROR;
	}
	else
	{
		UxStandardError (CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
		return ERROR;
	}
        return NO_ERROR;
}

static int string_XID (sw, udata, xdata, flag)
swidget sw;
char	**udata;
XID	*xdata;
int	flag;
{
	return string_Window (sw, udata, xdata, flag);
}

/******************************************************************************
NAME:		static int	string_translations(sw, udata, xdata, flag)
INPUTS:		swidget		sw	- swidget
		char		**udata	- UIMX string
		char		**xdata	- pointer to X translation
		int		flag	- TO_UIMX or TO_X
RETURN:		ERROR/NO_ERROR
DESCRIPTION:	Converts a string to a translation.
CREATION:	???
REVISIONS:	20 July 90  [bug705]
                -- translations are char*, with hidden table name.
		July 12 1990
		-- check first if UxTStringForX() returns a valid value.
-----------------------------------------------------------------------------*/
static int string_translations(sw, udata, xdata, flag)
	swidget sw;
	char    **udata;
	char 	**xdata;
	int 	flag;
{

  	if (flag == TO_UIMX)
	{
	    /* can't do it */
    	    *udata = NULL;
	}
  	else if (flag == TO_X) 
	{
#ifndef RUNTIME
	    /* Make sure we strip the hidden name if any
	     * before passing the string to XtParse...
	     */
	    char	*trans;

	    trans = UxTStringForX(*udata,sw);
	    if (trans)
    	    	*xdata = (char *) XtParseTranslationTable(trans);
#else
            if(*udata)
                *xdata  = (char*) XtParseTranslationTable(*udata);

#endif /* ! RUNTIME */
	    else
    	    	return ERROR;
  	} 
	else 
	{
    	    UxStandardError(CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
    	    return ERROR;
  	}
  	return NO_ERROR;
}

/******************************************************************************
NAME:		static int	string_accelerators(sw, udata, xdata, flag)
INPUTS:		swidget		sw	- swidget
		char		**udata	- UIMX string
		char		**xdata	- Pointer to X translation
		int		flag	- TO_UIMX or TO_X
RETURN:		ERROR/NO_ERROR
DESCRIPTION:	Converts a string to a translation.
CREATION:	???
REVISIONS:	20 July 90  [bug705]
                -- translations are char*, with hidden table name.
		July 12 1990
		-- replace call to XtParseTranslationTable() by call to
		   XtParseAcceleratorTable() ... makes sense !
		   and verify return value from UxTStringForX().
-----------------------------------------------------------------------------*/
static int string_accelerators(sw, udata, xdata, flag)
	swidget sw;
	char    **udata;
	char 	**xdata;
	int 	flag;
{
  	if (flag == TO_UIMX)
	{
	    /* can't do it */
    	    *udata = NULL;
	}
  	else if (flag == TO_X) 
	{
#ifndef RUNTIME
	    char	*acc;

	    acc = UxTStringForX(*udata,sw);
	    if (acc)
    	    	*xdata = (char *) XtParseAcceleratorTable(acc);
#else
            if(*udata)
                *xdata = (char*) XtParseAcceleratorTable(*udata);

#endif /* ! RUNTIME */
	    else
		return ERROR;
  	} 
	else 
	{
    	    UxStandardError(CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
    	    return ERROR;
  	}
  	return NO_ERROR;
}

/******************************************************************************
NAME:		static	int	voidFunction_GenericProc(sw, udata, xdata, flag, func)
	swidget		sw;		- The swidget
	voidFunction	*udata;		- The UIM/X repository
	voidFunction	*xdata;		- The X repository
	int		flag;		- The direction flag (for conversion)
	voidFunction	func;		- The function to return.
RETURN:		ERROR NO_ERROR
DESCRIPTION:	This function was created in order to simplify the code. It
		is the same as the previous ones but they all call this one
		now. The new parameter was the only difference between the 
		functions.
CREATION:	January 29 1991		(bug2032)
REVISIONS:	
-----------------------------------------------------------------------------*/
/*
static int voidFunction_GenericProc(sw, udata, xdata, flag, func)
	swidget		sw;
	voidFunction	*udata;
	voidFunction	*xdata;
	int		flag;
	voidFunction	func;
{

  	if (flag == TO_UIMX)
	{
#ifdef RUNTIME
	    *udata = *xdata;
#else
	    /. never used ./
#endif /. RUNTIME ./
	}
  	else if (flag == TO_X) 
	{
#ifdef RUNTIME
	    *xdata = *udata;
#else
    	    *xdata = func;
#endif /. RUNTIME ./
  	} 
	else 
	{
    	    UxStandardError(CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
    	    return ERROR;
  	}

	return NO_ERROR;
}
*/
	
/******************************************************************************
NAME:	static int voidFunction_createPopupChildProc(sw, udata, xdata, flag)	
	swidget 	sw;	- The swidget
	voidFunction 	*udata;	- The UIM/X repository
	voidFunction 	*xdata;	- The X repository
	int 		flag;	- The direction flag
RETURN:		ERROR or NO_ERROR
DESCRIPTION:	
CREATION:	January 29 1991		(bug2032)
REVISIONS:	
-----------------------------------------------------------------------------*/

/*
static int voidFunction_createPopupChildProc(sw, udata, xdata, flag)
	swidget 	sw;
	voidFunction 	*udata;
	voidFunction 	*xdata;
	int 		flag;
	
{
	voidFunction	func;
#ifdef	RUNTIME
	func = ( voidFunction ) NULL;
#else
	func = ( voidFunction ) UxCreatePopupChildProc;
#endif
	return( voidFunction_GenericProc(sw, udata, xdata, flag, func));
}
*/

/******************************************************************************
NAME:	static int cardFunction_insertPosition(sw, udata, xdata, flag)
	swidget 	sw;	- The swidget
	voidFunction 	*udata;	- The UIM/X repository
	voidFunction 	*xdata;	- The X repository
	int 		flag;	- The direction flag
RETURN:		ERROR or NO_ERROR
DESCRIPTION:	
CREATION:	January 29 1991		(bug2032)
REVISIONS:	
-----------------------------------------------------------------------------*/

/*
static int cardFunction_insertPosition(sw, udata, xdata, flag)
	swidget 	sw;
	cardFunction 	*udata;
	cardFunction 	*xdata;
	int 		flag;
{
	voidFunction	func;
#ifdef	RUNTIME
	func = ( voidFunction ) NULL;
#else
	func = ( voidFunction ) UxInsertPosition;
#endif
	return( voidFunction_GenericProc(sw, udata, xdata, flag, func));
}
*/

/******************************************************************************
NAME:	static int voidFunction_fileSearchProc(sw, udata, xdata, flag)
	swidget 	sw;	- The swidget
	voidFunction 	*udata;	- The UIM/X repository
	voidFunction 	*xdata;	- The X repository
	int 		flag;	- The direction flag
RETURN:		ERROR or NO_ERROR
DESCRIPTION:	
CREATION:	January 29 1991		(bug2032)
REVISIONS:	
-----------------------------------------------------------------------------*/

/* 
static int voidFunction_fileSearchProc(sw, udata, xdata, flag)
	swidget 	sw;
	voidFunction 	*udata;
	voidFunction	*xdata;
	int 		flag;
{
	voidFunction	func;
#ifdef	RUNTIME
	func = ( voidFunction ) NULL;
#else
	func = ( voidFunction ) UxFileSearchProc;
#endif
	return( voidFunction_GenericProc(sw, udata, xdata, flag, func));
}
*/

/******************************************************************************
NAME:	static int voidFunction_dirSearchProc(sw, udata, xdata, flag)
	swidget 	sw;	- The swidget
	voidFunction 	*udata;	- The UIM/X repository
	voidFunction 	*xdata;	- The X repository
	int 		flag;	- The direction flag
RETURN:		ERROR or NO_ERROR
DESCRIPTION:	
CREATION:	January 29 1991		(bug2032)
REVISIONS:	
-----------------------------------------------------------------------------*/

/* 
static int voidFunction_dirSearchProc(sw, udata, xdata, flag)
	swidget 	sw;
	voidFunction 	*udata;
	voidFunction	*xdata;
	int 		flag;
{
	voidFunction	func;
#ifdef	RUNTIME
	func = ( voidFunction ) NULL;
#else
	func = ( voidFunction ) UxDirSearchProc;
#endif
	return( voidFunction_GenericProc(sw, udata, xdata, flag, func));
}
*/

/******************************************************************************
NAME:	static int voidFunction_qualifySearchDataProc(sw, udata, xdata, flag)
	swidget 	sw;	- The swidget
	voidFunction 	*udata;	- The UIM/X repository
	voidFunction 	*xdata;	- The X repository
	int 		flag;	- The direction flag
RETURN:		ERROR or NO_ERROR
DESCRIPTION:	
CREATION:	January 29 1991		(bug2032)
REVISIONS:	
-----------------------------------------------------------------------------*/

/*
static int voidFunction_qualifySearchDataProc(sw, udata, xdata, flag)
	swidget 	sw;
	voidFunction 	*udata;
	voidFunction	*xdata;
	int 		flag;
{
	voidFunction	func;
#ifdef	RUNTIME
	func = ( voidFunction ) NULL;
#else
	func = ( voidFunction ) UxQualifySearchDataProc;
#endif
	return( voidFunction_GenericProc(sw, udata, xdata, flag, func));
}
*/

/* ---------------------------------------------------------------------------
NAME:		int UxCallConverter(sw, utype, udata, xtype, xdata, flag)
INPUT:		swidget sw	-- swidget
		int utype	-- Uimx type id
		char **udata	-- Address for uimx data
		int xtype	-- X type id
		char *xdata	-- Address for X data
		int flag	-- TO_X / TO_UIMX flag
RETURNS:	ERROR/NO_ERROR
DESCRIPTION:	Calls the converter needed to convert data between
	 	uimx and x types. The flag determines the direction
		of the conversion.
		
CREATION:       Apr 19 1988  Visual Edge Software
LAST REV:	Jan 09 1993  Name Changed.
---------------------------------------------------------------------------*/
int UxCallConverter(sw, utype, udata, xtype, xdata, flag)
	swidget sw;
	int utype;
	char **udata;
	int xtype;
	char *xdata;
	int flag;
{
	/* Simply look up the conversion routine and call it */
	_utype = utype;
	_xtype = xtype;
	if (UxUimx_x[utype][xtype])
		return (UxUimx_x[utype][xtype])(sw, udata, xdata, flag, xtype);
	
	if (flag == TO_UIMX)
	  UxInternalError(__FILE__, __LINE__,
		CGETS( MS_MISC_NO_CONV_ROUTINE,DS_MS_MISC_NO_CONV_ROUTINE),
		x_name(xtype), u_name(utype));
	else
	  UxInternalError(__FILE__, __LINE__,
		CGETS( MS_MISC_NO_CONV_ROUTINE,DS_MS_MISC_NO_CONV_ROUTINE),
		u_name(utype), x_name(xtype));

	return ERROR;
}

/* ---------------------------------------------------------------------------
NAME:		int UxUimx_to_x(sw, utype, udata, xtype, xdata, flag)
INPUT:		swidget sw	-- swidget
		int utype	-- Uimx type id
		char **udata	-- Address for uimx data
		int xtype	-- X type id
		char *xdata	-- Address for X data
		int flag	-- TO_X / TO_UIMX flag
RETURNS:	ERROR/NO_ERROR
DESCRIPTION:	Wrapper function for UxCallConverter(). Exists strictly
		for backward compatibility purposes. 
		
CREATION:       Jan 93	fix3820	   UxUimx_to_x renamed UxCallConverter
---------------------------------------------------------------------------*/
int UxUimx_to_x(sw, utype, udata, xtype, xdata, flag)
	swidget sw;
	int utype;
	char **udata;
	int xtype;
	char *xdata;
	int flag;
{
	return UxCallConverter(sw, utype, udata, xtype, xdata, flag);
}

/*----------------------------------------------------------------------
 * NAME:	< static int string_SelectionArray (sw, udata, xdata, flag, 
		  XT_type>
 * DESCRIPTION:	< For the TO_UIMX case,
   a rotating buffer will contain the strings. For the first pass, the buffer
   is filled up to its size and for the subsequent strings to be stored, the
   location is first reallocated before the new string takes its place.
   Every time the buffer index reaches the size of the buffer, it is reset
   to 0 to create the rotating buffer. This way, we avoid system crashes
   because the pointer will always point to valid memory addresses but
   the memory content may not be the right one if the user waited too long
   (more than "size of buffer" calls to this converter) before using the value
   returned. >
 * PARAMETERS: 
		swidget		sw		- swidget
		char		**udata		- UIMX string representation
		XmTextScanType	*xdata		- XmTextScanType Xm enum array
		int		flag		- TO_UIMX or TO_X
		int		XT_type		- the type identifier
 * RETURN:	ERROR/NO_ERROR	
 * EXT REFS:	globals_used
 * EXT EFFECTS:	globals or other things altered
 * ASSUMPTIONS:
 * REVISIONS: 	04/07/89	creation	
		xx/05/92	fix3571	runtime library rewrite
		19/11/92	fix3723	fix memory leak calling UxUpdateRotating
					Buffer for TO_UIMX case	
		01/12/92	fix3749	fix memory leak TO_X case
 *--------------------------------------------------------------------*/
static	int	string_SelectionArray(sw, udata, xdata, flag, XT_type)
	swidget 	sw;
	char		**udata;
	XmTextScanType	**xdata;
	int		flag;
	int		XT_type;
{
	int		i, match, err = 0;
	char 		**uconv = UxStr_conv[XT_type].strings;
	XmTextScanType 	*xconv = (XmTextScanType *) UxStr_conv[XT_type].values;
	int		n = UxStr_conv[XT_type].size;
        static char **RotatingBuffer;
        static int BufferIndex = -1;

	if (flag == TO_UIMX)
	{
	    Arg     a[1];
	    Widget  w;
	    int     count;
	    char    *s=0;

	    /* get the current size of the selection array */

	    w = UxGetWidget(sw);

	    if (!w)
	    {	
		*udata = "";
		return NO_ERROR;
	    }

	    XtSetArg(a[0], "selectionArrayCount", &count);
	    XtGetValues(w, a, 1);

	    if (count == 0)
	    {	
		*udata = "";
		return NO_ERROR;
	    }

	    /* assemble the uimx strings into one string, separated by	*/
	    /* spaces							*/
	    
	    for (i=0; i<count; i++)
	    {
		XmTextScanType	val;
		int		j, match;

		val = (*xdata)[i];

		/* search the xconv array for the current array element */
		/* if it is found, concatenate the corresponding uconv  */
		/* element onto the output string 			*/

		match = 0;
		for (j=0; j<n; j++)
		{
		    if (val == xconv[j])
		    {
			match = 1;
			if (s)
			{
			    s = UxRealloc(s, strlen(s) + strlen(uconv[j]) + 2);
			    strcat(s, " ");
			    strcat(s, uconv[j]);
			}
			else
			{
			    s = UxMalloc(strlen(uconv[j]) + 1);
			    strcpy(s, uconv[j]);
			}
			break;
		    }
		}

		/* if the current array element was not found in the xconv */
		/* array, then it is invalid, and we return an error       */

		if (!match)
		{
		    /* the ith element of the array is invalid; we free the */
		    /* string allocated so far and set the output to ""     */
		    if (s)
			UxFree(s);
	            *udata = "";
	    	    return ERROR;
	 	}
	    }
	
	    UxUpdateRotatingBuffer(&BufferIndex, &RotatingBuffer, s, UxFree);
	    *udata = RotatingBuffer[BufferIndex];
	    return NO_ERROR;
	}
	else if (flag == TO_X)
	{
	    char *c1;
	    char *c2;
	    char *temp;
	    XmTextScanType array[20];
	    int array_length;

	    /* protect strlen from NULL */
	    if (!*udata) return ERROR;

	    /* create temp copy of string to parse... */
	    temp = XtMalloc(strlen(*udata) + 1);
	    (void) strcpy(temp, *udata);
	    c1 = temp;

	    for (array_length = 0; *c1 &&
		    (array_length < (sizeof(array) / sizeof(array[0]))); )
	    {
		/* skip over leading whitespace... */
		while (isspace(*c1))
		    (void) c1++;

		/* skip to end of string... */
		c2 = c1;
		while (*c2 && !isspace(*c2))
		    (void) c2++;

		/* null terminate this chunk... */
		if (*c2)
		    *c2++ = '\0';

		/* find a match... */
		for (i = 0, match = 0; i < n; i++)
		{
		    if (strcmp(c1, uconv[i]) == 0)
		    {
			match = 1;
			break;
		    }
		}
		if (match)
		    array[array_length++] = xconv[i];
		else
		    err = 1;

		/* move to start of next chunk... */
		c1 = c2;
	    }
	    if (array_length > 0) {
		/* create a return table.  This is a memory leak, but normally
		 * this is only created once per widget...
		 */
		*xdata = (XmTextScanType *)
			XtMalloc((unsigned) (array_length * sizeof(array[0])));
		(void) memcpy(*xdata, array, array_length * sizeof(array[0]));
	    } else {
		*xdata = (XmTextScanType *) NULL;
	    }

	    /* now we can free the temp buffer... */
	    XtFree(temp);
	}
	else
	{
	    UxStandardError(CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
	    return ERROR;
	}
	if (!err)
	    return NO_ERROR;
	else
	{
	    UxStandardError(CGETS( MS_MISC_NO_MATCH, DS_MS_MISC_NO_MATCH));
	    return ERROR;
	}
}

/******************************************************************************
NAME:		static int		string_WidgetClass ()
INPUTS:		char		**udata	- UIMX string
		WidgetClass	*xdata	- WidgetClass pointer
		int		flag	- TO_UIMX or TO_X
RETURN:		ERROR/NO_ERROR
DESCRIPTION:	Converts a string to a WidgetClass pointer.
CREATION:	Jun 30/1989
REVISIONS:	July 12 1990
		-- previous converter used to convert only one class.
		   Made the converter general.
                July 29 1990
                   change to static function 
		August 06 1990
		-- converter uses now 2 static arrays to do the conversion
-----------------------------------------------------------------------------*/

static int	string_WidgetClass (sw, udata, xdata, flag)
swidget sw;
char		**udata;
WidgetClass	*xdata;
int		flag;
{
	int i;
	static char *uWidgetClass[] = {
		"arrowButtonGadget",
		"arrowButton",
		"bulletinBoard",
		"cascadeButtonGadget",
		"cascadeButton",
		"command",
		"drawingArea",
		"drawnButton",
		"fileSelectionBox",
		"form",
		"frame",
		"labelGadget",
		"label",
		"list",
		"mainWindow",
		"messageBox",
		"panedWindow",
		"pushButtonGadget",
		"pushButton",
		"rowColumn",
		"scale",
		"scrollBar",
		"scrolledWindow",
		"selectionBox",
		"separatorGadget",
		"separator",
		"text",
		"textField",
		"toggleButtonGadget",
		"toggleButton"
	};

	static WidgetClass *xWidgetClass[]= {
		&xmArrowButtonGadgetClass,
		&xmArrowButtonWidgetClass,
		&xmBulletinBoardWidgetClass,
		&xmCascadeButtonGadgetClass,
		&xmCascadeButtonWidgetClass,
		&xmCommandWidgetClass,
		&xmDrawingAreaWidgetClass,
		&xmDrawnButtonWidgetClass,
		&xmFileSelectionBoxWidgetClass,
		&xmFormWidgetClass,
		&xmFrameWidgetClass,
		&xmLabelGadgetClass,
		&xmLabelWidgetClass,
		&xmListWidgetClass,
		&xmMainWindowWidgetClass,
		&xmMessageBoxWidgetClass,
		&xmPanedWindowWidgetClass,
		&xmPushButtonGadgetClass,
		&xmPushButtonWidgetClass,
		&xmRowColumnWidgetClass,
		&xmScaleWidgetClass,
		&xmScrollBarWidgetClass,
		&xmScrolledWindowWidgetClass,
		&xmSelectionBoxWidgetClass,
		&xmSeparatorGadgetClass,
		&xmSeparatorWidgetClass,
		&xmTextWidgetClass,
		&xmTextFieldWidgetClass,
		&xmToggleButtonGadgetClass,
		&xmToggleButtonWidgetClass,
	};
	

	if (flag == TO_UIMX)
	{
		if (*xdata)
		{
			int num = XtNumber(uWidgetClass);
			char *pntr;
			char *wclass;

			pntr = (char *)
			    UxMalloc(strlen((*xdata)->core_class.class_name)+1);

			strcpy(pntr, (*xdata)->core_class.class_name);
			wclass = pntr;
			if ((pntr[0] == 'X') && (pntr[1] == 'm'))
			{
				pntr[2] = tolower(pntr[2]);
				wclass = &pntr[2];
			}

			for (i=0; i < num; i++)
			{

			   if (strcmp(uWidgetClass[i], wclass) == 0)
			   {
				*udata = uWidgetClass[i];
				break;
			   }
			}
			UxFree(pntr);
		}
		else
		{
			*udata = "";
		}
	}
	else if (flag == TO_X)
	{
		int num = XtNumber(uWidgetClass);

		if (!strcmp(*udata, ""))
		{
			*xdata = (WidgetClass) NULL;
		}

		*xdata = (WidgetClass) NULL;
		for (i=0; i < num; i++)
		{
			if (strcmp(uWidgetClass[i], *udata) == 0)
			{
				*xdata = *xWidgetClass[i];
				break;
			}
		}
	}
	else
	{
		UxStandardError (CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
		return ERROR;
	}
	return NO_ERROR;
}

/******************************************************************************
NAME:		int		int_Position (sw, udata, xdata, flag)
INPUT:		swidget		sw		- swidget
		int		*udata		- uimx value int address
		Position	*xdata		- x value Position address
		int		flag		- TO_UIMX or TO_X
RETURN:		ERROR/NO_ERROR
DESCRIPTION:	Converts int <--> Position representations.
		In MOTIF 1.1, Position is the standard Xt typedef of short.
-----------------------------------------------------------------------------*/

static	int	int_Position(sw, udata, xdata, flag)
swidget sw;
int	 *udata;
Position *xdata;
int	flag;
{
	if (flag == TO_UIMX) {
		*udata = (int) *xdata;
	} else if (flag == TO_X) {
		*xdata = (Position) *udata;
	} else {
		UxStandardError(CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
		return ERROR;
	}
	return NO_ERROR;
}

/******************************************************************************
NAME:		int		long_Colormap (sw, udata, xdata, flag)
INPUT:		swidget		sw		- swidget
		long		*udata		- uimx value long address
		Colormap	*xdata		- x value Colormap address
		int		flag		- TO_UIMX or TO_X
RETURN:		ERROR/NO_ERROR
DESCRIPTION:	Converts long <--> Colormap representations.
-----------------------------------------------------------------------------*/

static	int	long_Colormap(sw, udata, xdata, flag)
swidget sw;
long	  *udata;
Colormap *xdata;
int	flag;
{
	if (flag == TO_UIMX) {
		*udata = (long) *xdata;
	} else if (flag == TO_X) {
		*xdata = (Colormap) *udata;
	} else {
		UxStandardError(CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
		return ERROR;
	}
	return NO_ERROR;
}

/******************************************************************************
NAME:		int		int_Dimension (sw, udata, xdata, flag)
INPUT:		swidget		sw		- swidget
		int		*udata		- uimx value int address
		Dimension	*xdata		- x value Dimension address
		int		flag		- TO_UIMX or TO_X
RETURN:		ERROR/NO_ERROR
DESCRIPTION:	Converts int <--> Dimension representations.
		In MOTIF 1.1, Dimension is the standard Xt typedef of ushort
-----------------------------------------------------------------------------*/

static	int	int_Dimension(sw, udata, xdata, flag)
swidget sw;
int	  *udata;
Dimension *xdata;
int	flag;
{
	if (flag == TO_UIMX) {
		*udata = (int) *xdata;
	} else if (flag == TO_X) {
		*xdata = (Dimension) *udata;
	} else {
		UxStandardError(CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
		return ERROR;
	}
	return NO_ERROR;
}

/******************************************************************************
NAME:		int		int_short (sw, udata, xdata, flag)
INPUT:		swidget		sw		- swidget
		int		*udata		- uimx value short address
		short		*xdata		- x value int address
		int		flag		- TO_UIMX or TO_X
RETURN:		ERROR/NO_ERROR
DESCRIPTION:	Converts int <--> short representations.
CREATION:	2 Apr 90
REVISIONS:	--
-----------------------------------------------------------------------------*/

static	int	int_short(sw, udata, xdata, flag)
swidget sw;
int	*udata;
short	*xdata;
int	flag;
{
	if (flag == TO_UIMX)
		*udata = *xdata;
	else if (flag == TO_X)
		*xdata = *udata;
	else
	{
		UxStandardError (CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
		return ERROR;
	}
	return NO_ERROR;
}

/******************************************************************************
NAME:		int		short_int (sw, udata, xdata, flag)
INPUT:		swidget		sw		- swidget
		short		*udata		- uimx value short address
		int		*xdata		- x value int address
		int		flag		- TO_UIMX or TO_X
RETURN:		ERROR/NO_ERROR
DESCRIPTION:	Converts short <--> int representations.
CREATION:	2 Apr 90
REVISIONS:	--
-----------------------------------------------------------------------------*/

static	int	short_int(sw, udata, xdata, flag)
swidget sw;
short	*udata;
int	*xdata;
int	flag;
{
	if (flag == TO_UIMX)
		*udata = *xdata;
	else if (flag == TO_X)
		*xdata = *udata;
	else
	{
		UxStandardError (CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
		return ERROR;
	}
	return NO_ERROR;
}


/*----------------------------------------------------------------------
 * NAME:	< int string_Atom (sw, udata, xdata, flag)>
 * DESCRIPTION:	< Converts Atom -- String representations. For the TO_UIMX case,
   a rotating buffer will contain the strings. For the first pass, the buffer
   is filled up to its size and for the subsequent strings to be stored, the
   location is first reallocated before the new string takes its place.
   Every time the buffer index reaches the size of the buffer, it is reset
   to 0 to create the rotating buffer. This way, we avoid system crashes
   because the pointer will always point to valid memory addresses but
   the memory content may not be the right one if the user waited too long
   (more than "size of buffer" calls to this converter) before using the value
   returned.> 
 * PARAMETERS: 
		swidget		sw		- swidget
		char 		**udata		- uimx value char * address
		Atom		*xdata		- x value Atom address
		int		flag		- TO_UIMX or TO_X
 * RETURN:	ERROR/NO_ERROR	
 * EXT REFS:	globals_used
 * EXT EFFECTS:	globals or other things altered
 * ASSUMPTIONS:
 * LAST REVISION: March 15, 1993	Test for invalid zero value Atom
 *--------------------------------------------------------------------*/
static	int	string_Atom(sw, udata, xdata, flag)
swidget sw;
char	**udata;
Atom *xdata;
int	flag;
{
	if (flag == TO_UIMX) {
		char *atom_name;
		static char **RotatingBuffer;
		static int BufferIndex = -1;

		if (*xdata) {
			atom_name = XGetAtomName(UxDisplay, *xdata);
        		UxUpdateRotatingBuffer
			(&BufferIndex, &RotatingBuffer, atom_name,(func_ptr) XFree);
        		*udata = RotatingBuffer[BufferIndex];
		}
		else
        		*udata = "";
	} 
	else if (flag == TO_X) 
	{
		/* Create the atom if it does not exist */
		*xdata = XInternAtom(UxDisplay, *udata, False);
	} 
	else {
		UxStandardError(CGETS( MS_MISC_WRONG_FLAG, 
				       DS_MS_MISC_WRONG_FLAG));
		return ERROR;
	}
	return NO_ERROR;
}
/******************************************************************************
NAME:		int		string_Keysym (sw, udata, xdata, flag)
INPUT:		swidget		sw		- swidget
		char		**udata		- string representation
		char		*xdata		- character representation
		int		flag		- TO_UIMX or TO_X
RETURN:		ERROR/NO_ERROR
DESCRIPTION:	Converts string <--> keysym representations.
CREATION:	November 05 1990
REVISIONS:	July 30, 1991		(fix2773)
		- Don't allow NULL as udata and convert NULL xdata to "".
-----------------------------------------------------------------------------*/

static	int	string_Keysym (sw, udata, xdata, flag)
    swidget 	sw;
    char	**udata;
    KeySym	*xdata;
    int		flag;
{
	if (flag == TO_UIMX)
	{
		if (*xdata == NoSymbol)
		{
			*udata = "";
		}
		else if ((*udata = XKeysymToString (*xdata)) == NULL)
		{
			*udata = "";
			return ERROR;
		}
	}
	else if (flag == TO_X)
	{
		if (*udata == NULL)
		    return ERROR;

		if (UxStrEqual (*udata, "")) {
			*xdata = NoSymbol;
		} else {
			*xdata = XStringToKeysym (*udata);
			if (*xdata == NoSymbol)
				return ERROR;
		}
	}
	else
	{
		UxStandardError (CGETS( MS_MISC_WRONG_FLAG, 
					DS_MS_MISC_WRONG_FLAG));
		return ERROR;
	}
	return NO_ERROR;
}


/******************************************************************************
NAME:		Boolean		UxFontListCreate ( udata, xdata)
INPUT:		char		*udata		- string representation
		XmFontList	*xdata		- Motif XmFontList structure
RETURN:		True/False			- if succeeded
DESCRIPTION:	This will convert from a string representation into a
		XmFontList.

		The caller should not call XmFontListFree on the returned
		value.

CREATION:	3 Avril 1992
-----------------------------------------------------------------------------*/

Boolean
UxFontListCreate( udata, xdata)
char *udata;
XmFontList *xdata;
{
	XrmValue    from, to;
	from.size = strlen( udata ) + 1;
	from.addr = udata;
	to.size = sizeof(XmFontList);
	to.addr = (caddr_t) xdata ;
	return( XtConvertAndStore( UxTopLevel, XmRString, &from,
		XmRFontList, &to));
}


/*----------------------------------------------------------------------
 * NAME:	<int string_XmFontList (sw, udata, xdata, flag)>
 * DESCRIPTION:	<Performs the conversion from a font name to a Motif XmFontList
   and the reverse. A rotating buffer of strings is supported for the TO_UIMX 
   case.
   A rotating buffer will contain the strings. For the first pass, the buffer
   is filled up to its size and for the subsequent strings to be stored, the
   location is first reallocated before the new string takes its place.
   Every time the buffer index reaches the size of the buffer, it is reset
   to 0 to create the rotating buffer. This way, we avoid system crashes
   because the pointer will always point to valid memory addresses but
   the memory content may not be the right one if the user waited too long
   (more than "size of buffer" calls to this converter) before using the value
   returned.> 
 * PARAMETERS: 
		swidget		sw		- swidget
		char		**udata	- string representation
		XmFontList	*xdata	- Motif XmFontList structure
		int		flag		- TO_UIMX or TO_X
 * RETURN: 	ERROR/NO_ERROR	
 * EXT REFS:	globals_used
 * EXT EFFECTS:	globals or other things altered
 * ASSUMPTIONS:
 * REVISIONS:	04/07/89	creation	
				03/01/91	Motif 1.1 modifications in font struct.
				07/12/92	fix3767	support Motif 1.2	
				20/08/93	fix4447	Correct UxGet...
 *--------------------------------------------------------------------*/
static	int	string_XmFontList (sw, udata, xdata, flag)
swidget 	sw;
char		**udata;
XmFontList	*xdata;
int		flag;
{
	if (flag == TO_UIMX)
	{
		XFontStruct     *font_struct;
		XFontSet        font_set;
		XmFontListEntry font_list_entry;
		XmFontType      type_ret;
		XtPointer       font_or_fontset;
		unsigned long   *ret;
		XmFontContext   fc;
		char *font_tag;
		int len;
		char *font = "";
		char *ListOfFonts = NULL;
		char *PtrInList;
		static char **RotatingBuffer;
		static int BufferIndex = -1;

		if (*xdata)
		{
			if (!XmFontListInitFontContext (&fc, *xdata))
			{
				UxStandardError (CGETS( MS_MISC_WRONG_FLAG,
						DS_MS_MISC_WRONG_FLAG));
				return ERROR ;
			}
			
			while ((font_list_entry = XmFontListNextEntry (fc)) != NULL)
			{
				font_or_fontset = XmFontListEntryGetFont(font_list_entry, 
												&type_ret);
				if (type_ret == XmFONT_IS_FONT)
				{	
					font_struct = (XFontStruct *) font_or_fontset;
					XGetFontProperty(font_struct, XA_FONT, (unsigned long*)&ret);
					font = XGetAtomName(UxDisplay, (Atom)ret);
				}
				else if (type_ret == XmFONT_IS_FONTSET)
				{
					char * comma;
					font_set = (XFontSet) font_or_fontset;
					font = XBaseFontNameListOfFontSet(font_set);
					comma = font;
					while ((comma = strpbrk(comma,",")))
					{
						*comma++ = ';';
					}
				}

				if (ListOfFonts == NULL)
				{
					ListOfFonts = UxMalloc(strlen(font) + 1);
					PtrInList = ListOfFonts;
				}
				else
				{
					len = strlen(ListOfFonts);
					ListOfFonts = UxRealloc(ListOfFonts, len + strlen(font) + 2);
					PtrInList = &ListOfFonts[len];
					*PtrInList++ = ',';
				}
				strcpy(PtrInList, font);

				font_tag = XmFontListEntryGetTag(font_list_entry);
				len = strlen(ListOfFonts);
				if (font_tag)
				{
					ListOfFonts = UxRealloc(ListOfFonts, len + strlen(font_tag) + 2);
					PtrInList = &ListOfFonts[len];
					if (type_ret == XmFONT_IS_FONT)
						*PtrInList++ = '=';
					else if (type_ret == XmFONT_IS_FONTSET)
						*PtrInList++ = ':';
					strcpy(PtrInList, font_tag);
					XtFree(font_tag);
				}
				else if (type_ret == XmFONT_IS_FONTSET)
				{
					ListOfFonts = UxRealloc(ListOfFonts, len + 2);
					PtrInList = &ListOfFonts[len];
					*PtrInList++ = ':';
				}

				/* the value returned by XGetAtomName() has to be freed but not
		   		   the one returned by XBaseFontNameListOfFontSet() */
				if (type_ret == XmFONT_IS_FONT)
					XFree(font);
			} 	
	
			XmFontListFreeFontContext (fc);

			/* if it is NULL, the first call to XmFontListNextEntry() returned
			   NULL and we don't have a font list */
			if (ListOfFonts)
			{	
       			UxUpdateRotatingBuffer(&BufferIndex, &RotatingBuffer, 
										ListOfFonts, UxFree);
        		*udata = RotatingBuffer[BufferIndex];
				return NO_ERROR;
			}
			else
			{
				UxStandardError (CGETS( MS_MISC_WRONG_FLAG,
						DS_MS_MISC_WRONG_FLAG));
				return ERROR ;
			}
		} 
	    *udata = "";	/* CAN'T CONVERT TO UIMX */
	} 

	else if (flag == TO_X)
	{
	    if (!strcmp(*udata, ""))
	    	*xdata = (XmFontList)NULL;
	    else
	    {
	    if (!UxFontListCreate( *udata, xdata))
	        *xdata = (XmFontList)NULL;
	    }
	}

	else
	{
		UxStandardError (CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
		return ERROR;
	}
	return NO_ERROR;
}


/*----------------------------------------------------------------------
 * NAME:	<int string_XmString (sw, udata, xdata, flag)>
 * DESCRIPTION:	<Performs a fixed conversion of strings. For the TO_UIMX case,
                a rotating buffer of strings is supported.
   A rotating buffer will contain the strings. For the first pass, the buffer
   is filled up to its size and for the subsequent strings to be stored, the
   location is first reallocated before the new string takes its place. 
   Every time the buffer index reaches the size of the buffer, it is reset 
   to 0 to create the rotating buffer. This way, we avoid system crashes
   because the pointer will always point to valid memory addresses but
   the memory content may not be the right one if the user waited too long
   (more than "size of buffer" calls to this converter) before using the 
   value returned.> 
 * PARAMETERS: 
		swidget		sw		- swidget
		char		**udata		- string representation
		XmString	*xdata		- Motif XmString representation
		int		flag		- TO_UIMX or TO_X
 * RETURN:	ERROR/NO_ERROR	
 * EXT REFS:	globals_used
 * EXT EFFECTS:	globals or other things altered
 * ASSUMPTIONS:
 * REVISIONS:	04/07/89	creation	
	        HP              Mar 22/1990
                Apr 11/1990
                -- had to add a kludge to check if we are the end of the
                XmString, because there is a motif bug which allows the call to
                'XmStringGetNextComponent()' to read past the end of the string
		Aug 2/1990
			- check for NULL string (no useful components) and
			  return "" instead.
		Jan 03 1991	bug1065
		-- Porting to Motif 1.1
		8 Jan 91	byug1089
		-- Motif 1.1: strcmp test for DEFAULT_CHARSET
		dd/mm/yy	fix#	fix_description
 *--------------------------------------------------------------------*/
static	int	string_XmString (sw, udata, xdata, flag)
swidget sw;
char		**udata;
XmString	*xdata;
int		flag;
{
	if (flag == TO_UIMX)
	{
		char *txt;
		XmStringComponentType type;
		XmStringContext context;
		XmStringCharSet charset;
		XmStringDirection direction;
		XmStringComponentType unknown_tag;
		unsigned short unknown_length;
		unsigned char *unknown_value;
		int ignore_strings = False; /* give the benifit of the doubt */
		char *c1 = NULL;
		char *c2;
		static char **RotatingBuffer;
		static int BufferIndex = -1;

		if (!XmStringInitContext(&context, *xdata))
		    *udata = "";
		else {
		    while (XmSTRING_COMPONENT_END != (type =
			    XmStringGetNextComponent(context,
			    &txt, &charset, &direction, &unknown_tag,
			    &unknown_length, &unknown_value))) {
			switch (type) {

			case XmSTRING_COMPONENT_CHARSET:

			    /* We need more work here to decide how
			     * to deal with non-default charsets.
			     * In 1.1, a lot of XmStrings have
			     * charset "ISO8859-1".
			     * For the moment, we accumulate all text,
			     * no matter what the charset,
			     * by setting ignore_strings always to false.
			     * We still identify DEFAULT_CHARSET components
			     * so we can free the other charset names.
			     */
#if !defined(HP)
			    /* The standard Motif distribution uses
 			     *   #define XmSTRING_DEFAULT_CHARSET ""
			     * so equality testing doesn't work.
			     */
			    if (charset
				&& !strcmp(charset,XmSTRING_DEFAULT_CHARSET))
#else
			    /* The HP distribution uses 
			     *   extern char* XmSTRING_DEFAULT_CHARSET
			     * so we can test for pointer equality (much faster)
			     */
			    if (charset ==
				     (XmStringCharSet) XmSTRING_DEFAULT_CHARSET)
#endif /* !defined(HP) */
			    {
				ignore_strings = False;
			    } else {
				ignore_strings = False;
				/* If it is not DEFAULT_CHARSET, then we
				 * need to free it.  If it is DEFAULT_CHARSET,
				 * then we must not free it.
				 */
				XtFree((char *) charset);
			    }
			    break;
			case XmSTRING_COMPONENT_LOCALE_TEXT:
			case XmSTRING_COMPONENT_TEXT:
			    if (ignore_strings)
				break;
			    if (c1) {
				/* concatenate the 2 strings...
				 */
				c2 = XtMalloc(strlen(c1) + strlen(txt) + 1);
				(void) strcpy(c2, c1);
				(void) strcat(c2, txt);
				(void) XtFree(c1);
				c1 = c2;
				(void) free(txt);
			    } else {
				/* txt was XtMalloc'ed by
				 * XmStringGetNextComponent, so we don't need
				 * to recreate it (we will need to free it
				 * though)...
				 */
				c1 = txt;
			    }
			    break;

			case XmSTRING_COMPONENT_SEPARATOR:
			    if (c1) {
				/* append a '\n' as the separator just like
				 * XmStringCreateLtoR does...
				 */
				c2 = XtMalloc(strlen(c1) + strlen("\n") + 1);
				(void) strcpy(c2, c1);
				(void) strcat(c2, "\n");
				(void) XtFree(c1);
				c1 = c2;
			    } else {
				/* create the initial string of "\n"...
				 */
				c1 = XtMalloc(strlen("\n") + 1);
				(void) strcpy(c1, "\n");
			    }
			    break;

			default:
			    /* ignore everything else...
			     */
			    break;
			}
		    }

		UxUpdateRotatingBuffer(&BufferIndex, 
			         	&RotatingBuffer, c1, XtFree);
		*udata = RotatingBuffer[BufferIndex];
		(void) XmStringFreeContext(context);
		}
	}
	else if (flag == TO_X)
	{
		*xdata = XmStringLtoRCreate (*udata, XmSTRING_DEFAULT_CHARSET);
	}
	else
	{
		UxStandardError (CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
		return ERROR;
	}
	return NO_ERROR;
}

/******************************************************************************
NAME:		int		string_HistoryItems(sw, udata, xdata, flag)
		int		string_Items(sw, udata, xdata, flag)
     		int		string_ListItems(sw, udata, xdata, flag)
     		int		string_SelectedItems(sw, udata, xdata, flag)
     		int		string_DirListItems(sw, udata, xdata, flag)
     		int		string_FileListItems(sw, udata, xdata, flag)
INPUT:		swidget		sw		- swidget
		char		**udata		- string representation
		XmString	**xdata		- Motif StringTable
		int		flag		- TO_UIMX or TO_X
RETURN:		ERROR/NO_ERROR
DESCRIPTION:	Uses the resource converter to convert between a string table
		represented as a single string with entries separated by
		commas, and a Motif XmStringTable. 
CREATION:	18 April 1990
REVISION:	29 Janvier 1991
		-- Added new conversion routines for dirListItems and
		fileListItems.
-----------------------------------------------------------------------------*/


static	int	string_HistoryItems(sw, udata, xdata, flag)
	swidget   sw;
	char	  **udata;
	XmString  **xdata;
	int	  flag;
{
	return string_XmStringTable(XmNhistoryItemCount,sw, udata, xdata, flag);
}

static	int	string_Items(sw, udata, xdata, flag)
	swidget   sw;
	char	  **udata;
	XmString  **xdata;
	int	  flag;
{
	return string_XmStringTable(XmNitemCount, sw, udata, xdata, flag);
}

static	int	string_ListItems(sw, udata, xdata, flag)
	swidget   sw;
	char	  **udata;
	XmString  **xdata;
	int	  flag;
{
	return string_XmStringTable(XmNlistItemCount, sw, udata, xdata, flag);
}

static	int	string_SelectedItems(sw, udata, xdata, flag)
	swidget   sw;
	char	  **udata;
	XmString  **xdata;
	int	  flag;
{
	return string_XmStringTable(XmNselectedItemCount,sw,udata, xdata, flag);
}

static	int	string_FileListItems(sw, udata, xdata, flag)
	swidget   sw;
	char	  **udata;
	XmString  **xdata;
	int	  flag;
{
	return string_XmStringTable(XmNfileListItemCount, sw, udata, xdata, flag);
}

static	int	string_DirListItems(sw, udata, xdata, flag)
	swidget   sw;
	char	  **udata;
	XmString  **xdata;
	int	  flag;
{
	return string_XmStringTable(XmNdirListItemCount, sw, udata, xdata, flag);
}


/*----------------------------------------------------------------------
 * NAME:	<int     string_XmStringTable(pname, sw, udata, xdata, flag)>
 * DESCRIPTION: <Uses the resource converter to convert between a string table
                represented as a single string with entries separated by 
                commas, and a Motif XmStringTable. For the TO_UIMX case, 
   a rotating buffer will contain the strings. For the first pass, the buffer
   is filled up to its size and for the subsequent strings to be stored, the
   location is first reallocated before the new string takes its place. 
   Every time the buffer index reaches the size of the buffer, it is reset 
   to 0 to create the rotating buffer. This way, we avoid system crashes
   because the pointer will always point to valid memory addresses but
   the memory content may not be the right one if the user waited too long
   (more than "size of buffer" calls to this converter) before using the value
   returned.> 
 * PARAMETERS: 
		char		*pname		- the XmN property name
		swidget		sw		- swidget
		char		**udata		- string representation
		XmString	**xdata		- Motif StringTable
		int		flag		- TO_UIMX or TO_X
 *		parameter	[I|I/O|O]	parameter_description
 * RETURN:	ERROR/NO_ERROR	
 * EXT REFS:	globals_used
 * EXT EFFECTS:	globals or other things altered
 * ASSUMPTIONS:
 * REVISIONS:   05/07/89	creation
		xx/05/92	fix3571	runtime library rewrite		
		dd/mm/yy	fix#	fix_description
 *--------------------------------------------------------------------*/
static	int	string_XmStringTable(pname, sw, udata, xdata, flag)
	char	  *pname;
	swidget   sw;
	char	  **udata;
	XmString  **xdata;
	int	  flag;
{
	if (flag == TO_UIMX)
	{
	    Arg     a[1];
	    int	    i, n;
	    Widget  w;
	    char    *t = "";

	    static char **RotatingBuffer;
	    static int BufferIndex = -1;

	    /* First determine the size of the string table, by asking
	       the widget for its item count; the item count property
	       name was passed in as pname */

	    w = UxGetWidget(sw);

	    if (!w)
	    {
	        *udata = "";
	        return NO_ERROR;
	    }

	    XtSetArg(a[0], pname, &n);
	    XtGetValues(w, a, 1);

	    if (n == 0)
	    {
	        *udata = "";
	        return NO_ERROR;
	    }

	    /* Now construct a uimx string in which the x strings of the     */
	    /* string table are concatenated, separated by commas.  Commas   */
	    /* inside an X string have to be escaped with a double backslash */
	    /* in the uimx string.  We do not worry about \n characters in   */
	    /* any of the XmStrings, since this would not be appropriate for */
	    /* a list. 					     		     */

	    for (i=0; i<n; i++)
	    {
	        XmString xm;
	        char     *s, *sp, *tp;
		int	 j, comma_count;

	        xm = (*xdata)[i];
	        string_XmString(sw, &s, &xm, TO_UIMX);

		/* Count the number of commas, so we know how much space   */
		/* to allocated for the resulting uimx string              */

		comma_count = 0;
		for (j=0; s[j]; j++)
		    if (s[j] == ',')
			comma_count++;

		/* Allocate or reallocate the uimx string array used to    */
		/* accumulate the x strings 				   */

		if (i==0)
		{
		    t = UxMalloc(strlen(s) + comma_count + 1);
		    tp = t;
		}
		else
		{
		    int len = strlen(t);

		    t = UxRealloc(t, len + strlen(s) + comma_count + 2);
		    tp = &t[len];
		    *tp++ = ',';	/* a comma separates the x strings */
		}

		/* Add the current x string onto the end of the uimx string, */
		/* escaping commas with double backslashes 		     */

		sp = s;
		while (*sp)
		{
		    if (*sp == ',')
		    	*tp++ = '\\';
		    *tp++ = *sp++;
		}
		*tp = '\0';
	    }
	    UxUpdateRotatingBuffer(&BufferIndex, &RotatingBuffer, t, UxFree);
	    *udata = RotatingBuffer[BufferIndex];
	}
	else if (flag == TO_X)
	{
	    XrmValue 	from_val, to_val;

	    from_val.addr = *udata;

	    /* note: in _string_XmStringTable(), the args and num_args 	*/
	    /* parameters and from_val.size are not used.		*/
	    _string_XmStringTable(NULL, NULL, &from_val, &to_val);

	    *xdata = *((XmString **)(to_val.addr));
	}
	else
	{
	    UxStandardError (CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
	    return ERROR;
	}
	return NO_ERROR;
}

/******************************************************************************
NAME:		int	stringTable_WidgetList (sw, udata, xdata, flag)
INPUT:		swidget		sw		- swidget
		stringTable	*udata		- UIM/X string table
		WidgetList	*xdata		- Motif WidgetList
		int		flag		- TO_UIMX or TO_X
RETURN:		ERROR/NO_ERROR
DESCRIPTION:	Converts from a Motif WidgetList to a UIM/X stringTable, i.e.
		an array of widget names.
CREATION:	January 28/1991
-----------------------------------------------------------------------------*/

static	int	stringTable_WidgetList (sw, udata, xdata, flag)
	swidget   	sw;
	stringTable	*udata;
	WidgetList  	*xdata;
	int	  	flag;
{
	if (flag == TO_X)
	{
	    /* Function is only used to convert to UIM/X */
	    *udata = (stringTable) NULL;
	    return ERROR;
	}
	else if (flag == TO_UIMX)
	{
            Widget w;
            WidgetList wList;
	    static stringTable wNames = (stringTable) NULL;
	    char     *wName;
            static int wNum = 0;
            int i;

	    w = UxGetWidget(sw);

	    for (i=0; i < wNum; i++)
		UxFree (wNames[i]);
		
            XtVaGetValues (w,
                           XmNchildren, &wList,
                           XmNnumChildren, &wNum,
                           NULL);

	    wNames = (stringTable) UxRealloc (wNames,
					wNum * sizeof(wName));	
            for (i = 0; i < wNum; i++)
            {
			wNames[i] = (char *) UxMalloc (strlen (XtName (wList[i]) )+1);
			strcpy (wNames[i], XtName (wList[i]));
	    }
	    *udata = wNames;
	    return NO_ERROR;
	}
	else
	{
	    UxStandardError (CGETS( MS_MISC_WRONG_FLAG, DS_MS_MISC_WRONG_FLAG));
	    return ERROR;
	}
}


/* ---------------------------------------------------------------------------
NAME:		UxUtype_init()
INPUT:		---
OUTPUT:		---
RETURNS:	void
DESCRIPTION:	Adds UIMX types, X types and converters.
		UIMX should call this function at startup time.
CREATION:       May 11 1988  Visual Edge Software
LAST REV:	August 1, 1991		See bugfix 2857
		- Added new type and converter for UxXT_BorderPixmap
---------------------------------------------------------------------------*/
void UxUtype_init()
{
	char	**font_names;
	int	num_fonts;
	void	UxInitEnumTypes();

	/* UIMX types */

	UxUT_float 	= UxAdd_utype("float", sizeof(float), T_FLOAT);
	UxUT_int	= UxAdd_utype("int", sizeof(int), T_INT);
	UxUT_short	= UxAdd_utype("short", sizeof(short), T_SHORT);
	UxUT_string	= UxAdd_utype("string", sizeof(char*), T_PNTR);
	UxUT_vhandle	= UxAdd_utype("vhandle", sizeof(char*), T_STRUCT);
	UxUT_char	= UxAdd_utype("char", sizeof (char), T_CHAR);
	UxUT_long	= UxAdd_utype("long", sizeof (long), T_LONG);
	UxUT_stringTable = UxAdd_utype("stringTable", sizeof(char**), T_PNTR);
	UxUT_cardFunction = UxAdd_utype("cardFunction", sizeof(Cardinal (*)()),
								T_PNTR);
	UxUT_voidFunction = UxAdd_utype("voidFunction", sizeof(void (*)()), 
								T_PNTR);
	UxUT_visualPointer = UxAdd_utype("visualPointer", 
					 sizeof(Visual *),
					 T_PNTR);
	UxUT_XmTextSource = UxAdd_utype("XmTextSource", 
					 sizeof(XmTextSource),
					 T_PNTR);

	/* Add the xtypes and register the converters for enumerated-types */
	UxInitEnumTypes();


	/* X types in alphabetical order */

	UxXT_Atom       = UxAddXtype("Atom",           sizeof(Atom));
 	UxXT_Dimension  = UxAddXtype(XtRDimension, 	sizeof(Dimension));
	UxXT_FontStruct	= UxAddXtype(XtRFontStruct, 	sizeof(XFontStruct*));
	UxXT_KeySym 	= UxAddXtype(XmRKeySym, 	sizeof (KeySym));
	UxXT_Pixel	= UxAddXtype(XtRPixel, 	sizeof(Pixel));
	UxXT_Pixmap	= UxAddXtype(XtRPixmap, 	sizeof(Pixmap));
	UxXT_Pointer	= UxAddXtype("Pointer", 	sizeof(caddr_t));
	UxXT_BorderPixmap = UxAddXtype("BorderPixmap", sizeof(Pixmap));
	UxXT_HighlightPixmap = UxAddXtype("HighlightPixmap", sizeof(Pixmap));
	UxXT_TopShadowPixmap = UxAddXtype("TopShadowPixmap", sizeof(Pixmap));
	UxXT_BottomShadowPixmap
		= UxAddXtype("BottomShadowPixmap", 	sizeof(Pixmap));
	UxXT_bitmap	= UxAddXtype("bitmap", 	sizeof(Pixmap));
 	UxXT_Position   = UxAddXtype(XtRPosition, 	sizeof(Position));
	UxXT_String	= UxAddXtype(XtRString, 	sizeof(char*));
	UxXT_StringTable = UxAddXtype("StringTable", 	sizeof (char **));
	UxXT_InsertPosition 
		= UxAddXtype("InsertPosition", 	sizeof(Cardinal (*)()));
	UxXT_CreatePopupChildProc 
		= UxAddXtype("CreatePopupChildProc", 	sizeof(void (*)()));
	UxXT_FileSearchProc 
		= UxAddXtype("FileSearchProc", 	sizeof(void (*)()));
	UxXT_QualifySearchDataProc 
		= UxAddXtype("QualifySearchDataProc",  sizeof(void (*)()));
	UxXT_DirSearchProc 
		= UxAddXtype("DirSearchProc", 		sizeof(void (*)()));
	UxXT_Widget	= UxAddXtype("Widget", 	sizeof(Widget));
	UxXT_WidgetList	= UxAddXtype("WidgetList", 	sizeof(caddr_t));
	UxXT_Window	= UxAddXtype(XtRWindow, 	sizeof(Window));
	UxXT_XID	= UxAddXtype("XID", 		sizeof (XID));
	UxXT_Translations = UxAddXtype("Translations", sizeof(caddr_t));
	UxXT_Accelerators = UxAddXtype("Accelerators", sizeof(caddr_t));

	UxXT_HistoryItems = UxAddXtype("HistoryItems", sizeof(XmStringTable));
	UxXT_Items = UxAddXtype(XmRItems, 		sizeof(XmStringTable));
	UxXT_ListItems = UxAddXtype("ListItems", 	sizeof(XmStringTable));
	UxXT_StringOrNull = UxAddXtype("StringOrNull",	sizeof(char *));

	UxXT_FileListItems = UxAddXtype("FileListItems",sizeof(XmStringTable));
	UxXT_DirListItems = UxAddXtype("DirListItems", sizeof(XmStringTable));
	UxXT_SelectedItems
		= UxAddXtype(XmRSelectedItems, 	sizeof(XmStringTable));
	UxXT_SelectionArray
		= UxAddXtype ("SelectionArray", 	sizeof (XmTextScanType *));
	UxXT_WidgetClass = UxAddXtype ("WidgetClass", 	sizeof (WidgetClass));
	UxXT_char = UxAddXtype ("char", 		sizeof (char));
	UxXT_XmFontList = UxAddXtype (XmRFontList, 	sizeof (XmFontList));
	UxXT_XmString = UxAddXtype (XmRXmString, 	sizeof (XmString));
	UxXT_XmTextSource = UxAddXtype ("XmTextSource", sizeof (XmTextSource));
	UxXT_Colormap = UxAddXtype ("Colormap", sizeof (Colormap));
	UxXT_VisualPointer= UxAddXtype (XtRVisual, sizeof (Visual *));
        UxXT_ValueWcs= UxAddXtype (XmRValueWcs, sizeof (wchar_t *));

	UxXT_short	= UxAddXtype("short", 		sizeof(short));
	UxXT_int  	= UxAddXtype("int", 		sizeof(int));

	font_names = XListFonts(UxDisplay, "*", 200, &num_fonts);
	UxAdd_values(X_TYPE, UxXT_FontStruct, num_fonts, font_names);
	XFreeFontNames(font_names);

	/* values in alphabetical order */

	UxAddXValues(UxXT_SelectionArray, uSelectionArray, 
		xSelectionArray, XtNumber(uSelectionArray));

	/* converters in alphabetical order */

	UxAddConv(UxUT_string, UxXT_Atom, string_Atom);
	UxAddConv(UxUT_int, UxXT_short, int_short);
 	UxAddConv(UxUT_int, UxXT_Position, int_Position);
 	UxAddConv(UxUT_int, UxXT_Dimension, int_Dimension);
 	UxAddConv(UxUT_long, UxXT_Colormap, long_Colormap);
	UxAddConv(UxUT_short, UxXT_int, short_int);
#ifndef RUNTIME
	UxAddConv(UxUT_voidFunction, UxXT_CreatePopupChildProc, 
					voidFunction_createPopupChildProc);
	UxAddConv(UxUT_cardFunction, UxXT_InsertPosition, 
					cardFunction_insertPosition);
	UxAddConv(UxUT_voidFunction, UxXT_FileSearchProc, 
					voidFunction_fileSearchProc);
	UxAddConv(UxUT_voidFunction, UxXT_DirSearchProc, 
					voidFunction_dirSearchProc);
	UxAddConv(UxUT_voidFunction, UxXT_QualifySearchDataProc, 
					voidFunction_qualifySearchDataProc);
#endif /* ! RUNTIME */
	UxAddConv(UxUT_string, UxXT_KeySym,   string_Keysym);
	UxAddConv(UxUT_string, UxXT_Translations, string_translations);
	UxAddConv(UxUT_string, UxXT_Accelerators, string_accelerators);
	UxAddConv(UxUT_string, UxXT_FontStruct, string_FontStruct);

	UxAddConv(UxUT_string, UxXT_Pixel, string_Pixel);
	UxAddConv(UxUT_string, UxXT_Pixmap, string_Pixmap);
	UxAddConv(UxUT_string, UxXT_Pointer, string_Pointer);
        UxAddConv(UxUT_string, UxXT_BorderPixmap, string_BorderPixmap);
        UxAddConv(UxUT_string, UxXT_HighlightPixmap, string_HighlightPixmap);
        UxAddConv(UxUT_string, UxXT_TopShadowPixmap, string_TopShadowPixmap);
        UxAddConv(UxUT_string, UxXT_BottomShadowPixmap,
						string_BottomShadowPixmap);
	UxAddConv(UxUT_string, UxXT_bitmap, string_bitmap);
	UxAddConv(UxUT_string, UxXT_StringOrNull, string_StringOrNull);
	UxAddConv(UxUT_string, UxXT_String, string_String);
        UxAddConv(UxUT_string, UxXT_ValueWcs, string_ValueWcs);
	UxAddConv(UxUT_string, UxXT_Widget, string_Widget);
	UxAddConv(UxUT_string, UxXT_Window, string_Window);
	UxAddConv(UxUT_string, UxXT_XID, string_XID);
	UxAddConv(UxUT_string, UxXT_HistoryItems, string_HistoryItems);
	UxAddConv(UxUT_string, UxXT_Items, string_Items);
	UxAddConv(UxUT_string, UxXT_ListItems, string_ListItems);
	UxAddConv(UxUT_string, UxXT_FileListItems, string_FileListItems);
	UxAddConv(UxUT_string, UxXT_DirListItems, string_DirListItems);
	UxAddConv(UxUT_string, UxXT_SelectedItems, string_SelectedItems);
	UxAddConv(UxUT_string, UxXT_SelectionArray, string_SelectionArray);
	UxAddConv(UxUT_string, UxXT_WidgetClass, string_WidgetClass);
	UxAddConv(UxUT_string, UxXT_XmFontList, string_XmFontList);
	UxAddConv(UxUT_string, UxXT_XmString, string_XmString);
	UxAddConv(UxUT_stringTable, UxXT_WidgetList, stringTable_WidgetList);

	/********************************************************
	 * At this moment we are ready to add any new xtypes	*
	 * and converter the users wants.			*
	 ********************************************************/

	UxAddUserDefXtypes();

	/* We register our string-to-XmStringTable converter with Xt */

	XtAppAddConverter(UxAppContext, XmRString, XmRXmStringTable,
					_string_XmStringTable, NULL, 0);
}


/*----------------------------------------------------------------------
 * NAME:	<void UxUpdateRotatingBuffer(BufIndex, RingBuffer, Val, func)>
 * DESCRIPTION:	<This function copies the value Val at position BufIndex in the
	     RingBuffer and then destroys the value Val using function func.
	     The ring buffer is allocated the first time the function is entered
	     with Bufindex = -1 and space is reallocated for the specified 
	     BufIndex. When BufIndex reaches the end of the buffer, it is set
	     back to 0 to create the effect of the ring buffer.> 
 * PARAMETERS: 
		int *BufIndex;		 - index in the ring buffer 
		char ***RingBuffer;	 - ring buffer 
		char *Val;		 - value to store
		func_ptr func;		 - function to free variable Val
 * RETURN:	nothing	
 * EXT REFS:	UxRingBufferSize	
 * EXT EFFECTS:	globals or other things altered
 * ASSUMPTIONS:
 * REVISIONS:	19/11/92	creation	
		dd/mm/yy	fix#	fix_description
 *--------------------------------------------------------------------*/
void UxUpdateRotatingBuffer(BufIndex, RingBuffer, Val, free_func)
int *BufIndex;
char ***RingBuffer;
char *Val;
func_ptr free_func;
{
	    if (*BufIndex == -1)
	       *RingBuffer = (char **) UxMalloc(UxRingBufferSize * sizeof(char *));
	    (*BufIndex)++;		
	    if (*BufIndex >= UxRingBufferSize)
	       *BufIndex = 0;
	   if (!Val)
	   {
		(*RingBuffer)[*BufIndex] = 
	       		UxRealloc((*RingBuffer)[*BufIndex], 1);
		(*RingBuffer)[*BufIndex][0] = '\0';	
		return;
	   }	
	   (*RingBuffer)[*BufIndex] = 
	       UxRealloc((*RingBuffer)[*BufIndex], strlen(Val) + 1);
	    strcpy((*RingBuffer)[*BufIndex], Val);
	    free_func(Val);
}
