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