home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tkisrc04.zip / tk / os2 / tkOS2Font.c < prev    next >
C/C++ Source or Header  |  1998-08-07  |  61KB  |  1,761 lines

  1. /* 
  2.  * tkOS2Font.c --
  3.  *
  4.  *    This file contains the Xlib emulation routines relating to
  5.  *    creating and manipulating fonts.
  6.  *
  7.  * Copyright (c) 1996-1997 Illya Vaes
  8.  * Copyright (c) 1995 Sun Microsystems, Inc.
  9.  * Copyright (c) 1994 Software Research Associates, Inc. 
  10.  *
  11.  * See the file "license.terms" for information on usage and redistribution
  12.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  13.  */
  14.  
  15.  
  16. #include "tkOS2Int.h"
  17.  
  18. /*
  19.  * Forward declarations for functions used in this file.
  20.  */
  21. static int        NameToFont (_Xconst char *name, TkOS2Font *logfont);
  22. static int        XNameToFont (_Xconst char *name, TkOS2Font *logfont);
  23.  
  24. /*
  25.  * Code pages used in this file, 1004 is Windows compatible, 65400 must be
  26.  * used if the font contains special glyphs, ie. Symbol.
  27.  */
  28.  
  29. #define CP_LATIN1 850L
  30. #define CP_1004   1004L
  31. #define CP_65400  65400L
  32.  
  33. #ifdef IGNOREPMRES
  34.     /*
  35.      * Shrink 120 to 96 to facilitate 'better' sizing for those displays
  36.      * which report a resolution of 120dpi but have actual resolution close
  37.      * to 96dpi (VGA upto ?800x600?).
  38.      * This is obviously dependent on both resolution and screen size,
  39.      * as higher resolutions usually use 120dpi fonts, regardless of any
  40.      * screen size.
  41.      */
  42.     #define PIXTOPOINT(pixels) ( \
  43.         (aDevCaps[CAPS_VERTICAL_FONT_RES] == 120) \
  44.         ? (((pixels) * 72) / 96) \
  45.         : (((pixels) * 72) / aDevCaps[CAPS_VERTICAL_FONT_RES]) \
  46.     )
  47.     #define POINTTOPIX(points) ( \
  48.         (aDevCaps[CAPS_VERTICAL_FONT_RES] == 120) \
  49.         ? (((points) * 96) / 72) \
  50.         : (((points) * aDevCaps[CAPS_VERTICAL_FONT_RES]) / 72) \
  51.     )
  52.     #define PTOP(p) ( \
  53.         (aDevCaps[CAPS_VERTICAL_FONT_RES] == 120) \
  54.         ? (((p) * 96) / 120 ) \
  55.         : (p) \
  56.     )
  57. #else
  58.     #define PIXTOPOINT(pixels) \
  59.         (((pixels) * 72) / aDevCaps[CAPS_VERTICAL_FONT_RES])
  60.     #define POINTTOPIX(points) \
  61.         (((points) * aDevCaps[CAPS_VERTICAL_FONT_RES]) / 72)
  62.     #define PTOP(p)  (p)
  63. #endif
  64.  
  65.  
  66. /*
  67.  *----------------------------------------------------------------------
  68.  *
  69.  * NameToFont --
  70.  *
  71.  *    Converts into a logical font description:
  72.  *       - a three part font name of the form:
  73.  *        "Family point_size style_list"
  74.  *         Style_list contains a list of one or more attributes:
  75.  *        normal, bold, italic, underline, strikeout
  76.  *         Point size in decipoints.
  77.  *
  78.  * Results:
  79.  *    Returns false if the font name was syntactically invalid,
  80.  *    else true.  Sets the fields of the passed in TkOS2Font.
  81.  *
  82.  * Side effects:
  83.  *    None.
  84.  *
  85.  *----------------------------------------------------------------------
  86.  */
  87.  
  88. static int
  89. NameToFont(name, logfont)
  90.     _Xconst char *name;
  91.     TkOS2Font *logfont;
  92. {
  93.     int argc, argc2;
  94.     char **argv, **argv2;
  95.     int nameLen, i, pointSize = 0;
  96.     Tcl_Interp *dummy = Tcl_CreateInterp();
  97.  
  98. #ifdef DEBUG
  99.     printf("NameToFont %s\n", name);
  100. #endif
  101.  
  102.     if (Tcl_SplitList(dummy, (char *) name, &argc, &argv) != TCL_OK) {
  103. #ifdef DEBUG
  104.     printf("    Tcl_SplitList failed\n");
  105. #endif
  106.     goto nomatch;
  107.     }
  108.     if (argc != 3) {
  109. #ifdef DEBUG
  110.         printf("    not 3 args\n");
  111.         for (i=0;i<argc;i++) { printf("    arg[%d]=[%s]\n", i, argv[i]);}
  112. #endif
  113.     ckfree((char *) argv);
  114.     goto nomatch;
  115.     }
  116.  
  117.     /*
  118.      * Determine the font family name.
  119.      */
  120.  
  121.     nameLen = strlen(argv[0]);
  122.     if (nameLen > FACESIZE) {
  123.     nameLen = FACESIZE;
  124.     }
  125.     strncpy(logfont->fattrs.szFacename, argv[0], nameLen);
  126. #ifdef DEBUG
  127.     printf("    copied [%s] -> [%s] (%d)\n", argv[0],
  128.            logfont->fattrs.szFacename, nameLen);
  129. #endif
  130.  
  131.     /*
  132.      * Check the character set.
  133.      */
  134.  
  135.     logfont->fattrs.usCodePage = 0;
  136.     if (stricmp(logfont->fattrs.szFacename, "Symbol") == 0) {
  137.     logfont->fattrs.usCodePage = CP_65400;
  138.     } else if (stricmp(logfont->fattrs.szFacename, "Symbol Set") == 0) {
  139.     logfont->fattrs.usCodePage = CP_65400;
  140.     } else if (stricmp(logfont->fattrs.szFacename, "WingDings") == 0) {
  141.     logfont->fattrs.usCodePage = CP_65400;
  142.     } else if (stricmp(logfont->fattrs.szFacename, "ZapfDingbats") == 0) {
  143.     logfont->fattrs.usCodePage = CP_65400;
  144.     } else if (stricmp(logfont->fattrs.szFacename, "StarBats") == 0) {
  145.     logfont->fattrs.usCodePage = CP_65400;
  146.     }
  147.     
  148.     /*
  149.      * Determine the font size.
  150.      */
  151.  
  152.     if (Tcl_GetInt(dummy, argv[1], &pointSize) != TCL_OK) {
  153.     ckfree((char *) argv);
  154.     goto nomatch;
  155.     }
  156.     logfont->fattrs.lMaxBaselineExt = POINTTOPIX(pointSize);
  157.     logfont->deciPoints = pointSize;
  158. #ifdef DEBUG
  159.     printf("    pointSize %d, lMBE %d, deciPoints %d\n", pointSize,
  160.            logfont->fattrs.lMaxBaselineExt, logfont->deciPoints);
  161. #endif
  162.  
  163.     /*
  164.      * Apply any style modifiers.
  165.      */
  166.     
  167.     if (Tcl_SplitList(dummy, (char *) argv[2], &argc2, &argv2) != TCL_OK) {
  168.     ckfree((char*) argv);
  169.     goto nomatch;
  170.     }
  171.     for (i = 0; i < argc2; i++) {
  172.     if (stricmp(argv2[i], "bold") == 0) {
  173.         logfont->fattrs.fsSelection |= FATTR_SEL_BOLD;
  174.     } else if (stricmp(argv2[i], "heavy") == 0) {
  175.         logfont->fattrs.fsSelection |= FATTR_SEL_BOLD;
  176.     } else if (stricmp(argv2[i], "semibold") == 0) {
  177.         logfont->fattrs.fsSelection |= FATTR_SEL_BOLD;
  178.     } else if (stricmp(argv2[i], "extrabold") == 0) {
  179.         logfont->fattrs.fsSelection |= FATTR_SEL_BOLD;
  180.     } else if (stricmp(argv2[i], "italic") == 0) {
  181.         logfont->fattrs.fsSelection |= FATTR_SEL_ITALIC;
  182.     } else if (stricmp(argv2[i], "oblique") == 0) {
  183.         logfont->fattrs.fsSelection |= FATTR_SEL_ITALIC;
  184.     } else if (stricmp(argv2[i], "underline") == 0) {
  185.         logfont->fattrs.fsSelection |= FATTR_SEL_UNDERSCORE;
  186.     } else if (stricmp(argv2[i], "strikeout") == 0) {
  187.         logfont->fattrs.fsSelection |= FATTR_SEL_STRIKEOUT;
  188.     } else {
  189.         /* ignore for now */
  190.     }
  191.     }
  192.  
  193.     ckfree((char *) argv);
  194.     ckfree((char *) argv2);
  195.     return True;
  196.  
  197.     nomatch:
  198. #ifdef DEBUG
  199.     printf("NameToFont: nomatch\n");
  200. #endif
  201.     Tcl_DeleteInterp(dummy);
  202.     return False;
  203. }
  204.  
  205. /*
  206.  *----------------------------------------------------------------------
  207.  *
  208.  * XNameToFont --
  209.  *
  210.  *    This function constructs a logical font description from an
  211.  *    X font name.  This code only handles font names with all 13
  212.  *    parts, although a part can be '*'.
  213.  *
  214.  * Results:
  215.  *    Returns false if the font name was syntactically invalid,
  216.  *    else true.  Sets the fields of the passed in TkOS2Font.
  217.  *
  218.  * Side effects:
  219.  *    None.
  220.  *
  221.  *----------------------------------------------------------------------
  222.  */
  223.  
  224. static int
  225. XNameToFont(name, logfont)
  226.     _Xconst char *name;
  227.     TkOS2Font *logfont;
  228. {
  229.     const char *head, *tail;
  230.     const char *field[13];
  231.     int flen[13];
  232.     int i, len, togo = 0;
  233.  
  234. #ifdef DEBUG
  235.     printf("XNameToFont %s\n", name);
  236. #endif
  237.  
  238.     /*
  239.      * Valid font name patterns must have a leading '-' or '*'.
  240.      */
  241.  
  242.     head = tail = name;
  243.     if (*tail == '-') {
  244.     head++; tail++;
  245.     } else if (*tail != '*') {
  246. #ifdef DEBUG
  247.     printf("    no tail\n");
  248. #endif
  249.     return FALSE;
  250.     }
  251.  
  252.     /*
  253.      * Identify field boundaries.  Stores a pointer to the beginning
  254.      * of each field in field[i], and the length of the field in flen[i].
  255.      * Fields are separated by dashes.  Each '*' becomes a field by itself.
  256.      */
  257.  
  258.     i = 0;
  259.     while (*tail != '\0' && i < 12) {
  260.     if (*tail == '-') {
  261.         flen[i] = tail - head;
  262.         field[i] = head;
  263.         tail++;
  264.         head = tail;
  265.         i++;
  266.     } else if (*tail == '*') {
  267.         len = tail - head;
  268.         if (len > 0) {
  269.         flen[i] = tail - head;
  270.         field[i] = head;
  271.         } else {
  272.         flen[i] = 1;
  273.         field[i] = head;
  274.         tail++;
  275.         if (*tail == '-') {
  276.             tail++;
  277.         }
  278.         }
  279.         head = tail;
  280.         i++;
  281.     } else {
  282.         tail++;
  283.     }
  284.     }
  285.  
  286.     /*
  287.      * We handle the last field as a special case, since it may contain
  288.      * an embedded hyphen.
  289.      */
  290.  
  291.     flen[i] = strlen(head);
  292.     field[i] = head;
  293.  
  294.     /*
  295.      * Bail if we don't have at least a font and size.
  296.      */
  297.  
  298.     if (i < 8) {
  299. #ifdef DEBUG
  300.         printf("    not enough fields (just %d)\n", i);
  301. #endif
  302.     return FALSE;
  303.     } 
  304.  
  305. togo=i;
  306.     /*
  307.      * Now fill in the logical font description from the fields we have
  308.      * identified.
  309.      */
  310.  
  311.     /*
  312.      * Field 1: Foundry.  Skip.
  313.      */
  314.     if (--togo <= 0) return TRUE;
  315.  
  316.     /*
  317.      * Field 2: Font Family.
  318.      */
  319.  
  320.     i = 1;
  321.     if (!(flen[i] == 0 ||
  322.       (flen[i] == 1 && (field[i][0] == '*' || field[i][0] == '?'))))
  323.     {
  324.     len = (flen[i] < FACESIZE) ? flen[i] : FACESIZE - 1;
  325.     strncpy(logfont->fattrs.szFacename, field[i], len);
  326. #ifdef DEBUG
  327.         printf("    copied [%s] -> [%s] (%d)\n", field[i],
  328.                logfont->fattrs.szFacename, len);
  329. #endif
  330.  
  331.     /*
  332.      * Need to handle Symbol fonts specially.
  333.      */
  334.  
  335.     if (stricmp(logfont->fattrs.szFacename, "Symbol") == 0) {
  336. #ifdef DEBUG
  337.             printf("    Symbol font-> codepage CP_65400\n");
  338. #endif
  339.         logfont->fattrs.usCodePage = CP_65400;
  340.         } else if (stricmp(logfont->fattrs.szFacename, "Symbol Set") == 0) {
  341. #ifdef DEBUG
  342.             printf("    Symbol Set font-> codepage CP_65400\n");
  343. #endif
  344.         logfont->fattrs.usCodePage = CP_65400;
  345.         } else if (stricmp(logfont->fattrs.szFacename, "WingDings") == 0) {
  346. #ifdef DEBUG
  347.             printf("    WingDings font-> codepage CP_65400\n");
  348. #endif
  349.         logfont->fattrs.usCodePage = CP_65400;
  350.         } else if (stricmp(logfont->fattrs.szFacename, "ZapfDingbats") == 0) {
  351. #ifdef DEBUG
  352.             printf("    ZapfDingbats font-> codepage CP_65400\n");
  353. #endif
  354.         logfont->fattrs.usCodePage = CP_65400;
  355.         } else if (stricmp(logfont->fattrs.szFacename, "StarBats") == 0) {
  356. #ifdef DEBUG
  357.             printf("    StarBats font-> codepage CP_65400\n");
  358. #endif
  359.         logfont->fattrs.usCodePage = CP_65400;
  360.     }
  361.     }
  362.     if (--togo <= 0) return TRUE;
  363.  
  364.     /*
  365.      * Field 3: Weight.  Default is medium.
  366.      */
  367.  
  368.     i = 2;
  369.     if ((flen[i] > 0) && (strnicmp(field[i], "bold", flen[i]) == 0)) {
  370. #ifdef DEBUG
  371.         printf("    bold -> FATTR_SEL_BOLD\n");
  372. #endif
  373.     logfont->fattrs.fsSelection |= FATTR_SEL_BOLD;
  374.     } else {
  375.     logfont->fattrs.fsSelection &= ~FATTR_SEL_BOLD;
  376.     }
  377.     if (--togo <= 0) return TRUE;
  378.         
  379.     /*
  380.      * Field 4: Slant.  Default is Roman.
  381.      */
  382.     
  383.     i = 3;
  384.     if (!(flen[i] == 0 ||
  385.       (flen[i] == 1 && (field[i][0] == '*' || field[i][0] == '?'))))
  386.     {
  387.     if (strnicmp(field[i], "r", flen[i]) == 0) {
  388.         /* Roman. */
  389.         logfont->fattrs.fsSelection &= ~FATTR_SEL_ITALIC;
  390.     } else if (strnicmp(field[i], "i", flen[i]) == 0) {
  391.         /* Italic */
  392. #ifdef DEBUG
  393.             printf("    italic -> FATTR_SEL_ITALIC\n");
  394. #endif
  395.         logfont->fattrs.fsSelection |= FATTR_SEL_ITALIC;
  396.     } else if (strnicmp(field[i], "o", flen[i]) == 0) {
  397. #ifdef DEBUG
  398.             printf("    oblique -> FATTR_SEL_ITALIC + slant 15deg\n");
  399. #endif
  400.         /* Oblique, set to 15 degree slant forward */
  401.         logfont->shear.x = 2588;    /* 10000*cos(75) */
  402.         logfont->shear.y = 9659;    /* 10000*sin(75) */
  403.         logfont->setShear = TRUE;
  404.         logfont->fattrs.fsFontUse |= FATTR_FONTUSE_TRANSFORMABLE;
  405.             logfont->fattrs.fsSelection |= FATTR_SEL_ITALIC;
  406.     } else if (strnicmp(field[i], "ri", flen[i]) == 0) {
  407. #ifdef DEBUG
  408.             printf("    reverse italic -> FATTR_SEL_ITALIC + slant -30deg\n");
  409. #endif
  410.         /* Reverse Italic, set to 30 degree slant backward */
  411.         logfont->shear.x = -5000;    /* 10000*cos(120) */
  412.         logfont->shear.y = 8660;    /* 10000*sin(120) */
  413.         logfont->setShear = TRUE;
  414.         logfont->fattrs.fsFontUse |= FATTR_FONTUSE_TRANSFORMABLE;
  415.             logfont->fattrs.fsSelection |= FATTR_SEL_ITALIC;
  416.     } else if (strnicmp(field[i], "ro", flen[i]) == 0) {
  417. #ifdef DEBUG
  418.             printf("    reverse oblique -> FATTR_SEL_ITALIC + slant -15deg\n");
  419. #endif
  420.         /* Reverse Oblique, set to 15 degree slant backward */
  421.         logfont->shear.x = -2588;    /* 10000*cos(105) */
  422.         logfont->shear.y = 9659;    /* 10000*sin(105) */
  423.         logfont->setShear = TRUE;
  424.         logfont->fattrs.fsFontUse |= FATTR_FONTUSE_TRANSFORMABLE;
  425.             logfont->fattrs.fsSelection |= FATTR_SEL_ITALIC;
  426.     } else if (strnicmp(field[i], "ot", flen[i]) == 0) {
  427.         /* Other */
  428.     } else {
  429. #ifdef DEBUG
  430.             printf("    Unknown slant\n");
  431. #endif
  432.         return FALSE;
  433.     }
  434.     }
  435.     if (--togo <= 0) return TRUE;
  436.  
  437.     /*
  438.      * Field 5 & 6: Set Width & Blank.  Skip.
  439.      */
  440.     if (--togo <= 0) return TRUE;
  441.  
  442.     /*
  443.      * Field 7: Pixels.  Use this as the points if no points set.
  444.      */
  445.     if (--togo <= 0) return TRUE;
  446.  
  447.     i = 6;
  448.     if (!(flen[i] == 0 ||
  449.       (flen[i] == 1 && (field[i][0] == '*' || field[i][0] == '?'))))
  450.     {
  451.         logfont->fattrs.lMaxBaselineExt = atoi(field[i]);
  452.         /* Points is  (pixels * 72) / FONT_RES ; Note: decipixels! */
  453.         logfont->deciPoints = PIXTOPOINT(logfont->fattrs.lMaxBaselineExt * 10);
  454.  
  455. #ifdef DEBUG
  456.         printf("    pixels %s, Vert.Font Res. %d, decipixels %d\n", field[i],
  457.                aDevCaps[CAPS_VERTICAL_FONT_RES], logfont->deciPoints);
  458.         printf("    lMaxBaselineExt (pixel size) %d\n",
  459.                logfont->fattrs.lMaxBaselineExt);
  460. #endif
  461.     }
  462.     if (--togo <= 0) return TRUE;
  463.  
  464.     /*
  465.      * Field 8: Points in tenths of a point.
  466.      */
  467.  
  468.     i = 7;
  469.     if (!(flen[i] == 0 ||
  470.       (flen[i] == 1 && (field[i][0] == '*' || field[i][0] == '?'))))
  471.     {
  472.         logfont->deciPoints = atoi(field[i]);
  473.         logfont->fattrs.lMaxBaselineExt = POINTTOPIX(logfont->deciPoints) / 10;
  474. #ifdef DEBUG
  475.         printf("    lMaxBaselineExt (point size) %d\n",
  476.                logfont->fattrs.lMaxBaselineExt);
  477. #endif
  478.     }
  479.     if (--togo <= 0) return TRUE;
  480.  
  481.     /*
  482.      * Field 9: Horizontal Resolution in DPI.  Skip.
  483.      * Field 10: Vertical Resolution in DPI.  Skip.
  484.      */
  485.     if (--togo <= 0) return TRUE;
  486.  
  487.     /*
  488.      * Field 11: Spacing.
  489.      * we can't request this via PM's TkOS2Font, so skip.
  490.      */
  491.     if (--togo <= 0) return TRUE;
  492.  
  493.     /*
  494.      * Field 12: Average Width.
  495.      * Width should be 0 for outline fonts.
  496.      */
  497.  
  498.     i = 11;
  499.     if (!(flen[i] == 0 ||
  500.          (flen[i] == 1 && (field[i][0] == '*' || field[i][0] == '?'))))
  501.     {
  502.         logfont->fattrs.lAveCharWidth = (atoi(field[i]) / 10);
  503. #ifdef DEBUG
  504.         printf("    lAveCharWidth (average width) %d\n",
  505.                logfont->fattrs.lAveCharWidth);
  506. #endif
  507.     }
  508.     if (--togo <= 0) return TRUE;
  509.  
  510.     /*
  511.      * Field 13: Character Set.  Skip.
  512.      */
  513.     if (--togo <= 0) return TRUE;
  514.  
  515.     return TRUE;
  516. }
  517.  
  518. /*
  519.  *----------------------------------------------------------------------
  520.  *
  521.  * XLoadFont --
  522.  *
  523.  *    Get the font handle for the specified font.
  524.  *    Also handles:
  525.  *       - a "Presentation Parameter"-style specification
  526.  *        "pointsize.fontname[.attr][.attr][.attr][.attr][.attr]"
  527.  *         Point size in points.
  528.  *         Each attr one of bold, italic, underline, strikeout, outline.
  529.  *
  530.  * Results:
  531.  *    Returns the font handle.
  532.  *
  533.  * Side effects:
  534.  *    None.
  535.  *
  536.  *----------------------------------------------------------------------
  537.  */
  538.  
  539. Font
  540. XLoadFont(display, name)
  541.     Display* display;
  542.     _Xconst char* name;
  543. {
  544.     LONG lFontID= nextLogicalFont;
  545.     LONG match = 0;
  546.     PFONTMETRICS os2fonts;
  547.     LONG reqFonts, remFonts;
  548.     BOOL found = FALSE;
  549.     /* Use nominal size unless given Presentation Parameter style spec. */
  550.     /*
  551.     BOOL useIntended = TRUE;
  552.     */
  553.     BOOL useIntended = FALSE;
  554.     LONG outline = -1;
  555.     LONG font = 0;
  556.     int i, error = 30000, best = -1;
  557.  
  558. #ifdef DEBUG
  559.     SIZEF charBox;
  560.     printf("XLoadFont %s\n", name);
  561. #endif
  562.     if (lFontID > MAX_LID) {
  563.         /* We can't simultaneously  use more than MAX_LID fonts */
  564.         return (Font) 0;
  565.     }
  566.  
  567. #ifdef DEBUG
  568.     /* Determine total number of fonts */
  569.     reqFonts = 0L;
  570.     remFonts = GpiQueryFonts(globalPS, QF_PUBLIC, NULL, &reqFonts,
  571.                              (LONG) sizeof(FONTMETRICS), NULL);
  572.     printf("    nr.of fonts: %d\n", remFonts);
  573.     /* Allocate space for the fonts */
  574.     os2fonts = (PFONTMETRICS) ckalloc(remFonts * sizeof(FONTMETRICS));
  575.     if (os2fonts == NULL) {
  576.         return (Font) 0;
  577.     }
  578.     /* Retrieve the fonts */
  579.     reqFonts = remFonts;
  580.     remFonts = GpiQueryFonts(globalPS, QF_PUBLIC, NULL, &reqFonts,
  581.                              (LONG) sizeof(FONTMETRICS), os2fonts);
  582.     printf("    got %d (%d remaining)\n", reqFonts, remFonts);
  583.     for (i=0; i<reqFonts; i++) {
  584.         printf("m%d, Em %d (nom %ddpt, lMBE %d), xR %d, yR %d, %s, %s, face[%s]%s, fam[%s]%s\n",
  585.               os2fonts[i].lMatch, os2fonts[i].lEmHeight, os2fonts[i].sNominalPointSize,
  586.               os2fonts[i].lMaxBaselineExt, os2fonts[i].sXDeviceRes,
  587.               os2fonts[i].sYDeviceRes,
  588.               (os2fonts[i].fsType & FM_TYPE_FIXED) ? "fix" : "prop",
  589.               (os2fonts[i].fsDefn & FM_DEFN_OUTLINE) ? "outl" : "bmp",
  590.               os2fonts[i].szFacename,
  591.               (os2fonts[i].fsType & FM_TYPE_FACETRUNC) ? " (trunc()" : "",
  592.               os2fonts[i].szFamilyname,
  593.               (os2fonts[i].fsType & FM_TYPE_FAMTRUNC) ? " (trunc()" : "");
  594.     }
  595.     ckfree((char *)os2fonts);
  596. #endif
  597.  
  598.     /* Set defaults in logfont */
  599.     logfonts[lFontID].fattrs.usRecordLength = (USHORT)sizeof(FATTRS);
  600.     logfonts[lFontID].fattrs.fsSelection = (USHORT)0;
  601.     logfonts[lFontID].fattrs.lMatch = 0L;
  602.     memset(logfonts[lFontID].fattrs.szFacename, '\0', FACESIZE);
  603.     logfonts[lFontID].fattrs.idRegistry = 0;    /* Unknown */
  604.     logfonts[lFontID].fattrs.usCodePage = 0;    /* Use present codepage */
  605.     logfonts[lFontID].fattrs.lMaxBaselineExt = 0L;    /* 0 for vector fonts */
  606.     logfonts[lFontID].fattrs.lAveCharWidth = 0L;    /* 0 for vector fonts */
  607.     logfonts[lFontID].fattrs.fsType = 0;
  608.     logfonts[lFontID].fattrs.fsFontUse = 0;
  609.     logfonts[lFontID].shear.x = 0;
  610.     logfonts[lFontID].shear.y = 1;    /* Upright characters by default */
  611.     /* Not necessary to set shear by default */
  612.     logfonts[lFontID].setShear = FALSE;
  613.     logfonts[lFontID].outline = FALSE;
  614.     logfonts[lFontID].deciPoints = 120;
  615.     logfonts[lFontID].fattrs.lMaxBaselineExt = 12;
  616.  
  617.     if (! (((name[0] == '-') || (name[0] == '*')) &&
  618.          XNameToFont(name, &logfonts[lFontID]))) {
  619.         if (!NameToFont(name, &logfonts[lFontID])) {
  620.             /* Our own (non-X) fonts, recognize Windows fontnames for
  621.              * compatibility of scripts.
  622.              */
  623.     
  624.             if ((stricmp(name, "system") == 0) ||    /* OS/2 and Windows font */
  625.                 (stricmp(name, "device") == 0)) {    /* Windows font */
  626.                 strncpy(logfonts[lFontID].fattrs.szFacename, "System VIO", 10);
  627.             } else if ((strnicmp(name, "systemmonospaced", 16) == 0) ||
  628.                        (strnicmp(name, "ansifixed", 9) == 0) ||    /* Windows font */
  629.                        (strnicmp(name, "systemfixed", 11) == 0) ||  /* Windows font */
  630.                        (strnicmp(name, "oemfixed", 8) == 0)) {    /* Windows font */
  631.                 strncpy(logfonts[lFontID].fattrs.szFacename, "System Monospaced", 17);
  632.             } else if ((strnicmp(name, "systemproportional", 18) == 0) ||
  633.                        (strnicmp(name, "ansi", 4) == 0)) {    /* Windows font */
  634.                 strncpy(logfonts[lFontID].fattrs.szFacename, "System Proportional", 19);
  635.             } else {
  636.                 /*
  637.                  * The following code suggested by Ilya Zakharevich.
  638.                  * Its use is to allow font selection "in OS/2-style", like
  639.                  * "10.Courier".
  640.                  * Ilya's way of supplying attributes of the font is against
  641.                  * the documented "pointSize.Fontname[.attr ...]" though,
  642.                  * because it gives attributes between the pointsize and the
  643.                  * name of the font.
  644.                  * I take the "official" stance and also supply the rest of the
  645.                  * font Presentation Parameters: underline, strikeout, outline.
  646.                  */
  647.                 int l, off = 0;
  648.  
  649. #ifdef DEBUG
  650.                 printf("    trying Presentation Parameters-notation font\n");
  651. #endif
  652.                 if (sscanf(name, "%d.%n", &l, &off) && off > 0) {
  653.                     int fields;
  654. #ifdef DEBUG
  655.                 printf("    d %d, n %d\n", l, off);
  656. #endif
  657.                     logfonts[lFontID].fattrs.lMaxBaselineExt = POINTTOPIX(l);
  658.                     logfonts[lFontID].deciPoints = l * 10;
  659.                     name += off;
  660.                     useIntended = TRUE;
  661.                     /* Get the fontname out */
  662.                     fields = sscanf(name, "%[^.]%n",
  663.                                    (char *)&logfonts[lFontID].fattrs.szFacename,
  664.                                    &off);
  665. #ifdef DEBUG
  666.                     printf("    sscanf returns %d, off %d\n", fields, off);
  667. #endif
  668.                     if (fields==1 && strlen(name)==off) {
  669.                         /* Fontname is last part */
  670.                         l = strlen(name);
  671.                         if (l > FACESIZE - 1) {
  672.                             l = FACESIZE - 1;
  673.                         }
  674.                         strncpy(logfonts[lFontID].fattrs.szFacename, name, l);
  675. #ifdef DEBUG
  676.                         printf("    font [%s] last part\n", name);
  677. #endif
  678.                     } else {
  679. #ifdef DEBUG
  680.                         printf("    decomposing [%s]\n", name);
  681. #endif
  682.                         /* There are attributes after the fontname */
  683.                         name += off;
  684.                         while (TRUE) {
  685.                             if (strnicmp(name, ".bold", 5) == 0) {
  686.                                 logfonts[lFontID].fattrs.fsSelection
  687.                                     |= FATTR_SEL_BOLD;
  688. #ifdef DEBUG
  689.                                 printf("    .bold -> FATTR_SEL_BOLD\n");
  690. #endif
  691.                                 name += 5;
  692.                             } else if (strnicmp(name, ".italic", 7) == 0) {
  693.                                 logfonts[lFontID].fattrs.fsSelection
  694.                                     |= FATTR_SEL_ITALIC;
  695. #ifdef DEBUG
  696.                                 printf("    .italic -> FATTR_SEL_ITALIC\n");
  697. #endif
  698.                                 name += 7;
  699.                             } else if (strnicmp(name, ".underline", 10) == 0) {
  700.                                 logfonts[lFontID].fattrs.fsSelection
  701.                                     |= FATTR_SEL_UNDERSCORE;
  702. #ifdef DEBUG
  703.                                 printf("    .underline -> FATTR_SEL_UNDERSCORE\n");
  704. #endif
  705.                                 name += 10;
  706.                             } else if (strnicmp(name, ".strikeout", 10) == 0) {
  707.                                 logfonts[lFontID].fattrs.fsSelection
  708.                                     |= FATTR_SEL_STRIKEOUT;
  709. #ifdef DEBUG
  710.                                 printf("    .strikeout -> FATTR_SEL_STRIKEOUT\n");
  711. #endif
  712.                                 name += 10;
  713.                             } else if (strnicmp(name, ".outline", 8) == 0) {
  714.                                 logfonts[lFontID].fattrs.fsSelection
  715.                                     |= FATTR_SEL_OUTLINE;
  716. #ifdef DEBUG
  717.                                 printf("    .outline -> FATTR_SEL_OUTLINE\n");
  718. #endif
  719.                                 name += 8;
  720.                             } else if (*name == '.') {
  721.                                 name++;
  722.                                 break;
  723.                             } else {
  724.                                 break;
  725.                             }
  726.                         }
  727.                     }
  728.                 } else {
  729.                     l = strlen(name);
  730.                     if (l > FACESIZE - 1) {
  731.                         l = FACESIZE - 1;
  732.                     }
  733.                     strncpy(logfonts[lFontID].fattrs.szFacename, name, l);
  734.                 }
  735.             }
  736. #ifdef DEBUG
  737.             printf("XLoadFont trying font [%s]\n",
  738.                    logfonts[lFontID].fattrs.szFacename);
  739. #endif
  740.         }
  741.     }
  742.     /* Name has now been filled in with a correct or sane value */
  743.     /* Determine number of fonts */
  744.     reqFonts = 0L;
  745.     remFonts = GpiQueryFonts(globalPS, QF_PUBLIC,
  746.                              logfonts[lFontID].fattrs.szFacename, &reqFonts,
  747.                              (LONG) sizeof(FONTMETRICS), NULL);
  748. #ifdef DEBUG
  749.     printf("    nr.of fonts: %d\n", remFonts);
  750. #endif
  751.     reqFonts = remFonts;
  752.     if (reqFonts) {
  753.         /* Allocate space for the fonts */
  754.         os2fonts = (PFONTMETRICS) ckalloc(remFonts * sizeof(FONTMETRICS));
  755.         if (os2fonts == NULL) {
  756.             return (Font) 0;
  757.         }
  758.         /* Get the fonts that apply */
  759.         remFonts = GpiQueryFonts(globalPS, QF_PUBLIC,
  760.                                  logfonts[lFontID].fattrs.szFacename, &reqFonts,
  761.                                  (LONG) sizeof(FONTMETRICS), os2fonts);
  762. #ifdef DEBUG
  763.         if (remFonts == GPI_ALTERROR) {
  764.             printf("    GpiQueryFonts %s ERROR %x\n", logfonts[lFontID].fattrs.szFacename,
  765.             WinGetLastError(hab));
  766.         } else {
  767.             printf("    nr.of fonts [%s]: %d (%d remaining)\n",
  768.                    logfonts[lFontID].fattrs.szFacename, reqFonts, remFonts);
  769.         }
  770. #endif
  771.     } else {
  772.         os2fonts = NULL;
  773.     }
  774.     /*
  775.      * Determine the one that has the right size, preferring a bitmap font over
  776.      * a scalable (outline) one if it exists.
  777.      */
  778.     for (i=0; i<reqFonts && !found; i++) {
  779.         /*
  780.          * Note: scalable fonts appear to always return lEmHeight 16, so first
  781.          * check for outline, then "point size" to not match on size 16.
  782.          */
  783. #ifdef DEBUG
  784.         printf("    trying %s font %s (%ddp, lMaxBaselineExt %d), match %d\n",
  785.                (os2fonts[i].fsDefn & FM_DEFN_OUTLINE) ? "outline" : "fixed",
  786.                os2fonts[i].szFacename, os2fonts[i].sNominalPointSize,
  787.                os2fonts[i].lMaxBaselineExt, os2fonts[i].lMatch);
  788. #endif
  789.         if (os2fonts[i].fsDefn & FM_DEFN_OUTLINE) {
  790.             /* Remember we found an outline font */
  791.             outline = i;
  792. #ifdef DEBUG
  793.             printf("    found outline font %s, match %d\n",
  794.                    os2fonts[i].szFacename, os2fonts[i].lMatch);
  795. #endif
  796.         } else {
  797.             /* Bitmap font, check size, type, resolution */
  798.             int cerror = 0, err1;
  799.  
  800.             /*
  801.              * Note: FONTMETRICS.fsSelection can contain FM_SEL_ISO9241_TESTED,
  802.              * FATTRS.fsSelection cannot.
  803.              */
  804. #ifdef DEBUG
  805.         printf("m%d, Em %d (nom %ddpt, lMBE %d), xR %d, yR %d, %s, %s, face[%s]%s, fam[%s]%s\n",
  806.               os2fonts[i].lMatch, os2fonts[i].lEmHeight, os2fonts[i].sNominalPointSize,
  807.               os2fonts[i].lMaxBaselineExt, os2fonts[i].sXDeviceRes,
  808.               os2fonts[i].sYDeviceRes,
  809.               (os2fonts[i].fsType & FM_TYPE_FIXED) ? "fix" : "prop",
  810.               (os2fonts[i].fsDefn & FM_DEFN_OUTLINE) ? "outl" : "bmp",
  811.               os2fonts[i].szFacename,
  812.               (os2fonts[i].fsType & FM_TYPE_FACETRUNC) ? " (trunc()" : "",
  813.               os2fonts[i].szFamilyname,
  814.               (os2fonts[i].fsType & FM_TYPE_FAMTRUNC) ? " (trunc()" : "");
  815. #endif
  816. /*
  817.             if (
  818.                 ((useIntended ? os2fonts[i].sNominalPointSize :
  819.                                 (os2fonts[i].lMaxBaselineExt * 10)) ==
  820.                        logfonts[lFontID].fattrs.lMaxBaselineExt * 10)
  821. */
  822.             /* If we need a transformable font, we *need* an outline */
  823. /*
  824.                 &&
  825.         (!(logfonts[lFontID].fattrs.fsFontUse & FATTR_FONTUSE_TRANSFORMABLE))
  826.                 &&
  827.                 (os2fonts[i].sXDeviceRes == aDevCaps[CAPS_HORIZONTAL_FONT_RES])
  828.                 &&
  829.                 (os2fonts[i].sYDeviceRes == aDevCaps[CAPS_VERTICAL_FONT_RES])
  830.                 ) {
  831.                 found = TRUE;
  832.                 match = os2fonts[i].lMatch;
  833.                 font = i;
  834. */
  835. #ifdef DEBUG
  836.             printf("useInt %d, os2f.sNom %d, os2f.lMBE %d, logf.lMBE %d\n",
  837.               useIntended, os2fonts[i].sNominalPointSize,
  838.               os2fonts[i].lMaxBaselineExt * 10,
  839.               logfonts[lFontID].fattrs.lMaxBaselineExt * 10);
  840. #endif
  841. /*
  842.             err1 = ( useIntended ? os2fonts[i].sNominalPointSize
  843.                                  : (os2fonts[i].lMaxBaselineExt * 10))
  844.                      - logfonts[lFontID].fattrs.lMaxBaselineExt * 10;
  845. */
  846.             err1 = ( (os2fonts[i].lEmHeight * 10) 
  847.                      - logfonts[lFontID].fattrs.lMaxBaselineExt * 10 );
  848.             if (err1 < 0) {
  849.                 err1 = -err1;
  850.             }
  851.             cerror = err1;
  852.             if (logfonts[lFontID].fattrs.lAveCharWidth) {
  853.                 err1 = logfonts[lFontID].fattrs.lAveCharWidth
  854.                        - os2fonts[i].lAveCharWidth;
  855.                 if (err1 < 0) {
  856.                     err1 = -err1;
  857.                 }
  858.                 cerror += err1 * 3;    /* 10/3 times cheaper */
  859.             }
  860.             if (os2fonts[i].sXDeviceRes != aDevCaps[CAPS_HORIZONTAL_FONT_RES] ||
  861.                 os2fonts[i].sYDeviceRes != aDevCaps[CAPS_VERTICAL_FONT_RES]) {
  862.                 cerror += 1;
  863.             }
  864.             if (cerror < error) {
  865.                 error = cerror;
  866.                 best = i;
  867.             }
  868.             if (cerror == 0) {
  869.                 found = TRUE;
  870.                 font = best;
  871.                 match = os2fonts[best].lMatch;
  872.             }
  873. #ifdef DEBUG
  874.             if (found) printf("    found bitmap font %s, match %d (size %d)\n",
  875.                    os2fonts[i].szFacename, os2fonts[i].lMatch,
  876.                    os2fonts[i].sNominalPointSize);
  877. /*
  878.             } else { if (os2fonts[i].sNominalPointSize !=
  879.                     logfonts[lFontID].fattrs.lMaxBaselineExt * 10) {
  880.             if (os2fonts[i].sNominalPointSize !=
  881.                 logfonts[lFontID].fattrs.lMaxBaselineExt * 10) {
  882.                 printf("    height %d doesn't match required %d\n",
  883.                        os2fonts[i].sNominalPointSize,
  884.                        logfonts[lFontID].fattrs.lMaxBaselineExt * 10);
  885. */
  886.             if (os2fonts[i].lEmHeight !=
  887.                 logfonts[lFontID].fattrs.lMaxBaselineExt) {
  888.                 printf("    height %d doesn't match required %d\n",
  889.                        os2fonts[i].lEmHeight,
  890.                        logfonts[lFontID].fattrs.lMaxBaselineExt);
  891.             } else if (os2fonts[i].sXDeviceRes !=
  892.                 aDevCaps[CAPS_HORIZONTAL_FONT_RES]) {
  893.                 printf("    hor. device res %d doesn't match required %d\n",
  894.                        os2fonts[i].sXDeviceRes,
  895.                        aDevCaps[CAPS_HORIZONTAL_FONT_RES]);
  896.             } else if (os2fonts[i].sYDeviceRes !=
  897.                 aDevCaps[CAPS_VERTICAL_FONT_RES]) {
  898.                 printf("    vert. device res %d doesn't match required %d\n",
  899.                        os2fonts[i].sYDeviceRes,
  900.                        aDevCaps[CAPS_VERTICAL_FONT_RES]);
  901.             } else if ( logfonts[lFontID].fattrs.fsFontUse
  902.                         & FATTR_FONTUSE_TRANSFORMABLE) {
  903.                 printf("    transformations require outline font\n");
  904.             }
  905. #endif
  906.         }
  907.     }
  908.     /* If an exact bitmap for a different resolution found, take it */
  909.     if (!found && error <= 1) {
  910.         match = os2fonts[best].lMatch;
  911.         font = best;
  912.         found = TRUE;
  913.     }
  914.     /* If no bitmap but an outline found, take it */
  915.     if (!found && outline != -1) {
  916.         match = os2fonts[outline].lMatch;
  917.         font = outline;
  918.         found = TRUE;
  919.         logfonts[lFontID].outline = TRUE;
  920. #ifdef DEBUG
  921.         printf("    using outline font %s, match %d\n",
  922.                os2fonts[font].szFacename, os2fonts[font].lMatch);
  923. #endif
  924.     }
  925.     /* If no exact bitmap but an approximate found, take it */
  926.     if (!found && best != -1) {
  927.         match = os2fonts[best].lMatch;
  928.         font = best;
  929.         found = TRUE;
  930.     }
  931.     if (!found) {
  932.     /* Select default font by making facename empty */
  933. #ifdef DEBUG
  934.         printf("    GpiCreateLogFont ERROR %x\n", WinGetLastError(hab));
  935.         printf("XLoadFont trying default font\n");
  936. #endif
  937.         memset(logfonts[lFontID].fattrs.szFacename, '\0', FACESIZE);
  938.         match= GpiCreateLogFont(globalPS, NULL, lFontID,
  939.                                 &(logfonts[lFontID].fattrs));
  940.         if (match == GPI_ERROR) {
  941.             if (os2fonts) {
  942.                 ckfree((char *)os2fonts);
  943.             }
  944.             return (Font) 0;
  945.         } else if (match == FONT_DEFAULT) {
  946.             FONTMETRICS fm;
  947.             rc= GpiQueryFontMetrics(globalPS, sizeof(FONTMETRICS), &fm);
  948.             if (!rc) {
  949.                 return (Font) 0;
  950.             }
  951.             logfonts[lFontID].fattrs.lMatch = 0;
  952.             strcpy(logfonts[lFontID].fattrs.szFacename, fm.szFacename);
  953.             logfonts[lFontID].fattrs.idRegistry = fm.idRegistry;
  954.             logfonts[lFontID].fattrs.usCodePage = fm.usCodePage;
  955.             logfonts[lFontID].fattrs.lMaxBaselineExt = fm.lMaxBaselineExt;
  956.             logfonts[lFontID].fattrs.lAveCharWidth = fm.lAveCharWidth;
  957.             logfonts[lFontID].fattrs.fsType = 0;
  958.             logfonts[lFontID].fattrs.fsFontUse = 0;
  959.             goto got_it;
  960.         }
  961.     }
  962.     /* Fill in the exact font metrics if we found a font */
  963.     if (!found) {
  964.         if (os2fonts) {
  965.             ckfree((char *)os2fonts);
  966.         }
  967.         return (Font) 0;
  968.     } else {
  969.         logfonts[lFontID].fattrs.idRegistry = os2fonts[font].idRegistry;
  970.         logfonts[lFontID].fattrs.lMatch = match;
  971.         strcpy(logfonts[lFontID].fattrs.szFacename, os2fonts[font].szFacename);
  972. #ifdef DEBUG
  973.         printf("    using match %d (%s)\n", match,
  974.                logfonts[lFontID].fattrs.szFacename);
  975. #endif
  976.         if (os2fonts[font].fsDefn & FM_DEFN_OUTLINE) {
  977.             logfonts[lFontID].fattrs.lMaxBaselineExt = 0;
  978.             logfonts[lFontID].fattrs.lAveCharWidth = 0;
  979.             logfonts[lFontID].fattrs.fsFontUse |= FATTR_FONTUSE_OUTLINE;
  980.         } else {
  981.             logfonts[lFontID].fattrs.lMaxBaselineExt = os2fonts[font].lMaxBaselineExt;
  982.             logfonts[lFontID].fattrs.lAveCharWidth = os2fonts[font].lAveCharWidth;
  983.         }
  984.     }
  985.  
  986. got_it:
  987.  
  988. #ifdef DEBUG
  989.     printf("    length %d, sel %x, reg %d, cp %d, mbe %d, acw %d, type %x, fu %x\n",
  990.            logfonts[lFontID].fattrs.usRecordLength,
  991.            logfonts[lFontID].fattrs.fsSelection,
  992.            logfonts[lFontID].fattrs.idRegistry,
  993.            logfonts[lFontID].fattrs.usCodePage,
  994.            logfonts[lFontID].fattrs.lMaxBaselineExt,
  995.            logfonts[lFontID].fattrs.lAveCharWidth,
  996.            logfonts[lFontID].fattrs.fsType, logfonts[lFontID].fattrs.fsFontUse);
  997. #endif
  998.     match = GpiCreateLogFont(globalPS, NULL, lFontID,
  999.                              &(logfonts[lFontID].fattrs));
  1000.     if (match == GPI_ERROR) {
  1001.     /* Select default font by making facename empty */
  1002. #ifdef DEBUG
  1003.         printf("    GpiCreateLogFont ERROR %x\n", WinGetLastError(hab));
  1004.         printf("XLoadFont trying default font\n");
  1005. #endif
  1006.         memset(logfonts[lFontID].fattrs.szFacename, '\0', FACESIZE);
  1007.         match = GpiCreateLogFont(globalPS, NULL, lFontID,
  1008.                                  &(logfonts[lFontID].fattrs));
  1009.     }
  1010.     /* Scale the font to the right size if outline font */
  1011.     if (logfonts[lFontID].outline) {
  1012.         rc = TkOS2ScaleFont(globalPS, logfonts[lFontID].deciPoints, 0);
  1013. #ifdef DEBUG
  1014.         if (rc!=TRUE) {
  1015.             printf("TkOS2ScaleFont %d ERROR %x\n", logfonts[lFontID].deciPoints,
  1016.                    WinGetLastError(hab));
  1017.         } else {
  1018.             printf("TkOS2ScaleFont %d OK\n", logfonts[lFontID].deciPoints);
  1019.         }
  1020.         rc = GpiQueryCharBox(globalPS, &charBox);
  1021.         if (rc!=TRUE) {
  1022.             printf("GpiQueryCharBox ERROR %x\n");
  1023.         } else {
  1024.             printf("GpiQueryCharBox OK: now cx %d (%d,%d), cy %d (%d,%d)\n",
  1025.                     charBox.cx, FIXEDINT(charBox.cx), FIXEDFRAC(charBox.cx),
  1026.                     charBox.cy, FIXEDINT(charBox.cy), FIXEDFRAC(charBox.cy));
  1027.         }
  1028. #endif
  1029.     }
  1030.  
  1031. #ifdef DEBUG
  1032.         printf("XLoadFont match %s lFontID %d\n", match==FONT_MATCH ?
  1033.                "FONT_MATCH" : (match==FONT_DEFAULT ? "FONT_DEFAULT" :
  1034.                                "GPI_ERROR"), lFontID);
  1035. #endif
  1036.     if (match == GPI_ERROR) {
  1037.         if (os2fonts) {
  1038.             ckfree((char *)os2fonts);
  1039.         }
  1040.         return (Font) 0;
  1041.     } else {
  1042. #ifdef DEBUG
  1043.         if (match==FONT_DEFAULT) {
  1044.             FONTMETRICS fm;
  1045.             rc= GpiQueryFontMetrics(globalPS, sizeof(FONTMETRICS), &fm);
  1046.             if (rc==TRUE) {
  1047.                 printf("    metrics: family [%s], name [%s], %s\n",
  1048.                        fm.szFamilyname,
  1049.                        fm.szFacename, fm.fsType & FM_TYPE_FACETRUNC ?
  1050.                        "truncated" : "org");
  1051.                 printf("             avg width %d, maxBasel %d, %s\n",
  1052.                        fm.lAveCharWidth,
  1053.                        fm.lMaxBaselineExt, fm.fsDefn & FM_DEFN_OUTLINE ?
  1054.                        "outline" : "bitmap");
  1055.             }
  1056.         }
  1057. #endif
  1058.         ckfree((char *)os2fonts);
  1059.         nextLogicalFont++;
  1060.         return (Font) lFontID;
  1061.     }
  1062. }
  1063.  
  1064. /*
  1065.  *----------------------------------------------------------------------
  1066.  *
  1067.  * XQueryFont --
  1068.  *
  1069.  *    Retrieve information about the specified font.
  1070.  *
  1071.  * Results:
  1072.  *    Returns a newly allocated XFontStruct.
  1073.  *
  1074.  * Side effects:
  1075.  *    None.
  1076.  *
  1077.  *----------------------------------------------------------------------
  1078.  */
  1079.  
  1080. XFontStruct *
  1081. XQueryFont(display, font_ID)
  1082.     Display* display;
  1083.     XID font_ID;
  1084. {
  1085.     XFontStruct *fontPtr = (XFontStruct *) ckalloc(sizeof(XFontStruct));
  1086.     LONG oldFont;
  1087.     FONTMETRICS fm;
  1088.     XCharStruct bounds;
  1089.     BOOL rc;
  1090.     POINTL noShear= {0, 1};
  1091.  
  1092. #ifdef DEBUG
  1093. printf("XQueryFont FID %d\n", font_ID);
  1094. #endif
  1095.  
  1096.     if (!fontPtr) {
  1097.     return NULL;
  1098.     }
  1099.     
  1100.     fontPtr->fid = font_ID;
  1101.  
  1102.     oldFont = GpiQueryCharSet(globalPS);
  1103.     rc = GpiSetCharSet(globalPS, (LONG) fontPtr->fid);
  1104. #ifdef DEBUG
  1105. printf("GpiSetCharSet %d returns %d\n", fontPtr->fid, rc);
  1106. if (rc==FALSE) printf("Error=%x\n", WinGetLastError(hab));
  1107. #endif
  1108.     /* Set slant if necessary */
  1109.     if (logfonts[(LONG)fontPtr->fid].setShear) {
  1110.         GpiSetCharShear(globalPS, &(logfonts[(LONG)fontPtr->fid].shear));
  1111.     }
  1112.  
  1113.     /*
  1114.      * Determine the font metrics and store the values into the appropriate
  1115.      * X data structures.
  1116.      */
  1117.  
  1118.     /* If this is an outline font, set the char box */
  1119.     if (logfonts[font_ID].outline) {
  1120. #ifdef DEBUG
  1121.         SIZEF charBox;
  1122. #endif
  1123.         rc = TkOS2ScaleFont(globalPS, logfonts[font_ID].deciPoints, 0);
  1124. #ifdef DEBUG
  1125.         if (rc!=TRUE) {
  1126.             printf("TkOS2ScaleFont %d ERROR %x\n", logfonts[font_ID].deciPoints,
  1127.                    WinGetLastError(hab));
  1128.         } else {
  1129.             printf("TkOS2ScaleFont %d OK\n", logfonts[font_ID].deciPoints);
  1130.         }
  1131.         rc = GpiQueryCharBox(globalPS, &charBox);
  1132.         if (rc!=TRUE) {
  1133.             printf("GpiQueryCharBox ERROR %x\n");
  1134.         } else {
  1135.             printf("GpiQueryCharBox OK: now cx %d (%d,%d), cy %d (%d,%d)\n",
  1136.                    charBox.cx, FIXEDINT(charBox.cx), FIXEDFRAC(charBox.cx),
  1137.                    charBox.cy, FIXEDINT(charBox.cy), FIXEDFRAC(charBox.cy));
  1138.         }
  1139. #endif
  1140.     }
  1141.  
  1142.     if (GpiQueryFontMetrics(globalPS, sizeof(FONTMETRICS), &fm)) {
  1143. #ifdef DEBUG
  1144.         printf("Font metrics: first %c (%d), last %c (%d), def %c (%d),
  1145.                maxCharInc %d, maxAsc %d, maxDesc %d, maxBaselineExt %d,
  1146.                bounds %d\n", fm.sFirstChar, fm.sFirstChar, fm.sLastChar,
  1147.                fm.sLastChar, fm.sDefaultChar, fm.sDefaultChar, fm.lMaxCharInc,
  1148.                fm.lMaxAscender, fm.lMaxDescender, fm.lMaxBaselineExt, bounds);
  1149.         printf("    sNominalPointSize %d, size %d\n", fm.sNominalPointSize, 
  1150.                fm.lMaxBaselineExt);
  1151.         printf("    lEmInc %d, underpos %d, size %d\n", fm.lEmInc,
  1152.                fm.lUnderscorePosition, fm.lUnderscoreSize);
  1153. #endif
  1154.  
  1155.         /*
  1156.          * Copy fontmetrics into own structure, so we remember scalable font
  1157.          * modifications.
  1158.          */
  1159.         memcpy((void *)&logfonts[font_ID].fm, (void *)&fm, sizeof(FONTMETRICS));
  1160. #ifdef DEBUG
  1161.         printf("    sXDeviceRes %d, sYDeviceRes %d\n",
  1162.                logfonts[font_ID].fm.sXDeviceRes,
  1163.                logfonts[font_ID].fm.sYDeviceRes);
  1164. #endif
  1165.  
  1166.     fontPtr->direction = LOBYTE(fm.sInlineDir) < 90 || LOBYTE(fm.sInlineDir) > 270
  1167.                          ? FontLeftToRight : FontRightToLeft;
  1168.     fontPtr->min_byte1 = 0;
  1169.     fontPtr->max_byte1 = 0;
  1170.     fontPtr->min_char_or_byte2 = fm.sFirstChar;
  1171.     /* sLastChar is *offset* from sFirstChar! */
  1172.     fontPtr->max_char_or_byte2 = fm.sFirstChar + fm.sLastChar;
  1173.     fontPtr->all_chars_exist = True;
  1174.     fontPtr->default_char = fm.sDefaultChar;
  1175.     fontPtr->n_properties = 0;
  1176.     fontPtr->properties = NULL;
  1177.     bounds.lbearing = 0;
  1178.     bounds.rbearing = fm.lMaxCharInc;
  1179.     bounds.width = fm.lMaxCharInc;
  1180.     bounds.ascent = fm.lMaxAscender;
  1181.     bounds.descent = fm.lMaxDescender;
  1182.     bounds.attributes = 0;
  1183.     fontPtr->ascent = fm.lMaxAscender;
  1184.     fontPtr->descent = fm.lMaxDescender;
  1185.     fontPtr->min_bounds = bounds;
  1186.     fontPtr->max_bounds = bounds;
  1187.  
  1188.     /*
  1189.      * If the font is not fixed pitch, then we need to construct
  1190.      * the per_char array.
  1191.      */
  1192.  
  1193.     if ( !(fm.fsType & FM_TYPE_FIXED) ) {
  1194.         int i;
  1195.         char c;
  1196.             /*
  1197.              * sLastChar is offset from sFirstChar
  1198.              * Only 256 code points (0 - 255) allowed in a code page.
  1199.              */
  1200.         int nchars = MIN(((int)fm.sLastChar + 1), 255);
  1201.         int minWidth = 30000;
  1202. POINTL endPoint[2];
  1203.             PLONG widths;
  1204.         fontPtr->per_char =
  1205.         (XCharStruct *)ckalloc(sizeof(XCharStruct) * nchars);
  1206.  
  1207.             /*
  1208.              * GpiQueryCharStringPos seems to be more precise than
  1209.              * GpiQueryWidthTable. In the widget demo, the first only exhibits
  1210.              * some "dancing" when highlighting, while the latter gives a very
  1211.              * noticeable space before the cursor.
  1212.              * On the other hand, it is abysmal for raster fonts.
  1213.              */
  1214.             if (logfonts[font_ID].outline) {
  1215.                 for (i = 0, c = fm.sFirstChar; i < nchars ; i++, c++ ) {
  1216.                     GpiQueryCharStringPos(globalPS, 0L, 1, &c, NULL, endPoint);
  1217.                     /*
  1218.                     fontPtr->per_char[i] = bounds;
  1219.                     */
  1220.                     fontPtr->per_char[i].width = endPoint[1].x - endPoint[0].x;
  1221. #ifdef DEBUG
  1222.                     printf("    width [%c] %d (endP1.x %d, endP0.x %d)\n",
  1223.                            fm.sFirstChar+i, fontPtr->per_char[i].width,
  1224.                            endPoint[1].x, endPoint[0].x);
  1225. #endif
  1226.                     if (minWidth > fontPtr->per_char[i].width) {
  1227.                         minWidth = fontPtr->per_char[i].width;
  1228.                     }
  1229.                 }
  1230.             } else {
  1231.                 /* Bitmap -> use GpiQueryWidthTable */
  1232.                 widths = (PLONG) ckalloc(sizeof(LONG)*nchars);
  1233.                 if (widths != NULL) {
  1234.                     rc= GpiQueryWidthTable(globalPS, fm.sFirstChar, nchars,
  1235.                                            widths);
  1236.                     if (rc == TRUE) {
  1237.                         for (i = 0; i < nchars ; i++) {
  1238.                             fontPtr->per_char[i] = bounds;
  1239.                             fontPtr->per_char[i].width = widths[i];
  1240. #ifdef DEBUG
  1241.                             printf("    width (bmp) [%c] %d\n", fm.sFirstChar+i,
  1242.                                    fontPtr->per_char[i].width);
  1243. #endif
  1244.                             if (minWidth > fontPtr->per_char[i].width) {
  1245.                                 minWidth = fontPtr->per_char[i].width;
  1246.                             }
  1247.                         }
  1248. #ifdef DEBUG
  1249.                         printf("variable pitch, nchars %d, minWidth %d\n", nchars,
  1250.                                minWidth);
  1251. #endif
  1252.                     } else {
  1253.                         ckfree((char *)fontPtr);
  1254.                         fontPtr = NULL;
  1255. #ifdef DEBUG
  1256.                         printf("    GpiQueryWidthTable %d ERROR %x\n", nchars,
  1257.                                WinGetLastError(hab));
  1258. #endif
  1259.                     }
  1260.                 } else {
  1261.                     ckfree((char *)fontPtr);
  1262.                     fontPtr = NULL;
  1263. #ifdef DEBUG
  1264.                     printf("    couldn't allocate memory for widths\n");
  1265. #endif
  1266.                     goto restore;
  1267.                 }
  1268.             }
  1269.  
  1270.         fontPtr->min_bounds.width = minWidth;
  1271.     } else {
  1272. #ifdef DEBUG
  1273.             printf("    Fixed pitch font\n");
  1274. #endif
  1275.         fontPtr->per_char = NULL;
  1276.     }
  1277.     } else {
  1278.     ckfree((char *)fontPtr);
  1279.     fontPtr = NULL;
  1280.     }    
  1281.  
  1282. restore:
  1283.  
  1284.     /* Restore font */
  1285.     if (logfonts[(LONG)fontPtr->fid].setShear) {
  1286.         GpiSetCharShear(globalPS, &noShear);
  1287.     }
  1288.     GpiSetCharSet(globalPS, oldFont);
  1289.     
  1290.     return fontPtr;
  1291. }
  1292.  
  1293. /*
  1294.  *----------------------------------------------------------------------
  1295.  *
  1296.  * XLoadQueryFont --
  1297.  *
  1298.  *    Finds the closest available OS/2 font for the specified
  1299.  *    font name.
  1300.  *
  1301.  * Results:
  1302.  *    Allocates and returns an XFontStruct containing a description
  1303.  *    of the matching font.
  1304.  *
  1305.  * Side effects:
  1306.  *    None.
  1307.  *
  1308.  *----------------------------------------------------------------------
  1309.  */
  1310.  
  1311. XFontStruct *
  1312. XLoadQueryFont(display, name)
  1313.     Display* display;
  1314.     _Xconst char* name;
  1315. {
  1316.     Font font;
  1317.  
  1318. #ifdef DEBUG
  1319. printf("XLoadQueryFont %s\n", name);
  1320. #endif
  1321.     font = XLoadFont(display, name);
  1322.     return XQueryFont(display, font);
  1323. }
  1324.  
  1325. /*
  1326.  *----------------------------------------------------------------------
  1327.  *
  1328.  * XFreeFont --
  1329.  *
  1330.  *    Releases resources associated with the specified font.
  1331.  *
  1332.  * Results:
  1333.  *    None.
  1334.  *
  1335.  * Side effects:
  1336.  *    Frees the memory referenced by font_struct.
  1337.  *
  1338.  *----------------------------------------------------------------------
  1339.  */
  1340.  
  1341. void
  1342. XFreeFont(display, font_struct)
  1343.     Display* display;
  1344.     XFontStruct* font_struct;
  1345. {
  1346. #ifdef DEBUG
  1347. printf("XFreeFont\n");
  1348. #endif
  1349.  
  1350.     /* Only deleting the last ID can be done in this array-approach */
  1351.     if (nextLogicalFont-1 == (LONG)font_struct->fid) {
  1352.         GpiDeleteSetId(globalPS, (LONG)font_struct->fid);
  1353.         nextLogicalFont--;
  1354.     }
  1355. #ifdef DEBUG
  1356. else printf("      Logical ID %d leaves hole\n", font_struct->fid);
  1357. #endif
  1358.     if (font_struct->per_char != NULL) {
  1359.         ckfree((char *) font_struct->per_char);
  1360.     }
  1361.     ckfree((char *) font_struct);
  1362. }
  1363.  
  1364. /*
  1365.  *----------------------------------------------------------------------
  1366.  *
  1367.  * XTextWidth --
  1368.  *
  1369.  *    Compute the width of an 8-bit character string.
  1370.  *
  1371.  * Results:
  1372.  *    Returns the computed width of the specified string.
  1373.  *
  1374.  * Side effects:
  1375.  *    None.
  1376.  *
  1377.  *----------------------------------------------------------------------
  1378.  */
  1379.  
  1380. int
  1381. XTextWidth(font_struct, string, count)
  1382.     XFontStruct* font_struct;
  1383.     _Xconst char* string;
  1384.     int count;
  1385. {
  1386.     /*
  1387.     FONTMETRICS fm;
  1388.     */
  1389.     LONG oldFont;
  1390.     POINTL aSize[TXTBOX_COUNT];
  1391.     POINTL noShear= {0, 1};
  1392.  
  1393. #ifdef DEBUG
  1394.     printf("XTextWidth [%s], font ID [%d]\n", string, (LONG)font_struct->fid);
  1395. #endif
  1396.     oldFont = GpiQueryCharSet(globalPS);
  1397.     GpiSetCharSet(globalPS, (LONG) font_struct->fid);
  1398.     /* Set slant if necessary */
  1399.     if (logfonts[(LONG)font_struct->fid].setShear) {
  1400.         GpiSetCharShear(globalPS, &(logfonts[(LONG)font_struct->fid].shear));
  1401.     }
  1402.     /* If this is an outline font, set the char box */
  1403.     if (logfonts[(LONG)font_struct->fid].outline) {
  1404. #ifdef DEBUG
  1405.         SIZEF charBox;
  1406. #endif
  1407.         rc = TkOS2ScaleFont(globalPS,
  1408.                             logfonts[(LONG)font_struct->fid].deciPoints, 0);
  1409. #ifdef DEBUG
  1410.         if (rc!=TRUE) {
  1411.             printf("TkOS2ScaleFont %d ERROR %x\n",
  1412.                      logfonts[(LONG)font_struct->fid].deciPoints,
  1413.                      WinGetLastError(hab));
  1414.         } else {
  1415.             printf("TkOS2ScaleFont %d OK\n", logfonts[(LONG)font_struct->fid].deciPoints);
  1416.         }
  1417.         rc = GpiQueryCharBox(globalPS, &charBox);
  1418. if (rc!=TRUE) printf("GpiQueryCharBox ERROR %x\n");
  1419. else printf("GpiQueryCharBox OK: now cx %d (%d,%d), cy %d (%d,%d)\n", charBox.cx,
  1420.             FIXEDINT(charBox.cx), FIXEDFRAC(charBox.cx), charBox.cy,
  1421.             FIXEDINT(charBox.cy), FIXEDFRAC(charBox.cy));
  1422. #endif
  1423.     }
  1424. else {
  1425. /*
  1426.  * XTextWidth is only used by Tk as an average number, for '0'
  1427.  * -> use lAveCharWidth
  1428.  */
  1429. #ifdef DEBUG
  1430.     printf("XTextWidth returns AveCharWidth %d (font %d)\n",
  1431.     logfonts[(LONG)font_struct->fid].fattrs.lAveCharWidth,  font_struct->fid);
  1432. #endif
  1433. return logfonts[(LONG)font_struct->fid].fattrs.lAveCharWidth;
  1434. }
  1435.  
  1436.     GpiQueryTextBox(globalPS, count, (PCH)string, TXTBOX_COUNT, aSize);
  1437.     /* OS/2 PM does not have ths overhang
  1438.      * GpiQueryFontMetrics(globalPS, sizeof(FONTMETRICS), &fm);
  1439.      * size.cx -= fm.fmOverhang;
  1440.      */
  1441.  
  1442.     /* Restore font */
  1443.     if (logfonts[(LONG)font_struct->fid].setShear) {
  1444.         GpiSetCharShear(globalPS, &noShear);
  1445.     }
  1446.     GpiSetCharSet(globalPS, oldFont);
  1447.  
  1448. #ifdef DEBUG
  1449. printf("XTextWidth %s (font %d) returning %d\n", string, font_struct->fid,
  1450.        aSize[TXTBOX_BOTTOMRIGHT].x - aSize[TXTBOX_BOTTOMLEFT].x);
  1451. #endif
  1452.  
  1453.     return aSize[TXTBOX_BOTTOMRIGHT].x - aSize[TXTBOX_BOTTOMLEFT].x;
  1454. }
  1455.  
  1456. /*
  1457.  *----------------------------------------------------------------------
  1458.  *
  1459.  * XTextExtents --
  1460.  *
  1461.  *    Compute the bounding box for a string.
  1462.  *
  1463.  * Results:
  1464.  *    Sets the direction_return, ascent_return, descent_return, and
  1465.  *    overall_return values as defined by Xlib.
  1466.  *
  1467.  * Side effects:
  1468.  *    None.
  1469.  *
  1470.  *----------------------------------------------------------------------
  1471.  */
  1472.  
  1473. void
  1474. XTextExtents(font_struct, string, nchars, direction_return,
  1475.     font_ascent_return, font_descent_return, overall_return)
  1476.     XFontStruct* font_struct;
  1477.     _Xconst char* string;
  1478.     int nchars;
  1479.     int* direction_return;
  1480.     int* font_ascent_return;
  1481.     int* font_descent_return;
  1482.     XCharStruct* overall_return;
  1483. {
  1484.     LONG oldFont;
  1485.     POINTL aSize[TXTBOX_COUNT];
  1486.     POINTL noShear= {0, 1};
  1487.  
  1488. #ifdef DEBUG
  1489. printf("XTextExtents\n");
  1490. #endif
  1491.  
  1492.     *direction_return = font_struct->direction;
  1493.     *font_ascent_return = font_struct->ascent;
  1494.     *font_descent_return = font_struct->descent;
  1495.  
  1496.     oldFont = GpiQueryCharSet(globalPS);
  1497.     GpiSetCharSet(globalPS, (LONG) font_struct->fid);
  1498.     /* Set slant if necessary */
  1499.     if (logfonts[(LONG)font_struct->fid].setShear) {
  1500.         GpiSetCharShear(globalPS, &(logfonts[(LONG)font_struct->fid].shear));
  1501.     }
  1502.     /* If this is an outline font, set the char box */
  1503.     if (logfonts[(LONG)font_struct->fid].outline) {
  1504. #ifdef DEBUG
  1505.         SIZEF charBox;
  1506. #endif
  1507.         rc = TkOS2ScaleFont(globalPS,
  1508.                             logfonts[(LONG)font_struct->fid].deciPoints, 0);
  1509. #ifdef DEBUG
  1510.         if (rc!=TRUE) {
  1511.             printf("TkOS2ScaleFont %d ERROR %x\n",
  1512.                    logfonts[(LONG)font_struct->fid].deciPoints,
  1513.                    WinGetLastError(hab));
  1514.         } else {
  1515.             printf("TkOS2ScaleFont %d OK\n",
  1516.                    logfonts[(LONG)font_struct->fid].deciPoints);
  1517.         }
  1518.         rc = GpiQueryCharBox(globalPS, &charBox);
  1519.         if (rc!=TRUE) {
  1520.             printf("GpiQueryCharBox ERROR %x\n", WinGetLastError(hab));
  1521.         } else {
  1522.             printf("GpiQueryCharBox OK: now cx %d (%d,%d), cy %d (%d,%d)\n",
  1523.                    charBox.cx, FIXEDINT(charBox.cx), FIXEDFRAC(charBox.cx),
  1524.                    charBox.cy, FIXEDINT(charBox.cy), FIXEDFRAC(charBox.cy));
  1525.         }
  1526. #endif
  1527.     }
  1528.  
  1529.     overall_return->ascent = logfonts[(LONG)font_struct->fid].fm.lMaxAscender;
  1530.     overall_return->descent = logfonts[(LONG)font_struct->fid].fm.lMaxDescender;
  1531.     GpiQueryTextBox(globalPS, nchars, (char *)string, TXTBOX_COUNT, aSize);
  1532.     overall_return->width = aSize[TXTBOX_BOTTOMRIGHT].x - aSize[TXTBOX_BOTTOMLEFT].x;
  1533.     overall_return->lbearing = 0;
  1534.     overall_return->rbearing = overall_return->width;
  1535.  
  1536.     /* Restore font */
  1537.     if (logfonts[(LONG)font_struct->fid].setShear) {
  1538.         GpiSetCharShear(globalPS, &noShear);
  1539.     }
  1540.     GpiSetCharSet(globalPS, oldFont);
  1541. }
  1542.  
  1543. /*
  1544.  *----------------------------------------------------------------------
  1545.  *
  1546.  * XGetFontProperty --
  1547.  *
  1548.  *    Called to get font properties.
  1549.  *
  1550.  * Results:
  1551.  *    Return true for known properties, false otherwise
  1552.  *
  1553.  * Side effects:
  1554.  *    None.
  1555.  *
  1556.  *----------------------------------------------------------------------
  1557.  */
  1558.  
  1559. Bool
  1560. XGetFontProperty(font_struct, atom, value_return)
  1561.     XFontStruct* font_struct;
  1562.     Atom atom;
  1563.     unsigned long* value_return;
  1564. {
  1565.     FONTMETRICS fm;
  1566.  
  1567. #ifdef DEBUG
  1568. printf("XGetFontProperty %d\n", (LONG)atom);
  1569. #endif
  1570.  
  1571.     switch (atom) {
  1572.         case XA_SUPERSCRIPT_X:
  1573.             *value_return = (unsigned long) logfonts[(LONG)font_struct->fid].fm.lSuperscriptXOffset;
  1574.             return True;
  1575.             break;
  1576.         case XA_SUPERSCRIPT_Y:
  1577.             *value_return = (unsigned long) logfonts[(LONG)font_struct->fid].fm.lSuperscriptYOffset;
  1578.             return True;
  1579.             break;
  1580.         case XA_SUBSCRIPT_X:
  1581.             *value_return = (unsigned long) logfonts[(LONG)font_struct->fid].fm.lSubscriptXOffset;
  1582.             return True;
  1583.             break;
  1584.         case XA_SUBSCRIPT_Y:
  1585.             *value_return = (unsigned long) logfonts[(LONG)font_struct->fid].fm.lSubscriptYOffset;
  1586.             return True;
  1587.             break;
  1588.         case XA_UNDERLINE_POSITION:
  1589.             *value_return = (unsigned long) logfonts[(LONG)font_struct->fid].fm.lUnderscorePosition;
  1590.             return True;
  1591.             break;
  1592.         case XA_UNDERLINE_THICKNESS:
  1593.             *value_return = (unsigned long) logfonts[(LONG)font_struct->fid].fm.lUnderscoreSize;
  1594.             return True;
  1595.             break;
  1596.         case XA_STRIKEOUT_ASCENT:
  1597.             *value_return = (unsigned long) logfonts[(LONG)font_struct->fid].fm.lStrikeoutPosition;
  1598.             return True;
  1599.             break;
  1600.         case XA_STRIKEOUT_DESCENT:
  1601.             *value_return = (unsigned long) logfonts[(LONG)font_struct->fid].fm.lStrikeoutSize
  1602.                                             - logfonts[(LONG)font_struct->fid].fm.lStrikeoutPosition;
  1603.             return True;
  1604.             break;
  1605.         case XA_ITALIC_ANGLE: /* scaled by 64 */
  1606.             /* Degrees in sCharSlope second byte, minutes first byte */
  1607. /* Endian-ness!!! */
  1608.             *value_return = (unsigned long) 64 * 90 - (logfonts[(LONG)font_struct->fid].fm.sCharSlope >> 2);
  1609.             return True;
  1610.             break;
  1611.         case XA_X_HEIGHT:
  1612.             *value_return = (unsigned long) logfonts[(LONG)font_struct->fid].fm.lXHeight;
  1613.             return True;
  1614.             break;
  1615.         case XA_QUAD_WIDTH:
  1616.             *value_return = (unsigned long) logfonts[(LONG)font_struct->fid].fm.lEmInc;
  1617.             return True;
  1618.             break;
  1619.         case XA_CAP_HEIGHT:
  1620.             /* Same as max height */
  1621.             *value_return = (unsigned long) logfonts[(LONG)font_struct->fid].fm.lMaxAscender;
  1622.             return True;
  1623.             break;
  1624.         case XA_WEIGHT:
  1625.             /* Scale of 0 to 1000 */
  1626.             *value_return = (unsigned long) 100 * logfonts[(LONG)font_struct->fid].fm.usWeightClass;
  1627.             return True;
  1628.             break;
  1629.         case XA_POINT_SIZE:
  1630.             *value_return = (unsigned long) logfonts[(LONG)font_struct->fid].fm.sNominalPointSize;
  1631.             return True;
  1632.             break;
  1633.         case XA_RESOLUTION:
  1634.             /* expressed in hundredths */
  1635.             /* Fontmetrics give two fields: sXDeviceRes and sYDeviceRes */
  1636.             /* in pels/inch for bitmap fonts, notional units/Em for outline */
  1637.             if ( logfonts[(LONG)font_struct->fid].fm.fsDefn & FM_DEFN_OUTLINE ) {
  1638.                 /* Em size gives point size */
  1639.                 *value_return = (unsigned long) logfonts[(LONG)font_struct->fid].fm.sXDeviceRes* fm.lEmInc* 100;
  1640. #ifdef DEBUG
  1641.                 printf("    XA_RESOLUTION %d (OUTLINE, xres %d * lEmInc %d * 100)\n",
  1642.                        *value_return, logfonts[(LONG)font_struct->fid].fm.sXDeviceRes, fm.lEmInc);
  1643. #endif
  1644.             } else {
  1645.                 /* multiply by number of points in one inch, 72, + 100ths */
  1646.                 *value_return = (unsigned long) logfonts[(LONG)font_struct->fid].fm.sXDeviceRes * 722818;
  1647. #ifdef DEBUG
  1648.                 printf("    XA_RESOLUTION %d (xres %d * 72\n", *value_return,
  1649.                        logfonts[(LONG)font_struct->fid].fm.sXDeviceRes);
  1650. #endif
  1651.             }
  1652.             return True;
  1653.             break;
  1654.         default:
  1655.             return False;
  1656.             break;
  1657.     }
  1658. }
  1659.  
  1660. /*
  1661.  *----------------------------------------------------------------------
  1662.  *
  1663.  * TkOS2ScaleFont --
  1664.  *
  1665.  *      Adapted from "OS/2 Presentation Manager Programming" by Petzold.
  1666.  *    Called to scale a presentation space's font to a desired size.
  1667.  *
  1668.  * Results:
  1669.  *    Return true if successful.
  1670.  *
  1671.  * Side effects:
  1672.  *    Sets the character box attribute of a presentation space.
  1673.  *
  1674.  *----------------------------------------------------------------------
  1675.  */
  1676.  
  1677. BOOL
  1678. TkOS2ScaleFont(hps, pointSize, pointWidth)
  1679.     HPS hps;
  1680.     ULONG pointSize;    /* in decipixels */
  1681.     ULONG pointWidth;    /* 0 means "same as pointSize" */
  1682. {
  1683.     HDC hdc;
  1684.     LONG xRes, yRes;
  1685.     POINTL points[2];
  1686.     SIZEF sizef;
  1687.  
  1688. #ifdef DEBUG
  1689.     printf("TkOS2ScaleFont hps %x, pointSize %d, pointWidth %d\n", hps,
  1690.            pointSize, pointWidth);
  1691.     rc = GpiQueryCharBox(hps, &sizef);
  1692.     if (rc!=TRUE) printf("GpiQueryCharBox ERROR %x\n", WinGetLastError(hab));
  1693.     else printf("GpiQueryCharBox OK: cx %d (%d,%d), cy %d (%d,%d)\n", sizef.cx,
  1694.                 FIXEDINT(sizef.cx), FIXEDFRAC(sizef.cx), sizef.cy,
  1695.                 FIXEDINT(sizef.cy), FIXEDFRAC(sizef.cy));
  1696. #endif
  1697.     /* If pointWidth defaulted, set it to pointSize */
  1698.     if (pointWidth == 0) {
  1699.         pointWidth = pointSize;
  1700.     }
  1701.  
  1702.     /* Determine device and its resolutions */
  1703.     hdc = GpiQueryDevice(hps);
  1704.     if (hdc == HDC_ERROR) {
  1705. #ifdef DEBUG
  1706.         printf("    GpiQueryDevice ERROR %x\n", WinGetLastError(hab));
  1707. #endif
  1708.         return FALSE;
  1709.     } else if (hdc == NULLHANDLE) {
  1710.         /* No device context associated, assume the screen */
  1711.         xRes = aDevCaps[CAPS_HORIZONTAL_FONT_RES];
  1712.         yRes = aDevCaps[CAPS_VERTICAL_FONT_RES];
  1713.     } else {
  1714.         rc = DevQueryCaps(hdc, CAPS_HORIZONTAL_FONT_RES, 1, &xRes);
  1715.         if (rc != TRUE) {
  1716. #ifdef DEBUG
  1717.             printf("    DevQueryCaps xRes ERROR %x\n", WinGetLastError(hab));
  1718. #endif
  1719.             xRes = aDevCaps[CAPS_HORIZONTAL_FONT_RES];
  1720.         }
  1721.         rc = DevQueryCaps(hdc, CAPS_VERTICAL_FONT_RES, 1, &yRes);
  1722.         if (rc != TRUE) {
  1723. #ifdef DEBUG
  1724.             printf("    DevQueryCaps yRes ERROR %x\n", WinGetLastError(hab));
  1725. #endif
  1726.             yRes = aDevCaps[CAPS_VERTICAL_FONT_RES];
  1727.         }
  1728.     }
  1729.  
  1730.     /*
  1731.      * Determine desired point size in pixels with device resolution.
  1732.      * Font resolution is returned by PM in pels per inch, device resolution
  1733.      * is in dots per inch. 722.818 decipoints in an inch.
  1734.      * Add 361.409 for correct rounding.
  1735.      */
  1736.     points[0].x = 0;
  1737.     points[0].y = 0;
  1738.     points[1].x = (xRes * pointWidth + 361.409) / 722.818;
  1739.     points[1].y = (yRes * pointSize + 361.409) / 722.818;
  1740.  
  1741.     /* Convert to page coordinates */
  1742.     rc = GpiConvert(hps, CVTC_DEVICE, CVTC_PAGE, 2L, points);
  1743. #ifdef DEBUG
  1744.     if (rc!=TRUE) printf("GpiConvert ERROR %x\n", WinGetLastError(hab));
  1745.     else printf("GpiConvert OK: (%d,%d) -> (%d,%d)\n",
  1746.                 (aDevCaps[CAPS_HORIZONTAL_FONT_RES] * pointWidth + 360) / 720,
  1747.                 (aDevCaps[CAPS_VERTICAL_FONT_RES] * pointSize + 360) / 720,
  1748.                 points[1].x, points[1].y);
  1749. #endif
  1750.  
  1751.     /* Now set the character box */
  1752.     sizef.cx = MAKEFIXED((points[1].x - points[0].x), 0);
  1753.     sizef.cy = MAKEFIXED((points[1].y - points[0].y), 0);
  1754. #ifdef DEBUG
  1755.     printf("after GpiConvert: cx FIXED(%d), cy FIXED(%d)\n",
  1756.            points[1].x - points[0].x, points[1].y - points[0].y);
  1757. #endif
  1758.  
  1759.     return GpiSetCharBox(hps, &sizef);
  1760. }
  1761.