home *** CD-ROM | disk | FTP | other *** search
/ vsiftp.vmssoftware.com / VSIPUBLIC@vsiftp.vmssoftware.com.tar / FREEWARE / FREEWARE40.ZIP / xpaint-244 / src / fontselect.c < prev    next >
C/C++ Source or Header  |  1996-07-28  |  26KB  |  970 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com)           | */
  3. /* |                                       | */
  4. /* | Permission to use, copy, modify, and to distribute this software  | */
  5. /* | and its documentation for any purpose is hereby granted without   | */
  6. /* | fee, provided that the above copyright notice appear in all       | */
  7. /* | copies and that both that copyright notice and this permission    | */
  8. /* | notice appear in supporting documentation.     There is no           | */
  9. /* | representations about the suitability of this software for           | */
  10. /* | any purpose.  this software is provided "as is" without express   | */
  11. /* | or implied warranty.                           | */
  12. /* |                                       | */
  13. /* +-------------------------------------------------------------------+ */
  14.  
  15. /* $Id: fontSelect.c,v 1.3 1996/04/19 09:07:49 torsten Exp $ */
  16.  
  17. #include <X11/StringDefs.h>
  18. #include <X11/Intrinsic.h>
  19. #include <X11/Shell.h>
  20. #ifndef VMS
  21. #include <X11/Xaw/Form.h>
  22. #include <X11/Xaw/Paned.h>
  23. #include <X11/Xaw/List.h>
  24. #include <X11/Xaw/AsciiText.h>
  25. #include <X11/Xaw/Command.h>
  26. #include <X11/Xaw/Viewport.h>
  27. #else
  28. #include <X11Xaw/Form.h>
  29. #include <X11Xaw/Paned.h>
  30. #include <X11Xaw/List.h>
  31. #include <X11Xaw/AsciiText.h>
  32. #include <X11Xaw/Command.h>
  33. #include <X11Xaw/Viewport.h>
  34. #endif
  35. #include <X11/Xos.h>
  36. #include <math.h>
  37. #include <stdio.h>
  38.  
  39. /*
  40. **  swiped from X11/Xfuncproto.h
  41. **   since qsort() may or may not be defined with a constant sub-function
  42.  */
  43. #ifndef _Xconst
  44. #if __STDC__ || defined(__cplusplus) || defined(c_plusplus) || (FUNCPROTO&4)
  45. #define _Xconst const
  46. #else
  47. #define _Xconst
  48. #endif
  49. #endif                /* _Xconst */
  50.  
  51. #ifndef NOSTDHDRS
  52. #include <stdlib.h>
  53. #include <unistd.h>
  54. #endif
  55.  
  56. #include "xpaint.h"
  57. #include "misc.h"
  58. #include "operation.h"
  59. #include "ops.h"
  60. #include "graphic.h"
  61. #include "protocol.h"
  62.  
  63. typedef struct {
  64.     char *fontFamily;
  65.     char *registry;
  66.     char *foundry;
  67.     char *weight;
  68.     char *slant;
  69.     char *setWidth;
  70.     char *points;
  71.     char *spacing;
  72.     Boolean forcePoint;
  73. } FontName;
  74.  
  75. static Boolean haveScalable = False;
  76.  
  77. typedef struct StringList_s {
  78.     char *str;
  79.     struct StringList_s *next;
  80. } StringList;
  81.  
  82. typedef struct {
  83.     int number;
  84.     FontName *names;
  85.     char **namesStorage;
  86.     Widget text, paint;
  87.     Widget family, weight, point, spacing;
  88.     Widget expect, pointSelect;
  89.     Widget fontName;
  90.     Boolean expectFlag;
  91. } arg_t;
  92.  
  93.  
  94. static struct shortFamily_s {
  95.     char *name;
  96.     char *family, *registry, *foundry;
  97. } shortFamily[128];
  98. static int shortFamilyNum = 0;
  99.  
  100. static arg_t *theArg = NULL;
  101.  
  102. static char *
  103. getShortFamily(char *family, char *foundry, char *registry)
  104. {
  105.     int i;
  106.  
  107.     for (i = 0; i < shortFamilyNum; i++) {
  108.     if (strcmp(shortFamily[i].family, family) == 0 &&
  109.         strcmp(shortFamily[i].foundry, foundry) == 0 &&
  110.         strcmp(shortFamily[i].registry, registry) == 0)
  111.         return shortFamily[i].name;
  112.     }
  113.     return "UNKNOWN";
  114. }
  115.  
  116. static void 
  117. makeShortFamily(char *family, char *foundry, char *registry)
  118. {
  119.     char buf[256];
  120.  
  121.     if (strcmp(getShortFamily(family, foundry, registry), "UNKNOWN") != 0)
  122.     return;
  123.  
  124.     shortFamily[shortFamilyNum].family = family;
  125.     shortFamily[shortFamilyNum].foundry = foundry;
  126.     shortFamily[shortFamilyNum].registry = registry;
  127.     sprintf(buf, "%s (%s,%s)", family, foundry, registry);
  128.     shortFamily[shortFamilyNum].name = XtNewString(buf);
  129.     shortFamilyNum++;
  130. }
  131.  
  132. static struct shortSizes_s {
  133.     char *name;
  134.     char *weight;
  135.     char *slant;
  136.     char *setWidth;
  137.     char *serif;
  138. } shortSizes[128];
  139. static int shortSizesNum = 0;
  140.  
  141. static char *
  142. getShortName(char *weight, char *slant, char *setWidth, char *serif)
  143. {
  144.     int i;
  145.     for (i = 0; i < shortSizesNum; i++) {
  146.     if (strcmp(shortSizes[i].weight, weight) == 0 &&
  147.         strcmp(shortSizes[i].slant, slant) == 0 &&
  148.         strcmp(shortSizes[i].setWidth, setWidth) == 0 &&
  149.         strcmp(shortSizes[i].serif, serif) == 0)
  150.         return shortSizes[i].name;
  151.     }
  152.     return "UNKNOWN";
  153. }
  154.  
  155. static void 
  156. makeShortName(char *weight, char *slant, char *setWidth, char *serif)
  157. {
  158.     char *weStr, *slStr, *swStr, *seStr;
  159.     char *cp, buf[128];
  160.  
  161.     if (strcmp(getShortName(weight, slant, setWidth, serif), "UNKNOWN") != 0)
  162.     return;
  163.  
  164.     shortSizes[shortSizesNum].weight = weight;
  165.     shortSizes[shortSizesNum].slant = slant;
  166.     shortSizes[shortSizesNum].setWidth = setWidth;
  167.     shortSizes[shortSizesNum].serif = serif;
  168.  
  169.     if (*weight == '\0')
  170.     weStr = NULL;
  171.     else if (strcmp(weight, "medium") == 0)
  172.     weStr = "";
  173.     else if (strcmp(weight, "bold") == 0)
  174.     weStr = "Bold";
  175.     else
  176.     weStr = weight;
  177.  
  178.     if (*slant == '\0')
  179.     slStr = NULL;
  180.     else if (*slant == 'r')
  181.     slStr = "";
  182.     else if (*slant == 'i')
  183.     slStr = "Italic";
  184.     else if (*slant == 'o')
  185.     slStr = "Oblique";
  186.     else
  187.     slStr = slant;
  188.  
  189.     if (*setWidth == '\0')
  190.     swStr = NULL;
  191.     else if (strcmp(setWidth, "normal") == 0)
  192.     swStr = "";
  193.     else if (strcmp(setWidth, "semicondensed") == 0)
  194.     swStr = "Condensed";
  195.     else
  196.     swStr = setWidth;
  197.  
  198.     if (*serif == '\0')
  199.     seStr = NULL;
  200.     else if (strcmp(serif, "sans") == 0)
  201.     seStr = "";
  202.     else
  203.     seStr = serif;
  204.  
  205.     if (weStr == NULL && slStr == NULL && swStr == NULL && seStr == NULL) {
  206.     shortSizes[shortSizesNum++].name = "Unspecified";
  207.     return;
  208.     }
  209.     if (weStr == NULL)
  210.     weStr = "";
  211.     if (slStr == NULL)
  212.     slStr = "";
  213.     if (swStr == NULL)
  214.     swStr = "";
  215.     if (seStr == NULL)
  216.     seStr = "";
  217.  
  218.     if (*weStr == '\0' && *slStr == '\0' && *swStr == '\0' && *seStr == '\0') {
  219.     shortSizes[shortSizesNum++].name = "Normal";
  220.     return;
  221.     }
  222.     /*
  223.     ** Make the string, eat the leading and trailing white space.
  224.      */
  225.     sprintf(buf, "%s %s %s %s", weStr, slStr, swStr, seStr);
  226.     for (cp = buf + strlen(buf) - 1; *cp == ' '; cp--);
  227.     *++cp = '\0';
  228.     for (cp = buf; *cp == ' '; cp++);
  229.     shortSizes[shortSizesNum++].name = XtNewString(cp);
  230. }
  231.  
  232. static FontName *
  233. getSettings(arg_t * arg)
  234. {
  235.     static char pointBuf[20];
  236.     static FontName name;
  237.     XawListReturnStruct *item;
  238.     int i;
  239.  
  240.     name.fontFamily = NULL;
  241.     name.weight = NULL;
  242.     name.slant = NULL;
  243.     name.setWidth = NULL;
  244.     name.points = NULL;
  245.     name.spacing = NULL;
  246.     name.foundry = NULL;
  247.     name.registry = NULL;
  248.     name.forcePoint = False;
  249.  
  250.     if ((item = XawListShowCurrent(arg->family))->list_index != XAW_LIST_NONE) {
  251.     for (i = 0; i < XtNumber(shortFamily); i++) {
  252.         if (strcmp(item->string, shortFamily[i].name) == 0) {
  253.         name.fontFamily = shortFamily[i].family;
  254.         name.registry = shortFamily[i].registry;
  255.         name.foundry = shortFamily[i].foundry;
  256.         break;
  257.         }
  258.     }
  259.     XtFree((XtPointer) item);
  260.     }
  261.     if ((item = XawListShowCurrent(arg->point))->list_index != XAW_LIST_NONE) {
  262.     float ps = atof(item->string);
  263.     if (ps < 0.1 && haveScalable) {
  264.         String str;
  265.         name.forcePoint = True;
  266.         XtVaGetValues(arg->pointSelect, XtNstring, &str, NULL);
  267.         ps = atof(str);
  268.         if (ps < 0.1) {
  269.         ps = 12.0;
  270.         XtVaSetValues(arg->pointSelect, XtNstring, "12", NULL);
  271.         }
  272.     }
  273.     sprintf(pointBuf, "%d", (int) (ps * 10.0));
  274.     name.points = pointBuf;
  275.     XtFree((XtPointer) item);
  276.     }
  277.     if ((item = XawListShowCurrent(arg->weight))->list_index != XAW_LIST_NONE) {
  278.     for (i = 0; i < XtNumber(shortSizes); i++) {
  279.         if (strcmp(item->string, shortSizes[i].name) == 0) {
  280.         name.weight = shortSizes[i].weight;
  281.         name.slant = shortSizes[i].slant;
  282.         name.setWidth = shortSizes[i].setWidth;
  283.         break;
  284.         }
  285.     }
  286.     XtFree((XtPointer) item);
  287.     }
  288.     if ((item = XawListShowCurrent(arg->spacing))->list_index != XAW_LIST_NONE) {
  289.     if (strcmp(item->string, "Fixed") == 0)
  290.         name.spacing = "m";
  291.     else if (strcmp(item->string, "Variable") == 0)
  292.         name.spacing = "p";
  293.     else if (strcmp(item->string, "Cell") == 0)
  294.         name.spacing = "c";
  295.     else
  296.         name.spacing = item->string;
  297.     XtFree((XtPointer) item);
  298.     }
  299.     return &name;
  300. }
  301.  
  302. static int 
  303. strqsortcmp(char **a, char **b)
  304. {
  305.     return strcmp(*a, *b);
  306. }
  307.  
  308. static int 
  309. valqsortcmp(char **a, char **b)
  310. {
  311.     float fa = atof(*a);
  312.     float fb = atof(*b);
  313.     if (fa == fb)
  314.     return 0;
  315.     if (fa < fb)
  316.     return -1;
  317.     return 1;
  318. }
  319.  
  320. static void 
  321. cleanLists(arg_t * arg)
  322. {
  323.     String *strs;
  324.     int num;
  325.  
  326.     XtVaGetValues(arg->spacing, XtNnumberStrings, &num, XtNlist, &strs, NULL);
  327.     if (strs != NULL && num != 0)
  328.     XtFree((XtPointer) strs);
  329.     XtVaGetValues(arg->family, XtNnumberStrings, &num, XtNlist, &strs, NULL);
  330.     if (strs != NULL && num != 0)
  331.     XtFree((XtPointer) strs);
  332.     XtVaGetValues(arg->weight, XtNnumberStrings, &num, XtNlist, &strs, NULL);
  333.     if (strs != NULL && num != 0)
  334.     XtFree((XtPointer) strs);
  335.     XtVaGetValues(arg->point, XtNnumberStrings, &num, XtNlist, &strs, NULL);
  336.     if (strs != NULL && num != 0) {
  337.     int i;
  338.     for (i = 0; i < num; i++)
  339.         XtFree((XtPointer) strs[i]);
  340.     XtFree((XtPointer) strs);
  341.     }
  342. }
  343.  
  344. static void 
  345. match(arg_t * arg)
  346. {
  347.     static int firstTime = True;
  348.     int i;
  349.     int count = 0;
  350.     char *nm;
  351.     FontName *cur = arg->names, *last = NULL;
  352.     FontName *set = getSettings(arg);
  353.     StringList *familyList = NULL, *pointList = NULL;
  354.     StringList *weightList = NULL, *spacingList = NULL;
  355.     int familyListLen = 0, pointListLen = 0;
  356.     int weightListLen = 0, spacingListLen = 0;
  357.     StringList *curStr, *nxtStr;
  358.     String *list;
  359.  
  360.     if (firstTime)
  361.     firstTime = False;
  362.     else
  363.     cleanLists(arg);
  364.  
  365.     for (i = 0; i < arg->number; i++, cur++) {
  366.  
  367. #define TEST(f)    if (set->f != NULL && strcmp(set->f, cur->f) != 0) continue
  368.     TEST(fontFamily);
  369.     TEST(foundry);
  370.     TEST(registry);
  371.     TEST(weight);
  372.     TEST(slant);
  373.     TEST(setWidth);
  374.     if (set->forcePoint) {
  375.         if (strcmp(cur->points, "0") != 0)
  376.         continue;
  377.     } else {
  378.         TEST(points);
  379.     }
  380.     TEST(spacing);
  381. #undef TEST
  382.  
  383.     /*
  384.     **  Add the family name
  385.      */
  386.     switch (*cur->spacing) {
  387.     case 'm':
  388.         nm = "Fixed";
  389.         break;
  390.     case 'p':
  391.         nm = "Variable";
  392.         break;
  393.     case 'c':
  394.         nm = "Cell";
  395.         break;
  396.     default:
  397.         nm = cur->spacing;
  398.         break;
  399.     }
  400.     for (curStr = spacingList; curStr != NULL; curStr = curStr->next) {
  401.         if (strcmp(curStr->str, nm) == 0)
  402.         break;
  403.     }
  404.     if (curStr == NULL) {
  405.         curStr = XtNew(StringList);
  406.         curStr->next = spacingList;
  407.         curStr->str = nm;
  408.         spacingList = curStr;
  409.         spacingListLen++;
  410.     }
  411.     /*
  412.     **  Add the family name
  413.      */
  414.     nm = getShortFamily(cur->fontFamily, cur->foundry, cur->registry);
  415.     for (curStr = familyList; curStr != NULL; curStr = curStr->next) {
  416.         if (strcmp(curStr->str, nm) == 0)
  417.         break;
  418.     }
  419.     if (curStr == NULL) {
  420.         curStr = XtNew(StringList);
  421.         curStr->next = familyList;
  422.         curStr->str = nm;
  423.         familyList = curStr;
  424.         familyListLen++;
  425.     }
  426.     /*
  427.     **  Add the width info
  428.      */
  429.     nm = getShortName(cur->weight, cur->slant, cur->setWidth, "");
  430.     for (curStr = weightList; curStr != NULL; curStr = curStr->next) {
  431.         if (strcmp(curStr->str, nm) == 0)
  432.         break;
  433.     }
  434.     if (curStr == NULL) {
  435.         curStr = XtNew(StringList);
  436.         curStr->next = weightList;
  437.         curStr->str = nm;
  438.         weightList = curStr;
  439.         weightListLen++;
  440.     }
  441.     /*
  442.     **  Add the point size
  443.      */
  444.     for (curStr = pointList; curStr != NULL; curStr = curStr->next) {
  445.         if ((int) (atof(curStr->str) * 10.0) == atoi(cur->points))
  446.         break;
  447.     }
  448.     if (curStr == NULL) {
  449.         char buf[14];
  450.         int p = atoi(cur->points);
  451.  
  452.         curStr = XtNew(StringList);
  453.         curStr->next = pointList;
  454.         if (p % 10 == 0) {
  455.         sprintf(buf, "%d   ", p / 10);
  456.         } else {
  457.         sprintf(buf, "%d.%d   ", p / 10, p % 10);
  458.         }
  459.         curStr->str = XtNewString(buf);
  460.         pointList = curStr;
  461.         pointListLen++;
  462.     }
  463.     count++;
  464.     last = cur;
  465.     }
  466.  
  467.     if (count == 1 && last != NULL) {
  468.     char buf[512];
  469.     XFontStruct *info;
  470.     sprintf(buf, "-%s-%s-%s-%s-%s-*-*-%s-*-*-%s-*-%s-*",
  471.         last->foundry,
  472.         last->fontFamily,
  473.         last->weight == NULL ? "" : last->weight,
  474.         last->slant == NULL ? "" : last->slant,
  475.         last->setWidth == NULL ? "" : last->setWidth,
  476.         set->forcePoint ? set->points : last->points,
  477.         last->spacing,
  478.         last->registry);
  479.  
  480.     if ((info = XLoadQueryFont(XtDisplay(arg->text), buf)) != NULL) {
  481.         XtVaSetValues(arg->text,
  482.               XtNfont, info,
  483.               XtNstring,
  484.         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijlmnopqrstuvwxyz0123456789",
  485.               NULL);
  486.         XtVaSetValues(arg->fontName, XtNstring, buf, NULL);
  487.     }
  488.     } else {
  489.     XtVaSetValues(arg->text, XtNstring, "", NULL);
  490.     XtVaSetValues(arg->fontName, XtNstring, "", NULL);
  491.     }
  492.  
  493.     /*
  494.     **    Set the widgets
  495.      */
  496.  
  497.     list = (String *) XtCalloc(spacingListLen + 1, sizeof(String));
  498.     for (i = 0, curStr = spacingList; curStr != NULL; curStr = curStr->next, i++)
  499.     list[i] = curStr->str;
  500.     qsort(list, i, sizeof(String),
  501.       (int (*)(_Xconst void *, _Xconst void *)) strqsortcmp);
  502.     XawListChange(arg->spacing, list, spacingListLen, 0, True);
  503.     if (set->spacing)
  504.     XawListHighlight(arg->spacing, 0);
  505.  
  506.     list = (String *) XtCalloc(familyListLen + 1, sizeof(String));
  507.     for (i = 0, curStr = familyList; curStr != NULL; curStr = curStr->next, i++)
  508.     list[i] = curStr->str;
  509.     qsort(list, i, sizeof(String),
  510.       (int (*)(_Xconst void *, _Xconst void *)) strqsortcmp);
  511.     XawListChange(arg->family, list, familyListLen, 0, True);
  512.     if (set->fontFamily)
  513.     XawListHighlight(arg->family, 0);
  514.  
  515.     list = (String *) XtCalloc(weightListLen + 1, sizeof(String));
  516.     for (i = 0, curStr = weightList; curStr != NULL; curStr = curStr->next, i++)
  517.     list[i] = curStr->str;
  518.     qsort(list, i, sizeof(String),
  519.       (int (*)(_Xconst void *, _Xconst void *)) strqsortcmp);
  520.     XawListChange(arg->weight, list, weightListLen, 0, True);
  521.     if (set->weight)
  522.     XawListHighlight(arg->weight, 0);
  523.  
  524.     list = (String *) XtCalloc(pointListLen + 1, sizeof(String));
  525.     for (i = 0, curStr = pointList; curStr != NULL; curStr = curStr->next, i++)
  526.     list[i] = curStr->str;
  527.     qsort(list, i, sizeof(String),
  528.       (int (*)(_Xconst void *, _Xconst void *)) valqsortcmp);
  529.     XawListChange(arg->point, list, pointListLen, 0, True);
  530.     if (set->points)
  531.     XawListHighlight(arg->point, 0);
  532.  
  533.     /*
  534.     **    Clean up
  535.      */
  536.     for (curStr = spacingList; curStr != NULL; curStr = nxtStr) {
  537.     nxtStr = curStr->next;
  538.     XtFree((XtPointer) curStr);
  539.     }
  540.     for (curStr = familyList; curStr != NULL; curStr = nxtStr) {
  541.     nxtStr = curStr->next;
  542.     XtFree((XtPointer) curStr);
  543.     }
  544.     for (curStr = weightList; curStr != NULL; curStr = nxtStr) {
  545.     nxtStr = curStr->next;
  546.     XtFree((XtPointer) curStr);
  547.     }
  548.     for (curStr = pointList; curStr != NULL; curStr = nxtStr) {
  549.     nxtStr = curStr->next;
  550.     XtFree((XtPointer) curStr);
  551.     }
  552. }
  553.  
  554. static FontName *
  555. chop(int *number, char **names)
  556. {
  557.     int i, j, count = 0;
  558.     FontName *n = (FontName *) XtCalloc(*number, sizeof(FontName));
  559.  
  560.     if (n == NULL)
  561.     return NULL;
  562.  
  563. #define NEXT(p) {    char    *np;                \
  564.             if ((np = strchr(p, '-')) == NULL)    \
  565.                 continue;            \
  566.             *np++ = '\0';                \
  567.             p = np;                    \
  568.         }
  569.  
  570.     for (i = 0; i < *number; i++) {
  571.     char *cp = names[i];
  572.     FontName *cur = &n[count];
  573.  
  574.     NEXT(cp);        /* foundry */
  575.     cur->foundry = cp;
  576.     NEXT(cp);        /* font family */
  577.     cur->fontFamily = cp;
  578.     NEXT(cp);        /* weight */
  579.     cur->weight = cp;
  580.     NEXT(cp);        /* slant */
  581.     cur->slant = cp;
  582.     NEXT(cp);        /* set width */
  583.     cur->setWidth = cp;
  584.     NEXT(cp);        /* NULL */
  585.     NEXT(cp);        /* pixels */
  586.     NEXT(cp);        /* point size */
  587.     cur->points = cp;
  588.     NEXT(cp);        /* horizontal resolution */
  589.     NEXT(cp);        /* vertical resolution */
  590.     NEXT(cp);        /* spacing */
  591.     cur->spacing = cp;
  592.     NEXT(cp);        /* average width */
  593.     NEXT(cp);        /* character set */
  594.     cur->registry = cp;
  595.     NEXT(cp);        /* character class */
  596.  
  597.     /*
  598.     **  Check to make sure that this is a unique font
  599.     **   from the rest of the set.
  600.      */
  601.     for (j = 0; j < count; j++) {
  602.         if (strcmp(cur->fontFamily, n[j].fontFamily) == 0 &&
  603.         strcmp(cur->weight, n[j].weight) == 0 &&
  604.         strcmp(cur->slant, n[j].slant) == 0 &&
  605.         strcmp(cur->setWidth, n[j].setWidth) == 0 &&
  606.         strcmp(cur->points, n[j].points) == 0 &&
  607.         strcmp(cur->spacing, n[j].spacing) == 0)
  608.         break;
  609.     }
  610.     makeShortName(cur->weight, cur->slant, cur->setWidth, "");
  611.     makeShortFamily(cur->fontFamily, cur->foundry, cur->registry);
  612.     if (j != count)
  613.         continue;
  614.     if (atoi(cur->points) == 0)
  615.         haveScalable = True;
  616.     count++;
  617.     }
  618. #undef NEXT
  619.  
  620.     *number = count;
  621.     return n;
  622. }
  623.  
  624.  
  625. static void 
  626. applySetCallback(Widget paint, Arg * xarg)
  627. {
  628.     XtSetValues(paint, xarg, 1);
  629.     FontChanged(paint);
  630. }
  631. static void 
  632. applyCallback(Widget w, XtPointer argArg, XtPointer junk)
  633. {
  634.     arg_t *arg = (arg_t *) argArg;
  635.     XFontStruct *info;
  636.     Arg xarg;
  637.  
  638.     XtVaGetValues(arg->text, XtNfont, &info, NULL);
  639.  
  640.     XtSetArg(xarg, XtNfont, info);
  641.     OperationAddArg(xarg);
  642.     GraphicAll((GraphicAllProc) applySetCallback, (void *) &xarg);
  643. }
  644. static void 
  645. closeCallback(Widget w, XtPointer argArg, XtPointer junk)
  646. {
  647.     arg_t *arg = (arg_t *) argArg;
  648.  
  649.     XtPopdown(GetShell(arg->family));
  650. }
  651. static void 
  652. okCallback(Widget w, XtPointer argArg, XtPointer junk)
  653. {
  654.     applyCallback(w, argArg, junk);
  655.     closeCallback(w, argArg, junk);
  656. }
  657. static void 
  658. listCallback(Widget w, XtPointer argArg, XtPointer junk)
  659. {
  660.     arg_t *arg = (arg_t *) argArg;
  661.     arg->expectFlag = True;
  662.     arg->expect = None;
  663.     match(arg);
  664. }
  665. static void 
  666. expectCallback(Widget w, XtPointer argArg, XEvent * event, Boolean * junk)
  667. {
  668.     arg_t *arg = (arg_t *) argArg;
  669.  
  670.     if (event->type == ButtonRelease) {
  671.     if (arg->expect != None)
  672.         match(arg);
  673.     arg->expect = None;
  674.     arg->expectFlag = False;
  675.     } else if (arg->expectFlag == False) {
  676.     arg->expect = w;
  677.     }
  678. }
  679. static void 
  680. pointSizeAction(Widget w, XEvent * event, String * prms, Cardinal * nprms)
  681. {
  682.     /* XXX */
  683.     if (theArg == NULL)
  684.     return;
  685.  
  686.     if (!XtIsManaged(theArg->pointSelect))
  687.     return;
  688.     match(theArg);
  689. }
  690.  
  691. void 
  692. FontSelect(Widget w, Widget paint)
  693. {
  694.     static XtActionsRec pointAct =
  695.     {"point-size-ok", (XtActionProc) pointSizeAction};
  696.     static Widget shell = None;
  697.     Widget pane, form, selectLabel, form2;
  698.     Widget applyButton, okButton, doneButton, vport, label;
  699.     arg_t *arg = XtNew(arg_t);
  700.  
  701.     if (shell != None) {
  702.     XtPopup(shell, XtGrabNone);
  703.     XMapRaised(XtDisplay(shell), XtWindow(shell));
  704.     return;
  705.     }
  706.     StateSetBusyWatch(True);
  707.  
  708.     shell = XtVaCreatePopupShell("fontSelect",
  709.                  topLevelShellWidgetClass, GetToplevel(w),
  710.                  NULL);
  711.  
  712.     pane = XtVaCreateManagedWidget("pane",
  713.                    panedWidgetClass, shell,
  714.                    XtNborderWidth, 0,
  715.                    NULL);
  716.  
  717.     label = XtVaCreateManagedWidget("title",
  718.                     labelWidgetClass, pane,
  719.              XtNlabel, "Select the font properties you wish",
  720.                     XtNborderWidth, 0,
  721.                     XtNshowGrip, False,
  722.                     NULL);
  723.  
  724.     form = XtVaCreateManagedWidget("form",
  725.                    formWidgetClass, pane,
  726.                    XtNborderWidth, 0,
  727.                    NULL);
  728.  
  729.     /*
  730.     **    lists of items to select
  731.      */
  732.     label = XtVaCreateManagedWidget("spacingLabel",
  733.                     labelWidgetClass, form,
  734.                     XtNborderWidth, 0,
  735.                     XtNtop, XtChainTop,
  736.                     XtNbottom, XtChainTop,
  737.                     NULL);
  738.     vport = XtVaCreateManagedWidget("vport",
  739.                     viewportWidgetClass, form,
  740.                     XtNuseBottom, True,
  741.                     XtNuseRight, True,
  742.                     XtNforceBars, True,
  743.                     XtNallowHoriz, False,
  744.                     XtNallowVert, True,
  745.                     XtNfromVert, label,
  746.                     XtNtop, XtChainTop,
  747.                     NULL);
  748.     arg->spacing = XtVaCreateManagedWidget("spacing",
  749.                        listWidgetClass, vport,
  750.                        XtNverticalList, True,
  751.                        XtNforceColumns, True,
  752.                        XtNdefaultColumns, 1,
  753.                        XtNnumberStrings, 0,
  754.                        NULL);
  755.     label = XtVaCreateManagedWidget("familyLabel",
  756.                     labelWidgetClass, form,
  757.                     XtNborderWidth, 0,
  758.                     XtNfromHoriz, vport,
  759.                     XtNtop, XtChainTop,
  760.                     XtNbottom, XtChainTop,
  761.                     NULL);
  762.     vport = XtVaCreateManagedWidget("vport",
  763.                     viewportWidgetClass, form,
  764.                     XtNuseBottom, True,
  765.                     XtNuseRight, True,
  766.                     XtNforceBars, True,
  767.                     XtNallowHoriz, False,
  768.                     XtNallowVert, True,
  769.                     XtNfromVert, label,
  770.                     XtNfromHoriz, vport,
  771.                     XtNtop, XtChainTop,
  772.                     NULL);
  773.     arg->family = XtVaCreateManagedWidget("font",
  774.                       listWidgetClass, vport,
  775.                       XtNverticalList, True,
  776.                       XtNforceColumns, True,
  777.                       XtNdefaultColumns, 1,
  778.                       XtNnumberStrings, 0,
  779.                       NULL);
  780.     label = XtVaCreateManagedWidget("weightLabel",
  781.                     labelWidgetClass, form,
  782.                     XtNborderWidth, 0,
  783.                     XtNfromHoriz, vport,
  784.                     XtNtop, XtChainTop,
  785.                     XtNbottom, XtChainTop,
  786.                     NULL);
  787.     vport = XtVaCreateManagedWidget("vport",
  788.                     viewportWidgetClass, form,
  789.                     XtNuseBottom, True,
  790.                     XtNuseRight, True,
  791.                     XtNforceBars, True,
  792.                     XtNallowHoriz, False,
  793.                     XtNallowVert, True,
  794.                     XtNfromHoriz, vport,
  795.                     XtNfromVert, label,
  796.                     XtNtop, XtChainTop,
  797.                     NULL);
  798.     arg->weight = XtVaCreateManagedWidget("weight",
  799.                       listWidgetClass, vport,
  800.                       XtNverticalList, True,
  801.                       XtNforceColumns, True,
  802.                       XtNdefaultColumns, 1,
  803.                       XtNnumberStrings, 0,
  804.                       NULL);
  805.     label = XtVaCreateManagedWidget("pointLabel",
  806.                     labelWidgetClass, form,
  807.                     XtNborderWidth, 0,
  808.                     XtNfromHoriz, vport,
  809.                     XtNtop, XtChainTop,
  810.                     XtNbottom, XtChainTop,
  811.                     NULL);
  812.     vport = XtVaCreateManagedWidget("vport",
  813.                     viewportWidgetClass, form,
  814.                     XtNuseBottom, True,
  815.                     XtNuseRight, True,
  816.                     XtNforceBars, True,
  817.                     XtNallowHoriz, False,
  818.                     XtNallowVert, True,
  819.                     XtNfromHoriz, vport,
  820.                     XtNfromVert, label,
  821.                     XtNtop, XtChainTop,
  822.                     NULL);
  823.     arg->point = XtVaCreateManagedWidget("point",
  824.                      listWidgetClass, vport,
  825.                      XtNverticalList, True,
  826.                      XtNforceColumns, True,
  827.                      XtNdefaultColumns, 1,
  828.                      XtNnumberStrings, 0,
  829.                      NULL);
  830.  
  831.     /*
  832.     **    The text area and buttons
  833.      */
  834.     form = XtVaCreateManagedWidget("form2",
  835.                    formWidgetClass, pane,
  836.                    XtNborderWidth, 0,
  837.                    NULL);
  838.     form2 = XtVaCreateManagedWidget("subForm",
  839.                     formWidgetClass, form,
  840.                     XtNborderWidth, 0,
  841.                     XtNtop, XtChainTop,
  842.                     XtNbottom, XtChainTop,
  843.                     NULL);
  844.  
  845.     selectLabel = XtVaCreateWidget("pointLabel",
  846.                    labelWidgetClass, form2,
  847.                    XtNborderWidth, 0,
  848.                    XtNleft, XtChainLeft,
  849.                    XtNright, XtChainLeft,
  850.                    NULL);
  851.  
  852.     XtAppAddActions(XtWidgetToApplicationContext(form2), &pointAct, 1);
  853.  
  854.     arg->pointSelect = XtVaCreateWidget("pointSelect",
  855.                     asciiTextWidgetClass, form2,
  856.                     XtNleft, XtChainLeft,
  857.                     XtNright, XtChainRight,
  858.                     XtNfromHoriz, selectLabel,
  859.                     XtNeditType, XawtextEdit,
  860.                     XtNwrap, XawtextWrapNever,
  861.                     XtNlength, 8,
  862.                     XtNtranslations,
  863.                     XtParseTranslationTable("#override\n\
  864.                     <Key>Return: point-size-ok()\n\
  865.                     <Key>Linefeed: point-size-ok()\n\
  866.                     Ctrl<Key>M: point-size-ok()\n\
  867.                     Ctrl<Key>J: point-size-ok()\n"),
  868.                     NULL);
  869.  
  870.     label = XtVaCreateManagedWidget("fontNameLabel",
  871.                     labelWidgetClass, form,
  872.                     XtNborderWidth, 0,
  873.                     XtNfromVert, form2,
  874.                     XtNleft, XtChainLeft,
  875.                     XtNtop, XtChainTop,
  876.                     XtNbottom, XtChainTop,
  877.                     NULL);
  878.     arg->fontName = XtVaCreateManagedWidget("fontName",
  879.                         asciiTextWidgetClass, form,
  880.                         XtNfromVert, form2,
  881.                         XtNfromHoriz, label,
  882.                         XtNallowResize, True,
  883.                         XtNstring, "",
  884.                         XtNtop, XtChainTop,
  885.                         XtNbottom, XtChainTop,
  886.                         XtNdisplayCaret, False,
  887.                         NULL);
  888.  
  889.     arg->text = XtVaCreateManagedWidget("text",
  890.                     asciiTextWidgetClass, form,
  891.                     XtNfromVert, arg->fontName,
  892.                     XtNallowResize, True,
  893.                     XtNstring, "",
  894.                     XtNtop, XtChainTop,
  895.                     XtNbottom, XtChainBottom,
  896.                     XtNdisplayCaret, False,
  897.                     NULL);
  898.  
  899.     okButton = XtVaCreateManagedWidget("ok",
  900.                        commandWidgetClass, form,
  901.                        XtNfromVert, arg->text,
  902.                        XtNtop, XtChainBottom,
  903.                        XtNbottom, XtChainBottom,
  904.                        XtNright, XtChainLeft,
  905.                        XtNleft, XtChainLeft,
  906.                        NULL);
  907.     applyButton = XtVaCreateManagedWidget("apply",
  908.                       commandWidgetClass, form,
  909.                       XtNfromVert, arg->text,
  910.                       XtNfromHoriz, okButton,
  911.                       XtNtop, XtChainBottom,
  912.                       XtNbottom, XtChainBottom,
  913.                       XtNright, XtChainLeft,
  914.                       XtNleft, XtChainLeft,
  915.                       NULL);
  916.  
  917.     doneButton = XtVaCreateManagedWidget("done",
  918.                      commandWidgetClass, form,
  919.                      XtNfromVert, arg->text,
  920.                      XtNfromHoriz, applyButton,
  921.                      XtNtop, XtChainBottom,
  922.                      XtNbottom, XtChainBottom,
  923.                      XtNleft, XtChainLeft,
  924.                      XtNright, XtChainLeft,
  925.                      XtNleft, XtChainLeft,
  926.                      NULL);
  927.  
  928.     /*
  929.     **    Init the world
  930.      */
  931.     arg->paint = paint;
  932.     arg->namesStorage = XListFonts(XtDisplay(shell), "*", 32767, &arg->number),
  933.     arg->names = chop(&arg->number, arg->namesStorage);
  934.     arg->expectFlag = False;
  935.     match(arg);
  936.  
  937.     if (haveScalable) {
  938.     Widget list[2];
  939.     list[0] = selectLabel;
  940.     list[1] = arg->pointSelect;
  941.     XtManageChildren(list, 2);
  942.     } else {
  943.     XtVaSetValues(form2, XtNwidth, 1, XtNheight, 1, NULL);
  944.     }
  945.  
  946.     XtAddEventHandler(arg->spacing, ButtonPressMask | ButtonReleaseMask,
  947.               False, expectCallback, (XtPointer) arg);
  948.     XtAddEventHandler(arg->family, ButtonPressMask | ButtonReleaseMask,
  949.               False, expectCallback, (XtPointer) arg);
  950.     XtAddEventHandler(arg->weight, ButtonPressMask | ButtonReleaseMask,
  951.               False, expectCallback, (XtPointer) arg);
  952.     XtAddEventHandler(arg->point, ButtonPressMask | ButtonReleaseMask,
  953.               False, expectCallback, (XtPointer) arg);
  954.  
  955.     XtAddCallback(arg->spacing, XtNcallback, listCallback, (XtPointer) arg);
  956.     XtAddCallback(arg->family, XtNcallback, listCallback, (XtPointer) arg);
  957.     XtAddCallback(arg->weight, XtNcallback, listCallback, (XtPointer) arg);
  958.     XtAddCallback(arg->point, XtNcallback, listCallback, (XtPointer) arg);
  959.  
  960.     XtAddCallback(okButton, XtNcallback, okCallback, (XtPointer) arg);
  961.     XtAddCallback(applyButton, XtNcallback, applyCallback, (XtPointer) arg);
  962.     XtAddCallback(doneButton, XtNcallback, closeCallback, (XtPointer) arg);
  963.     AddDestroyCallback(shell, (DestroyCallbackFunc) closeCallback, arg);
  964.  
  965.     XtPopup(shell, XtGrabNone);
  966.     StateSetBusyWatch(False);
  967.  
  968.     theArg = arg;
  969. }
  970.