home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 mARCH / PCWK3A99.iso / Linux / DDD331 / DDD-3_1_.000 / DDD-3_1_ / ddd-3.1.1 / ddd / converters.C < prev    next >
C/C++ Source or Header  |  1998-12-02  |  30KB  |  1,042 lines

  1. // $Id: converters.C,v 1.37 1998/12/02 08:39:34 zeller Exp $
  2. // Own converters
  3.  
  4. // Copyright (C) 1995-1997 Technische Universitaet Braunschweig, Germany.
  5. // Written by Andreas Zeller <zeller@ips.cs.tu-bs.de>.
  6. // 
  7. // This file is part of DDD.
  8. // 
  9. // DDD is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. // 
  14. // DDD is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. // See the GNU General Public License for more details.
  18. // 
  19. // You should have received a copy of the GNU General Public
  20. // License along with DDD -- see the file COPYING.
  21. // If not, write to the Free Software Foundation, Inc.,
  22. // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. // 
  24. // DDD is the data display debugger.
  25. // For details, see the DDD World-Wide-Web page, 
  26. // `http://www.cs.tu-bs.de/softech/ddd/',
  27. // or send a mail to the DDD developers <ddd@ips.cs.tu-bs.de>.
  28.  
  29. char converters_rcsid[] = 
  30.     "$Id: converters.C,v 1.37 1998/12/02 08:39:34 zeller Exp $";
  31.  
  32. #include <X11/Xlib.h>
  33. #include <X11/Intrinsic.h>
  34. #include <X11/IntrinsicP.h>
  35. #include <X11/StringDefs.h>
  36. #include <stdlib.h>
  37. #include <unistd.h>
  38. #include <pwd.h>
  39. #include <ctype.h>
  40.  
  41. #include <X11/CoreP.h>
  42.  
  43. #include "bool.h"
  44. #include "home.h"
  45. #include "BindingS.h"
  46. #include "OnOff.h"
  47. #include "strclass.h"
  48. #include "charsets.h"
  49. #include "StringSA.h"
  50. #include "string-fun.h"
  51. #include "MString.h"
  52.  
  53. #include <Xm/Xm.h>
  54.  
  55. #define new new_w
  56. #define class class_w
  57.  
  58. #if XmVersion < 1002
  59. #include <Xm/bitmaps.h>
  60. #else
  61.  
  62. // Some reasonable defaults...
  63. static unsigned char bitmaps [3][32] =
  64. {
  65.     {  0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88,
  66.        0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88,
  67.        0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88,
  68.        0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88  },
  69.  
  70.     {  0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
  71.        0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
  72.        0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55,
  73.        0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55  },
  74.  
  75.     {  0xFF, 0xFF, 0xAA, 0xAA, 0xFF, 0xFF, 0x55, 0x55,
  76.        0xFF, 0xFF, 0xAA, 0xAA, 0xFF, 0xFF, 0x55, 0x55,
  77.        0xFF, 0xFF, 0xAA, 0xAA, 0xFF, 0xFF, 0x55, 0x55,
  78.        0xFF, 0xFF, 0xAA, 0xAA, 0xFF, 0xFF, 0x55, 0x55  }
  79. };
  80.  
  81. static String bitmap_name_set[] =
  82. {
  83.    "25_foreground",
  84.    "50_foreground",
  85.    "75_foreground"
  86. };
  87.  
  88. #endif
  89.  
  90. // Decl of XmIsSlowSubclass in Motif 1.1 is not C++-aware, hence extern "C"
  91. extern "C" {
  92. #include <Xm/XmP.h>
  93. }
  94.  
  95. // <Xm/PrimitiveP.h> only exists in Motif 1.2 and later
  96. #if XmVersion >= 1002
  97. #include <Xm/PrimitiveP.h>
  98. #endif
  99.  
  100. #undef new
  101. #undef class
  102.  
  103. #include "converters.h"
  104. #include "MString.h"
  105.  
  106.  
  107. // ANSI C++ doesn't like the XtIsRealized() macro
  108. #ifdef XtIsRealized
  109. #undef XtIsRealized
  110. #endif
  111.  
  112.  
  113. // Do we want to define our own @STRING@ to font converters?
  114. #define OWN_FONT_CONVERTERS 0
  115.  
  116. // Declarations
  117.  
  118. // Convert String to Widget
  119. static Boolean CvtStringToWidget(Display *display, 
  120.                  XrmValue *args, Cardinal *num_args, 
  121.                  XrmValue *fromVal, XrmValue *toVal,
  122.                  XtPointer *converter_data);
  123.  
  124. // Convert String to Pixmap, converting 1s and 0s to fg/bg color
  125. static Boolean CvtStringToPixmap(Display *display, 
  126.                  XrmValue *args, Cardinal *num_args, 
  127.                  XrmValue *fromVal, XrmValue *toVal,
  128.                  XtPointer *converter_data);
  129.  
  130. // Convert String to Bitmap, leaving 1s and 0s untouched
  131. static Boolean CvtStringToBitmap(Display *display, 
  132.                  XrmValue *args, Cardinal *num_args, 
  133.                  XrmValue *fromVal, XrmValue *toVal,
  134.                  XtPointer *converter_data);
  135.  
  136. // Convert String to XmString, using `@' for font specs
  137. static Boolean CvtStringToXmString(Display *display, 
  138.                    XrmValue *args, Cardinal *num_args, 
  139.                    XrmValue *fromVal, XrmValue *toVal,
  140.                    XtPointer *converter_data);
  141.  
  142. // Convert String to Alignment
  143. static Boolean CvtStringToAlignment(Display *display, 
  144.                     XrmValue *args, Cardinal *num_args, 
  145.                     XrmValue *fromVal, XrmValue *toVal,
  146.                     XtPointer *converter_data);
  147.  
  148. // Convert String to Orientation
  149. static Boolean CvtStringToOrientation(Display *display, 
  150.                       XrmValue *args, Cardinal *num_args, 
  151.                       XrmValue *fromVal, XrmValue *toVal,
  152.                       XtPointer *converter_data);
  153.  
  154. // Convert String to Packing
  155. static Boolean CvtStringToPacking(Display *display, 
  156.                   XrmValue *args, Cardinal *num_args, 
  157.                   XrmValue *fromVal, XrmValue *toVal,
  158.                   XtPointer *converter_data);
  159.  
  160.  
  161.  
  162. // Return a value of given type
  163. #define done(type, value) \
  164.     do {                                                \
  165.         if (toVal->addr != NULL) {                      \
  166.             if (toVal->size < sizeof(type)) {           \
  167.                 toVal->size = sizeof(type);             \
  168.                 return False;                           \
  169.             }                                           \
  170.             *(type *)(toVal->addr) = (value);           \
  171.         }                                               \
  172.         else {                                          \
  173.             static type static_val;                     \
  174.             static_val = (value);                       \
  175.             toVal->addr = (caddr_t)&static_val;         \
  176.         }                                               \
  177.                                                         \
  178.         toVal->size = sizeof(type);                     \
  179.         return True;                                    \
  180.     } while(0)
  181.  
  182.  
  183. // Return string of value.  If STRIP is set, strip leading and
  184. // trailing whitespace.
  185. static string str(XrmValue *from, bool strip)
  186. {
  187.     // Use the length given in FROM->size; strip trailing '\0'
  188.     String s = (String)from->addr;
  189.     int sz   = from->size;
  190.     if (sz > 0 && s[sz - 1] == '\0')
  191.     sz--;
  192.     string v(s, sz);
  193.  
  194.     if (strip)
  195.     {
  196.     // Strip leading and trailing space.  Pinwu Xu
  197.     // <pxu@perigee.net> reports a `Warning: Cannot convert string
  198.     // "false " to type OnOff'.  No idea where the trailing space in
  199.     // `"false "' comes from, so remove it here.
  200.     while (v.length() > 0 && isspace(v[0]))
  201.         v = v.after(0);
  202.     while (v.length() > 0 && isspace(v[v.length() - 1]))
  203.         v = v.before(int(v.length()) - 1);
  204.     }
  205.  
  206.     return v;
  207. }
  208.  
  209. // Convert String to Widget
  210. // This is based on Asente/Swick: The X Window System Toolkit,
  211. // Digital Press, Example 3.9
  212.  
  213. Boolean CvtStringToWidget(Display *display, 
  214.               XrmValue *args, Cardinal *num_args, 
  215.               XrmValue *fromVal, XrmValue *toVal,
  216.               XtPointer *)
  217. {
  218.     // Convert first arg into parent    
  219.     if (*num_args != 1) 
  220.     {
  221.     XtAppErrorMsg(XtDisplayToApplicationContext(display),
  222.         "wrongParameters", "CvtStringToWidget",
  223.         "XtToolkitError",
  224.         "String to Widget conversion needs parent arg",
  225.         (String *)NULL, (Cardinal *)NULL);
  226.     }
  227.     Widget parent = *(Widget *) args[0].addr;
  228.  
  229.     // Get widget
  230.     string value = str(fromVal, false);
  231.     Widget w = XtNameToWidget(parent, value);
  232.     if (w == NULL)
  233.     {
  234.     XtDisplayStringConversionWarning(display, fromVal->addr, XtRWidget);
  235.     return False;
  236.     }
  237.  
  238.     done(Widget, w);
  239. }
  240.  
  241.  
  242. // Convert String to Pixmap (using XmGetPixmap)
  243. // A Pixmap will be read in as bitmap file
  244. // 1 and 0 values are set according to the widget's 
  245. // foreground/background colors.
  246. static Boolean CvtStringToPixmap(Display *display, 
  247.                  XrmValue *args, Cardinal *num_args, 
  248.                  XrmValue *fromVal, XrmValue *toVal,
  249.                  XtPointer *)
  250. {
  251.     // Default parameters
  252.     Screen *screen   = DefaultScreenOfDisplay(display);
  253.     Pixel background = WhitePixelOfScreen(screen);
  254.     Pixel foreground = BlackPixelOfScreen(screen);
  255.  
  256.     if (*num_args >= 1)
  257.     {
  258.     // convert first arg into widget
  259.     Widget w = *(Widget *) args[0].addr;
  260.     background = w->core.background_pixel;
  261.     
  262.     screen = XtScreen(w);
  263.     
  264.     if (XtIsWidget(w) && XmIsPrimitive(w))
  265.     {
  266.         // Get foreground color from widget
  267.         foreground = XmPrimitiveWidget(w)->primitive.foreground;
  268.     }
  269.     else
  270.     {
  271.         // Ask Motif for a default foreground color
  272.         Pixel newfg, newtop, newbot, newselect;
  273.         XmGetColors(screen, w->core.colormap, background,
  274.             &newfg, &newtop, &newbot, &newselect);
  275.         foreground = newfg;
  276.     }
  277.     }
  278.  
  279.     // Get pixmap
  280.     Pixmap p = XmUNSPECIFIED_PIXMAP;
  281.  
  282.     string value = str(fromVal, false);
  283.  
  284.     // Some Motif versions use `unspecified_pixmap' and `unspecified pixmap'
  285.     // as values for XmUNSPECIFIED_PIXMAP.  Check for this.
  286.     string v = downcase(value);
  287.     v.gsub(" ", "_");
  288.     if (v.contains("xm", 0))
  289.     v = v.after("xm");
  290.     if (v != "unspecified_pixmap")
  291.     {
  292.     p = XmGetPixmap(screen, value, foreground, background);
  293.  
  294.     if (p == XmUNSPECIFIED_PIXMAP)
  295.     {
  296.         XtDisplayStringConversionWarning(display, fromVal->addr, 
  297.                          XmRPixmap);
  298.         return False;
  299.     }
  300.     }
  301.  
  302.     done(Pixmap, p);
  303. }
  304.  
  305.  
  306.  
  307. static String locateBitmap(Display *display, String basename);
  308.  
  309. // Convert String to Bitmap
  310. // A Bitmap will be read in as bitmap file -- 1 and 0 values remain unchanged.
  311. static Boolean CvtStringToBitmap(Display *display, 
  312.                  XrmValue *, Cardinal *, 
  313.                  XrmValue *fromVal, XrmValue *toVal,
  314.                  XtPointer *)
  315. {
  316.     // Fetch a drawable
  317.     Window window = None;
  318.  
  319. #if 0
  320.     if (*num_args >= 1)
  321.     {
  322.     // convert first arg into widget
  323.     Widget w = *(Widget *) args[0].addr;
  324.     if (XtIsRealized(w))
  325.         window = XtWindow(w);
  326.     }
  327. #endif
  328.  
  329.     if (window == None)
  330.     window = DefaultRootWindow(display);
  331.  
  332.     // Locate file
  333.     string basename = str(fromVal, false);
  334.     String filename = locateBitmap(display, basename);
  335.     if (filename == NULL)
  336.     {
  337.     // Cannot find file -- check for predefined motif bitmaps
  338.     for (Cardinal i = 0; i < XtNumber(bitmap_name_set); i++)
  339.     {
  340.         if (basename == bitmap_name_set[i])
  341.         {
  342.         Pixmap bitmap = XCreateBitmapFromData(display, window,
  343.                               (char *)(bitmaps[i]),
  344.                               16, 16);
  345.         if (bitmap == None)
  346.             break;
  347.  
  348.         done(Pixmap, bitmap);
  349.         }
  350.     }
  351.  
  352.     // Cannot find file and no predefined bitmap found
  353.     XtDisplayStringConversionWarning(display, fromVal->addr, XtRBitmap);
  354.     return False;
  355.     }
  356.  
  357.  
  358.     // create pixmap
  359.     unsigned int width, height;
  360.     Pixmap bitmap;
  361.     int x_hot, y_hot;
  362.     int success = XReadBitmapFile(display, window, filename, 
  363.                   &width, &height, &bitmap, &x_hot, &y_hot);
  364.     if (success != BitmapSuccess)
  365.     {
  366.     XtDisplayStringConversionWarning(display, fromVal->addr, XtRBitmap);
  367.     XtFree(filename);
  368.     return False;
  369.     }
  370.  
  371.     done(Pixmap, bitmap);
  372. }
  373.  
  374. // Note: <percent>B<percent> is expanded by SCCS -- thus inserting ""
  375. static string BASENAME = "%B""%S";
  376. static string DELIMITER = ":";
  377.  
  378. // add default search paths to path
  379. static void addDefaultPaths(string& path, string root)
  380. {
  381.     path += DELIMITER + root + "/%L/%T/%N/" + BASENAME;
  382.     path += DELIMITER + root + "/%l/%T/%N/" + BASENAME;
  383.     path += DELIMITER + root + "/%T/%N/"    + BASENAME;
  384.     path += DELIMITER + root + "/%L/%T/"    + BASENAME;
  385.     path += DELIMITER + root + "/%l/%T/"    + BASENAME;
  386.     path += DELIMITER + root + "/%T/"       + BASENAME;
  387. }
  388.  
  389. // locate path
  390. // this mimics XmGetPixmap's efforts to build a path
  391. static string bitmapPath()
  392. {
  393.     static string path = "";
  394.  
  395.     if (path != "")
  396.     return path;
  397.  
  398.     path = BASENAME;
  399.     char *xbmlangpath = getenv("XBMLANGPATH");
  400.     if (xbmlangpath == NULL)
  401.     {
  402.     char *xapplresdir = getenv("XAPPLRESDIR");
  403.     string home = gethome();
  404.  
  405.     if (xapplresdir != NULL)
  406.         addDefaultPaths(path, xapplresdir);
  407.     else
  408.         addDefaultPaths(path, home);
  409.  
  410.     path += DELIMITER + home + BASENAME;
  411.     addDefaultPaths(path, "/usr/lib/X11");
  412.     path += DELIMITER + "/usr/include/X11/%T/" + BASENAME;
  413.     }
  414.     else
  415.     path = xbmlangpath;
  416.  
  417.     return path;
  418. }
  419.  
  420. static string PATH = bitmapPath();
  421.  
  422. // locate bitmap
  423. // this mimics XmGetPixmap's efforts to locate a path
  424. static String locateBitmap(Display *display, String basename)
  425. {
  426.     SubstitutionRec subst;
  427.     subst.match        = 'B';
  428.     subst.substitution = basename;
  429.  
  430.     return XtResolvePathname(display,      // the display we use
  431.                  "bitmaps",    // %T = bitmaps
  432.                  NULL,         // %N = application class name
  433.                  "",           // %S = "" (suffix)
  434.                  (String)PATH, // path to use
  435.                  &subst, 1,    // %B = basename
  436.                  NULL);        // no checking for valid bitmap
  437. }
  438.  
  439. // Macro tables
  440. static StringStringAssoc conversionMacroTable;
  441.  
  442. // Return length of leading font id
  443. static int font_id_len(const string& s)
  444. {
  445.     // Font ids have the syntax "[_A-Za-z][-_A-Za-z0-9]*"
  446.  
  447.     if (s == "")
  448.     return 0;
  449.  
  450.     if (s[0] != '_' && !isalpha(s[0]))
  451.     return 0;
  452.  
  453.     for (int i = 1; i < int(s.length()); i++)
  454.     if (s[i] != '-' && s[i] != '_' && !isalnum(s[i]))
  455.         return i;
  456.  
  457.     return s.length();
  458. }
  459.  
  460. // Convert String to XmString, using `@' for font specs: `@FONT TEXT'
  461. // makes TEXT be displayed in font FONT; a single space after FONT is
  462. // eaten.  `@ ' displays a single `@'.
  463. static Boolean CvtStringToXmString(Display *display, 
  464.                    XrmValue *, Cardinal *, 
  465.                    XrmValue *fromVal, XrmValue *toVal,
  466.                    XtPointer *)
  467. {
  468.     const string font_esc = "@";
  469.  
  470.     // Get string
  471.     string source = str(fromVal, false);
  472.     string charset = (String)MSTRING_DEFAULT_CHARSET;
  473.  
  474.     int n_segments = source.freq(font_esc) + 1;
  475.     string *segments = new string[n_segments];
  476.     
  477.     split(source, segments, n_segments, font_esc);
  478.  
  479.     MString buf;
  480.     for (int i = 0; i < n_segments && buf.xmstring() != 0; i++)
  481.     {
  482.     string segment;
  483.  
  484.     if (i == 0)
  485.     {
  486.         // At beginning of text
  487.         segment = segments[i];
  488.     }
  489.     else
  490.     {
  491.         int len = font_id_len(segments[i]);
  492.         if (len > 0)
  493.         {
  494.         // Found @[font-id] <segment>: process it
  495.         string c = segments[i].before(len);
  496.         segment = segments[i].from(int(c.length()));
  497.         if (segment == "")
  498.         {
  499.             // Found @MACRO@: process it
  500.             if (conversionMacroTable.has(c))
  501.             {
  502.             // Replace macro by value
  503.             segment = conversionMacroTable[c] + segments[++i];
  504.             }
  505.             else
  506.             {
  507.             // No such macro
  508.             Cardinal num_params = 1;
  509.             String params = (String)c.chars();
  510.             XtAppWarningMsg(XtDisplayToApplicationContext(display),
  511.                     "noSuchMacro", "CvtStringToXmString",
  512.                     "XtToolkitError",
  513.                     "No such macro: @%s@",
  514.                     ¶ms, &num_params);
  515.             segment = font_esc + segment + font_esc;
  516.             }
  517.         }
  518.         else
  519.         {
  520.             // Found @CHARSET: set new charset
  521.             charset = c;
  522.             if (segment.contains(' ', 0)
  523.             || segment.contains('\t', 0))
  524.             segment = segment.after(0);
  525.         }
  526.         }
  527.         else if (segments[i].contains(' ', 0))
  528.         {
  529.         // found @[space]: remove space
  530.         segment = font_esc + segments[i].from(1);
  531.         }
  532.         else
  533.         {
  534.         // found @[anything-else]: ignore @, take remainder literally
  535.         segment = segments[i];
  536.         }
  537.     }
  538.  
  539.     while (segment.contains('\n'))
  540.     {
  541.         buf += MString(segment.before('\n'), charset) + cr();
  542.         segment = segment.after('\n');
  543.     }
  544.  
  545.     if (segment.length() > 0)
  546.         buf += MString(segment, charset);
  547.     }
  548.  
  549.     XmString target = XmStringCopy(buf.xmstring());
  550.     delete[] segments;
  551.  
  552.     if (target == 0)
  553.     {
  554.     XtDisplayStringConversionWarning(display, fromVal->addr, XmRXmString);
  555.     return False;
  556.     }
  557.     
  558.     done(XmString, target);
  559. }
  560.  
  561.  
  562. #if OWN_FONT_CONVERTERS
  563.  
  564. static bool convert_fontspec(Display *display,
  565.                  string& fontspec, const string& name)
  566. {
  567.     if (fontspec.contains('@', 0))
  568.     {
  569.     string c = fontspec.after('@');
  570.     c = c.before('@');
  571.     if (conversionMacroTable.has(c))
  572.     {
  573.         // Replace macro by value
  574.         fontspec = conversionMacroTable[c];
  575.     }
  576.     else
  577.     {
  578.         // No such macro
  579.         Cardinal num_params = 1;
  580.         String params = (String)c.chars();
  581.         XtAppWarningMsg(XtDisplayToApplicationContext(display),
  582.                 "noSuchMacro", name.chars(),
  583.                 "XtToolkitError",
  584.                 "No such macro: @%s@",
  585.                 ¶ms, &num_params);
  586.         return false;
  587.     }
  588.     }
  589.  
  590.     return true;
  591. }
  592.  
  593.  
  594. // Convert String to FontStruct, relacing `@NAME@' by symbolic font specs.
  595. static Boolean CvtStringToFontStruct(Display *display, 
  596.                      XrmValue *, Cardinal *, 
  597.                      XrmValue *fromVal, XrmValue *toVal,
  598.                      XtPointer *)
  599. {
  600.     string fontspec = str(fromVal, false);
  601.     strip_space(fontspec);
  602.  
  603.     if (!convert_fontspec(display, fontspec, "CvtStringToFontStruct"))
  604.     return False;
  605.  
  606.     XFontStruct *font = XLoadQueryFont(display, fontspec);
  607.     if (font == 0)
  608.     {
  609.     Cardinal num_params = 1;
  610.     String params = (String)fontspec.chars();
  611.     XtAppWarningMsg(XtDisplayToApplicationContext(display),
  612.             "noSuchFont", "CvtStringToFontStruct",
  613.             "XtToolkitError",
  614.             "No such font: %s",
  615.             ¶ms, &num_params);
  616.     return False;
  617.     }
  618.  
  619.     done(XFontStruct *, font);
  620. }
  621.  
  622. // Convert String to FontList, relacing `@NAME@' by symbolic font specs.
  623. static Boolean CvtStringToXmFontList(Display *display, 
  624.                      XrmValue *, Cardinal *, 
  625.                      XrmValue *fromVal, XrmValue *toVal,
  626.                      XtPointer *)
  627. {
  628.     // Get string
  629.     string source = str(fromVal, false);
  630.  
  631.     int n_segments = source.freq(',') + 1;
  632.     string *segments = new string[n_segments];
  633.     
  634.     split(source, segments, n_segments, ',');
  635.  
  636.     XmFontList target = 0;
  637.     for (int i = 0; i < n_segments; i++)
  638.     {
  639.     const string& segment = segments[i];
  640.     string fontspec = segment.before('=');
  641.     string charset  = segment.after('=');
  642.  
  643.     if (!segment.contains('='))    // "fixed" occurs in Motif 1.1
  644.     {
  645.         fontspec = segment;
  646.         charset  = MSTRING_DEFAULT_CHARSET;
  647.     }
  648.  
  649.     strip_space(fontspec);
  650.     strip_space(charset);
  651.  
  652.     if (fontspec == "" || 
  653.         (charset == "" && charset != MSTRING_DEFAULT_CHARSET))
  654.     {
  655.         Cardinal num_params = 1;
  656.         String params = (String)segment.chars();
  657.         XtAppWarningMsg(XtDisplayToApplicationContext(display),
  658.                 "syntaxError", "CvtStringToXmFontList",
  659.                 "XtToolkitError",
  660.                 "Syntax error in %s",
  661.                 ¶ms, &num_params);
  662.         continue;
  663.     }
  664.  
  665.     if (!convert_fontspec(display, fontspec, "CvtStringToXmFontList"))
  666.         continue;
  667.  
  668. #if XmVersion < 1002
  669.     XFontStruct *font = XLoadQueryFont(display, fontspec);
  670.     if (font == 0)
  671.     {
  672.         Cardinal num_params = 1;
  673.         String params = (String)fontspec.chars();
  674.         XtAppWarningMsg(XtDisplayToApplicationContext(display),
  675.                 "noSuchFont", "CvtStringToXmFontList",
  676.                 "XtToolkitError",
  677.                 "No such font: %s",
  678.                 ¶ms, &num_params);
  679.         continue;
  680.     }
  681.  
  682.     if (target == 0)
  683.         target = XmFontListCreate(font, charset);
  684.     else
  685.         target = XmFontListAdd(target, font, charset);
  686.  
  687. #else  // XmVersion >= 1002
  688.     XmFontListEntry entry = XmFontListEntryLoad(display, (char *)fontspec, 
  689.                             XmFONT_IS_FONT, charset);
  690.     target = XmFontListAppendEntry(target, entry);
  691.     XmFontListEntryFree(&entry);
  692. #endif
  693.     }
  694.  
  695.     delete[] segments;
  696.  
  697.     if (target == 0)
  698.     {
  699.     XtDisplayStringConversionWarning(display, fromVal->addr, XmRXmString);
  700.     return False;
  701.     }
  702.     
  703.     done(XmFontList, target);
  704. }
  705.  
  706. #endif
  707.  
  708.  
  709. // Convert the strings 'beginning', 'center' and 'end' in any case to a value
  710. // suitable for the specification of the XmNentryAlignment-resource in 
  711. // RowColumn-widgets (or anything else using alignment-resources)
  712. static Boolean CvtStringToAlignment(Display*   display, 
  713.                     XrmValue*  ,
  714.                     Cardinal*  , 
  715.                     XrmValue*  fromVal,
  716.                     XrmValue*  toVal,
  717.                     XtPointer* )
  718. {
  719.     string theAlignment = str(fromVal, true);
  720.     theAlignment.downcase();
  721.  
  722.     if (theAlignment.contains("xm", 0))
  723.     theAlignment = theAlignment.after("xm");
  724.     if (theAlignment.contains("alignment_", 0))
  725.     theAlignment = theAlignment.after("alignment_");
  726.  
  727.     if      (theAlignment == "beginning")
  728.     done(unsigned char, XmALIGNMENT_BEGINNING);
  729.     else if (theAlignment == "center")
  730.     done(unsigned char, XmALIGNMENT_CENTER);
  731.     else if (theAlignment == "end")
  732.     done(unsigned char, XmALIGNMENT_END);
  733.  
  734.     XtDisplayStringConversionWarning(display, fromVal->addr, XmCAlignment);
  735.     return False;
  736. }
  737.  
  738.  
  739. // Convert the strings 'vertical' and 'horizontal' in any case to a value
  740. // suitable for the specification of the XmNorientation-resource in 
  741. // RowColumn-widgets (or anything else using orientation-resources)
  742. static Boolean CvtStringToOrientation(Display*         display, 
  743.                       XrmValue*        ,
  744.                       Cardinal*        , 
  745.                       XrmValue*        fromVal,
  746.                       XrmValue*        toVal,
  747.                       XtPointer*       )
  748. {
  749.     string theOrientation = str(fromVal, true);
  750.     theOrientation.downcase();
  751.     if (theOrientation.contains("xm", 0))
  752.     theOrientation = theOrientation.after("xm");
  753.   
  754.     if      (theOrientation == "vertical")
  755.     done(unsigned char, XmVERTICAL);
  756.     else if (theOrientation == "horizontal")
  757.     done(unsigned char, XmHORIZONTAL);
  758.     else
  759.     {
  760.     XtDisplayStringConversionWarning(display, fromVal->addr, 
  761.                      XmCOrientation);
  762.     return False;
  763.     }
  764. }
  765.  
  766.  
  767. // Convert the strings 'tight', 'column' and 'none' in any case to a value
  768. // suitable for the specification of the XmNpacking-resource in
  769. // RowColumn-widgets (or anything else using packing-resources)
  770. static Boolean CvtStringToPacking(Display*     display, 
  771.                   XrmValue*    ,
  772.                   Cardinal*    , 
  773.                   XrmValue*    fromVal,
  774.                   XrmValue*    toVal,
  775.                   XtPointer*   )
  776. {
  777.     string thePacking = str(fromVal, true);
  778.     thePacking.downcase();
  779.     if (thePacking.contains("xm", 0))
  780.     thePacking = thePacking.after("xm");
  781.     if (thePacking.contains("pack_", 0))
  782.     thePacking = thePacking.after("pack_");
  783.   
  784.     if      (thePacking == "tight")
  785.     done(unsigned char, XmPACK_TIGHT);
  786.     else if (thePacking == "column")
  787.     done(unsigned char, XmPACK_COLUMN);
  788.     else if (thePacking == "none")
  789.     done(unsigned char, XmPACK_NONE);
  790.  
  791.  
  792.     XtDisplayStringConversionWarning(display, fromVal->addr, XmRPacking);
  793.     return False;
  794. }
  795.  
  796. // Convert the strings 'pixels', '100th_millimeters' and so on
  797. // to unit types.
  798. static Boolean CvtStringToUnitType(Display*     display, 
  799.                    XrmValue*    ,
  800.                    Cardinal*    , 
  801.                    XrmValue*    fromVal,
  802.                    XrmValue*    toVal,
  803.                    XtPointer*   )
  804. {
  805.     string theType = str(fromVal, true);
  806.     theType.downcase();
  807.     if (theType.contains("xm", 0))
  808.     theType = theType.after("xm");
  809.   
  810.     if      (theType == "pixels")
  811.     done(unsigned char, XmPIXELS);
  812.     else if (theType == "100th_millimeters")
  813.     done(unsigned char, Xm100TH_MILLIMETERS);
  814.     else if (theType == "1000th_inches")
  815.     done(unsigned char, Xm1000TH_INCHES);
  816.     else if (theType == "100th_points")
  817.     done(unsigned char, Xm100TH_POINTS);
  818.     else if (theType == "100th_font_units")
  819.     done(unsigned char, Xm100TH_FONT_UNITS);
  820.  
  821.     XtDisplayStringConversionWarning(display, fromVal->addr, XmRUnitType);
  822.     return False;
  823. }
  824.  
  825. // Convert the strings 'on', `off', `auto' to OnOff values
  826. Boolean CvtStringToOnOff(Display*     display, 
  827.              XrmValue*    ,
  828.              Cardinal*    , 
  829.              XrmValue*    fromVal,
  830.              XrmValue*    toVal,
  831.              XtPointer*   )
  832. {
  833.     string value = str(fromVal, true);
  834.     value.downcase();
  835.     value.gsub('_', ' ');
  836.  
  837.     if (value == "on" || value == "true" || value == "yes")
  838.     done(OnOff, On);
  839.     else if (value == "off" || value == "false" || value == "no")
  840.     done(OnOff, Off);
  841.     else if (value == "when needed" || value == "automatic" || value == "auto")
  842.     done(OnOff, Auto);
  843.  
  844.     XtDisplayStringConversionWarning(display, fromVal->addr, XtROnOff);
  845.     return False;
  846. }
  847.  
  848. // Convert the strings 'motif', `kde' to BindingStyle values
  849. Boolean CvtStringToBindingStyle(Display*     display, 
  850.                 XrmValue*    ,
  851.                 Cardinal*    , 
  852.                 XrmValue*    fromVal,
  853.                 XrmValue*    toVal,
  854.                 XtPointer*   )
  855. {
  856.     string value = str(fromVal, true);
  857.     value.downcase();
  858.  
  859.     if (value == "kde")
  860.     done(BindingStyle, KDEBindings);
  861.     else if (value == "motif")
  862.     done(BindingStyle, MotifBindings);
  863.  
  864.     XtDisplayStringConversionWarning(display, fromVal->addr, XtRBindingStyle);
  865.     return False;
  866. }
  867.  
  868. // Convert a string to Cardinal.
  869. static Boolean CvtStringToCardinal(Display*     display, 
  870.                    XrmValue*    ,
  871.                    Cardinal*    , 
  872.                    XrmValue*    fromVal,
  873.                    XrmValue*    toVal,
  874.                    XtPointer*   )
  875. {
  876.     string value = str(fromVal, true);
  877.     char *ptr = 0;
  878.     long val = strtol(value.chars(), &ptr, 0);
  879.     if (ptr == value.chars() || val < 0)
  880.     {
  881.     XtDisplayStringConversionWarning(display, fromVal->addr, XtRCardinal);
  882.     return False;
  883.     }
  884.  
  885.     done(Cardinal, val);
  886. }
  887.  
  888.  
  889. // Register all converters
  890. void registerOwnConverters()
  891. {
  892.     static XtConvertArgRec parentCvtArgs[] = {
  893.     { XtWidgetBaseOffset, XtPointer(XtOffsetOf(CoreRec, core.parent)),
  894.       sizeof(CoreWidget) }
  895.     };
  896.  
  897.     static XtConvertArgRec thisCvtArgs[] = {
  898.     { XtBaseOffset, XtPointer(0), 
  899.       sizeof(Widget) }
  900.     };
  901.  
  902.     // String -> Widget
  903.     XtSetTypeConverter(XtRString, XtRWidget, CvtStringToWidget,
  904.                parentCvtArgs, XtNumber(parentCvtArgs), XtCacheNone,
  905.                XtDestructor(NULL));
  906.  
  907.     // String -> Window
  908.     // We use CvtStringToWidget for conversions to "Window" as well,
  909.     // since Motif widgets want a widget id in their "Window" fields.
  910.     XtSetTypeConverter(XtRString, XtRWindow, CvtStringToWidget,
  911.                parentCvtArgs, XtNumber(parentCvtArgs), XtCacheNone,
  912.                XtDestructor(NULL));
  913.  
  914.     // String -> Pixmap
  915.     XtSetTypeConverter(XtRString, XmRPixmap, CvtStringToPixmap,
  916.                thisCvtArgs, XtNumber(thisCvtArgs), XtCacheNone,
  917.                XtDestructor(NULL));
  918.  
  919.     // String -> GadgetPixmap
  920.     XtSetTypeConverter(XtRString, XmRGadgetPixmap, CvtStringToPixmap,
  921.                thisCvtArgs, XtNumber(thisCvtArgs), XtCacheNone,
  922.                XtDestructor(NULL));
  923.  
  924.     // String -> PrimForegroundPixmap
  925.     XtSetTypeConverter(XtRString, XmRPrimForegroundPixmap, CvtStringToPixmap,
  926.                thisCvtArgs, XtNumber(thisCvtArgs), XtCacheNone,
  927.                XtDestructor(NULL));
  928.  
  929.     // String -> ManForegroundPixmap
  930.     XtSetTypeConverter(XtRString, XmRManForegroundPixmap, CvtStringToPixmap,
  931.                thisCvtArgs, XtNumber(thisCvtArgs), XtCacheNone,
  932.                XtDestructor(NULL));
  933.  
  934.     // String -> BackgroundPixmap
  935.     XtSetTypeConverter(XtRString, XmRBackgroundPixmap, CvtStringToPixmap,
  936.                thisCvtArgs, XtNumber(thisCvtArgs), XtCacheNone,
  937.                XtDestructor(NULL));
  938.  
  939.     // String -> PrimHighlightPixmap
  940.     XtSetTypeConverter(XtRString, XmRPrimHighlightPixmap, CvtStringToPixmap,
  941.                thisCvtArgs, XtNumber(thisCvtArgs), XtCacheNone,
  942.                XtDestructor(NULL));
  943.  
  944.     // String -> PrimTopShadowPixmap
  945.     XtSetTypeConverter(XtRString, XmRPrimTopShadowPixmap, CvtStringToPixmap,
  946.                thisCvtArgs, XtNumber(thisCvtArgs), XtCacheNone,
  947.                XtDestructor(NULL));
  948.  
  949.     // String -> PrimBottomShadowPixmap
  950.     XtSetTypeConverter(XtRString, XmRPrimBottomShadowPixmap, CvtStringToPixmap,
  951.                thisCvtArgs, XtNumber(thisCvtArgs), XtCacheNone,
  952.                XtDestructor(NULL));
  953.  
  954.     // String -> ManTopShadowPixmap
  955.     XtSetTypeConverter(XtRString, XmRManTopShadowPixmap, CvtStringToPixmap,
  956.                thisCvtArgs, XtNumber(thisCvtArgs), XtCacheNone,
  957.                XtDestructor(NULL));
  958.  
  959.     // String -> ManBottomShadowPixmap
  960.     XtSetTypeConverter(XtRString, XmRManBottomShadowPixmap, CvtStringToPixmap,
  961.                thisCvtArgs, XtNumber(thisCvtArgs), XtCacheNone,
  962.                XtDestructor(NULL));
  963.  
  964.     // String -> ManHighlightPixmap
  965.     XtSetTypeConverter(XtRString, XmRManHighlightPixmap, CvtStringToPixmap,
  966.                thisCvtArgs, XtNumber(thisCvtArgs), XtCacheNone,
  967.                XtDestructor(NULL));
  968.  
  969. #if XmVersion >= 1002
  970.     // String -> AnimationPixmap
  971.     XtSetTypeConverter(XtRString, XmRAnimationPixmap, CvtStringToPixmap,
  972.                thisCvtArgs, XtNumber(thisCvtArgs), XtCacheNone,
  973.                XtDestructor(NULL));
  974. #endif
  975.  
  976.     // String -> Bitmap
  977.     XtSetTypeConverter(XtRString, XtRBitmap, CvtStringToBitmap,
  978.                thisCvtArgs, XtNumber(thisCvtArgs), XtCacheByDisplay,
  979.                XtDestructor(NULL));
  980.  
  981.     // String -> XmString
  982.     XtSetTypeConverter(XmRString, XmRXmString, CvtStringToXmString,
  983.                NULL, 0, XtCacheNone,
  984.                XtDestructor(NULL));
  985.  
  986. #if OWN_FONT_CONVERTERS
  987.     // String -> FontList
  988.     XtSetTypeConverter(XmRString, XmRFontList, CvtStringToXmFontList,
  989.                NULL, 0, XtCacheAll,
  990.                XtDestructor(NULL));
  991.  
  992.     // String -> FontStruct
  993.     XtSetTypeConverter(XmRString, XtRFontStruct, CvtStringToFontStruct,
  994.                NULL, 0, XtCacheAll,
  995.                XtDestructor(NULL));
  996. #endif
  997.  
  998.     // String -> UnitType
  999.     XtSetTypeConverter(XmRString, XmRUnitType, CvtStringToUnitType,
  1000.                NULL, 0, XtCacheAll, 
  1001.                XtDestructor(NULL));
  1002.  
  1003.     // String -> OnOff
  1004.     XtSetTypeConverter(XmRString, XtROnOff, CvtStringToOnOff,
  1005.                NULL, 0, XtCacheAll, 
  1006.                XtDestructor(NULL));
  1007.  
  1008.     // String -> BindingStyle
  1009.     XtSetTypeConverter(XmRString, XtRBindingStyle, CvtStringToBindingStyle,
  1010.                NULL, 0, XtCacheAll, 
  1011.                XtDestructor(NULL));
  1012.  
  1013.     // String -> Cardinal
  1014.     XtSetTypeConverter(XmRString, XtRCardinal, CvtStringToCardinal,
  1015.                NULL, 0, XtCacheAll,
  1016.                XtDestructor(NULL));
  1017.  
  1018.     // The following three were contributed by Thorsten Sommer
  1019.     // <sommer@ips.cs.tu-bs.de>
  1020.  
  1021.     // String -> Alignment
  1022.     XtSetTypeConverter(XtRString, XmNentryAlignment, CvtStringToAlignment,
  1023.                parentCvtArgs, XtNumber(parentCvtArgs), XtCacheNone,
  1024.                XtDestructor(NULL));
  1025.  
  1026.     // String -> Orientation
  1027.     XtSetTypeConverter(XtRString, XmNorientation, CvtStringToOrientation,
  1028.                parentCvtArgs, XtNumber(parentCvtArgs), XtCacheNone,
  1029.                XtDestructor(NULL));
  1030.  
  1031.     // String -> Packing
  1032.     XtSetTypeConverter(XtRString, XmNpacking, CvtStringToPacking,
  1033.                parentCvtArgs, XtNumber(parentCvtArgs), XtCacheNone,
  1034.                XtDestructor(NULL));
  1035. }
  1036.  
  1037. // Define a macro: @NAME@ will be replaced by VALUE in CvtStringToXmString
  1038. void defineConversionMacro(String name, String value)
  1039. {
  1040.     conversionMacroTable[name] = value;
  1041. }
  1042.