/[dtapublic]/projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkwinfont.c
ViewVC logotype

Diff of /projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkwinfont.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 69 by dashley, Sat Nov 5 10:54:17 2016 UTC revision 71 by dashley, Sat Nov 5 11:07:06 2016 UTC
# Line 1  Line 1 
1  /* $Header$ */  /* $Header$ */
2    
3  /*  /*
4   * tkWinFont.c --   * tkWinFont.c --
5   *   *
6   *      Contains the Windows implementation of the platform-independant   *      Contains the Windows implementation of the platform-independant
7   *      font package interface.   *      font package interface.
8   *   *
9   * Copyright (c) 1994 Software Research Associates, Inc.   * Copyright (c) 1994 Software Research Associates, Inc.
10   * Copyright (c) 1995-1997 Sun Microsystems, Inc.   * Copyright (c) 1995-1997 Sun Microsystems, Inc.
11   * Copyright (c) 1998-1999 by Scriptics Corporation.   * Copyright (c) 1998-1999 by Scriptics Corporation.
12   *   *
13   * See the file "license.terms" for information on usage and redistribution   * See the file "license.terms" for information on usage and redistribution
14   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15   *   *
16   * RCS: @(#) $Id: tkwinfont.c,v 1.1.1.1 2001/06/13 05:13:30 dtashley Exp $   * RCS: @(#) $Id: tkwinfont.c,v 1.1.1.1 2001/06/13 05:13:30 dtashley Exp $
17   */   */
18    
19  #include "tkWinInt.h"  #include "tkWinInt.h"
20  #include "tkFont.h"  #include "tkFont.h"
21    
22  /*  /*
23   * The following structure represents a font family.  It is assumed that   * The following structure represents a font family.  It is assumed that
24   * all screen fonts constructed from the same "font family" share certain   * all screen fonts constructed from the same "font family" share certain
25   * properties; all screen fonts with the same "font family" point to a   * properties; all screen fonts with the same "font family" point to a
26   * shared instance of this structure.  The most important shared property   * shared instance of this structure.  The most important shared property
27   * is the character existence metrics, used to determine if a screen font   * is the character existence metrics, used to determine if a screen font
28   * can display a given Unicode character.   * can display a given Unicode character.
29   *   *
30   * Under Windows, a "font family" is uniquely identified by its face name.   * Under Windows, a "font family" is uniquely identified by its face name.
31   */   */
32    
33  #define FONTMAP_SHIFT       10  #define FONTMAP_SHIFT       10
34    
35  #define FONTMAP_PAGES           (1 << (sizeof(Tcl_UniChar)*8 - FONTMAP_SHIFT))  #define FONTMAP_PAGES           (1 << (sizeof(Tcl_UniChar)*8 - FONTMAP_SHIFT))
36  #define FONTMAP_BITSPERPAGE     (1 << FONTMAP_SHIFT)  #define FONTMAP_BITSPERPAGE     (1 << FONTMAP_SHIFT)
37    
38  typedef struct FontFamily {  typedef struct FontFamily {
39      struct FontFamily *nextPtr; /* Next in list of all known font families. */      struct FontFamily *nextPtr; /* Next in list of all known font families. */
40      int refCount;               /* How many SubFonts are referring to this      int refCount;               /* How many SubFonts are referring to this
41                                   * FontFamily.  When the refCount drops to                                   * FontFamily.  When the refCount drops to
42                                   * zero, this FontFamily may be freed. */                                   * zero, this FontFamily may be freed. */
43      /*      /*
44       * Key.       * Key.
45       */       */
46            
47      Tk_Uid faceName;            /* Face name key for this FontFamily. */      Tk_Uid faceName;            /* Face name key for this FontFamily. */
48    
49      /*      /*
50       * Derived properties.       * Derived properties.
51       */       */
52            
53      Tcl_Encoding encoding;      /* Encoding for this font family. */      Tcl_Encoding encoding;      /* Encoding for this font family. */
54      int isSymbolFont;           /* Non-zero if this is a symbol font. */      int isSymbolFont;           /* Non-zero if this is a symbol font. */
55      int isWideFont;             /* 1 if this is a double-byte font, 0      int isWideFont;             /* 1 if this is a double-byte font, 0
56                                   * otherwise. */                                   * otherwise. */
57      BOOL (WINAPI *textOutProc)(HDC, int, int, TCHAR *, int);      BOOL (WINAPI *textOutProc)(HDC, int, int, TCHAR *, int);
58                                  /* The procedure to use to draw text after                                  /* The procedure to use to draw text after
59                                   * it has been converted from UTF-8 to the                                   * it has been converted from UTF-8 to the
60                                   * encoding of this font. */                                   * encoding of this font. */
61      BOOL (WINAPI *getTextExtentPoint32Proc)(HDC, TCHAR *, int, LPSIZE);      BOOL (WINAPI *getTextExtentPoint32Proc)(HDC, TCHAR *, int, LPSIZE);
62                                  /* The procedure to use to measure text after                                  /* The procedure to use to measure text after
63                                   * it has been converted from UTF-8 to the                                   * it has been converted from UTF-8 to the
64                                   * encoding of this font. */                                   * encoding of this font. */
65    
66      char *fontMap[FONTMAP_PAGES];      char *fontMap[FONTMAP_PAGES];
67                                  /* Two-level sparse table used to determine                                  /* Two-level sparse table used to determine
68                                   * quickly if the specified character exists.                                   * quickly if the specified character exists.
69                                   * As characters are encountered, more pages                                   * As characters are encountered, more pages
70                                   * in this table are dynamically added.  The                                   * in this table are dynamically added.  The
71                                   * contents of each page is a bitmask                                   * contents of each page is a bitmask
72                                   * consisting of FONTMAP_BITSPERPAGE bits,                                   * consisting of FONTMAP_BITSPERPAGE bits,
73                                   * representing whether this font can be used                                   * representing whether this font can be used
74                                   * to display the given character at the                                   * to display the given character at the
75                                   * corresponding bit position.  The high bits                                   * corresponding bit position.  The high bits
76                                   * of the character are used to pick which                                   * of the character are used to pick which
77                                   * page of the table is used. */                                   * page of the table is used. */
78    
79      /*      /*
80       * Cached Truetype font info.       * Cached Truetype font info.
81       */       */
82            
83      int segCount;               /* The length of the following arrays. */      int segCount;               /* The length of the following arrays. */
84      USHORT *startCount;         /* Truetype information about the font, */      USHORT *startCount;         /* Truetype information about the font, */
85      USHORT *endCount;           /* indicating which characters this font      USHORT *endCount;           /* indicating which characters this font
86                                   * can display (malloced).  The format of                                   * can display (malloced).  The format of
87                                   * this information is (relatively) compact,                                   * this information is (relatively) compact,
88                                   * but would take longer to search than                                   * but would take longer to search than
89                                   * indexing into the fontMap[][] table. */                                   * indexing into the fontMap[][] table. */
90  } FontFamily;  } FontFamily;
91    
92  /*  /*
93   * The following structure encapsulates an individual screen font.  A font   * The following structure encapsulates an individual screen font.  A font
94   * object is made up of however many SubFonts are necessary to display a   * object is made up of however many SubFonts are necessary to display a
95   * stream of multilingual characters.   * stream of multilingual characters.
96   */   */
97    
98  typedef struct SubFont {  typedef struct SubFont {
99      char **fontMap;             /* Pointer to font map from the FontFamily,      char **fontMap;             /* Pointer to font map from the FontFamily,
100                                   * cached here to save a dereference. */                                   * cached here to save a dereference. */
101      HFONT hFont;                /* The specific screen font that will be      HFONT hFont;                /* The specific screen font that will be
102                                   * used when displaying/measuring chars                                   * used when displaying/measuring chars
103                                   * belonging to the FontFamily. */                                   * belonging to the FontFamily. */
104      FontFamily *familyPtr;      /* The FontFamily for this SubFont. */      FontFamily *familyPtr;      /* The FontFamily for this SubFont. */
105  } SubFont;  } SubFont;
106    
107  /*  /*
108   * The following structure represents Windows' implementation of a font   * The following structure represents Windows' implementation of a font
109   * object.   * object.
110   */   */
111    
112  #define SUBFONT_SPACE           3  #define SUBFONT_SPACE           3
113  #define BASE_CHARS              128  #define BASE_CHARS              128
114    
115  typedef struct WinFont {  typedef struct WinFont {
116      TkFont font;                /* Stuff used by generic font package.  Must      TkFont font;                /* Stuff used by generic font package.  Must
117                                   * be first in structure. */                                   * be first in structure. */
118      SubFont staticSubFonts[SUBFONT_SPACE];      SubFont staticSubFonts[SUBFONT_SPACE];
119                                  /* Builtin space for a limited number of                                  /* Builtin space for a limited number of
120                                   * SubFonts. */                                   * SubFonts. */
121      int numSubFonts;            /* Length of following array. */      int numSubFonts;            /* Length of following array. */
122      SubFont *subFontArray;      /* Array of SubFonts that have been loaded      SubFont *subFontArray;      /* Array of SubFonts that have been loaded
123                                   * in order to draw/measure all the characters                                   * in order to draw/measure all the characters
124                                   * encountered by this font so far.  All fonts                                   * encountered by this font so far.  All fonts
125                                   * start off with one SubFont initialized by                                   * start off with one SubFont initialized by
126                                   * AllocFont() from the original set of font                                   * AllocFont() from the original set of font
127                                   * attributes.  Usually points to                                   * attributes.  Usually points to
128                                   * staticSubFonts, but may point to malloced                                   * staticSubFonts, but may point to malloced
129                                   * space if there are lots of SubFonts. */                                   * space if there are lots of SubFonts. */
130    
131      HWND hwnd;                  /* Toplevel window of application that owns      HWND hwnd;                  /* Toplevel window of application that owns
132                                   * this font, used for getting HDC for                                   * this font, used for getting HDC for
133                                   * offscreen measurements. */                                   * offscreen measurements. */
134      int pixelSize;              /* Original pixel size used when font was      int pixelSize;              /* Original pixel size used when font was
135                                   * constructed. */                                   * constructed. */
136      int widths[BASE_CHARS];     /* Widths of first 128 chars in the base      int widths[BASE_CHARS];     /* Widths of first 128 chars in the base
137                                   * font, for handling common case.  The base                                   * font, for handling common case.  The base
138                                   * font is always used to draw characters                                   * font is always used to draw characters
139                                   * between 0x0000 and 0x007f. */                                   * between 0x0000 and 0x007f. */
140  } WinFont;  } WinFont;
141    
142  /*  /*
143   * The following structure is passed as the LPARAM when calling the font   * The following structure is passed as the LPARAM when calling the font
144   * enumeration procedure to determine if a font can support the given   * enumeration procedure to determine if a font can support the given
145   * character.   * character.
146   */   */
147    
148  typedef struct CanUse {  typedef struct CanUse {
149      HDC hdc;      HDC hdc;
150      WinFont *fontPtr;      WinFont *fontPtr;
151      Tcl_DString *nameTriedPtr;      Tcl_DString *nameTriedPtr;
152      int ch;      int ch;
153      SubFont *subFontPtr;      SubFont *subFontPtr;
154  } CanUse;  } CanUse;
155    
156  /*  /*
157   * The following structure is used to map between the Tcl strings that   * The following structure is used to map between the Tcl strings that
158   * represent the system fonts and the numbers used by Windows.   * represent the system fonts and the numbers used by Windows.
159   */   */
160    
161  static TkStateMap systemMap[] = {  static TkStateMap systemMap[] = {
162      {ANSI_FIXED_FONT,       "ansifixed"},      {ANSI_FIXED_FONT,       "ansifixed"},
163      {ANSI_VAR_FONT,         "ansi"},      {ANSI_VAR_FONT,         "ansi"},
164      {DEVICE_DEFAULT_FONT,   "device"},      {DEVICE_DEFAULT_FONT,   "device"},
165      {OEM_FIXED_FONT,        "oemfixed"},      {OEM_FIXED_FONT,        "oemfixed"},
166      {SYSTEM_FIXED_FONT,     "systemfixed"},      {SYSTEM_FIXED_FONT,     "systemfixed"},
167      {SYSTEM_FONT,           "system"},      {SYSTEM_FONT,           "system"},
168      {-1,                    NULL}      {-1,                    NULL}
169  };  };
170    
171  typedef struct ThreadSpecificData {  typedef struct ThreadSpecificData {
172      FontFamily *fontFamilyList; /* The list of font families that are      FontFamily *fontFamilyList; /* The list of font families that are
173                                   * currently loaded.  As screen fonts                                   * currently loaded.  As screen fonts
174                                   * are loaded, this list grows to hold                                   * are loaded, this list grows to hold
175                                   * information about what characters                                   * information about what characters
176                                   * exist in each font family.  */                                   * exist in each font family.  */
177      Tcl_HashTable uidTable;      Tcl_HashTable uidTable;
178  } ThreadSpecificData;  } ThreadSpecificData;
179  static Tcl_ThreadDataKey dataKey;  static Tcl_ThreadDataKey dataKey;
180    
181  /*  /*
182   * Information cached about the system at startup time.   * Information cached about the system at startup time.
183   */   */
184    
185  static Tcl_Encoding unicodeEncoding;  static Tcl_Encoding unicodeEncoding;
186  static Tcl_Encoding systemEncoding;  static Tcl_Encoding systemEncoding;
187    
188  /*  /*
189   * Procedures used only in this file.   * Procedures used only in this file.
190   */   */
191    
192  static FontFamily *     AllocFontFamily(HDC hdc, HFONT hFont, int base);  static FontFamily *     AllocFontFamily(HDC hdc, HFONT hFont, int base);
193  static SubFont *        CanUseFallback(HDC hdc, WinFont *fontPtr,  static SubFont *        CanUseFallback(HDC hdc, WinFont *fontPtr,
194                              char *fallbackName, int ch);                              char *fallbackName, int ch);
195  static SubFont *        CanUseFallbackWithAliases(HDC hdc, WinFont *fontPtr,  static SubFont *        CanUseFallbackWithAliases(HDC hdc, WinFont *fontPtr,
196                              char *faceName, int ch, Tcl_DString *nameTriedPtr);                              char *faceName, int ch, Tcl_DString *nameTriedPtr);
197  static int              FamilyExists(HDC hdc, CONST char *faceName);  static int              FamilyExists(HDC hdc, CONST char *faceName);
198  static char *           FamilyOrAliasExists(HDC hdc, CONST char *faceName);  static char *           FamilyOrAliasExists(HDC hdc, CONST char *faceName);
199  static SubFont *        FindSubFontForChar(WinFont *fontPtr, int ch);  static SubFont *        FindSubFontForChar(WinFont *fontPtr, int ch);
200  static void             FontMapInsert(SubFont *subFontPtr, int ch);  static void             FontMapInsert(SubFont *subFontPtr, int ch);
201  static void             FontMapLoadPage(SubFont *subFontPtr, int row);  static void             FontMapLoadPage(SubFont *subFontPtr, int row);
202  static int              FontMapLookup(SubFont *subFontPtr, int ch);  static int              FontMapLookup(SubFont *subFontPtr, int ch);
203  static void             FreeFontFamily(FontFamily *familyPtr);  static void             FreeFontFamily(FontFamily *familyPtr);
204  static HFONT            GetScreenFont(CONST TkFontAttributes *faPtr,  static HFONT            GetScreenFont(CONST TkFontAttributes *faPtr,
205                              CONST char *faceName, int pixelSize);                              CONST char *faceName, int pixelSize);
206  static void             InitFont(Tk_Window tkwin, HFONT hFont,  static void             InitFont(Tk_Window tkwin, HFONT hFont,
207                              int overstrike, WinFont *tkFontPtr);                              int overstrike, WinFont *tkFontPtr);
208  static void             InitSubFont(HDC hdc, HFONT hFont, int base,  static void             InitSubFont(HDC hdc, HFONT hFont, int base,
209                              SubFont *subFontPtr);                              SubFont *subFontPtr);
210  static int              LoadFontRanges(HDC hdc, HFONT hFont,  static int              LoadFontRanges(HDC hdc, HFONT hFont,
211                              USHORT **startCount, USHORT **endCount,                              USHORT **startCount, USHORT **endCount,
212                              int *symbolPtr);                              int *symbolPtr);
213  static void             MultiFontTextOut(HDC hdc, WinFont *fontPtr,  static void             MultiFontTextOut(HDC hdc, WinFont *fontPtr,
214                              CONST char *source, int numBytes, int x, int y);                              CONST char *source, int numBytes, int x, int y);
215  static void             ReleaseFont(WinFont *fontPtr);  static void             ReleaseFont(WinFont *fontPtr);
216  static void             ReleaseSubFont(SubFont *subFontPtr);  static void             ReleaseSubFont(SubFont *subFontPtr);
217  static int              SeenName(CONST char *name, Tcl_DString *dsPtr);  static int              SeenName(CONST char *name, Tcl_DString *dsPtr);
218  static void             SwapLong(PULONG p);  static void             SwapLong(PULONG p);
219  static void             SwapShort(USHORT *p);  static void             SwapShort(USHORT *p);
220  static int CALLBACK     WinFontCanUseProc(ENUMLOGFONT *lfPtr,  static int CALLBACK     WinFontCanUseProc(ENUMLOGFONT *lfPtr,
221                              NEWTEXTMETRIC *tmPtr, int fontType,                              NEWTEXTMETRIC *tmPtr, int fontType,
222                              LPARAM lParam);                              LPARAM lParam);
223  static int CALLBACK     WinFontExistProc(ENUMLOGFONT *lfPtr,  static int CALLBACK     WinFontExistProc(ENUMLOGFONT *lfPtr,
224                              NEWTEXTMETRIC *tmPtr, int fontType,                              NEWTEXTMETRIC *tmPtr, int fontType,
225                              LPARAM lParam);                              LPARAM lParam);
226  static int CALLBACK     WinFontFamilyEnumProc(ENUMLOGFONT *lfPtr,  static int CALLBACK     WinFontFamilyEnumProc(ENUMLOGFONT *lfPtr,
227                              NEWTEXTMETRIC *tmPtr, int fontType,                              NEWTEXTMETRIC *tmPtr, int fontType,
228                              LPARAM lParam);                              LPARAM lParam);
229    
230  /*  /*
231   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
232   *   *
233   * TkpFontPkgInit --   * TkpFontPkgInit --
234   *   *
235   *      This procedure is called when an application is created.  It   *      This procedure is called when an application is created.  It
236   *      initializes all the structures that are used by the   *      initializes all the structures that are used by the
237   *      platform-dependent code on a per application basis.   *      platform-dependent code on a per application basis.
238   *   *
239   * Results:   * Results:
240   *      None.     *      None.  
241   *   *
242   * Side effects:   * Side effects:
243   *         *      
244   *      None.   *      None.
245   *   *
246   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
247   */   */
248    
249  void  void
250  TkpFontPkgInit(  TkpFontPkgInit(
251      TkMainInfo *mainPtr)        /* The application being created. */      TkMainInfo *mainPtr)        /* The application being created. */
252  {  {
253      unicodeEncoding = Tcl_GetEncoding(NULL, "unicode");      unicodeEncoding = Tcl_GetEncoding(NULL, "unicode");
254      if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {      if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
255          /*          /*
256           * If running NT, then we will be calling some Unicode functions           * If running NT, then we will be calling some Unicode functions
257           * explictly.  So, even if the Tcl system encoding isn't Unicode,           * explictly.  So, even if the Tcl system encoding isn't Unicode,
258           * make sure we convert to/from the Unicode char set.           * make sure we convert to/from the Unicode char set.
259           */           */
260    
261          systemEncoding = unicodeEncoding;          systemEncoding = unicodeEncoding;
262      }      }
263  }  }
264    
265  /*  /*
266   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
267   *   *
268   * TkpGetNativeFont --   * TkpGetNativeFont --
269   *   *
270   *      Map a platform-specific native font name to a TkFont.   *      Map a platform-specific native font name to a TkFont.
271   *   *
272   * Results:   * Results:
273   *      The return value is a pointer to a TkFont that represents the   *      The return value is a pointer to a TkFont that represents the
274   *      native font.  If a native font by the given name could not be   *      native font.  If a native font by the given name could not be
275   *      found, the return value is NULL.     *      found, the return value is NULL.  
276   *   *
277   *      Every call to this procedure returns a new TkFont structure,   *      Every call to this procedure returns a new TkFont structure,
278   *      even if the name has already been seen before.  The caller should   *      even if the name has already been seen before.  The caller should
279   *      call TkpDeleteFont() when the font is no longer needed.   *      call TkpDeleteFont() when the font is no longer needed.
280   *   *
281   *      The caller is responsible for initializing the memory associated   *      The caller is responsible for initializing the memory associated
282   *      with the generic TkFont when this function returns and releasing   *      with the generic TkFont when this function returns and releasing
283   *      the contents of the generic TkFont before calling TkpDeleteFont().   *      the contents of the generic TkFont before calling TkpDeleteFont().
284   *   *
285   * Side effects:   * Side effects:
286   *      Memory allocated.   *      Memory allocated.
287   *   *
288   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
289   */   */
290    
291  TkFont *  TkFont *
292  TkpGetNativeFont(  TkpGetNativeFont(
293      Tk_Window tkwin,            /* For display where font will be used. */      Tk_Window tkwin,            /* For display where font will be used. */
294      CONST char *name)           /* Platform-specific font name. */      CONST char *name)           /* Platform-specific font name. */
295  {  {
296      int object;      int object;
297      WinFont *fontPtr;      WinFont *fontPtr;
298    
299      object = TkFindStateNum(NULL, NULL, systemMap, name);      object = TkFindStateNum(NULL, NULL, systemMap, name);
300      if (object < 0) {      if (object < 0) {
301          return NULL;          return NULL;
302      }      }
303    
304      tkwin = (Tk_Window) ((TkWindow *) tkwin)->mainPtr->winPtr;      tkwin = (Tk_Window) ((TkWindow *) tkwin)->mainPtr->winPtr;
305      fontPtr = (WinFont *) ckalloc(sizeof(WinFont));      fontPtr = (WinFont *) ckalloc(sizeof(WinFont));
306      InitFont(tkwin, GetStockObject(object), 0, fontPtr);      InitFont(tkwin, GetStockObject(object), 0, fontPtr);
307    
308      return (TkFont *) fontPtr;      return (TkFont *) fontPtr;
309  }  }
310    
311  /*  /*
312   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
313   *   *
314   * TkpGetFontFromAttributes --   * TkpGetFontFromAttributes --
315   *   *
316   *      Given a desired set of attributes for a font, find a font with   *      Given a desired set of attributes for a font, find a font with
317   *      the closest matching attributes.   *      the closest matching attributes.
318   *   *
319   * Results:   * Results:
320   *      The return value is a pointer to a TkFont that represents the   *      The return value is a pointer to a TkFont that represents the
321   *      font with the desired attributes.  If a font with the desired   *      font with the desired attributes.  If a font with the desired
322   *      attributes could not be constructed, some other font will be   *      attributes could not be constructed, some other font will be
323   *      substituted automatically.  NULL is never returned.   *      substituted automatically.  NULL is never returned.
324   *   *
325   *      Every call to this procedure returns a new TkFont structure,   *      Every call to this procedure returns a new TkFont structure,
326   *      even if the specified attributes have already been seen before.   *      even if the specified attributes have already been seen before.
327   *      The caller should call TkpDeleteFont() to free the platform-   *      The caller should call TkpDeleteFont() to free the platform-
328   *      specific data when the font is no longer needed.     *      specific data when the font is no longer needed.  
329   *   *
330   *      The caller is responsible for initializing the memory associated   *      The caller is responsible for initializing the memory associated
331   *      with the generic TkFont when this function returns and releasing   *      with the generic TkFont when this function returns and releasing
332   *      the contents of the generic TkFont before calling TkpDeleteFont().   *      the contents of the generic TkFont before calling TkpDeleteFont().
333   *   *
334   * Side effects:   * Side effects:
335   *      Memory allocated.   *      Memory allocated.
336   *   *
337   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
338   */   */
339    
340  TkFont *  TkFont *
341  TkpGetFontFromAttributes(  TkpGetFontFromAttributes(
342      TkFont *tkFontPtr,          /* If non-NULL, store the information in      TkFont *tkFontPtr,          /* If non-NULL, store the information in
343                                   * this existing TkFont structure, rather than                                   * this existing TkFont structure, rather than
344                                   * allocating a new structure to hold the                                   * allocating a new structure to hold the
345                                   * font; the existing contents of the font                                   * font; the existing contents of the font
346                                   * will be released.  If NULL, a new TkFont                                   * will be released.  If NULL, a new TkFont
347                                   * structure is allocated. */                                   * structure is allocated. */
348      Tk_Window tkwin,            /* For display where font will be used. */      Tk_Window tkwin,            /* For display where font will be used. */
349      CONST TkFontAttributes *faPtr)      CONST TkFontAttributes *faPtr)
350                                  /* Set of attributes to match. */                                  /* Set of attributes to match. */
351  {  {
352      int i, j;      int i, j;
353      HDC hdc;      HDC hdc;
354      HWND hwnd;      HWND hwnd;
355      HFONT hFont;      HFONT hFont;
356      Window window;      Window window;
357      WinFont *fontPtr;      WinFont *fontPtr;
358      char ***fontFallbacks;      char ***fontFallbacks;
359      char *faceName, *fallback, *actualName;      char *faceName, *fallback, *actualName;
360    
361      tkwin   = (Tk_Window) ((TkWindow *) tkwin)->mainPtr->winPtr;      tkwin   = (Tk_Window) ((TkWindow *) tkwin)->mainPtr->winPtr;
362      window  = Tk_WindowId(tkwin);      window  = Tk_WindowId(tkwin);
363      hwnd    = (window == None) ? NULL : TkWinGetHWND(window);      hwnd    = (window == None) ? NULL : TkWinGetHWND(window);
364      hdc     = GetDC(hwnd);      hdc     = GetDC(hwnd);
365    
366      /*      /*
367       * Algorithm to get the closest font name to the one requested.       * Algorithm to get the closest font name to the one requested.
368       *       *
369       * try fontname       * try fontname
370       * try all aliases for fontname       * try all aliases for fontname
371       * foreach fallback for fontname       * foreach fallback for fontname
372       *      try the fallback       *      try the fallback
373       *      try all aliases for the fallback       *      try all aliases for the fallback
374       */       */
375    
376      faceName = faPtr->family;      faceName = faPtr->family;
377      if (faceName != NULL) {      if (faceName != NULL) {
378          actualName = FamilyOrAliasExists(hdc, faceName);          actualName = FamilyOrAliasExists(hdc, faceName);
379          if (actualName != NULL) {          if (actualName != NULL) {
380              faceName = actualName;              faceName = actualName;
381              goto found;              goto found;
382          }          }
383          fontFallbacks = TkFontGetFallbacks();          fontFallbacks = TkFontGetFallbacks();
384          for (i = 0; fontFallbacks[i] != NULL; i++) {          for (i = 0; fontFallbacks[i] != NULL; i++) {
385              for (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) {              for (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) {
386                  if (strcasecmp(faceName, fallback) == 0) {                  if (strcasecmp(faceName, fallback) == 0) {
387                      break;                      break;
388                  }                  }
389              }              }
390              if (fallback != NULL) {              if (fallback != NULL) {
391                  for (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) {                  for (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) {
392                      actualName = FamilyOrAliasExists(hdc, fallback);                      actualName = FamilyOrAliasExists(hdc, fallback);
393                      if (actualName != NULL) {                      if (actualName != NULL) {
394                          faceName = actualName;                          faceName = actualName;
395                          goto found;                          goto found;
396                      }                      }
397                  }                  }
398              }              }
399          }          }
400      }      }
401    
402      found:      found:
403      ReleaseDC(hwnd, hdc);      ReleaseDC(hwnd, hdc);
404    
405      hFont = GetScreenFont(faPtr, faceName, TkFontGetPixels(tkwin, faPtr->size));      hFont = GetScreenFont(faPtr, faceName, TkFontGetPixels(tkwin, faPtr->size));
406      if (tkFontPtr == NULL) {      if (tkFontPtr == NULL) {
407          fontPtr = (WinFont *) ckalloc(sizeof(WinFont));          fontPtr = (WinFont *) ckalloc(sizeof(WinFont));
408      } else {      } else {
409          fontPtr = (WinFont *) tkFontPtr;          fontPtr = (WinFont *) tkFontPtr;
410          ReleaseFont(fontPtr);          ReleaseFont(fontPtr);
411      }      }
412      InitFont(tkwin, hFont, faPtr->overstrike, fontPtr);      InitFont(tkwin, hFont, faPtr->overstrike, fontPtr);
413    
414      return (TkFont *) fontPtr;      return (TkFont *) fontPtr;
415  }  }
416    
417  /*  /*
418   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
419   *   *
420   * TkpDeleteFont --   * TkpDeleteFont --
421   *   *
422   *      Called to release a font allocated by TkpGetNativeFont() or   *      Called to release a font allocated by TkpGetNativeFont() or
423   *      TkpGetFontFromAttributes().  The caller should have already   *      TkpGetFontFromAttributes().  The caller should have already
424   *      released the fields of the TkFont that are used exclusively by   *      released the fields of the TkFont that are used exclusively by
425   *      the generic TkFont code.   *      the generic TkFont code.
426   *   *
427   * Results:   * Results:
428   *      None.   *      None.
429   *   *
430   * Side effects:   * Side effects:
431   *      TkFont is deallocated.   *      TkFont is deallocated.
432   *   *
433   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
434   */   */
435    
436  void  void
437  TkpDeleteFont(  TkpDeleteFont(
438      TkFont *tkFontPtr)          /* Token of font to be deleted. */      TkFont *tkFontPtr)          /* Token of font to be deleted. */
439  {  {
440      WinFont *fontPtr;      WinFont *fontPtr;
441    
442      fontPtr = (WinFont *) tkFontPtr;      fontPtr = (WinFont *) tkFontPtr;
443      ReleaseFont(fontPtr);      ReleaseFont(fontPtr);
444  }  }
445    
446  /*  /*
447   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
448   *   *
449   * TkpGetFontFamilies, WinFontFamilyEnumProc --   * TkpGetFontFamilies, WinFontFamilyEnumProc --
450   *   *
451   *      Return information about the font families that are available   *      Return information about the font families that are available
452   *      on the display of the given window.   *      on the display of the given window.
453   *   *
454   * Results:   * Results:
455   *      Modifies interp's result object to hold a list of all the available   *      Modifies interp's result object to hold a list of all the available
456   *      font families.   *      font families.
457   *   *
458   * Side effects:   * Side effects:
459   *      None.   *      None.
460   *   *
461   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
462   */   */
463    
464  void  void
465  TkpGetFontFamilies(  TkpGetFontFamilies(
466      Tcl_Interp *interp,         /* Interp to hold result. */      Tcl_Interp *interp,         /* Interp to hold result. */
467      Tk_Window tkwin)            /* For display to query. */      Tk_Window tkwin)            /* For display to query. */
468  {      {    
469      HDC hdc;      HDC hdc;
470      HWND hwnd;      HWND hwnd;
471      Window window;      Window window;
472    
473      window  = Tk_WindowId(tkwin);      window  = Tk_WindowId(tkwin);
474      hwnd    = (window == None) ? NULL : TkWinGetHWND(window);      hwnd    = (window == None) ? NULL : TkWinGetHWND(window);
475      hdc     = GetDC(hwnd);      hdc     = GetDC(hwnd);
476    
477      /*      /*
478       * On any version NT, there may fonts with international names.         * On any version NT, there may fonts with international names.  
479       * Use the NT-only Unicode version of EnumFontFamilies to get the       * Use the NT-only Unicode version of EnumFontFamilies to get the
480       * font names.  If we used the ANSI version on a non-internationalized       * font names.  If we used the ANSI version on a non-internationalized
481       * version of NT, we would get font names with '?' replacing all       * version of NT, we would get font names with '?' replacing all
482       * the international characters.       * the international characters.
483       *       *
484       * On a non-internationalized verson of 95, fonts with international       * On a non-internationalized verson of 95, fonts with international
485       * names are not allowed, so the ANSI version of EnumFontFamilies will       * names are not allowed, so the ANSI version of EnumFontFamilies will
486       * work.  On an internationalized version of 95, there may be fonts with       * work.  On an internationalized version of 95, there may be fonts with
487       * international names; the ANSI version will work, fetching the       * international names; the ANSI version will work, fetching the
488       * name in the system code page.  Can't use the Unicode version of       * name in the system code page.  Can't use the Unicode version of
489       * EnumFontFamilies because it only exists under NT.       * EnumFontFamilies because it only exists under NT.
490       */       */
491    
492      if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {      if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
493          EnumFontFamiliesW(hdc, NULL, (FONTENUMPROCW) WinFontFamilyEnumProc,          EnumFontFamiliesW(hdc, NULL, (FONTENUMPROCW) WinFontFamilyEnumProc,
494                  (LPARAM) interp);                  (LPARAM) interp);
495      } else {      } else {
496          EnumFontFamiliesA(hdc, NULL, (FONTENUMPROCA) WinFontFamilyEnumProc,          EnumFontFamiliesA(hdc, NULL, (FONTENUMPROCA) WinFontFamilyEnumProc,
497                  (LPARAM) interp);                  (LPARAM) interp);
498      }            }      
499      ReleaseDC(hwnd, hdc);      ReleaseDC(hwnd, hdc);
500  }  }
501    
502  static int CALLBACK  static int CALLBACK
503  WinFontFamilyEnumProc(  WinFontFamilyEnumProc(
504      ENUMLOGFONT *lfPtr,         /* Logical-font data. */      ENUMLOGFONT *lfPtr,         /* Logical-font data. */
505      NEWTEXTMETRIC *tmPtr,       /* Physical-font data (not used). */      NEWTEXTMETRIC *tmPtr,       /* Physical-font data (not used). */
506      int fontType,               /* Type of font (not used). */      int fontType,               /* Type of font (not used). */
507      LPARAM lParam)              /* Result object to hold result. */      LPARAM lParam)              /* Result object to hold result. */
508  {  {
509      char *faceName;      char *faceName;
510      Tcl_DString faceString;      Tcl_DString faceString;
511      Tcl_Obj *strPtr;      Tcl_Obj *strPtr;
512      Tcl_Interp *interp;      Tcl_Interp *interp;
513    
514      interp = (Tcl_Interp *) lParam;      interp = (Tcl_Interp *) lParam;
515      faceName = lfPtr->elfLogFont.lfFaceName;      faceName = lfPtr->elfLogFont.lfFaceName;
516      Tcl_ExternalToUtfDString(systemEncoding, faceName, -1, &faceString);      Tcl_ExternalToUtfDString(systemEncoding, faceName, -1, &faceString);
517      strPtr = Tcl_NewStringObj(Tcl_DStringValue(&faceString),      strPtr = Tcl_NewStringObj(Tcl_DStringValue(&faceString),
518              Tcl_DStringLength(&faceString));              Tcl_DStringLength(&faceString));
519      Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp), strPtr);      Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp), strPtr);
520      Tcl_DStringFree(&faceString);      Tcl_DStringFree(&faceString);
521      return 1;      return 1;
522  }  }
523    
524  /*  /*
525   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
526   *   *
527   * TkpGetSubFonts --   * TkpGetSubFonts --
528   *   *
529   *      A function used by the testing package for querying the actual   *      A function used by the testing package for querying the actual
530   *      screen fonts that make up a font object.   *      screen fonts that make up a font object.
531   *   *
532   * Results:   * Results:
533   *      Modifies interp's result object to hold a list containing the   *      Modifies interp's result object to hold a list containing the
534   *      names of the screen fonts that make up the given font object.   *      names of the screen fonts that make up the given font object.
535   *   *
536   * Side effects:   * Side effects:
537   *      None.   *      None.
538   *   *
539   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
540   */   */
541                    
542  void  void
543  TkpGetSubFonts(  TkpGetSubFonts(
544      Tcl_Interp *interp,         /* Interp to hold result. */      Tcl_Interp *interp,         /* Interp to hold result. */
545      Tk_Font tkfont)             /* Font object to query. */      Tk_Font tkfont)             /* Font object to query. */
546  {  {
547      int i;      int i;
548      WinFont *fontPtr;      WinFont *fontPtr;
549      FontFamily *familyPtr;      FontFamily *familyPtr;
550      Tcl_Obj *resultPtr, *strPtr;      Tcl_Obj *resultPtr, *strPtr;
551    
552      resultPtr = Tcl_GetObjResult(interp);          resultPtr = Tcl_GetObjResult(interp);    
553      fontPtr = (WinFont *) tkfont;      fontPtr = (WinFont *) tkfont;
554      for (i = 0; i < fontPtr->numSubFonts; i++) {      for (i = 0; i < fontPtr->numSubFonts; i++) {
555          familyPtr = fontPtr->subFontArray[i].familyPtr;          familyPtr = fontPtr->subFontArray[i].familyPtr;
556          strPtr = Tcl_NewStringObj(familyPtr->faceName, -1);          strPtr = Tcl_NewStringObj(familyPtr->faceName, -1);
557          Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);          Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);
558      }      }
559  }  }
560    
561  /*  /*
562   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
563   *   *
564   *  Tk_MeasureChars --   *  Tk_MeasureChars --
565   *   *
566   *      Determine the number of bytes from the string that will fit   *      Determine the number of bytes from the string that will fit
567   *      in the given horizontal span.  The measurement is done under the   *      in the given horizontal span.  The measurement is done under the
568   *      assumption that Tk_DrawChars() will be used to actually display   *      assumption that Tk_DrawChars() will be used to actually display
569   *      the characters.   *      the characters.
570   *   *
571   * Results:   * Results:
572   *      The return value is the number of bytes from source that   *      The return value is the number of bytes from source that
573   *      fit into the span that extends from 0 to maxLength.  *lengthPtr is   *      fit into the span that extends from 0 to maxLength.  *lengthPtr is
574   *      filled with the x-coordinate of the right edge of the last   *      filled with the x-coordinate of the right edge of the last
575   *      character that did fit.   *      character that did fit.
576   *   *
577   * Side effects:   * Side effects:
578   *      None.   *      None.
579   *   *
580   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
581   */   */
582    
583  int  int
584  Tk_MeasureChars(  Tk_MeasureChars(
585      Tk_Font tkfont,             /* Font in which characters will be drawn. */      Tk_Font tkfont,             /* Font in which characters will be drawn. */
586      CONST char *source,         /* UTF-8 string to be displayed.  Need not be      CONST char *source,         /* UTF-8 string to be displayed.  Need not be
587                                   * '\0' terminated. */                                   * '\0' terminated. */
588      int numBytes,               /* Maximum number of bytes to consider      int numBytes,               /* Maximum number of bytes to consider
589                                   * from source string. */                                   * from source string. */
590      int maxLength,              /* If >= 0, maxLength specifies the longest      int maxLength,              /* If >= 0, maxLength specifies the longest
591                                   * permissible line length in pixels; don't                                   * permissible line length in pixels; don't
592                                   * consider any character that would cross                                   * consider any character that would cross
593                                   * this x-position.  If < 0, then line length                                   * this x-position.  If < 0, then line length
594                                   * is unbounded and the flags argument is                                   * is unbounded and the flags argument is
595                                   * ignored. */                                   * ignored. */
596      int flags,                  /* Various flag bits OR-ed together:      int flags,                  /* Various flag bits OR-ed together:
597                                   * TK_PARTIAL_OK means include the last char                                   * TK_PARTIAL_OK means include the last char
598                                   * which only partially fit on this line.                                   * which only partially fit on this line.
599                                   * TK_WHOLE_WORDS means stop on a word                                   * TK_WHOLE_WORDS means stop on a word
600                                   * boundary, if possible.                                   * boundary, if possible.
601                                   * TK_AT_LEAST_ONE means return at least one                                   * TK_AT_LEAST_ONE means return at least one
602                                   * character even if no characters fit. */                                   * character even if no characters fit. */
603      int *lengthPtr)             /* Filled with x-location just after the      int *lengthPtr)             /* Filled with x-location just after the
604                                   * terminating character. */                                   * terminating character. */
605  {  {
606      HDC hdc;      HDC hdc;
607      HFONT oldFont;      HFONT oldFont;
608      WinFont *fontPtr;      WinFont *fontPtr;
609      int curX, curByte;      int curX, curByte;
610      SubFont *lastSubFontPtr;      SubFont *lastSubFontPtr;
611    
612      /*      /*
613       * According to Microsoft tech support, Windows does not use kerning       * According to Microsoft tech support, Windows does not use kerning
614       * or fractional character widths when displaying text on the screen.       * or fractional character widths when displaying text on the screen.
615       * So that means we can safely measure individual characters or spans       * So that means we can safely measure individual characters or spans
616       * of characters and add up the widths w/o any "off-by-one-pixel"       * of characters and add up the widths w/o any "off-by-one-pixel"
617       * errors.         * errors.  
618       */       */
619    
620      fontPtr = (WinFont *) tkfont;      fontPtr = (WinFont *) tkfont;
621    
622      hdc = GetDC(fontPtr->hwnd);      hdc = GetDC(fontPtr->hwnd);
623      lastSubFontPtr = &fontPtr->subFontArray[0];      lastSubFontPtr = &fontPtr->subFontArray[0];
624      oldFont = SelectObject(hdc, lastSubFontPtr->hFont);      oldFont = SelectObject(hdc, lastSubFontPtr->hFont);
625    
626      if (numBytes == 0) {      if (numBytes == 0) {
627          curX = 0;          curX = 0;
628          curByte = 0;          curByte = 0;
629      } else if (maxLength < 0) {                                } else if (maxLength < 0) {                          
630          Tcl_UniChar ch;          Tcl_UniChar ch;
631          SIZE size;          SIZE size;
632          FontFamily *familyPtr;          FontFamily *familyPtr;
633          Tcl_DString runString;          Tcl_DString runString;
634          SubFont *thisSubFontPtr;          SubFont *thisSubFontPtr;
635          CONST char *p, *end, *next;          CONST char *p, *end, *next;
636    
637          /*          /*
638           * A three step process:           * A three step process:
639           * 1. Find a contiguous range of characters that can all be           * 1. Find a contiguous range of characters that can all be
640           *    represented by a single screen font.           *    represented by a single screen font.
641           * 2. Convert those chars to the encoding of that font.           * 2. Convert those chars to the encoding of that font.
642           * 3. Measure converted chars.           * 3. Measure converted chars.
643           */           */
644    
645          curX = 0;          curX = 0;
646          end = source + numBytes;          end = source + numBytes;
647          for (p = source; p < end; ) {          for (p = source; p < end; ) {
648              next = p + Tcl_UtfToUniChar(p, &ch);              next = p + Tcl_UtfToUniChar(p, &ch);
649              thisSubFontPtr = FindSubFontForChar(fontPtr, ch);              thisSubFontPtr = FindSubFontForChar(fontPtr, ch);
650              if (thisSubFontPtr != lastSubFontPtr) {              if (thisSubFontPtr != lastSubFontPtr) {
651                  familyPtr = lastSubFontPtr->familyPtr;                  familyPtr = lastSubFontPtr->familyPtr;
652                  Tcl_UtfToExternalDString(familyPtr->encoding, source,                  Tcl_UtfToExternalDString(familyPtr->encoding, source,
653                          p - source, &runString);                          p - source, &runString);
654                  (*familyPtr->getTextExtentPoint32Proc)(hdc,                  (*familyPtr->getTextExtentPoint32Proc)(hdc,
655                          Tcl_DStringValue(&runString),                          Tcl_DStringValue(&runString),
656                          Tcl_DStringLength(&runString) >> familyPtr->isWideFont,                          Tcl_DStringLength(&runString) >> familyPtr->isWideFont,
657                          &size);                          &size);
658                  curX += size.cx;                  curX += size.cx;
659                  Tcl_DStringFree(&runString);                  Tcl_DStringFree(&runString);
660                  lastSubFontPtr = thisSubFontPtr;                  lastSubFontPtr = thisSubFontPtr;
661                  source = p;                  source = p;
662    
663                  SelectObject(hdc, lastSubFontPtr->hFont);                  SelectObject(hdc, lastSubFontPtr->hFont);
664              }              }
665              p = next;              p = next;
666          }          }
667          familyPtr = lastSubFontPtr->familyPtr;          familyPtr = lastSubFontPtr->familyPtr;
668          Tcl_UtfToExternalDString(familyPtr->encoding, source, p - source,          Tcl_UtfToExternalDString(familyPtr->encoding, source, p - source,
669                  &runString);                  &runString);
670          (*familyPtr->getTextExtentPoint32Proc)(hdc,          (*familyPtr->getTextExtentPoint32Proc)(hdc,
671                  Tcl_DStringValue(&runString),                  Tcl_DStringValue(&runString),
672                  Tcl_DStringLength(&runString) >> familyPtr->isWideFont,                  Tcl_DStringLength(&runString) >> familyPtr->isWideFont,
673                  &size);                  &size);
674          curX += size.cx;          curX += size.cx;
675          Tcl_DStringFree(&runString);          Tcl_DStringFree(&runString);
676          curByte = numBytes;          curByte = numBytes;
677      } else {      } else {
678          Tcl_UniChar ch;          Tcl_UniChar ch;
679          SIZE size;          SIZE size;
680          char buf[16];          char buf[16];
681          FontFamily *familyPtr;          FontFamily *familyPtr;
682          SubFont *thisSubFontPtr;          SubFont *thisSubFontPtr;
683          CONST char *term, *end, *p, *next;          CONST char *term, *end, *p, *next;
684          int newX, termX, sawNonSpace, dstWrote;          int newX, termX, sawNonSpace, dstWrote;
685    
686          /*          /*
687           * How many chars will fit in the space allotted?           * How many chars will fit in the space allotted?
688           * This first version may be inefficient because it measures           * This first version may be inefficient because it measures
689           * every character individually.  There is a function call that           * every character individually.  There is a function call that
690           * can measure multiple characters at once and return the           * can measure multiple characters at once and return the
691           * offset of each of them, but it only works on NT, even though           * offset of each of them, but it only works on NT, even though
692           * the documentation claims it works for 95.           * the documentation claims it works for 95.
693           * TODO: verify that GetTextExtentExPoint is still broken in '95, and           * TODO: verify that GetTextExtentExPoint is still broken in '95, and
694           * possibly use it for NT anyway since it should be much faster and           * possibly use it for NT anyway since it should be much faster and
695           * more accurate.           * more accurate.
696           */           */
697    
698          next = source + Tcl_UtfToUniChar(source, &ch);          next = source + Tcl_UtfToUniChar(source, &ch);
699          newX = curX = termX = 0;          newX = curX = termX = 0;
700                    
701          term = source;          term = source;
702          end = source + numBytes;          end = source + numBytes;
703    
704          sawNonSpace = (ch > 255) || !isspace(ch);          sawNonSpace = (ch > 255) || !isspace(ch);
705          for (p = source; ; ) {          for (p = source; ; ) {
706              if (ch < BASE_CHARS) {              if (ch < BASE_CHARS) {
707                  newX += fontPtr->widths[ch];                  newX += fontPtr->widths[ch];
708              } else {              } else {
709                  thisSubFontPtr = FindSubFontForChar(fontPtr, ch);                  thisSubFontPtr = FindSubFontForChar(fontPtr, ch);
710                  if (thisSubFontPtr != lastSubFontPtr) {                  if (thisSubFontPtr != lastSubFontPtr) {
711                      SelectObject(hdc, thisSubFontPtr->hFont);                      SelectObject(hdc, thisSubFontPtr->hFont);
712                      lastSubFontPtr = thisSubFontPtr;                      lastSubFontPtr = thisSubFontPtr;
713                  }                  }
714                  familyPtr = lastSubFontPtr->familyPtr;                  familyPtr = lastSubFontPtr->familyPtr;
715                  Tcl_UtfToExternal(NULL, familyPtr->encoding, p, next - p,                  Tcl_UtfToExternal(NULL, familyPtr->encoding, p, next - p,
716                          0, NULL, buf, sizeof(buf), NULL, &dstWrote, NULL);                          0, NULL, buf, sizeof(buf), NULL, &dstWrote, NULL);
717                  (*familyPtr->getTextExtentPoint32Proc)(hdc, buf,                  (*familyPtr->getTextExtentPoint32Proc)(hdc, buf,
718                          dstWrote >> familyPtr->isWideFont, &size);                          dstWrote >> familyPtr->isWideFont, &size);
719                  newX += size.cx;                  newX += size.cx;
720              }              }
721              if (newX > maxLength) {              if (newX > maxLength) {
722                  break;                  break;
723              }              }
724              curX = newX;              curX = newX;
725              p = next;              p = next;
726              if (p >= end) {              if (p >= end) {
727                  term = end;                  term = end;
728                  termX = curX;                  termX = curX;
729                  break;                  break;
730              }              }
731    
732              next += Tcl_UtfToUniChar(next, &ch);              next += Tcl_UtfToUniChar(next, &ch);
733              if ((ch < 256) && isspace(ch)) {              if ((ch < 256) && isspace(ch)) {
734                  if (sawNonSpace) {                  if (sawNonSpace) {
735                      term = p;                      term = p;
736                      termX = curX;                      termX = curX;
737                      sawNonSpace = 0;                      sawNonSpace = 0;
738                  }                  }
739              } else {              } else {
740                  sawNonSpace = 1;                  sawNonSpace = 1;
741              }              }
742          }          }
743    
744          /*          /*
745           * P points to the first character that doesn't fit in the desired           * P points to the first character that doesn't fit in the desired
746           * span.  Use the flags to figure out what to return.           * span.  Use the flags to figure out what to return.
747           */           */
748    
749          if ((flags & TK_PARTIAL_OK) && (p < end) && (curX < maxLength)) {          if ((flags & TK_PARTIAL_OK) && (p < end) && (curX < maxLength)) {
750              /*              /*
751               * Include the first character that didn't quite fit in the desired               * Include the first character that didn't quite fit in the desired
752               * span.  The width returned will include the width of that extra               * span.  The width returned will include the width of that extra
753               * character.               * character.
754               */               */
755    
756              curX = newX;              curX = newX;
757              p += Tcl_UtfToUniChar(p, &ch);              p += Tcl_UtfToUniChar(p, &ch);
758          }          }
759          if ((flags & TK_AT_LEAST_ONE) && (term == source) && (p < end)) {          if ((flags & TK_AT_LEAST_ONE) && (term == source) && (p < end)) {
760              term = p;              term = p;
761              termX = curX;              termX = curX;
762              if (term == source) {              if (term == source) {
763                  term += Tcl_UtfToUniChar(term, &ch);                  term += Tcl_UtfToUniChar(term, &ch);
764                  termX = newX;                  termX = newX;
765              }              }
766          } else if ((p >= end) || !(flags & TK_WHOLE_WORDS)) {          } else if ((p >= end) || !(flags & TK_WHOLE_WORDS)) {
767              term = p;              term = p;
768              termX = curX;              termX = curX;
769          }          }
770    
771          curX = termX;          curX = termX;
772          curByte = term - source;                  curByte = term - source;        
773      }      }
774    
775      SelectObject(hdc, oldFont);      SelectObject(hdc, oldFont);
776      ReleaseDC(fontPtr->hwnd, hdc);      ReleaseDC(fontPtr->hwnd, hdc);
777    
778      *lengthPtr = curX;      *lengthPtr = curX;
779      return curByte;      return curByte;
780  }  }
781    
782  /*  /*
783   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
784   *   *
785   * Tk_DrawChars --   * Tk_DrawChars --
786   *   *
787   *      Draw a string of characters on the screen.     *      Draw a string of characters on the screen.  
788   *   *
789   * Results:   * Results:
790   *      None.   *      None.
791   *   *
792   * Side effects:   * Side effects:
793   *      Information gets drawn on the screen.   *      Information gets drawn on the screen.
794   *   *
795   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
796   */   */
797    
798  void  void
799  Tk_DrawChars(  Tk_DrawChars(
800      Display *display,           /* Display on which to draw. */      Display *display,           /* Display on which to draw. */
801      Drawable drawable,          /* Window or pixmap in which to draw. */      Drawable drawable,          /* Window or pixmap in which to draw. */
802      GC gc,                      /* Graphics context for drawing characters. */      GC gc,                      /* Graphics context for drawing characters. */
803      Tk_Font tkfont,             /* Font in which characters will be drawn;      Tk_Font tkfont,             /* Font in which characters will be drawn;
804                                   * must be the same as font used in GC. */                                   * must be the same as font used in GC. */
805      CONST char *source,         /* UTF-8 string to be displayed.  Need not be      CONST char *source,         /* UTF-8 string to be displayed.  Need not be
806                                   * '\0' terminated.  All Tk meta-characters                                   * '\0' terminated.  All Tk meta-characters
807                                   * (tabs, control characters, and newlines)                                   * (tabs, control characters, and newlines)
808                                   * should be stripped out of the string that                                   * should be stripped out of the string that
809                                   * is passed to this function.  If they are                                   * is passed to this function.  If they are
810                                   * not stripped out, they will be displayed as                                   * not stripped out, they will be displayed as
811                                   * regular printing characters. */                                   * regular printing characters. */
812      int numBytes,               /* Number of bytes in string. */      int numBytes,               /* Number of bytes in string. */
813      int x, int y)               /* Coordinates at which to place origin of      int x, int y)               /* Coordinates at which to place origin of
814                                   * string when drawing. */                                   * string when drawing. */
815  {  {
816      HDC dc;      HDC dc;
817      WinFont *fontPtr;      WinFont *fontPtr;
818      TkWinDCState state;      TkWinDCState state;
819    
820      fontPtr = (WinFont *) gc->font;      fontPtr = (WinFont *) gc->font;
821      display->request++;      display->request++;
822    
823      if (drawable == None) {      if (drawable == None) {
824          return;          return;
825      }      }
826    
827      dc = TkWinGetDrawableDC(display, drawable, &state);      dc = TkWinGetDrawableDC(display, drawable, &state);
828    
829      SetROP2(dc, tkpWinRopModes[gc->function]);      SetROP2(dc, tkpWinRopModes[gc->function]);
830    
831      if ((gc->fill_style == FillStippled      if ((gc->fill_style == FillStippled
832              || gc->fill_style == FillOpaqueStippled)              || gc->fill_style == FillOpaqueStippled)
833              && gc->stipple != None) {              && gc->stipple != None) {
834          TkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;          TkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;
835          HBRUSH oldBrush, stipple;          HBRUSH oldBrush, stipple;
836          HBITMAP oldBitmap, bitmap;          HBITMAP oldBitmap, bitmap;
837          HDC dcMem;          HDC dcMem;
838          TEXTMETRIC tm;          TEXTMETRIC tm;
839          SIZE size;          SIZE size;
840    
841          if (twdPtr->type != TWD_BITMAP) {          if (twdPtr->type != TWD_BITMAP) {
842              panic("unexpected drawable type in stipple");              panic("unexpected drawable type in stipple");
843          }          }
844    
845          /*          /*
846           * Select stipple pattern into destination dc.           * Select stipple pattern into destination dc.
847           */           */
848                    
849          dcMem = CreateCompatibleDC(dc);          dcMem = CreateCompatibleDC(dc);
850    
851          stipple = CreatePatternBrush(twdPtr->bitmap.handle);          stipple = CreatePatternBrush(twdPtr->bitmap.handle);
852          SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);          SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
853          oldBrush = SelectObject(dc, stipple);          oldBrush = SelectObject(dc, stipple);
854    
855          SetTextAlign(dcMem, TA_LEFT | TA_BASELINE);          SetTextAlign(dcMem, TA_LEFT | TA_BASELINE);
856          SetTextColor(dcMem, gc->foreground);          SetTextColor(dcMem, gc->foreground);
857          SetBkMode(dcMem, TRANSPARENT);          SetBkMode(dcMem, TRANSPARENT);
858          SetBkColor(dcMem, RGB(0, 0, 0));          SetBkColor(dcMem, RGB(0, 0, 0));
859    
860          /*          /*
861           * Compute the bounding box and create a compatible bitmap.           * Compute the bounding box and create a compatible bitmap.
862           */           */
863    
864          GetTextExtentPoint(dcMem, source, numBytes, &size);          GetTextExtentPoint(dcMem, source, numBytes, &size);
865          GetTextMetrics(dcMem, &tm);          GetTextMetrics(dcMem, &tm);
866          size.cx -= tm.tmOverhang;          size.cx -= tm.tmOverhang;
867          bitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);          bitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);
868          oldBitmap = SelectObject(dcMem, bitmap);          oldBitmap = SelectObject(dcMem, bitmap);
869    
870          /*          /*
871           * The following code is tricky because fonts are rendered in multiple           * The following code is tricky because fonts are rendered in multiple
872           * colors.  First we draw onto a black background and copy the white           * colors.  First we draw onto a black background and copy the white
873           * bits.  Then we draw onto a white background and copy the black bits.           * bits.  Then we draw onto a white background and copy the black bits.
874           * Both the foreground and background bits of the font are ANDed with           * Both the foreground and background bits of the font are ANDed with
875           * the stipple pattern as they are copied.           * the stipple pattern as they are copied.
876           */           */
877    
878          PatBlt(dcMem, 0, 0, size.cx, size.cy, BLACKNESS);          PatBlt(dcMem, 0, 0, size.cx, size.cy, BLACKNESS);
879          MultiFontTextOut(dc, fontPtr, source, numBytes, x, y);          MultiFontTextOut(dc, fontPtr, source, numBytes, x, y);
880          BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,          BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,
881                  0, 0, 0xEA02E9);                  0, 0, 0xEA02E9);
882          PatBlt(dcMem, 0, 0, size.cx, size.cy, WHITENESS);          PatBlt(dcMem, 0, 0, size.cx, size.cy, WHITENESS);
883          MultiFontTextOut(dc, fontPtr, source, numBytes, x, y);          MultiFontTextOut(dc, fontPtr, source, numBytes, x, y);
884          BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,          BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,
885                  0, 0, 0x8A0E06);                  0, 0, 0x8A0E06);
886    
887          /*          /*
888           * Destroy the temporary bitmap and restore the device context.           * Destroy the temporary bitmap and restore the device context.
889           */           */
890    
891          SelectObject(dcMem, oldBitmap);          SelectObject(dcMem, oldBitmap);
892          DeleteObject(bitmap);          DeleteObject(bitmap);
893          DeleteDC(dcMem);          DeleteDC(dcMem);
894          SelectObject(dc, oldBrush);          SelectObject(dc, oldBrush);
895          DeleteObject(stipple);          DeleteObject(stipple);
896      } else {      } else {
897          SetTextAlign(dc, TA_LEFT | TA_BASELINE);          SetTextAlign(dc, TA_LEFT | TA_BASELINE);
898          SetTextColor(dc, gc->foreground);          SetTextColor(dc, gc->foreground);
899          SetBkMode(dc, TRANSPARENT);          SetBkMode(dc, TRANSPARENT);
900          MultiFontTextOut(dc, fontPtr, source, numBytes, x, y);          MultiFontTextOut(dc, fontPtr, source, numBytes, x, y);
901      }      }
902      TkWinReleaseDrawableDC(drawable, dc, &state);      TkWinReleaseDrawableDC(drawable, dc, &state);
903  }  }
904    
905  /*  /*
906   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
907   *   *
908   * MultiFontTextOut --   * MultiFontTextOut --
909   *   *
910   *      Helper function for Tk_DrawChars.  Draws characters, using the   *      Helper function for Tk_DrawChars.  Draws characters, using the
911   *      various screen fonts in fontPtr to draw multilingual characters.   *      various screen fonts in fontPtr to draw multilingual characters.
912   *      Note: No bidirectional support.   *      Note: No bidirectional support.
913   *   *
914   * Results:   * Results:
915   *      None.   *      None.
916   *   *
917   * Side effects:   * Side effects:
918   *      Information gets drawn on the screen.     *      Information gets drawn on the screen.  
919   *      Contents of fontPtr may be modified if more subfonts were loaded   *      Contents of fontPtr may be modified if more subfonts were loaded
920   *      in order to draw all the multilingual characters in the given   *      in order to draw all the multilingual characters in the given
921   *      string.   *      string.
922   *   *
923   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
924   */   */
925    
926  static void  static void
927  MultiFontTextOut(  MultiFontTextOut(
928      HDC hdc,                    /* HDC to draw into. */      HDC hdc,                    /* HDC to draw into. */
929      WinFont *fontPtr,           /* Contains set of fonts to use when drawing      WinFont *fontPtr,           /* Contains set of fonts to use when drawing
930                                   * following string. */                                   * following string. */
931      CONST char *source,         /* Potentially multilingual UTF-8 string. */      CONST char *source,         /* Potentially multilingual UTF-8 string. */
932      int numBytes,               /* Length of string in bytes. */      int numBytes,               /* Length of string in bytes. */
933      int x, int y)               /* Coordinates at which to place origin *      int x, int y)               /* Coordinates at which to place origin *
934                                   * of string when drawing. */                                   * of string when drawing. */
935  {  {
936      Tcl_UniChar ch;      Tcl_UniChar ch;
937      SIZE size;      SIZE size;
938      HFONT oldFont;      HFONT oldFont;
939      FontFamily *familyPtr;      FontFamily *familyPtr;
940      Tcl_DString runString;      Tcl_DString runString;
941      CONST char *p, *end, *next;      CONST char *p, *end, *next;
942      SubFont *lastSubFontPtr, *thisSubFontPtr;      SubFont *lastSubFontPtr, *thisSubFontPtr;
943    
944      lastSubFontPtr = &fontPtr->subFontArray[0];      lastSubFontPtr = &fontPtr->subFontArray[0];
945      oldFont = SelectObject(hdc, lastSubFontPtr->hFont);      oldFont = SelectObject(hdc, lastSubFontPtr->hFont);
946    
947      end = source + numBytes;      end = source + numBytes;
948      for (p = source; p < end; ) {      for (p = source; p < end; ) {
949          next = p + Tcl_UtfToUniChar(p, &ch);          next = p + Tcl_UtfToUniChar(p, &ch);
950          thisSubFontPtr = FindSubFontForChar(fontPtr, ch);          thisSubFontPtr = FindSubFontForChar(fontPtr, ch);
951          if (thisSubFontPtr != lastSubFontPtr) {          if (thisSubFontPtr != lastSubFontPtr) {
952              if (p > source) {              if (p > source) {
953                  familyPtr = lastSubFontPtr->familyPtr;                  familyPtr = lastSubFontPtr->familyPtr;
954                  Tcl_UtfToExternalDString(familyPtr->encoding, source,                  Tcl_UtfToExternalDString(familyPtr->encoding, source,
955                          p - source, &runString);                          p - source, &runString);
956                  (*familyPtr->textOutProc)(hdc, x, y,                  (*familyPtr->textOutProc)(hdc, x, y,
957                          Tcl_DStringValue(&runString),                          Tcl_DStringValue(&runString),
958                          Tcl_DStringLength(&runString) >> familyPtr->isWideFont);                          Tcl_DStringLength(&runString) >> familyPtr->isWideFont);
959                  (*familyPtr->getTextExtentPoint32Proc)(hdc,                  (*familyPtr->getTextExtentPoint32Proc)(hdc,
960                          Tcl_DStringValue(&runString),                          Tcl_DStringValue(&runString),
961                          Tcl_DStringLength(&runString) >> familyPtr->isWideFont,                          Tcl_DStringLength(&runString) >> familyPtr->isWideFont,
962                          &size);                          &size);
963                  x += size.cx;                  x += size.cx;
964                  Tcl_DStringFree(&runString);                  Tcl_DStringFree(&runString);
965              }              }
966              lastSubFontPtr = thisSubFontPtr;              lastSubFontPtr = thisSubFontPtr;
967              source = p;              source = p;
968              SelectObject(hdc, lastSubFontPtr->hFont);              SelectObject(hdc, lastSubFontPtr->hFont);
969          }          }
970          p = next;          p = next;
971      }      }
972      if (p > source) {      if (p > source) {
973          familyPtr = lastSubFontPtr->familyPtr;          familyPtr = lastSubFontPtr->familyPtr;
974          Tcl_UtfToExternalDString(familyPtr->encoding, source, p - source,          Tcl_UtfToExternalDString(familyPtr->encoding, source, p - source,
975                  &runString);                  &runString);
976          (*familyPtr->textOutProc)(hdc, x, y, Tcl_DStringValue(&runString),          (*familyPtr->textOutProc)(hdc, x, y, Tcl_DStringValue(&runString),
977                  Tcl_DStringLength(&runString) >> familyPtr->isWideFont);                  Tcl_DStringLength(&runString) >> familyPtr->isWideFont);
978          Tcl_DStringFree(&runString);          Tcl_DStringFree(&runString);
979      }      }
980      SelectObject(hdc, oldFont);      SelectObject(hdc, oldFont);
981  }  }
982    
983  /*  /*
984   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
985   *   *
986   * InitFont --   * InitFont --
987   *   *
988   *      Helper for TkpGetNativeFont() and TkpGetFontFromAttributes().   *      Helper for TkpGetNativeFont() and TkpGetFontFromAttributes().
989   *      Initializes the memory for a new WinFont that wraps the   *      Initializes the memory for a new WinFont that wraps the
990   *      platform-specific data.   *      platform-specific data.
991   *   *
992   *      The caller is responsible for initializing the fields of the   *      The caller is responsible for initializing the fields of the
993   *      WinFont that are used exclusively by the generic TkFont code, and   *      WinFont that are used exclusively by the generic TkFont code, and
994   *      for releasing those fields before calling TkpDeleteFont().   *      for releasing those fields before calling TkpDeleteFont().
995   *   *
996   * Results:   * Results:
997   *      Fills the WinFont structure.   *      Fills the WinFont structure.
998   *   *
999   * Side effects:   * Side effects:
1000   *      Memory allocated.   *      Memory allocated.
1001   *   *
1002   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
1003   */   */
1004    
1005  static void  static void
1006  InitFont(  InitFont(
1007      Tk_Window tkwin,            /* Main window of interp in which font will      Tk_Window tkwin,            /* Main window of interp in which font will
1008                                   * be used, for getting HDC. */                                   * be used, for getting HDC. */
1009      HFONT hFont,                /* Windows token for font. */      HFONT hFont,                /* Windows token for font. */
1010      int overstrike,             /* The overstrike attribute of logfont used      int overstrike,             /* The overstrike attribute of logfont used
1011                                   * to allocate this font.  For some reason,                                   * to allocate this font.  For some reason,
1012                                   * the TEXTMETRICs may contain incorrect info                                   * the TEXTMETRICs may contain incorrect info
1013                                   * in the tmStruckOut field. */                                   * in the tmStruckOut field. */
1014      WinFont *fontPtr)           /* Filled with information constructed from      WinFont *fontPtr)           /* Filled with information constructed from
1015                                   * the above arguments. */                                   * the above arguments. */
1016  {  {
1017      HDC hdc;      HDC hdc;
1018      HWND hwnd;      HWND hwnd;
1019      HFONT oldFont;      HFONT oldFont;
1020      TEXTMETRIC tm;      TEXTMETRIC tm;
1021      Window window;      Window window;
1022      TkFontMetrics *fmPtr;      TkFontMetrics *fmPtr;
1023      Tcl_Encoding encoding;      Tcl_Encoding encoding;
1024      Tcl_DString faceString;      Tcl_DString faceString;
1025      TkFontAttributes *faPtr;      TkFontAttributes *faPtr;
1026      char buf[LF_FACESIZE * sizeof(WCHAR)];      char buf[LF_FACESIZE * sizeof(WCHAR)];
1027    
1028      window  = Tk_WindowId(tkwin);      window  = Tk_WindowId(tkwin);
1029      hwnd    = (window == None) ? NULL : TkWinGetHWND(window);      hwnd    = (window == None) ? NULL : TkWinGetHWND(window);
1030      hdc     = GetDC(hwnd);      hdc     = GetDC(hwnd);
1031      oldFont = SelectObject(hdc, hFont);      oldFont = SelectObject(hdc, hFont);
1032    
1033      GetTextMetrics(hdc, &tm);      GetTextMetrics(hdc, &tm);
1034    
1035      /*      /*
1036       * On any version NT, there may fonts with international names.         * On any version NT, there may fonts with international names.  
1037       * Use the NT-only Unicode version of GetTextFace to get the font's       * Use the NT-only Unicode version of GetTextFace to get the font's
1038       * name.  If we used the ANSI version on a non-internationalized       * name.  If we used the ANSI version on a non-internationalized
1039       * version of NT, we would get a font name with '?' replacing all       * version of NT, we would get a font name with '?' replacing all
1040       * the international characters.       * the international characters.
1041       *       *
1042       * On a non-internationalized verson of 95, fonts with international       * On a non-internationalized verson of 95, fonts with international
1043       * names are not allowed, so the ANSI version of GetTextFace will work.       * names are not allowed, so the ANSI version of GetTextFace will work.
1044       * On an internationalized version of 95, there may be fonts with       * On an internationalized version of 95, there may be fonts with
1045       * international names; the ANSI version will work, fetching the       * international names; the ANSI version will work, fetching the
1046       * name in the international system code page.  Can't use the Unicode       * name in the international system code page.  Can't use the Unicode
1047       * version of GetTextFace because it only exists under NT.       * version of GetTextFace because it only exists under NT.
1048       */       */
1049    
1050      if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {      if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
1051          GetTextFaceW(hdc, LF_FACESIZE, (WCHAR *) buf);          GetTextFaceW(hdc, LF_FACESIZE, (WCHAR *) buf);
1052      } else {      } else {
1053          GetTextFaceA(hdc, LF_FACESIZE, (char *) buf);          GetTextFaceA(hdc, LF_FACESIZE, (char *) buf);
1054      }      }
1055      Tcl_ExternalToUtfDString(systemEncoding, buf, -1, &faceString);      Tcl_ExternalToUtfDString(systemEncoding, buf, -1, &faceString);
1056    
1057      fontPtr->font.fid   = (Font) fontPtr;      fontPtr->font.fid   = (Font) fontPtr;
1058    
1059      faPtr               = &fontPtr->font.fa;      faPtr               = &fontPtr->font.fa;
1060      faPtr->family       = Tk_GetUid(Tcl_DStringValue(&faceString));      faPtr->family       = Tk_GetUid(Tcl_DStringValue(&faceString));
1061      faPtr->size         = TkFontGetPoints(tkwin, -(tm.tmHeight - tm.tmInternalLeading));      faPtr->size         = TkFontGetPoints(tkwin, -(tm.tmHeight - tm.tmInternalLeading));
1062      faPtr->weight       = (tm.tmWeight > FW_MEDIUM) ? TK_FW_BOLD : TK_FW_NORMAL;      faPtr->weight       = (tm.tmWeight > FW_MEDIUM) ? TK_FW_BOLD : TK_FW_NORMAL;
1063      faPtr->slant        = (tm.tmItalic != 0) ? TK_FS_ITALIC : TK_FS_ROMAN;      faPtr->slant        = (tm.tmItalic != 0) ? TK_FS_ITALIC : TK_FS_ROMAN;
1064      faPtr->underline    = (tm.tmUnderlined != 0) ? 1 : 0;      faPtr->underline    = (tm.tmUnderlined != 0) ? 1 : 0;
1065      faPtr->overstrike   = overstrike;      faPtr->overstrike   = overstrike;
1066            
1067      fmPtr               = &fontPtr->font.fm;      fmPtr               = &fontPtr->font.fm;
1068      fmPtr->ascent       = tm.tmAscent;      fmPtr->ascent       = tm.tmAscent;
1069      fmPtr->descent      = tm.tmDescent;      fmPtr->descent      = tm.tmDescent;
1070      fmPtr->maxWidth     = tm.tmMaxCharWidth;      fmPtr->maxWidth     = tm.tmMaxCharWidth;
1071      fmPtr->fixed        = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH);      fmPtr->fixed        = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
1072    
1073      fontPtr->hwnd       = hwnd;      fontPtr->hwnd       = hwnd;
1074      fontPtr->pixelSize  = tm.tmHeight - tm.tmInternalLeading;      fontPtr->pixelSize  = tm.tmHeight - tm.tmInternalLeading;
1075    
1076      fontPtr->numSubFonts        = 1;      fontPtr->numSubFonts        = 1;
1077      fontPtr->subFontArray       = fontPtr->staticSubFonts;      fontPtr->subFontArray       = fontPtr->staticSubFonts;
1078      InitSubFont(hdc, hFont, 1, &fontPtr->subFontArray[0]);      InitSubFont(hdc, hFont, 1, &fontPtr->subFontArray[0]);
1079    
1080      encoding = fontPtr->subFontArray[0].familyPtr->encoding;      encoding = fontPtr->subFontArray[0].familyPtr->encoding;
1081      if (encoding == unicodeEncoding) {      if (encoding == unicodeEncoding) {
1082          GetCharWidthW(hdc, 0, BASE_CHARS - 1, fontPtr->widths);          GetCharWidthW(hdc, 0, BASE_CHARS - 1, fontPtr->widths);
1083      } else {      } else {
1084          GetCharWidthA(hdc, 0, BASE_CHARS - 1, fontPtr->widths);          GetCharWidthA(hdc, 0, BASE_CHARS - 1, fontPtr->widths);
1085      }      }
1086      Tcl_DStringFree(&faceString);      Tcl_DStringFree(&faceString);
1087    
1088      SelectObject(hdc, oldFont);      SelectObject(hdc, oldFont);
1089      ReleaseDC(hwnd, hdc);      ReleaseDC(hwnd, hdc);
1090  }  }
1091    
1092  /*  /*
1093   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1094   *   *
1095   * ReleaseFont --   * ReleaseFont --
1096   *   *
1097   *      Called to release the windows-specific contents of a TkFont.   *      Called to release the windows-specific contents of a TkFont.
1098   *      The caller is responsible for freeing the memory used by the   *      The caller is responsible for freeing the memory used by the
1099   *      font itself.   *      font itself.
1100   *   *
1101   * Results:   * Results:
1102   *      None.   *      None.
1103   *   *
1104   * Side effects:   * Side effects:
1105   *      Memory is freed.   *      Memory is freed.
1106   *   *
1107   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
1108   */   */
1109    
1110  static void  static void
1111  ReleaseFont(  ReleaseFont(
1112      WinFont *fontPtr)           /* The font to delete. */      WinFont *fontPtr)           /* The font to delete. */
1113  {  {
1114      int i;      int i;
1115    
1116      for (i = 0; i < fontPtr->numSubFonts; i++) {      for (i = 0; i < fontPtr->numSubFonts; i++) {
1117          ReleaseSubFont(&fontPtr->subFontArray[i]);          ReleaseSubFont(&fontPtr->subFontArray[i]);
1118      }      }
1119      if (fontPtr->subFontArray != fontPtr->staticSubFonts) {      if (fontPtr->subFontArray != fontPtr->staticSubFonts) {
1120          ckfree((char *) fontPtr->subFontArray);          ckfree((char *) fontPtr->subFontArray);
1121      }      }
1122  }  }
1123    
1124  /*  /*
1125   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1126   *   *
1127   * InitSubFont --   * InitSubFont --
1128   *   *
1129   *      Wrap a screen font and load the FontFamily that represents   *      Wrap a screen font and load the FontFamily that represents
1130   *      it.  Used to prepare a SubFont so that characters can be mapped   *      it.  Used to prepare a SubFont so that characters can be mapped
1131   *      from UTF-8 to the charset of the font.   *      from UTF-8 to the charset of the font.
1132   *   *
1133   * Results:   * Results:
1134   *      The subFontPtr is filled with information about the font.   *      The subFontPtr is filled with information about the font.
1135   *   *
1136   * Side effects:   * Side effects:
1137   *      None.   *      None.
1138   *   *
1139   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1140   */   */
1141    
1142  static void  static void
1143  InitSubFont(  InitSubFont(
1144      HDC hdc,                    /* HDC in which font can be selected. */      HDC hdc,                    /* HDC in which font can be selected. */
1145      HFONT hFont,                /* The screen font. */      HFONT hFont,                /* The screen font. */
1146      int base,                   /* Non-zero if this SubFont is being used      int base,                   /* Non-zero if this SubFont is being used
1147                                   * as the base font for a font object. */                                   * as the base font for a font object. */
1148      SubFont *subFontPtr)        /* Filled with SubFont constructed from      SubFont *subFontPtr)        /* Filled with SubFont constructed from
1149                                   * above attributes. */                                   * above attributes. */
1150  {  {
1151      subFontPtr->hFont       = hFont;      subFontPtr->hFont       = hFont;
1152      subFontPtr->familyPtr   = AllocFontFamily(hdc, hFont, base);      subFontPtr->familyPtr   = AllocFontFamily(hdc, hFont, base);
1153      subFontPtr->fontMap     = subFontPtr->familyPtr->fontMap;      subFontPtr->fontMap     = subFontPtr->familyPtr->fontMap;
1154  }  }
1155    
1156  /*  /*
1157   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1158   *   *
1159   * ReleaseSubFont --   * ReleaseSubFont --
1160   *   *
1161   *      Called to release the contents of a SubFont.  The caller is   *      Called to release the contents of a SubFont.  The caller is
1162   *      responsible for freeing the memory used by the SubFont itself.   *      responsible for freeing the memory used by the SubFont itself.
1163   *   *
1164   * Results:   * Results:
1165   *      None.   *      None.
1166   *   *
1167   * Side effects:   * Side effects:
1168   *      Memory and resources are freed.   *      Memory and resources are freed.
1169   *   *
1170   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
1171   */   */
1172    
1173  static void  static void
1174  ReleaseSubFont(  ReleaseSubFont(
1175      SubFont *subFontPtr)        /* The SubFont to delete. */      SubFont *subFontPtr)        /* The SubFont to delete. */
1176  {  {
1177      DeleteObject(subFontPtr->hFont);      DeleteObject(subFontPtr->hFont);
1178      FreeFontFamily(subFontPtr->familyPtr);      FreeFontFamily(subFontPtr->familyPtr);
1179  }  }
1180    
1181  /*  /*
1182   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1183   *   *
1184   * AllocFontFamily --   * AllocFontFamily --
1185   *   *
1186   *      Find the FontFamily structure associated with the given font   *      Find the FontFamily structure associated with the given font
1187   *      name.  The information should be stored by the caller in a   *      name.  The information should be stored by the caller in a
1188   *      SubFont and used when determining if that SubFont supports a   *      SubFont and used when determining if that SubFont supports a
1189   *      character.   *      character.
1190   *   *
1191   *      Cannot use the string name used to construct the font as the   *      Cannot use the string name used to construct the font as the
1192   *      key, because the capitalization may not be canonical.  Therefore   *      key, because the capitalization may not be canonical.  Therefore
1193   *      use the face name actually retrieved from the font metrics as   *      use the face name actually retrieved from the font metrics as
1194   *      the key.   *      the key.
1195   *   *
1196   * Results:   * Results:
1197   *      A pointer to a FontFamily.  The reference count in the FontFamily   *      A pointer to a FontFamily.  The reference count in the FontFamily
1198   *      is automatically incremented.  When the SubFont is released, the   *      is automatically incremented.  When the SubFont is released, the
1199   *      reference count is decremented.  When no SubFont is using this   *      reference count is decremented.  When no SubFont is using this
1200   *      FontFamily, it may be deleted.   *      FontFamily, it may be deleted.
1201   *   *
1202   * Side effects:   * Side effects:
1203   *      A new FontFamily structure will be allocated if this font family   *      A new FontFamily structure will be allocated if this font family
1204   *      has not been seen.  TrueType character existence metrics are   *      has not been seen.  TrueType character existence metrics are
1205   *      loaded into the FontFamily structure.   *      loaded into the FontFamily structure.
1206   *   *
1207   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1208   */   */
1209    
1210  static FontFamily *  static FontFamily *
1211  AllocFontFamily(  AllocFontFamily(
1212      HDC hdc,                    /* HDC in which font can be selected. */      HDC hdc,                    /* HDC in which font can be selected. */
1213      HFONT hFont,                /* Screen font whose FontFamily is to be      HFONT hFont,                /* Screen font whose FontFamily is to be
1214                                   * returned. */                                   * returned. */
1215      int base)                   /* Non-zero if this font family is to be      int base)                   /* Non-zero if this font family is to be
1216                                   * used in the base font of a font object. */                                   * used in the base font of a font object. */
1217  {  {
1218      Tk_Uid faceName;      Tk_Uid faceName;
1219      FontFamily *familyPtr;      FontFamily *familyPtr;
1220      Tcl_DString faceString;      Tcl_DString faceString;
1221      Tcl_Encoding encoding;      Tcl_Encoding encoding;
1222      char buf[LF_FACESIZE * sizeof(WCHAR)];      char buf[LF_FACESIZE * sizeof(WCHAR)];
1223      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
1224              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
1225    
1226      hFont = SelectObject(hdc, hFont);      hFont = SelectObject(hdc, hFont);
1227      if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {      if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
1228          GetTextFaceW(hdc, LF_FACESIZE, (WCHAR *) buf);          GetTextFaceW(hdc, LF_FACESIZE, (WCHAR *) buf);
1229      } else {      } else {
1230          GetTextFaceA(hdc, LF_FACESIZE, (char *) buf);          GetTextFaceA(hdc, LF_FACESIZE, (char *) buf);
1231      }      }
1232      Tcl_ExternalToUtfDString(systemEncoding, buf, -1, &faceString);      Tcl_ExternalToUtfDString(systemEncoding, buf, -1, &faceString);
1233      faceName = Tk_GetUid(Tcl_DStringValue(&faceString));      faceName = Tk_GetUid(Tcl_DStringValue(&faceString));
1234      Tcl_DStringFree(&faceString);      Tcl_DStringFree(&faceString);
1235      hFont = SelectObject(hdc, hFont);      hFont = SelectObject(hdc, hFont);
1236    
1237      familyPtr = tsdPtr->fontFamilyList;      familyPtr = tsdPtr->fontFamilyList;
1238      for ( ; familyPtr != NULL; familyPtr = familyPtr->nextPtr) {      for ( ; familyPtr != NULL; familyPtr = familyPtr->nextPtr) {
1239          if (familyPtr->faceName == faceName) {          if (familyPtr->faceName == faceName) {
1240              familyPtr->refCount++;              familyPtr->refCount++;
1241              return familyPtr;              return familyPtr;
1242          }          }
1243      }      }
1244    
1245      familyPtr = (FontFamily *) ckalloc(sizeof(FontFamily));      familyPtr = (FontFamily *) ckalloc(sizeof(FontFamily));
1246      memset(familyPtr, 0, sizeof(FontFamily));      memset(familyPtr, 0, sizeof(FontFamily));
1247      familyPtr->nextPtr = tsdPtr->fontFamilyList;      familyPtr->nextPtr = tsdPtr->fontFamilyList;
1248      tsdPtr->fontFamilyList = familyPtr;      tsdPtr->fontFamilyList = familyPtr;
1249    
1250      /*      /*
1251       * Set key for this FontFamily.       * Set key for this FontFamily.
1252       */       */
1253    
1254      familyPtr->faceName = faceName;      familyPtr->faceName = faceName;
1255    
1256      /*      /*
1257       * An initial refCount of 2 means that FontFamily information will       * An initial refCount of 2 means that FontFamily information will
1258       * persist even when the SubFont that loaded the FontFamily is released.       * persist even when the SubFont that loaded the FontFamily is released.
1259       * Change it to 1 to cause FontFamilies to be unloaded when not in use.       * Change it to 1 to cause FontFamilies to be unloaded when not in use.
1260       */       */
1261    
1262      familyPtr->refCount = 2;      familyPtr->refCount = 2;
1263    
1264      familyPtr->segCount = LoadFontRanges(hdc, hFont, &familyPtr->startCount,      familyPtr->segCount = LoadFontRanges(hdc, hFont, &familyPtr->startCount,
1265              &familyPtr->endCount, &familyPtr->isSymbolFont);              &familyPtr->endCount, &familyPtr->isSymbolFont);
1266    
1267      encoding = NULL;      encoding = NULL;
1268      if (familyPtr->isSymbolFont != 0) {      if (familyPtr->isSymbolFont != 0) {
1269          /*          /*
1270           * Symbol fonts are handled specially.  For instance, Unicode 0393           * Symbol fonts are handled specially.  For instance, Unicode 0393
1271           * (GREEK CAPITAL GAMMA) must be mapped to Symbol character 0047           * (GREEK CAPITAL GAMMA) must be mapped to Symbol character 0047
1272           * (GREEK CAPITAL GAMMA), because the Symbol font doesn't have a           * (GREEK CAPITAL GAMMA), because the Symbol font doesn't have a
1273           * GREEK CAPITAL GAMMA at location 0393.  If Tk interpreted the           * GREEK CAPITAL GAMMA at location 0393.  If Tk interpreted the
1274           * Symbol font using the Unicode encoding, it would decide that           * Symbol font using the Unicode encoding, it would decide that
1275           * the Symbol font has no GREEK CAPITAL GAMMA, because the Symbol           * the Symbol font has no GREEK CAPITAL GAMMA, because the Symbol
1276           * encoding (of course) reports that character 0393 doesn't exist.             * encoding (of course) reports that character 0393 doesn't exist.  
1277           *           *
1278           * With non-symbol Windows fonts, such as Times New Roman, if the           * With non-symbol Windows fonts, such as Times New Roman, if the
1279           * font has a GREEK CAPITAL GAMMA, it will be found in the correct           * font has a GREEK CAPITAL GAMMA, it will be found in the correct
1280           * Unicode location (0393); the GREEK CAPITAL GAMMA will not be off           * Unicode location (0393); the GREEK CAPITAL GAMMA will not be off
1281           * hiding at some other location.           * hiding at some other location.
1282           */           */
1283    
1284          encoding = Tcl_GetEncoding(NULL, faceName);          encoding = Tcl_GetEncoding(NULL, faceName);
1285      }      }
1286    
1287      if (encoding == NULL) {      if (encoding == NULL) {
1288          encoding = Tcl_GetEncoding(NULL, "unicode");          encoding = Tcl_GetEncoding(NULL, "unicode");
1289          familyPtr->textOutProc =          familyPtr->textOutProc =
1290              (BOOL (WINAPI *)(HDC, int, int, TCHAR *, int)) TextOutW;              (BOOL (WINAPI *)(HDC, int, int, TCHAR *, int)) TextOutW;
1291          familyPtr->getTextExtentPoint32Proc =          familyPtr->getTextExtentPoint32Proc =
1292              (BOOL (WINAPI *)(HDC, TCHAR *, int, LPSIZE)) GetTextExtentPoint32W;              (BOOL (WINAPI *)(HDC, TCHAR *, int, LPSIZE)) GetTextExtentPoint32W;
1293          familyPtr->isWideFont = 1;          familyPtr->isWideFont = 1;
1294      } else {      } else {
1295          familyPtr->textOutProc =          familyPtr->textOutProc =
1296              (BOOL (WINAPI *)(HDC, int, int, TCHAR *, int)) TextOutA;              (BOOL (WINAPI *)(HDC, int, int, TCHAR *, int)) TextOutA;
1297          familyPtr->getTextExtentPoint32Proc =          familyPtr->getTextExtentPoint32Proc =
1298              (BOOL (WINAPI *)(HDC, TCHAR *, int, LPSIZE)) GetTextExtentPoint32A;              (BOOL (WINAPI *)(HDC, TCHAR *, int, LPSIZE)) GetTextExtentPoint32A;
1299          familyPtr->isWideFont = 0;          familyPtr->isWideFont = 0;
1300      }      }
1301    
1302      familyPtr->encoding = encoding;      familyPtr->encoding = encoding;
1303    
1304      return familyPtr;      return familyPtr;
1305  }  }
1306    
1307  /*  /*
1308   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1309   *   *
1310   * FreeFontFamily --   * FreeFontFamily --
1311   *   *
1312   *      Called to free a FontFamily when the SubFont is finished using it.   *      Called to free a FontFamily when the SubFont is finished using it.
1313   *      Frees the contents of the FontFamily and the memory used by the   *      Frees the contents of the FontFamily and the memory used by the
1314   *      FontFamily itself.   *      FontFamily itself.
1315   *   *
1316   * Results:   * Results:
1317   *      None.   *      None.
1318   *   *
1319   * Side effects:   * Side effects:
1320   *      None.   *      None.
1321   *   *
1322   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1323   */   */
1324    
1325  static void  static void
1326  FreeFontFamily(  FreeFontFamily(
1327      FontFamily *familyPtr)      /* The FontFamily to delete. */      FontFamily *familyPtr)      /* The FontFamily to delete. */
1328  {  {
1329      int i;      int i;
1330      FontFamily **familyPtrPtr;      FontFamily **familyPtrPtr;
1331      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
1332              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
1333    
1334      if (familyPtr == NULL) {      if (familyPtr == NULL) {
1335          return;          return;
1336      }      }
1337      familyPtr->refCount--;      familyPtr->refCount--;
1338      if (familyPtr->refCount > 0) {      if (familyPtr->refCount > 0) {
1339          return;          return;
1340      }      }
1341      for (i = 0; i < FONTMAP_PAGES; i++) {      for (i = 0; i < FONTMAP_PAGES; i++) {
1342          if (familyPtr->fontMap[i] != NULL) {          if (familyPtr->fontMap[i] != NULL) {
1343              ckfree(familyPtr->fontMap[i]);              ckfree(familyPtr->fontMap[i]);
1344          }          }
1345      }      }
1346      if (familyPtr->startCount != NULL) {      if (familyPtr->startCount != NULL) {
1347          ckfree((char *) familyPtr->startCount);          ckfree((char *) familyPtr->startCount);
1348      }      }
1349      if (familyPtr->endCount != NULL) {      if (familyPtr->endCount != NULL) {
1350          ckfree((char *) familyPtr->endCount);          ckfree((char *) familyPtr->endCount);
1351      }      }
1352      if (familyPtr->encoding != unicodeEncoding) {      if (familyPtr->encoding != unicodeEncoding) {
1353          Tcl_FreeEncoding(familyPtr->encoding);          Tcl_FreeEncoding(familyPtr->encoding);
1354      }      }
1355            
1356      /*      /*
1357       * Delete from list.       * Delete from list.
1358       */       */
1359                    
1360      for (familyPtrPtr = &tsdPtr->fontFamilyList; ; ) {      for (familyPtrPtr = &tsdPtr->fontFamilyList; ; ) {
1361          if (*familyPtrPtr == familyPtr) {          if (*familyPtrPtr == familyPtr) {
1362              *familyPtrPtr = familyPtr->nextPtr;              *familyPtrPtr = familyPtr->nextPtr;
1363              break;              break;
1364          }          }
1365          familyPtrPtr = &(*familyPtrPtr)->nextPtr;          familyPtrPtr = &(*familyPtrPtr)->nextPtr;
1366      }      }
1367            
1368      ckfree((char *) familyPtr);      ckfree((char *) familyPtr);
1369  }  }
1370    
1371  /*  /*
1372   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1373   *   *
1374   * FindSubFontForChar --   * FindSubFontForChar --
1375   *   *
1376   *      Determine which screen font is necessary to use to display the   *      Determine which screen font is necessary to use to display the
1377   *      given character.  If the font object does not have a screen font   *      given character.  If the font object does not have a screen font
1378   *      that can display the character, another screen font may be loaded   *      that can display the character, another screen font may be loaded
1379   *      into the font object, following a set of preferred fallback rules.   *      into the font object, following a set of preferred fallback rules.
1380   *   *
1381   * Results:   * Results:
1382   *      The return value is the SubFont to use to display the given   *      The return value is the SubFont to use to display the given
1383   *      character.   *      character.
1384   *   *
1385   * Side effects:   * Side effects:
1386   *      The contents of fontPtr are modified to cache the results   *      The contents of fontPtr are modified to cache the results
1387   *      of the lookup and remember any SubFonts that were dynamically   *      of the lookup and remember any SubFonts that were dynamically
1388   *      loaded.   *      loaded.
1389   *   *
1390   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1391   */   */
1392    
1393  static SubFont *  static SubFont *
1394  FindSubFontForChar(  FindSubFontForChar(
1395      WinFont *fontPtr,           /* The font object with which the character      WinFont *fontPtr,           /* The font object with which the character
1396                                   * will be displayed. */                                   * will be displayed. */
1397      int ch)                     /* The Unicode character to be displayed. */      int ch)                     /* The Unicode character to be displayed. */
1398  {  {
1399      HDC hdc;      HDC hdc;
1400      int i, j, k;      int i, j, k;
1401      CanUse canUse;      CanUse canUse;
1402      char **aliases, **anyFallbacks;      char **aliases, **anyFallbacks;
1403      char ***fontFallbacks;      char ***fontFallbacks;
1404      char *fallbackName;      char *fallbackName;
1405      SubFont *subFontPtr;      SubFont *subFontPtr;
1406      Tcl_DString ds;      Tcl_DString ds;
1407            
1408      if (ch < BASE_CHARS) {      if (ch < BASE_CHARS) {
1409          return &fontPtr->subFontArray[0];          return &fontPtr->subFontArray[0];
1410      }      }
1411    
1412      for (i = 0; i < fontPtr->numSubFonts; i++) {      for (i = 0; i < fontPtr->numSubFonts; i++) {
1413          if (FontMapLookup(&fontPtr->subFontArray[i], ch)) {          if (FontMapLookup(&fontPtr->subFontArray[i], ch)) {
1414              return &fontPtr->subFontArray[i];              return &fontPtr->subFontArray[i];
1415          }          }
1416      }      }
1417    
1418      /*      /*
1419       * Keep track of all face names that we check, so we don't check some       * Keep track of all face names that we check, so we don't check some
1420       * name multiple times if it can be reached by multiple paths.       * name multiple times if it can be reached by multiple paths.
1421       */       */
1422            
1423      Tcl_DStringInit(&ds);      Tcl_DStringInit(&ds);
1424      hdc = GetDC(fontPtr->hwnd);      hdc = GetDC(fontPtr->hwnd);
1425                    
1426      aliases = TkFontGetAliasList(fontPtr->font.fa.family);      aliases = TkFontGetAliasList(fontPtr->font.fa.family);
1427    
1428      fontFallbacks = TkFontGetFallbacks();      fontFallbacks = TkFontGetFallbacks();
1429      for (i = 0; fontFallbacks[i] != NULL; i++) {      for (i = 0; fontFallbacks[i] != NULL; i++) {
1430          for (j = 0; fontFallbacks[i][j] != NULL; j++) {          for (j = 0; fontFallbacks[i][j] != NULL; j++) {
1431              fallbackName = fontFallbacks[i][j];              fallbackName = fontFallbacks[i][j];
1432              if (strcasecmp(fallbackName, fontPtr->font.fa.family) == 0) {              if (strcasecmp(fallbackName, fontPtr->font.fa.family) == 0) {
1433                  /*                  /*
1434                   * If the base font has a fallback...                   * If the base font has a fallback...
1435                   */                   */
1436    
1437                  goto tryfallbacks;                  goto tryfallbacks;
1438              } else if (aliases != NULL) {              } else if (aliases != NULL) {
1439                  /*                  /*
1440                   * Or if an alias for the base font has a fallback...                   * Or if an alias for the base font has a fallback...
1441                   */                   */
1442    
1443                  for (k = 0; aliases[k] != NULL; k++) {                  for (k = 0; aliases[k] != NULL; k++) {
1444                      if (strcasecmp(aliases[k], fallbackName) == 0) {                      if (strcasecmp(aliases[k], fallbackName) == 0) {
1445                          goto tryfallbacks;                          goto tryfallbacks;
1446                      }                      }
1447                  }                  }
1448              }              }
1449          }          }
1450          continue;          continue;
1451    
1452          /*          /*
1453           * ...then see if we can use one of the fallbacks, or an           * ...then see if we can use one of the fallbacks, or an
1454           * alias for one of the fallbacks.           * alias for one of the fallbacks.
1455           */           */
1456    
1457          tryfallbacks:          tryfallbacks:
1458          for (j = 0; fontFallbacks[i][j] != NULL; j++) {          for (j = 0; fontFallbacks[i][j] != NULL; j++) {
1459              fallbackName = fontFallbacks[i][j];              fallbackName = fontFallbacks[i][j];
1460              subFontPtr = CanUseFallbackWithAliases(hdc, fontPtr, fallbackName,              subFontPtr = CanUseFallbackWithAliases(hdc, fontPtr, fallbackName,
1461                      ch, &ds);                      ch, &ds);
1462              if (subFontPtr != NULL) {              if (subFontPtr != NULL) {
1463                  goto end;                  goto end;
1464              }              }
1465          }          }
1466      }      }
1467    
1468      /*      /*
1469       * See if we can use something from the global fallback list.       * See if we can use something from the global fallback list.
1470       */       */
1471    
1472      anyFallbacks = TkFontGetGlobalClass();      anyFallbacks = TkFontGetGlobalClass();
1473      for (i = 0; anyFallbacks[i] != NULL; i++) {      for (i = 0; anyFallbacks[i] != NULL; i++) {
1474          fallbackName = anyFallbacks[i];          fallbackName = anyFallbacks[i];
1475          subFontPtr = CanUseFallbackWithAliases(hdc, fontPtr, fallbackName,          subFontPtr = CanUseFallbackWithAliases(hdc, fontPtr, fallbackName,
1476                  ch, &ds);                  ch, &ds);
1477          if (subFontPtr != NULL) {          if (subFontPtr != NULL) {
1478              goto end;              goto end;
1479          }          }
1480      }      }
1481    
1482      /*      /*
1483       * Try all face names available in the whole system until we       * Try all face names available in the whole system until we
1484       * find one that can be used.       * find one that can be used.
1485       */       */
1486    
1487      canUse.hdc = hdc;      canUse.hdc = hdc;
1488      canUse.fontPtr = fontPtr;      canUse.fontPtr = fontPtr;
1489      canUse.nameTriedPtr = &ds;      canUse.nameTriedPtr = &ds;
1490      canUse.ch = ch;      canUse.ch = ch;
1491      canUse.subFontPtr = NULL;      canUse.subFontPtr = NULL;
1492      if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {      if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
1493          EnumFontFamiliesW(hdc, NULL, (FONTENUMPROCW) WinFontCanUseProc,          EnumFontFamiliesW(hdc, NULL, (FONTENUMPROCW) WinFontCanUseProc,
1494                  (LPARAM) &canUse);                  (LPARAM) &canUse);
1495      } else {      } else {
1496          EnumFontFamiliesA(hdc, NULL, (FONTENUMPROCA) WinFontCanUseProc,          EnumFontFamiliesA(hdc, NULL, (FONTENUMPROCA) WinFontCanUseProc,
1497                  (LPARAM) &canUse);                  (LPARAM) &canUse);
1498      }      }
1499      subFontPtr = canUse.subFontPtr;      subFontPtr = canUse.subFontPtr;
1500    
1501      end:      end:
1502      Tcl_DStringFree(&ds);      Tcl_DStringFree(&ds);
1503            
1504      if (subFontPtr == NULL) {      if (subFontPtr == NULL) {
1505          /*          /*
1506           * No font can display this character.  We will use the base font           * No font can display this character.  We will use the base font
1507           * and have it display the "unknown" character.           * and have it display the "unknown" character.
1508           */           */
1509    
1510          subFontPtr = &fontPtr->subFontArray[0];          subFontPtr = &fontPtr->subFontArray[0];
1511          FontMapInsert(subFontPtr, ch);          FontMapInsert(subFontPtr, ch);
1512      }      }
1513      ReleaseDC(fontPtr->hwnd, hdc);      ReleaseDC(fontPtr->hwnd, hdc);
1514      return subFontPtr;      return subFontPtr;
1515  }  }
1516    
1517  static int CALLBACK  static int CALLBACK
1518  WinFontCanUseProc(  WinFontCanUseProc(
1519      ENUMLOGFONT *lfPtr,         /* Logical-font data. */      ENUMLOGFONT *lfPtr,         /* Logical-font data. */
1520      NEWTEXTMETRIC *tmPtr,       /* Physical-font data (not used). */      NEWTEXTMETRIC *tmPtr,       /* Physical-font data (not used). */
1521      int fontType,               /* Type of font (not used). */      int fontType,               /* Type of font (not used). */
1522      LPARAM lParam)              /* Result object to hold result. */      LPARAM lParam)              /* Result object to hold result. */
1523  {  {
1524      int ch;      int ch;
1525      HDC hdc;      HDC hdc;
1526      WinFont *fontPtr;      WinFont *fontPtr;
1527      CanUse *canUsePtr;      CanUse *canUsePtr;
1528      char *fallbackName;      char *fallbackName;
1529      SubFont *subFontPtr;      SubFont *subFontPtr;
1530      Tcl_DString faceString;      Tcl_DString faceString;
1531      Tcl_DString *nameTriedPtr;      Tcl_DString *nameTriedPtr;
1532    
1533      canUsePtr       = (CanUse *) lParam;      canUsePtr       = (CanUse *) lParam;
1534      ch              = canUsePtr->ch;      ch              = canUsePtr->ch;
1535      hdc             = canUsePtr->hdc;      hdc             = canUsePtr->hdc;
1536      fontPtr         = canUsePtr->fontPtr;      fontPtr         = canUsePtr->fontPtr;
1537      nameTriedPtr    = canUsePtr->nameTriedPtr;      nameTriedPtr    = canUsePtr->nameTriedPtr;
1538    
1539      fallbackName = lfPtr->elfLogFont.lfFaceName;      fallbackName = lfPtr->elfLogFont.lfFaceName;
1540      Tcl_ExternalToUtfDString(systemEncoding, fallbackName, -1, &faceString);      Tcl_ExternalToUtfDString(systemEncoding, fallbackName, -1, &faceString);
1541      fallbackName = Tcl_DStringValue(&faceString);      fallbackName = Tcl_DStringValue(&faceString);
1542    
1543      if (SeenName(fallbackName, nameTriedPtr) == 0) {      if (SeenName(fallbackName, nameTriedPtr) == 0) {
1544          subFontPtr = CanUseFallback(hdc, fontPtr, fallbackName, ch);          subFontPtr = CanUseFallback(hdc, fontPtr, fallbackName, ch);
1545          if (subFontPtr != NULL) {          if (subFontPtr != NULL) {
1546              canUsePtr->subFontPtr = subFontPtr;              canUsePtr->subFontPtr = subFontPtr;
1547              Tcl_DStringFree(&faceString);              Tcl_DStringFree(&faceString);
1548              return 0;              return 0;
1549          }          }
1550      }      }
1551      Tcl_DStringFree(&faceString);      Tcl_DStringFree(&faceString);
1552      return 1;      return 1;
1553  }  }
1554    
1555  /*  /*
1556   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1557   *   *
1558   * FontMapLookup --   * FontMapLookup --
1559   *   *
1560   *      See if the screen font can display the given character.   *      See if the screen font can display the given character.
1561   *   *
1562   * Results:   * Results:
1563   *      The return value is 0 if the screen font cannot display the   *      The return value is 0 if the screen font cannot display the
1564   *      character, non-zero otherwise.   *      character, non-zero otherwise.
1565   *   *
1566   * Side effects:   * Side effects:
1567   *      New pages are added to the font mapping cache whenever the   *      New pages are added to the font mapping cache whenever the
1568   *      character belongs to a page that hasn't been seen before.   *      character belongs to a page that hasn't been seen before.
1569   *      When a page is loaded, information about all the characters on   *      When a page is loaded, information about all the characters on
1570   *      that page is stored, not just for the single character in   *      that page is stored, not just for the single character in
1571   *      question.   *      question.
1572   *   *
1573   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1574   */   */
1575    
1576  static int  static int
1577  FontMapLookup(  FontMapLookup(
1578      SubFont *subFontPtr,        /* Contains font mapping cache to be queried      SubFont *subFontPtr,        /* Contains font mapping cache to be queried
1579                                   * and possibly updated. */                                   * and possibly updated. */
1580      int ch)                     /* Character to be tested. */      int ch)                     /* Character to be tested. */
1581  {  {
1582      int row, bitOffset;      int row, bitOffset;
1583    
1584      row = ch >> FONTMAP_SHIFT;      row = ch >> FONTMAP_SHIFT;
1585      if (subFontPtr->fontMap[row] == NULL) {      if (subFontPtr->fontMap[row] == NULL) {
1586          FontMapLoadPage(subFontPtr, row);          FontMapLoadPage(subFontPtr, row);
1587      }      }
1588      bitOffset = ch & (FONTMAP_BITSPERPAGE - 1);      bitOffset = ch & (FONTMAP_BITSPERPAGE - 1);
1589      return (subFontPtr->fontMap[row][bitOffset >> 3] >> (bitOffset & 7)) & 1;      return (subFontPtr->fontMap[row][bitOffset >> 3] >> (bitOffset & 7)) & 1;
1590  }  }
1591    
1592  /*  /*
1593   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1594   *   *
1595   * FontMapInsert --   * FontMapInsert --
1596   *   *
1597   *      Tell the font mapping cache that the given screen font should be   *      Tell the font mapping cache that the given screen font should be
1598   *      used to display the specified character.  This is called when no   *      used to display the specified character.  This is called when no
1599   *      font on the system can be be found that can display that   *      font on the system can be be found that can display that
1600   *      character; we lie to the font and tell it that it can display   *      character; we lie to the font and tell it that it can display
1601   *      the character, otherwise we would end up re-searching the entire   *      the character, otherwise we would end up re-searching the entire
1602   *      fallback hierarchy every time that character was seen.   *      fallback hierarchy every time that character was seen.
1603   *   *
1604   * Results:   * Results:
1605   *      None.   *      None.
1606   *   *
1607   * Side effects:   * Side effects:
1608   *      New pages are added to the font mapping cache whenever the   *      New pages are added to the font mapping cache whenever the
1609   *      character belongs to a page that hasn't been seen before.   *      character belongs to a page that hasn't been seen before.
1610   *      When a page is loaded, information about all the characters on   *      When a page is loaded, information about all the characters on
1611   *      that page is stored, not just for the single character in   *      that page is stored, not just for the single character in
1612   *      question.   *      question.
1613   *   *
1614   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1615   */   */
1616    
1617  static void  static void
1618  FontMapInsert(  FontMapInsert(
1619      SubFont *subFontPtr,        /* Contains font mapping cache to be      SubFont *subFontPtr,        /* Contains font mapping cache to be
1620                                   * updated. */                                   * updated. */
1621      int ch)                     /* Character to be added to cache. */      int ch)                     /* Character to be added to cache. */
1622  {  {
1623      int row, bitOffset;      int row, bitOffset;
1624    
1625      row = ch >> FONTMAP_SHIFT;      row = ch >> FONTMAP_SHIFT;
1626      if (subFontPtr->fontMap[row] == NULL) {      if (subFontPtr->fontMap[row] == NULL) {
1627          FontMapLoadPage(subFontPtr, row);          FontMapLoadPage(subFontPtr, row);
1628      }      }
1629      bitOffset = ch & (FONTMAP_BITSPERPAGE - 1);      bitOffset = ch & (FONTMAP_BITSPERPAGE - 1);
1630      subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);      subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);
1631  }  }
1632    
1633  /*  /*
1634   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1635   *   *
1636   * FontMapLoadPage --   * FontMapLoadPage --
1637   *   *
1638   *      Load information about all the characters on a given page.   *      Load information about all the characters on a given page.
1639   *      This information consists of one bit per character that indicates   *      This information consists of one bit per character that indicates
1640   *      whether the associated HFONT can (1) or cannot (0) display the   *      whether the associated HFONT can (1) or cannot (0) display the
1641   *      characters on the page.   *      characters on the page.
1642   *   *
1643   * Results:   * Results:
1644   *      None.   *      None.
1645   *   *
1646   * Side effects:   * Side effects:
1647   *      Mempry allocated.   *      Mempry allocated.
1648   *   *
1649   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1650   */   */
1651  static void  static void
1652  FontMapLoadPage(  FontMapLoadPage(
1653      SubFont *subFontPtr,        /* Contains font mapping cache to be      SubFont *subFontPtr,        /* Contains font mapping cache to be
1654                                   * updated. */                                   * updated. */
1655      int row)                    /* Index of the page to be loaded into      int row)                    /* Index of the page to be loaded into
1656                                   * the cache. */                                   * the cache. */
1657  {  {
1658      FontFamily *familyPtr;      FontFamily *familyPtr;
1659      Tcl_Encoding encoding;      Tcl_Encoding encoding;
1660      char src[TCL_UTF_MAX], buf[16];      char src[TCL_UTF_MAX], buf[16];
1661      USHORT *startCount, *endCount;      USHORT *startCount, *endCount;
1662      int i, j, bitOffset, end, segCount;      int i, j, bitOffset, end, segCount;
1663    
1664      subFontPtr->fontMap[row] = (char *) ckalloc(FONTMAP_BITSPERPAGE / 8);      subFontPtr->fontMap[row] = (char *) ckalloc(FONTMAP_BITSPERPAGE / 8);
1665      memset(subFontPtr->fontMap[row], 0, FONTMAP_BITSPERPAGE / 8);      memset(subFontPtr->fontMap[row], 0, FONTMAP_BITSPERPAGE / 8);
1666    
1667      familyPtr = subFontPtr->familyPtr;      familyPtr = subFontPtr->familyPtr;
1668      encoding = familyPtr->encoding;      encoding = familyPtr->encoding;
1669    
1670      if (familyPtr->encoding == unicodeEncoding) {      if (familyPtr->encoding == unicodeEncoding) {
1671          /*          /*
1672           * Font is Unicode.  Few fonts are going to have all characters, so           * Font is Unicode.  Few fonts are going to have all characters, so
1673           * examine the TrueType character existence metrics to determine           * examine the TrueType character existence metrics to determine
1674           * what characters actually exist in this font.           * what characters actually exist in this font.
1675           */           */
1676    
1677          segCount    = familyPtr->segCount;          segCount    = familyPtr->segCount;
1678          startCount  = familyPtr->startCount;          startCount  = familyPtr->startCount;
1679          endCount    = familyPtr->endCount;          endCount    = familyPtr->endCount;
1680    
1681          j = 0;          j = 0;
1682          end = (row + 1) << FONTMAP_SHIFT;          end = (row + 1) << FONTMAP_SHIFT;
1683          for (i = row << FONTMAP_SHIFT; i < end; i++) {          for (i = row << FONTMAP_SHIFT; i < end; i++) {
1684              for ( ; j < segCount; j++) {              for ( ; j < segCount; j++) {
1685                  if (endCount[j] >= i) {                  if (endCount[j] >= i) {
1686                      if (startCount[j] <= i) {                      if (startCount[j] <= i) {
1687                          bitOffset = i & (FONTMAP_BITSPERPAGE - 1);                          bitOffset = i & (FONTMAP_BITSPERPAGE - 1);
1688                          subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);                          subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);
1689                      }                      }
1690                      break;                      break;
1691                  }                  }
1692              }              }
1693          }          }
1694      } else if (familyPtr->isSymbolFont) {      } else if (familyPtr->isSymbolFont) {
1695          /*          /*
1696           * Assume that a symbol font with a known encoding has all the           * Assume that a symbol font with a known encoding has all the
1697           * characters that its encoding claims it supports.             * characters that its encoding claims it supports.  
1698           *                 *      
1699           * The test for "encoding == unicodeEncoding"           * The test for "encoding == unicodeEncoding"
1700           * must occur before this case, to catch all symbol fonts (such           * must occur before this case, to catch all symbol fonts (such
1701           * as {Comic Sans MS} or Wingdings) for which we don't have           * as {Comic Sans MS} or Wingdings) for which we don't have
1702           * encoding information; those symbol fonts are treated as if           * encoding information; those symbol fonts are treated as if
1703           * they were in the Unicode encoding and their symbolic           * they were in the Unicode encoding and their symbolic
1704           * character existence metrics are treated as if they were Unicode           * character existence metrics are treated as if they were Unicode
1705           * character existence metrics.  This way, although we don't know           * character existence metrics.  This way, although we don't know
1706           * the proper Unicode -> symbol font mapping, we can install the           * the proper Unicode -> symbol font mapping, we can install the
1707           * symbol font as the base font and access its glyphs.           * symbol font as the base font and access its glyphs.
1708           */           */
1709    
1710          end = (row + 1) << FONTMAP_SHIFT;          end = (row + 1) << FONTMAP_SHIFT;
1711          for (i = row << FONTMAP_SHIFT; i < end; i++) {          for (i = row << FONTMAP_SHIFT; i < end; i++) {
1712              if (Tcl_UtfToExternal(NULL, encoding, src,              if (Tcl_UtfToExternal(NULL, encoding, src,
1713                      Tcl_UniCharToUtf(i, src), TCL_ENCODING_STOPONERROR, NULL,                      Tcl_UniCharToUtf(i, src), TCL_ENCODING_STOPONERROR, NULL,
1714                      buf, sizeof(buf), NULL, NULL, NULL) != TCL_OK) {                      buf, sizeof(buf), NULL, NULL, NULL) != TCL_OK) {
1715                  continue;                  continue;
1716              }              }
1717              bitOffset = i & (FONTMAP_BITSPERPAGE - 1);              bitOffset = i & (FONTMAP_BITSPERPAGE - 1);
1718              subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);              subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);
1719          }          }
1720      }      }
1721  }  }
1722    
1723  /*  /*
1724   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
1725   *   *
1726   * CanUseFallbackWithAliases --   * CanUseFallbackWithAliases --
1727   *   *
1728   *      Helper function for FindSubFontForChar.  Determine if the   *      Helper function for FindSubFontForChar.  Determine if the
1729   *      specified face name (or an alias of the specified face name)   *      specified face name (or an alias of the specified face name)
1730   *      can be used to construct a screen font that can display the   *      can be used to construct a screen font that can display the
1731   *      given character.   *      given character.
1732   *   *
1733   * Results:   * Results:
1734   *      See CanUseFallback().   *      See CanUseFallback().
1735   *   *
1736   * Side effects:   * Side effects:
1737   *      If the name and/or one of its aliases was rejected, the   *      If the name and/or one of its aliases was rejected, the
1738   *      rejected string is recorded in nameTriedPtr so that it won't   *      rejected string is recorded in nameTriedPtr so that it won't
1739   *      be tried again.   *      be tried again.
1740   *   *
1741   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
1742   */   */
1743    
1744  static SubFont *  static SubFont *
1745  CanUseFallbackWithAliases(  CanUseFallbackWithAliases(
1746      HDC hdc,                    /* HDC in which font can be selected. */      HDC hdc,                    /* HDC in which font can be selected. */
1747      WinFont *fontPtr,           /* The font object that will own the new      WinFont *fontPtr,           /* The font object that will own the new
1748                                   * screen font. */                                   * screen font. */
1749      char *faceName,             /* Desired face name for new screen font. */      char *faceName,             /* Desired face name for new screen font. */
1750      int ch,                     /* The Unicode character that the new      int ch,                     /* The Unicode character that the new
1751                                   * screen font must be able to display. */                                   * screen font must be able to display. */
1752      Tcl_DString *nameTriedPtr)  /* Records face names that have already      Tcl_DString *nameTriedPtr)  /* Records face names that have already
1753                                   * been tried.  It is possible for the same                                   * been tried.  It is possible for the same
1754                                   * face name to be queried multiple times when                                   * face name to be queried multiple times when
1755                                   * trying to find a suitable screen font. */                                   * trying to find a suitable screen font. */
1756  {  {
1757      int i;      int i;
1758      char **aliases;      char **aliases;
1759      SubFont *subFontPtr;      SubFont *subFontPtr;
1760            
1761      if (SeenName(faceName, nameTriedPtr) == 0) {      if (SeenName(faceName, nameTriedPtr) == 0) {
1762          subFontPtr = CanUseFallback(hdc, fontPtr, faceName, ch);          subFontPtr = CanUseFallback(hdc, fontPtr, faceName, ch);
1763          if (subFontPtr != NULL) {          if (subFontPtr != NULL) {
1764              return subFontPtr;              return subFontPtr;
1765          }          }
1766      }      }
1767      aliases = TkFontGetAliasList(faceName);      aliases = TkFontGetAliasList(faceName);
1768      if (aliases != NULL) {      if (aliases != NULL) {
1769          for (i = 0; aliases[i] != NULL; i++) {          for (i = 0; aliases[i] != NULL; i++) {
1770              if (SeenName(aliases[i], nameTriedPtr) == 0) {              if (SeenName(aliases[i], nameTriedPtr) == 0) {
1771                  subFontPtr = CanUseFallback(hdc, fontPtr, aliases[i], ch);                  subFontPtr = CanUseFallback(hdc, fontPtr, aliases[i], ch);
1772                  if (subFontPtr != NULL) {                  if (subFontPtr != NULL) {
1773                      return subFontPtr;                      return subFontPtr;
1774                  }                  }
1775              }              }
1776          }          }
1777      }      }
1778      return NULL;      return NULL;
1779  }  }
1780    
1781  /*  /*
1782   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
1783   *   *
1784   * SeenName --   * SeenName --
1785   *   *
1786   *      Used to determine we have already tried and rejected the given   *      Used to determine we have already tried and rejected the given
1787   *      face name when looking for a screen font that can support some   *      face name when looking for a screen font that can support some
1788   *      Unicode character.   *      Unicode character.
1789   *   *
1790   * Results:   * Results:
1791   *      The return value is 0 if this face name has not already been seen,   *      The return value is 0 if this face name has not already been seen,
1792   *      non-zero otherwise.   *      non-zero otherwise.
1793   *   *
1794   * Side effects:   * Side effects:
1795   *      None.   *      None.
1796   *   *
1797   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
1798   */   */
1799    
1800  static int  static int
1801  SeenName(  SeenName(
1802      CONST char *name,           /* The name to check. */      CONST char *name,           /* The name to check. */
1803      Tcl_DString *dsPtr)         /* Contains names that have already been      Tcl_DString *dsPtr)         /* Contains names that have already been
1804                                   * seen. */                                   * seen. */
1805  {  {
1806      CONST char *seen, *end;      CONST char *seen, *end;
1807    
1808      seen = Tcl_DStringValue(dsPtr);      seen = Tcl_DStringValue(dsPtr);
1809      end = seen + Tcl_DStringLength(dsPtr);      end = seen + Tcl_DStringLength(dsPtr);
1810      while (seen < end) {      while (seen < end) {
1811          if (strcasecmp(seen, name) == 0) {          if (strcasecmp(seen, name) == 0) {
1812              return 1;              return 1;
1813          }          }
1814          seen += strlen(seen) + 1;          seen += strlen(seen) + 1;
1815      }      }
1816      Tcl_DStringAppend(dsPtr, (char *) name, (int) (strlen(name) + 1));      Tcl_DStringAppend(dsPtr, (char *) name, (int) (strlen(name) + 1));
1817      return 0;      return 0;
1818  }  }
1819    
1820  /*  /*
1821   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1822   *   *
1823   * CanUseFallback --   * CanUseFallback --
1824   *   *
1825   *      If the specified screen font has not already been loaded into   *      If the specified screen font has not already been loaded into
1826   *      the font object, determine if it can display the given character.   *      the font object, determine if it can display the given character.
1827   *   *
1828   * Results:   * Results:
1829   *      The return value is a pointer to a newly allocated SubFont, owned   *      The return value is a pointer to a newly allocated SubFont, owned
1830   *      by the font object.  This SubFont can be used to display the given   *      by the font object.  This SubFont can be used to display the given
1831   *      character.  The SubFont represents the screen font with the base set   *      character.  The SubFont represents the screen font with the base set
1832   *      of font attributes from the font object, but using the specified   *      of font attributes from the font object, but using the specified
1833   *      font name.  NULL is returned if the font object already holds   *      font name.  NULL is returned if the font object already holds
1834   *      a reference to the specified physical font or if the specified   *      a reference to the specified physical font or if the specified
1835   *      physical font cannot display the given character.   *      physical font cannot display the given character.
1836   *   *
1837   * Side effects:                                         * Side effects:                                      
1838   *      The font object's subFontArray is updated to contain a reference   *      The font object's subFontArray is updated to contain a reference
1839   *      to the newly allocated SubFont.   *      to the newly allocated SubFont.
1840   *   *
1841   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1842   */   */
1843    
1844  static SubFont *  static SubFont *
1845  CanUseFallback(  CanUseFallback(
1846      HDC hdc,                    /* HDC in which font can be selected. */      HDC hdc,                    /* HDC in which font can be selected. */
1847      WinFont *fontPtr,           /* The font object that will own the new      WinFont *fontPtr,           /* The font object that will own the new
1848                                   * screen font. */                                   * screen font. */
1849      char *faceName,             /* Desired face name for new screen font. */      char *faceName,             /* Desired face name for new screen font. */
1850      int ch)                     /* The Unicode character that the new      int ch)                     /* The Unicode character that the new
1851                                   * screen font must be able to display. */                                   * screen font must be able to display. */
1852  {  {
1853      int i;      int i;
1854      HFONT hFont;      HFONT hFont;
1855      SubFont subFont;      SubFont subFont;
1856    
1857      if (FamilyExists(hdc, faceName) == 0) {      if (FamilyExists(hdc, faceName) == 0) {
1858          return NULL;          return NULL;
1859      }      }
1860    
1861      /*      /*
1862       * Skip all fonts we've already used.       * Skip all fonts we've already used.
1863       */       */
1864            
1865      for (i = 0; i < fontPtr->numSubFonts; i++) {      for (i = 0; i < fontPtr->numSubFonts; i++) {
1866          if (faceName == fontPtr->subFontArray[i].familyPtr->faceName) {          if (faceName == fontPtr->subFontArray[i].familyPtr->faceName) {
1867              return NULL;              return NULL;
1868          }          }
1869      }      }
1870    
1871      /*      /*
1872       * Load this font and see if it has the desired character.       * Load this font and see if it has the desired character.
1873       */       */
1874    
1875      hFont = GetScreenFont(&fontPtr->font.fa, faceName, fontPtr->pixelSize);      hFont = GetScreenFont(&fontPtr->font.fa, faceName, fontPtr->pixelSize);
1876      InitSubFont(hdc, hFont, 0, &subFont);      InitSubFont(hdc, hFont, 0, &subFont);
1877      if (((ch < 256) && (subFont.familyPtr->isSymbolFont))      if (((ch < 256) && (subFont.familyPtr->isSymbolFont))
1878              || (FontMapLookup(&subFont, ch) == 0)) {              || (FontMapLookup(&subFont, ch) == 0)) {
1879          /*          /*
1880           * Don't use a symbol font as a fallback font for characters below           * Don't use a symbol font as a fallback font for characters below
1881           * 256.           * 256.
1882           */           */
1883    
1884          ReleaseSubFont(&subFont);          ReleaseSubFont(&subFont);
1885          return NULL;          return NULL;
1886      }      }
1887    
1888      if (fontPtr->numSubFonts >= SUBFONT_SPACE) {      if (fontPtr->numSubFonts >= SUBFONT_SPACE) {
1889          SubFont *newPtr;          SubFont *newPtr;
1890                    
1891          newPtr = (SubFont *) ckalloc(sizeof(SubFont)          newPtr = (SubFont *) ckalloc(sizeof(SubFont)
1892                  * (fontPtr->numSubFonts + 1));                  * (fontPtr->numSubFonts + 1));
1893          memcpy((char *) newPtr, fontPtr->subFontArray,          memcpy((char *) newPtr, fontPtr->subFontArray,
1894                  fontPtr->numSubFonts * sizeof(SubFont));                  fontPtr->numSubFonts * sizeof(SubFont));
1895          if (fontPtr->subFontArray != fontPtr->staticSubFonts) {          if (fontPtr->subFontArray != fontPtr->staticSubFonts) {
1896              ckfree((char *) fontPtr->subFontArray);              ckfree((char *) fontPtr->subFontArray);
1897          }          }
1898          fontPtr->subFontArray = newPtr;          fontPtr->subFontArray = newPtr;
1899      }      }
1900      fontPtr->subFontArray[fontPtr->numSubFonts] = subFont;      fontPtr->subFontArray[fontPtr->numSubFonts] = subFont;
1901      fontPtr->numSubFonts++;      fontPtr->numSubFonts++;
1902      return &fontPtr->subFontArray[fontPtr->numSubFonts - 1];      return &fontPtr->subFontArray[fontPtr->numSubFonts - 1];
1903  }  }
1904    
1905  /*  /*
1906   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
1907   *   *
1908   * GetScreenFont --   * GetScreenFont --
1909   *   *
1910   *      Given the name and other attributes, construct an HFONT.   *      Given the name and other attributes, construct an HFONT.
1911   *      This is where all the alias and fallback substitution bottoms   *      This is where all the alias and fallback substitution bottoms
1912   *      out.   *      out.
1913   *   *
1914   * Results:   * Results:
1915   *      The screen font that corresponds to the attributes.   *      The screen font that corresponds to the attributes.
1916   *   *
1917   * Side effects:   * Side effects:
1918   *      None.   *      None.
1919   *   *
1920   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
1921   */   */
1922    
1923  static HFONT  static HFONT
1924  GetScreenFont(  GetScreenFont(
1925      CONST TkFontAttributes *faPtr,      CONST TkFontAttributes *faPtr,
1926                                  /* Desired font attributes for new HFONT. */                                  /* Desired font attributes for new HFONT. */
1927      CONST char *faceName,       /* Overrides font family specified in font      CONST char *faceName,       /* Overrides font family specified in font
1928                                   * attributes. */                                   * attributes. */
1929      int pixelSize)              /* Overrides size specified in font      int pixelSize)              /* Overrides size specified in font
1930                                   * attributes. */                                   * attributes. */
1931  {  {
1932      Tcl_DString ds;      Tcl_DString ds;
1933      HFONT hFont;      HFONT hFont;
1934      LOGFONTW lf;      LOGFONTW lf;
1935    
1936      lf.lfHeight         = -pixelSize;      lf.lfHeight         = -pixelSize;
1937      lf.lfWidth          = 0;      lf.lfWidth          = 0;
1938      lf.lfEscapement     = 0;      lf.lfEscapement     = 0;
1939      lf.lfOrientation    = 0;      lf.lfOrientation    = 0;
1940      lf.lfWeight         = (faPtr->weight == TK_FW_NORMAL) ? FW_NORMAL : FW_BOLD;      lf.lfWeight         = (faPtr->weight == TK_FW_NORMAL) ? FW_NORMAL : FW_BOLD;
1941      lf.lfItalic         = faPtr->slant;      lf.lfItalic         = faPtr->slant;
1942      lf.lfUnderline      = faPtr->underline;      lf.lfUnderline      = faPtr->underline;
1943      lf.lfStrikeOut      = faPtr->overstrike;      lf.lfStrikeOut      = faPtr->overstrike;
1944      lf.lfCharSet        = DEFAULT_CHARSET;      lf.lfCharSet        = DEFAULT_CHARSET;
1945      lf.lfOutPrecision   = OUT_TT_PRECIS;      lf.lfOutPrecision   = OUT_TT_PRECIS;
1946      lf.lfClipPrecision  = CLIP_DEFAULT_PRECIS;      lf.lfClipPrecision  = CLIP_DEFAULT_PRECIS;
1947      lf.lfQuality        = DEFAULT_QUALITY;      lf.lfQuality        = DEFAULT_QUALITY;
1948      lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;      lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
1949    
1950      Tcl_UtfToExternalDString(systemEncoding, faceName, -1, &ds);      Tcl_UtfToExternalDString(systemEncoding, faceName, -1, &ds);
1951    
1952      if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {      if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
1953          Tcl_UniChar *src, *dst;          Tcl_UniChar *src, *dst;
1954    
1955          /*          /*
1956           * We can only store up to LF_FACESIZE wide characters           * We can only store up to LF_FACESIZE wide characters
1957           */           */
1958          if (Tcl_DStringLength(&ds) >= (LF_FACESIZE * sizeof(WCHAR))) {          if (Tcl_DStringLength(&ds) >= (LF_FACESIZE * sizeof(WCHAR))) {
1959              Tcl_DStringSetLength(&ds, LF_FACESIZE);              Tcl_DStringSetLength(&ds, LF_FACESIZE);
1960          }          }
1961          src = (Tcl_UniChar *) Tcl_DStringValue(&ds);          src = (Tcl_UniChar *) Tcl_DStringValue(&ds);
1962          dst = (Tcl_UniChar *) lf.lfFaceName;          dst = (Tcl_UniChar *) lf.lfFaceName;
1963          while (*src != '\0') {          while (*src != '\0') {
1964              *dst++ = *src++;              *dst++ = *src++;
1965          }          }
1966          *dst = '\0';          *dst = '\0';
1967          hFont = CreateFontIndirectW(&lf);          hFont = CreateFontIndirectW(&lf);
1968      } else {      } else {
1969          /*          /*
1970           * We can only store up to LF_FACESIZE characters           * We can only store up to LF_FACESIZE characters
1971           */           */
1972          if (Tcl_DStringLength(&ds) >= LF_FACESIZE) {          if (Tcl_DStringLength(&ds) >= LF_FACESIZE) {
1973              Tcl_DStringSetLength(&ds, LF_FACESIZE);              Tcl_DStringSetLength(&ds, LF_FACESIZE);
1974          }          }
1975          strcpy((char *) lf.lfFaceName, Tcl_DStringValue(&ds));          strcpy((char *) lf.lfFaceName, Tcl_DStringValue(&ds));
1976          hFont = CreateFontIndirectA((LOGFONTA *) &lf);          hFont = CreateFontIndirectA((LOGFONTA *) &lf);
1977      }      }
1978      Tcl_DStringFree(&ds);      Tcl_DStringFree(&ds);
1979      return hFont;      return hFont;
1980  }  }
1981    
1982  /*  /*
1983   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
1984   *   *
1985   * FamilyExists, FamilyOrAliasExists, WinFontExistsProc --   * FamilyExists, FamilyOrAliasExists, WinFontExistsProc --
1986   *   *
1987   *      Determines if any physical screen font exists on the system with   *      Determines if any physical screen font exists on the system with
1988   *      the given family name.  If the family exists, then it should be   *      the given family name.  If the family exists, then it should be
1989   *      possible to construct some physical screen font with that family   *      possible to construct some physical screen font with that family
1990   *      name.   *      name.
1991   *   *
1992   * Results:   * Results:
1993   *      The return value is 0 if the specified font family does not exist,   *      The return value is 0 if the specified font family does not exist,
1994   *      non-zero otherwise.   *      non-zero otherwise.
1995   *   *
1996   * Side effects:   * Side effects:
1997   *      None.   *      None.
1998   *   *
1999   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
2000   */   */
2001    
2002  static int  static int
2003  FamilyExists(  FamilyExists(
2004      HDC hdc,                    /* HDC in which font family will be used. */      HDC hdc,                    /* HDC in which font family will be used. */
2005      CONST char *faceName)       /* Font family to query. */      CONST char *faceName)       /* Font family to query. */
2006  {  {
2007      int result;      int result;
2008      Tcl_DString faceString;      Tcl_DString faceString;
2009    
2010      /*      /*
2011       * Just immediately rule out the following fonts, because they look so       * Just immediately rule out the following fonts, because they look so
2012       * ugly on windows.  The caller's fallback mechanism will cause the       * ugly on windows.  The caller's fallback mechanism will cause the
2013       * corresponding appropriate TrueType fonts to be selected.       * corresponding appropriate TrueType fonts to be selected.
2014       */       */
2015    
2016      if (strcasecmp(faceName, "Courier") == 0) {      if (strcasecmp(faceName, "Courier") == 0) {
2017          return 0;          return 0;
2018      }      }
2019      if (strcasecmp(faceName, "Times") == 0) {      if (strcasecmp(faceName, "Times") == 0) {
2020          return 0;          return 0;
2021      }      }
2022      if (strcasecmp(faceName, "Helvetica") == 0) {      if (strcasecmp(faceName, "Helvetica") == 0) {
2023          return 0;          return 0;
2024      }      }
2025            
2026      Tcl_UtfToExternalDString(systemEncoding, faceName, -1, &faceString);      Tcl_UtfToExternalDString(systemEncoding, faceName, -1, &faceString);
2027    
2028      /*      /*
2029       * If the family exists, WinFontExistProc() will be called and       * If the family exists, WinFontExistProc() will be called and
2030       * EnumFontFamilies() will return whatever WinFontExistProc() returns.         * EnumFontFamilies() will return whatever WinFontExistProc() returns.  
2031       * If the family doesn't exist, EnumFontFamilies() will just return a       * If the family doesn't exist, EnumFontFamilies() will just return a
2032       * non-zero value.       * non-zero value.
2033       */       */
2034    
2035      if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {      if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
2036          result = EnumFontFamiliesW(hdc, (WCHAR *) Tcl_DStringValue(&faceString),          result = EnumFontFamiliesW(hdc, (WCHAR *) Tcl_DStringValue(&faceString),
2037                  (FONTENUMPROCW) WinFontExistProc, 0);                  (FONTENUMPROCW) WinFontExistProc, 0);
2038      } else {      } else {
2039          result = EnumFontFamiliesA(hdc, (char *) Tcl_DStringValue(&faceString),          result = EnumFontFamiliesA(hdc, (char *) Tcl_DStringValue(&faceString),
2040                  (FONTENUMPROCA) WinFontExistProc, 0);                  (FONTENUMPROCA) WinFontExistProc, 0);
2041      }      }
2042      Tcl_DStringFree(&faceString);      Tcl_DStringFree(&faceString);
2043      return (result == 0);      return (result == 0);
2044  }  }
2045    
2046  static char *  static char *
2047  FamilyOrAliasExists(  FamilyOrAliasExists(
2048      HDC hdc,      HDC hdc,
2049      CONST char *faceName)      CONST char *faceName)
2050  {  {
2051      char **aliases;      char **aliases;
2052      int i;      int i;
2053    
2054      if (FamilyExists(hdc, faceName) != 0) {      if (FamilyExists(hdc, faceName) != 0) {
2055          return (char *) faceName;          return (char *) faceName;
2056      }      }
2057      aliases = TkFontGetAliasList(faceName);      aliases = TkFontGetAliasList(faceName);
2058      if (aliases != NULL) {      if (aliases != NULL) {
2059          for (i = 0; aliases[i] != NULL; i++) {          for (i = 0; aliases[i] != NULL; i++) {
2060              if (FamilyExists(hdc, aliases[i]) != 0) {              if (FamilyExists(hdc, aliases[i]) != 0) {
2061                  return aliases[i];                  return aliases[i];
2062              }              }
2063          }          }
2064      }      }
2065      return NULL;      return NULL;
2066  }  }
2067    
2068  static int CALLBACK  static int CALLBACK
2069  WinFontExistProc(  WinFontExistProc(
2070      ENUMLOGFONT *lfPtr,         /* Logical-font data. */      ENUMLOGFONT *lfPtr,         /* Logical-font data. */
2071      NEWTEXTMETRIC *tmPtr,       /* Physical-font data (not used). */      NEWTEXTMETRIC *tmPtr,       /* Physical-font data (not used). */
2072      int fontType,               /* Type of font (not used). */      int fontType,               /* Type of font (not used). */
2073      LPARAM lParam)              /* EnumFontData to hold result. */      LPARAM lParam)              /* EnumFontData to hold result. */
2074  {  {
2075      return 0;      return 0;
2076  }  }
2077    
2078  /*  /*
2079   * The following data structures are used when querying a TrueType font file   * The following data structures are used when querying a TrueType font file
2080   * to determine which characters the font supports.   * to determine which characters the font supports.
2081   */   */
2082    
2083  #pragma pack(1)                 /* Structures are byte aligned in file. */  #pragma pack(1)                 /* Structures are byte aligned in file. */
2084    
2085  #define CMAPHEX  0x636d6170     /* Key for character map resource. */  #define CMAPHEX  0x636d6170     /* Key for character map resource. */
2086    
2087  typedef struct CMAPTABLE {  typedef struct CMAPTABLE {
2088      USHORT version;             /* Table version number (0). */      USHORT version;             /* Table version number (0). */
2089      USHORT numTables;           /* Number of encoding tables following. */      USHORT numTables;           /* Number of encoding tables following. */
2090  } CMAPTABLE;  } CMAPTABLE;
2091    
2092  typedef struct ENCODINGTABLE {  typedef struct ENCODINGTABLE {
2093      USHORT platform;            /* Platform for which data is targeted.        USHORT platform;            /* Platform for which data is targeted.  
2094                                   * 3 means data is for Windows. */                                   * 3 means data is for Windows. */
2095      USHORT encoding;            /* How characters in font are encoded.        USHORT encoding;            /* How characters in font are encoded.  
2096                                   * 1 means that the following subtable is                                   * 1 means that the following subtable is
2097                                   * keyed based on Unicode. */                                   * keyed based on Unicode. */
2098      ULONG offset;               /* Byte offset from beginning of CMAPTABLE      ULONG offset;               /* Byte offset from beginning of CMAPTABLE
2099                                   * to the subtable for this encoding. */                                   * to the subtable for this encoding. */
2100  } ENCODINGTABLE;  } ENCODINGTABLE;
2101    
2102  typedef struct ANYTABLE {  typedef struct ANYTABLE {
2103      USHORT format;              /* Format number. */      USHORT format;              /* Format number. */
2104      USHORT length;              /* The actual length in bytes of this      USHORT length;              /* The actual length in bytes of this
2105                                   * subtable. */                                   * subtable. */
2106      USHORT version;             /* Version number (starts at 0). */      USHORT version;             /* Version number (starts at 0). */
2107  } ANYTABLE;  } ANYTABLE;
2108    
2109  typedef struct BYTETABLE {  typedef struct BYTETABLE {
2110      USHORT format;              /* Format number is set to 0. */      USHORT format;              /* Format number is set to 0. */
2111      USHORT length;              /* The actual length in bytes of this      USHORT length;              /* The actual length in bytes of this
2112                                   * subtable. */                                   * subtable. */
2113      USHORT version;             /* Version number (starts at 0). */      USHORT version;             /* Version number (starts at 0). */
2114      BYTE glyphIdArray[256];     /* Array that maps up to 256 single-byte char      BYTE glyphIdArray[256];     /* Array that maps up to 256 single-byte char
2115                                   * codes to glyph indices. */                                   * codes to glyph indices. */
2116  } BYTETABLE;  } BYTETABLE;
2117    
2118  typedef struct SUBHEADER {  typedef struct SUBHEADER {
2119      USHORT firstCode;           /* First valid low byte for subHeader. */      USHORT firstCode;           /* First valid low byte for subHeader. */
2120      USHORT entryCount;          /* Number valid low bytes for subHeader. */      USHORT entryCount;          /* Number valid low bytes for subHeader. */
2121      SHORT idDelta;              /* Constant adder to get base glyph index. */      SHORT idDelta;              /* Constant adder to get base glyph index. */
2122      USHORT idRangeOffset;       /* Byte offset from here to appropriate      USHORT idRangeOffset;       /* Byte offset from here to appropriate
2123                                   * glyphIndexArray. */                                   * glyphIndexArray. */
2124  } SUBHEADER;  } SUBHEADER;
2125    
2126  typedef struct HIBYTETABLE {  typedef struct HIBYTETABLE {
2127      USHORT format;              /* Format number is set to 2. */      USHORT format;              /* Format number is set to 2. */
2128      USHORT length;              /* The actual length in bytes of this      USHORT length;              /* The actual length in bytes of this
2129                                   * subtable. */                                   * subtable. */
2130      USHORT version;             /* Version number (starts at 0). */      USHORT version;             /* Version number (starts at 0). */
2131      USHORT subHeaderKeys[256];  /* Maps high bytes to subHeaders: value is      USHORT subHeaderKeys[256];  /* Maps high bytes to subHeaders: value is
2132                                   * subHeader index * 8. */                                   * subHeader index * 8. */
2133  #if 0  #if 0
2134      SUBHEADER subHeaders[];     /* Variable-length array of SUBHEADERs. */      SUBHEADER subHeaders[];     /* Variable-length array of SUBHEADERs. */
2135      USHORT glyphIndexArray[];   /* Variable-length array containing subarrays      USHORT glyphIndexArray[];   /* Variable-length array containing subarrays
2136                                   * used for mapping the low byte of 2-byte                                   * used for mapping the low byte of 2-byte
2137                                   * characters. */                                   * characters. */
2138  #endif  #endif
2139  } HIBYTETABLE;  } HIBYTETABLE;
2140    
2141  typedef struct SEGMENTTABLE {  typedef struct SEGMENTTABLE {
2142      USHORT format;              /* Format number is set to 4. */      USHORT format;              /* Format number is set to 4. */
2143      USHORT length;              /* The actual length in bytes of this      USHORT length;              /* The actual length in bytes of this
2144                                   * subtable. */                                   * subtable. */
2145      USHORT version;             /* Version number (starts at 0). */      USHORT version;             /* Version number (starts at 0). */
2146      USHORT segCountX2;          /* 2 x segCount. */      USHORT segCountX2;          /* 2 x segCount. */
2147      USHORT searchRange;         /* 2 x (2**floor(log2(segCount))). */      USHORT searchRange;         /* 2 x (2**floor(log2(segCount))). */
2148      USHORT entrySelector;       /* log2(searchRange/2). */      USHORT entrySelector;       /* log2(searchRange/2). */
2149      USHORT rangeShift;          /* 2 x segCount - searchRange. */      USHORT rangeShift;          /* 2 x segCount - searchRange. */
2150  #if 0  #if 0
2151      USHORT endCount[segCount]   /* End characterCode for each segment. */      USHORT endCount[segCount]   /* End characterCode for each segment. */
2152      USHORT reservedPad;         /* Set to 0. */      USHORT reservedPad;         /* Set to 0. */
2153      USHORT startCount[segCount];/* Start character code for each segment. */      USHORT startCount[segCount];/* Start character code for each segment. */
2154      USHORT idDelta[segCount];   /* Delta for all character in segment. */      USHORT idDelta[segCount];   /* Delta for all character in segment. */
2155      USHORT idRangeOffset[segCount]; /* Offsets into glyphIdArray or 0. */      USHORT idRangeOffset[segCount]; /* Offsets into glyphIdArray or 0. */
2156      USHORT glyphIdArray[]       /* Glyph index array. */      USHORT glyphIdArray[]       /* Glyph index array. */
2157  #endif  #endif
2158  } SEGMENTTABLE;  } SEGMENTTABLE;
2159    
2160  typedef struct TRIMMEDTABLE {  typedef struct TRIMMEDTABLE {
2161      USHORT format;              /* Format number is set to 6. */      USHORT format;              /* Format number is set to 6. */
2162      USHORT length;              /* The actual length in bytes of this      USHORT length;              /* The actual length in bytes of this
2163                                   * subtable. */                                   * subtable. */
2164      USHORT version;             /* Version number (starts at 0). */      USHORT version;             /* Version number (starts at 0). */
2165      USHORT firstCode;           /* First character code of subrange. */      USHORT firstCode;           /* First character code of subrange. */
2166      USHORT entryCount;          /* Number of character codes in subrange. */      USHORT entryCount;          /* Number of character codes in subrange. */
2167  #if 0  #if 0
2168      USHORT glyphIdArray[];      /* Array of glyph index values for      USHORT glyphIdArray[];      /* Array of glyph index values for
2169                                          character codes in the range. */                                          character codes in the range. */
2170  #endif  #endif
2171  } TRIMMEDTABLE;  } TRIMMEDTABLE;
2172    
2173  typedef union SUBTABLE {  typedef union SUBTABLE {
2174      ANYTABLE any;      ANYTABLE any;
2175      BYTETABLE byte;      BYTETABLE byte;
2176      HIBYTETABLE hiByte;      HIBYTETABLE hiByte;
2177      SEGMENTTABLE segment;      SEGMENTTABLE segment;
2178      TRIMMEDTABLE trimmed;      TRIMMEDTABLE trimmed;
2179  } SUBTABLE;  } SUBTABLE;
2180    
2181  #pragma pack()  #pragma pack()
2182    
2183  /*  /*
2184   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
2185   *   *
2186   * LoadFontRanges --   * LoadFontRanges --
2187   *   *
2188   *      Given an HFONT, get the information about the characters that   *      Given an HFONT, get the information about the characters that
2189   *      this font can display.   *      this font can display.
2190   *   *
2191   * Results:   * Results:
2192   *      If the font has no Unicode character information, the return value   *      If the font has no Unicode character information, the return value
2193   *      is 0 and *startCountPtr and *endCountPtr are filled with NULL.     *      is 0 and *startCountPtr and *endCountPtr are filled with NULL.  
2194   *      Otherwise, *startCountPtr and *endCountPtr are set to pointers to   *      Otherwise, *startCountPtr and *endCountPtr are set to pointers to
2195   *      arrays of TrueType character existence information and the return   *      arrays of TrueType character existence information and the return
2196   *      value is the length of the arrays (the two arrays are always the   *      value is the length of the arrays (the two arrays are always the
2197   *      same length as each other).   *      same length as each other).
2198   *   *
2199   * Side effects:   * Side effects:
2200   *      None.   *      None.
2201   *   *
2202   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
2203   */   */
2204    
2205  static int  static int
2206  LoadFontRanges(  LoadFontRanges(
2207      HDC hdc,                    /* HDC into which font can be selected. */      HDC hdc,                    /* HDC into which font can be selected. */
2208      HFONT hFont,                /* HFONT to query. */      HFONT hFont,                /* HFONT to query. */
2209      USHORT **startCountPtr,     /* Filled with malloced pointer to      USHORT **startCountPtr,     /* Filled with malloced pointer to
2210                                   * character range information. */                                   * character range information. */
2211      USHORT **endCountPtr,       /* Filled with malloced pointer to      USHORT **endCountPtr,       /* Filled with malloced pointer to
2212                                   * character range information. */                                   * character range information. */
2213      int *symbolPtr)      int *symbolPtr)
2214   {   {
2215      int n, i, swapped, offset, cbData, segCount;      int n, i, swapped, offset, cbData, segCount;
2216      DWORD cmapKey;      DWORD cmapKey;
2217      USHORT *startCount, *endCount;      USHORT *startCount, *endCount;
2218      CMAPTABLE cmapTable;      CMAPTABLE cmapTable;
2219      ENCODINGTABLE encTable;      ENCODINGTABLE encTable;
2220      SUBTABLE subTable;      SUBTABLE subTable;
2221      char *s;      char *s;
2222    
2223      segCount = 0;      segCount = 0;
2224      startCount = NULL;      startCount = NULL;
2225      endCount = NULL;      endCount = NULL;
2226      *symbolPtr = 0;      *symbolPtr = 0;
2227    
2228      hFont = SelectObject(hdc, hFont);      hFont = SelectObject(hdc, hFont);
2229    
2230      i = 0;      i = 0;
2231      s = (char *) &i;      s = (char *) &i;
2232      *s = '\1';      *s = '\1';
2233      swapped = 0;      swapped = 0;
2234    
2235      if (i == 1) {      if (i == 1) {
2236          swapped = 1;          swapped = 1;
2237      }      }
2238    
2239      cmapKey = CMAPHEX;      cmapKey = CMAPHEX;
2240      if (swapped) {      if (swapped) {
2241          SwapLong(&cmapKey);          SwapLong(&cmapKey);
2242      }      }
2243    
2244      n = GetFontData(hdc, cmapKey, 0, &cmapTable, sizeof(cmapTable));      n = GetFontData(hdc, cmapKey, 0, &cmapTable, sizeof(cmapTable));
2245      if (n != GDI_ERROR) {      if (n != GDI_ERROR) {
2246          if (swapped) {          if (swapped) {
2247              SwapShort(&cmapTable.numTables);              SwapShort(&cmapTable.numTables);
2248          }          }
2249          for (i = 0; i < cmapTable.numTables; i++) {          for (i = 0; i < cmapTable.numTables; i++) {
2250              offset = sizeof(cmapTable) + i * sizeof(encTable);              offset = sizeof(cmapTable) + i * sizeof(encTable);
2251              GetFontData(hdc, cmapKey, offset, &encTable, sizeof(encTable));              GetFontData(hdc, cmapKey, offset, &encTable, sizeof(encTable));
2252              if (swapped) {              if (swapped) {
2253                  SwapShort(&encTable.platform);                  SwapShort(&encTable.platform);
2254                  SwapShort(&encTable.encoding);                  SwapShort(&encTable.encoding);
2255                  SwapLong(&encTable.offset);                  SwapLong(&encTable.offset);
2256              }              }
2257              if (encTable.platform != 3) {              if (encTable.platform != 3) {
2258                  /*                  /*
2259                   * Not Microsoft encoding.                   * Not Microsoft encoding.
2260                   */                   */
2261    
2262                  continue;                  continue;
2263              }              }
2264              if (encTable.encoding == 0) {              if (encTable.encoding == 0) {
2265                  *symbolPtr = 1;                  *symbolPtr = 1;
2266              } else if (encTable.encoding != 1) {              } else if (encTable.encoding != 1) {
2267                  continue;                  continue;
2268              }              }
2269    
2270              GetFontData(hdc, cmapKey, encTable.offset, &subTable,              GetFontData(hdc, cmapKey, encTable.offset, &subTable,
2271                      sizeof(subTable));                      sizeof(subTable));
2272              if (swapped) {              if (swapped) {
2273                  SwapShort(&subTable.any.format);                  SwapShort(&subTable.any.format);
2274              }              }
2275              if (subTable.any.format == 4) {              if (subTable.any.format == 4) {
2276                  if (swapped) {                  if (swapped) {
2277                      SwapShort(&subTable.segment.segCountX2);                      SwapShort(&subTable.segment.segCountX2);
2278                  }                  }
2279                  segCount = subTable.segment.segCountX2 / 2;                  segCount = subTable.segment.segCountX2 / 2;
2280                  cbData = segCount * sizeof(USHORT);                  cbData = segCount * sizeof(USHORT);
2281    
2282                  startCount = (USHORT *) ckalloc(cbData);                  startCount = (USHORT *) ckalloc(cbData);
2283                  endCount = (USHORT *) ckalloc(cbData);                  endCount = (USHORT *) ckalloc(cbData);
2284    
2285                  offset = encTable.offset + sizeof(subTable.segment);                  offset = encTable.offset + sizeof(subTable.segment);
2286                  GetFontData(hdc, cmapKey, offset, endCount, cbData);                  GetFontData(hdc, cmapKey, offset, endCount, cbData);
2287                  offset += cbData + sizeof(USHORT);                  offset += cbData + sizeof(USHORT);
2288                  GetFontData(hdc, cmapKey, offset, startCount, cbData);                  GetFontData(hdc, cmapKey, offset, startCount, cbData);
2289                  if (swapped) {                  if (swapped) {
2290                      for (i = 0; i < segCount; i++) {                      for (i = 0; i < segCount; i++) {
2291                          SwapShort(&endCount[i]);                          SwapShort(&endCount[i]);
2292                          SwapShort(&startCount[i]);                          SwapShort(&startCount[i]);
2293                      }                      }
2294                  }                  }
2295                  if (*symbolPtr != 0) {                  if (*symbolPtr != 0) {
2296                      /*                      /*
2297                       * Empirically determined:  When a symbol font is                       * Empirically determined:  When a symbol font is
2298                       * loaded, the character existence metrics obtained                       * loaded, the character existence metrics obtained
2299                       * from the system are mildly wrong.  If the real range                       * from the system are mildly wrong.  If the real range
2300                       * of the symbol font is from 0020 to 00FE, then the                       * of the symbol font is from 0020 to 00FE, then the
2301                       * metrics are reported as F020 to F0FE.  When we load                       * metrics are reported as F020 to F0FE.  When we load
2302                       * a symbol font, we must fix the character existence                       * a symbol font, we must fix the character existence
2303                       * metrics.                       * metrics.
2304                       *                       *
2305                       * Symbol fonts should only use the symbol encoding                       * Symbol fonts should only use the symbol encoding
2306                       * for 8-bit characters [note Bug: 2406]                       * for 8-bit characters [note Bug: 2406]
2307                       */                       */
2308    
2309                      for (i = 0; i < segCount; i++) {                      for (i = 0; i < segCount; i++) {
2310                          if (((startCount[i] & 0xff00) == 0xf000)                          if (((startCount[i] & 0xff00) == 0xf000)
2311                                  && ((endCount[i] & 0xff00) == 0xf000)) {                                  && ((endCount[i] & 0xff00) == 0xf000)) {
2312                              startCount[i] &= 0xff;                              startCount[i] &= 0xff;
2313                              endCount[i] &= 0xff;                              endCount[i] &= 0xff;
2314                          }                          }
2315                      }                      }
2316                  }                  }
2317              }              }
2318          }          }
2319      }      }
2320      SelectObject(hdc, hFont);      SelectObject(hdc, hFont);
2321    
2322      *startCountPtr = startCount;      *startCountPtr = startCount;
2323      *endCountPtr = endCount;      *endCountPtr = endCount;
2324      return segCount;      return segCount;
2325  }  }
2326    
2327  /*  /*
2328   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
2329   *   *
2330   * SwapShort, SwapLong --   * SwapShort, SwapLong --
2331   *   *
2332   *      Helper functions to convert the data loaded from TrueType font   *      Helper functions to convert the data loaded from TrueType font
2333   *      files to Intel byte ordering.   *      files to Intel byte ordering.
2334   *   *
2335   * Results:   * Results:
2336   *      Bytes of input value are swapped and stored back in argument.   *      Bytes of input value are swapped and stored back in argument.
2337   *   *
2338   * Side effects:   * Side effects:
2339   *      None.   *      None.
2340   *   *
2341   *-------------------------------------------------------------------------   *-------------------------------------------------------------------------
2342   */   */
2343    
2344  static void  static void
2345  SwapShort(PUSHORT p)  SwapShort(PUSHORT p)
2346  {  {
2347      *p = (SHORT)(HIBYTE(*p) + (LOBYTE(*p) << 8));      *p = (SHORT)(HIBYTE(*p) + (LOBYTE(*p) << 8));
2348  }  }
2349    
2350  static void  static void
2351  SwapLong(PULONG p)  SwapLong(PULONG p)
2352  {                                              {                                            
2353      ULONG temp;      ULONG temp;
2354    
2355      temp = (LONG) ((BYTE) *p);      temp = (LONG) ((BYTE) *p);
2356      temp <<= 8;      temp <<= 8;
2357      *p >>=8;      *p >>=8;
2358    
2359      temp += (LONG) ((BYTE) *p);      temp += (LONG) ((BYTE) *p);
2360      temp <<= 8;      temp <<= 8;
2361      *p >>=8;      *p >>=8;
2362    
2363      temp += (LONG) ((BYTE) *p);      temp += (LONG) ((BYTE) *p);
2364      temp <<= 8;      temp <<= 8;
2365      *p >>=8;      *p >>=8;
2366    
2367      temp += (LONG) ((BYTE) *p);      temp += (LONG) ((BYTE) *p);
2368      *p = temp;      *p = temp;
2369  }  }
2370    
2371  /* End of tkwinfont.c */  /* End of tkwinfont.c */

Legend:
Removed from v.69  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25