/**
 *
 * $Id: ResConvert.c,v 1.10 1997/08/19 19:29:13 miers Exp $
 *
 * Copyright (C) 1995 Free Software Foundation, Inc.
 *
 * This file is part of the GNU LessTif Library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 **/

static char rcsid[] = "$Id: ResConvert.c,v 1.10 1997/08/19 19:29:13 miers Exp $";

#include <stdio.h>
#include <stdlib.h>
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include <ctype.h>

#include <LTconfig.h>
#include <XmI/XmI.h>
#include <Xm/XmP.h>
#include <Xm/RepType.h>
#include <Xm/BulletinBP.h>
#include <Xm/MenuShellP.h>
#include <Xm/VendorSEP.h>
#include <Xm/ExtObjectP.h>
#include <Xm/XmosP.h>
#include <X11/Xfuncs.h>

#include <XmI/DebugUtil.h>

#ifndef XmUNSPECIFIED
#define XmUNSPECIFIED (~0)
#endif

Boolean _XmCvtStringToHorizontalInt(Display *, XrmValue *, Cardinal *,
				    XrmValue *, XrmValue *, XtPointer *);

Boolean _XmCvtStringToVerticalInt(Display *, XrmValue *, Cardinal *,
				  XrmValue *, XrmValue *, XtPointer *);

Boolean _XmCvtStringToHorizontalPosition(Display *, XrmValue *, Cardinal *,
					 XrmValue *, XrmValue *, XtPointer *);

Boolean _XmCvtStringToVerticalPosition(Display *, XrmValue *, Cardinal *,
				       XrmValue *, XrmValue *, XtPointer *);

/* please be careful if you're editting these arrays, as
 * the strings have to be in the _same_ order as the
 * enumerated constants in the include files.  Failure to comply
 * will bring about the death of your firstborn.  Have
 * a nice day.
 */

static char *multi_click[] =
{
    "multiclick_discard",
    "multiclick_keep"
};

static char *packing_styles[] =
{
    "no_packing",
    "pack_tight",
    "pack_column",
    "pack_none"
};

static char *focus_policies[] =
{
    "explicit",
    "pointer"
};

static char *label_types[] =
{
    "pixmap",
    "string"
};
static unsigned char label_type_values[] =
{
    XmPIXMAP,
    XmSTRING
};

static char *vertical_alignments[] =
{
    "alignment_baseline_top",
    "alignment_baseline_bottom",
    "alignment_widget_top",
    "alignment_widget_bottom",
    "alignment_contents_top",
    "alignment_contents_bottom",
    "alignment_left",
    "alignment_right",
};
static unsigned char vertical_alignment_values[] =
{
    XmALIGNMENT_BASELINE_TOP,
    XmALIGNMENT_BASELINE_BOTTOM,
    XmALIGNMENT_WIDGET_TOP,
    XmALIGNMENT_WIDGET_BOTTOM,
    XmALIGNMENT_CONTENTS_TOP,
    XmALIGNMENT_CONTENTS_BOTTOM,
    0,				/* I can't find these two anywhere in Motif */
    0				/* I can't find these two anywhere in Motif */
};

static char *horizontal_alignments[] =
{
    "alignment_beginning",
    "alignment_center",
    "alignment_end"
};
static unsigned char horizontal_alignment_values[] =
{
    XmALIGNMENT_BEGINNING,
    XmALIGNMENT_CENTER,
    XmALIGNMENT_END
};

static char *arrow_directions[] =
{
    "arrow_up",
    "arrow_down",
    "arrow_left",
    "arrow_right"
};

static char *attachments[] =
{
    "attach_none",
    "attach_form",
    "attach_opposite_form",
    "attach_widget",
    "attach_opposite_widget",
    "attach_position",
    "attach_self"
};

static char *audible_warnings[] =
{
    "none",
    "bell"
};

static char *frame_child_types[] =
{
    "frame_generic_child",
    "frame_workarea_child",
    "frame_title_child"
};

static char *delete_responses[] =
{
    "destroy",
    "unmap",
    "do_nothing"
};

static char *navigation_types[] =
{
    "none",
    "tab_group",
    "sticky_tab_group",
    "exclusive_tab_group"
};

static char *orientations[] =
{
    "vertical",
    "horizontal",
};
static unsigned char orientation_values[] =
{
    XmVERTICAL,
    XmHORIZONTAL
};

static char *protocol_styles[] =
{
    "drag_none",
    "drag_drop_only",
    "drag_prefer_preregister",
    "drag_preregister",
    "drag_prefer_dynamic",
    "drag_dynamic",
    "drag_prefer_receiver"
};

static char *scrollbar_placement[] =
{
    "bottom_right",
    "top_right",
    "bottom_left",
    "top_left"
};

static char *scrolling_policy[] =
{
    "automatic",
    "application_defined"
};

static char *scrollbar_policy[] =
{
    "static",
    "as_needed"
};

static char *edit_mode[] =
{
    "multi_line_edit",
    "single_line_edit"
};

static char *unit_types[] =
{
    "pixels",
    "100th_millimeters",
    "1000th_inches",
    "100th_points",
    "100th_font_units"
};

static char *dialog_types[] =
{
    "dialog_template",
    "dialog_error",
    "dialog_information",
    "dialog_message",
    "dialog_question",
    "dialog_warning",
    "dialog_working"
};

static char *dialog_styles[] =
{
    "dialog_modeless",
    "dialog_primary_application_modal",
    "dialog_full_application_modal",
    "dialog_system_modal"
};

static char *shadow_types[] =
{
    "shadow_in",
    "shadow_out",
    "shadow_etched_in",
    "shadow_etched_out"
};
static unsigned char shadow_type_values[] =
{
    XmSHADOW_IN,
    XmSHADOW_OUT,
    XmSHADOW_ETCHED_IN,
    XmSHADOW_ETCHED_OUT
};

static char *separator_types[] =
{
    "no_line",
    "single_line",
    "double_line",
    "single_dashed_line",
    "double_dashed_line",
    "shadow_etched_in",
    "shadow_etched_out",
    "shadow_etched_in_dash",
    "shadow_etched_out_dash",
    "invalid_separator_type"
};

static char *row_column_types[] =
{
    "work_area",
    "menu_bar",
    "menu_pulldown",
    "menu_popup",
    "menu_option"
};

static unsigned char row_column_type_values[] =
{
    XmWORK_AREA,
    XmMENU_BAR,
    XmMENU_PULLDOWN,
    XmMENU_POPUP,
    XmMENU_OPTION
};

static char *indicator_types[] =
{
    "n_of_many",
    "one_of_many"
};

static char *resize_policies[] =
{
    "resize_none",
    "resize_grow",
    "resize_any"
};

static char *extension_types[] =
{
    "cache_extension",
    "desktop_extension",
    "shell_extension",
    "protocol_extension",
    "default_extension"
};

static unsigned char extension_type_values[] =
{
    XmCACHE_EXTENSION,
    XmDESKTOP_EXTENSION,
    XmSHELL_EXTENSION,
    XmPROTOCOL_EXTENSION,
    XmDEFAULT_EXTENSION
};

static char *icon_attachments[] =
{
    "attach_north_west",
    "attach_north",
    "attach_north_east",
    "attach_east",
    "attach_south_east",
    "attach_south",
    "attach_south_west",
    "attach_west",
    "attach_center",
    "attach_hot"
};

static char *transfer_statuses[] =
{
    "transfer_failure",
    "transfer_success"
};

static char *file_types[] =
{
    "file_directory",
    "file_regular",
    "file_any_type"
};
static unsigned char file_type_values[] =
{
    XmFILE_DIRECTORY,
    XmFILE_REGULAR,
    XmFILE_ANY_TYPE
};

static char *string_directions[] =
{
    "string_direction_l_to_r",
    "string_direction_r_to_l"
};

static char *command_locations[] =
{
    "command_above_workspace",
    "command_below_workspace"
};

static char *default_button_types[] =
{
    "dialog_none",
    "dialog_cancel_button",
    "dialog_ok_button",
    "dialog_help_button"
};
static unsigned char default_button_type_values[] =
{
    XmDIALOG_NONE,
    XmDIALOG_CANCEL_BUTTON,
    XmDIALOG_OK_BUTTON,
    XmDIALOG_HELP_BUTTON
};

static char *processing_directions[] =
{
    "max_on_top",
    "max_on_bottom",
    "max_on_left",
    "max_on_right"
};

static char *unpost_behaviours[] =
{
    "unpost",
    "unpost_and_replay"
};

static char *visual_policies[] =
{
    "variable",
    "constant"
};

static char *child_placements[] =
{
    "place_top",
    "place_above_selection",
    "place_below_selection"
};

static char *selection_policies[] =
{
    "single_select",
    "multiple_select",
    "extended_select",
    "browse_select"
};

void
XmRegisterConverters()
{
    /* don't really know the difference between the two, so 
       we'll just call the other from here for now. */

    _XmRegisterConverters();
}

void
_XmRegisterConverters()
{
#ifndef LESSTIF_PRODUCTION
    extern void _XmRegisterNSEConverters();
#endif

#define REPTYPE_REGISTER(reptype,array) \
    XmRepTypeRegister((reptype), \
                     (array), \
                     NULL, XtNumber((array)));
#define REPTYPE_REGISTER_WITH_VALUES(reptype,array,values) \
    XmRepTypeRegister((reptype), \
                     (array), \
                     (values), XtNumber((array)));

    REPTYPE_REGISTER(XmRMultiClick, multi_click);
    REPTYPE_REGISTER(XmRPacking, packing_styles);
    REPTYPE_REGISTER(XmRKeyboardFocusPolicy, focus_policies);
    REPTYPE_REGISTER(XmRArrowDirection, arrow_directions);
    REPTYPE_REGISTER(XmRAttachment, attachments);
    REPTYPE_REGISTER(XmRAudibleWarning, audible_warnings);
    REPTYPE_REGISTER(XmRChildType, frame_child_types);
    REPTYPE_REGISTER(XmRDeleteResponse, delete_responses);
    REPTYPE_REGISTER(XmRNavigationType, navigation_types);
    REPTYPE_REGISTER(XmRScrollBarPlacement, scrollbar_placement);
    REPTYPE_REGISTER(XmRScrollingPolicy, scrolling_policy);
    REPTYPE_REGISTER(XmRScrollBarDisplayPolicy, scrollbar_policy);
    REPTYPE_REGISTER(XmREditMode, edit_mode);
    REPTYPE_REGISTER(XmRDragInitiatorProtocolStyle, protocol_styles);
    REPTYPE_REGISTER(XmRDragReceiverProtocolStyle, protocol_styles);
    REPTYPE_REGISTER(XmRUnitType, unit_types);
    REPTYPE_REGISTER(XmRDialogType, dialog_types);
    REPTYPE_REGISTER(XmRSelectionType, dialog_types);
    REPTYPE_REGISTER(XmRDialogStyle, dialog_styles);
    REPTYPE_REGISTER(XmRSeparatorType, separator_types);
    REPTYPE_REGISTER(XmRIndicatorType, indicator_types);
    REPTYPE_REGISTER(XmRResizePolicy, resize_policies);
    REPTYPE_REGISTER(XmRIconAttachment, icon_attachments);
    REPTYPE_REGISTER(XmRTransferStatus, transfer_statuses);
    REPTYPE_REGISTER(XmRStringDirection, string_directions);
    REPTYPE_REGISTER(XmRCommandWindowLocation, command_locations);
    REPTYPE_REGISTER(XmRProcessingDirection, processing_directions);
    REPTYPE_REGISTER(XmRUnpostBehavior, unpost_behaviours);
    REPTYPE_REGISTER(XmRVisualPolicy, visual_policies);
    REPTYPE_REGISTER(XmRChildPlacement, child_placements);
    REPTYPE_REGISTER(XmRSelectionPolicy, selection_policies);

    REPTYPE_REGISTER_WITH_VALUES(XmRLabelType, label_types, label_type_values);
    REPTYPE_REGISTER_WITH_VALUES(XmRAlignment, horizontal_alignments,
				 horizontal_alignment_values);
    REPTYPE_REGISTER_WITH_VALUES(XmRChildHorizontalAlignment, horizontal_alignments,
				 horizontal_alignment_values);
    REPTYPE_REGISTER_WITH_VALUES(XmRChildVerticalAlignment, vertical_alignments,
				 vertical_alignment_values);
    REPTYPE_REGISTER_WITH_VALUES(XmRShadowType, shadow_types,
				 shadow_type_values);
    REPTYPE_REGISTER_WITH_VALUES(XmRRowColumnType, row_column_types,
				 row_column_type_values);
    REPTYPE_REGISTER_WITH_VALUES(XmRExtensionType, extension_types,
				 extension_type_values);
    REPTYPE_REGISTER_WITH_VALUES(XmRFileTypeMask, file_types,
				 file_type_values);
    REPTYPE_REGISTER_WITH_VALUES(XmRDefaultButtonType, default_button_types,
				 default_button_type_values);
    REPTYPE_REGISTER_WITH_VALUES(XmROrientation, orientations,
				 orientation_values);

#undef REPTYPE_REGISTER
#undef REPTYPE_REGISTER_WITH_VALUES

    /* now we install the other toolkit converters */

    XtSetTypeConverter(XtRString,	/* source type */
		       XmRXmString,	/* target type */
		       _XmCvtStringToXmString,	/* converter routine */
		       NULL,	/* args for converter routine */
		       0,	/* number of args to converter routine */
		       XtCacheAll,	/* caching instructions */
		       NULL);	/* destructor function */

    XtSetTypeConverter(XtRString,	/* source type */
		       XmRFontList,	/* target type */
		       _XmCvtStringToFontlist,	/* converter routine */
		       NULL,	/* args for converter routine */
		       0,	/* number of args to converter routine */
		       XtCacheNone,	/* caching instructions */
		       NULL);	/* destructor function */

    XtSetTypeConverter(XtRString,	/* source type */
		       XmRHorizontalDimension,	/* target type */
		       _XmCvtStringToDimension,		/* converter routine */
		       NULL,	/* args for converter routine */
		       0,	/* number of args to converter routine */
		       XtCacheAll,	/* caching instructions */
		       NULL);	/* destructor function */

    XtSetTypeConverter(XtRString,	/* source type */
		       XmRShellHorizDim,	/* target type */
		       _XmCvtStringToDimension,		/* converter routine */
		       NULL,	/* args for converter routine */
		       0,	/* number of args to converter routine */
		       XtCacheAll,	/* caching instructions */
		       NULL);	/* destructor function */

    XtSetTypeConverter(XtRString,	/* source type */
		       XmRHorizontalInt,	/* target type */
		       _XmCvtStringToHorizontalInt,	/* converter routine */
		       NULL,	/* args for converter routine */
		       0,	/* number of args to converter routine */
		       XtCacheAll,	/* caching instructions */
		       NULL);	/* destructor function */

    XtSetTypeConverter(XtRString,	/* source type */
		       XmRHorizontalPosition,	/* target type */
		       _XmCvtStringToHorizontalPosition, /* converter routine */
		       NULL,	/* args for converter routine */
		       0,	/* number of args to converter routine */
		       XtCacheAll,	/* caching instructions */
		       NULL);	/* destructor function */

    XtSetTypeConverter(XtRString,	/* source type */
		       XmRShellHorizPos,	/* target type */
		       _XmCvtStringToHorizontalPosition, /* converter routine */
		       NULL,	/* args for converter routine */
		       0,	/* number of args to converter routine */
		       XtCacheAll,	/* caching instructions */
		       NULL);	/* destructor function */

    XtSetTypeConverter(XtRString,	/* source type */
		       XmRShellVertPos,	/* target type */
		       _XmCvtStringToVerticalPosition,	/* converter routine */
		       NULL,	/* args for converter routine */
		       0,	/* number of args to converter routine */
		       XtCacheAll,	/* caching instructions */
		       NULL);	/* destructor function */

    XtSetTypeConverter(XtRString,	/* source type */
		       XmRVerticalPosition,	/* target type */
		       _XmCvtStringToVerticalPosition,	/* converter routine */
		       NULL,	/* args for converter routine */
		       0,	/* number of args to converter routine */
		       XtCacheAll,	/* caching instructions */
		       NULL);	/* destructor function */

    XtSetTypeConverter(XtRString,	/* source type */
		       XmRShellVertDim,		/* target type */
		       _XmCvtStringToDimension,		/* converter routine */
		       NULL,	/* args for converter routine */
		       0,	/* number of args to converter routine */
		       XtCacheAll,	/* caching instructions */
		       NULL);	/* destructor function */

    XtSetTypeConverter(XtRString,	/* source type */
		       XmRVerticalDimension,	/* target type */
		       _XmCvtStringToDimension,		/* converter routine */
		       NULL,	/* args for converter routine */
		       0,	/* number of args to converter routine */
		       XtCacheAll,	/* caching instructions */
		       NULL);	/* destructor function */

    XtSetTypeConverter(XtRString,	/* source type */
		       XmRVerticalInt,	/* target type */
		       _XmCvtStringToVerticalInt,	/* converter routine */
		       NULL,	/* args for converter routine */
		       0,	/* number of args to converter routine */
		       XtCacheAll,	/* caching instructions */
		       NULL);	/* destructor function */

    XtSetTypeConverter(XtRString,	/* source type */
		       XmRKeySym,	/* target type */
		       _XmCvtStringToKeySym,	/* converter routine */
		       NULL,	/* args for converter routine */
		       0,	/* number of args to converter routine */
		       XtCacheAll,	/* caching instructions */
		       NULL);	/* destructor function */

#if 0
    XtSetTypeConverter(XtRString,	/* source type */
		       XmRNavigation,	/* target type */
		       _XmCvtStringToXmNavigation,	/* converter routine */
		       NULL,	/* args for converter routine */
		       0,	/* number of args to converter routine */
		       XtCacheAll,	/* caching instructions */
		       NULL);	/* destructor function */
#endif

    XtSetTypeConverter(XtRString,	/* source type */
		       XmRXmStringTable,	/* target type */
		       _XmCvtStringToStringTable,	/* converter routine */
		       NULL,	/* args for converter routine */
		       0,	/* number of args to converter routine */
		       XtCacheAll,	/* caching instructions */
		       _XmDestroyStringTable);	/* destructor function */

#ifndef LESSTIF_PRODUCTION
    _XmRegisterNSEConverters();
#endif
}

/*
 * error convenience
 */
void
#ifdef __STDC__
_XmError(Widget w, char *fmt,...)
{
    va_list arg_list;
    char buf[256];

    va_start(arg_list, fmt);
#else
_XmError(w, fmt, va_alist)
     Widget w;
     char *fmt;
     va_dcl
{
    char buf[256];
    va_list arg_list;

    va_start(arg_list);
#endif
    if (w)
    {
	vsprintf(buf, fmt, arg_list);
	va_end(arg_list);

	XtAppError(XtWidgetToApplicationContext(w), buf);
    }
    else
    {
	vsprintf(buf, fmt, arg_list);
	va_end(arg_list);

	XtError(buf);
    }
}

/*
 * Warning convenience
 *
 * Added XdbDebug stuff here to be able to avoid infinite loops in applications
 * that redirect stderr to a scrolledText. ML suffers from this, due to LessTif
 * bugs of cource :-(
 */
void
#ifdef __STDC__
_XmWarning(Widget w, char *fmt,...)
{
    va_list arg_list;
    char buf[256];

    va_start(arg_list, fmt);
#else
_XmWarning(Widget w, fmt, va_list)
     Widget w;
     char *fmt;
     va_dcl
{
    char buf[256];

    va_start(arg_list);
#endif
    if (w)
    {
	sprintf(buf, "\n    Name: %s\n    Class: %s\n    ",
		XtName(w), XtClass(w)->core_class.class_name);

	vsprintf(buf + strlen(buf), fmt, arg_list);
	va_end(arg_list);

	strcat(buf, "\n");

#ifdef	LESSTIF_PRODUCTION
	XtAppWarning(XtWidgetToApplicationContext(w), buf);
#else
	if (getenv("DEBUG_REDIRECT_XMWARNING"))
	{
	    XdbPrintString(buf);
	}
	else
	{
	    XtAppWarning(XtWidgetToApplicationContext(w), buf);
	}
#endif
    }
    else
    {
	buf[0] = '\0';
	vsprintf(buf + strlen(buf), fmt, arg_list);
	va_end(arg_list);

#ifdef	LESSTIF_PRODUCTION
	XtWarning(buf);
#else
	if (getenv("DEBUG_REDIRECT_XMWARNING"))
	{
	    XdbPrintString(buf);
	}
	else
	{
	    XtWarning(buf);
	}
#endif
    }
}

void
XmCvtStringToUnitType(XrmValuePtr args, Cardinal *num_args,
		      XrmValue *from_val, XrmValue *to_val)
{
}

char *
XmRegisterSegmentEncoding(char *fontlist_tag, char *ct_encoding)
{
    return NULL;
}

char *
XmMapSegmentEncoding(char *fontlist_tag)
{
    return NULL;
}

XmString
XmCvtCTToXmString(char *text)
{
    return XmStringCreate(text, XmFONTLIST_DEFAULT_TAG);
}

Boolean
XmCvtTextToXmString(Display *display, XrmValuePtr args,
		    Cardinal *num_args, XrmValue *from_val, XrmValue *to_val,
		    XtPointer *converter_data)
{
    return False;
}

char *
XmCvtXmStringToCT(XmString string)
{
    char *text = (char *)NULL;
    XmStringContext context = NULL;
    char *pbuf = (char *)NULL, *pstr;
    XmStringCharSet tag;
    XmStringDirection direction;
    Boolean separator;

    DEBUGOUT(XdbDebug(__FILE__, NULL, "XmCvtXmStringToCT\n"));

    if (XmStringInitContext(&context, string) == True)
    {
	while (XmStringGetNextSegment(context,
				      &text,
				      &tag,
				      &direction,
				      &separator) == True)
	{
	    if (pbuf == NULL)
	    {
		/* allocate space for the buffer and init it */
		pbuf = XtMalloc(strlen(text) + 2);
		*pbuf = '\0';
	    }
	    else
	    {
		/* allocate more space for the buffer */
		pbuf = XtRealloc(pbuf, sizeof(pbuf) + strlen(text) + 2);
	    }

	    /* reset the pointer pstr to point back at pbuf */
	    pstr = pbuf;

	    pstr += (strlen(strcat(pstr, text)));
	    if (separator == True)
	    {			/* add newline */
		*pstr++ = '\n';
		*pstr = '\0';
	    }

	    /* free the text segment we just grabbed */
	    XtFree(text);
	}
	text = pbuf;
    }

    return text;
}

Boolean
XmCvtXmStringToText(Display *display, XrmValuePtr args,
		    Cardinal *num_args, XrmValue *from_val, XrmValue *to_val,
		    XtPointer *converter_data)
{
    DEBUGOUT(XdbDebug(__FILE__, NULL, "XmCvtXmStringToText\n"));
    return False;
}

/*
 * Compare two strings to see if they're equivalent. This one is used
 * whenever comparing motif constants with resource string values. The
 * motif constants must have the Xm prefix stripped off and must be
 * in lower case.
 */
Boolean
_XmStringsAreEqual(char *in_str,
		   char *text_str)
{
    if (in_str[0] && (tolower(in_str[0]) == 'x') &&
	in_str[1] && (tolower(in_str[1]) == 'm'))
    {
	in_str += 2;		/* skip the Xm prefix */
    }

    while (*in_str)
    {
	if (tolower(*in_str) != *text_str)
	    return False;
	in_str++;
	text_str++;
    }

    return *text_str ? False : True;
}

/*
 * Fixed this thing to make a COPY of the fontlist it returns.
 * Danny 16/4/1996
 */
XmFontList
_XmGetDefaultFontList(Widget w,
		      unsigned char fontListType)
{
    static XmFontList labelFontList = NULL;
    static XmFontList buttonFontList = NULL;
    static XmFontList textFontList = NULL;
    Widget par = w;
    XmFontList fontlist;
    XmVendorShellExtObject ve = NULL;

    fontlist = NULL;
    switch (fontListType)
    {
    case XmTEXT_FONTLIST:
	while ((par = XtParent(par)) != NULL)
	{
	    if (XmIsBulletinBoard(par) && BB_TextFontList(par) != NULL)
	    {
		fontlist = BB_TextFontList(par);
		break;
	    }
	    else if (XmIsVendorShell(par))
	    {
		/* Danny, I found out the hard way that this function can
		 * get called before the VSEP child is valid, but the context
		 * has been set.  It was with that UIL compiler you sent.
		 * Thus the next three ve checks have been converted.
		 * - MLM
		 */
		ve = (XmVendorShellExtObject)_LtFindVendorExt((Widget)par);
		if (ve && VSEP_TextFontList(ve) != NULL)
		{
		    fontlist = VSEP_TextFontList(ve);
		    break;
		}
	    }
	}
	if (fontlist)
	{
	    return XmFontListCopy(fontlist);
	}

	if (!textFontList)
	{
	    XmFontListEntry newEntry = XmFontListEntryLoad(XtDisplay(w),
							   XmDEFAULT_FONT,
							   XmFONT_IS_FONT,
						       XmFONTLIST_DEFAULT_TAG);
	    textFontList = XmFontListAppendEntry(NULL, newEntry);
	}
	return XmFontListCopy(textFontList);
	break;

    case XmBUTTON_FONTLIST:
	while ((par = XtParent(par)) != NULL)
	{
	    if (XmIsBulletinBoard(par) && BB_ButtonFontList(par) != NULL)
	    {
		fontlist = BB_ButtonFontList(par);
		break;
	    }
	    else if (XmIsMenuShell(par) && MS_ButtonFontList(par) != NULL)
	    {
		fontlist = MS_ButtonFontList(par);
		break;
	    }
	    else if (XmIsVendorShell(par))
	    {
		ve = (XmVendorShellExtObject)_LtFindVendorExt((Widget)par);
		if (ve && VSEP_ButtonFontList(ve) != NULL)
		{
		    fontlist = VSEP_LabelFontList(ve);
		    break;
		}
	    }
	}
	if (fontlist)
	    return XmFontListCopy(fontlist);

	if (!buttonFontList)
	{
	    XmFontListEntry newEntry = XmFontListEntryLoad(XtDisplay(w),
							   XmDEFAULT_FONT,
							   XmFONT_IS_FONT,
						       XmFONTLIST_DEFAULT_TAG);
	    buttonFontList = XmFontListAppendEntry(NULL, newEntry);
	}

	return XmFontListCopy(buttonFontList);
	break;

    default:
    case XmLABEL_FONTLIST:
	while ((par = XtParent(par)) != NULL)
	{
	    if (XmIsBulletinBoard(par) && BB_LabelFontList(par) != NULL)
	    {
		fontlist = BB_LabelFontList(par);
		break;
	    }
	    else if (XmIsMenuShell(par) && MS_LabelFontList(par) != NULL)
	    {
		fontlist = MS_LabelFontList(par);
		break;
	    }
	    else if (XmIsVendorShell(par))
	    {
		ve = (XmVendorShellExtObject)_LtFindVendorExt((Widget)par);
		if (ve && VSEP_LabelFontList(ve) != NULL)
		{
		    fontlist = VSEP_LabelFontList(ve);
		    break;
		}
	    }
	}

	if (fontlist)
	{
	    return XmFontListCopy(fontlist);
	}

	if (!labelFontList)
	{
	    XmFontListEntry newEntry = XmFontListEntryLoad(XtDisplay(w),
							   XmDEFAULT_FONT,
							   XmFONT_IS_FONT,
						       XmFONTLIST_DEFAULT_TAG);
	    labelFontList = XmFontListAppendEntry(NULL, newEntry);
	}
	return XmFontListCopy(labelFontList);

	break;
    }
}

/* resource converters, of various types */

extern char *
_XmConvertCSToString(XmString cs)
{
    return NULL;
}

extern Boolean
_XmCvtXmStringToCT(XrmValue *from,
		   XrmValue *to)
{
    return False;
}

/*
 * One to convert from String (char *) to XmString
 */
Boolean
_XmCvtStringToXmString(Display *display,
		       XrmValue *args,
		       Cardinal *num_args,
		       XrmValue *from,
		       XrmValue *to,
		       XtPointer *converter_data)
{
    static XmString newString = NULL;

    if (*num_args != 0)
    {
	XtWarningMsg("wrongParameters", "cvtStringToXmString",
		     "XtToolkitError",
		     "String to XmString conversion needs no extra arguments",
		     (String *)NULL, (Cardinal *)NULL);
    }
    newString = XmStringCreateLtoR(from->addr, XmFONTLIST_DEFAULT_TAG);

    if (newString)
    {
	if (to->addr == NULL)
	{
	    to->addr = (XtPointer)&newString;
	    to->size = sizeof(XmString);
	}
	else
	{
	    if (to->size >= sizeof(XmString))
	    {
		*((XmString *)to->addr) = newString;
		to->size = sizeof(XmString);
	    }
	    else
	    {
		XtDisplayStringConversionWarning(display, (char *)from->addr,
						 XmRXmString);
	    }
	}
    }
    else
    {
	XtDisplayStringConversionWarning(display, (char *)from->addr,
					 XmRXmString);
    }

    DEBUGOUT(XdbDebug(__FILE__, NULL,
		      "_XmCvtStringToXmString(%s) => %p\n",
		      from->addr, to->addr));

    return True;
}

Boolean
_XmCvtStringToStringTable(Display *display, XrmValuePtr args,
			  Cardinal *num_args, XrmValue *from_val,
			  XrmValue *to_val, XtPointer *converter_data)
{
    int len = from_val->size;
    int i, start, item, num_items;
    XmStringTable string_table;

    /* Copy the data so it can be stomped on below */
    char *str = (char *)XtMalloc(from_val->size + 1);
    bcopy(from_val->addr, str, from_val->size);

    /* Find the number of strings */
    for (num_items = 0, i = 0; i < len; num_items++)
    {
	while (i < len && isspace(str[i]))
	{
	    i++;
	}
	if (i == len)
	{
	    break;
	}
	while (i < len && str[i++] != ',')
	{
	}
    }

    string_table = (XmStringTable)XtMalloc(sizeof(XmString) * num_items);

    /* Put the strings in the string table */
    for (i = 0, item = 0; item < num_items; item++)
    {
	/* Skip whitespace */
	while (i < len && isspace(str[i]))
	{
	    i++;
	}
	if (i == len)
	{
	    break;
	}

	/* Null terminate the string */
	start = i;
	while (i < len && str[i] != ',')
	{
	    i++;
	}
	str[i] = '\0';

	/* Create the XmString */
	string_table[item] = XmStringCreateSimple(&str[start]);
	i++;
    }

    XtFree((XtPointer)str);

    to_val->addr = (XtPointer)string_table;
    to_val->size = sizeof(XmString) * num_items;

    return True;
}

void
_XmDestroyStringTable(XtAppContext app, XrmValue *to,
		      XtPointer converer_data, XrmValue *args,
		      Cardinal *num_args)
{
    int i;
    XmStringTable strings = (XmStringTable)to->addr;

    for (i = 0; i < to->size / sizeof(XmString); i++)
    {
	XmStringFree(strings[i]);
    }
}

/*
 * This function is only used by the _XmCvtStringToFontlist resource
 * converter
 *
 * According to the docs, a font entry is :
 *      font_entry = font_name [ ";" font_name ]+ ":" [ tag ]
 *                 | font_name [ "=" tag ]
 *      font_name = XLFD font name
 *      tag = a string (no space, comma, colon, semicolon, equalsign)
 *
 * For a simple example, see test/Xm/international/test1.
 */
XmFontList
__XmFontListResourceAddEntry(Display *display,
			     char *full_entry,
			     XmFontList oldFontList)
{
    XmFontList newFontList;
    char *eq, *end, *fn, *ft, *tag, *font, *semi, *colon;

    DEBUGOUT(XdbDebug(__FILE__, NULL,
		      "__XmFontListResourceAddEntry(%s)\n", full_entry));

    eq = strchr(full_entry, (int)'=');

    /* there was an equal sign, the left side is the font,
       and the right side the tag. */
    if (eq)
    {
	/* set the equal sign to a null so we can XtNewString the font */
	*eq = 0;
	fn = font = XtNewString(full_entry);

	/* set it back again, and XtNewString the tag */
	*eq = '=';
	ft = tag = XtNewString(eq + 1);

	end = font + strlen(font);
	while (isspace(*font) && font < end)
	{
	    font++;
	}
	while (isspace(*end) && end > font)
	{
	    end--;
	}

	if (end != font + strlen(font))
	{
	    end++;
	    *end = 0;
	}

	end = tag + strlen(tag);
	while (isspace(*tag) && tag < end)
	{
	    tag++;
	}
	while (isspace(*end) && end > tag)
	{
	    end--;
	}

	if (end != tag + strlen(tag))
	{
	    end++;
	    *end = 0;
	}

	newFontList = XmFontListAppendEntry(oldFontList,
					    XmFontListEntryLoad(display,
								font,
								XmFONT_IS_FONT,
								tag));

	XtFree(ft);
	XtFree(fn);

	return newFontList;
    }

    /* Now treat the case with no equal sign */
    semi = strchr(full_entry, ';');
    colon = strchr(full_entry, ':');

    if (semi || colon)
    {
	/* font_entry = font_name [ ";" font_name ]+ ":" [ tag ] */

	/* First find the tag if there is one */
	if (colon)
	{
	    tag = colon + 1;
	    while (tag && *tag != '\0' && isspace(*tag))
	    {
		tag++;
	    }
	    if (*tag == '\0')
	    {
		tag = XmFONTLIST_DEFAULT_TAG;
	    }
	}
	else
	{
	    tag = XmFONTLIST_DEFAULT_TAG;
	}

	/* Find all the font names and process them */
	fn = font = XtNewString(full_entry);
	colon = strchr(fn, ':');

	if (colon)
	{
	    *colon = '\0';
	}
	newFontList = XmFontListAppendEntry(oldFontList,
					    XmFontListEntryLoad(display,
								fn,
							      XmFONT_IS_FONTSET,
								tag));

	XtFree(fn);

	return newFontList;
    }

    /* A simple font name */
    fn = font = XtNewString(full_entry);

    end = font + strlen(font);
    while (isspace(*font) && font < end)
    {
	font++;
    }

    while (isspace(*end) && end > font)
    {
	end--;
    }

    if (end != font + strlen(font))
    {
	end++;
	*end = 0;
    }
    newFontList = XmFontListAppendEntry(oldFontList,
					XmFontListEntryLoad(display, full_entry,
							    XmFONT_IS_FONT,
						      XmFONTLIST_DEFAULT_TAG));
    XtFree(fn);
    return newFontList;
}

/*
 * This thing should do reference counting, or make copies
 * Danny 16/4/1996
 */
/*
 * According to the docs, the following format should be converted :
 *      font_list = font_entry [ "," font_entry ]+
 *      font_entry = font_name [ ";" font_name ]+ ":" [ tag ]
 *                 | font_name [ "=" tag ]
 *      font_name = XLFD font name
 *      tag = a string (no space, comma, colon, semicolon, equalsign)
 *
 * For a simple example, see test/Xm/international/test1.
 */
Boolean
_XmCvtStringToFontlist(Display *display,
		       XrmValue *args,
		       Cardinal *num_args,
		       XrmValue *from,
		       XrmValue *to,
		       XtPointer *converter_data)
{
    XmFontList newFontList = NULL;
    char *p, *end, *font, *fn, *buf;

    if (*num_args != 0)
    {
	XtWarningMsg("wrongParameters", "cvtStringToFontlist",
		     "XtToolkitError",
		     "String to Fontlist conversion needs no extra arguments",
		     (String *)NULL, (Cardinal *)NULL);
    }

    /* there is an implicit rule here.  strtok() modifies the passed in buffer
     * at least on Linux, so if a comma is found, a \0 is put there.  This is
     * bad, as this memory didn't come from us, but from the Intrinsics, and
     * may get used again (especially if it's in the resource cache)! */

    buf = XtNewString(from->addr);

    p = strtok(buf, ",");

    /* if there was actually a comma character in the string. */
    if (p)
    {
	do
	{
	    fn = font = XtNewString(p);

	    end = font + strlen(font);
	    while (isspace(*font) && font < end)
	    {
		font++;
	    }
	    while (isspace(*end) && end > font)
	    {
		end--;
	    }
	    if (end != font + strlen(font))
	    {
		end++;
		*end = 0;
	    }

	    newFontList = __XmFontListResourceAddEntry(display, font,
						       newFontList);

	    XtFree(fn);
	    p = strtok(NULL, ",");

	}
	while (p != NULL);

	XtFree(buf);
    }
    else
    {
	fn = font = buf;

	end = font + strlen(font);
	while (isspace(*font) && font < end)
	{
	    font++;
	}
	while (isspace(*end) && end > font)
	{
	    end--;
	}

	if (end != font + strlen(font))
	{
	    end++;
	    *end = 0;
	}
	newFontList = __XmFontListResourceAddEntry(display, font, newFontList);

	XtFree(buf);
    }

    if (newFontList)
    {
	if (to->addr == NULL)
	{
	    to->addr = (XtPointer)&newFontList;
	    to->size = sizeof(XmFontList);
	}
	else
	{
	    if (to->size >= sizeof(XmFontList))
	    {
		*((XmFontList *)to->addr) = newFontList;
		to->size = sizeof(XmFontList);
	    }
	    else
	    {
		XtDisplayStringConversionWarning(display, (char *)from->addr,
						 XmRFontList);
	    }
	}
    }
    else
    {
	XtDisplayStringConversionWarning(display, (char *)from->addr,
					 XmRFontList);
    }

    return True;
}


/* One from String to XmNavigationType */
Boolean
_XmCvtStringToXmNavigation(Display *display,
			   XrmValue *args,
			   Cardinal *num_args,
			   XrmValue *from,
			   XrmValue *to,
			   XtPointer *converter_data)
{
    static XmNavigationType navType;

    navType = 10;

    if (*num_args != 0)
    {
	XtWarningMsg("wrongParameters", "cvtStringToXmNavigation",
		     "XtToolkitError",
		  "String to XmNavigation conversion needs no extra arguments",
		     (String *)NULL, (Cardinal *)NULL);
    }

    if (!strcmp((char *)from->addr, "NONE"))
    {
	navType = XmNONE;
    }
    else if (!strcmp((char *)from->addr, "TAB_GROUP"))
    {
	navType = XmTAB_GROUP;
    }
    else if (!strcmp((char *)from->addr, "STICKY_TAB_GROUP"))
    {
	navType = XmSTICKY_TAB_GROUP;
    }
    else if (!strcmp((char *)from->addr, "EXCLUSIVE_TAB_GROUP"))
    {
	navType = XmEXCLUSIVE_TAB_GROUP;
    }

    if (navType != 10)
    {
	if (to->addr == NULL)
	{
	    to->addr = (XtPointer)&navType;
	    to->size = sizeof(XmNavigationType);
	}
	else
	{
	    if (to->size >= sizeof(XmNavigationType))
	    {
		*((XmNavigationType *)to->addr) = navType;
		to->size = sizeof(XmNavigationType);
	    }
	    else
	    {
		XtDisplayStringConversionWarning(display, (char *)from->addr,
						 XmRNavigationType);
	    }
	}
    }
    else
    {
	XtDisplayStringConversionWarning(display, (char *)from->addr,
					 XmRNavigationType);
    }

    return True;
}

/* One from String to {Horizontal,Vertical}Dimension */
Boolean
_XmCvtStringToDimension(Display *display,
			XrmValue *args,
			Cardinal *num_args,
			XrmValue *from,
			XrmValue *to,
			XtPointer *converter_data)
{
    static Dimension dim;

    dim = (Dimension)XmUNSPECIFIED;

    if (*num_args != 0)
    {
	XtWarningMsg("wrongParameters", "cvtStringToDimension",
		     "XtToolkitError",
		  "String to XmRDimension conversion needs no extra arguments",
		     (String *)NULL, (Cardinal *)NULL);
    }

    dim = (Dimension)atoi((char *)from->addr);

    if (dim != (Dimension)XmUNSPECIFIED)
    {
	if (to->addr == NULL)
	{
	    to->addr = (XtPointer)&dim;
	    to->size = sizeof(Dimension);
	}
	else
	{
	    if (to->size >= sizeof(Dimension))
	    {
		*((Dimension *)to->addr) = dim;
		to->size = sizeof(Dimension);
	    }
	    else
	    {
		XtDisplayStringConversionWarning(display, (char *)from->addr,
						 XmRHorizontalDimension);
	    }
	}
    }
    else
    {
	XtDisplayStringConversionWarning(display, (char *)from->addr,
					 XmRHorizontalDimension);
    }

    return True;
}


Boolean
_XmCvtStringToKeySym(Display *d, XrmValue *args, Cardinal *nargs,
		     XrmValue *from, XrmValue *to, XtPointer *data)
{
    static KeySym k;

    k = XStringToKeysym((char *)from->addr);

    if (k != NoSymbol)
    {
	if (to->addr == NULL)
	{
	    to->addr = (XtPointer)&k;
	    to->size = sizeof(k);
	    return True;
	}
	else
	{
	    if (to->size >= sizeof(KeySym))
	    {
		*((KeySym *)to->addr) = k;
		to->size = sizeof(k);
		return True;
	    }
	    else
	    {
		XtDisplayStringConversionWarning(d, (char *)from->addr,
						 XmRKeySym);
		DEBUGOUT(XdbDebug(__FILE__, NULL,
				  "_XmCvtStringToKeySym fail at line %d\n",
				  __LINE__));
		return False;
	    }
	}
    }

    XtDisplayStringConversionWarning(d, (char *)from->addr, XmRKeySym);

    DEBUGOUT(XdbDebug(__FILE__, NULL,
		      "_XmCvtStringToKeySym fail at line %d\n", __LINE__));
    return False;
}

Boolean
_XmCvtStringToPosition(Display *display,
		       XrmValue *args,
		       Cardinal *num_args,
		       XrmValue *from,
		       XrmValue *to,
		       XtPointer *converter_data)
{
    static Position pos;

    pos = (Position)XmUNSPECIFIED;

    if (*num_args != 0)
	XtWarningMsg("wrongParameters", "cvtStringToPosition",
		     "XtToolkitError",
		   "String to XmRPosition conversion needs no extra arguments",
		     (String *)NULL, (Cardinal *)NULL);

    pos = (Position)atoi((char *)from->addr);

    if (pos != (Position)XmUNSPECIFIED)
    {
	if (to->addr == NULL)
	{
	    to->addr = (XtPointer)&pos;
	    to->size = sizeof(Position);
	}
	else
	{
	    if (to->size >= sizeof(Position))
	    {
		*((Position *)to->addr) = pos;
		to->size = sizeof(Position);
	    }
	    else
	    {
		XtDisplayStringConversionWarning(display, (char *)from->addr,
						 XmRHorizontalPosition);
	    }
	}
    }
    else
    {
	XtDisplayStringConversionWarning(display, (char *)from->addr,
					 XmRHorizontalPosition);
    }

    return True;
}


/*
 * FIX ME: this should probably be ResInd aware
 */
Boolean
_XmCvtStringToVerticalPosition(Display *display,
			       XrmValue *args,
			       Cardinal *num_args,
			       XrmValue *from,
			       XrmValue *to,
			       XtPointer *converter_data)
{
    static Position pos;

    pos = (Position)XmUNSPECIFIED;

    if (*num_args != 0)
	XtWarningMsg("wrongParameters", "cvtStringToVerticalPosition",
		     "XtToolkitError",
	   "String to XmRVerticalPosition conversion needs no extra arguments",
		     (String *)NULL, (Cardinal *)NULL);

    pos = (Position)atoi((char *)from->addr);	/* FIX ME: error checks */

    if (pos != (Position)XmUNSPECIFIED)
    {
	if (to->addr == NULL)
	{
	    to->addr = (XtPointer)&pos;
	    to->size = sizeof(Position);
	}
	else
	{
	    if (to->size >= sizeof(Position))
	    {
		*((Position *)to->addr) = pos;
		to->size = sizeof(Position);
	    }
	    else
	    {
		XtDisplayStringConversionWarning(display, (char *)from->addr,
						 XmRVerticalPosition);
	    }
	}
    }
    else
    {
	XtDisplayStringConversionWarning(display, (char *)from->addr,
					 XmRVerticalPosition);
    }

    return True;
}


/*
 * FIX ME: this should probably be ResInd aware
 */
Boolean
_XmCvtStringToHorizontalPosition(Display *display,
				 XrmValue *args,
				 Cardinal *num_args,
				 XrmValue *from,
				 XrmValue *to,
				 XtPointer *converter_data)
{
    static Position pos;

    pos = (Position)XmUNSPECIFIED;

    if (*num_args != 0)
	XtWarningMsg("wrongParameters", "cvtStringToPosition",
		     "XtToolkitError",
	 "String to XmRHorizontalPosition conversion needs no extra arguments",
		     (String *)NULL, (Cardinal *)NULL);

    pos = (Position)atoi((char *)from->addr);	/* FIX ME: error checks */

    if (pos != (Position)XmUNSPECIFIED)
    {
	if (to->addr == NULL)
	{
	    to->addr = (XtPointer)&pos;
	    to->size = sizeof(Position);
	}
	else
	{
	    if (to->size >= sizeof(Position))
	    {
		*((Position *)to->addr) = pos;
		to->size = sizeof(Position);
	    }
	    else
	    {
		XtDisplayStringConversionWarning(display, (char *)from->addr,
						 XmRHorizontalPosition);
	    }
	}
    }
    else
    {
	XtDisplayStringConversionWarning(display, (char *)from->addr,
					 XmRHorizontalPosition);
    }

    return True;
}


/*
 * FIX ME: this should probably be ResInd aware
 */
Boolean
_XmCvtStringToVerticalInt(Display *display,
			  XrmValue *args,
			  Cardinal *num_args,
			  XrmValue *from,
			  XrmValue *to,
			  XtPointer *converter_data)
{
    static int pos;

    pos = (int)XmUNSPECIFIED;

    if (*num_args != 0)
	XtWarningMsg("wrongParameters", "cvtStringToVerticalInt",
		     "XtToolkitError",
	   "String to XmRVerticalInt conversion needs no extra arguments",
		     (String *)NULL, (Cardinal *)NULL);

    pos = atoi((char *)from->addr);	/* FIX ME: error checks */

    if (pos != (int)XmUNSPECIFIED)
    {
	if (to->addr == NULL)
	{
	    to->addr = (XtPointer)&pos;
	    to->size = sizeof(int);
	}
	else
	{
	    if (to->size >= sizeof(int))
	    {
		*((int *)to->addr) = pos;
		to->size = sizeof(int);
	    }
	    else
	    {
		XtDisplayStringConversionWarning(display, (char *)from->addr,
						 XmRVerticalInt);
	    }
	}
    }
    else
    {
	XtDisplayStringConversionWarning(display, (char *)from->addr,
					 XmRVerticalInt);
    }

    return True;
}


/*
 * FIX ME: this should probably be ResInd aware
 */
Boolean
_XmCvtStringToHorizontalInt(Display *display,
			    XrmValue *args,
			    Cardinal *num_args,
			    XrmValue *from,
			    XrmValue *to,
			    XtPointer *converter_data)
{
    static int pos;

    pos = (int)XmUNSPECIFIED;

    if (*num_args != 0)
	XtWarningMsg("wrongParameters", "cvtStringToInt",
		     "XtToolkitError",
	 "String to XmRHorizontalInt conversion needs no extra arguments",
		     (String *)NULL, (Cardinal *)NULL);

    pos = (int)atoi((char *)from->addr);	/* FIX ME: error checks */

    if (pos != (int)XmUNSPECIFIED)
    {
	if (to->addr == NULL)
	{
	    to->addr = (XtPointer)&pos;
	    to->size = sizeof(int);
	}
	else
	{
	    if (to->size >= sizeof(int))
	    {
		*((int *)to->addr) = pos;
		to->size = sizeof(int);
	    }
	    else
	    {
		XtDisplayStringConversionWarning(display, (char *)from->addr,
						 XmRHorizontalInt);
	    }
	}
    }
    else
    {
	XtDisplayStringConversionWarning(display, (char *)from->addr,
					 XmRHorizontalInt);
    }

    return True;
}
