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 / fonts.C < prev    next >
C/C++ Source or Header  |  1998-10-04  |  19KB  |  783 lines

  1. // $Id: fonts.C,v 1.22 1998/10/04 15:26:38 zeller Exp $ -*- C++ -*-
  2. // Setup DDD fonts
  3.  
  4. // Copyright (C) 1998 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 fonts_rcsid[] = 
  30.     "$Id: fonts.C,v 1.22 1998/10/04 15:26:38 zeller Exp $";
  31.  
  32. #ifdef __GNUG__
  33. #pragma implementation
  34. #endif
  35.  
  36. #include "fonts.h"
  37. #include "charsets.h"
  38.  
  39. #include "AppData.h"
  40. #include "DestroyCB.h"
  41. #include "LessTifH.h"
  42. #include "LiterateA.h"
  43. #include "StringSA.h"
  44. #include "assert.h"
  45. #include "converters.h"
  46. #include "cook.h"
  47. #include "ddd.h"
  48. #include "events.h"
  49. #include "shell.h"
  50. #include "status.h"
  51. #include "strclass.h"
  52. #include "string-fun.h"
  53. #include "post.h"
  54. #include "TimeOut.h"
  55.  
  56. #include <stdlib.h>        // atoi()
  57. #include <ctype.h>
  58. #include <Xm/TextF.h>
  59. #include <Xm/Text.h>
  60. #include <Xm/PushB.h>
  61. #include <X11/Xatom.h>        // XA_...
  62.  
  63.  
  64. //-----------------------------------------------------------------------------
  65. // Return X font attributes
  66. //-----------------------------------------------------------------------------
  67.  
  68. //  1     2    3    4     5     6  7     8    9    10   11  12   13     14
  69. // -fndry-fmly-wght-slant-sWdth-ad-pxlsz-ptSz-resx-resy-spc-avgW-rgstry-encdng
  70.  
  71. const int Foundry       = 1;
  72. const int Family        = 2;
  73. const int Weight        = 3;
  74. const int Slant         = 4;
  75. // const int sWidth     = 5;
  76. // const int Ad         = 6;
  77. // const int PixelSize  = 7;
  78. const int PointSize     = 8;
  79. // const int ResX       = 9;
  80. // const int ResY       = 10;
  81. // const int Spacing    = 11;
  82. // const int AvgWidth   = 12;
  83. // const int Registry   = 13;
  84. // const int Encoding   = 14;
  85.  
  86. const int AllComponents = 14;
  87.  
  88. typedef int FontComponent;
  89.  
  90. // Return the Nth component from NAME, or DEFAULT_VALUE if none
  91. static string component(string name, FontComponent n)
  92. {
  93.     // If name does not begin with `-', assume it's a font family
  94.     if (!name.contains('-', 0))
  95.     name.prepend("-*-");
  96.  
  97.     // Let I point to the Nth occurrence of `-'
  98.     int i = -1;
  99.     while (n >= Foundry && (i = name.index('-', i + 1)) >= 0)
  100.     n--;
  101.  
  102.     string w = "";
  103.     if (i >= 0)
  104.     {
  105.     w = name.after(i);
  106.     if (w.contains('-'))
  107.         w = w.before('-');
  108.     }
  109.  
  110.     return w;
  111. }
  112.  
  113.  
  114. //-----------------------------------------------------------------------------
  115. // Access X font resources
  116. //-----------------------------------------------------------------------------
  117.  
  118. // User-specified values
  119. static string userfont(const AppData& ad, DDDFont font)
  120. {
  121.     switch (font) 
  122.     {
  123.     case DefaultDDDFont:
  124.     return ad.default_font;
  125.     case VariableWidthDDDFont:
  126.     return ad.variable_width_font;
  127.     case FixedWidthDDDFont:
  128.     return ad.fixed_width_font;
  129.     case SymbolDDDFont:
  130.     return "";
  131.     }
  132.  
  133.     assert(0);
  134.     return "";            // Never reached
  135. }
  136.  
  137. // Return a symbolic name for FONT
  138. static string font_type(DDDFont font)
  139. {
  140.     switch (font)
  141.     {
  142.     case DefaultDDDFont:
  143.     return "default font";
  144.     case VariableWidthDDDFont:
  145.      return "variable width font";
  146.     case FixedWidthDDDFont:
  147.      return "fixed width font";
  148.     case SymbolDDDFont:
  149.      return "symbol font";
  150.     }
  151.  
  152.     assert(0);
  153.     return "";            // Never reached
  154. }
  155.  
  156. // defaults to use if nothing is specified
  157. static string fallbackfont(DDDFont font)
  158. {
  159.     switch (font) 
  160.     {
  161.     case DefaultDDDFont:
  162.      return "-*-helvetica-bold-r-*-*-*-120-*-*-*-*-iso8859-*";
  163.     case VariableWidthDDDFont:
  164.      return "-*-helvetica-medium-r-*-*-*-120-*-*-*-*-iso8859-*";
  165.     case FixedWidthDDDFont:
  166.      return "-*-lucidatypewriter-medium-r-*-*-*-120-*-*-*-*-iso8859-*";
  167.     case SymbolDDDFont:
  168.      return "-*-symbol-*-*-*-*-*-120-*-*-*-*-adobe-*";
  169.     }
  170.  
  171.     assert(0);
  172.     return "";            // Never reached
  173. }
  174.  
  175. // Fetch a component
  176. static string component(const AppData& ad, DDDFont font, FontComponent n)
  177. {
  178.     if (n == PointSize)
  179.     {
  180.     int sz = 0;
  181.     switch(font)
  182.     {
  183.     case DefaultDDDFont:
  184.         sz = ad.default_font_size;
  185.         break;
  186.  
  187.     case VariableWidthDDDFont:
  188.     case SymbolDDDFont:
  189.         sz = ad.variable_width_font_size;
  190.         break;
  191.  
  192.     case FixedWidthDDDFont:
  193.         sz = ad.fixed_width_font_size;
  194.         break;
  195.     }
  196.  
  197.     return itostring(sz);
  198.     }
  199.  
  200.     string w = component(userfont(ad, font), n);
  201.     if (w == "")        // nothing specified
  202.     w = component(fallbackfont(font), n);
  203.     return w;
  204. }
  205.  
  206.  
  207.  
  208. //-----------------------------------------------------------------------------
  209. // Create an X font name
  210. //-----------------------------------------------------------------------------
  211.  
  212. static string override(FontComponent new_n, 
  213.                const string& new_value, const string& font = "")
  214. {
  215.     string new_font = "";
  216.     for (FontComponent n = Foundry; n <= AllComponents; n++)
  217.     {
  218.     string w;
  219.     if (n == new_n)
  220.         w = new_value;
  221.     else
  222.         w = component(font, n);
  223.     new_font += "-" + w;
  224.     }
  225.  
  226.     return new_font;
  227. }
  228.  
  229. string make_font(const AppData& ad, DDDFont base, const string& override)
  230. {
  231.     string font = "";
  232.     for (FontComponent n = Foundry; n <= AllComponents; n++)
  233.     {
  234.     string w = component(override, n);
  235.     if (w == "" || w == " ")
  236.         w = component(ad, base, n);
  237.     font += "-" + w;
  238.     }
  239.  
  240. #if 0
  241.     clog << "make_font(" << font_type(base) << ", " << quote(override) 
  242.      << ") = " << quote(font) << "\n";
  243. #endif
  244.  
  245.     return font;
  246. }
  247.  
  248.  
  249.  
  250. //-----------------------------------------------------------------------------
  251. // Setup X fonts
  252. //-----------------------------------------------------------------------------
  253.  
  254. static StringStringAssoc font_defs;
  255.  
  256. static void define_font(const AppData& ad,
  257.             const string& name, DDDFont base, 
  258.             const string& override = "")
  259. {
  260.     string font = make_font(ad, base, override);
  261.     defineConversionMacro(upcase(name), font);
  262.     font_defs[name] = font;
  263.  
  264.     if (ad.show_fonts)
  265.     {
  266.     string sym;
  267.     if (name == MSTRING_DEFAULT_CHARSET)
  268.         sym = "default";
  269.     else
  270.         sym = "@" + name;
  271.     cout << sym << "\t" << font << "\n";
  272.     }
  273. }
  274.  
  275. static void set_db_font(const AppData& ad, XrmDatabase& db,
  276.             const string& line)
  277. {
  278.     XrmPutLineResource(&db, line);
  279.  
  280.     if (ad.show_fonts)
  281.     {
  282.     string s = line;
  283.     s.gsub(":", ": \\\n   ");
  284.     s.gsub(",", ",\\\n    ");
  285.     cout << s << "\n\n";
  286.     }
  287. }
  288.  
  289. static string define_default_font(const string& font_def)
  290. {
  291.     string s = "";
  292.  
  293.     // The canonical way of doing it.
  294.     s += font_def + "=" + MSTRING_DEFAULT_CHARSET + ",";
  295.  
  296.     // Special cases
  297.     if (string(MSTRING_DEFAULT_CHARSET) != "charset")
  298.     {
  299.     // This happens in Motif 1.1 and LessTif.  Ensure
  300.     // compatibility with other Motif versions.
  301.     s += font_def + "=charset,";
  302.     }
  303.  
  304.     return s;
  305. }
  306.         
  307.  
  308. static void setup_font_db(const AppData& ad, XrmDatabase& db)
  309. {
  310.     // Default fonts
  311.     string special_fontlist = 
  312.     font_defs[CHARSET_SMALL] + "=" CHARSET_SMALL "," +
  313.     font_defs[CHARSET_TT] + "=" CHARSET_TT "," +
  314.     font_defs[CHARSET_TB] + "=" CHARSET_TB "," +
  315.     font_defs[CHARSET_KEY] + "=" CHARSET_KEY "," +
  316.     font_defs[CHARSET_RM] + "=" CHARSET_RM "," +
  317.     font_defs[CHARSET_SL] + "=" CHARSET_SL "," +
  318.     font_defs[CHARSET_BF] + "=" CHARSET_BF "," +
  319.     font_defs[CHARSET_BS] + "=" CHARSET_BS "," +
  320.     font_defs[CHARSET_LOGO] + "=" CHARSET_LOGO "," +
  321.     font_defs[CHARSET_LLOGO] + "=" CHARSET_LLOGO "," +
  322.     font_defs[CHARSET_SYMBOL] + "=" CHARSET_SYMBOL;
  323.  
  324.  
  325.     string default_fontlist = 
  326.     define_default_font(font_defs[CHARSET_DEFAULT]) + special_fontlist;
  327.  
  328.     set_db_font(ad, db, string(DDD_CLASS_NAME "*") + 
  329.         XmCFontList + ": " + default_fontlist);
  330.  
  331.     // Text fonts
  332.     string text_fontlist = 
  333.     define_default_font(font_defs[CHARSET_TEXT]) + special_fontlist;
  334.  
  335.     set_db_font(ad, db, string(DDD_CLASS_NAME "*XmTextField.") + 
  336.         XmCFontList + ": " + text_fontlist);
  337.     set_db_font(ad, db, string(DDD_CLASS_NAME "*XmText.") + 
  338.         XmCFontList + ": " + text_fontlist);
  339.     set_db_font(ad, db, string(DDD_CLASS_NAME "*XmCommand*XmList.") + 
  340.         XmCFontList + ": " + text_fontlist);
  341.  
  342.     // Command tool fonts
  343.     string tool_fontlist = 
  344.     define_default_font(font_defs[CHARSET_LIGHT]) + special_fontlist;
  345.  
  346.     set_db_font(ad, db, 
  347.         string(DDD_CLASS_NAME "*tool_buttons.run.") + 
  348.         XmCFontList + ": " + default_fontlist);
  349.     set_db_font(ad, db, 
  350.         string(DDD_CLASS_NAME "*tool_buttons.break.") +
  351.         XmCFontList + ": " + default_fontlist);
  352.     set_db_font(ad, db, 
  353.         string(DDD_CLASS_NAME "*tool_buttons*") +
  354.         XmCFontList + ": " + tool_fontlist);
  355. }
  356.  
  357. static void title(const AppData& ad, const string& s)
  358. {
  359.     if (!ad.show_fonts)
  360.     return;
  361.  
  362.     static bool title_seen = false;
  363.  
  364.     if (title_seen)
  365.     cout << "\n\n";
  366.  
  367.     cout << s << "\n" << replicate("-", s.length()) << "\n\n";
  368.  
  369.     title_seen = true;
  370. }
  371.  
  372. static void setup_x_fonts(const AppData& ad, XrmDatabase& db)
  373. {
  374.     Dimension small_size = 
  375.     ((ad.default_font_size * 8) / 90) * 10;
  376.     Dimension llogo_size =
  377.     ((ad.default_font_size * 3) / 20) * 10;
  378.  
  379.     if (small_size < 80)
  380.     small_size = ad.default_font_size;
  381.  
  382.     string small_size_s = itostring(small_size);
  383.     string llogo_size_s = itostring(llogo_size);
  384.  
  385.     // Clear old font defs
  386.     static StringStringAssoc empty;
  387.     font_defs = empty;
  388.  
  389.     title(ad, "Symbolic font names");
  390.  
  391.     // Default font
  392.     define_font(ad, CHARSET_DEFAULT, DefaultDDDFont);
  393.  
  394.     define_font(ad, CHARSET_SMALL, DefaultDDDFont,
  395.         override(PointSize, small_size_s));
  396.  
  397.     define_font(ad, CHARSET_LIGHT, DefaultDDDFont,
  398.         override(Weight, "medium",
  399.              override(PointSize, small_size_s)));
  400.  
  401.     // Text fonts
  402.     define_font(ad, CHARSET_TEXT, FixedWidthDDDFont);
  403.  
  404.     // Text fonts
  405.     define_font(ad, CHARSET_LOGO, VariableWidthDDDFont,
  406.         override(Weight, "bold"));
  407.  
  408.     define_font(ad, CHARSET_LLOGO, VariableWidthDDDFont,
  409.         override(Weight, "bold",
  410.              override(PointSize, llogo_size_s)));
  411.  
  412.     define_font(ad, CHARSET_RM, VariableWidthDDDFont,
  413.         override(Slant, "r"));
  414.  
  415.     define_font(ad, CHARSET_SL, VariableWidthDDDFont,
  416.         override(Slant, "*")); // matches `i' and `o'
  417.  
  418.     define_font(ad, CHARSET_BF, VariableWidthDDDFont,
  419.         override(Weight, "bold",
  420.              override(Slant, "r")));
  421.  
  422.     define_font(ad, CHARSET_BS, VariableWidthDDDFont,
  423.         override(Weight, "bold",
  424.              override(Slant, "*")));
  425.  
  426.     define_font(ad, CHARSET_TT, FixedWidthDDDFont);
  427.  
  428.     define_font(ad, CHARSET_TB, FixedWidthDDDFont,
  429.         override(Weight, "bold"));
  430.  
  431.     define_font(ad, CHARSET_TS, FixedWidthDDDFont,
  432.         override(Slant, "*"));
  433.  
  434.     define_font(ad, CHARSET_TBS, FixedWidthDDDFont,
  435.         override(Weight, "bold",
  436.              override(Slant, "*")));
  437.  
  438.     define_font(ad, CHARSET_KEY, VariableWidthDDDFont,
  439.         override(Weight, "bold"));
  440.  
  441.     define_font(ad, CHARSET_SYMBOL, SymbolDDDFont);
  442.  
  443.     title(ad, "Font resources");
  444.  
  445.     setup_font_db(ad, db);
  446. }
  447.  
  448.  
  449.  
  450. //-----------------------------------------------------------------------------
  451. // Set VSL font resources
  452. //-----------------------------------------------------------------------------
  453.  
  454. static void replace_vsl_def(string& s, const string& func, const string& val)
  455. {
  456.     s += "#pragma replace " + func + "\n" + 
  457.     func + "(box) = font(box, " + val + ");\n";
  458. }
  459.  
  460. static void setup_vsl_fonts(AppData& ad)
  461. {
  462.     static string defs;
  463.  
  464.     title(ad, "VSL defs");
  465.  
  466.     replace_vsl_def(defs, "rm", quote(font_defs[CHARSET_TT]));
  467.     replace_vsl_def(defs, "bf", quote(font_defs[CHARSET_TB]));
  468.     replace_vsl_def(defs, "it", quote(font_defs[CHARSET_TS]));
  469.     replace_vsl_def(defs, "bi", quote(font_defs[CHARSET_TBS]));
  470.     replace_vsl_def(defs, "small", quote(font_defs[CHARSET_LIGHT]));
  471.  
  472.     if (ad.show_fonts)
  473.     cout << defs;
  474.  
  475.     defs += ad.vsl_base_defs;
  476.     ad.vsl_base_defs = defs;
  477. }
  478.  
  479. void setup_fonts(AppData& ad, XrmDatabase db)
  480. {
  481.     XrmDatabase db2 = db;
  482.     setup_x_fonts(ad, db2);
  483.     assert(db == db2);
  484.  
  485.     setup_vsl_fonts(ad);
  486. }
  487.  
  488.  
  489.  
  490. //-----------------------------------------------------------------------------
  491. // Handle font resources
  492. //-----------------------------------------------------------------------------
  493.  
  494. // Simplify font specs
  495. static string simplify_font(const AppData& ad, DDDFont font, 
  496.                 const string& source)
  497. {
  498.     string s = "";
  499.  
  500.     for (FontComponent n = AllComponents; n >= Foundry; n--)
  501.     {
  502.     string c = component(source, n);
  503.     if (s == "" && c == component(ad, font, n))
  504.     {
  505.         // Default setting -- ignore
  506.     }
  507.     else
  508.     {
  509.         s.prepend("-" + c);
  510.     }
  511.     }
  512.  
  513.     if (s.contains("-*-", 0))
  514.     s = s.after("-*-");
  515.  
  516.     if (s == "")
  517.     s = component(ad, font, Family);
  518.     if (!s.contains('-'))
  519.     s += "-" + component(ad, font, Weight);
  520.  
  521. #if 0
  522.     clog << "simplify_font(" << font_type(font) << ", " 
  523.      << quote(source) << ") = " << quote(s) << "\n";
  524. #endif
  525.  
  526.     return s;
  527. }
  528.  
  529. // Set a new font resource
  530. void set_font(DDDFont font, const string& name)
  531. {
  532.     switch (font)
  533.     {
  534.     case DefaultDDDFont:
  535.     {
  536.     static string s;
  537.     s = name;
  538.     app_data.default_font = s;
  539.     break;
  540.     }
  541.     case VariableWidthDDDFont:
  542.     {
  543.     static string s;
  544.     s = name;
  545.     app_data.variable_width_font = s;
  546.     break;
  547.     }
  548.     case FixedWidthDDDFont:
  549.     {
  550.     static string s;
  551.     s = name;
  552.     app_data.fixed_width_font = s;
  553.     break;
  554.     }
  555.     default:
  556.     assert(0);
  557.     }
  558. }
  559.  
  560. // Set a new font resource
  561. void set_font_size(DDDFont font, int size)
  562. {
  563.     switch (font)
  564.     {
  565.     case DefaultDDDFont:
  566.     app_data.default_font_size = size;
  567.     break;
  568.     case VariableWidthDDDFont:
  569.     app_data.variable_width_font_size = size;
  570.     break;
  571.     case FixedWidthDDDFont:
  572.     app_data.fixed_width_font_size = size;
  573.     break;
  574.     default:
  575.     assert(0);
  576.     }
  577. }
  578.  
  579.  
  580. void SetFontNameCB(Widget w, XtPointer client_data, XtPointer)
  581. {
  582.     DDDFont font = (DDDFont) (long) client_data;
  583.     String s = XmTextFieldGetString(w);
  584.     set_font(font, s);
  585.     XtFree(s);
  586.  
  587.     update_reset_preferences();
  588. }
  589.  
  590. void SetFontSizeCB(Widget w, XtPointer client_data, XtPointer)
  591. {
  592.     DDDFont font = (DDDFont) (long) client_data;
  593.     String s = XmTextFieldGetString(w);
  594.     set_font_size(font, atoi(s));
  595.     XtFree(s);
  596.  
  597.     update_reset_preferences();
  598. }
  599.  
  600.  
  601.  
  602. //-----------------------------------------------------------------------------
  603. // Font browser
  604. //-----------------------------------------------------------------------------
  605.  
  606. struct FontSelectInfo {
  607.     DDDFont font;
  608.     Widget text;
  609. };
  610.  
  611. static void gdbDeleteFontSelectAgent(XtPointer client_data, XtIntervalId *)
  612. {
  613.     // Delete agent after use
  614.     Agent *font_select_agent = (Agent *)client_data;
  615.     delete font_select_agent;
  616. }
  617.  
  618. static string output_buffer;
  619.  
  620. static void FontSelectionErrorHP(Agent *, void *, void *call_data)
  621. {
  622.     DataLength *input = (DataLength *)call_data;
  623.     output_buffer += string(input->data, input->length);
  624.     while (output_buffer.contains('\n'))
  625.     {
  626.     set_status(output_buffer.before('\n'));
  627.     output_buffer = output_buffer.after('\n');
  628.     }
  629.     if (output_buffer != "")
  630.     set_status(output_buffer);
  631. }
  632.  
  633. static void DeleteAgentHP(Agent *agent, void *client_data, void *)
  634. {
  635.     FontSelectInfo *info = (FontSelectInfo *)client_data;
  636.  
  637.     // Agent has died -- delete it
  638.     XtAppAddTimeOut(XtWidgetToApplicationContext(gdb_w), 0, 
  639.             gdbDeleteFontSelectAgent, 
  640.             XtPointer(agent));
  641.  
  642.     // Destroy the text
  643.     DestroyWhenIdle(info->text);
  644.  
  645.     if (output_buffer != "")
  646.     set_status("");
  647. }
  648.  
  649. static void process_font(DDDFont font, string fontspec)
  650. {
  651.     string sz = component(fontspec, PointSize);
  652.     if (sz != "*")
  653.     set_font_size(font, atoi(sz));
  654.  
  655.     fontspec.gsub('*', ' ');
  656.     set_font(font, simplify_font(app_data, font, 
  657.                  make_font(app_data, font, fontspec)));
  658.  
  659.     update_options();
  660. }
  661.  
  662. // Handle `Quit' button in xfontsel
  663. static void FontSelectionDoneHP(Agent *agent, void *client_data, 
  664.                 void *call_data)
  665. {
  666.     FontSelectInfo *info = (FontSelectInfo *)client_data;
  667.  
  668.     // Fetch string from font selector
  669.     DataLength *d = (DataLength *)call_data;
  670.     string fontspec(d->data, d->length);
  671.     strip_space(fontspec);
  672.  
  673.     if (!fontspec.contains('-', 0))
  674.     {
  675.     // Treat as error
  676.     FontSelectionErrorHP(agent, client_data, call_data);
  677.     return;
  678.     }
  679.  
  680.     process_font(info->font, fontspec);
  681. }
  682.  
  683.  
  684. static void GotSelectionCB(Widget w, XtPointer client_data,
  685.                Atom *, Atom *type, XtPointer value,
  686.                unsigned long *length, int *format)
  687. {
  688.     FontSelectInfo *info = (FontSelectInfo *)client_data;
  689.  
  690.     if (*type == None)
  691.     return;            // Could not fetch selection
  692.  
  693.     if (*type != XA_STRING)
  694.     {
  695.     XtFree((char *)value);
  696.     return;            // Not a string
  697.     }
  698.  
  699.     if (*format != 8)
  700.     {
  701.     XtFree((char *)value);
  702.     return;            // No 8-bit-string
  703.     }
  704.  
  705.     string s((String)value, *length);
  706.     if (s.contains('\0'))
  707.     s = s.before('\0');
  708.     XtFree((char *)value);
  709.  
  710.     if (s.contains("-", 0) && !s.contains('\n') && 
  711.     s.freq('-') == AllComponents)
  712.     {
  713.     process_font(info->font, s);
  714.     }
  715.  
  716.     XmTextSetString(w, (String)s);
  717.  
  718.     // Get the selection again.
  719.     // This will fail if we have multiple font selectors (FIXME).
  720.     XmTextSetSelection(w, 0, s.length(), 
  721.                XtLastTimestampProcessed(XtDisplay(w)));
  722. }
  723.  
  724. // Handle `Select' button in xfontsel
  725. static void SelectionLostCB(Widget w, XtPointer client_data, XtPointer)
  726. {
  727.     FontSelectInfo *info = (FontSelectInfo *)client_data;
  728.     assert(info->text == w);
  729.  
  730.     XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, GotSelectionCB,
  731.             XtPointer(info), 
  732.             XtLastTimestampProcessed(XtDisplay(w)));
  733. }
  734.  
  735.  
  736. // Browse fonts
  737. void BrowseFontCB(Widget w, XtPointer client_data, XtPointer call_data)
  738. {
  739.     Time tm = CurrentTime;
  740.     XmPushButtonCallbackStruct *cbs = (XmPushButtonCallbackStruct *)call_data;
  741.     if (cbs && cbs->event)
  742.     tm = time(cbs->event);
  743.  
  744.     DDDFont font = (DDDFont) (long) client_data;
  745.  
  746.     StatusDelay delay("Invoking " + font_type(font) + " selector");
  747.  
  748.     string cmd = app_data.font_select_command;
  749.     cmd.gsub("@FONT@", make_font(app_data, DefaultDDDFont));
  750.     string type = font_type(font);
  751.     type[0] = toupper(type[0]);
  752.     cmd.gsub("@TYPE@", type);
  753.     cmd = sh_command(cmd, true);
  754.  
  755.     // Create a TextField to fetch the selection
  756.     FontSelectInfo *info = new FontSelectInfo;
  757.     info->text = XmCreateText(XtParent(w), "text", 0, 0);
  758.     info->font = font;
  759.  
  760.     XtRealizeWidget(info->text);
  761.  
  762.     string text = "dummy";
  763.     XmTextSetString(info->text, (String)text);
  764.     XmTextSetSelection(info->text, 0, text.length(), tm);
  765.     XtAddCallback(info->text, XmNlosePrimaryCallback, 
  766.           SelectionLostCB, XtPointer(info));
  767.  
  768.     // Invoke a font selector
  769.     LiterateAgent *font_select_agent = 
  770.     new LiterateAgent(XtWidgetToApplicationContext(w), cmd);
  771.  
  772.     output_buffer = "";
  773.  
  774.     font_select_agent->removeAllHandlers(Died);
  775.     font_select_agent->addHandler(Died,
  776.                   DeleteAgentHP, (void *)info);
  777.     font_select_agent->addHandler(Input,
  778.                   FontSelectionDoneHP, (void *)info);
  779.     font_select_agent->addHandler(Error,
  780.                   FontSelectionErrorHP, (void *)info);
  781.     font_select_agent->start();
  782. }
  783.