home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tcltk805.zip / tcl805s.zip / tk8.0.5 / os2 / tkOS2Font.c < prev    next >
C/C++ Source or Header  |  2001-09-08  |  88KB  |  2,301 lines

  1. /* 
  2.  * tkOS2Font.c --
  3.  *
  4.  *    Contains the OS/2 implementation of the platform-independant
  5.  *    font package interface.
  6.  *
  7.  * Copyright (c) 1996-2000 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. #include "tkFont.h"
  18.  
  19. /*
  20.  * The following structure represents OS/2's implementation of a font.
  21.  */
  22.  
  23. typedef struct OS2Font {
  24.     TkFont font;                /* Stuff used by generic font package.  Must
  25.                                  * be first in structure. */
  26.     LONG fontID;                /* OS/2 "handle" to font. */
  27.     HWND hwnd;                  /* Toplevel window of application that owns
  28.                                  * this font, used for getting HPS. */
  29. } OS2Font;
  30.  
  31. /*
  32.  * The following structure is used as to map between the Tcl strings
  33.  * that represent the system fonts and the numbers used by Windows and OS/2.
  34.  */
  35.  
  36. #define OS2_SYSTEM_FONT           0
  37. #define OS2_SYSTEM_MONO_FONT      1
  38. #define OS2_SYSTEM_PROP_FONT      2
  39. #define OS2_SYSTEM_SANS_FONT      3
  40. /*
  41. #define WIN_ANSI_FIXED_FONT       100
  42. #define WIN_ANSI_VAR_FONT         101
  43. #define WIN_DEVICE_DEFAULT_FONT   102
  44. #define WIN_OEM_FIXED_FONT        103
  45. #define WIN_SYSTEM_FIXED_FONT     104
  46. #define WIN_SYSTEM_FONT           105
  47. */
  48.  
  49. static TkStateMap systemMap[] = {
  50. /*
  51.     {WIN_ANSI_FIXED_FONT,       "ansifixed"},
  52.     {WIN_ANSI_VAR_FONT,         "ansi"},
  53.     {WIN_DEVICE_DEFAULT_FONT,   "device"},
  54.     {WIN_OEM_FIXED_FONT,        "oemfixed"},
  55.     {WIN_SYSTEM_FIXED_FONT,     "systemfixed"},
  56.     {WIN_SYSTEM_FONT,           "system"},
  57. */
  58.     {OS2_SYSTEM_FONT,      "System"},
  59.     {OS2_SYSTEM_MONO_FONT, "System Monospaced"},
  60.     {OS2_SYSTEM_PROP_FONT, "System Proportional"},
  61.     {OS2_SYSTEM_SANS_FONT, "WarpSans"},
  62.     {OS2_SYSTEM_MONO_FONT, "ansifixed"},
  63.     {OS2_SYSTEM_PROP_FONT, "ansi"},
  64.     {OS2_SYSTEM_FONT,      "device"},
  65.     {OS2_SYSTEM_MONO_FONT, "oemfixed"},
  66.     {OS2_SYSTEM_MONO_FONT, "systemfixed"},
  67.     {OS2_SYSTEM_FONT,      "system"},
  68.     {-1,                    NULL}
  69. };
  70.  
  71. /*
  72.  * The following structure is used as to map between the numbers that
  73.  * represent the system fonts and the numbers used by Windows to the
  74.  * names of fonts that are needed for succesful calling of GpiCreateLogFont.
  75.  */
  76.  
  77. static TkStateMap nameMap[] = {
  78.     {OS2_SYSTEM_FONT,       "System"},
  79.     {OS2_SYSTEM_MONO_FONT,  "System Monospaced"},
  80.     {OS2_SYSTEM_PROP_FONT,  "System Proportional"},
  81.     {OS2_SYSTEM_SANS_FONT,  "WarpSans"},
  82. /*
  83.     {WIN_ANSI_FIXED_FONT,       "System Monospaced"},
  84.     {WIN_ANSI_VAR_FONT,         "System Proportional"},
  85.     {WIN_DEVICE_DEFAULT_FONT,   "System"},
  86.     {WIN_OEM_FIXED_FONT,        "System Monospaced"},
  87.     {WIN_SYSTEM_FIXED_FONT,     "System Monospaced"},
  88.     {WIN_SYSTEM_FONT,           "System"},
  89. */
  90.     {-1,                    NULL}
  91. };
  92.  
  93. #define ABS(x)          (((x) < 0) ? -(x) : (x))
  94.  
  95. /*
  96.  * Forward declarations for functions used in this file.
  97.  */
  98.  
  99. static TkFont *         AllocFont _ANSI_ARGS_((TkFont *tkFontPtr,
  100.                             Tk_Window tkwin, LONG fontID));
  101.  
  102. /*
  103.  * Code pages used in this file, 1004 is Windows compatible, 65400 must be
  104.  * used if the font contains special glyphs, ie. Symbol.
  105.  */
  106.  
  107. #define CP_LATIN1 850L
  108. #define CP_1004   1004L
  109. #define CP_65400  65400L
  110.  
  111. /*
  112.  * Determine desired point size in pixels with device resolution.
  113.  * Font resolution is returned by PM in pels per inch, device resolution
  114.  * is in dots per inch. 72.2818 decipoints in an inch.
  115.  * Add 36.1409 for correct rounding.
  116.  * aDevCaps[CAPS_VERTICAL_FONT_RES] is vertical font resolution in pels per
  117.  * inch
  118.  */
  119. #ifdef IGNOREPMRES
  120.     /*
  121.      * Requested by Ilya Zakharevich:
  122.      * Shrink 120 to the value of overrideResolution to facilitate 'better'
  123.      * sizing for those displays which report a resolution of 120dpi but have
  124.      * actual resolution close to 96dpi (VGA upto ?800x600?).
  125.      * This is obviously dependent on both resolution and screen size,
  126.      * as higher resolutions usually use 120dpi fonts, regardless of any
  127.      * screen size.
  128.      */
  129.     #define PIXTOPOINT(pixels) ( \
  130.         (aDevCaps[CAPS_VERTICAL_FONT_RES] == 120) \
  131.         ? (((pixels) * 72.2818 + 36.1409) / overrideResolution) \
  132.         : (((pixels) * 72.2818 + 36.1409) / aDevCaps[CAPS_VERTICAL_FONT_RES]) \
  133.     )
  134.     #define POINTTOPIX(points) ( \
  135.         (aDevCaps[CAPS_VERTICAL_FONT_RES] == 120) \
  136.         ? (((points) * overrideResolution + 36.1409) / 72.2818) \
  137.         : (((points) * aDevCaps[CAPS_VERTICAL_FONT_RES] + 36.1409) / 72.2818) \
  138.     )
  139.     #define PTOP(p) ( \
  140.         (aDevCaps[CAPS_VERTICAL_FONT_RES] == 120) \
  141.         ? (((p) * overrideResolution + 60) / 120 ) \
  142.         : (p) \
  143.     )
  144.     #define FIX_RES(res) (if (res==120) {res = overrideResolution})
  145. #else
  146.     #define PIXTOPOINT(pixels) \
  147.         (((pixels) * 72.2818 + 36.1409) / aDevCaps[CAPS_VERTICAL_FONT_RES])
  148.     #define POINTTOPIX(points) \
  149.         (((points) * aDevCaps[CAPS_VERTICAL_FONT_RES] + 36.1409) / 72.2818)
  150.     #define PTOP(p)  (p)
  151.     #define FIX_RES(res)
  152. #endif
  153.  
  154. /*
  155.  * Quotes from GPI Guide and Reference:
  156.  * "Font Data structures and Attributes"
  157.  *  [...]
  158.  *  The value of Em height represents the font point size in world coordinates
  159.  *  and is the same as the character cell height. For an outline font, this can
  160.  *  be set by the character cell height attribute.
  161.  *  [...]
  162.  *  The maximum baseline extent for a font is the sum of the maximum ascender
  163.  *  and the maximum descender. Maximum baseline extent is not equal to cell
  164.  *  height for outline fonts, but is for image fonts."
  165.  * "FATTRS Data structure
  166.  *  [...]
  167.  *  The maximum baseline extent is the vertical space occupied by the
  168.  *  characters in the font. If you are setting the font-use indicator
  169.  *  FATTR_FONTUSE_OUTLINE, you should set the maximum baseline extent to 0.
  170.  *  Outline fonts take an equivalent value from the character cell attribute
  171.  *  that is current when text is written to an output device.
  172.  *  The maximum baseline extent is required to select an image font and must be
  173.  *  specified in world coordinates.
  174.  *  [...]
  175.  *  The maximum baseline extent in the FATTRS data structure is used for
  176.  *  programming, unlike the maximum baseline extent in the FONTMETRICS data
  177.  *  structure, which is only a measurement as recommended by the font's
  178.  *  designer."
  179.  */
  180.  
  181.  
  182. /*
  183.  *---------------------------------------------------------------------------
  184.  *
  185.  * TkpGetNativeFont --
  186.  *
  187.  *      Map a platform-specific native font name to a TkFont.
  188.  *
  189.  * Results:
  190.  *      The return value is a pointer to a TkFont that represents the
  191.  *      native font.  If a native font by the given name could not be
  192.  *      found, the return value is NULL.
  193.  *
  194.  *      Every call to this procedure returns a new TkFont structure,
  195.  *      even if the name has already been seen before.  The caller should
  196.  *      call TkpDeleteFont() when the font is no longer needed.
  197.  *
  198.  *      The caller is responsible for initializing the memory associated
  199.  *      with the generic TkFont when this function returns and releasing
  200.  *      the contents of the generic TkFont before calling TkpDeleteFont().
  201.  *
  202.  * Side effects:
  203.  *      None.
  204.  *
  205.  *---------------------------------------------------------------------------
  206.  */
  207.  
  208. TkFont *
  209. TkpGetNativeFont(tkwin, name)
  210.     Tk_Window tkwin;            /* For display where font will be used. */
  211.     CONST char *name;           /* Platform-specific font name. */
  212. {
  213.     int object;
  214.     char *fontName;
  215.     FATTRS fattrs;
  216.     LONG lFontID= nextLogicalFont;
  217.     LONG match;
  218.     TkFont *tkFont;
  219.  
  220. #ifdef VERBOSE
  221.     printf("TkpGetNativeFont (%s), tkwin %x\n", name, tkwin);
  222. #endif
  223.  
  224.     if (lFontID > MAX_LID) {
  225.         /* We can't simultaneously  use more than MAX_LID fonts */
  226. #ifdef VERBOSE
  227.         printf("    => too many font IDs\n");
  228. #endif
  229.         return (TkFont *) NULL;
  230.     }
  231.  
  232.     object = TkFindStateNum(NULL, NULL, systemMap, name);
  233.     if (object < 0) {
  234. #ifdef VERBOSE
  235.         printf("    => object < 0\n");
  236. #endif
  237.         return NULL;
  238.     }
  239.  
  240.     fontName = TkFindStateString(nameMap, object);
  241.     if (fontName == NULL) {
  242. #ifdef VERBOSE
  243.         printf("    => fontName NULL\n");
  244. #endif
  245.         return NULL;
  246.     }
  247. #ifdef VERBOSE
  248.     printf("    => fontName %s\n", fontName);
  249. #endif
  250.  
  251.     fattrs.usRecordLength   = (USHORT)sizeof(FATTRS);
  252.     fattrs.fsSelection      = 0;
  253.     fattrs.lMatch           = 0L;
  254.     strncpy(fattrs.szFacename, fontName, FACESIZE);
  255.     fattrs.idRegistry       = 0;    /* Unknown */
  256.     fattrs.usCodePage       = 0;    /* Use present codepage */
  257.     fattrs.lMaxBaselineExt  = 0L;
  258.     fattrs.lAveCharWidth    = 0L;
  259.     fattrs.fsType           = 0;
  260.     fattrs.fsFontUse        = 0;
  261.  
  262.     /*
  263.      * Replace the standard X, Mac and Windows family names with the names that
  264.      * OS/2 likes.
  265.      */
  266.  
  267.     if ((stricmp(fattrs.szFacename, "Times") == 0)
  268.             || (stricmp(fattrs.szFacename, "New York") == 0)) {
  269.         strcpy(fattrs.szFacename, "Times New Roman");
  270.     } else if ((stricmp(fattrs.szFacename, "Courier New") == 0)
  271.             || (stricmp(fattrs.szFacename, "Monaco") == 0)) {
  272.         strcpy(fattrs.szFacename, "Courier");
  273.     } else if ((stricmp(fattrs.szFacename, "Arial") == 0)
  274.             || (stricmp(fattrs.szFacename, "Geneva") == 0)) {
  275.         strcpy(fattrs.szFacename, "Helvetica");
  276.     }
  277.  
  278.     match = GpiCreateLogFont(globalPS, NULL, lFontID, &fattrs);
  279.     WinReleasePS(globalPS);
  280.  
  281.     if (match == GPI_ERROR) {
  282. #ifdef VERBOSE
  283.         printf("GpiCreateLogFont %s (%x, id %d) ERROR, error %x\n",
  284.            fattrs.szFacename, globalPS, lFontID,
  285.                WinGetLastError(TclOS2GetHAB()));
  286. #endif
  287.         return (TkFont *)NULL;
  288.     }
  289. #ifdef VERBOSE
  290.     printf("    GpiCreateLogFont %s (%x, id %d) OK, match %d\n",
  291.            fattrs.szFacename, globalPS, lFontID, match);
  292. #endif
  293.     memcpy((void *)&logfonts[lFontID].fattrs, (void *)&fattrs, sizeof(fattrs));
  294.     logfonts[lFontID].fattrs.lMatch = match;
  295.  
  296.     tkFont = AllocFont(NULL, tkwin, lFontID);
  297.     if (tkFont != NULL) {
  298.         nextLogicalFont++;
  299.     }
  300.  
  301.     return tkFont;
  302. }
  303.  
  304. /*
  305.  *---------------------------------------------------------------------------
  306.  *
  307.  * TkpGetFontFromAttributes --
  308.  *
  309.  *      Given a desired set of attributes for a font, find a font with
  310.  *      the closest matching attributes.
  311.  *
  312.  * Results:
  313.  *      The return value is a pointer to a TkFont that represents the
  314.  *      font with the desired attributes.  If a font with the desired
  315.  *      attributes could not be constructed, some other font will be
  316.  *      substituted automatically.  NULL is never returned.
  317.  *
  318.  *      Every call to this procedure returns a new TkFont structure,
  319.  *      even if the specified attributes have already been seen before.
  320.  *      The caller should call TkpDeleteFont() to free the platform-
  321.  *      specific data when the font is no longer needed.
  322.  *
  323.  *      The caller is responsible for initializing the memory associated
  324.  *      with the generic TkFont when this function returns and releasing
  325.  *      the contents of the generic TkFont before calling TkpDeleteFont().
  326.  *
  327.  * Side effects:
  328.  *      None.
  329.  *
  330.  *---------------------------------------------------------------------------
  331.  */
  332. TkFont *
  333. TkpGetFontFromAttributes(tkFontPtr, tkwin, faPtr)
  334.     TkFont *tkFontPtr;          /* If non-NULL, store the information in
  335.                                  * this existing TkFont structure, rather than
  336.                                  * allocating a new structure to hold the
  337.                                  * font; the existing contents of the font
  338.                                  * will be released.  If NULL, a new TkFont
  339.                                  * structure is allocated. */
  340.     Tk_Window tkwin;            /* For display where font will be used. */
  341.     CONST TkFontAttributes *faPtr;  /* Set of attributes to match. */
  342. {
  343.     LONG lFontID= nextLogicalFont;
  344.     Window window;
  345.     HWND hwnd;
  346.     HPS hps;
  347.     LONG match = 0;
  348.     BOOL useIntended = FALSE;
  349.     LONG reqFonts, remFonts;
  350.     PFONTMETRICS os2fonts;
  351.     BOOL found = FALSE;
  352.     LONG outline = -1;
  353.     LONG font = 0;
  354.     int i, error = 30000, best = -1;
  355.     TkFont *tkFont;
  356.     char caseName[FACESIZE];
  357.     int faceLen = 0;
  358.  
  359. #ifdef VERBOSE
  360.     printf("TkpGetFontFromAttributes (%s), tkwin %x\n", faPtr->family, tkwin);
  361. #endif
  362.  
  363.     if (lFontID > MAX_LID) {
  364.         /* We can't simultaneously  use more than MAX_LID fonts */
  365.         lFontID = MAX_LID;
  366.         goto defaultFont;
  367.     }
  368.     window = Tk_WindowId(((TkWindow *) tkwin)->mainPtr->winPtr);
  369.     hwnd = (window == None) ? HWND_DESKTOP : TkOS2GetHWND(window);
  370.     hps = WinGetPS(hwnd);
  371.  
  372.     /*
  373.      * Watch out: we are called with all-lowercase font name!
  374.      * => check to see if there's a font with the same name when using
  375.      * stricmp but different when using strcmp.
  376.      */
  377.  
  378.     if (faPtr->family != NULL) {
  379.         /* Determine total number of fonts */
  380.         reqFonts = 0L;
  381.         remFonts = GpiQueryFonts(hps, QF_PUBLIC, NULL, &reqFonts,
  382.                                  (LONG) sizeof(FONTMETRICS), NULL);
  383. #ifdef VERBOSE
  384.         printf("    nr.of fonts: %ld\n", remFonts);
  385. #endif
  386.         /* Allocate space for the fonts */
  387.         os2fonts = (PFONTMETRICS) ckalloc(remFonts * sizeof(FONTMETRICS));
  388.         if (os2fonts == NULL) {
  389.             WinReleasePS(hps);
  390.             goto defaultFont;
  391.         }
  392.         /* Retrieve the fonts */
  393.         reqFonts = remFonts;
  394.         remFonts = GpiQueryFonts(hps, QF_PUBLIC, NULL, &reqFonts,
  395.                                  (LONG) sizeof(FONTMETRICS), os2fonts);
  396. #ifdef VERBOSE
  397.         printf("    got %d (%d remaining)\n", reqFonts, remFonts);
  398. #endif
  399.         caseName[0] = '\0';
  400.         for (i=0; i<reqFonts; i++) {
  401.             if ((strcmp(faPtr->family, os2fonts[i].szFacename) != 0)
  402.             && (stricmp(faPtr->family, os2fonts[i].szFacename) == 0)) {
  403.             strcpy(caseName, os2fonts[i].szFacename);
  404. #ifdef VERBOSE
  405.                 printf("    => case sensitive name [%s]\n", caseName);
  406. #endif
  407.         }
  408. #ifdef VERBOSE
  409.             printf("m%d, Em %d (nom %ddpt, lMBE %d) res %dx%d %s %s face[%s]%s, fam[%s]%s\n",
  410.                   os2fonts[i].lMatch, os2fonts[i].lEmHeight,
  411.                   os2fonts[i].sNominalPointSize, os2fonts[i].lMaxBaselineExt,
  412.                   os2fonts[i].sXDeviceRes, os2fonts[i].sYDeviceRes,
  413.                   (os2fonts[i].fsType & FM_TYPE_FIXED) ? "fix" : "prop",
  414.                   (os2fonts[i].fsDefn & FM_DEFN_OUTLINE) ? "outl" : "bmp",
  415.                   os2fonts[i].szFacename,
  416.                   (os2fonts[i].fsType & FM_TYPE_FACETRUNC) ? " (trunc()" : "",
  417.                   os2fonts[i].szFamilyname,
  418.                   (os2fonts[i].fsType & FM_TYPE_FAMTRUNC) ? " (trunc()" : "");
  419. #endif
  420.         }
  421.         ckfree((char *)os2fonts);
  422.     }
  423.  
  424.     /* Set defaults in logfont */
  425.     logfonts[lFontID].fattrs.usRecordLength = (USHORT)sizeof(FATTRS);
  426.     logfonts[lFontID].fattrs.fsSelection = (USHORT)0;
  427.     logfonts[lFontID].fattrs.lMatch = 0L;
  428.     if (faPtr->family == NULL) {
  429.         memset(logfonts[lFontID].fattrs.szFacename, '\0', FACESIZE);
  430.     } else if (caseName[0] != '\0') {
  431.         strncpy(logfonts[lFontID].fattrs.szFacename, caseName, FACESIZE);
  432.     } else {
  433.         strncpy(logfonts[lFontID].fattrs.szFacename, faPtr->family, FACESIZE);
  434.     }
  435.     logfonts[lFontID].fattrs.idRegistry = 0;    /* Unknown */
  436.     logfonts[lFontID].fattrs.usCodePage = 0;    /* Use present codepage */
  437.     logfonts[lFontID].fattrs.lMaxBaselineExt = 0L;      /* 0 for vector fonts */
  438.     logfonts[lFontID].fattrs.lAveCharWidth = 0L;        /* 0 for vector fonts */
  439.     logfonts[lFontID].fattrs.fsType = 0;
  440.     logfonts[lFontID].fattrs.fsFontUse = 0;
  441.     logfonts[lFontID].shear.x = 0;
  442.     logfonts[lFontID].shear.y = 1;      /* Upright characters by default */
  443.     /* Not necessary to set shear by default */
  444.     logfonts[lFontID].setShear = FALSE;
  445.     logfonts[lFontID].outline = FALSE;
  446.     logfonts[lFontID].fattrs.lMaxBaselineExt = 12;
  447.     /*
  448.      * A negative number for faPtr->pointsize means pixel size,
  449.      * 0 means default font size
  450.      */
  451.     if (faPtr->pointsize < 0) {
  452.         logfonts[lFontID].fattrs.lMaxBaselineExt = -(faPtr->pointsize);
  453.         logfonts[lFontID].deciPoints = 10 * PIXTOPOINT(-faPtr->pointsize);
  454. #ifdef VERBOSE
  455.         printf("pixel size %d, deciPoints %d\n",
  456.                logfonts[lFontID].fattrs.lMaxBaselineExt,
  457.                logfonts[lFontID].deciPoints);
  458. #endif
  459.     } else {
  460.         logfonts[lFontID].fattrs.lMaxBaselineExt = POINTTOPIX(faPtr->pointsize);
  461.         if (faPtr->pointsize == 0) {
  462.             logfonts[lFontID].deciPoints = 120;
  463.         } else {
  464.             logfonts[lFontID].deciPoints = 10 * faPtr->pointsize;
  465.         }
  466. #ifdef VERBOSE
  467.         printf("point size %d => pixel size %d, deciPoints %d\n",
  468.                faPtr->pointsize, logfonts[lFontID].fattrs.lMaxBaselineExt,
  469.                logfonts[lFontID].deciPoints);
  470. #endif
  471.     }
  472.  
  473.     /* Determine additional selection criteria */
  474.     /* If the name already contains "Bold" then don't specify that */
  475.     if (faPtr->weight == TK_FW_BOLD &&
  476.         (strstr(logfonts[lFontID].fattrs.szFacename, "Bold") == NULL)) {
  477.         logfonts[lFontID].fattrs.fsSelection |= FATTR_SEL_BOLD;
  478. #ifdef VERBOSE
  479.         printf("FATTR_SEL_BOLD\n");
  480. #endif
  481.     }
  482.     /* If the name already contains "Italic" then don't specify that */
  483.     if (faPtr->slant == TK_FS_ITALIC &&
  484.         (strstr(logfonts[lFontID].fattrs.szFacename, "Italic") == NULL)) {
  485.         logfonts[lFontID].fattrs.fsSelection |= FATTR_SEL_ITALIC;
  486. #ifdef VERBOSE
  487.         printf("FATTR_SEL_ITALIC\n");
  488. #endif
  489.     }
  490.     if (faPtr->underline != 0) {
  491.         logfonts[lFontID].fattrs.fsSelection |= FATTR_SEL_UNDERSCORE;
  492. #ifdef VERBOSE
  493.         printf("FATTR_SEL_UNDERSCORE\n");
  494. #endif
  495.     }
  496.     if (faPtr->overstrike != 0) {
  497.         logfonts[lFontID].fattrs.fsSelection |= FATTR_SEL_STRIKEOUT;
  498. #ifdef VERBOSE
  499.         printf("FATTR_SEL_STRIKEOUT\n");
  500. #endif
  501.     }
  502.  
  503.     /*
  504.      * Replace the standard X, Mac and Windows family names with the names that
  505.      * OS/2 likes.
  506.      */
  507.  
  508.     if ((stricmp(logfonts[lFontID].fattrs.szFacename, "Times") == 0)
  509.            || (stricmp(logfonts[lFontID].fattrs.szFacename, "New York") == 0)) {
  510.         strcpy(logfonts[lFontID].fattrs.szFacename, "Times New Roman");
  511.     } else if ((stricmp(logfonts[lFontID].fattrs.szFacename, "Courier New")== 0)
  512.             || (stricmp(logfonts[lFontID].fattrs.szFacename, "Monaco") == 0)) {
  513.         strcpy(logfonts[lFontID].fattrs.szFacename, "Courier");
  514.     } else if ((stricmp(logfonts[lFontID].fattrs.szFacename, "Arial") == 0)
  515.             || (stricmp(logfonts[lFontID].fattrs.szFacename, "Geneva") == 0)) {
  516.         strcpy(logfonts[lFontID].fattrs.szFacename, "Helvetica");
  517.     } else {
  518.         /*
  519.          * The following code suggested by Ilya Zakharevich.
  520.          * Its use is to allow font selection "in OS/2-style", like
  521.          * "10.Courier".
  522.          * Ilya's way of supplying attributes of the font is against
  523.          * the documented "pointSize.Fontname[.attr ...]" though,
  524.          * because it gives attributes between the pointsize and the
  525.          * name of the font.
  526.          * I take the "official" stance and also supply the rest of the
  527.          * font Presentation Parameters: underline, strikeout, outline.
  528.          */
  529.         int l, off = 0;
  530.         char *name = faPtr->family;
  531.  
  532.         if (name != NULL && sscanf(name, "%d.%n", &l, &off) && off > 0) {
  533.             int fields;
  534. #ifdef VERBOSE
  535.             printf("    trying Presentation Parameters-notation font\n");
  536.             printf("    d %d, n %d\n", l, off);
  537. #endif
  538.             logfonts[lFontID].fattrs.lMaxBaselineExt = POINTTOPIX(l);
  539.             logfonts[lFontID].deciPoints = l * 10;
  540.             /*
  541.             logfonts[lFontID].fattrs.lMaxBaselineExt = l;
  542.             logfonts[lFontID].deciPoints = PIXTOPOINT(l * 10);
  543.             */
  544.             name += off;
  545.             useIntended = TRUE;
  546.             /* Get the fontname out */
  547.             fields = sscanf(name, "%[^.]%n",
  548.                             (char *)&logfonts[lFontID].fattrs.szFacename, &off);
  549. #ifdef VERBOSE
  550.             printf("    sscanf returns %d, off %d\n", fields, off);
  551. #endif
  552.             if (fields==1 && strlen(name)==off) {
  553.                 /* Fontname is last part */
  554.                 l = strlen(name);
  555.                 if (l > FACESIZE - 1) {
  556.                     l = FACESIZE - 1;
  557.                 }
  558.                 strncpy(logfonts[lFontID].fattrs.szFacename, name, l);
  559. #ifdef VERBOSE
  560.                 printf("    font [%s] last part\n", name);
  561. #endif
  562.             } else {
  563. #ifdef VERBOSE
  564.                 printf("    decomposing [%s]\n", name);
  565. #endif
  566.                 /* There are attributes after the fontname */
  567.                 name += off;
  568.                 while (TRUE) {
  569.                     if (strnicmp(name, ".bold", 5) == 0) {
  570.                         logfonts[lFontID].fattrs.fsSelection |= FATTR_SEL_BOLD;
  571. #ifdef VERBOSE
  572.                         printf("    .bold -> FATTR_SEL_BOLD\n");
  573. #endif
  574.                         name += 5;
  575.                     } else if (strnicmp(name, ".italic", 7) == 0) {
  576.                         logfonts[lFontID].fattrs.fsSelection
  577.                                          |= FATTR_SEL_ITALIC;
  578. #ifdef VERBOSE
  579.                         printf("    .italic -> FATTR_SEL_ITALIC\n");
  580. #endif
  581.                         name += 7;
  582.                     } else if (strnicmp(name, ".underline", 10) == 0) {
  583.                         logfonts[lFontID].fattrs.fsSelection
  584.                                          |= FATTR_SEL_UNDERSCORE;
  585. #ifdef VERBOSE
  586.                         printf("    .underline -> FATTR_SEL_UNDERSCORE\n");
  587. #endif
  588.                         name += 10;
  589.                     } else if (strnicmp(name, ".strikeout", 10) == 0) {
  590.                         logfonts[lFontID].fattrs.fsSelection
  591.                                          |= FATTR_SEL_STRIKEOUT;
  592. #ifdef VERBOSE
  593.                         printf("    .strikeout -> FATTR_SEL_STRIKEOUT\n");
  594. #endif
  595.                         name += 10;
  596.                     } else if (strnicmp(name, ".outline", 8) == 0) {
  597.                         logfonts[lFontID].fattrs.fsSelection
  598.                                          |= FATTR_SEL_OUTLINE;
  599. #ifdef VERBOSE
  600.                         printf("    .outline -> FATTR_SEL_OUTLINE\n");
  601. #endif
  602.                         name += 8;
  603.                     } else if (*name == '.') {
  604.                         name++;
  605.                         break;
  606.                     } else {
  607.                         break;
  608.                     }
  609.                 }
  610.             }
  611.         } else if (name != NULL) {
  612.             l = strlen(name);
  613.             if (l > FACESIZE - 1) {
  614.                 l = FACESIZE - 1;
  615.             }
  616.             if (caseName[0] != '\0') {
  617.                 strncpy(logfonts[lFontID].fattrs.szFacename, caseName, l);
  618.             } else {
  619.                 strncpy(logfonts[lFontID].fattrs.szFacename, name, l);
  620.             }
  621.         }
  622.     }
  623.     /*
  624.      * If we have to use an outline font (instead of a bitmap font) that we
  625.      * ask for with an unqualified name (eg. Courier) and specifying we want
  626.      * a bold or italic font, then we can get the situation where we select
  627.      * the normal font because it comes before the bold version (eg. Courier
  628.      * outline has match 46 on my system, while Courier Bold has 47), and
  629.      * selecting the non-bold version with FATTR_SEL_BOLD doesn't give us the
  630.      * bold version. Hoping for standard specifications in normal fonts, I'll
  631.      * add " Bold" and/or " Italic" here if they're not already in the name.
  632.      */
  633.     faceLen = strlen(caseName);
  634.     if ((logfonts[lFontID].fattrs.fsSelection & FATTR_SEL_BOLD) &&
  635.         strstr(logfonts[lFontID].fattrs.szFacename, "Bold") == NULL) {
  636.         strncat(logfonts[lFontID].fattrs.szFacename, " Bold",
  637.                 FACESIZE - 1 - strlen(logfonts[lFontID].fattrs.szFacename));
  638.     }
  639.     if ((logfonts[lFontID].fattrs.fsSelection & FATTR_SEL_ITALIC) &&
  640.         strstr(logfonts[lFontID].fattrs.szFacename, "Italic") == NULL) {
  641.         strncat(logfonts[lFontID].fattrs.szFacename, " Italic",
  642.                 FACESIZE - 1 - strlen(logfonts[lFontID].fattrs.szFacename));
  643.     }
  644. #ifdef VERBOSE
  645.     printf("  trying font [%s]\n", logfonts[lFontID].fattrs.szFacename);
  646. #endif
  647.  
  648.     /* Name has now been filled in with a correct or sane value */
  649.     /* Determine number of fonts */
  650.     reqFonts = 0L;
  651.     remFonts = GpiQueryFonts(hps, QF_PUBLIC,
  652.                              logfonts[lFontID].fattrs.szFacename, &reqFonts,
  653.                              (LONG) sizeof(FONTMETRICS), NULL);
  654. #ifdef VERBOSE
  655.     printf("    nr.of fonts: %d\n", remFonts);
  656. #endif
  657.     reqFonts = remFonts;
  658.     if (reqFonts) {
  659.         /* Allocate space for the fonts */
  660.         os2fonts = (PFONTMETRICS) ckalloc(remFonts * sizeof(FONTMETRICS));
  661.         if (os2fonts == NULL) {
  662.             WinReleasePS(hps);
  663.             goto defaultFont;
  664.         }
  665.         /* Get the fonts that apply */
  666.         remFonts = GpiQueryFonts(hps, QF_PUBLIC,
  667.                                  logfonts[lFontID].fattrs.szFacename, &reqFonts,
  668.                                  (LONG) sizeof(FONTMETRICS), os2fonts);
  669. #ifdef VERBOSE
  670.         if (remFonts == GPI_ALTERROR) {
  671.             printf("    GpiQueryFonts %s ERROR %x\n", logfonts[lFontID].fattrs.szFacename,
  672.             WinGetLastError(TclOS2GetHAB()));
  673.         } else {
  674.             printf("    nr.of fonts [%s]: %d (%d remaining)\n",
  675.                    logfonts[lFontID].fattrs.szFacename, reqFonts, remFonts);
  676.         }
  677. #endif
  678.     } else {
  679.         os2fonts = NULL;
  680.     }
  681.     /*
  682.      * Determine the one that has the right size, preferring a bitmap font over
  683.      * a scalable (outline) one if it exists.
  684.      */
  685.     for (i=0; i<reqFonts && !found; i++) {
  686.         /*
  687.          * Note: scalable fonts appear to always return lEmHeight 16, so first
  688.          * check for outline, then "point size" to not match on size 16.
  689.          */
  690. #ifdef VERBOSE
  691.         printf("    trying %s font %s (%ddp, lMaxBaselineExt %d), match %d\n",
  692.                (os2fonts[i].fsDefn & FM_DEFN_OUTLINE) ? "outline" : "fixed",
  693.                os2fonts[i].szFacename, os2fonts[i].sNominalPointSize,
  694.                os2fonts[i].lMaxBaselineExt, os2fonts[i].lMatch);
  695. #endif
  696.         if (os2fonts[i].fsDefn & FM_DEFN_OUTLINE) {
  697.             /* Remember we found an outline font */
  698.             outline = i;
  699. #ifdef VERBOSE
  700.             printf("    found outline font %s, match %d\n",
  701.                    os2fonts[i].szFacename, os2fonts[i].lMatch);
  702. #endif
  703.         } else {
  704.             /* Bitmap font, check size, type, resolution */
  705.             int cerror = 0, err1;
  706.  
  707.             /*
  708.              * Note: FONTMETRICS.fsSelection can contain FM_SEL_ISO9241_TESTED,
  709.              * FATTRS.fsSelection cannot.
  710.              */
  711. #ifdef VERBOSE
  712.         printf("m%d, Em %d (nom %ddpt, lMBE %d), xR %d, yR %d, %s, %s, face[%s]%s, fam[%s]%s\n",
  713.               os2fonts[i].lMatch, os2fonts[i].lEmHeight,
  714.               os2fonts[i].sNominalPointSize, os2fonts[i].lMaxBaselineExt,
  715.               os2fonts[i].sXDeviceRes, os2fonts[i].sYDeviceRes,
  716.               (os2fonts[i].fsType & FM_TYPE_FIXED) ? "fix" : "prop",
  717.               (os2fonts[i].fsDefn & FM_DEFN_OUTLINE) ? "outl" : "bmp",
  718.               os2fonts[i].szFacename,
  719.               (os2fonts[i].fsType & FM_TYPE_FACETRUNC) ? " (trunc()" : "",
  720.               os2fonts[i].szFamilyname,
  721.               (os2fonts[i].fsType & FM_TYPE_FAMTRUNC) ? " (trunc()" : "");
  722. #endif
  723. /*
  724.             if (
  725.                 ((useIntended ? os2fonts[i].sNominalPointSize :
  726.                                 (os2fonts[i].lMaxBaselineExt * 10)) ==
  727.                        logfonts[lFontID].fattrs.lMaxBaselineExt * 10)
  728. */
  729.             /* If we need a transformable font, we *need* an outline */
  730. /*
  731.                 &&
  732.         (!(logfonts[lFontID].fattrs.fsFontUse & FATTR_FONTUSE_TRANSFORMABLE))
  733.                 &&
  734.                 (os2fonts[i].sXDeviceRes == aDevCaps[CAPS_HORIZONTAL_FONT_RES])
  735.                 &&
  736.                 (os2fonts[i].sYDeviceRes == aDevCaps[CAPS_VERTICAL_FONT_RES])
  737.                 ) {
  738.                 found = TRUE;
  739.                 match = os2fonts[i].lMatch;
  740.                 font = i;
  741. */
  742. #ifdef VERBOSE
  743.             printf("    useInt %d, os2f.sNom %d, os2f.lMBE %d, logf.lMBE %d\n",
  744.               useIntended, os2fonts[i].sNominalPointSize,
  745.               os2fonts[i].lMaxBaselineExt * 10,
  746.               logfonts[lFontID].fattrs.lMaxBaselineExt * 10);
  747. #endif
  748.             err1 = ( useIntended
  749.                      ? os2fonts[i].sNominalPointSize
  750.                      : (os2fonts[i].lMaxBaselineExt * 10))
  751.                        - logfonts[lFontID].fattrs.lMaxBaselineExt * 10;
  752.             if (err1 < 0) {
  753.                 err1 = -err1;
  754.             }
  755.             cerror = err1;
  756.             if (logfonts[lFontID].fattrs.lAveCharWidth) {
  757.                 err1 = logfonts[lFontID].fattrs.lAveCharWidth
  758.                        - os2fonts[i].lAveCharWidth;
  759.                 if (err1 < 0) {
  760.                     err1 = -err1;
  761.                 }
  762.                 cerror += err1 * 3;     /* 10/3 times cheaper */
  763.             }
  764.             if (os2fonts[i].sXDeviceRes != aDevCaps[CAPS_HORIZONTAL_FONT_RES] ||
  765.                 os2fonts[i].sYDeviceRes != aDevCaps[CAPS_VERTICAL_FONT_RES]) {
  766.                 cerror += 1;
  767.             }
  768.             if (cerror < error) {
  769.                 error = cerror;
  770.                 best = i;
  771.             }
  772.             if (cerror == 0) {
  773.                 found = TRUE;
  774.                 font = best;
  775.                 match = os2fonts[best].lMatch;
  776.             }
  777. #ifdef VERBOSE
  778.             if (found) printf("    found bitmap font %s, match %d (size %d)\n",
  779.                    os2fonts[i].szFacename, os2fonts[i].lMatch,
  780.                    os2fonts[i].lMaxBaselineExt);
  781. /*
  782.             } else { if (os2fonts[i].sNominalPointSize !=
  783.                     logfonts[lFontID].fattrs.lMaxBaselineExt * 10) {
  784.             if (os2fonts[i].sNominalPointSize !=
  785.                 logfonts[lFontID].fattrs.lMaxBaselineExt * 10) {
  786.                 printf("    height %d doesn't match required %d\n",
  787.                        os2fonts[i].sNominalPointSize,
  788.                        logfonts[lFontID].fattrs.lMaxBaselineExt * 10);
  789. */
  790.             if (os2fonts[i].lMaxBaselineExt !=
  791.                 logfonts[lFontID].fattrs.lMaxBaselineExt) {
  792.                 printf("    height %d doesn't match required %d\n",
  793.                        os2fonts[i].lMaxBaselineExt,
  794.                        logfonts[lFontID].fattrs.lMaxBaselineExt);
  795.             } else if (os2fonts[i].sXDeviceRes !=
  796.                 aDevCaps[CAPS_HORIZONTAL_FONT_RES]) {
  797.                 printf("    hor. device res %d doesn't match required %d\n",
  798.                        os2fonts[i].sXDeviceRes,
  799.                        aDevCaps[CAPS_HORIZONTAL_FONT_RES]);
  800.             } else if (os2fonts[i].sYDeviceRes !=
  801.                 aDevCaps[CAPS_VERTICAL_FONT_RES]) {
  802.                 printf("    vert. device res %d doesn't match required %d\n",
  803.                        os2fonts[i].sYDeviceRes,
  804.                        aDevCaps[CAPS_VERTICAL_FONT_RES]);
  805.             } else if ( logfonts[lFontID].fattrs.fsFontUse
  806.                         & FATTR_FONTUSE_TRANSFORMABLE) {
  807.                 printf("    transformations require outline font\n");
  808.             }
  809. #endif
  810.         }
  811.     }
  812.     /* If an exact bitmap for a different resolution found, take it */
  813.     if (!found && error <= 1) {
  814.         match = os2fonts[best].lMatch;
  815.         font = best;
  816.         found = TRUE;
  817.     }
  818.     /* If no bitmap but an outline found, take it */
  819.     if (!found && outline != -1) {
  820.         match = os2fonts[outline].lMatch;
  821.         font = outline;
  822.         found = TRUE;
  823.         logfonts[lFontID].outline = TRUE;
  824. #ifdef VERBOSE
  825.         printf("    using outline font %s, match %d\n",
  826.                os2fonts[font].szFacename, os2fonts[font].lMatch);
  827. #endif
  828.     }
  829.     /* If no exact bitmap but an approximate found, take it */
  830.     if (!found && best != -1) {
  831.         match = os2fonts[best].lMatch;
  832.         font = best;
  833.         found = TRUE;
  834.     }
  835.     if (!found) {
  836.         /* Select default font by making facename empty */
  837. #ifdef VERBOSE
  838.         printf("XLoadFont trying default font\n");
  839. #endif
  840.         memset(logfonts[lFontID].fattrs.szFacename, '\0', FACESIZE);
  841.         match= GpiCreateLogFont(hps, NULL, lFontID,
  842.                                 &(logfonts[lFontID].fattrs));
  843.         if (match == GPI_ERROR) {
  844.             if (os2fonts) {
  845.                 ckfree((char *)os2fonts);
  846.             }
  847.             WinReleasePS(hps);
  848.             goto defaultFont;
  849.         } else if (match == FONT_DEFAULT) {
  850.             FONTMETRICS fm;
  851.             rc= GpiQueryFontMetrics(hps, sizeof(FONTMETRICS), &fm);
  852.             if (!rc) {
  853.                 WinReleasePS(hps);
  854.                 goto defaultFont;
  855.             }
  856.             logfonts[lFontID].fattrs.lMatch = 0;
  857.             strcpy(logfonts[lFontID].fattrs.szFacename, fm.szFacename);
  858.             logfonts[lFontID].fattrs.idRegistry = fm.idRegistry;
  859.             logfonts[lFontID].fattrs.usCodePage = fm.usCodePage;
  860.             logfonts[lFontID].fattrs.lMaxBaselineExt = fm.lMaxBaselineExt;
  861.             logfonts[lFontID].fattrs.lAveCharWidth = fm.lAveCharWidth;
  862.             logfonts[lFontID].fattrs.fsType = 0;
  863.             logfonts[lFontID].fattrs.fsFontUse = 0;
  864.             goto got_it;
  865.         }
  866.     }
  867.     /* Fill in the exact font metrics if we found a font */
  868.     if (!found) {
  869.         if (os2fonts) {
  870.             ckfree((char *)os2fonts);
  871.         }
  872.         WinReleasePS(hps);
  873.         goto defaultFont;
  874.     } else {
  875.         logfonts[lFontID].fattrs.idRegistry = os2fonts[font].idRegistry;
  876.         logfonts[lFontID].fattrs.usCodePage = os2fonts[font].usCodePage;
  877.         logfonts[lFontID].fattrs.lMaxBaselineExt=os2fonts[font].lMaxBaselineExt;
  878.         logfonts[lFontID].fattrs.lAveCharWidth = os2fonts[font].lAveCharWidth;
  879.         /*
  880.          * NOTE: values for fsSelection and fsType in FONTMETRICS and FATTRS
  881.          * differ, so check for each supported value.
  882.          */
  883.         if (os2fonts[font].fsSelection & FM_SEL_ITALIC) {
  884.             logfonts[lFontID].fattrs.fsSelection |= FATTR_SEL_ITALIC;
  885.         }
  886.         if (os2fonts[font].fsSelection & FM_SEL_UNDERSCORE) {
  887.             logfonts[lFontID].fattrs.fsSelection |= FATTR_SEL_UNDERSCORE;
  888.         }
  889.         if (os2fonts[font].fsSelection & FM_SEL_OUTLINE) {
  890.             logfonts[lFontID].fattrs.fsSelection |= FATTR_SEL_OUTLINE;
  891.         }
  892.         if (os2fonts[font].fsSelection & FM_SEL_STRIKEOUT) {
  893.             logfonts[lFontID].fattrs.fsSelection |= FATTR_SEL_STRIKEOUT;
  894.         }
  895.         if (os2fonts[font].fsSelection & FM_SEL_BOLD) {
  896.             logfonts[lFontID].fattrs.fsSelection |= FATTR_SEL_BOLD;
  897.         }
  898.  
  899.         if (os2fonts[font].fsType & FM_TYPE_KERNING) {
  900.             logfonts[lFontID].fattrs.fsType |= FATTR_TYPE_KERNING;
  901.         }
  902.         if (os2fonts[font].fsType & FM_TYPE_MBCS) {
  903.             logfonts[lFontID].fattrs.fsType |= FATTR_TYPE_MBCS;
  904.         }
  905.         if (os2fonts[font].fsType & FM_TYPE_DBCS) {
  906.             logfonts[lFontID].fattrs.fsType |= FATTR_TYPE_DBCS;
  907.         }
  908.         /* Nothing to determine FATTR_TYPE_ANTIALIASED ? */
  909.         logfonts[lFontID].fattrs.fsFontUse = 0;
  910.         if (os2fonts[font].fsCapabilities & FM_CAP_NOMIX) {
  911.             logfonts[lFontID].fattrs.fsFontUse |= FATTR_FONTUSE_NOMIX;
  912.         }
  913.         if (os2fonts[font].fsDefn & FM_DEFN_OUTLINE) {
  914.             logfonts[lFontID].fattrs.fsFontUse |= FATTR_FONTUSE_OUTLINE;
  915.             /*
  916.             logfonts[lFontID].fattrs.fsFontUse |= FATTR_FONTUSE_TRANSFORMABLE;
  917.             */
  918.         }
  919.         logfonts[lFontID].fattrs.lMatch = match;
  920.         if (logfonts[lFontID].outline == TRUE) {
  921.             logfonts[lFontID].fattrs.lMaxBaselineExt = 0;
  922.             logfonts[lFontID].fattrs.lAveCharWidth = 0;
  923.         }
  924.         strcpy(logfonts[lFontID].fattrs.szFacename, os2fonts[font].szFacename);
  925. #ifdef VERBOSE
  926.         printf("    using match %d (%s)\n", match,
  927.                logfonts[lFontID].fattrs.szFacename);
  928. #endif
  929.     }
  930.  
  931. got_it:
  932.  
  933. #ifdef VERBOSE
  934.     printf("m %d len %d sel %x reg %d cp %d mbe %d acw %d sel %x tp %x fu %x\n",
  935.            logfonts[lFontID].fattrs.lMatch,
  936.            logfonts[lFontID].fattrs.usRecordLength,
  937.            logfonts[lFontID].fattrs.fsSelection,
  938.            logfonts[lFontID].fattrs.idRegistry,
  939.            logfonts[lFontID].fattrs.usCodePage,
  940.            logfonts[lFontID].fattrs.lMaxBaselineExt,
  941.            logfonts[lFontID].fattrs.lAveCharWidth,
  942.            logfonts[lFontID].fattrs.fsSelection,
  943.            logfonts[lFontID].fattrs.fsType, logfonts[lFontID].fattrs.fsFontUse);
  944. #endif
  945.  
  946.     rc = GpiCreateLogFont(hps, NULL, lFontID, &(logfonts[lFontID].fattrs));
  947.     WinReleasePS(hps);
  948.  
  949.     if (rc == GPI_ERROR) {
  950. #ifdef VERBOSE
  951.         printf("GpiCreateLogFont %x recL %d sel %d m %d n %s r %d cp %d lMBE %d lACW %d t %x fu %x ERROR, error %x\n",
  952.                hps, logfonts[lFontID].fattrs.usRecordLength,
  953.            logfonts[lFontID].fattrs.fsSelection,
  954.            logfonts[lFontID].fattrs.lMatch,
  955.            logfonts[lFontID].fattrs.szFacename,
  956.            logfonts[lFontID].fattrs.idRegistry,
  957.            logfonts[lFontID].fattrs.usCodePage,
  958.                logfonts[lFontID].fattrs.lMaxBaselineExt,
  959.                logfonts[lFontID].fattrs.lAveCharWidth,
  960.                logfonts[lFontID].fattrs.fsType,
  961.                logfonts[lFontID].fattrs.fsFontUse,
  962.                WinGetLastError(TclOS2GetHAB()));
  963. #endif
  964.         WinReleasePS(hps);
  965.         goto defaultFont;
  966.     }
  967. #ifdef VERBOSE
  968.     printf("GpiCreateLogFont %x recL %d sel %d m %d n %s r %d cp %d lMBE %d lACW %d t %d fu %d %s (%d)\n",
  969.            hps, logfonts[lFontID].fattrs.usRecordLength,
  970.        logfonts[lFontID].fattrs.fsSelection,
  971.        logfonts[lFontID].fattrs.lMatch,
  972.        logfonts[lFontID].fattrs.szFacename,
  973.        logfonts[lFontID].fattrs.idRegistry,
  974.        logfonts[lFontID].fattrs.usCodePage,
  975.            logfonts[lFontID].fattrs.lMaxBaselineExt,
  976.            logfonts[lFontID].fattrs.lAveCharWidth,
  977.            logfonts[lFontID].fattrs.fsType,
  978.            logfonts[lFontID].fattrs.fsFontUse,
  979.            rc == FONT_MATCH ? "FONT_MATCH"
  980.                             : (rc == FONT_DEFAULT ? "FONT_DEFAULT" : "??"), rc);
  981. #endif
  982.  
  983.     tkFont = AllocFont(tkFontPtr, tkwin, lFontID);
  984.     if (tkFont != NULL) {
  985.         nextLogicalFont++;
  986.         return tkFont;
  987.     }
  988.  
  989.     
  990.     /* We have to return some font in case of an error */
  991. defaultFont:
  992.     window = Tk_WindowId(((TkWindow *) tkwin)->mainPtr->winPtr);
  993.     hwnd = (window == None) ? HWND_DESKTOP : TkOS2GetHWND(window);
  994.     hps = WinGetPS(hwnd);
  995.  
  996.     /* Set defaults in logfont */
  997.     logfonts[lFontID].fattrs.usRecordLength = (USHORT)sizeof(FATTRS);
  998.     logfonts[lFontID].fattrs.fsSelection = (USHORT)0;
  999.     logfonts[lFontID].fattrs.lMatch = 0L;
  1000.     memset(logfonts[lFontID].fattrs.szFacename, '\0', FACESIZE);
  1001.     logfonts[lFontID].fattrs.idRegistry = 0;    /* Unknown */
  1002.     logfonts[lFontID].fattrs.usCodePage = 0;    /* Use present codepage */
  1003.     logfonts[lFontID].fattrs.lMaxBaselineExt = 0L;      /* 0 for vector fonts */
  1004.     logfonts[lFontID].fattrs.lAveCharWidth = 0L;        /* 0 for vector fonts */
  1005.     logfonts[lFontID].fattrs.fsType = 0;
  1006.     logfonts[lFontID].fattrs.fsFontUse = 0;
  1007.     logfonts[lFontID].shear.x = 0;
  1008.     logfonts[lFontID].shear.y = 1;
  1009.     logfonts[lFontID].setShear = FALSE;
  1010.     logfonts[lFontID].outline = FALSE;
  1011.     logfonts[lFontID].deciPoints = 120;
  1012.     logfonts[lFontID].fattrs.lMaxBaselineExt = 12;
  1013.     match= GpiCreateLogFont(hps, NULL, lFontID, &(logfonts[lFontID].fattrs));
  1014.     WinReleasePS(hps);
  1015.  
  1016.     tkFont = AllocFont(tkFontPtr, tkwin, lFontID);
  1017.     return tkFont;
  1018. }
  1019.  
  1020. /*
  1021.  *---------------------------------------------------------------------------
  1022.  *
  1023.  * TkpDeleteFont --
  1024.  *
  1025.  *      Called to release a font allocated by TkpGetNativeFont() or
  1026.  *      TkpGetFontFromAttributes().  The caller should have already
  1027.  *      released the fields of the TkFont that are used exclusively by
  1028.  *      the generic TkFont code.
  1029.  *
  1030.  * Results:
  1031.  *      None.
  1032.  *
  1033.  * Side effects:
  1034.  *      TkFont is deallocated.
  1035.  *
  1036.  *---------------------------------------------------------------------------
  1037.  */
  1038.  
  1039. void
  1040. TkpDeleteFont(tkFontPtr)
  1041.     TkFont *tkFontPtr;          /* Token of font to be deleted. */
  1042. {
  1043.     HPS hps;
  1044.     OS2Font *fontPtr;
  1045.  
  1046.     fontPtr = (OS2Font *) tkFontPtr;
  1047.     hps = WinGetPS(fontPtr->hwnd);
  1048.     GpiDeleteSetId(hps, fontPtr->fontID);
  1049.     WinReleasePS(hps);
  1050.     ckfree((char *) fontPtr);
  1051. }
  1052.  
  1053. /*
  1054.  *---------------------------------------------------------------------------
  1055.  *
  1056.  * TkpGetFontFamilies --
  1057.  *
  1058.  *      Return information about the font families that are available
  1059.  *      on the display of the given window.
  1060.  *
  1061.  * Results:
  1062.  *      interp->result is modified to hold a list of all the available
  1063.  *      font families.
  1064.  *
  1065.  * Side effects:
  1066.  *      None.
  1067.  *
  1068.  *---------------------------------------------------------------------------
  1069.  */
  1070.  
  1071. void
  1072. TkpGetFontFamilies(interp, tkwin)
  1073.     Tcl_Interp *interp;         /* Interp to hold result. */
  1074.     Tk_Window tkwin;            /* For display to query. */
  1075. {
  1076.     Window window;
  1077.     HWND hwnd;
  1078.     HPS hps;
  1079.     PFONTMETRICS os2fonts;
  1080.     LONG reqFonts, remFonts;
  1081.     int i;
  1082.  
  1083.     window = Tk_WindowId(tkwin);
  1084.     hwnd = (window == (Window) NULL) ? HWND_DESKTOP : TkOS2GetHWND(window);
  1085.  
  1086.     hps = WinGetPS(hwnd);
  1087.  
  1088.     /* Determine total number of fonts */
  1089.     reqFonts = 0L;
  1090.     remFonts = GpiQueryFonts(hps, QF_PUBLIC, NULL, &reqFonts,
  1091.                              (LONG) sizeof(FONTMETRICS), NULL);
  1092. #ifdef VERBOSE
  1093.     printf("TkpGetFontFamilies, nr.of fonts: %d\n", remFonts);
  1094. #endif
  1095.  
  1096.     /* Allocate space for the fonts */
  1097.     os2fonts = (PFONTMETRICS) ckalloc(remFonts * sizeof(FONTMETRICS));
  1098.     if (os2fonts == NULL) {
  1099.         return;
  1100.     }
  1101.  
  1102.     /* Retrieve the fonts */
  1103.     reqFonts = remFonts;
  1104.     remFonts = GpiQueryFonts(hps, QF_PUBLIC, NULL, &reqFonts,
  1105.                              (LONG) sizeof(FONTMETRICS), os2fonts);
  1106. #ifdef VERBOSE
  1107.     printf("    got %d (%d remaining)\n", reqFonts, remFonts);
  1108. #endif
  1109.     for (i=0; i<reqFonts; i++) {
  1110. #ifdef VERBOSE
  1111.         printf("m%d, Em %d, nom %ddpt, lMBE %d, res %dx%d, %s, %s, face[%s]%s, fam[%s]%s\n",
  1112.               os2fonts[i].lMatch, os2fonts[i].lEmHeight,
  1113.               os2fonts[i].sNominalPointSize, os2fonts[i].lMaxBaselineExt,
  1114.               os2fonts[i].sXDeviceRes, os2fonts[i].sYDeviceRes,
  1115.               (os2fonts[i].fsType & FM_TYPE_FIXED) ? "fix" : "prop",
  1116.               (os2fonts[i].fsDefn & FM_DEFN_OUTLINE) ? "outl" : "bmp",
  1117.               os2fonts[i].szFacename,
  1118.               (os2fonts[i].fsType & FM_TYPE_FACETRUNC) ? " (trunc()" : "",
  1119.               os2fonts[i].szFamilyname,
  1120.               (os2fonts[i].fsType & FM_TYPE_FAMTRUNC) ? " (trunc()" : "");
  1121. #endif
  1122.     if (os2fonts[i].fsType & FM_TYPE_FAMTRUNC) {
  1123.             char fullName[MAX_FLEN];
  1124.         rc = WinQueryAtomName(WinQuerySystemAtomTable(),
  1125.                                   os2fonts[i].FaceNameAtom, (PSZ)&fullName,
  1126.                                   MAX_FLEN);
  1127.             if (rc != 0) {
  1128. #ifdef VERBOSE
  1129.                 printf("WinQueryAtomName OK: %s\n", fullName);
  1130. #endif
  1131.                 if (rc >= 256) {
  1132.                     fullName[255] = '\0';
  1133.                 }
  1134.                 Tcl_AppendElement(interp, fullName);
  1135.             } else {
  1136. #ifdef VERBOSE
  1137.                 printf("WinQueryAtomName ERROR %d\n",
  1138.                        WinGetLastError(TclOS2GetHAB()));
  1139. #endif
  1140.                 Tcl_AppendElement(interp, os2fonts[i].szFamilyname);
  1141.             }
  1142.     } else {
  1143.             Tcl_AppendElement(interp, os2fonts[i].szFamilyname);
  1144.     }
  1145.     }
  1146.     ckfree((char *)os2fonts);
  1147.  
  1148.     WinReleasePS(hps);
  1149. }
  1150.  
  1151. /*
  1152.  *---------------------------------------------------------------------------
  1153.  *
  1154.  *  Tk_MeasureChars --
  1155.  *
  1156.  *      Determine the number of characters from the string that will fit
  1157.  *      in the given horizontal span.  The measurement is done under the
  1158.  *      assumption that Tk_DrawChars() will be used to actually display
  1159.  *      the characters.
  1160.  *
  1161.  * Results:
  1162.  *      The return value is the number of characters from source that
  1163.  *      fit into the span that extends from 0 to maxLength.  *lengthPtr is
  1164.  *      filled with the x-coordinate of the right edge of the last
  1165.  *      character that did fit.
  1166.  *
  1167.  * Side effects:
  1168.  *      None.
  1169.  *
  1170.  *---------------------------------------------------------------------------
  1171.  */
  1172. int
  1173. Tk_MeasureChars(tkfont, source, numChars, maxLength, flags, lengthPtr)
  1174.     Tk_Font tkfont;             /* Font in which characters will be drawn. */
  1175.     CONST char *source;         /* Characters to be displayed.  Need not be
  1176.                                  * '\0' terminated. */
  1177.     int numChars;               /* Maximum number of characters to consider
  1178.                                  * from source string. */
  1179.     int maxLength;              /* If > 0, maxLength specifies the longest
  1180.                                  * permissible line length; don't consider any
  1181.                                  * character that would cross this
  1182.                                  * x-position.  If <= 0, then line length is
  1183.                                  * unbounded and the flags argument is
  1184.                                  * ignored. */
  1185.     int flags;                  /* Various flag bits OR-ed together:
  1186.                                  * TK_PARTIAL_OK means include the last char
  1187.                                  * which only partially fit on this line.
  1188.                                  * TK_WHOLE_WORDS means stop on a word
  1189.                                  * boundary, if possible.
  1190.                                  * TK_AT_LEAST_ONE means return at least one
  1191.                                  * character even if no characters fit. */
  1192.     int *lengthPtr;             /* Filled with x-location just after the
  1193.                                  * terminating character. */
  1194. {
  1195.     OS2Font *fontPtr;
  1196.     HPS hps;
  1197.     LONG oldFont;
  1198.     POINTL aSize[TXTBOX_COUNT];
  1199.     int curX = 0, curIdx = 0;
  1200.     int l, tmpNumChars;
  1201.     char *str;
  1202.  
  1203.     fontPtr = (OS2Font *) tkfont;
  1204.  
  1205. #ifdef VERBOSE
  1206.     printf("Tk_MeasureChars [%s] (%d), maxLength %d, font ID [%d]\n", source,
  1207.            numChars, maxLength, fontPtr->fontID);
  1208. #endif
  1209.  
  1210.     hps = WinGetPS(fontPtr->hwnd);
  1211.     oldFont = GpiQueryCharSet(hps);
  1212.     rc = GpiCreateLogFont(hps, NULL, fontPtr->fontID,
  1213.                           &logfonts[fontPtr->fontID].fattrs);
  1214. #ifdef VERBOSE
  1215.     if (rc == GPI_ERROR) {
  1216.         printf("    GpiCreateLogFont %s hps %x, id %d (match %d) ERROR %x\n",
  1217.            logfonts[fontPtr->fontID].fattrs.szFacename, hps,
  1218.            fontPtr->fontID, logfonts[fontPtr->fontID].fattrs.lMatch,
  1219.            WinGetLastError(TclOS2GetHAB()));
  1220.     } else {
  1221.         printf("    GpiCreateLogFont %s hps %x, id %d (match %d) OK: %d\n",
  1222.            logfonts[fontPtr->fontID].fattrs.szFacename, hps,
  1223.            fontPtr->fontID, logfonts[fontPtr->fontID].fattrs.lMatch, rc);
  1224.     }
  1225. #endif
  1226.     GpiSetCharSet(hps, fontPtr->fontID);
  1227.     /* If this is an outline font, set the char box */
  1228.     if (logfonts[fontPtr->fontID].outline) {
  1229. #ifdef VERBOSE
  1230.         SIZEF charBox;
  1231. #endif
  1232.         rc = TkOS2ScaleFont(hps, logfonts[fontPtr->fontID].deciPoints, 0);
  1233. #ifdef VERBOSE
  1234.         if (rc!=TRUE) {
  1235.             printf("TkOS2ScaleFont %d ERROR %x\n",
  1236.                    logfonts[fontPtr->fontID].deciPoints,
  1237.                    WinGetLastError(TclOS2GetHAB()));
  1238.         } else {
  1239.             printf("TkOS2ScaleFont %d OK\n",
  1240.                    logfonts[fontPtr->fontID].deciPoints);
  1241.         }
  1242.         rc = GpiQueryCharBox(hps, &charBox);
  1243.         if (rc!=TRUE) {
  1244.             printf("GpiQueryCharBox ERROR %x\n");
  1245.         } else {
  1246.             printf("GpiQueryCharBox OK: now cx %d (%d,%d), cy %d (%d,%d)\n",
  1247.                    charBox.cx, FIXEDINT(charBox.cx), FIXEDFRAC(charBox.cx),
  1248.                    charBox.cy, FIXEDINT(charBox.cy), FIXEDFRAC(charBox.cy));
  1249.         }
  1250. #endif
  1251.     }
  1252.  
  1253.     if (numChars == 0) {
  1254.         curX = 0;
  1255.         curIdx = 0;
  1256.     } else if (maxLength <= 0) {
  1257.         /* only 512 bytes allowed in string */
  1258.         for (tmpNumChars = numChars, str = (char *)source, curX = curIdx = 0;
  1259.              tmpNumChars > 0;
  1260.              tmpNumChars -= 512, str += 512) {
  1261.             l = tmpNumChars > 512 ? 512 : tmpNumChars;
  1262.             rc = GpiQueryTextBox(hps, l, (PCH)str, TXTBOX_COUNT, aSize);
  1263. #ifdef VERBOSE
  1264.             if (rc != TRUE) {
  1265.                 printf("    GpiQueryTextBox [%s] (%d) ERROR %x\n", str, l,
  1266.                        WinGetLastError(TclOS2GetHAB()));
  1267.             } else {
  1268.                 printf("    GpiQueryTextBox [%s] (%d) OK: %d + %d\n", str, l,
  1269.                        curX,aSize[TXTBOX_CONCAT].x- aSize[TXTBOX_BOTTOMLEFT].x);
  1270.             }
  1271. #endif
  1272.             curX += aSize[TXTBOX_CONCAT].x - aSize[TXTBOX_BOTTOMLEFT].x;
  1273.             curIdx += l;
  1274.         }
  1275. #ifdef VERBOSE
  1276.         printf("    maxLength <= 0; curX %d, curIdx %d\n", curX, curIdx);
  1277. #endif
  1278.     } else {
  1279.         int localMax, max;
  1280.         int *partials;
  1281.  
  1282.         partials = (int *) ckalloc(numChars * sizeof (int));
  1283.         /*
  1284.          * For each number of chars upto numChars see if it is shorter
  1285.          * than maxLength.
  1286.          * GpiQueryTextBox (and GpiCharString*At) only allow 512 bytes in
  1287.          * string; check each chunk of 512 separately, so we don't do the
  1288.          * chunking upto numChars times.
  1289.          */
  1290.         memset((VOID *)partials, 0, numChars * sizeof (int));
  1291.         max = 0;
  1292.         for (tmpNumChars = numChars, str = (char *)source;
  1293.              tmpNumChars > 0;
  1294.              tmpNumChars -= 512, str += 512) {
  1295.             /* Check from 0 to tmpNumChars or 512 additional chars */
  1296.             l = tmpNumChars > 512 ? 512 : tmpNumChars;
  1297. #ifdef VERBOSE
  1298.             printf("tmpNumChars %d, str %x, l %d\n", tmpNumChars, str, l);
  1299. #endif
  1300.             for (localMax= 0; localMax<l; localMax++) {
  1301.                 rc = GpiQueryTextBox(hps, localMax+1, (PCH)str, TXTBOX_COUNT,
  1302.                                      aSize);
  1303.                 partials[max] += aSize[TXTBOX_CONCAT].x
  1304.                                  - aSize[TXTBOX_BOTTOMLEFT].x;
  1305. #ifdef VERBOSE
  1306.                 if (rc != TRUE) {
  1307.                     printf("GpiQueryTextBox [%s] (%d) ERROR %x\n", str,
  1308.                            localMax, WinGetLastError(TclOS2GetHAB()));
  1309.                 } else {
  1310.                     printf("GpiQueryTextBox [%s] (%d): %d partials[%d] %d\n",
  1311.                            str, localMax,
  1312.                            aSize[TXTBOX_CONCAT].x - aSize[TXTBOX_BOTTOMLEFT].x,
  1313.                            max, partials[max]);
  1314.                 }
  1315. #endif
  1316.                 if (partials[max] > maxLength) {
  1317.                     /* Stop outer loop by making tmpNumChars not > 0 */
  1318.                     tmpNumChars = -1;
  1319.                     break;
  1320.                 }
  1321.                 max++;
  1322.             }
  1323.             /* Carry present maximum forward for next chunk of 512 */
  1324.             if (max < numChars - 1) {
  1325.                 int newval = partials[max];
  1326. #ifdef VERBOSE
  1327.                 printf("memset partials+%d+1 to partials[%d] (%d) for %d\n",
  1328.                        max, max, newval, numChars - max - 1);
  1329. #endif
  1330.                 memset((VOID *)(partials+max+1), newval,
  1331.                        (numChars - max - 1) * sizeof (int));
  1332.             }
  1333.         }
  1334.  
  1335.             /* only 512 bytes allowed in string */
  1336. /*
  1337.         for (max= 0; max<numChars; max++) {
  1338.             partials[max] = 0;
  1339.             for (tmpNumChars = numChars, str = (char *)source;
  1340.                  tmpNumChars > 0;
  1341.                  tmpNumChars -= 512, str += 512) {
  1342.                 l = tmpNumChars > 512 ? 512 : tmpNumChars;
  1343.                 rc = GpiQueryTextBox(hps, l, (PCH)str, TXTBOX_COUNT, aSize);
  1344.                 partials[max] += aSize[TXTBOX_CONCAT].x
  1345.                                  - aSize[TXTBOX_BOTTOMLEFT].x;
  1346. #ifdef VERBOSE
  1347.                 if (rc != TRUE) {
  1348.                     printf("GpiQueryTextBox [%s] (%d) ERROR %x\n", str, l,
  1349.                            WinGetLastError(TclOS2GetHAB()));
  1350.                 } else {
  1351.                     printf("GpiQueryTextBox [%s] (%d): %d p[%d] %d curIdx %d\n",
  1352.                            str, l, aSize[TXTBOX_CONCAT].x
  1353.                            - aSize[TXTBOX_BOTTOMLEFT].x, partials[max], curIdx);
  1354.                 }
  1355. #endif
  1356.             }
  1357.             if (partials[max] > maxLength) {
  1358.                 break;
  1359.             }
  1360.         }
  1361. */
  1362.  
  1363.         if ((flags & TK_WHOLE_WORDS) && max < numChars) {
  1364.             int sawSpace;
  1365.             int index;
  1366.  
  1367.             sawSpace = 0;
  1368.             index = max;
  1369.             while (index >= 0 && !isspace(source[index])) {
  1370.                 --index;
  1371.             }
  1372.             while (index >= 0 && isspace(source[index])) {
  1373.                 sawSpace = 1;
  1374.                 --index;
  1375.             }
  1376.  
  1377.             /*
  1378.              * If a space char was not found, and the flag for forcing
  1379.              * at least on (or more) chars to be drawn is false, then
  1380.              * set MAX to zero so no text is drawn.  Otherwise, if a
  1381.              * space was found, set max to be one char past the space.
  1382.              */
  1383.  
  1384.             if ((index < 0) && !(flags & TK_AT_LEAST_ONE)) {
  1385.                 max = 0;
  1386.             } else if (sawSpace) {
  1387.                 max = index + 1;
  1388.             }
  1389.  
  1390.         }
  1391.  
  1392.         if (max == 0) {
  1393.             curX = 0;
  1394.         } else {
  1395.             curX = partials[max - 1];
  1396.         }
  1397.  
  1398.         if (((flags & TK_PARTIAL_OK) && max < numChars && curX < maxLength)
  1399.                 || ((flags & TK_AT_LEAST_ONE) && max == 0 && numChars > 0)) {
  1400.             /*
  1401.              * We want to include the first character that didn't
  1402.              * quite fit.  Call the function again to include the
  1403.              * width of the extra character.
  1404.              */
  1405.  
  1406.             /* only 512 bytes allowed in string */
  1407.             for (tmpNumChars = numChars, str = (char *)source;
  1408.                  tmpNumChars > 0;
  1409.                  tmpNumChars -= 512, str += 512) {
  1410.                 l = tmpNumChars > 512 ? 512 : tmpNumChars;
  1411.                 rc = GpiQueryTextBox(hps, l, (PCH)str, TXTBOX_COUNT, aSize);
  1412. #ifdef VERBOSE
  1413.                 if (rc != TRUE) {
  1414.                     printf("    GpiQueryTextBox [%s] (%d) ERROR %x\n", str, l,
  1415.                            WinGetLastError(TclOS2GetHAB()));
  1416.                 } else {
  1417.                     printf("    GpiQueryTextBox [%s] (%d) OK %d + %d\n", str, l,
  1418.                            curX, aSize[TXTBOX_CONCAT].x
  1419.                            - aSize[TXTBOX_BOTTOMLEFT].x);
  1420.                 }
  1421. #endif
  1422.                 curX += aSize[TXTBOX_CONCAT].x - aSize[TXTBOX_BOTTOMLEFT].x;
  1423.             }
  1424.             ++max;
  1425.  
  1426.         }
  1427.  
  1428.         ckfree((char *) partials);
  1429.         curIdx = max;
  1430. #ifdef VERBOSE
  1431.         printf("    curX %d, curIdx %d\n", curX, curIdx);
  1432. #endif
  1433.     }
  1434.  
  1435.     GpiSetCharSet(hps, oldFont);
  1436.     WinReleasePS(hps);
  1437.  
  1438. #ifdef VERBOSE
  1439.     printf("Tk_MeasureChars [%s] (%d), maxLength %d returns x %d (%d chars)\n",
  1440.            source, numChars, maxLength, curX, curIdx);
  1441. #endif
  1442.     *lengthPtr = curX;
  1443.     return curIdx;
  1444. }
  1445.  
  1446. /*
  1447.  *---------------------------------------------------------------------------
  1448.  *
  1449.  * Tk_DrawChars --
  1450.  *
  1451.  *      Draw a string of characters on the screen.
  1452.  *
  1453.  * Results:
  1454.  *      None.
  1455.  *
  1456.  * Side effects:
  1457.  *      Information gets drawn on the screen.
  1458.  *
  1459.  *---------------------------------------------------------------------------
  1460.  */
  1461.  
  1462. void
  1463. Tk_DrawChars(display, drawable, gc, tkfont, source, numChars, x, y)
  1464.     Display *display;           /* Display on which to draw. */
  1465.     Drawable drawable;          /* Window or pixmap in which to draw. */
  1466.     GC gc;                      /* Graphics context for drawing characters. */
  1467.     Tk_Font tkfont;             /* Font in which characters will be drawn;
  1468.                                  * must be the same as font used in GC. */
  1469.     CONST char *source;         /* Characters to be displayed.  Need not be
  1470.                                  * '\0' terminated.  All Tk meta-characters
  1471.                                  * (tabs, control characters, and newlines)
  1472.                                  * should be stripped out of the string that
  1473.                                  * is passed to this function.  If they are
  1474.                                  * not stripped out, they will be displayed as
  1475.                                  * regular printing characters. */
  1476.     int numChars;               /* Number of characters in string. */
  1477.     int x, y;                   /* Coordinates at which to place origin of
  1478.                                  * string when drawing. */
  1479. {
  1480.     HPS hps;
  1481.     LONG oldFont = 0L;
  1482.     LONG oldHorAlign, oldVerAlign;
  1483.     LONG oldBackMix;
  1484.     LONG oldColor, oldBackColor = 0L;
  1485.     POINTL oldRefPoint;
  1486.     LONG oldPattern;
  1487.     HBITMAP oldBitmap;
  1488.     POINTL aPoints[3]; /* Lower-left, upper-right, lower-left source */
  1489.     CHARBUNDLE cBundle;
  1490.     LONG windowHeight;
  1491.     int l, tmpNumChars;
  1492.     char *str;
  1493.     POINTL refPoint;
  1494.     TkOS2PSState state;
  1495.     OS2Font *fontPtr;
  1496.  
  1497.     fontPtr = (OS2Font *) gc->font;
  1498.     display->request++;
  1499.  
  1500.     if (drawable == None) {
  1501.         return;
  1502.     }
  1503.  
  1504. #ifdef VERBOSE
  1505.     printf("Tk_DrawChars [%s] (%d) at (%d,%d) font [%d], GC %x (fs %s, s %x)\n",
  1506.            source, numChars, x, y, fontPtr->fontID, gc,
  1507.            gc->fill_style == FillStippled ? "FillStippled" :
  1508.            (gc->fill_style == FillOpaqueStippled ? "FillOpaqueStippled" :
  1509.            (gc->fill_style == FillSolid ? "FillSolid" :
  1510.            (gc->fill_style == FillTiled ? "FillTiled" : "UNKNOWN"))));
  1511. #endif
  1512.  
  1513.     hps = TkOS2GetDrawablePS(display, drawable, &state);
  1514.  
  1515.     GpiSetMix(hps, tkpOS2MixModes[gc->function]);
  1516.  
  1517.     /*
  1518.      * Translate the Y coordinates to PM coordinates.
  1519.      * X Window System y-coordinate is the position of the baseline like
  1520.      * in PM, so we don't have to take the height of the characters into
  1521.      * consideration.
  1522.      */
  1523.     windowHeight = TkOS2WindowHeight((TkOS2Drawable *)drawable);
  1524. #ifdef VERBOSE
  1525.     printf("    x %d, y %d (PM: %d)\n", x, y, windowHeight - y);
  1526. #endif
  1527.     y = windowHeight - y;
  1528.  
  1529.     if ((gc->fill_style == FillStippled
  1530.             || gc->fill_style == FillOpaqueStippled)
  1531.             && (gc->stipple != None)) {
  1532.  
  1533.         TkOS2Drawable *todPtr = (TkOS2Drawable *)gc->stipple;
  1534.         HDC dcMem;
  1535.         HPS psMem;
  1536.         DEVOPENSTRUC dop = {0L, (PSZ)"DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
  1537.         SIZEL sizl = {0,0}; /* use same page size as device */
  1538.         HBITMAP bitmap;
  1539.         BITMAPINFOHEADER2 bmpInfo;
  1540.         RECTL rect;
  1541.         POINTL textBox[TXTBOX_COUNT];
  1542.  
  1543. #ifdef VERBOSE
  1544.        printf("Tk_DrawChars stippled \"%s\" (%x) at %d,%d fg %d bg %d bmp %x\n",
  1545.               source, gc->stipple, x, y, gc->foreground, gc->background,
  1546.               todPtr->bitmap.handle);
  1547. #endif
  1548.  
  1549.         if (todPtr->type != TOD_BITMAP) {
  1550.             panic("unexpected drawable type in stipple");
  1551.         }
  1552.  
  1553.         /*
  1554.          * Select stipple pattern into destination PS.
  1555.          * gc->ts_x_origin and y_origin are relative to origin of the
  1556.          * destination drawable, while PatternRefPoint is in world coords.
  1557.          */
  1558.  
  1559.         dcMem = DevOpenDC(TclOS2GetHAB(), OD_MEMORY, (PSZ)"*", 5L,
  1560.                           (PDEVOPENDATA)&dop, NULLHANDLE);
  1561.         if (dcMem == DEV_ERROR) {
  1562. #ifdef VERBOSE
  1563.             printf("DevOpenDC ERROR %x in Tk_DrawChars\n",
  1564.                    WinGetLastError(TclOS2GetHAB()));
  1565. #endif
  1566.             return;
  1567.         }
  1568. #ifdef VERBOSE
  1569.         printf("DevOpenDC in Tk_DrawChars returns %x\n", dcMem);
  1570. #endif
  1571.         psMem = GpiCreatePS(TclOS2GetHAB(), dcMem, &sizl,
  1572.                             PU_PELS | GPIT_NORMAL | GPIA_ASSOC);
  1573.         if (psMem == GPI_ERROR) {
  1574. #ifdef VERBOSE
  1575.             printf("GpiCreatePS ERROR %x in Tk_DrawChars\n",
  1576.                    WinGetLastError(TclOS2GetHAB()));
  1577. #endif
  1578.             DevCloseDC(dcMem);
  1579.             return;
  1580.         }
  1581. #ifdef VERBOSE
  1582.         printf("GpiCreatePS in Tk_DrawChars returns %x\n", psMem);
  1583. #endif
  1584.  
  1585.         /*
  1586.          * Compute the bounding box and create a compatible bitmap.
  1587.          */
  1588.  
  1589.         rc = WinQueryWindowRect(((TkOS2Drawable *)drawable)->bitmap.parent,
  1590.                             &rect);
  1591. #ifdef VERBOSE
  1592.         if (rc != TRUE) {
  1593.             printf("WinQueryWindowRect ERROR %x\n",
  1594.                    WinGetLastError(TclOS2GetHAB()));
  1595.         } else {
  1596.             printf("WinQueryWindowRect OK %d,%d->%d,%d\n", rect.xLeft,
  1597.                    rect.yBottom, rect.xRight, rect.yTop);
  1598.         }
  1599. #endif
  1600.         bmpInfo.cbFix = 16L;
  1601.         /*
  1602.         bmpInfo.cx = rect.xRight - rect.xLeft;
  1603.         bmpInfo.cy = rect.yTop - rect.yBottom;
  1604.         */
  1605.         bmpInfo.cx = xScreen;
  1606.         bmpInfo.cy = yScreen;
  1607.         bmpInfo.cPlanes = 1;
  1608.         bmpInfo.cBitCount= display->screens[display->default_screen].root_depth;
  1609.         bitmap = GpiCreateBitmap(psMem, &bmpInfo, 0L, NULL, NULL);
  1610. #ifdef VERBOSE
  1611.         if (bitmap == GPI_ERROR) {
  1612.             printf("GpiCreateBitmap (%d,%d) GPI_ERROR %x\n", bmpInfo.cx,
  1613.                    bmpInfo.cy, WinGetLastError(TclOS2GetHAB()));
  1614.         } else {
  1615.             printf("GpiCreateBitmap (%d,%d) returned %x\n", bmpInfo.cx,
  1616.                    bmpInfo.cy, bitmap);
  1617.         }
  1618. #endif
  1619.         oldBitmap = GpiSetBitmap(psMem, bitmap);
  1620. #ifdef VERBOSE
  1621.         if (bitmap == HBM_ERROR) {
  1622.             printf("GpiSetBitmap (%x) HBM_ERROR %x\n", bitmap,
  1623.                    WinGetLastError(TclOS2GetHAB()));
  1624.         } else {
  1625.             printf("GpiSetBitmap %x returned %x\n", bitmap, oldBitmap);
  1626.         }
  1627. #endif
  1628.  
  1629.         refPoint.x = gc->ts_x_origin;
  1630.         refPoint.y = windowHeight - gc->ts_y_origin;
  1631.  
  1632. #ifdef VERBOSE
  1633.         printf("gc->ts_x_origin=%d (->%d), gc->ts_y_origin=%d (->%d)\n",
  1634.                gc->ts_x_origin, refPoint.x, gc->ts_y_origin, refPoint.y);
  1635. #endif
  1636.         /* The bitmap mustn't be selected in the HPS */
  1637.         TkOS2SetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
  1638.                         refPoint.x, refPoint.y, &oldPattern, &oldRefPoint);
  1639.  
  1640.         GpiQueryTextAlignment(psMem, &oldHorAlign, &oldVerAlign);
  1641.         GpiSetTextAlignment(psMem, TA_LEFT, TA_BASE);
  1642.  
  1643.         GpiQueryAttrs(psMem, PRIM_CHAR, LBB_COLOR, (PBUNDLE)&cBundle);
  1644.         cBundle.lColor = gc->foreground;
  1645.         rc = GpiSetAttrs(psMem, PRIM_CHAR, LBB_COLOR, 0L, (PBUNDLE)&cBundle);
  1646. #ifdef VERBOSE
  1647.         if (rc!=TRUE) {
  1648.             printf("GpiSetAttrs textColor %d ERROR %x\n", cBundle.lColor,
  1649.                    WinGetLastError(TclOS2GetHAB()));
  1650.         } else {
  1651.             printf("GpiSetAttrs textColor %d OK\n", cBundle.lColor);
  1652.         }
  1653. #endif
  1654.  
  1655.         oldBackMix = GpiQueryBackMix(psMem);
  1656.         rc = GpiSetBackMix(psMem, BM_LEAVEALONE);
  1657. #ifdef VERBOSE
  1658.         if (rc!=TRUE) {
  1659.             printf("GpiSetBackMix ERROR %x\n", WinGetLastError(TclOS2GetHAB()));
  1660.         } else {
  1661.             printf("GpiSetBackMix OK\n");
  1662.         }
  1663. #endif
  1664.         oldBackColor = GpiQueryBackColor(psMem);
  1665.         GpiSetBackColor(psMem, CLR_FALSE);
  1666. #ifdef VERBOSE
  1667.         if (rc!=TRUE) {
  1668.             printf("GpiSetBackColor CLR_FALSE ERROR %x\n",
  1669.                    WinGetLastError(TclOS2GetHAB()));
  1670.         } else {
  1671.             printf("GpiSetBackColor CLR_FALSE OK\n");
  1672.         }
  1673. #endif
  1674.  
  1675.         if (fontPtr->fontID != None) {
  1676.             rc = GpiCreateLogFont(psMem, NULL, fontPtr->fontID,
  1677.                                   &(logfonts[fontPtr->fontID].fattrs));
  1678. #ifdef VERBOSE
  1679.             if (rc!=GPI_ERROR) {
  1680.                 printf("GpiCreateLogFont (%x, id %d) OK\n", psMem,
  1681.                fontPtr->fontID);
  1682.             } else {
  1683.                 printf("GpiCreateLogFont (%x, id %d) ERROR, error %x\n", psMem,
  1684.                        fontPtr->fontID, WinGetLastError(TclOS2GetHAB()));
  1685.             }
  1686. #endif
  1687.             oldFont = GpiQueryCharSet(psMem);
  1688. #ifdef VERBOSE
  1689.             if (rc==LCID_ERROR) {
  1690.                 printf("GpiQueryCharSet ERROR %x\n",
  1691.                        WinGetLastError(TclOS2GetHAB()));
  1692.             } else {
  1693.                 printf("GpiQueryCharSet OK\n");
  1694.             }
  1695. #endif
  1696.             rc = GpiSetCharSet(psMem, fontPtr->fontID);
  1697. #ifdef VERBOSE
  1698.             if (rc!=TRUE) {
  1699.                 printf("GpiSetCharSet (%x, id %d, face [%s]) ERROR, error %x\n",
  1700.                        psMem, fontPtr->fontID,
  1701.                        logfonts[fontPtr->fontID].fattrs.szFacename,
  1702.                        WinGetLastError(TclOS2GetHAB()));
  1703.             } else {
  1704.                 printf("GpiSetCharSet (%x, id %d, face [%s]) OK\n", psMem,
  1705.                        fontPtr->fontID,
  1706.                logfonts[fontPtr->fontID].fattrs.szFacename);
  1707.             }
  1708. #endif
  1709.             /* If this is an outline font, set the char box */
  1710.             if (logfonts[fontPtr->fontID].outline) {
  1711. #ifdef VERBOSE
  1712.                 SIZEF charBox;
  1713. #endif
  1714.                 rc = TkOS2ScaleFont(psMem, logfonts[fontPtr->fontID].deciPoints,
  1715.                                     0);
  1716. #ifdef VERBOSE
  1717.                 if (rc!=TRUE) {
  1718.                     printf("TkOS2ScaleFont %d ERROR %x\n",
  1719.                            logfonts[fontPtr->fontID].deciPoints,
  1720.                            WinGetLastError(TclOS2GetHAB()));
  1721.                 } else {
  1722.                     printf("TkOS2ScaleFont %d OK\n",
  1723.                            logfonts[fontPtr->fontID].deciPoints);
  1724.                 }
  1725.                 rc = GpiQueryCharBox(psMem, &charBox);
  1726.                 if (rc!=TRUE) {
  1727.                     printf("GpiQueryCharBox ERROR %x\n");
  1728.                 } else {
  1729.                     printf("GpiQueryCharBox OK: now cx %d (%d,%d), cy %d (%d,%d)\n",
  1730.                            charBox.cx, FIXEDINT(charBox.cx),
  1731.                            FIXEDFRAC(charBox.cx), charBox.cy,
  1732.                            FIXEDINT(charBox.cy), FIXEDFRAC(charBox.cy));
  1733.                 }
  1734. #endif
  1735.             }
  1736.             aPoints[0].y = -fontPtr->font.fm.descent;
  1737.         } else {
  1738.             FONTMETRICS fm;
  1739.             rc = GpiQueryFontMetrics(hps, sizeof(FONTMETRICS), &fm);
  1740.             aPoints[0].y = -fm.lMaxDescender;
  1741.             if (fm.fsDefn & FM_DEFN_OUTLINE) {
  1742.                 /* Scale the value */
  1743.                 aPoints[0].y *= fm.lEmHeight;
  1744.                 aPoints[0].y /= 12;
  1745.             }
  1746.         }
  1747.  
  1748.         refPoint.x = x;
  1749.         refPoint.y = y;
  1750.         rc = GpiSetCurrentPosition(psMem, &refPoint);
  1751. #ifdef VERBOSE
  1752.         if (rc!=TRUE) {
  1753.             printf("GpiSetCurrentPosition %d,%d ERROR %x\n", refPoint.x,
  1754.                    refPoint.y, WinGetLastError(TclOS2GetHAB()));
  1755.         } else {
  1756.             printf("GpiSetCurrentPosition %d,%d OK\n", refPoint.x, refPoint.y);
  1757.         }
  1758. #endif
  1759.         /* only 512 bytes allowed in string */
  1760.         aPoints[0].x = refPoint.x;
  1761.         aPoints[0].y += refPoint.y;
  1762.         aPoints[1].x = refPoint.x;
  1763.         aPoints[1].y = refPoint.y;
  1764.         aPoints[2].x = aPoints[0].x;
  1765.         aPoints[2].y = aPoints[0].y;
  1766.         for (tmpNumChars = numChars, str = (char *)source; tmpNumChars > 0;
  1767.              tmpNumChars -= 512, str += 512) {
  1768.             l = tmpNumChars > 512 ? 512 : tmpNumChars;
  1769.             rc = GpiQueryTextBox(psMem, l, (PCH)str, TXTBOX_COUNT, textBox);
  1770. #ifdef VERBOSE
  1771.             if (rc != TRUE) {
  1772.                 printf("GpiQueryTextBox \"%s\" (%d) ERROR %x\n", str, l,
  1773.                        WinGetLastError(TclOS2GetHAB()));
  1774.             } else {
  1775.                 printf("GpiQueryTextBox \"%s\" (%d) OK: %d, refPoint (%d,%d)\n",
  1776.                        str,  l,
  1777.                        textBox[TXTBOX_CONCAT].x - textBox[TXTBOX_BOTTOMLEFT].x,
  1778.                        refPoint.x, refPoint.y);
  1779.             }
  1780. #endif
  1781.             aPoints[1].x += textBox[TXTBOX_CONCAT].x
  1782.                             - textBox[TXTBOX_BOTTOMLEFT].x;
  1783.         }
  1784.         aPoints[1].y += textBox[TXTBOX_TOPRIGHT].y;
  1785.  
  1786. #ifdef VERBOSE
  1787.         printf("aPoints: %d,%d %d,%d <- %d,%d\n", aPoints[0].x, aPoints[0].y,
  1788.                aPoints[1].x, aPoints[1].y, aPoints[2].x, aPoints[2].y);
  1789. #endif
  1790.  
  1791.         /*
  1792.          * The following code is tricky because fonts are rendered in multiple
  1793.          * colors.  First we draw onto a black background and copy the white
  1794.          * bits.  Then we draw onto a white background and copy the black bits.
  1795.          * Both the foreground and background bits of the font are ANDed with
  1796.          * the stipple pattern as they are copied.
  1797.          */
  1798.  
  1799.         rc = GpiBitBlt(psMem, (HPS)0, 2, aPoints, ROP_ZERO, BBO_IGNORE);
  1800. #ifdef VERBOSE
  1801.         if (rc!=TRUE) {
  1802.             printf("GpiBitBlt ZERO %d,%d ERROR %x\n", aPoints[0].x,
  1803.                    aPoints[0].y, WinGetLastError(TclOS2GetHAB()));
  1804.         } else {
  1805.             printf("GpiBitBlt ZERO %d,%d OK\n", aPoints[0].x, aPoints[0].y);
  1806.         }
  1807. #endif
  1808.  
  1809.         rc = GpiSetCurrentPosition(psMem, &refPoint);
  1810. #ifdef VERBOSE
  1811.         if (rc!=TRUE) {
  1812.             printf("GpiSetCurrentPosition %d,%d ERROR %x\n", refPoint.x,
  1813.                    refPoint.y, WinGetLastError(TclOS2GetHAB()));
  1814.         } else {
  1815.             printf("GpiSetCurrentPosition %d,%d OK\n", refPoint.x, refPoint.y);
  1816.         }
  1817. #endif
  1818.         /* only 512 bytes allowed in string */
  1819.         l = numChars;
  1820.         str = (char *)source;
  1821.         while (numChars>512) {
  1822.             rc = GpiCharString(psMem, l, (PCH)str);
  1823. #ifdef VERBOSE
  1824.             if (rc==GPI_ERROR) {
  1825.                 printf("GpiCharString [%s] ERROR %x\n", str,
  1826.                        WinGetLastError(TclOS2GetHAB()));
  1827.             } else {
  1828.                 printf("GpiCharString [%s] OK\n", str);
  1829.             }
  1830. #endif
  1831.             l -= 512;
  1832.             str += 512;
  1833.         }
  1834.         rc = GpiCharString(psMem, l, (PCH)str);
  1835. #ifdef VERBOSE
  1836.         if (rc==GPI_ERROR) {
  1837.             printf("GpiCharString [%s] ERROR %x\n", str,
  1838.                    WinGetLastError(TclOS2GetHAB()));
  1839.         } else {
  1840.             printf("GpiCharString [%s] OK\n", str);
  1841.         }
  1842. #endif
  1843.  
  1844.         rc = GpiBitBlt(hps, psMem, 3, aPoints, (LONG)0x00ea, BBO_IGNORE);
  1845. #ifdef VERBOSE
  1846.         if (rc==GPI_ERROR) {
  1847.             printf("GpiBitBlt ERROR %x\n", WinGetLastError(TclOS2GetHAB()));
  1848.         } else {
  1849.             printf("GpiBitBlt OK\n");
  1850.         }
  1851. #endif
  1852.  
  1853.         rc = GpiBitBlt(psMem, (HPS)0, 2, aPoints, ROP_ONE, BBO_IGNORE);
  1854. #ifdef VERBOSE
  1855.         if (rc!=TRUE) {
  1856.             printf("GpiBitBlt ONE %d,%d ERROR %x\n", aPoints[0].x, aPoints[0].y,
  1857.                    WinGetLastError(TclOS2GetHAB()));
  1858.         } else {
  1859.             printf("GpiBitBlt ONE %d,%d OK\n", aPoints[0].x, aPoints[0].y);
  1860.         }
  1861. #endif
  1862.  
  1863.         /* only 512 bytes allowed in string */
  1864.         rc = GpiSetCurrentPosition(psMem, &refPoint);
  1865. #ifdef VERBOSE
  1866.         if (rc!=TRUE) {
  1867.             printf("GpiSetCurrentPosition %d, %d ERROR %x\n", refPoint.x,
  1868.                    refPoint.y, WinGetLastError(TclOS2GetHAB()));
  1869.         } else {
  1870.             printf("GpiSetCurrentPosition %d,%d OK\n", refPoint.x, refPoint.y);
  1871.         }
  1872. #endif
  1873.         l = numChars;
  1874.         str = (char *)source;
  1875.         while (numChars>512) {
  1876.             rc = GpiCharString(psMem, 512, (PCH)str);
  1877. #ifdef VERBOSE
  1878.         if (rc==GPI_ERROR) {
  1879.             printf("GpiCharString ERROR %x\n", WinGetLastError(TclOS2GetHAB()));
  1880.         } else {
  1881.             printf("GpiCharString OK\n");
  1882.         }
  1883. #endif
  1884.             l -= 512;
  1885.             str += 512;
  1886.         }
  1887.         rc = GpiCharString(psMem, l, (PCH)str);
  1888. #ifdef VERBOSE
  1889.         if (rc==GPI_ERROR) {
  1890.             printf("GpiCharString ERROR %x\n", WinGetLastError(TclOS2GetHAB()));
  1891.         } else {
  1892.             printf("GpiCharString OK\n");
  1893.         }
  1894. #endif
  1895.  
  1896. /*
  1897.         rc = GpiBitBlt(hps, psMem, 3, aPoints, (LONG)0x00ba, BBO_IGNORE);
  1898. */
  1899.         rc = GpiBitBlt(hps, psMem, 3, aPoints, (LONG)0x008a, BBO_IGNORE);
  1900. #ifdef VERBOSE
  1901.         if (rc==GPI_ERROR) {
  1902.             printf("GpiBitBlt ERROR %x\n", WinGetLastError(TclOS2GetHAB()));
  1903.         } else {
  1904.             printf("GpiBitBlt OK\n");
  1905.         }
  1906. #endif
  1907.         /*
  1908.          * Destroy the temporary bitmap and restore the device context.
  1909.          */
  1910.  
  1911.         GpiSetBitmap(psMem, oldBitmap);
  1912.         GpiDeleteBitmap(bitmap);
  1913.         GpiDestroyPS(psMem);
  1914.         DevCloseDC(dcMem);
  1915.  
  1916.         if (fontPtr->fontID != None) {
  1917.             rc = GpiSetCharSet(hps, oldFont);
  1918.         }
  1919.         rc = GpiSetBackMix(hps, oldBackMix);
  1920.         /* The bitmap must be reselected in the HPS */
  1921.         TkOS2UnsetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
  1922.                           oldPattern, &oldRefPoint);
  1923.  
  1924.     } else {
  1925.  
  1926.         GpiQueryTextAlignment(hps, &oldHorAlign, &oldVerAlign);
  1927.         GpiSetTextAlignment(hps, TA_LEFT, TA_BASE);
  1928.  
  1929.         GpiQueryAttrs(hps, PRIM_CHAR, LBB_COLOR, (PBUNDLE)&cBundle);
  1930.         oldColor = cBundle.lColor;
  1931.         cBundle.lColor = gc->foreground;
  1932.         rc = GpiSetAttrs(hps, PRIM_CHAR, LBB_COLOR, 0L, (PBUNDLE)&cBundle);
  1933. #ifdef VERBOSE
  1934.         if (rc!=TRUE) {
  1935.             printf("GpiSetAttrs color %x ERROR %x\n", gc->foreground,
  1936.                    WinGetLastError(TclOS2GetHAB()));
  1937.         } else {
  1938.             printf("GpiSetAttrs color %x OK\n", gc->foreground);
  1939.         }
  1940. #endif
  1941.  
  1942.         oldBackMix = GpiQueryBackMix(hps);
  1943.         GpiSetBackMix(hps, BM_LEAVEALONE);
  1944.  
  1945.         if (fontPtr->fontID != None) {
  1946.  
  1947.             rc = GpiCreateLogFont(hps, NULL, fontPtr->fontID,
  1948.                                   &(logfonts[fontPtr->fontID].fattrs));
  1949. #ifdef VERBOSE
  1950.             if (rc!=GPI_ERROR) {
  1951.                 printf("GpiCreateLogFont (%x, id %d, match %d) OK\n", hps,
  1952.                fontPtr->fontID,
  1953.                        logfonts[fontPtr->fontID].fattrs.lMatch);
  1954.             } else {
  1955.                 printf("GpiCreateLogFont (%x, id %d, match %d) ERROR %x\n", hps,
  1956.                        fontPtr->fontID, logfonts[fontPtr->fontID].fattrs.lMatch,
  1957.                        WinGetLastError(TclOS2GetHAB()));
  1958.             }
  1959. #endif
  1960.  
  1961.             oldFont = GpiQueryCharSet(hps);
  1962.             rc = GpiSetCharSet(hps, fontPtr->fontID);
  1963. #ifdef VERBOSE
  1964.             if (rc==TRUE) {
  1965.                 printf("GpiSetCharSet (%x, id %d, %s) OK\n", hps,
  1966.                fontPtr->fontID,
  1967.                        logfonts[fontPtr->fontID].fattrs.szFacename);
  1968.             } else {
  1969.                 printf("GpiSetCharSet (%x, id %d, %s) ERROR, error %x\n", hps,
  1970.                        fontPtr->fontID,
  1971.                logfonts[fontPtr->fontID].fattrs.szFacename,
  1972.                        WinGetLastError(TclOS2GetHAB()));
  1973.             }
  1974. #endif
  1975.             /* If this is an outline font, set the char box */
  1976.             if (logfonts[fontPtr->fontID].outline) {
  1977. #ifdef VERBOSE
  1978.                 SIZEF charBox;
  1979. #endif
  1980.                 rc = TkOS2ScaleFont(hps, logfonts[fontPtr->fontID].deciPoints,
  1981.                             0);
  1982. #ifdef VERBOSE
  1983.                 if (rc!=TRUE) {
  1984.                     printf("TkOS2ScaleFont %d ERROR %x\n",
  1985.                            logfonts[fontPtr->fontID].deciPoints,
  1986.                            WinGetLastError(TclOS2GetHAB()));
  1987.                 } else {
  1988.                     printf("TkOS2ScaleFont %d OK\n",
  1989.                            logfonts[fontPtr->fontID].deciPoints);
  1990.                 }
  1991.                 rc = GpiQueryCharBox(hps, &charBox);
  1992.                 if (rc!=TRUE) {
  1993.                     printf("GpiQueryCharBox ERROR %x\n");
  1994.                 } else {
  1995.                     printf("GpiQueryCharBox OK now cx%d (%d,%d) cy%d (%d,%d)\n",
  1996.                            charBox.cx, FIXEDINT(charBox.cx),
  1997.                            FIXEDFRAC(charBox.cx), charBox.cy,
  1998.                            FIXEDINT(charBox.cy), FIXEDFRAC(charBox.cy));
  1999.                 }
  2000. #endif
  2001.             }
  2002.         }
  2003.  
  2004.         refPoint.x = x;
  2005.         refPoint.y = y;
  2006.         /* only 512 bytes allowed in string */
  2007.         rc = GpiSetCurrentPosition(hps, &refPoint);
  2008. #ifdef VERBOSE
  2009.         if (rc==TRUE) {
  2010.             printf("GpiSetCurrentPosition %d,%d OK\n", refPoint.x, refPoint.y);
  2011.         } else {
  2012.             printf("GpiSetCurrentPosition %d,%d ERROR %x\n", refPoint.x,
  2013.                    refPoint.y, WinGetLastError(TclOS2GetHAB()));
  2014.         }
  2015. #endif
  2016.         l = numChars;
  2017.         str = (char *)source;
  2018.         while (l>512) {
  2019.             rc = GpiCharString(hps, 512, (PCH)str);
  2020. #ifdef VERBOSE
  2021.         if (rc==GPI_OK) {
  2022.             printf("GpiCharString returns GPI_OK\n");
  2023.         } else {
  2024.             printf("GpiCharString returns %d, ERROR %x\n", rc,
  2025.                    WinGetLastError(TclOS2GetHAB()));
  2026.         }
  2027. #endif
  2028.             l -= 512;
  2029.             str += 512;
  2030.         }
  2031.         rc = GpiCharString(hps, l, (PCH)str);
  2032. #ifdef VERBOSE
  2033.         if (rc==GPI_OK) {
  2034.             printf("GpiCharString returns GPI_OK\n");
  2035.         } else {
  2036.             printf("GpiCharString returns %d, ERROR %x\n", rc,
  2037.                    WinGetLastError(TclOS2GetHAB()));
  2038.         }
  2039. #endif
  2040.  
  2041.         rc = GpiSetCharSet(hps, LCID_DEFAULT);
  2042. #ifdef VERBOSE
  2043.         if (rc==TRUE) {
  2044.             printf("GpiSetCharSet (%x, default) OK\n", hps);
  2045.         } else {
  2046.             printf("GpiSetCharSet (%x, default) ERROR, error %x\n", hps,
  2047.                    WinGetLastError(TclOS2GetHAB()));
  2048.         }
  2049. #endif
  2050.         rc = GpiDeleteSetId(hps, fontPtr->fontID);
  2051. #ifdef VERBOSE
  2052.         if (rc==TRUE) {
  2053.             printf("GpiDeleteSetId (%x, id %d) OK\n", hps, fontPtr->fontID);
  2054.         } else {
  2055.             printf("GpiDeleteSetId (%x, id %d) ERROR, error %x\n", hps,
  2056.                    fontPtr->fontID, WinGetLastError(TclOS2GetHAB()));
  2057.         }
  2058. #endif
  2059.  
  2060.         if (fontPtr->fontID != None) {
  2061.             GpiSetCharSet(hps, oldFont);
  2062.         }
  2063.         GpiSetBackMix(hps, oldBackMix);
  2064.         GpiSetBackColor(hps, oldBackColor);
  2065.         cBundle.lColor = oldColor;
  2066.         GpiSetAttrs(hps, PRIM_CHAR, LBB_COLOR, 0L, (PBUNDLE)&cBundle);
  2067.         GpiSetTextAlignment(hps, oldHorAlign, oldVerAlign);
  2068.  
  2069.     }
  2070.  
  2071.     TkOS2ReleaseDrawablePS(drawable, hps, &state);
  2072. }
  2073.  
  2074. /*
  2075.  *---------------------------------------------------------------------------
  2076.  *
  2077.  * AllocFont --
  2078.  *
  2079.  *      Helper for TkpGetNativeFont() and TkpGetFontFromAttributes().
  2080.  *      Allocates and intializes the memory for a new TkFont that
  2081.  *      wraps the platform-specific data.
  2082.  *
  2083.  * Results:
  2084.  *      Returns pointer to newly constructed TkFont.
  2085.  *
  2086.  *      The caller is responsible for initializing the fields of the
  2087.  *      TkFont that are used exclusively by the generic TkFont code, and
  2088.  *      for releasing those fields before calling TkpDeleteFont().
  2089.  *
  2090.  * Side effects:
  2091.  *      Memory allocated.
  2092.  *
  2093.  *---------------------------------------------------------------------------
  2094.  */
  2095.  
  2096. static TkFont *
  2097. AllocFont(tkFontPtr, tkwin, fontID)
  2098.     TkFont *tkFontPtr;          /* If non-NULL, store the information in
  2099.                                  * this existing TkFont structure, rather than
  2100.                                  * allocating a new structure to hold the
  2101.                                  * font; the existing contents of the font
  2102.                                  * will be released.  If NULL, a new TkFont
  2103.                                  * structure is allocated. */
  2104.     Tk_Window tkwin;            /* For display where font will be used. */
  2105.     LONG fontID;                /* Windows information about font. */
  2106. {
  2107.     HWND hwnd;
  2108.     OS2Font *fontPtr;
  2109.     HPS hps;
  2110.     ULONG oldFont;
  2111.     FONTMETRICS fm;
  2112.     Window window;
  2113.     TkFontAttributes *faPtr;
  2114. #ifdef VERBOSE
  2115.     printf("AllocFont id %d\n", fontID);
  2116. #endif
  2117.  
  2118.     if (tkFontPtr != NULL) {
  2119.         fontPtr = (OS2Font *) tkFontPtr;
  2120.         hps = WinGetPS(fontPtr->hwnd);
  2121.         GpiDeleteSetId(hps, fontPtr->fontID);
  2122.         WinReleasePS(hps);
  2123.     } else {
  2124.         fontPtr = (OS2Font *) ckalloc(sizeof(OS2Font));
  2125.     }
  2126.  
  2127.     window = Tk_WindowId(((TkWindow *) tkwin)->mainPtr->winPtr);
  2128.     hwnd = (window == None) ? HWND_DESKTOP : TkOS2GetHWND(window);
  2129.  
  2130.     hps = WinGetPS(hwnd);
  2131.     oldFont = GpiQueryCharSet(hps);
  2132.     rc = GpiCreateLogFont(hps, NULL, fontID, &logfonts[fontID].fattrs);
  2133. #ifdef VERBOSE
  2134.     if (rc == GPI_ERROR) {
  2135.         printf("    GpiCreateLogFont %s hps %x, id %d (match %d) ERROR %x\n",
  2136.            logfonts[fontID].fattrs.szFacename, hps, fontID,
  2137.            logfonts[fontID].fattrs.lMatch, WinGetLastError(TclOS2GetHAB()));
  2138.     } else {
  2139.         printf("    GpiCreateLogFont %s hps %x, id %d (match %d) OK: %d\n",
  2140.            logfonts[fontID].fattrs.szFacename, hps, fontID,
  2141.            logfonts[fontID].fattrs.lMatch, rc);
  2142.     }
  2143. #endif
  2144.     GpiSetCharSet(hps, fontID);
  2145.  
  2146.     rc = GpiQueryFontMetrics(hps, sizeof(FONTMETRICS), &fm);
  2147.  
  2148.     fontPtr->font.fid   = (Font) fontPtr;
  2149.  
  2150.     faPtr = &fontPtr->font.fa;
  2151.     faPtr->family       = Tk_GetUid(fm.szFacename);
  2152.     faPtr->pointsize    = fm.lEmHeight;
  2153.     faPtr->weight       = (fm.usWeightClass > 5) ? TK_FW_BOLD : TK_FW_NORMAL;
  2154.     faPtr->slant        = (fm.fsSelection & FM_SEL_ITALIC) ? TK_FS_ITALIC
  2155.                                                            : TK_FS_ROMAN;
  2156.     faPtr->underline    = (fm.fsSelection & FM_SEL_UNDERSCORE) ? 1 : 0;
  2157.     faPtr->overstrike   = (fm.fsSelection & FM_SEL_STRIKEOUT) ? 1 : 0;
  2158.  
  2159.     fontPtr->font.fm.ascent     = fm.lMaxAscender;
  2160.     fontPtr->font.fm.descent    = fm.lMaxDescender;
  2161.     fontPtr->font.fm.maxWidth   = fm.lMaxCharInc;
  2162.     fontPtr->font.fm.fixed      = (fm.fsType & FM_TYPE_FIXED);
  2163.     logfonts[fontID].outline    = (fm.fsDefn & FM_DEFN_OUTLINE);
  2164.     if (logfonts[fontID].outline) {
  2165.         /* Scale the values */
  2166. #ifdef VERBOSE
  2167.         printf("Set scaling %s ascent %d->%d descent %d->%d maxWidth %d->%d\n",
  2168.                logfonts[fontID].fattrs.szFacename, fontPtr->font.fm.ascent,
  2169.                fontPtr->font.fm.ascent * logfonts[fontID].deciPoints / 120,
  2170.                fontPtr->font.fm.descent,
  2171.                fontPtr->font.fm.descent * logfonts[fontID].deciPoints / 120,
  2172.                fontPtr->font.fm.maxWidth,
  2173.                fontPtr->font.fm.maxWidth * logfonts[fontID].deciPoints / 120);
  2174. #endif
  2175.         fontPtr->font.fm.ascent     *= logfonts[fontID].deciPoints;
  2176.         fontPtr->font.fm.ascent     /= 120;
  2177.         fontPtr->font.fm.descent    *= logfonts[fontID].deciPoints;
  2178.         fontPtr->font.fm.descent    /= 120;
  2179.         fontPtr->font.fm.maxWidth   *= logfonts[fontID].deciPoints;
  2180.         fontPtr->font.fm.maxWidth   /= 120;
  2181.     }
  2182.  
  2183.     GpiSetCharSet(hps, oldFont);
  2184.     WinReleasePS(hps);
  2185.  
  2186.     fontPtr->fontID             = fontID;
  2187.     fontPtr->hwnd               = hwnd;
  2188.  
  2189.     return (TkFont *) fontPtr;
  2190. }
  2191.  
  2192. /*
  2193.  *----------------------------------------------------------------------
  2194.  *
  2195.  * TkOS2ScaleFont --
  2196.  *
  2197.  *      Adapted from "OS/2 Presentation Manager Programming" by Petzold.
  2198.  *    Called to scale a presentation space's font to a desired size.
  2199.  *
  2200.  * Results:
  2201.  *    Return true if successful.
  2202.  *
  2203.  * Side effects:
  2204.  *    Sets the character box attribute of a presentation space.
  2205.  *
  2206.  *----------------------------------------------------------------------
  2207.  */
  2208.  
  2209. BOOL
  2210. TkOS2ScaleFont(hps, pointSize, pointWidth)
  2211.     HPS hps;
  2212.     ULONG pointSize;    /* in decipixels */
  2213.     ULONG pointWidth;    /* 0 means "same as pointSize" */
  2214. {
  2215.     HDC hdc;
  2216.     LONG xRes, yRes;
  2217.     POINTL points[2];
  2218.     SIZEF sizef;
  2219.  
  2220. #ifdef VERBOSE
  2221.     printf("TkOS2ScaleFont hps %x, pointSize %d, pointWidth %d\n", hps,
  2222.            pointSize, pointWidth);
  2223.     rc = GpiQueryCharBox(hps, &sizef);
  2224.     if (rc!=TRUE) printf("GpiQueryCharBox ERROR %x\n",
  2225.                          WinGetLastError(TclOS2GetHAB()));
  2226.     else printf("GpiQueryCharBox OK: cx %d (%d,%d), cy %d (%d,%d)\n", sizef.cx,
  2227.                 FIXEDINT(sizef.cx), FIXEDFRAC(sizef.cx), sizef.cy,
  2228.                 FIXEDINT(sizef.cy), FIXEDFRAC(sizef.cy));
  2229. #endif
  2230.     /* If pointWidth defaulted, set it to pointSize */
  2231.     if (pointWidth == 0) {
  2232.         pointWidth = pointSize;
  2233.     }
  2234.  
  2235.     /* Determine device and its resolutions */
  2236.     hdc = GpiQueryDevice(hps);
  2237.     if (hdc == HDC_ERROR) {
  2238. #ifdef VERBOSE
  2239.         printf("    GpiQueryDevice ERROR %x\n",
  2240.                WinGetLastError(TclOS2GetHAB()));
  2241. #endif
  2242.         return FALSE;
  2243.     } else if (hdc == NULLHANDLE) {
  2244.         /* No device context associated, assume the screen */
  2245.         xRes = aDevCaps[CAPS_HORIZONTAL_FONT_RES];
  2246.         yRes = aDevCaps[CAPS_VERTICAL_FONT_RES];
  2247.     } else {
  2248.         rc = DevQueryCaps(hdc, CAPS_HORIZONTAL_FONT_RES, 1, &xRes);
  2249.         if (rc != TRUE) {
  2250. #ifdef VERBOSE
  2251.             printf("    DevQueryCaps xRes ERROR %x\n",
  2252.                    WinGetLastError(TclOS2GetHAB()));
  2253. #endif
  2254.             xRes = aDevCaps[CAPS_HORIZONTAL_FONT_RES];
  2255.         }
  2256.         rc = DevQueryCaps(hdc, CAPS_VERTICAL_FONT_RES, 1, &yRes);
  2257.         if (rc != TRUE) {
  2258. #ifdef VERBOSE
  2259.             printf("    DevQueryCaps yRes ERROR %x\n",
  2260.                    WinGetLastError(TclOS2GetHAB()));
  2261. #endif
  2262.             yRes = aDevCaps[CAPS_VERTICAL_FONT_RES];
  2263.         }
  2264.     }
  2265.  
  2266.     FIX_RES(xRes);
  2267.     FIX_RES(yRes);
  2268.  
  2269.     /*
  2270.      * Determine desired point size in pixels with device resolution.
  2271.      * Font resolution is returned by PM in pels per inch, device resolution
  2272.      * is in dots per inch. 722.818 decipoints in an inch.
  2273.      * Add 361.409 for correct rounding.
  2274.      */
  2275.     points[0].x = 0;
  2276.     points[0].y = 0;
  2277.     points[1].x = (xRes * pointWidth + 361.409) / 722.818;
  2278.     points[1].y = (yRes * pointSize + 361.409) / 722.818;
  2279.  
  2280.     /* Convert to page coordinates */
  2281.     rc = GpiConvert(hps, CVTC_DEVICE, CVTC_PAGE, 2L, points);
  2282. #ifdef VERBOSE
  2283.     if (rc!=TRUE) printf("GpiConvert ERROR %x\n",
  2284.                          WinGetLastError(TclOS2GetHAB()));
  2285.     else printf("GpiConvert OK: (%d,%d) -> (%d,%d)\n",
  2286.                 (aDevCaps[CAPS_HORIZONTAL_FONT_RES] * pointWidth + 360) / 720,
  2287.                 (aDevCaps[CAPS_VERTICAL_FONT_RES] * pointSize + 360) / 720,
  2288.                 points[1].x, points[1].y);
  2289. #endif
  2290.  
  2291.     /* Now set the character box */
  2292.     sizef.cx = MAKEFIXED((points[1].x - points[0].x), 0);
  2293.     sizef.cy = MAKEFIXED((points[1].y - points[0].y), 0);
  2294. #ifdef VERBOSE
  2295.     printf("after GpiConvert: cx FIXED(%d), cy FIXED(%d)\n",
  2296.            points[1].x - points[0].x, points[1].y - points[0].y);
  2297. #endif
  2298.  
  2299.     return GpiSetCharBox(hps, &sizef);
  2300. }
  2301.