1/***********************************************************
2Copyright (c) 1993, Oracle and/or its affiliates.
3
4Permission is hereby granted, free of charge, to any person obtaining a
5copy of this software and associated documentation files (the "Software"),
6to deal in the Software without restriction, including without limitation
7the rights to use, copy, modify, merge, publish, distribute, sublicense,
8and/or sell copies of the Software, and to permit persons to whom the
9Software is furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice (including the next
12paragraph) shall be included in all copies or substantial portions of the
13Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21DEALINGS IN THE SOFTWARE.
22
23Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
24
25                        All Rights Reserved
26
27Permission to use, copy, modify, and distribute this software and its
28documentation for any purpose and without fee is hereby granted,
29provided that the above copyright notice appear in all copies and that
30both that copyright notice and this permission notice appear in
31supporting documentation, and that the name of Digital not be
32used in advertising or publicity pertaining to distribution of the
33software without specific, written prior permission.
34
35DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
36ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
37DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
38ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
39WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
40ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
41SOFTWARE.
42
43******************************************************************/
44
45/*
46
47Copyright 1987, 1988, 1994, 1998  The Open Group
48
49Permission to use, copy, modify, distribute, and sell this software and its
50documentation for any purpose is hereby granted without fee, provided that
51the above copyright notice appear in all copies and that both that
52copyright notice and this permission notice appear in supporting
53documentation.
54
55The above copyright notice and this permission notice shall be included in
56all copies or substantial portions of the Software.
57
58THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
61OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
62AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
63CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
64
65Except as contained in this notice, the name of The Open Group shall not be
66used in advertising or otherwise to promote the sale, use or other dealings
67in this Software without prior written authorization from The Open Group.
68
69*/
70
71/* Conversion.c - implementations of resource type conversion procs */
72
73#ifdef HAVE_CONFIG_H
74#include <config.h>
75#endif
76#include        "IntrinsicI.h"
77#include        "StringDefs.h"
78#include        "Shell.h"
79#include        <stdio.h>
80#include        <X11/cursorfont.h>
81#include        <X11/keysym.h>
82#include        <X11/Xlocale.h>
83#include        <errno.h>       /* for StringToDirectoryString */
84
85#define IsNewline(str) ((str) == '\n')
86#define IsWhitespace(str) ((str)== ' ' || (str) == '\t')
87
88static _Xconst _XtString XtNwrongParameters = "wrongParameters";
89static _Xconst _XtString XtNconversionError = "conversionError";
90static _Xconst _XtString XtNmissingCharsetList = "missingCharsetList";
91
92/* Representation types */
93
94#define XtQAtom                 XrmPermStringToQuark(XtRAtom)
95#define XtQCommandArgArray      XrmPermStringToQuark(XtRCommandArgArray)
96#define XtQCursor               XrmPermStringToQuark(XtRCursor)
97#define XtQDirectoryString      XrmPermStringToQuark(XtRDirectoryString)
98#define XtQDisplay              XrmPermStringToQuark(XtRDisplay)
99#define XtQFile                 XrmPermStringToQuark(XtRFile)
100#define XtQFloat                XrmPermStringToQuark(XtRFloat)
101#define XtQInitialState         XrmPermStringToQuark(XtRInitialState)
102#define XtQPixmap               XrmPermStringToQuark(XtRPixmap)
103#define XtQRestartStyle         XrmPermStringToQuark(XtRRestartStyle)
104#define XtQShort                XrmPermStringToQuark(XtRShort)
105#define XtQUnsignedChar         XrmPermStringToQuark(XtRUnsignedChar)
106#define XtQVisual               XrmPermStringToQuark(XtRVisual)
107
108static XrmQuark XtQBool;
109static XrmQuark XtQBoolean;
110static XrmQuark XtQColor;
111static XrmQuark XtQDimension;
112static XrmQuark XtQFont;
113static XrmQuark XtQFontSet;
114static XrmQuark XtQFontStruct;
115static XrmQuark XtQGravity;
116static XrmQuark XtQInt;
117static XrmQuark XtQPixel;
118static XrmQuark XtQPosition;
119XrmQuark _XtQString;
120
121void
122_XtConvertInitialize(void)
123{
124    XtQBool = XrmPermStringToQuark(XtRBool);
125    XtQBoolean = XrmPermStringToQuark(XtRBoolean);
126    XtQColor = XrmPermStringToQuark(XtRColor);
127    XtQDimension = XrmPermStringToQuark(XtRDimension);
128    XtQFont = XrmPermStringToQuark(XtRFont);
129    XtQFontSet = XrmPermStringToQuark(XtRFontSet);
130    XtQFontStruct = XrmPermStringToQuark(XtRFontStruct);
131    XtQGravity = XrmPermStringToQuark(XtRGravity);
132    XtQInt = XrmPermStringToQuark(XtRInt);
133    XtQPixel = XrmPermStringToQuark(XtRPixel);
134    XtQPosition = XrmPermStringToQuark(XtRPosition);
135    _XtQString = XrmPermStringToQuark(XtRString);
136}
137
138#define done_typed_string(type, typed_value, tstr) \
139        {                                                       \
140            if (toVal->addr != NULL) {                          \
141                if (toVal->size < sizeof(type)) {               \
142                    toVal->size = sizeof(type);                 \
143                    XtDisplayStringConversionWarning(dpy,       \
144                        (char*) fromVal->addr, tstr);           \
145                    return False;                               \
146                }                                               \
147                *(type*)(toVal->addr) = typed_value;            \
148            }                                                   \
149            else {                                              \
150                static type static_val;                         \
151                static_val = typed_value;                       \
152                toVal->addr = (XPointer)&static_val;            \
153            }                                                   \
154            toVal->size = sizeof(type);                         \
155            return True;                                        \
156        }
157
158#define done_string(type, value, tstr) \
159        done_typed_string(type, (type) (value), tstr)
160
161#define done_typed(type, typed_value) \
162        {                                                       \
163            if (toVal->addr != NULL) {                          \
164                if (toVal->size < sizeof(type)) {               \
165                    toVal->size = sizeof(type);                 \
166                    return False;                               \
167                }                                               \
168                *(type*)(toVal->addr) = typed_value;            \
169            }                                                   \
170            else {                                              \
171                static type static_val;                         \
172                static_val = typed_value;                       \
173                toVal->addr = (XPointer)&static_val;            \
174            }                                                   \
175            toVal->size = sizeof(type);                         \
176            return True;                                        \
177        }
178
179#define done(type, value) \
180        done_typed(type, (type) (value))
181
182void
183XtDisplayStringConversionWarning(Display *dpy,
184                                 _Xconst char *from,
185                                 _Xconst char *toType)
186{
187#ifndef NO_MIT_HACKS
188    /* Allow suppression of conversion warnings. %%%  Not specified. */
189
190    static enum { Check, Report, Ignore } report_it = Check;
191    XtAppContext app = XtDisplayToApplicationContext(dpy);
192
193    LOCK_APP(app);
194    LOCK_PROCESS;
195    if (report_it == Check) {
196        XrmDatabase rdb = XtDatabase(dpy);
197        XrmName xrm_name[2];
198        XrmClass xrm_class[2];
199        XrmRepresentation rep_type;
200        XrmValue value;
201
202        xrm_name[0] = XrmPermStringToQuark("stringConversionWarnings");
203        xrm_name[1] = 0;
204        xrm_class[0] = XrmPermStringToQuark("StringConversionWarnings");
205        xrm_class[1] = 0;
206        if (XrmQGetResource(rdb, xrm_name, xrm_class, &rep_type, &value)) {
207            if (rep_type == XtQBoolean)
208                report_it = *(Boolean *) value.addr ? Report : Ignore;
209            else if (rep_type == _XtQString) {
210                XrmValue toVal;
211                Boolean report = False;
212
213                toVal.addr = (XPointer) &report;
214                toVal.size = sizeof(Boolean);
215                if (XtCallConverter
216                    (dpy, XtCvtStringToBoolean, (XrmValuePtr) NULL,
217                     (Cardinal) 0, &value, &toVal, (XtCacheRef *) NULL))
218                    report_it = report ? Report : Ignore;
219            }
220            else
221                report_it = Report;
222        }
223        else
224            report_it = Report;
225    }
226
227    if (report_it == Report) {
228#endif                          /* ifndef NO_MIT_HACKS */
229        String params[2];
230        Cardinal num_params = 2;
231
232        params[0] = (String) from;
233        params[1] = (String) toType;
234        XtAppWarningMsg(app,
235                        XtNconversionError, "string", XtCXtToolkitError,
236                        "Cannot convert string \"%s\" to type %s",
237                        params, &num_params);
238#ifndef NO_MIT_HACKS
239    }
240#endif                          /* ifndef NO_MIT_HACKS */
241    UNLOCK_PROCESS;
242    UNLOCK_APP(app);
243}
244
245void
246XtStringConversionWarning(_Xconst char *from, _Xconst char *toType)
247{
248    String params[2];
249    Cardinal num_params = 2;
250
251    params[0] = (String) from;
252    params[1] = (String) toType;
253    XtWarningMsg(XtNconversionError, "string", XtCXtToolkitError,
254                 "Cannot convert string \"%s\" to type %s",
255                 params, &num_params);
256}
257
258static int CompareISOLatin1(const char *, const char *);
259
260static Boolean
261IsInteger(String string, int *value)
262{
263    Boolean foundDigit = False;
264    Boolean isNegative = False;
265    Boolean isPositive = False;
266    int val = 0;
267    char ch;
268
269    /* skip leading whitespace */
270    while ((ch = *string) == ' ' || ch == '\t')
271        string++;
272    while ((ch = *string++)) {
273        if (ch >= '0' && ch <= '9') {
274            val *= 10;
275            val += ch - '0';
276            foundDigit = True;
277            continue;
278        }
279        if (IsWhitespace(ch)) {
280            if (!foundDigit)
281                return False;
282            /* make sure only trailing whitespace */
283            while ((ch = *string++)) {
284                if (!IsWhitespace(ch))
285                    return False;
286            }
287            break;
288        }
289        if (ch == '-' && !foundDigit && !isNegative && !isPositive) {
290            isNegative = True;
291            continue;
292        }
293        if (ch == '+' && !foundDigit && !isNegative && !isPositive) {
294            isPositive = True;
295            continue;
296        }
297        return False;
298    }
299    if (ch == '\0') {
300        if (isNegative)
301            *value = -val;
302        else
303            *value = val;
304        return True;
305    }
306    return False;
307}
308
309Boolean
310XtCvtIntToBoolean(Display *dpy,
311                  XrmValuePtr args _X_UNUSED,
312                  Cardinal *num_args,
313                  XrmValuePtr fromVal,
314                  XrmValuePtr toVal,
315                  XtPointer *closure_ret _X_UNUSED)
316{
317    if (*num_args != 0)
318        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
319                        XtNwrongParameters, "cvtIntToBoolean",
320                        XtCXtToolkitError,
321                        "Integer to Boolean conversion needs no extra arguments",
322                        NULL, NULL);
323    done(Boolean, (*(int *) fromVal->addr != 0));
324}
325
326Boolean
327XtCvtIntToShort(Display *dpy,
328                XrmValuePtr args _X_UNUSED,
329                Cardinal *num_args,
330                XrmValuePtr fromVal,
331                XrmValuePtr toVal,
332                XtPointer *closure_ret _X_UNUSED)
333{
334    if (*num_args != 0)
335        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
336                        XtNwrongParameters, "cvtIntToShort", XtCXtToolkitError,
337                        "Integer to Short conversion needs no extra arguments",
338                        NULL, NULL);
339    done(short, (*(int *) fromVal->addr));
340}
341
342Boolean
343XtCvtStringToBoolean(Display *dpy,
344                     XrmValuePtr args _X_UNUSED,
345                     Cardinal *num_args,
346                     XrmValuePtr fromVal,
347                     XrmValuePtr toVal,
348                     XtPointer *closure_ret _X_UNUSED)
349{
350    String str = (String) fromVal->addr;
351
352    if (*num_args != 0)
353        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
354                        XtNwrongParameters, "cvtStringToBoolean",
355                        XtCXtToolkitError,
356                        "String to Boolean conversion needs no extra arguments",
357                        NULL, NULL);
358
359    if ((CompareISOLatin1(str, "true") == 0)
360        || (CompareISOLatin1(str, "yes") == 0)
361        || (CompareISOLatin1(str, "on") == 0)
362        || (CompareISOLatin1(str, "1") == 0))
363        done_string(Boolean, True, XtRBoolean);
364
365    if ((CompareISOLatin1(str, "false") == 0)
366        || (CompareISOLatin1(str, "no") == 0)
367        || (CompareISOLatin1(str, "off") == 0)
368        || (CompareISOLatin1(str, "0") == 0))
369        done_string(Boolean, False, XtRBoolean);
370
371    XtDisplayStringConversionWarning(dpy, str, XtRBoolean);
372    return False;
373}
374
375Boolean
376XtCvtIntToBool(Display *dpy,
377               XrmValuePtr args _X_UNUSED,
378               Cardinal *num_args,
379               XrmValuePtr fromVal,
380               XrmValuePtr toVal,
381               XtPointer *closure_ret _X_UNUSED)
382{
383    if (*num_args != 0)
384        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
385                        XtNwrongParameters, "cvtIntToBool", XtCXtToolkitError,
386                        "Integer to Bool conversion needs no extra arguments",
387                        NULL, NULL);
388    done(Bool, (*(int *) fromVal->addr != 0));
389}
390
391Boolean
392XtCvtStringToBool(Display *dpy,
393                  XrmValuePtr args _X_UNUSED,
394                  Cardinal *num_args,
395                  XrmValuePtr fromVal,
396                  XrmValuePtr toVal,
397                  XtPointer *closure_ret _X_UNUSED)
398{
399    String str = (String) fromVal->addr;
400
401    if (*num_args != 0)
402        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
403                        XtNwrongParameters, "cvtStringToBool",
404                        XtCXtToolkitError,
405                        "String to Bool conversion needs no extra arguments",
406                        NULL, NULL);
407
408    if ((CompareISOLatin1(str, "true") == 0)
409        || (CompareISOLatin1(str, "yes") == 0)
410        || (CompareISOLatin1(str, "on") == 0)
411        || (CompareISOLatin1(str, "1") == 0))
412        done_string(Bool, True, XtRBool);
413
414    if ((CompareISOLatin1(str, "false") == 0)
415        || (CompareISOLatin1(str, "no") == 0)
416        || (CompareISOLatin1(str, "off") == 0)
417        || (CompareISOLatin1(str, "0") == 0))
418        done_string(Bool, False, XtRBool);
419
420    XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRBool);
421    return False;
422}
423
424/* *INDENT-OFF* */
425XtConvertArgRec const colorConvertArgs[] = {
426    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
427     sizeof(Screen *)},
428    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
429     sizeof(Colormap)}
430};
431/* *INDENT-ON* */
432
433Boolean
434XtCvtIntToColor(Display *dpy,
435                XrmValuePtr args,
436                Cardinal *num_args,
437                XrmValuePtr fromVal,
438                XrmValuePtr toVal,
439                XtPointer *closure_ret _X_UNUSED)
440{
441    XColor c;
442    Screen *screen;
443    Colormap colormap;
444
445    if (*num_args != 2) {
446        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
447                        XtNwrongParameters, "cvtIntOrPixelToXColor",
448                        XtCXtToolkitError,
449                        "Pixel to color conversion needs screen and colormap arguments",
450                        NULL, NULL);
451        return False;
452    }
453    screen = *((Screen **) args[0].addr);
454    colormap = *((Colormap *) args[1].addr);
455    c.pixel = (unsigned long) (*(int *) fromVal->addr);
456
457    XQueryColor(DisplayOfScreen(screen), colormap, &c);
458    done_typed(XColor, c);
459}
460
461Boolean
462XtCvtStringToPixel(Display *dpy,
463                   XrmValuePtr args,
464                   Cardinal *num_args,
465                   XrmValuePtr fromVal,
466                   XrmValuePtr toVal,
467                   XtPointer *closure_ret)
468{
469    String str = (String) fromVal->addr;
470    XColor screenColor;
471    XColor exactColor;
472    Screen *screen;
473    XtPerDisplay pd = _XtGetPerDisplay(dpy);
474    Colormap colormap;
475    Status status;
476    Cardinal num_params = 1;
477
478    if (*num_args != 2) {
479        XtAppWarningMsg(pd->appContext, XtNwrongParameters, "cvtStringToPixel",
480                        XtCXtToolkitError,
481                        "String to pixel conversion needs screen and colormap arguments",
482                        NULL, NULL);
483        return False;
484    }
485
486    screen = *((Screen **) args[0].addr);
487    colormap = *((Colormap *) args[1].addr);
488
489    if (CompareISOLatin1(str, XtDefaultBackground) == 0) {
490        *closure_ret = NULL;
491        if (pd->rv) {
492            done_string(Pixel, BlackPixelOfScreen(screen), XtRPixel);
493        }
494        else {
495            done_string(Pixel, WhitePixelOfScreen(screen), XtRPixel);
496        }
497    }
498    if (CompareISOLatin1(str, XtDefaultForeground) == 0) {
499        *closure_ret = NULL;
500        if (pd->rv) {
501            done_string(Pixel, WhitePixelOfScreen(screen), XtRPixel);
502        }
503        else {
504            done_string(Pixel, BlackPixelOfScreen(screen), XtRPixel);
505        }
506    }
507
508    status = XAllocNamedColor(DisplayOfScreen(screen), colormap,
509                              (_Xconst char *) str, &screenColor, &exactColor);
510    if (status == 0) {
511        _Xconst _XtString msg;
512        _Xconst _XtString type;
513        String params[1];
514
515        params[0] = str;
516        /* Server returns a specific error code but Xlib discards it.  Ugh */
517        if (XLookupColor
518            (DisplayOfScreen(screen), colormap, (_Xconst char *) str,
519             &exactColor, &screenColor)) {
520            type = "noColormap";
521            msg = "Cannot allocate colormap entry for \"%s\"";
522        }
523        else {
524            type = "badValue";
525            msg = "Color name \"%s\" is not defined";
526        }
527
528        XtAppWarningMsg(pd->appContext, type, "cvtStringToPixel",
529                        XtCXtToolkitError, msg, params, &num_params);
530        *closure_ret = NULL;
531        return False;
532    }
533    else {
534        *closure_ret = (char *) True;
535        done_string(Pixel, screenColor.pixel, XtRPixel);
536    }
537}
538
539static void
540FreePixel(XtAppContext app,
541          XrmValuePtr toVal,
542          XtPointer closure,
543          XrmValuePtr args,
544          Cardinal *num_args)
545{
546    Screen *screen;
547    Colormap colormap;
548
549    if (*num_args != 2) {
550        XtAppWarningMsg(app, XtNwrongParameters, "freePixel", XtCXtToolkitError,
551                        "Freeing a pixel requires screen and colormap arguments",
552                        NULL, NULL);
553        return;
554    }
555
556    screen = *((Screen **) args[0].addr);
557    colormap = *((Colormap *) args[1].addr);
558
559    if (closure) {
560        XFreeColors(DisplayOfScreen(screen), colormap,
561                    (unsigned long *) toVal->addr, 1, (unsigned long) 0);
562    }
563}
564
565/* no longer used by Xt, but it's in the spec */
566XtConvertArgRec const screenConvertArg[] = {
567    {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.screen),
568     sizeof(Screen *)}
569};
570
571static void
572FetchDisplayArg(Widget widget, Cardinal *size _X_UNUSED, XrmValue *value)
573{
574    if (widget == NULL) {
575        XtErrorMsg("missingWidget", "fetchDisplayArg", XtCXtToolkitError,
576                   "FetchDisplayArg called without a widget to reference",
577                   NULL, NULL);
578        /* can't return any useful Display and caller will de-ref NULL,
579           so aborting is the only useful option */
580    }
581    else {
582        value->size = sizeof(Display *);
583        value->addr = (XPointer) &DisplayOfScreen(XtScreenOfObject(widget));
584    }
585}
586
587/* *INDENT-OFF* */
588static XtConvertArgRec const displayConvertArg[] = {
589    {XtProcedureArg, (XtPointer)FetchDisplayArg, 0},
590};
591/* *INDENT-ON* */
592
593Boolean
594XtCvtStringToCursor(Display *dpy,
595                    XrmValuePtr args,
596                    Cardinal *num_args,
597                    XrmValuePtr fromVal,
598                    XrmValuePtr toVal,
599                    XtPointer *closure_ret _X_UNUSED)
600{
601    /* *INDENT-OFF* */
602    static const struct _CursorName {
603        const char      *name;
604        unsigned int    shape;
605    } cursor_names[] = {
606        {"X_cursor",            XC_X_cursor},
607        {"arrow",               XC_arrow},
608        {"based_arrow_down",    XC_based_arrow_down},
609        {"based_arrow_up",      XC_based_arrow_up},
610        {"boat",                XC_boat},
611        {"bogosity",            XC_bogosity},
612        {"bottom_left_corner",  XC_bottom_left_corner},
613        {"bottom_right_corner", XC_bottom_right_corner},
614        {"bottom_side",         XC_bottom_side},
615        {"bottom_tee",          XC_bottom_tee},
616        {"box_spiral",          XC_box_spiral},
617        {"center_ptr",          XC_center_ptr},
618        {"circle",              XC_circle},
619        {"clock",               XC_clock},
620        {"coffee_mug",          XC_coffee_mug},
621        {"cross",               XC_cross},
622        {"cross_reverse",       XC_cross_reverse},
623        {"crosshair",           XC_crosshair},
624        {"diamond_cross",       XC_diamond_cross},
625        {"dot",                 XC_dot},
626        {"dotbox",              XC_dotbox},
627        {"double_arrow",        XC_double_arrow},
628        {"draft_large",         XC_draft_large},
629        {"draft_small",         XC_draft_small},
630        {"draped_box",          XC_draped_box},
631        {"exchange",            XC_exchange},
632        {"fleur",               XC_fleur},
633        {"gobbler",             XC_gobbler},
634        {"gumby",               XC_gumby},
635        {"hand1",               XC_hand1},
636        {"hand2",               XC_hand2},
637        {"heart",               XC_heart},
638        {"icon",                XC_icon},
639        {"iron_cross",          XC_iron_cross},
640        {"left_ptr",            XC_left_ptr},
641        {"left_side",           XC_left_side},
642        {"left_tee",            XC_left_tee},
643        {"leftbutton",          XC_leftbutton},
644        {"ll_angle",            XC_ll_angle},
645        {"lr_angle",            XC_lr_angle},
646        {"man",                 XC_man},
647        {"middlebutton",        XC_middlebutton},
648        {"mouse",               XC_mouse},
649        {"pencil",              XC_pencil},
650        {"pirate",              XC_pirate},
651        {"plus",                XC_plus},
652        {"question_arrow",      XC_question_arrow},
653        {"right_ptr",           XC_right_ptr},
654        {"right_side",          XC_right_side},
655        {"right_tee",           XC_right_tee},
656        {"rightbutton",         XC_rightbutton},
657        {"rtl_logo",            XC_rtl_logo},
658        {"sailboat",            XC_sailboat},
659        {"sb_down_arrow",       XC_sb_down_arrow},
660        {"sb_h_double_arrow",   XC_sb_h_double_arrow},
661        {"sb_left_arrow",       XC_sb_left_arrow},
662        {"sb_right_arrow",      XC_sb_right_arrow},
663        {"sb_up_arrow",         XC_sb_up_arrow},
664        {"sb_v_double_arrow",   XC_sb_v_double_arrow},
665        {"shuttle",             XC_shuttle},
666        {"sizing",              XC_sizing},
667        {"spider",              XC_spider},
668        {"spraycan",            XC_spraycan},
669        {"star",                XC_star},
670        {"target",              XC_target},
671        {"tcross",              XC_tcross},
672        {"top_left_arrow",      XC_top_left_arrow},
673        {"top_left_corner",     XC_top_left_corner},
674        {"top_right_corner",    XC_top_right_corner},
675        {"top_side",            XC_top_side},
676        {"top_tee",             XC_top_tee},
677        {"trek",                XC_trek},
678        {"ul_angle",            XC_ul_angle},
679        {"umbrella",            XC_umbrella},
680        {"ur_angle",            XC_ur_angle},
681        {"watch",               XC_watch},
682        {"xterm",               XC_xterm},
683    };
684    /* *INDENT-ON* */
685    const struct _CursorName *nP;
686    char *name = (char *) fromVal->addr;
687    register Cardinal i;
688
689    if (*num_args != 1) {
690        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
691                        XtNwrongParameters, "cvtStringToCursor",
692                        XtCXtToolkitError,
693                        "String to cursor conversion needs display argument",
694                        NULL, NULL);
695        return False;
696    }
697
698    for (i = 0, nP = cursor_names; i < XtNumber(cursor_names); i++, nP++) {
699        if (strcmp(name, nP->name) == 0) {
700            Display *display = *(Display **) args[0].addr;
701            Cursor cursor = XCreateFontCursor(display, nP->shape);
702
703            done_string(Cursor, cursor, XtRCursor);
704        }
705    }
706    XtDisplayStringConversionWarning(dpy, name, XtRCursor);
707    return False;
708}
709
710static void
711FreeCursor(XtAppContext app,
712           XrmValuePtr toVal,
713           XtPointer closure _X_UNUSED,
714           XrmValuePtr args,
715           Cardinal *num_args)
716{
717    Display *display;
718
719    if (*num_args != 1) {
720        XtAppWarningMsg(app,
721                        XtNwrongParameters, "freeCursor", XtCXtToolkitError,
722                        "Free Cursor requires display argument", NULL, NULL);
723        return;
724    }
725
726    display = *(Display **) args[0].addr;
727    XFreeCursor(display, *(Cursor *) toVal->addr);
728}
729
730Boolean
731XtCvtStringToDisplay(Display *dpy,
732                     XrmValuePtr args _X_UNUSED,
733                     Cardinal *num_args,
734                     XrmValuePtr fromVal,
735                     XrmValuePtr toVal,
736                     XtPointer *closure_ret _X_UNUSED)
737{
738    Display *d;
739
740    if (*num_args != 0)
741        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
742                        XtNwrongParameters, "cvtStringToDisplay",
743                        XtCXtToolkitError,
744                        "String to Display conversion needs no extra arguments",
745                        NULL, NULL);
746
747    d = XOpenDisplay((char *) fromVal->addr);
748    if (d != NULL)
749        done_string(Display *, d, XtRDisplay);
750
751    XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRDisplay);
752    return False;
753}
754
755Boolean
756XtCvtStringToFile(Display *dpy,
757                  XrmValuePtr args _X_UNUSED,
758                  Cardinal *num_args,
759                  XrmValuePtr fromVal,
760                  XrmValuePtr toVal,
761                  XtPointer *closure_ret _X_UNUSED)
762{
763    FILE *f;
764
765    if (*num_args != 0)
766        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
767                        XtNwrongParameters, "cvtStringToFile",
768                        XtCXtToolkitError,
769                        "String to File conversion needs no extra arguments",
770                        NULL, NULL);
771
772    f = fopen((char *) fromVal->addr, "r");
773    if (f != NULL)
774        done_string(FILE *, f, XtRFile);
775
776    XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRFile);
777    return False;
778}
779
780static void
781FreeFile(XtAppContext app,
782         XrmValuePtr toVal,
783         XtPointer closure _X_UNUSED,
784         XrmValuePtr args _X_UNUSED,
785         Cardinal *num_args)
786{
787    if (*num_args != 0)
788        XtAppWarningMsg(app,
789                        XtNwrongParameters, "freeFile", XtCXtToolkitError,
790                        "Free File requires no extra arguments", NULL, NULL);
791
792    fclose(*(FILE **) toVal->addr);
793}
794
795Boolean
796XtCvtIntToFloat(Display *dpy,
797                XrmValuePtr args _X_UNUSED,
798                Cardinal *num_args,
799                XrmValuePtr fromVal,
800                XrmValuePtr toVal,
801                XtPointer *closure_ret _X_UNUSED)
802{
803    if (*num_args != 0)
804        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
805                        XtNwrongParameters, "cvtIntToFloat", XtCXtToolkitError,
806                        "Integer to Float conversion needs no extra arguments",
807                        NULL, NULL);
808    done(float, (*(int *) fromVal->addr));
809}
810
811Boolean
812XtCvtStringToFloat(Display *dpy,
813                   XrmValuePtr args _X_UNUSED,
814                   Cardinal *num_args,
815                   XrmValuePtr fromVal,
816                   XrmValuePtr toVal,
817                   XtPointer *closure_ret _X_UNUSED)
818{
819    int ret;
820    float f, nan = 0.0;
821
822    (void) sscanf("NaN", "%g",
823                  toVal->addr != NULL ? (float *) toVal->addr : &nan);
824
825    if (*num_args != 0)
826        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
827                        XtNwrongParameters, "cvtStringToFloat",
828                        XtCXtToolkitError,
829                        "String to Float conversion needs no extra arguments",
830                        NULL, NULL);
831
832    ret = sscanf(fromVal->addr, "%g", &f);
833    if (ret == 0) {
834        if (toVal->addr != NULL && toVal->size == sizeof nan)
835            *(float *) toVal->addr = nan;
836        XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRFloat);
837        return False;
838    }
839    done_string(float, f, XtRFloat);
840}
841
842Boolean
843XtCvtStringToFont(Display *dpy,
844                  XrmValuePtr args,
845                  Cardinal *num_args,
846                  XrmValuePtr fromVal,
847                  XrmValuePtr toVal,
848                  XtPointer *closure_ret _X_UNUSED)
849{
850    Font f;
851    Display *display;
852
853    if (*num_args != 1) {
854        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
855                        XtNwrongParameters, "cvtStringToFont",
856                        XtCXtToolkitError,
857                        "String to font conversion needs display argument",
858                        NULL, NULL);
859        return False;
860    }
861
862    display = *(Display **) args[0].addr;
863
864    if (CompareISOLatin1((String) fromVal->addr, XtDefaultFont) != 0) {
865        f = XLoadFont(display, (char *) fromVal->addr);
866
867        if (f != 0) {
868 Done:     done_string(Font, f, XtRFont);
869        }
870        XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRFont);
871    }
872    /* try and get the default font */
873
874    {
875        XrmName xrm_name[2];
876        XrmClass xrm_class[2];
877        XrmRepresentation rep_type;
878        XrmValue value;
879
880        xrm_name[0] = XrmPermStringToQuark("xtDefaultFont");
881        xrm_name[1] = 0;
882        xrm_class[0] = XrmPermStringToQuark("XtDefaultFont");
883        xrm_class[1] = 0;
884        if (XrmQGetResource(XtDatabase(display), xrm_name, xrm_class,
885                            &rep_type, &value)) {
886            if (rep_type == _XtQString) {
887                f = XLoadFont(display, (char *) value.addr);
888
889                if (f != 0)
890                    goto Done;
891                else
892                    XtDisplayStringConversionWarning(dpy, (char *) value.addr,
893                                                     XtRFont);
894            }
895            else if (rep_type == XtQFont) {
896                f = *(Font *) value.addr;
897                goto Done;
898            }
899            else if (rep_type == XtQFontStruct) {
900                f = ((XFontStruct *) value.addr)->fid;
901                goto Done;
902            }
903        }
904    }
905    /* Should really do XListFonts, but most servers support this */
906    f = XLoadFont(display, "-*-*-*-R-*-*-*-120-*-*-*-*-ISO8859-*");
907
908    if (f != 0)
909        goto Done;
910
911    XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
912                    "noFont", "cvtStringToFont", XtCXtToolkitError,
913                    "Unable to load any usable ISO8859 font", NULL, NULL);
914
915    return False;
916}
917
918static void
919FreeFont(XtAppContext app,
920         XrmValuePtr toVal,
921         XtPointer closure _X_UNUSED,
922         XrmValuePtr args,
923         Cardinal *num_args)
924{
925    Display *display;
926
927    if (*num_args != 1) {
928        XtAppWarningMsg(app,
929                        XtNwrongParameters, "freeFont", XtCXtToolkitError,
930                        "Free Font needs display argument", NULL, NULL);
931        return;
932    }
933
934    display = *(Display **) args[0].addr;
935    XUnloadFont(display, *(Font *) toVal->addr);
936}
937
938Boolean
939XtCvtIntToFont(Display *dpy,
940               XrmValuePtr args _X_UNUSED,
941               Cardinal *num_args,
942               XrmValuePtr fromVal,
943               XrmValuePtr toVal,
944               XtPointer *closure_ret _X_UNUSED)
945{
946    if (*num_args != 0)
947        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
948                        XtNwrongParameters, "cvtIntToFont", XtCXtToolkitError,
949                        "Integer to Font conversion needs no extra arguments",
950                        NULL, NULL);
951    done(Font, *(int *) fromVal->addr);
952}
953
954Boolean
955XtCvtStringToFontSet(Display *dpy,
956                     XrmValuePtr args,
957                     Cardinal *num_args,
958                     XrmValuePtr fromVal,
959                     XrmValuePtr toVal,
960                     XtPointer *closure_ret _X_UNUSED)
961{
962    XFontSet f;
963    Display *display;
964    char **missing_charset_list;
965    int missing_charset_count;
966    char *def_string;
967
968    if (*num_args != 2) {
969        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
970                        XtNwrongParameters, "cvtStringToFontSet",
971                        XtCXtToolkitError,
972                        "String to FontSet conversion needs display and locale arguments",
973                        NULL, NULL);
974        return False;
975    }
976
977    display = *(Display **) args[0].addr;
978
979    if (CompareISOLatin1((String) fromVal->addr, XtDefaultFontSet) != 0) {
980        f = XCreateFontSet(display, (char *) fromVal->addr,
981                           &missing_charset_list, &missing_charset_count,
982                           &def_string);
983        /* Free any returned missing charset list */
984        if (missing_charset_count) {
985            XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
986                            XtNmissingCharsetList, "cvtStringToFontSet",
987                            XtCXtToolkitError,
988                            "Missing charsets in String to FontSet conversion",
989                            NULL, NULL);
990            XFreeStringList(missing_charset_list);
991        }
992        if (f != NULL) {
993 Done:     done_string(XFontSet, f, XtRFontSet);
994        }
995        XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr,
996                                         XtRFontSet);
997    }
998    /* try and get the default fontset */
999
1000    {
1001        XrmName xrm_name[2];
1002        XrmClass xrm_class[2];
1003        XrmRepresentation rep_type;
1004        XrmValue value;
1005
1006        xrm_name[0] = XrmPermStringToQuark("xtDefaultFontSet");
1007        xrm_name[1] = 0;
1008        xrm_class[0] = XrmPermStringToQuark("XtDefaultFontSet");
1009        xrm_class[1] = 0;
1010        if (XrmQGetResource(XtDatabase(display), xrm_name, xrm_class,
1011                            &rep_type, &value)) {
1012            if (rep_type == _XtQString) {
1013
1014                f = XCreateFontSet(display, (char *) value.addr,
1015                                   &missing_charset_list,
1016                                   &missing_charset_count, &def_string);
1017                /* Free any returned missing charset list */
1018                if (missing_charset_count) {
1019                    XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1020                                    XtNmissingCharsetList, "cvtStringToFontSet",
1021                                    XtCXtToolkitError,
1022                                    "Missing charsets in String to FontSet conversion",
1023                                    NULL, NULL);
1024                    XFreeStringList(missing_charset_list);
1025                }
1026                if (f != NULL)
1027                    goto Done;
1028                else
1029                    XtDisplayStringConversionWarning(dpy, (char *) value.addr,
1030                                                     XtRFontSet);
1031            }
1032            else if (rep_type == XtQFontSet) {
1033                f = *(XFontSet *) value.addr;
1034                goto Done;
1035            }
1036        }
1037    }
1038
1039    /* Should really do XListFonts, but most servers support this */
1040    f = XCreateFontSet(display, "-*-*-*-R-*-*-*-120-*-*-*-*,*",
1041                       &missing_charset_list, &missing_charset_count,
1042                       &def_string);
1043
1044    /* Free any returned missing charset list */
1045    if (missing_charset_count) {
1046        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1047                        XtNmissingCharsetList, "cvtStringToFontSet",
1048                        XtCXtToolkitError,
1049                        "Missing charsets in String to FontSet conversion",
1050                        NULL, NULL);
1051        XFreeStringList(missing_charset_list);
1052    }
1053    if (f != NULL)
1054        goto Done;
1055
1056    XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1057                    "noFont", "cvtStringToFontSet", XtCXtToolkitError,
1058                    "Unable to load any usable fontset", NULL, NULL);
1059
1060    return False;
1061}
1062
1063static void
1064FreeFontSet(XtAppContext app,
1065            XrmValuePtr toVal,
1066            XtPointer closure _X_UNUSED,
1067            XrmValuePtr args,
1068            Cardinal *num_args)
1069{
1070    Display *display;
1071
1072    if (*num_args != 2) {
1073        XtAppWarningMsg(app,
1074                        XtNwrongParameters, "freeFontSet", XtCXtToolkitError,
1075                        "FreeFontSet needs display and locale arguments",
1076                        NULL, NULL);
1077        return;
1078    }
1079
1080    display = *(Display **) args[0].addr;
1081    XFreeFontSet(display, *(XFontSet *) toVal->addr);
1082}
1083
1084static void
1085FetchLocaleArg(Widget widget _X_UNUSED,
1086               Cardinal *size _X_UNUSED,
1087               XrmValue *value)
1088{
1089    static XrmString locale;
1090
1091    locale = XrmQuarkToString(XrmStringToQuark
1092                              (setlocale(LC_CTYPE, (char *) NULL)));
1093    value->size = sizeof(XrmString);
1094    value->addr = (XPointer) &locale;
1095}
1096
1097/* *INDENT-OFF* */
1098static XtConvertArgRec const localeDisplayConvertArgs[] = {
1099    {XtProcedureArg, (XtPointer)FetchDisplayArg, 0},
1100    {XtProcedureArg, (XtPointer)FetchLocaleArg, 0},
1101};
1102/* *INDENT-ON* */
1103
1104Boolean
1105XtCvtStringToFontStruct(Display *dpy,
1106                        XrmValuePtr args,
1107                        Cardinal *num_args,
1108                        XrmValuePtr fromVal,
1109                        XrmValuePtr toVal,
1110                        XtPointer *closure_ret _X_UNUSED)
1111{
1112    XFontStruct *f;
1113    Display *display;
1114
1115    if (*num_args != 1) {
1116        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1117                        XtNwrongParameters, "cvtStringToFontStruct",
1118                        XtCXtToolkitError,
1119                        "String to font conversion needs display argument",
1120                        NULL, NULL);
1121        return False;
1122    }
1123
1124    display = *(Display **) args[0].addr;
1125
1126    if (CompareISOLatin1((String) fromVal->addr, XtDefaultFont) != 0) {
1127        f = XLoadQueryFont(display, (char *) fromVal->addr);
1128
1129        if (f != NULL) {
1130 Done:     done_string(XFontStruct *, f, XtRFontStruct);
1131        }
1132
1133        XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr,
1134                                         XtRFontStruct);
1135    }
1136
1137    /* try and get the default font */
1138
1139    {
1140        XrmName xrm_name[2];
1141        XrmClass xrm_class[2];
1142        XrmRepresentation rep_type;
1143        XrmValue value;
1144
1145        xrm_name[0] = XrmPermStringToQuark("xtDefaultFont");
1146        xrm_name[1] = 0;
1147        xrm_class[0] = XrmPermStringToQuark("XtDefaultFont");
1148        xrm_class[1] = 0;
1149        if (XrmQGetResource(XtDatabase(display), xrm_name, xrm_class,
1150                            &rep_type, &value)) {
1151            if (rep_type == _XtQString) {
1152                f = XLoadQueryFont(display, (char *) value.addr);
1153
1154                if (f != NULL)
1155                    goto Done;
1156                else
1157                    XtDisplayStringConversionWarning(dpy, (char *) value.addr,
1158                                                     XtRFontStruct);
1159            }
1160            else if (rep_type == XtQFont) {
1161                f = XQueryFont(display, *(Font *) value.addr);
1162
1163                if (f != NULL)
1164                    goto Done;
1165            }
1166            else if (rep_type == XtQFontStruct) {
1167                f = (XFontStruct *) value.addr;
1168                goto Done;
1169            }
1170        }
1171    }
1172    /* Should really do XListFonts, but most servers support this */
1173    f = XLoadQueryFont(display, "-*-*-*-R-*-*-*-120-*-*-*-*-ISO8859-*");
1174
1175    if (f != NULL)
1176        goto Done;
1177
1178    XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1179                    "noFont", "cvtStringToFontStruct", XtCXtToolkitError,
1180                    "Unable to load any usable ISO8859 font", NULL, NULL);
1181
1182    return False;
1183}
1184
1185static void
1186FreeFontStruct(XtAppContext app,
1187               XrmValuePtr toVal,
1188               XtPointer closure _X_UNUSED,
1189               XrmValuePtr args,
1190               Cardinal *num_args)
1191{
1192    Display *display;
1193
1194    if (*num_args != 1) {
1195        XtAppWarningMsg(app,
1196                        XtNwrongParameters, "freeFontStruct", XtCXtToolkitError,
1197                        "Free FontStruct requires display argument",
1198                        NULL, NULL);
1199        return;
1200    }
1201
1202    display = *(Display **) args[0].addr;
1203    XFreeFont(display, *(XFontStruct **) toVal->addr);
1204}
1205
1206Boolean
1207XtCvtStringToInt(Display *dpy,
1208                 XrmValuePtr args _X_UNUSED,
1209                 Cardinal *num_args,
1210                 XrmValuePtr fromVal,
1211                 XrmValuePtr toVal,
1212                 XtPointer *closure_ret _X_UNUSED)
1213{
1214    int i;
1215
1216    if (*num_args != 0)
1217        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1218                        XtNwrongParameters, "cvtStringToInt", XtCXtToolkitError,
1219                        "String to Integer conversion needs no extra arguments",
1220                        NULL, NULL);
1221    if (IsInteger((String) fromVal->addr, &i))
1222        done_string(int, i, XtRInt);
1223
1224    XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRInt);
1225    return False;
1226}
1227
1228Boolean
1229XtCvtStringToShort(Display *dpy,
1230                   XrmValuePtr args _X_UNUSED,
1231                   Cardinal *num_args,
1232                   XrmValuePtr fromVal,
1233                   XrmValuePtr toVal,
1234                   XtPointer *closure_ret _X_UNUSED)
1235{
1236    int i;
1237
1238    if (*num_args != 0)
1239        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1240                        XtNwrongParameters, "cvtStringToShort",
1241                        XtCXtToolkitError,
1242                        "String to Integer conversion needs no extra arguments",
1243                        NULL, NULL);
1244    if (IsInteger((String) fromVal->addr, &i))
1245        done_string(short, (short) i, XtRShort);
1246
1247    XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRShort);
1248    return False;
1249}
1250
1251Boolean
1252XtCvtStringToDimension(Display *dpy,
1253                       XrmValuePtr args _X_UNUSED,
1254                       Cardinal *num_args,
1255                       XrmValuePtr fromVal,
1256                       XrmValuePtr toVal,
1257                       XtPointer *closure_ret _X_UNUSED)
1258{
1259    int i;
1260
1261    if (*num_args != 0)
1262        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1263                        XtNwrongParameters, "cvtStringToDimension",
1264                        XtCXtToolkitError,
1265                        "String to Dimension conversion needs no extra arguments",
1266                        NULL, NULL);
1267    if (IsInteger((String) fromVal->addr, &i)) {
1268        if (i < 0)
1269            XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr,
1270                                             XtRDimension);
1271        done_string(Dimension, (Dimension) i, XtRDimension);
1272    }
1273    XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRDimension);
1274    return False;
1275}
1276
1277Boolean
1278XtCvtIntToUnsignedChar(Display *dpy,
1279                       XrmValuePtr args _X_UNUSED,
1280                       Cardinal *num_args,
1281                       XrmValuePtr fromVal,
1282                       XrmValuePtr toVal,
1283                       XtPointer *closure_ret _X_UNUSED)
1284{
1285    if (*num_args != 0)
1286        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1287                        XtNwrongParameters, "cvtIntToUnsignedChar",
1288                        XtCXtToolkitError,
1289                        "Integer to UnsignedChar conversion needs no extra arguments",
1290                        NULL, NULL);
1291    done(unsigned char, (*(int *) fromVal->addr));
1292}
1293
1294Boolean
1295XtCvtStringToUnsignedChar(Display *dpy,
1296                          XrmValuePtr args _X_UNUSED,
1297                          Cardinal *num_args,
1298                          XrmValuePtr fromVal,
1299                          XrmValuePtr toVal,
1300                          XtPointer *closure_ret _X_UNUSED)
1301{
1302    int i;
1303
1304    if (*num_args != 0)
1305        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1306                        XtNwrongParameters, "cvtStringToUnsignedChar",
1307                        XtCXtToolkitError,
1308                        "String to Integer conversion needs no extra arguments",
1309                        NULL, NULL);
1310    if (IsInteger((String) fromVal->addr, &i)) {
1311        if (i < 0 || i > 255)
1312            XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr,
1313                                             XtRUnsignedChar);
1314        done_string(unsigned char, i, XtRUnsignedChar);
1315    }
1316    XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr,
1317                                     XtRUnsignedChar);
1318    return False;
1319}
1320
1321Boolean
1322XtCvtColorToPixel(Display *dpy,
1323                  XrmValuePtr args _X_UNUSED,
1324                  Cardinal *num_args,
1325                  XrmValuePtr fromVal,
1326                  XrmValuePtr toVal,
1327                  XtPointer *closure_ret _X_UNUSED)
1328{
1329    if (*num_args != 0)
1330        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1331                        XtNwrongParameters, "cvtXColorToPixel",
1332                        XtCXtToolkitError,
1333                        "Color to Pixel conversion needs no extra arguments",
1334                        NULL, NULL);
1335    done(Pixel, ((XColor *) fromVal->addr)->pixel);
1336}
1337
1338Boolean
1339XtCvtIntToPixel(Display *dpy,
1340                XrmValuePtr args _X_UNUSED,
1341                Cardinal *num_args,
1342                XrmValuePtr fromVal,
1343                XrmValuePtr toVal,
1344                XtPointer *closure_ret _X_UNUSED)
1345{
1346    if (*num_args != 0)
1347        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1348                        XtNwrongParameters, "cvtIntToPixel", XtCXtToolkitError,
1349                        "Integer to Pixel conversion needs no extra arguments",
1350                        NULL, NULL);
1351    done(Pixel, *(int *) fromVal->addr);
1352}
1353
1354Boolean
1355XtCvtIntToPixmap(Display *dpy,
1356                 XrmValuePtr args _X_UNUSED,
1357                 Cardinal *num_args,
1358                 XrmValuePtr fromVal,
1359                 XrmValuePtr toVal,
1360                 XtPointer *closure_ret _X_UNUSED)
1361{
1362    if (*num_args != 0)
1363        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1364                        XtNwrongParameters, "cvtIntToPixmap", XtCXtToolkitError,
1365                        "Integer to Pixmap conversion needs no extra arguments",
1366                        NULL, NULL);
1367    done(Pixmap, *(int *) fromVal->addr);
1368}
1369
1370#ifdef MOTIFBC
1371void
1372LowerCase(register char *source, register *dest)
1373{
1374    register char ch;
1375    int i;
1376
1377    for (i = 0; (ch = *source) != 0 && i < 999; source++, dest++, i++) {
1378        if ('A' <= ch && ch <= 'Z')
1379            *dest = ch - 'A' + 'a';
1380        else
1381            *dest = ch;
1382    }
1383    *dest = 0;
1384}
1385#endif
1386
1387static int
1388CompareISOLatin1(const char *first, const char *second)
1389{
1390    register const unsigned char *ap, *bp;
1391
1392    for (ap = (const unsigned char *) first,
1393         bp = (const unsigned char *) second; *ap && *bp; ap++, bp++) {
1394        register unsigned char a, b;
1395
1396        if ((a = *ap) != (b = *bp)) {
1397            /* try lowercasing and try again */
1398
1399            if ((a >= XK_A) && (a <= XK_Z))
1400                a = (unsigned char) (a + (XK_a - XK_A));
1401            else if ((a >= XK_Agrave) && (a <= XK_Odiaeresis))
1402                a = (unsigned char) (a + (XK_agrave - XK_Agrave));
1403            else if ((a >= XK_Ooblique) && (a <= XK_Thorn))
1404                a = (unsigned char) (a + (XK_oslash - XK_Ooblique));
1405
1406            if ((b >= XK_A) && (b <= XK_Z))
1407                b = (unsigned char) (b + (XK_a - XK_A));
1408            else if ((b >= XK_Agrave) && (b <= XK_Odiaeresis))
1409                b = (unsigned char) (b + (XK_agrave - XK_Agrave));
1410            else if ((b >= XK_Ooblique) && (b <= XK_Thorn))
1411                b = (unsigned char) (b + (XK_oslash - XK_Ooblique));
1412
1413            if (a != b)
1414                break;
1415        }
1416    }
1417    return (((int) *bp) - ((int) *ap));
1418}
1419
1420static void
1421CopyISOLatin1Lowered(char *dst, const char *src)
1422{
1423    unsigned char *dest = (unsigned char *) dst;
1424    const unsigned char *source = (const unsigned char *) src;
1425
1426    for (; *source; source++, dest++) {
1427        if (*source >= XK_A && *source <= XK_Z)
1428            *dest = (unsigned char) (*source + (XK_a - XK_A));
1429        else if (*source >= XK_Agrave && *source <= XK_Odiaeresis)
1430            *dest = (unsigned char) (*source + (XK_agrave - XK_Agrave));
1431        else if (*source >= XK_Ooblique && *source <= XK_Thorn)
1432            *dest = (unsigned char) (*source + (XK_oslash - XK_Ooblique));
1433        else
1434            *dest = *source;
1435    }
1436    *dest = '\0';
1437}
1438
1439Boolean
1440XtCvtStringToInitialState(Display *dpy,
1441                          XrmValuePtr args _X_UNUSED,
1442                          Cardinal *num_args,
1443                          XrmValuePtr fromVal,
1444                          XrmValuePtr toVal,
1445                          XtPointer *closure_ret _X_UNUSED)
1446{
1447    String str = (String) fromVal->addr;
1448
1449    if (*num_args != 0)
1450        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1451                        XtNwrongParameters, "cvtStringToInitialState",
1452                        XtCXtToolkitError,
1453                        "String to InitialState conversion needs no extra arguments",
1454                        NULL, NULL);
1455
1456    if (CompareISOLatin1(str, "NormalState") == 0)
1457        done_string(int, NormalState, XtRInitialState);
1458
1459    if (CompareISOLatin1(str, "IconicState") == 0)
1460        done_string(int, IconicState, XtRInitialState);
1461
1462    {
1463        int val;
1464
1465        if (IsInteger(str, &val))
1466            done_string(int, val, XtRInitialState);
1467    }
1468    XtDisplayStringConversionWarning(dpy, str, XtRInitialState);
1469    return False;
1470}
1471
1472/* *INDENT-OFF* */
1473static XtConvertArgRec const visualConvertArgs[] = {
1474    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
1475     sizeof(Screen *)},
1476    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.depth),
1477     sizeof(Cardinal)}
1478};
1479/* *INDENT-ON* */
1480
1481Boolean
1482XtCvtStringToVisual(Display *dpy, XrmValuePtr args,     /* Screen, depth */
1483                    Cardinal *num_args,        /* 2 */
1484                    XrmValuePtr fromVal,
1485                    XrmValuePtr toVal,
1486                    XtPointer *closure_ret _X_UNUSED)
1487{
1488    String str = (String) fromVal->addr;
1489    int vc;
1490    XVisualInfo vinfo;
1491
1492    if (*num_args != 2) {
1493        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1494                        XtNwrongParameters, "cvtStringToVisual",
1495                        XtCXtToolkitError,
1496                        "String to Visual conversion needs screen and depth arguments",
1497                        NULL, NULL);
1498        return False;
1499    }
1500
1501    if (CompareISOLatin1(str, "StaticGray") == 0)
1502        vc = StaticGray;
1503    else if (CompareISOLatin1(str, "StaticColor") == 0)
1504        vc = StaticColor;
1505    else if (CompareISOLatin1(str, "TrueColor") == 0)
1506        vc = TrueColor;
1507    else if (CompareISOLatin1(str, "GrayScale") == 0)
1508        vc = GrayScale;
1509    else if (CompareISOLatin1(str, "PseudoColor") == 0)
1510        vc = PseudoColor;
1511    else if (CompareISOLatin1(str, "DirectColor") == 0)
1512        vc = DirectColor;
1513    else if (!IsInteger(str, &vc)) {
1514        XtDisplayStringConversionWarning(dpy, str, "Visual class name");
1515        return False;
1516    }
1517
1518    if (XMatchVisualInfo(XDisplayOfScreen((Screen *) *(Screen **) args[0].addr),
1519                         XScreenNumberOfScreen((Screen *) *(Screen **) args[0].
1520                                               addr),
1521                         (int) *(int *) args[1].addr, vc, &vinfo)) {
1522        done_string(Visual *, vinfo.visual, XtRVisual);
1523    }
1524    else {
1525        String params[2];
1526        Cardinal num_params = 2;
1527
1528        params[0] = str;
1529        params[1] =
1530            DisplayString(XDisplayOfScreen
1531                          ((Screen *) *(Screen **) args[0].addr));
1532        XtAppWarningMsg(XtDisplayToApplicationContext(dpy), XtNconversionError,
1533                        "stringToVisual", XtCXtToolkitError,
1534                        "Cannot find Visual of class %s for display %s", params,
1535                        &num_params);
1536        return False;
1537    }
1538}
1539
1540Boolean
1541XtCvtStringToAtom(Display *dpy,
1542                  XrmValuePtr args,
1543                  Cardinal *num_args,
1544                  XrmValuePtr fromVal,
1545                  XrmValuePtr toVal,
1546                  XtPointer *closure_ret _X_UNUSED)
1547{
1548    Atom atom;
1549
1550    if (*num_args != 1) {
1551        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1552                        XtNwrongParameters, "cvtStringToAtom",
1553                        XtCXtToolkitError,
1554                        "String to Atom conversion needs Display argument",
1555                        NULL, NULL);
1556        return False;
1557    }
1558
1559    atom = XInternAtom(*(Display **) args->addr, (char *) fromVal->addr, False);
1560    done_string(Atom, atom, XtRAtom);
1561}
1562
1563Boolean
1564XtCvtStringToDirectoryString(Display *dpy,
1565                             XrmValuePtr args _X_UNUSED,
1566                             Cardinal *num_args,
1567                             XrmValuePtr fromVal,
1568                             XrmValuePtr toVal,
1569                             XtPointer *closure_ret _X_UNUSED)
1570{
1571    String str;
1572    char directory[PATH_MAX + 1];
1573
1574    if (*num_args != 0)
1575        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1576                        XtNwrongParameters, "cvtStringToDirectoryString",
1577                        XtCXtToolkitError,
1578                        "String to DirectoryString conversion needs no extra arguments",
1579                        NULL, NULL);
1580
1581    str = (String) fromVal->addr;
1582    if (CompareISOLatin1(str, "XtCurrentDirectory") == 0) {
1583        /* uglier, but does not depend on compiler knowing return type */
1584#if !defined(X_NOT_POSIX) || defined(SYSV) || defined(WIN32)
1585        if (getcwd(directory, PATH_MAX + 1))
1586            str = directory;
1587#else
1588        if (getwd(directory))
1589            str = directory;
1590#endif
1591        if (!str) {
1592            if (errno == EACCES)
1593                errno = 0;      /* reset errno */
1594            XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr,
1595                                             XtRDirectoryString);
1596            return False;
1597        }
1598    }
1599
1600    /* Since memory from the resource database or from static buffers of
1601     * system libraries may be freed or overwritten, allocate memory.
1602     * The memory is freed when all cache references are released.
1603     */
1604    str = XtNewString(str);
1605    done_string(String, str, XtRDirectoryString);
1606}
1607
1608static void
1609FreeDirectoryString(XtAppContext app,
1610                    XrmValuePtr toVal,
1611                    XtPointer closure _X_UNUSED,
1612                    XrmValuePtr args _X_UNUSED,
1613                    Cardinal *num_args)
1614{
1615    if (*num_args != 0)
1616        XtAppWarningMsg(app,
1617                        XtNwrongParameters, "freeDirectoryString",
1618                        XtCXtToolkitError,
1619                        "Free Directory String requires no extra arguments",
1620                        NULL, NULL);
1621
1622    XtFree((char *) toVal->addr);
1623}
1624
1625Boolean
1626XtCvtStringToRestartStyle(Display *dpy,
1627                          XrmValuePtr args _X_UNUSED,
1628                          Cardinal *num_args,
1629                          XrmValuePtr fromVal,
1630                          XrmValuePtr toVal,
1631                          XtPointer *closure_ret _X_UNUSED)
1632{
1633    String str = (String) fromVal->addr;
1634
1635    if (*num_args != 0)
1636        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1637                        XtNwrongParameters, "cvtStringToRestartStyle",
1638                        XtCXtToolkitError,
1639                        "String to RestartStyle conversion needs no extra arguments",
1640                        NULL, NULL);
1641
1642    if (CompareISOLatin1(str, "RestartIfRunning") == 0)
1643        done_string(unsigned char, SmRestartIfRunning, XtRRestartStyle);
1644
1645    if (CompareISOLatin1(str, "RestartAnyway") == 0)
1646        done_string(unsigned char, SmRestartAnyway, XtRRestartStyle);
1647
1648    if (CompareISOLatin1(str, "RestartImmediately") == 0)
1649        done_string(unsigned char, SmRestartImmediately, XtRRestartStyle);
1650
1651    if (CompareISOLatin1(str, "RestartNever") == 0)
1652        done_string(unsigned char, SmRestartNever, XtRRestartStyle);
1653
1654    XtDisplayStringConversionWarning(dpy, str, XtRRestartStyle);
1655    return False;
1656}
1657
1658Boolean
1659XtCvtStringToCommandArgArray(Display *dpy,
1660                             XrmValuePtr args _X_UNUSED,
1661                             Cardinal *num_args,
1662                             XrmValuePtr fromVal,
1663                             XrmValuePtr toVal,
1664                             XtPointer *closure_ret)
1665{
1666    String *strarray, *ptr;
1667    char *src;
1668    char *dst, *dst_str;
1669    int tokens, len;
1670
1671    if (*num_args != 0)
1672        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1673                        XtNwrongParameters, "cvtStringToCommandArgArray",
1674                        XtCXtToolkitError,
1675                        "String to CommandArgArray conversion needs no extra arguments",
1676                        NULL, NULL);
1677
1678    src = fromVal->addr;
1679    dst = dst_str = __XtMalloc((unsigned) strlen(src) + 1);
1680    tokens = 0;
1681
1682    while (*src != '\0') {
1683        char *start;
1684
1685        /* skip whitespace */
1686        while (IsWhitespace(*src) || IsNewline(*src))
1687            src++;
1688        /* test for end of string */
1689        if (*src == '\0')
1690            break;
1691
1692        /* start new token */
1693        tokens++;
1694        start = src;
1695        while (*src != '\0' && !IsWhitespace(*src) && !IsNewline(*src)) {
1696            if (*src == '\\' &&
1697                (IsWhitespace(*(src + 1)) || IsNewline(*(src + 1)))) {
1698                len = (int) (src - start);
1699                if (len) {
1700                    /* copy preceding part of token */
1701                    memcpy(dst, start, (size_t) len);
1702                    dst += len;
1703                }
1704                /* skip backslash */
1705                src++;
1706                /* next part of token starts at whitespace */
1707                start = src;
1708            }
1709            src++;
1710        }
1711        len = (int) (src - start);
1712        if (len) {
1713            /* copy last part of token */
1714            memcpy(dst, start, (size_t) len);
1715            dst += len;
1716        }
1717        *dst = '\0';
1718        if (*src != '\0')
1719            dst++;
1720    }
1721
1722    ptr = strarray = XtMallocArray((Cardinal) tokens + 1,
1723                                   (Cardinal) sizeof(String));
1724    src = dst_str;
1725    while (--tokens >= 0) {
1726        *ptr = src;
1727        ptr++;
1728        if (tokens) {
1729            len = (int) strlen(src);
1730            src = src + len + 1;
1731        }
1732    }
1733    *ptr = NULL;
1734
1735    *closure_ret = (XtPointer) strarray;
1736    done_typed_string(String *, strarray, XtRCommandArgArray)
1737}
1738
1739static void
1740ArgArrayDestructor(XtAppContext app _X_UNUSED,
1741                   XrmValuePtr toVal _X_UNUSED,
1742                   XtPointer closure,
1743                   XrmValuePtr args _X_UNUSED,
1744                   Cardinal *num_args _X_UNUSED)
1745{
1746    if (closure) {
1747        _XtString *strarray = (_XtString *) closure;
1748
1749        XtFree(*strarray);
1750        XtFree((char *) strarray);
1751    }
1752}
1753
1754Boolean
1755XtCvtStringToGravity(Display *dpy,
1756                     XrmValuePtr args _X_UNUSED,
1757                     Cardinal *num_args,
1758                     XrmValuePtr fromVal,
1759                     XrmValuePtr toVal,
1760                     XtPointer *closure_ret _X_UNUSED)
1761{
1762    /* *INDENT-OFF* */
1763    static struct _namepair {
1764        XrmQuark quark;
1765        const char *name;
1766        int gravity;
1767    } names[] = {
1768        { NULLQUARK, "forget",          ForgetGravity },
1769        { NULLQUARK, "northwest",       NorthWestGravity },
1770        { NULLQUARK, "north",           NorthGravity },
1771        { NULLQUARK, "northeast",       NorthEastGravity },
1772        { NULLQUARK, "west",            WestGravity },
1773        { NULLQUARK, "center",          CenterGravity },
1774        { NULLQUARK, "east",            EastGravity },
1775        { NULLQUARK, "southwest",       SouthWestGravity },
1776        { NULLQUARK, "south",           SouthGravity },
1777        { NULLQUARK, "southeast",       SouthEastGravity },
1778        { NULLQUARK, "static",          StaticGravity },
1779        { NULLQUARK, "unmap",           UnmapGravity },
1780        { NULLQUARK, "0",               ForgetGravity },
1781        { NULLQUARK, "1",               NorthWestGravity },
1782        { NULLQUARK, "2",               NorthGravity },
1783        { NULLQUARK, "3",               NorthEastGravity },
1784        { NULLQUARK, "4",               WestGravity },
1785        { NULLQUARK, "5",               CenterGravity },
1786        { NULLQUARK, "6",               EastGravity },
1787        { NULLQUARK, "7",               SouthWestGravity },
1788        { NULLQUARK, "8",               SouthGravity },
1789        { NULLQUARK, "9",               SouthEastGravity },
1790        { NULLQUARK, "10",              StaticGravity },
1791        { NULLQUARK, NULL,              ForgetGravity }
1792    };
1793    /* *INDENT-ON* */
1794    static Boolean haveQuarks = FALSE;
1795    char lowerName[40];
1796    XrmQuark q;
1797    char *s;
1798    struct _namepair *np;
1799
1800    if (*num_args != 0) {
1801        XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1802                        "wrongParameters", "cvtStringToGravity",
1803                        "XtToolkitError",
1804                        "String to Gravity conversion needs no extra arguments",
1805                        NULL, NULL);
1806        return False;
1807    }
1808    if (!haveQuarks) {
1809        for (np = names; np->name; np++) {
1810            np->quark = XrmPermStringToQuark(np->name);
1811        }
1812        haveQuarks = TRUE;
1813    }
1814    s = (char *) fromVal->addr;
1815    if (strlen(s) < sizeof lowerName) {
1816        CopyISOLatin1Lowered(lowerName, s);
1817        q = XrmStringToQuark(lowerName);
1818        for (np = names; np->name; np++)
1819            if (np->quark == q)
1820                done_string(int, np->gravity, XtRGravity);
1821    }
1822    XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRGravity);
1823    return False;
1824}
1825
1826void
1827_XtAddDefaultConverters(ConverterTable table)
1828{
1829#define Add(from, to, proc, convert_args, num_args, cache) \
1830    _XtTableAddConverter(table, from, to, proc, \
1831            (XtConvertArgRec const*) convert_args, (Cardinal)num_args, \
1832            True, cache, (XtDestructor)NULL, True)
1833
1834#define Add2(from, to, proc, convert_args, num_args, cache, destructor) \
1835    _XtTableAddConverter(table, from, to, proc, \
1836            (XtConvertArgRec const *) convert_args, (Cardinal)num_args, \
1837            True, cache, destructor, True)
1838
1839    Add(XtQColor, XtQPixel, XtCvtColorToPixel, NULL, 0, XtCacheNone);
1840
1841    Add(XtQInt, XtQBool, XtCvtIntToBool, NULL, 0, XtCacheNone);
1842    Add(XtQInt, XtQBoolean, XtCvtIntToBoolean, NULL, 0, XtCacheNone);
1843    Add(XtQInt, XtQColor, XtCvtIntToColor,
1844        colorConvertArgs, XtNumber(colorConvertArgs), XtCacheByDisplay);
1845    Add(XtQInt, XtQDimension, XtCvtIntToShort, NULL, 0, XtCacheNone);
1846    Add(XtQInt, XtQFloat, XtCvtIntToFloat, NULL, 0, XtCacheNone);
1847    Add(XtQInt, XtQFont, XtCvtIntToFont, NULL, 0, XtCacheNone);
1848    Add(XtQInt, XtQPixel, XtCvtIntToPixel, NULL, 0, XtCacheNone);
1849    Add(XtQInt, XtQPixmap, XtCvtIntToPixmap, NULL, 0, XtCacheNone);
1850    Add(XtQInt, XtQPosition, XtCvtIntToShort, NULL, 0, XtCacheNone);
1851    Add(XtQInt, XtQShort, XtCvtIntToShort, NULL, 0, XtCacheNone);
1852    Add(XtQInt, XtQUnsignedChar, XtCvtIntToUnsignedChar, NULL, 0, XtCacheNone);
1853
1854    Add(XtQPixel, XtQColor, XtCvtIntToColor,
1855        colorConvertArgs, XtNumber(colorConvertArgs), XtCacheByDisplay);
1856
1857    Add(_XtQString, XtQAtom, XtCvtStringToAtom,
1858        displayConvertArg, XtNumber(displayConvertArg), XtCacheNone);
1859    Add(_XtQString, XtQBool, XtCvtStringToBool, NULL, 0, XtCacheNone);
1860    Add(_XtQString, XtQBoolean, XtCvtStringToBoolean, NULL, 0, XtCacheNone);
1861    Add2(_XtQString, XtQCommandArgArray, XtCvtStringToCommandArgArray,
1862         NULL, 0, XtCacheNone | XtCacheRefCount, ArgArrayDestructor);
1863    Add2(_XtQString, XtQCursor, XtCvtStringToCursor,
1864         displayConvertArg, XtNumber(displayConvertArg),
1865         XtCacheByDisplay, FreeCursor);
1866    Add(_XtQString, XtQDimension, XtCvtStringToDimension, NULL, 0, XtCacheNone);
1867    Add2(_XtQString, XtQDirectoryString, XtCvtStringToDirectoryString, NULL, 0,
1868         XtCacheNone | XtCacheRefCount, FreeDirectoryString);
1869    Add(_XtQString, XtQDisplay, XtCvtStringToDisplay, NULL, 0, XtCacheAll);
1870    Add2(_XtQString, XtQFile, XtCvtStringToFile, NULL, 0,
1871         XtCacheAll | XtCacheRefCount, FreeFile);
1872    Add(_XtQString, XtQFloat, XtCvtStringToFloat, NULL, 0, XtCacheNone);
1873
1874    Add2(_XtQString, XtQFont, XtCvtStringToFont,
1875         displayConvertArg, XtNumber(displayConvertArg),
1876         XtCacheByDisplay, FreeFont);
1877    Add2(_XtQString, XtQFontSet, XtCvtStringToFontSet,
1878         localeDisplayConvertArgs, XtNumber(localeDisplayConvertArgs),
1879         XtCacheByDisplay, FreeFontSet);
1880    Add2(_XtQString, XtQFontStruct, XtCvtStringToFontStruct,
1881         displayConvertArg, XtNumber(displayConvertArg),
1882         XtCacheByDisplay, FreeFontStruct);
1883
1884    Add(_XtQString, XtQGravity, XtCvtStringToGravity, NULL, 0, XtCacheNone);
1885    Add(_XtQString, XtQInitialState, XtCvtStringToInitialState, NULL, 0,
1886        XtCacheNone);
1887    Add(_XtQString, XtQInt, XtCvtStringToInt, NULL, 0, XtCacheAll);
1888    Add2(_XtQString, XtQPixel, XtCvtStringToPixel,
1889         colorConvertArgs, XtNumber(colorConvertArgs),
1890         XtCacheByDisplay, FreePixel);
1891    Add(_XtQString, XtQPosition, XtCvtStringToShort, NULL, 0, XtCacheAll);
1892    Add(_XtQString, XtQRestartStyle, XtCvtStringToRestartStyle, NULL, 0,
1893        XtCacheNone);
1894    Add(_XtQString, XtQShort, XtCvtStringToShort, NULL, 0, XtCacheAll);
1895    Add(_XtQString, XtQUnsignedChar, XtCvtStringToUnsignedChar,
1896        NULL, 0, XtCacheAll);
1897    Add2(_XtQString, XtQVisual, XtCvtStringToVisual,
1898         visualConvertArgs, XtNumber(visualConvertArgs),
1899         XtCacheByDisplay, NULL);
1900
1901    _XtAddTMConverters(table);
1902}
1903