1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  * Copyright (C) 1998-2002 Tor Lillqvist
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20 
21 /*
22  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
26  */
27 
28 #include "config.h"
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32 
33 #include "gdkfont.h"
34 #include "gdkpango.h" /* gdk_pango_context_get() */
35 #include "gdkdisplay.h"
36 #include "gdkprivate-win32.h"
37 
38 static GHashTable *font_name_hash = NULL;
39 static GHashTable *fontset_name_hash = NULL;
40 
41 static void
gdk_font_hash_insert(GdkFontType type,GdkFont * font,const gchar * font_name)42 gdk_font_hash_insert (GdkFontType  type,
43 		      GdkFont     *font,
44 		      const gchar *font_name)
45 {
46   GdkFontPrivateWin32 *private = (GdkFontPrivateWin32 *) font;
47   GHashTable **hashp = (type == GDK_FONT_FONT) ?
48     &font_name_hash : &fontset_name_hash;
49 
50   if (!*hashp)
51     *hashp = g_hash_table_new (g_str_hash, g_str_equal);
52 
53   private->names = g_slist_prepend (private->names, g_strdup (font_name));
54   g_hash_table_insert (*hashp, private->names->data, font);
55 }
56 
57 static void
gdk_font_hash_remove(GdkFontType type,GdkFont * font)58 gdk_font_hash_remove (GdkFontType type,
59 		      GdkFont    *font)
60 {
61   GdkFontPrivateWin32 *private = (GdkFontPrivateWin32 *) font;
62   GSList *tmp_list;
63   GHashTable *hash = (type == GDK_FONT_FONT) ?
64     font_name_hash : fontset_name_hash;
65 
66   tmp_list = private->names;
67   while (tmp_list)
68     {
69       g_hash_table_remove (hash, tmp_list->data);
70       g_free (tmp_list->data);
71 
72       tmp_list = tmp_list->next;
73     }
74 
75   g_slist_free (private->names);
76   private->names = NULL;
77 }
78 
79 static GdkFont *
gdk_font_hash_lookup(GdkFontType type,const gchar * font_name)80 gdk_font_hash_lookup (GdkFontType  type,
81 		      const gchar *font_name)
82 {
83   GdkFont *result;
84   GHashTable *hash = (type == GDK_FONT_FONT) ?
85     font_name_hash : fontset_name_hash;
86 
87   if (!hash)
88     return NULL;
89   else
90     {
91       result = g_hash_table_lookup (hash, font_name);
92       if (result)
93 	gdk_font_ref (result);
94 
95       return result;
96     }
97 }
98 
99 #ifdef G_ENABLE_DEBUG
100 static const char *
charset_name(DWORD charset)101 charset_name (DWORD charset)
102 {
103   switch (charset)
104     {
105     case ANSI_CHARSET: return "ansi";
106     case DEFAULT_CHARSET: return "default";
107     case SYMBOL_CHARSET: return "symbol";
108     case SHIFTJIS_CHARSET: return "shiftjis";
109     case HANGEUL_CHARSET: return "hangeul";
110     case GB2312_CHARSET: return "gb2312";
111     case CHINESEBIG5_CHARSET: return "big5";
112     case JOHAB_CHARSET: return "johab";
113     case HEBREW_CHARSET: return "hebrew";
114     case ARABIC_CHARSET: return "arabic";
115     case GREEK_CHARSET: return "greek";
116     case TURKISH_CHARSET: return "turkish";
117     case VIETNAMESE_CHARSET: return "vietnamese";
118     case THAI_CHARSET: return "thai";
119     case EASTEUROPE_CHARSET: return "easteurope";
120     case RUSSIAN_CHARSET: return "russian";
121     case MAC_CHARSET: return "mac";
122     case BALTIC_CHARSET: return "baltic";
123     }
124   return "unknown";
125 }
126 #endif
127 
128 /* This table classifies Unicode characters according to the Microsoft
129  * Unicode subset numbering. This is based on the table in "Developing
130  * International Software for Windows 95 and Windows NT". This is almost,
131  * but not quite, the same as the official Unicode block table in
132  * Blocks.txt from ftp.unicode.org. The bit number field is the bitfield
133  * number as in the FONTSIGNATURE struct's fsUsb field.
134  * There are some grave bugs in the table in the books. For instance
135  * it claims there are Hangul at U+3400..U+4DFF while this range in
136  * fact contains CJK Unified Ideographs Extension A. Also, the whole
137  * block of Hangul Syllables U+AC00..U+D7A3 is missing from the book.
138  */
139 
140 typedef enum
141 {
142   U_BASIC_LATIN = 0,
143   U_LATIN_1_SUPPLEMENT = 1,
144   U_LATIN_EXTENDED_A = 2,
145   U_LATIN_EXTENDED_B = 3,
146   U_IPA_EXTENSIONS = 4,
147   U_SPACING_MODIFIER_LETTERS = 5,
148   U_COMBINING_DIACRITICAL_MARKS = 6,
149   U_BASIC_GREEK = 7,
150   U_GREEK_SYMBOLS_AND_COPTIC = 8,
151   U_CYRILLIC = 9,
152   U_ARMENIAN = 10,
153   U_HEBREW_EXTENDED = 12,
154   U_BASIC_HEBREW = 11,
155   U_BASIC_ARABIC = 13,
156   U_ARABIC_EXTENDED = 14,
157   U_DEVANAGARI = 15,
158   U_BENGALI = 16,
159   U_GURMUKHI = 17,
160   U_GUJARATI = 18,
161   U_ORIYA = 19,
162   U_TAMIL = 20,
163   U_TELUGU = 21,
164   U_KANNADA = 22,
165   U_MALAYALAM = 23,
166   U_THAI = 24,
167   U_LAO = 25,
168   U_GEORGIAN_EXTENDED = 27,
169   U_BASIC_GEORGIAN = 26,
170   U_HANGUL_JAMO = 28,
171   U_LATIN_EXTENDED_ADDITIONAL = 29,
172   U_GREEK_EXTENDED = 30,
173   U_GENERAL_PUNCTUATION = 31,
174   U_SUPERSCRIPTS_AND_SUBSCRIPTS = 32,
175   U_CURRENCY_SYMBOLS = 33,
176   U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS = 34,
177   U_LETTERLIKE_SYMBOLS = 35,
178   U_NUMBER_FORMS = 36,
179   U_ARROWS = 37,
180   U_MATHEMATICAL_OPERATORS = 38,
181   U_MISCELLANEOUS_TECHNICAL = 39,
182   U_CONTROL_PICTURES = 40,
183   U_OPTICAL_CHARACTER_RECOGNITION = 41,
184   U_ENCLOSED_ALPHANUMERICS = 42,
185   U_BOX_DRAWING = 43,
186   U_BLOCK_ELEMENTS = 44,
187   U_GEOMETRIC_SHAPES = 45,
188   U_MISCELLANEOUS_SYMBOLS = 46,
189   U_DINGBATS = 47,
190   U_CJK_SYMBOLS_AND_PUNCTUATION = 48,
191   U_HIRAGANA = 49,
192   U_KATAKANA = 50,
193   U_BOPOMOFO = 51,
194   U_HANGUL_COMPATIBILITY_JAMO = 52,
195   U_CJK_MISCELLANEOUS = 53,
196   U_ENCLOSED_CJK = 54,
197   U_CJK_COMPATIBILITY = 55,
198   U_HANGUL = 56,
199   U_HANGUL_SUPPLEMENTARY_A = 57,
200   U_HANGUL_SUPPLEMENTARY_B = 58,
201   U_CJK_UNIFIED_IDEOGRAPHS = 59,
202   U_PRIVATE_USE_AREA = 60,
203   U_CJK_COMPATIBILITY_IDEOGRAPHS = 61,
204   U_ALPHABETIC_PRESENTATION_FORMS = 62,
205   U_ARABIC_PRESENTATION_FORMS_A = 63,
206   U_COMBINING_HALF_MARKS = 64,
207   U_CJK_COMPATIBILITY_FORMS = 65,
208   U_SMALL_FORM_VARIANTS = 66,
209   U_ARABIC_PRESENTATION_FORMS_B = 67,
210   U_SPECIALS = 69,
211   U_HALFWIDTH_AND_FULLWIDTH_FORMS = 68,
212   U_LAST_PLUS_ONE
213 } unicode_subset;
214 
215 static struct {
216   wchar_t low, high;
217   unicode_subset bit;
218   gchar *name;
219 } utab[] =
220 {
221   { 0x0000, 0x007E,
222     U_BASIC_LATIN, "Basic Latin" },
223   { 0x00A0, 0x00FF,
224     U_LATIN_1_SUPPLEMENT, "Latin-1 Supplement" },
225   { 0x0100, 0x017F,
226     U_LATIN_EXTENDED_A, "Latin Extended-A" },
227   { 0x0180, 0x024F,
228     U_LATIN_EXTENDED_B, "Latin Extended-B" },
229   { 0x0250, 0x02AF,
230     U_IPA_EXTENSIONS, "IPA Extensions" },
231   { 0x02B0, 0x02FF,
232     U_SPACING_MODIFIER_LETTERS, "Spacing Modifier Letters" },
233   { 0x0300, 0x036F,
234     U_COMBINING_DIACRITICAL_MARKS, "Combining Diacritical Marks" },
235   { 0x0370, 0x03CF,
236     U_BASIC_GREEK, "Basic Greek" },
237   { 0x03D0, 0x03FF,
238     U_GREEK_SYMBOLS_AND_COPTIC, "Greek Symbols and Coptic" },
239   { 0x0400, 0x04FF,
240     U_CYRILLIC, "Cyrillic" },
241   { 0x0530, 0x058F,
242     U_ARMENIAN, "Armenian" },
243   { 0x0590, 0x05CF,
244     U_HEBREW_EXTENDED, "Hebrew Extended" },
245   { 0x05D0, 0x05FF,
246     U_BASIC_HEBREW, "Basic Hebrew" },
247   { 0x0600, 0x0652,
248     U_BASIC_ARABIC, "Basic Arabic" },
249   { 0x0653, 0x06FF,
250     U_ARABIC_EXTENDED, "Arabic Extended" },
251   { 0x0900, 0x097F,
252     U_DEVANAGARI, "Devanagari" },
253   { 0x0980, 0x09FF,
254     U_BENGALI, "Bengali" },
255   { 0x0A00, 0x0A7F,
256     U_GURMUKHI, "Gurmukhi" },
257   { 0x0A80, 0x0AFF,
258     U_GUJARATI, "Gujarati" },
259   { 0x0B00, 0x0B7F,
260     U_ORIYA, "Oriya" },
261   { 0x0B80, 0x0BFF,
262     U_TAMIL, "Tamil" },
263   { 0x0C00, 0x0C7F,
264     U_TELUGU, "Telugu" },
265   { 0x0C80, 0x0CFF,
266     U_KANNADA, "Kannada" },
267   { 0x0D00, 0x0D7F,
268     U_MALAYALAM, "Malayalam" },
269   { 0x0E00, 0x0E7F,
270     U_THAI, "Thai" },
271   { 0x0E80, 0x0EFF,
272     U_LAO, "Lao" },
273   { 0x10A0, 0x10CF,
274     U_GEORGIAN_EXTENDED, "Georgian Extended" },
275   { 0x10D0, 0x10FF,
276     U_BASIC_GEORGIAN, "Basic Georgian" },
277   { 0x1100, 0x11FF,
278     U_HANGUL_JAMO, "Hangul Jamo" },
279   { 0x1E00, 0x1EFF,
280     U_LATIN_EXTENDED_ADDITIONAL, "Latin Extended Additional" },
281   { 0x1F00, 0x1FFF,
282     U_GREEK_EXTENDED, "Greek Extended" },
283   { 0x2000, 0x206F,
284     U_GENERAL_PUNCTUATION, "General Punctuation" },
285   { 0x2070, 0x209F,
286     U_SUPERSCRIPTS_AND_SUBSCRIPTS, "Superscripts and Subscripts" },
287   { 0x20A0, 0x20CF,
288     U_CURRENCY_SYMBOLS, "Currency Symbols" },
289   { 0x20D0, 0x20FF,
290     U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS, "Combining Diacritical Marks for Symbols" },
291   { 0x2100, 0x214F,
292     U_LETTERLIKE_SYMBOLS, "Letterlike Symbols" },
293   { 0x2150, 0x218F,
294     U_NUMBER_FORMS, "Number Forms" },
295   { 0x2190, 0x21FF,
296     U_ARROWS, "Arrows" },
297   { 0x2200, 0x22FF,
298     U_MATHEMATICAL_OPERATORS, "Mathematical Operators" },
299   { 0x2300, 0x23FF,
300     U_MISCELLANEOUS_TECHNICAL, "Miscellaneous Technical" },
301   { 0x2400, 0x243F,
302     U_CONTROL_PICTURES, "Control Pictures" },
303   { 0x2440, 0x245F,
304     U_OPTICAL_CHARACTER_RECOGNITION, "Optical Character Recognition" },
305   { 0x2460, 0x24FF,
306     U_ENCLOSED_ALPHANUMERICS, "Enclosed Alphanumerics" },
307   { 0x2500, 0x257F,
308     U_BOX_DRAWING, "Box Drawing" },
309   { 0x2580, 0x259F,
310     U_BLOCK_ELEMENTS, "Block Elements" },
311   { 0x25A0, 0x25FF,
312     U_GEOMETRIC_SHAPES, "Geometric Shapes" },
313   { 0x2600, 0x26FF,
314     U_MISCELLANEOUS_SYMBOLS, "Miscellaneous Symbols" },
315   { 0x2700, 0x27BF,
316     U_DINGBATS, "Dingbats" },
317   { 0x3000, 0x303F,
318     U_CJK_SYMBOLS_AND_PUNCTUATION, "CJK Symbols and Punctuation" },
319   { 0x3040, 0x309F,
320     U_HIRAGANA, "Hiragana" },
321   { 0x30A0, 0x30FF,
322     U_KATAKANA, "Katakana" },
323   { 0x3100, 0x312F,
324     U_BOPOMOFO, "Bopomofo" },
325   { 0x3130, 0x318F,
326     U_HANGUL_COMPATIBILITY_JAMO, "Hangul Compatibility Jamo" },
327   { 0x3190, 0x319F,
328     U_CJK_MISCELLANEOUS, "CJK Miscellaneous" },
329   { 0x3200, 0x32FF,
330     U_ENCLOSED_CJK, "Enclosed CJK" },
331   { 0x3300, 0x33FF,
332     U_CJK_COMPATIBILITY, "CJK Compatibility" },
333   /* The book claims:
334    * U+3400..U+3D2D = Hangul
335    * U+3D2E..U+44B7 = Hangul Supplementary A
336    * U+44B8..U+4DFF = Hangul Supplementary B
337    * but actually in Unicode
338    * U+3400..U+4DB5 = CJK Unified Ideographs Extension A
339    */
340   { 0x3400, 0x4DB5,
341     U_CJK_UNIFIED_IDEOGRAPHS, "CJK Unified Ideographs Extension A" },
342   { 0x4E00, 0x9FFF,
343     U_CJK_UNIFIED_IDEOGRAPHS, "CJK Unified Ideographs" },
344   /* This was missing completely from the book's table. */
345   { 0xAC00, 0xD7A3,
346     U_HANGUL, "Hangul Syllables" },
347   { 0xE000, 0xF8FF,
348     U_PRIVATE_USE_AREA, "Private Use Area" },
349   { 0xF900, 0xFAFF,
350     U_CJK_COMPATIBILITY_IDEOGRAPHS, "CJK Compatibility Ideographs" },
351   { 0xFB00, 0xFB4F,
352     U_ALPHABETIC_PRESENTATION_FORMS, "Alphabetic Presentation Forms" },
353   { 0xFB50, 0xFDFF,
354     U_ARABIC_PRESENTATION_FORMS_A, "Arabic Presentation Forms-A" },
355   { 0xFE20, 0xFE2F,
356     U_COMBINING_HALF_MARKS, "Combining Half Marks" },
357   { 0xFE30, 0xFE4F,
358     U_CJK_COMPATIBILITY_FORMS, "CJK Compatibility Forms" },
359   { 0xFE50, 0xFE6F,
360     U_SMALL_FORM_VARIANTS, "Small Form Variants" },
361   { 0xFE70, 0xFEFE,
362     U_ARABIC_PRESENTATION_FORMS_B, "Arabic Presentation Forms-B" },
363   { 0xFEFF, 0xFEFF,
364     U_SPECIALS, "Specials" },
365   { 0xFF00, 0xFFEF,
366     U_HALFWIDTH_AND_FULLWIDTH_FORMS, "Halfwidth and Fullwidth Forms" },
367   { 0xFFF0, 0xFFFD,
368     U_SPECIALS, "Specials" }
369 };
370 
371 #ifdef G_ENABLE_DEBUG
372 static void
print_unicode_subranges(FONTSIGNATURE * fsp)373 print_unicode_subranges (FONTSIGNATURE *fsp)
374 {
375   int i;
376   gboolean checked[G_N_ELEMENTS (utab)];
377   gboolean need_comma = FALSE;
378 
379   memset (checked, 0, sizeof (checked));
380 
381   for (i = 0; i < G_N_ELEMENTS (utab); i++)
382     if (!checked[i]
383 	&& (fsp->fsUsb[utab[i].bit/32] & (1 << (utab[i].bit % 32))))
384       {
385 	g_print ("%s %s", (need_comma ? "," : ""), utab[i].name);
386 	need_comma = TRUE;
387 	checked[i] = TRUE;
388       }
389   if (!need_comma)
390     g_print (" none!");
391   g_print ("\n");
392 }
393 #endif
394 
395 static gboolean
check_unicode_subranges(UINT charset,FONTSIGNATURE * fsp)396 check_unicode_subranges (UINT           charset,
397 			 FONTSIGNATURE *fsp)
398 {
399   gint i;
400   gboolean retval = FALSE;
401 
402   /* If the fsUsb bit array has at least one of the bits set, trust it */
403   for (i = 0; i < U_LAST_PLUS_ONE; i++)
404     if (i != U_PRIVATE_USE_AREA && (fsp->fsUsb[i/32] & (1 << (i % 32))))
405       return FALSE;
406 
407   /* Otherwise, guess what subranges there should be in the font */
408   fsp->fsUsb[0] = fsp->fsUsb[1] = fsp->fsUsb[2] = fsp->fsUsb[3] = 0;
409 
410 #define set_bit(bitno) (fsp->fsUsb[(bitno)/32] |= (1 << ((bitno) % 32)))
411 
412   /* Set Unicode subrange bits based on code pages supported.
413    * This is mostly just guesswork.
414    */
415 
416 #define check_cp(bit) (fsp->fsCsb[0] & (bit))
417 
418   if (check_cp(FS_LATIN1))
419     {
420       set_bit (U_BASIC_LATIN);
421       set_bit (U_LATIN_1_SUPPLEMENT);
422       set_bit (U_CURRENCY_SYMBOLS);
423       retval = TRUE;
424     }
425   if (check_cp (FS_LATIN2))
426     {
427       set_bit (U_BASIC_LATIN);
428       set_bit (U_LATIN_1_SUPPLEMENT);
429       set_bit (U_LATIN_EXTENDED_A);
430       set_bit (U_CURRENCY_SYMBOLS);
431       retval = TRUE;
432     }
433   if (check_cp (FS_CYRILLIC))
434     {
435       set_bit (U_BASIC_LATIN);
436       set_bit (U_CYRILLIC);
437       retval = TRUE;
438     }
439   if (check_cp (FS_GREEK))
440     {
441       set_bit (U_BASIC_LATIN);
442       set_bit (U_BASIC_GREEK);
443       retval = TRUE;
444     }
445   if (check_cp (FS_TURKISH))
446     {
447       set_bit (U_BASIC_LATIN);
448       set_bit (U_LATIN_1_SUPPLEMENT);
449       set_bit (U_LATIN_EXTENDED_A);
450       set_bit (U_CURRENCY_SYMBOLS);
451       retval = TRUE;
452     }
453   if (check_cp (FS_HEBREW))
454     {
455       set_bit (U_BASIC_LATIN);
456       set_bit (U_CURRENCY_SYMBOLS);
457       set_bit (U_BASIC_HEBREW);
458       set_bit (U_HEBREW_EXTENDED);
459       retval = TRUE;
460     }
461   if (check_cp (FS_ARABIC))
462     {
463       set_bit (U_BASIC_LATIN);
464       set_bit (U_CURRENCY_SYMBOLS);
465       set_bit (U_BASIC_ARABIC);
466       set_bit (U_ARABIC_EXTENDED);
467       retval = TRUE;
468     }
469   if (check_cp (FS_BALTIC))
470     {
471       set_bit (U_BASIC_LATIN);
472       set_bit (U_LATIN_1_SUPPLEMENT);
473       set_bit (U_CURRENCY_SYMBOLS);
474       set_bit (U_LATIN_EXTENDED_A);
475       set_bit (U_LATIN_EXTENDED_B);
476       retval = TRUE;
477     }
478   if (check_cp (FS_VIETNAMESE))
479     {
480       /* ??? */
481       set_bit (U_BASIC_LATIN);
482       retval = TRUE;
483     }
484   if (check_cp (FS_THAI))
485     {
486       set_bit (U_BASIC_LATIN);
487       set_bit (U_THAI);
488       retval = TRUE;
489     }
490   if (check_cp (FS_JISJAPAN))
491     {
492       /* Based on MS Gothic */
493       set_bit (U_BASIC_LATIN);
494       set_bit (U_CJK_SYMBOLS_AND_PUNCTUATION);
495       set_bit (U_HIRAGANA);
496       set_bit (U_KATAKANA);
497       set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
498       set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
499       retval = TRUE;
500     }
501   if (check_cp (FS_CHINESESIMP))
502     {
503       /* Based on MS Hei */
504       set_bit (U_BASIC_LATIN);
505       set_bit (U_HIRAGANA);
506       set_bit (U_KATAKANA);
507       set_bit (U_BOPOMOFO);
508       set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
509       retval = TRUE;
510     }
511   if (check_cp (FS_WANSUNG)
512       || check_cp (FS_JOHAB))	/* ??? */
513     {
514       /* Based on GulimChe. I wonder if all Korean fonts
515        * really support this large range of Unicode subranges?
516        */
517       set_bit (U_BASIC_LATIN);
518       set_bit (U_LATIN_1_SUPPLEMENT);
519       set_bit (U_LATIN_EXTENDED_A);
520       set_bit (U_SPACING_MODIFIER_LETTERS);
521       set_bit (U_BASIC_GREEK);
522       set_bit (U_CYRILLIC);
523       set_bit (U_HANGUL_JAMO);
524       set_bit (U_GENERAL_PUNCTUATION);
525       set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
526       set_bit (U_CURRENCY_SYMBOLS);
527       set_bit (U_LETTERLIKE_SYMBOLS);
528       set_bit (U_NUMBER_FORMS);
529       set_bit (U_ARROWS);
530       set_bit (U_MATHEMATICAL_OPERATORS);
531       set_bit (U_MISCELLANEOUS_TECHNICAL);
532       set_bit (U_ENCLOSED_ALPHANUMERICS);
533       set_bit (U_BOX_DRAWING);
534       set_bit (U_BLOCK_ELEMENTS);
535       set_bit (U_GEOMETRIC_SHAPES);
536       set_bit (U_MISCELLANEOUS_SYMBOLS);
537       set_bit (U_CJK_SYMBOLS_AND_PUNCTUATION);
538       set_bit (U_HIRAGANA);
539       set_bit (U_KATAKANA);
540       set_bit (U_HANGUL_COMPATIBILITY_JAMO);
541       set_bit (U_ENCLOSED_CJK);
542       set_bit (U_CJK_COMPATIBILITY_FORMS);
543       set_bit (U_HANGUL);
544       set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
545       set_bit (U_CJK_COMPATIBILITY_IDEOGRAPHS);
546       set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
547       retval = TRUE;
548     }
549   if (check_cp (FS_CHINESETRAD))
550     {
551       /* Based on MingLiU */
552       set_bit (U_BASIC_LATIN);
553       set_bit (U_GENERAL_PUNCTUATION);
554       set_bit (U_BOX_DRAWING);
555       set_bit (U_BLOCK_ELEMENTS);
556       set_bit (U_CJK_SYMBOLS_AND_PUNCTUATION);
557       set_bit (U_BOPOMOFO);
558       set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
559       set_bit (U_CJK_COMPATIBILITY_IDEOGRAPHS);
560       set_bit (U_SMALL_FORM_VARIANTS);
561       set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
562       retval = TRUE;
563     }
564   if (check_cp (FS_SYMBOL) || charset == MAC_CHARSET)
565     {
566       /* Non-Unicode encoding, I guess. Pretend it covers
567        * the single-byte range of values.
568        */
569       set_bit (U_BASIC_LATIN);
570       set_bit (U_LATIN_1_SUPPLEMENT);
571       retval = TRUE;
572     }
573 
574   if (retval)
575     return TRUE;
576 
577   GDK_NOTE (MISC, g_print ("... No code page bits set!\n"));
578 
579   /* Sigh. Not even any code page bits were set. Guess based on
580    * charset, then. These somewhat optimistic guesses are based on the
581    * table in Appendix M in the book "Developing ..."  mentioned
582    * above.
583    */
584   switch (charset)
585     {
586     case ANSI_CHARSET:
587       set_bit (U_BASIC_LATIN);
588       set_bit (U_LATIN_1_SUPPLEMENT);
589       set_bit (U_LATIN_EXTENDED_A);
590       set_bit (U_LATIN_EXTENDED_B);
591       set_bit (U_SPACING_MODIFIER_LETTERS);
592       set_bit (U_COMBINING_DIACRITICAL_MARKS);
593       set_bit (U_GENERAL_PUNCTUATION);
594       set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
595       set_bit (U_CURRENCY_SYMBOLS);
596 #if 0 /* I find this too hard to believe... */
597       set_bit (U_BASIC_GREEK);
598       set_bit (U_CYRILLIC);
599       set_bit (U_BASIC_HEBREW);
600       set_bit (U_HEBREW_EXTENDED);
601       set_bit (U_BASIC_ARABIC);
602       set_bit (U_ARABIC_EXTENDED);
603       set_bit (U_LETTERLIKE_SYMBOLS);
604       set_bit (U_NUMBER_FORMS);
605       set_bit (U_ARROWS);
606       set_bit (U_MATHEMATICAL_OPERATORS);
607       set_bit (U_MISCELLANEOUS_TECHNICAL);
608       set_bit (U_ENCLOSED_ALPHANUMERICS);
609       set_bit (U_BOX_DRAWING);
610       set_bit (U_BLOCK_ELEMENTS);
611       set_bit (U_GEOMETRIC_SHAPES);
612       set_bit (U_MISCELLANEOUS_SYMBOLS);
613       set_bit (U_HIRAGANA);
614       set_bit (U_KATAKANA);
615       set_bit (U_BOPOMOFO);
616       set_bit (U_HANGUL_COMPATIBILITY_JAMO);
617       set_bit (U_CJK_MISCELLANEOUS);
618       set_bit (U_CJK_COMPATIBILITY);
619       set_bit (U_HANGUL);
620       set_bit (U_HANGUL_SUPPLEMENTARY_A);
621       set_bit (U_CJK_COMPATIBILITY_IDEOGRAPHS);
622       set_bit (U_ALPHABETIC_PRESENTATION_FORMS);
623       set_bit (U_SMALL_FORM_VARIANTS);
624       set_bit (U_ARABIC_PRESENTATION_FORMS_B);
625       set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
626       set_bit (U_SPECIALS);
627 #endif
628       retval = TRUE;
629       break;
630     case SYMBOL_CHARSET:
631       /* Unggh */
632       set_bit (U_BASIC_LATIN);
633       set_bit (U_LATIN_1_SUPPLEMENT);
634       retval = TRUE;
635       break;
636     case SHIFTJIS_CHARSET:
637     case HANGEUL_CHARSET:
638     case GB2312_CHARSET:
639     case CHINESEBIG5_CHARSET:
640     case JOHAB_CHARSET:
641       /* The table really does claim these "locales" (it doesn't
642        * talk about charsets per se) cover the same Unicode
643        * subranges
644        */
645       set_bit (U_BASIC_LATIN);
646       set_bit (U_LATIN_1_SUPPLEMENT);
647       set_bit (U_LATIN_EXTENDED_A);
648       set_bit (U_LATIN_EXTENDED_B);
649       set_bit (U_SPACING_MODIFIER_LETTERS);
650       set_bit (U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS);
651       set_bit (U_BASIC_GREEK);
652       set_bit (U_CYRILLIC);
653       set_bit (U_HANGUL_JAMO);
654       set_bit (U_GENERAL_PUNCTUATION);
655       set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
656       set_bit (U_CURRENCY_SYMBOLS);
657       set_bit (U_LETTERLIKE_SYMBOLS);
658       set_bit (U_NUMBER_FORMS);
659       set_bit (U_ARROWS);
660       set_bit (U_MATHEMATICAL_OPERATORS);
661       set_bit (U_MISCELLANEOUS_TECHNICAL);
662       set_bit (U_ENCLOSED_ALPHANUMERICS);
663       set_bit (U_BOX_DRAWING);
664       set_bit (U_BLOCK_ELEMENTS);
665       set_bit (U_GEOMETRIC_SHAPES);
666       set_bit (U_MISCELLANEOUS_SYMBOLS);
667       set_bit (U_CJK_SYMBOLS_AND_PUNCTUATION);
668       set_bit (U_HIRAGANA);
669       set_bit (U_KATAKANA);
670       set_bit (U_BOPOMOFO);
671       set_bit (U_HANGUL_COMPATIBILITY_JAMO);
672       set_bit (U_CJK_MISCELLANEOUS);
673       set_bit (U_CJK_COMPATIBILITY);
674       set_bit (U_HANGUL);
675       set_bit (U_HANGUL_SUPPLEMENTARY_A);
676       set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
677       set_bit (U_CJK_COMPATIBILITY_IDEOGRAPHS);
678       set_bit (U_ALPHABETIC_PRESENTATION_FORMS);
679       set_bit (U_SMALL_FORM_VARIANTS);
680       set_bit (U_ARABIC_PRESENTATION_FORMS_B);
681       set_bit (U_SPECIALS);
682       retval = TRUE;
683       break;
684     case HEBREW_CHARSET:
685       set_bit (U_BASIC_LATIN);
686       set_bit (U_LATIN_1_SUPPLEMENT);
687       set_bit (U_LATIN_EXTENDED_B);
688       set_bit (U_SPACING_MODIFIER_LETTERS);
689       set_bit (U_BASIC_HEBREW);
690       set_bit (U_HEBREW_EXTENDED);
691       set_bit (U_GENERAL_PUNCTUATION);
692       set_bit (U_LETTERLIKE_SYMBOLS);
693       retval = TRUE;
694       break;
695     case ARABIC_CHARSET:
696       set_bit (U_BASIC_LATIN);
697       set_bit (U_LATIN_1_SUPPLEMENT);
698       set_bit (U_LATIN_EXTENDED_A);
699       set_bit (U_LATIN_EXTENDED_B);
700       set_bit (U_SPACING_MODIFIER_LETTERS);
701       set_bit (U_BASIC_GREEK);
702       set_bit (U_BASIC_ARABIC);
703       set_bit (U_ARABIC_EXTENDED);
704       set_bit (U_GENERAL_PUNCTUATION);
705       set_bit (U_LETTERLIKE_SYMBOLS);
706       set_bit (U_ARROWS);
707       set_bit (U_MATHEMATICAL_OPERATORS);
708       set_bit (U_MISCELLANEOUS_TECHNICAL);
709       set_bit (U_BOX_DRAWING);
710       set_bit (U_BLOCK_ELEMENTS);
711       set_bit (U_GEOMETRIC_SHAPES);
712       set_bit (U_MISCELLANEOUS_SYMBOLS);
713       set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
714       retval = TRUE;
715       break;
716     case GREEK_CHARSET:
717       set_bit (U_BASIC_LATIN);
718       set_bit (U_LATIN_1_SUPPLEMENT);
719       set_bit (U_LATIN_EXTENDED_B);
720       set_bit (U_BASIC_GREEK);
721       set_bit (U_GENERAL_PUNCTUATION);
722       set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
723       set_bit (U_LETTERLIKE_SYMBOLS);
724       set_bit (U_ARROWS);
725       set_bit (U_MATHEMATICAL_OPERATORS);
726       set_bit (U_MISCELLANEOUS_TECHNICAL);
727       set_bit (U_BOX_DRAWING);
728       set_bit (U_BLOCK_ELEMENTS);
729       set_bit (U_GEOMETRIC_SHAPES);
730       set_bit (U_MISCELLANEOUS_SYMBOLS);
731       retval = TRUE;
732       break;
733     case TURKISH_CHARSET:
734       set_bit (U_BASIC_LATIN);
735       set_bit (U_LATIN_1_SUPPLEMENT);
736       set_bit (U_LATIN_EXTENDED_A);
737       set_bit (U_LATIN_EXTENDED_B);
738       set_bit (U_SPACING_MODIFIER_LETTERS);
739       set_bit (U_BASIC_GREEK);
740       set_bit (U_GENERAL_PUNCTUATION);
741       set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
742       set_bit (U_CURRENCY_SYMBOLS);
743       set_bit (U_LETTERLIKE_SYMBOLS);
744       set_bit (U_ARROWS);
745       set_bit (U_MATHEMATICAL_OPERATORS);
746       set_bit (U_MISCELLANEOUS_TECHNICAL);
747       set_bit (U_BOX_DRAWING);
748       set_bit (U_BLOCK_ELEMENTS);
749       set_bit (U_GEOMETRIC_SHAPES);
750       set_bit (U_MISCELLANEOUS_SYMBOLS);
751       retval = TRUE;
752       break;
753     case VIETNAMESE_CHARSET:
754     case THAI_CHARSET:
755       /* These are not in the table, so I have no idea */
756       break;
757     case BALTIC_CHARSET:
758       set_bit (U_BASIC_LATIN);
759       set_bit (U_LATIN_1_SUPPLEMENT);
760       set_bit (U_LATIN_EXTENDED_A);
761       set_bit (U_LATIN_EXTENDED_B);
762       set_bit (U_SPACING_MODIFIER_LETTERS);
763       set_bit (U_BASIC_GREEK);
764       set_bit (U_GENERAL_PUNCTUATION);
765       set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
766       set_bit (U_CURRENCY_SYMBOLS);
767       set_bit (U_LETTERLIKE_SYMBOLS);
768       set_bit (U_ARROWS);
769       set_bit (U_MATHEMATICAL_OPERATORS);
770       set_bit (U_MISCELLANEOUS_TECHNICAL);
771       set_bit (U_BOX_DRAWING);
772       set_bit (U_BLOCK_ELEMENTS);
773       set_bit (U_GEOMETRIC_SHAPES);
774       set_bit (U_MISCELLANEOUS_SYMBOLS);
775       retval = TRUE;
776       break;
777     case EASTEUROPE_CHARSET:
778       set_bit (U_BASIC_LATIN);
779       set_bit (U_LATIN_1_SUPPLEMENT);
780       set_bit (U_LATIN_EXTENDED_A);
781       set_bit (U_LATIN_EXTENDED_B);
782       set_bit (U_SPACING_MODIFIER_LETTERS);
783       set_bit (U_BASIC_GREEK);
784       set_bit (U_GENERAL_PUNCTUATION);
785       set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
786       set_bit (U_CURRENCY_SYMBOLS);
787       set_bit (U_LETTERLIKE_SYMBOLS);
788       set_bit (U_ARROWS);
789       set_bit (U_MATHEMATICAL_OPERATORS);
790       set_bit (U_MISCELLANEOUS_TECHNICAL);
791       set_bit (U_BOX_DRAWING);
792       set_bit (U_BLOCK_ELEMENTS);
793       set_bit (U_GEOMETRIC_SHAPES);
794       set_bit (U_MISCELLANEOUS_SYMBOLS);
795       retval = TRUE;
796       break;
797     case RUSSIAN_CHARSET:
798       set_bit (U_BASIC_LATIN);
799       set_bit (U_LATIN_1_SUPPLEMENT);
800       set_bit (U_CYRILLIC);
801       set_bit (U_GENERAL_PUNCTUATION);
802       set_bit (U_LETTERLIKE_SYMBOLS);
803       set_bit (U_ARROWS);
804       set_bit (U_MATHEMATICAL_OPERATORS);
805       set_bit (U_MISCELLANEOUS_TECHNICAL);
806       set_bit (U_BOX_DRAWING);
807       set_bit (U_BLOCK_ELEMENTS);
808       set_bit (U_GEOMETRIC_SHAPES);
809       set_bit (U_MISCELLANEOUS_SYMBOLS);
810       retval = TRUE;
811       break;
812     }
813 
814 #undef set_bit
815   return retval;
816 }
817 
818 static GdkWin32SingleFont *
gdk_font_load_logfont(LOGFONT * lfp)819 gdk_font_load_logfont (LOGFONT *lfp)
820 {
821   GdkWin32SingleFont *singlefont;
822   HFONT hfont;
823   LOGFONT logfont;
824   CHARSETINFO csi;
825   HGDIOBJ oldfont;
826   int tries;
827   gchar face[100];
828 
829   for (tries = 0; ; tries++)
830     {
831       GDK_NOTE (MISC, g_print ("... trying %ld,%ld,%ld,%ld,"
832 			       "%ld,%d,%d,%d,"
833 			       "%d,%d,%d,"
834 			       "%d,%#.02x,\"%s\"\n",
835 			       lfp->lfHeight, lfp->lfWidth,
836 			       lfp->lfEscapement, lfp->lfOrientation,
837 			       lfp->lfWeight, lfp->lfItalic,
838 			       lfp->lfUnderline, lfp->lfStrikeOut,
839 			       lfp->lfCharSet,
840 			       lfp->lfOutPrecision, lfp->lfClipPrecision,
841 			       lfp->lfQuality, lfp->lfPitchAndFamily,
842 			       lfp->lfFaceName));
843       hfont = CreateFontIndirect (lfp);
844 
845       if (hfont != NULL)
846 	break;
847 
848       /* If we fail, try some similar fonts often found on Windows. */
849       if (tries == 0)
850 	{
851 	  if (g_ascii_strcasecmp (lfp->lfFaceName, "helvetica") == 0)
852 	    strcpy (lfp->lfFaceName, "arial");
853 	  else if (g_ascii_strcasecmp (lfp->lfFaceName, "new century schoolbook") == 0)
854 	    strcpy (lfp->lfFaceName, "century schoolbook");
855 	  else if (g_ascii_strcasecmp (lfp->lfFaceName, "courier") == 0)
856 	    strcpy (lfp->lfFaceName, "courier new");
857 	  else if (g_ascii_strcasecmp (lfp->lfFaceName, "lucida") == 0)
858 	    strcpy (lfp->lfFaceName, "lucida sans unicode");
859 	  else if (g_ascii_strcasecmp (lfp->lfFaceName, "lucidatypewriter") == 0)
860 	    strcpy (lfp->lfFaceName, "lucida console");
861 	  else if (g_ascii_strcasecmp (lfp->lfFaceName, "times") == 0)
862 	    strcpy (lfp->lfFaceName, "times new roman");
863 	}
864       else if (tries == 1)
865 	{
866 	  if (g_ascii_strcasecmp (lfp->lfFaceName, "courier") == 0)
867 	    {
868 	      strcpy (lfp->lfFaceName, "");
869 	      lfp->lfPitchAndFamily |= FF_MODERN;
870 	    }
871 	  else if (g_ascii_strcasecmp (lfp->lfFaceName, "times new roman") == 0)
872 	    {
873 	      strcpy (lfp->lfFaceName, "");
874 	      lfp->lfPitchAndFamily |= FF_ROMAN;
875 	    }
876 	  else if (g_ascii_strcasecmp (lfp->lfFaceName, "helvetica") == 0
877 		   || g_ascii_strcasecmp (lfp->lfFaceName, "lucida") == 0)
878 	    {
879 	      strcpy (lfp->lfFaceName, "");
880 	      lfp->lfPitchAndFamily |= FF_SWISS;
881 	    }
882 	  else
883 	    {
884 	      strcpy (lfp->lfFaceName, "");
885 	      lfp->lfPitchAndFamily = (lfp->lfPitchAndFamily & 0x0F) | FF_DONTCARE;
886 	    }
887 	}
888       else
889 	break;
890       tries++;
891     }
892 
893   if (!hfont)
894     return NULL;
895 
896   singlefont = g_new (GdkWin32SingleFont, 1);
897   singlefont->hfont = hfont;
898   GetObject (singlefont->hfont, sizeof (logfont), &logfont);
899   oldfont = SelectObject (_gdk_display_hdc, singlefont->hfont);
900   memset (&singlefont->fs, 0, sizeof (singlefont->fs));
901   singlefont->charset = GetTextCharsetInfo (_gdk_display_hdc, &singlefont->fs, 0);
902   GetTextFace (_gdk_display_hdc, sizeof (face), face);
903   SelectObject (_gdk_display_hdc, oldfont);
904   if (TranslateCharsetInfo ((DWORD *) (gintptr) singlefont->charset, &csi,
905 			    TCI_SRCCHARSET)
906       && singlefont->charset != MAC_CHARSET)
907     singlefont->codepage = csi.ciACP;
908   else
909     singlefont->codepage = 0;
910 
911   GDK_NOTE (MISC, (g_print ("... = %p %s cs %s cp%d\n",
912 			    singlefont->hfont, face,
913 			    charset_name (singlefont->charset),
914 			    singlefont->codepage),
915 		   g_print ("... Unicode subranges:"),
916 		   print_unicode_subranges (&singlefont->fs)));
917   if (check_unicode_subranges (singlefont->charset, &singlefont->fs))
918     GDK_NOTE (MISC, (g_print ("... Guesstimated Unicode subranges:"),
919 		     print_unicode_subranges (&singlefont->fs)));
920 
921   return singlefont;
922 }
923 
924 static GdkWin32SingleFont *
gdk_font_load_internal(const gchar * font_name)925 gdk_font_load_internal (const gchar *font_name)
926 {
927   LOGFONT logfont;
928 
929   char *fn;
930   int numfields, n1, n2;
931   char foundry[32], family[100], weight[32], slant[32], set_width[32],
932     spacing[32], registry[32], encoding[32];
933   char pixel_size[10], point_size[10], res_x[10], res_y[10], avg_width[10];
934   int c;
935   char *p;
936   int logpixelsy;
937 
938   g_return_val_if_fail (font_name != NULL, NULL);
939 
940   GDK_NOTE (MISC, g_print ("gdk_font_load_internal: %s\n", font_name));
941 
942   numfields = sscanf (font_name,
943 		      "-%30[^-]-%100[^-]-%30[^-]-%30[^-]-%30[^-]-%n",
944 		      foundry,
945 		      family,
946 		      weight,
947 		      slant,
948 		      set_width,
949 		      &n1);
950   if (numfields == 0)
951     {
952       /* Probably a plain Windows font name */
953       logfont.lfHeight = 0;
954       logfont.lfWidth = 0;
955       logfont.lfEscapement = 0;
956       logfont.lfOrientation = 0;
957       logfont.lfWeight = FW_DONTCARE;
958       logfont.lfItalic = FALSE;
959       logfont.lfUnderline = FALSE;
960       logfont.lfStrikeOut = FALSE;
961       logfont.lfCharSet = ANSI_CHARSET;
962       logfont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
963       logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
964       logfont.lfQuality = PROOF_QUALITY;
965       logfont.lfPitchAndFamily = DEFAULT_PITCH;
966       fn = g_filename_from_utf8 (font_name, -1, NULL, NULL, NULL);
967       strcpy (logfont.lfFaceName, fn);
968       g_free (fn);
969     }
970   else if (numfields != 5)
971     {
972       g_warning ("gdk_font_load: font name %s illegal", font_name);
973       return NULL;
974     }
975   else
976     {
977       /* It must be a XLFD name */
978 
979       /* Check for hex escapes in the font family,
980        * put in there by logfont_to_xlfd. Convert them in-place.
981        */
982       p = family;
983       while (*p)
984 	{
985 	  if (*p == '%' && isxdigit (p[1]) && isxdigit (p[2]))
986 	    {
987 	      sscanf (p+1, "%2x", &c);
988 	      *p = c;
989 	      strcpy (p+1, p+3);
990 	    }
991 	  p++;
992 	}
993 
994       /* Skip add_style which often is empty in the requested font name */
995       while (font_name[n1] && font_name[n1] != '-')
996 	n1++;
997       numfields++;
998 
999       numfields += sscanf (font_name + n1,
1000 			   "-%8[^-]-%8[^-]-%8[^-]-%8[^-]-%30[^-]-%8[^-]-%30[^-]-%30[^-]%n",
1001 			   pixel_size,
1002 			   point_size,
1003 			   res_x,
1004 			   res_y,
1005 			   spacing,
1006 			   avg_width,
1007 			   registry,
1008 			   encoding,
1009 			   &n2);
1010 
1011       if (numfields != 14 || font_name[n1 + n2] != '\0')
1012 	{
1013 	  g_warning ("gdk_font_load: font name %s illegal", font_name);
1014 	  return NULL;
1015 	}
1016 
1017       logpixelsy = GetDeviceCaps (_gdk_display_hdc, LOGPIXELSY);
1018 
1019       if (strcmp (pixel_size, "*") == 0)
1020 	if (strcmp (point_size, "*") == 0)
1021 	  logfont.lfHeight = 0;
1022 	else
1023 	  logfont.lfHeight = -(int) (((double) atoi (point_size))/720.*logpixelsy);
1024       else
1025 	logfont.lfHeight = -atoi (pixel_size);
1026 
1027       logfont.lfWidth = 0;
1028       logfont.lfEscapement = 0;
1029       logfont.lfOrientation = 0;
1030 
1031       if (g_ascii_strcasecmp (weight, "thin") == 0)
1032 	logfont.lfWeight = FW_THIN;
1033       else if (g_ascii_strcasecmp (weight, "extralight") == 0)
1034 	logfont.lfWeight = FW_EXTRALIGHT;
1035       else if (g_ascii_strcasecmp (weight, "ultralight") == 0)
1036 #ifdef FW_ULTRALIGHT
1037 	logfont.lfWeight = FW_ULTRALIGHT;
1038 #else
1039 	logfont.lfWeight = FW_EXTRALIGHT; /* In fact, FW_ULTRALIGHT really is
1040 					   * defined as FW_EXTRALIGHT anyway.
1041 					   */
1042 #endif
1043       else if (g_ascii_strcasecmp (weight, "light") == 0)
1044 	logfont.lfWeight = FW_LIGHT;
1045       else if (g_ascii_strcasecmp (weight, "normal") == 0)
1046 	logfont.lfWeight = FW_NORMAL;
1047       else if (g_ascii_strcasecmp (weight, "regular") == 0)
1048 	logfont.lfWeight = FW_REGULAR;
1049       else if (g_ascii_strcasecmp (weight, "medium") == 0)
1050 	logfont.lfWeight = FW_MEDIUM;
1051       else if (g_ascii_strcasecmp (weight, "semibold") == 0)
1052 	logfont.lfWeight = FW_SEMIBOLD;
1053       else if (g_ascii_strcasecmp (weight, "demibold") == 0)
1054 #ifdef FW_DEMIBOLD
1055 	logfont.lfWeight = FW_DEMIBOLD;
1056 #else
1057 	logfont.lfWeight = FW_SEMIBOLD;	/* As above */
1058 #endif
1059       else if (g_ascii_strcasecmp (weight, "bold") == 0)
1060 	logfont.lfWeight = FW_BOLD;
1061       else if (g_ascii_strcasecmp (weight, "extrabold") == 0)
1062 	logfont.lfWeight = FW_EXTRABOLD;
1063       else if (g_ascii_strcasecmp (weight, "ultrabold") == 0)
1064 #ifdef FW_ULTRABOLD
1065 	logfont.lfWeight = FW_ULTRABOLD;
1066 #else
1067 	logfont.lfWeight = FW_EXTRABOLD; /* As above */
1068 #endif
1069       else if (g_ascii_strcasecmp (weight, "heavy") == 0)
1070 	logfont.lfWeight = FW_HEAVY;
1071       else if (g_ascii_strcasecmp (weight, "black") == 0)
1072 #ifdef FW_BLACK
1073 	logfont.lfWeight = FW_BLACK;
1074 #else
1075 	logfont.lfWeight = FW_HEAVY;	/* As above */
1076 #endif
1077       else
1078 	logfont.lfWeight = FW_DONTCARE;
1079 
1080       if (g_ascii_strcasecmp (slant, "italic") == 0
1081 	  || g_ascii_strcasecmp (slant, "oblique") == 0
1082 	  || g_ascii_strcasecmp (slant, "i") == 0
1083 	  || g_ascii_strcasecmp (slant, "o") == 0)
1084 	logfont.lfItalic = TRUE;
1085       else
1086 	logfont.lfItalic = FALSE;
1087       logfont.lfUnderline = FALSE;
1088       logfont.lfStrikeOut = FALSE;
1089       if (g_ascii_strcasecmp (registry, "iso8859") == 0)
1090 	if (strcmp (encoding, "1") == 0)
1091 	  logfont.lfCharSet = ANSI_CHARSET;
1092 	else if (strcmp (encoding, "2") == 0)
1093 	  logfont.lfCharSet = EASTEUROPE_CHARSET;
1094 	else if (strcmp (encoding, "7") == 0)
1095 	  logfont.lfCharSet = GREEK_CHARSET;
1096 	else if (strcmp (encoding, "8") == 0)
1097 	  logfont.lfCharSet = HEBREW_CHARSET;
1098 	else if (strcmp (encoding, "9") == 0)
1099 	  logfont.lfCharSet = TURKISH_CHARSET;
1100 	else
1101 	  logfont.lfCharSet = ANSI_CHARSET; /* XXX ??? */
1102       else if (g_ascii_strcasecmp (registry, "jisx0208.1983") == 0)
1103 	logfont.lfCharSet = SHIFTJIS_CHARSET;
1104       else if (g_ascii_strcasecmp (registry, "ksc5601.1987") == 0)
1105 	logfont.lfCharSet = HANGEUL_CHARSET;
1106       else if (g_ascii_strcasecmp (registry, "gb2312.1980") == 0)
1107 	logfont.lfCharSet = GB2312_CHARSET;
1108       else if (g_ascii_strcasecmp (registry, "big5") == 0)
1109 	logfont.lfCharSet = CHINESEBIG5_CHARSET;
1110       else if (g_ascii_strcasecmp (registry, "windows") == 0
1111 	       || g_ascii_strcasecmp (registry, "microsoft") == 0)
1112 	if (g_ascii_strcasecmp (encoding, "symbol") == 0)
1113 	  logfont.lfCharSet = SYMBOL_CHARSET;
1114 	else if (g_ascii_strcasecmp (encoding, "shiftjis") == 0)
1115 	  logfont.lfCharSet = SHIFTJIS_CHARSET;
1116 	else if (g_ascii_strcasecmp (encoding, "gb2312") == 0)
1117 	  logfont.lfCharSet = GB2312_CHARSET;
1118 	else if (g_ascii_strcasecmp (encoding, "hangeul") == 0)
1119 	  logfont.lfCharSet = HANGEUL_CHARSET;
1120 	else if (g_ascii_strcasecmp (encoding, "big5") == 0)
1121 	  logfont.lfCharSet = CHINESEBIG5_CHARSET;
1122 	else if (g_ascii_strcasecmp (encoding, "johab") == 0)
1123 	  logfont.lfCharSet = JOHAB_CHARSET;
1124 	else if (g_ascii_strcasecmp (encoding, "hebrew") == 0)
1125 	  logfont.lfCharSet = HEBREW_CHARSET;
1126 	else if (g_ascii_strcasecmp (encoding, "arabic") == 0)
1127 	  logfont.lfCharSet = ARABIC_CHARSET;
1128 	else if (g_ascii_strcasecmp (encoding, "greek") == 0)
1129 	  logfont.lfCharSet = GREEK_CHARSET;
1130 	else if (g_ascii_strcasecmp (encoding, "turkish") == 0)
1131 	  logfont.lfCharSet = TURKISH_CHARSET;
1132 	else if (g_ascii_strcasecmp (encoding, "easteurope") == 0)
1133 	  logfont.lfCharSet = EASTEUROPE_CHARSET;
1134 	else if (g_ascii_strcasecmp (encoding, "russian") == 0)
1135 	  logfont.lfCharSet = RUSSIAN_CHARSET;
1136 	else if (g_ascii_strcasecmp (encoding, "mac") == 0)
1137 	  logfont.lfCharSet = MAC_CHARSET;
1138 	else if (g_ascii_strcasecmp (encoding, "baltic") == 0)
1139 	  logfont.lfCharSet = BALTIC_CHARSET;
1140 	else if (g_ascii_strcasecmp (encoding, "cp1251") == 0)
1141 	  logfont.lfCharSet = RUSSIAN_CHARSET;
1142 	else
1143 	  logfont.lfCharSet = ANSI_CHARSET; /* XXX ??? */
1144       else
1145 	logfont.lfCharSet = ANSI_CHARSET; /* XXX ??? */
1146       logfont.lfOutPrecision = OUT_TT_PRECIS;
1147       logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1148       logfont.lfQuality = PROOF_QUALITY;
1149       if (g_ascii_strcasecmp (spacing, "m") == 0)
1150 	logfont.lfPitchAndFamily = FIXED_PITCH;
1151       else if (g_ascii_strcasecmp (spacing, "p") == 0)
1152 	logfont.lfPitchAndFamily = VARIABLE_PITCH;
1153       else
1154 	logfont.lfPitchAndFamily = DEFAULT_PITCH;
1155       fn = g_filename_from_utf8 (family, -1, NULL, NULL, NULL);
1156       strcpy (logfont.lfFaceName, fn);
1157       g_free (fn);
1158     }
1159 
1160   return gdk_font_load_logfont (&logfont);
1161 }
1162 
1163 static GdkFont *
gdk_font_from_one_singlefont(GdkWin32SingleFont * singlefont)1164 gdk_font_from_one_singlefont (GdkWin32SingleFont *singlefont)
1165 {
1166   GdkFont *font;
1167   GdkFontPrivateWin32 *private;
1168   HGDIOBJ oldfont;
1169   TEXTMETRIC textmetric;
1170 
1171   private = g_new (GdkFontPrivateWin32, 1);
1172   font = (GdkFont*) private;
1173 
1174   private->base.ref_count = 1;
1175   private->names = NULL;
1176   private->fonts = g_slist_append (NULL, singlefont);
1177 
1178   /* Pretend all fonts are fontsets... Gtktext and gtkentry work better
1179    * that way, they use wide chars, which is necessary for non-ASCII
1180    * chars to work. (Yes, even Latin-1, as we use Unicode internally.)
1181    */
1182   font->type = GDK_FONT_FONTSET;
1183   oldfont = SelectObject (_gdk_display_hdc, singlefont->hfont);
1184   GetTextMetrics (_gdk_display_hdc, &textmetric);
1185   SelectObject (_gdk_display_hdc, oldfont);
1186   font->ascent = textmetric.tmAscent;
1187   font->descent = textmetric.tmDescent;
1188 
1189   GDK_NOTE (MISC, g_print ("... asc %d desc %d\n",
1190 			   font->ascent, font->descent));
1191 
1192   return font;
1193 }
1194 
1195 GdkFont*
gdk_font_load_for_display(GdkDisplay * display,const gchar * font_name)1196 gdk_font_load_for_display (GdkDisplay  *display,
1197                            const gchar *font_name)
1198 {
1199   GdkFont *font;
1200   GdkFontPrivateWin32 *private;
1201   GdkWin32SingleFont *singlefont;
1202   HGDIOBJ oldfont;
1203   TEXTMETRIC textmetric;
1204 
1205   g_return_val_if_fail (font_name != NULL, NULL);
1206   g_return_val_if_fail (display == gdk_display_get_default (), NULL);
1207 
1208   font = gdk_font_hash_lookup (GDK_FONT_FONTSET, font_name);
1209   if (font)
1210     return font;
1211 
1212   private = g_new (GdkFontPrivateWin32, 1);
1213   font = (GdkFont*) private;
1214 
1215   singlefont = gdk_font_load_internal (font_name);
1216 
1217   private->base.ref_count = 1;
1218   private->names = NULL;
1219   private->fonts = g_slist_append (NULL, singlefont);
1220 
1221   /* Pretend all fonts are fontsets... Gtktext and gtkentry work better
1222    * that way, they use wide chars, which is necessary for non-ASCII
1223    * chars to work. (Yes, even Latin-1, as we use Unicode internally.)
1224    */
1225   font->type = GDK_FONT_FONTSET;
1226   oldfont = SelectObject (_gdk_display_hdc, singlefont->hfont);
1227   GetTextMetrics (_gdk_display_hdc, &textmetric);
1228   SelectObject (_gdk_display_hdc, oldfont);
1229   font->ascent = textmetric.tmAscent;
1230   font->descent = textmetric.tmDescent;
1231 
1232   GDK_NOTE (MISC, g_print ("... asc %d desc %d\n",
1233 			   font->ascent, font->descent));
1234 
1235   gdk_font_hash_insert (GDK_FONT_FONTSET, font, font_name);
1236 
1237   return gdk_font_from_one_singlefont (gdk_font_load_internal (font_name));
1238 }
1239 
1240 GdkFont*
gdk_font_from_description_for_display(GdkDisplay * display,PangoFontDescription * font_desc)1241 gdk_font_from_description_for_display (GdkDisplay           *display,
1242                                        PangoFontDescription *font_desc)
1243 {
1244   LOGFONT logfont;
1245   int size;
1246 
1247   g_return_val_if_fail (font_desc != NULL, NULL);
1248   g_return_val_if_fail (display == gdk_display_get_default (), NULL);
1249 
1250   size = PANGO_PIXELS (pango_font_description_get_size (font_desc));
1251 
1252   logfont.lfHeight = - MulDiv (size,
1253   			       GetDeviceCaps (_gdk_display_hdc, LOGPIXELSY),
1254 			       72);
1255   logfont.lfWidth = 0;
1256   logfont.lfEscapement = 0;
1257   logfont.lfOrientation = 0;
1258   logfont.lfWeight = FW_DONTCARE;
1259   logfont.lfItalic = FALSE;
1260   logfont.lfUnderline = FALSE;
1261   logfont.lfStrikeOut = FALSE;
1262   logfont.lfCharSet = ANSI_CHARSET;
1263   logfont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
1264   logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1265   logfont.lfQuality = PROOF_QUALITY;
1266   logfont.lfPitchAndFamily = DEFAULT_PITCH;
1267   strcpy (logfont.lfFaceName, "Arial");
1268 
1269   return gdk_font_from_one_singlefont (gdk_font_load_logfont (&logfont));
1270 }
1271 
1272 GdkFont*
gdk_fontset_load(const gchar * fontset_name)1273 gdk_fontset_load (const gchar *fontset_name)
1274 {
1275   GdkFont *font;
1276   GdkFontPrivateWin32 *private;
1277   GdkWin32SingleFont *singlefont;
1278   HGDIOBJ oldfont;
1279   TEXTMETRIC textmetric;
1280   gchar *fs;
1281   gchar *b, *p, *s;
1282 
1283   g_return_val_if_fail (fontset_name != NULL, NULL);
1284 
1285   font = gdk_font_hash_lookup (GDK_FONT_FONTSET, fontset_name);
1286   if (font)
1287     return font;
1288 
1289   s = fs = g_strdup (fontset_name);
1290   while (*s && isspace (*s))
1291     s++;
1292 
1293   g_return_val_if_fail (*s, NULL);
1294 
1295   private = g_new (GdkFontPrivateWin32, 1);
1296   font = (GdkFont*) private;
1297 
1298   private->base.ref_count = 1;
1299   private->names = NULL;
1300   private->fonts = NULL;
1301 
1302   font->type = GDK_FONT_FONTSET;
1303   font->ascent = 0;
1304   font->descent = 0;
1305 
1306   while (TRUE)
1307     {
1308       if ((p = strchr (s, ',')) != NULL)
1309 	b = p;
1310       else
1311 	b = s + strlen (s);
1312 
1313       while (isspace (b[-1]))
1314 	b--;
1315       *b = '\0';
1316       singlefont = gdk_font_load_internal (s);
1317       if (singlefont)
1318 	{
1319 	  private->fonts = g_slist_append (private->fonts, singlefont);
1320 	  oldfont = SelectObject (_gdk_display_hdc, singlefont->hfont);
1321 	  GetTextMetrics (_gdk_display_hdc, &textmetric);
1322 	  SelectObject (_gdk_display_hdc, oldfont);
1323 	  font->ascent = MAX (font->ascent, textmetric.tmAscent);
1324 	  font->descent = MAX (font->descent, textmetric.tmDescent);
1325 	}
1326       if (p)
1327 	{
1328 	  s = p + 1;
1329 	  while (*s && isspace (*s))
1330 	    s++;
1331 	}
1332       else
1333 	break;
1334       if (!*s)
1335 	break;
1336     }
1337 
1338   g_free (fs);
1339 
1340   gdk_font_hash_insert (GDK_FONT_FONTSET, font, fontset_name);
1341 
1342   return font;
1343 }
1344 
1345 GdkFont*
gdk_fontset_load_for_display(GdkDisplay * display,const gchar * fontset_name)1346 gdk_fontset_load_for_display (GdkDisplay  *display,
1347 			      const gchar *fontset_name)
1348 {
1349   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1350 
1351   return gdk_fontset_load (fontset_name);
1352 }
1353 
1354 void
_gdk_font_destroy(GdkFont * font)1355 _gdk_font_destroy (GdkFont *font)
1356 {
1357   GdkFontPrivateWin32 *private = (GdkFontPrivateWin32 *) font;
1358   GdkWin32SingleFont *singlefont;
1359   GSList *list;
1360 
1361   singlefont = (GdkWin32SingleFont *) private->fonts->data;
1362   GDK_NOTE (MISC, g_print ("_gdk_font_destroy %p\n",
1363 			   singlefont->hfont));
1364 
1365   gdk_font_hash_remove (font->type, font);
1366 
1367   switch (font->type)
1368     {
1369     case GDK_FONT_FONT:
1370       DeleteObject (singlefont->hfont);
1371       break;
1372 
1373     case GDK_FONT_FONTSET:
1374       list = private->fonts;
1375       while (list)
1376 	{
1377 	  singlefont = (GdkWin32SingleFont *) list->data;
1378 	  DeleteObject (singlefont->hfont);
1379 
1380 	  list = list->next;
1381 	}
1382       g_slist_free (private->fonts);
1383       break;
1384     }
1385   g_free (font);
1386 }
1387 
1388 gint
_gdk_font_strlen(GdkFont * font,const gchar * str)1389 _gdk_font_strlen (GdkFont     *font,
1390 		  const gchar *str)
1391 {
1392   g_return_val_if_fail (font != NULL, -1);
1393   g_return_val_if_fail (str != NULL, -1);
1394 
1395   return strlen (str);
1396 }
1397 
1398 gint
gdk_font_id(const GdkFont * font)1399 gdk_font_id (const GdkFont *font)
1400 {
1401   const GdkFontPrivateWin32 *private;
1402 
1403   g_return_val_if_fail (font != NULL, 0);
1404 
1405   private = (const GdkFontPrivateWin32 *) font;
1406 
1407   /* FIXME: What to do on Win64? */
1408   if (font->type == GDK_FONT_FONT)
1409     return (gint) (gintptr) ((GdkWin32SingleFont *) private->fonts->data)->hfont;
1410   else
1411     return 0;
1412 }
1413 
1414 gboolean
gdk_font_equal(const GdkFont * fonta,const GdkFont * fontb)1415 gdk_font_equal (const GdkFont *fonta,
1416                 const GdkFont *fontb)
1417 {
1418   const GdkFontPrivateWin32 *privatea;
1419   const GdkFontPrivateWin32 *privateb;
1420 
1421   g_return_val_if_fail (fonta != NULL, FALSE);
1422   g_return_val_if_fail (fontb != NULL, FALSE);
1423 
1424   privatea = (const GdkFontPrivateWin32 *) fonta;
1425   privateb = (const GdkFontPrivateWin32 *) fontb;
1426 
1427   if (fonta->type == GDK_FONT_FONT && fontb->type == GDK_FONT_FONT)
1428     return (((GdkWin32SingleFont *) privatea->fonts->data)->hfont
1429 	    == ((GdkWin32SingleFont *) privateb->fonts->data)->hfont);
1430   else if (fonta->type == GDK_FONT_FONTSET && fontb->type == GDK_FONT_FONTSET)
1431     {
1432       GSList *lista = privatea->fonts;
1433       GSList *listb = privateb->fonts;
1434 
1435       while (lista && listb)
1436 	{
1437 	  if (((GdkWin32SingleFont *) lista->data)->hfont
1438 	      != ((GdkWin32SingleFont *) listb->data)->hfont)
1439 	    return FALSE;
1440 	  lista = lista->next;
1441 	  listb = listb->next;
1442 	}
1443       if (lista || listb)
1444 	return FALSE;
1445       else
1446 	return TRUE;
1447     }
1448   else
1449     return FALSE;
1450 }
1451 
1452 /* Return the Unicode Subset bitfield number for a Unicode character */
1453 
1454 static int
unicode_classify(wchar_t wc)1455 unicode_classify (wchar_t wc)
1456 {
1457   int min = 0;
1458   int max = G_N_ELEMENTS (utab) - 1;
1459   int mid;
1460 
1461   while (max >= min)
1462     {
1463       mid = (min + max) / 2;
1464       if (utab[mid].high < wc)
1465 	min = mid + 1;
1466       else if (wc < utab[mid].low)
1467 	max = mid - 1;
1468       else if (utab[mid].low <= wc && wc <= utab[mid].high)
1469 	return utab[mid].bit;
1470       else
1471 	break;
1472     }
1473   /* Fallback... returning -1 might cause problems. Returning
1474    * U_BASIC_LATIN won't help handling strange characters, but won't
1475    * do harm either.
1476    */
1477   return U_BASIC_LATIN;
1478 }
1479 
1480 void
_gdk_wchar_text_handle(GdkFont * font,const wchar_t * wcstr,int wclen,void (* handler)(GdkWin32SingleFont *,const wchar_t *,int,void *),void * arg)1481 _gdk_wchar_text_handle (GdkFont       *font,
1482 		       const wchar_t *wcstr,
1483 		       int            wclen,
1484 		       void         (*handler)(GdkWin32SingleFont *,
1485 					       const wchar_t *,
1486 					       int,
1487 					       void *),
1488 		       void          *arg)
1489 {
1490   GdkFontPrivateWin32 *private;
1491   GdkWin32SingleFont *singlefont;
1492   GSList *list;
1493   int  block;
1494   const wchar_t *start, *end, *wcp;
1495 
1496   wcp = wcstr;
1497   end = wcp + wclen;
1498   private = (GdkFontPrivateWin32 *) font;
1499 
1500   g_assert (private->base.ref_count > 0);
1501 
1502   GDK_NOTE (MISC, g_print ("_gdk_wchar_text_handle: "));
1503 
1504   while (wcp < end)
1505     {
1506       /* Split Unicode string into pieces of the same class */
1507       start = wcp;
1508       block = unicode_classify (*wcp);
1509       while (wcp + 1 < end && unicode_classify (wcp[1]) == block)
1510 	wcp++;
1511 
1512       /* Find a font in the fontset that can handle this class */
1513       list = private->fonts;
1514       while (list)
1515 	{
1516 	  singlefont = (GdkWin32SingleFont *) list->data;
1517 
1518 	  if (singlefont->fs.fsUsb[block/32] & (1 << (block % 32)))
1519 	    break;
1520 
1521 	  list = list->next;
1522 	}
1523 
1524       if (!list)
1525 	singlefont = NULL;
1526 
1527       GDK_NOTE (MISC, g_print ("%" G_GSIZE_FORMAT ":%" G_GSIZE_FORMAT ":%d:%p ",
1528 			       start-wcstr, wcp-wcstr, block,
1529 			       (singlefont ? singlefont->hfont : 0)));
1530 
1531       /* Call the callback function */
1532       (*handler) (singlefont, start, wcp+1 - start, arg);
1533       wcp++;
1534     }
1535   GDK_NOTE (MISC, g_print ("\n"));
1536 }
1537 
1538 typedef struct
1539 {
1540   SIZE total;
1541 } gdk_text_size_arg;
1542 
1543 static void
gdk_text_size_handler(GdkWin32SingleFont * singlefont,const wchar_t * wcstr,int wclen,void * argp)1544 gdk_text_size_handler (GdkWin32SingleFont *singlefont,
1545 		       const wchar_t      *wcstr,
1546 		       int		   wclen,
1547 		       void		  *argp)
1548 {
1549   SIZE this_size;
1550   HGDIOBJ oldfont;
1551   gdk_text_size_arg *arg = (gdk_text_size_arg *) argp;
1552 
1553   if (!singlefont)
1554     return;
1555 
1556   if ((oldfont = SelectObject (_gdk_display_hdc, singlefont->hfont)) == NULL)
1557     {
1558       WIN32_GDI_FAILED ("SelectObject");
1559       return;
1560     }
1561   GetTextExtentPoint32W (_gdk_display_hdc, wcstr, wclen, &this_size);
1562   SelectObject (_gdk_display_hdc, oldfont);
1563 
1564   arg->total.cx += this_size.cx;
1565   arg->total.cy = MAX (arg->total.cy, this_size.cy);
1566 }
1567 
1568 gint
gdk_text_width(GdkFont * font,const gchar * text,gint text_length)1569 gdk_text_width (GdkFont      *font,
1570 		const gchar  *text,
1571 		gint          text_length)
1572 {
1573   gint width = -1;
1574 
1575   gdk_text_extents (font, text, text_length, NULL, NULL, &width, NULL, NULL);
1576 
1577   return width;
1578 }
1579 
1580 gint
gdk_text_width_wc(GdkFont * font,const GdkWChar * text,gint text_length)1581 gdk_text_width_wc (GdkFont	  *font,
1582 		   const GdkWChar *text,
1583 		   gint		   text_length)
1584 {
1585   gint width = -1;
1586 
1587   gdk_text_extents_wc (font, text, text_length, NULL, NULL, &width, NULL, NULL);
1588 
1589   return width;
1590 }
1591 
1592 void
gdk_text_extents(GdkFont * font,const gchar * text,gint text_length,gint * lbearing,gint * rbearing,gint * width,gint * ascent,gint * descent)1593 gdk_text_extents (GdkFont     *font,
1594                   const gchar *text,
1595                   gint         text_length,
1596 		  gint        *lbearing,
1597 		  gint        *rbearing,
1598 		  gint        *width,
1599 		  gint        *ascent,
1600 		  gint        *descent)
1601 {
1602   gdk_text_size_arg arg;
1603   glong wlen;
1604   wchar_t *wcstr, wc;
1605 
1606   g_return_if_fail (font != NULL);
1607   g_return_if_fail (text != NULL);
1608 
1609   if (text_length == 0)
1610     {
1611       if (lbearing)
1612 	*lbearing = 0;
1613       if (rbearing)
1614 	*rbearing = 0;
1615       if (width)
1616 	*width = 0;
1617       if (ascent)
1618 	*ascent = 0;
1619       if (descent)
1620 	*descent = 0;
1621       return;
1622     }
1623 
1624   g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
1625 
1626   arg.total.cx = arg.total.cy = 0;
1627 
1628   if (text_length == 1)
1629     {
1630       wc = (guchar) text[0];
1631       _gdk_wchar_text_handle (font, &wc, 1, gdk_text_size_handler, &arg);
1632     }
1633   else
1634     {
1635       wcstr = g_utf8_to_utf16 (text, text_length, NULL, &wlen, NULL);
1636       _gdk_wchar_text_handle (font, wcstr, wlen, gdk_text_size_handler, &arg);
1637       g_free (wcstr);
1638     }
1639 
1640   /* XXX This is quite bogus */
1641   if (lbearing)
1642     *lbearing = 0;
1643   if (rbearing)
1644     *rbearing = arg.total.cx;
1645   /* What should be the difference between width and rbearing? */
1646   if (width)
1647     *width = arg.total.cx;
1648   if (ascent)
1649     *ascent = arg.total.cy + 1;
1650   if (descent)
1651     *descent = font->descent + 1;
1652 }
1653 
1654 void
gdk_text_extents_wc(GdkFont * font,const GdkWChar * text,gint text_length,gint * lbearing,gint * rbearing,gint * width,gint * ascent,gint * descent)1655 gdk_text_extents_wc (GdkFont        *font,
1656 		     const GdkWChar *text,
1657 		     gint            text_length,
1658 		     gint           *lbearing,
1659 		     gint           *rbearing,
1660 		     gint           *width,
1661 		     gint           *ascent,
1662 		     gint           *descent)
1663 {
1664   gdk_text_size_arg arg;
1665   wchar_t *wcstr;
1666   gint i;
1667 
1668   g_return_if_fail (font != NULL);
1669   g_return_if_fail (text != NULL);
1670 
1671   if (text_length == 0)
1672     {
1673       if (lbearing)
1674 	*lbearing = 0;
1675       if (rbearing)
1676 	*rbearing = 0;
1677       if (width)
1678 	*width = 0;
1679       if (ascent)
1680 	*ascent = 0;
1681       if (descent)
1682 	*descent = 0;
1683       return;
1684     }
1685 
1686   g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
1687 
1688   if (sizeof (wchar_t) != sizeof (GdkWChar))
1689     {
1690       wcstr = g_new (wchar_t, text_length);
1691       for (i = 0; i < text_length; i++)
1692 	wcstr[i] = text[i];
1693     }
1694   else
1695     wcstr = (wchar_t *) text;
1696 
1697   arg.total.cx = arg.total.cy = 0;
1698 
1699   _gdk_wchar_text_handle (font, wcstr, text_length,
1700 			 gdk_text_size_handler, &arg);
1701 
1702   if (sizeof (wchar_t) != sizeof (GdkWChar))
1703     g_free (wcstr);
1704 
1705   /* XXX This is quite bogus */
1706   if (lbearing)
1707     *lbearing = 0;
1708   if (rbearing)
1709     *rbearing = arg.total.cx;
1710   if (width)
1711     *width = arg.total.cx;
1712   if (ascent)
1713     *ascent = arg.total.cy + 1;
1714   if (descent)
1715     *descent = font->descent + 1;
1716 }
1717 
1718 GdkDisplay*
gdk_font_get_display(GdkFont * font)1719 gdk_font_get_display (GdkFont* font)
1720 {
1721   return _gdk_display;
1722 }
1723