1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
35 static GHashTable *font_name_hash = NULL;
36 static GHashTable *fontset_name_hash = NULL;
39 gdk_font_hash_insert (GdkFontType type,
41 const gchar *font_name)
43 GdkFontPrivateWin32 *private = (GdkFontPrivateWin32 *) font;
44 GHashTable **hashp = (type == GDK_FONT_FONT) ?
45 &font_name_hash : &fontset_name_hash;
48 *hashp = g_hash_table_new (g_str_hash, g_str_equal);
50 private->names = g_slist_prepend (private->names, g_strdup (font_name));
51 g_hash_table_insert (*hashp, private->names->data, font);
55 gdk_font_hash_remove (GdkFontType type,
58 GdkFontPrivateWin32 *private = (GdkFontPrivateWin32 *) font;
60 GHashTable *hash = (type == GDK_FONT_FONT) ?
61 font_name_hash : fontset_name_hash;
63 tmp_list = private->names;
66 g_hash_table_remove (hash, tmp_list->data);
67 g_free (tmp_list->data);
69 tmp_list = tmp_list->next;
72 g_slist_free (private->names);
73 private->names = NULL;
77 gdk_font_hash_lookup (GdkFontType type,
78 const gchar *font_name)
81 GHashTable *hash = (type == GDK_FONT_FONT) ?
82 font_name_hash : fontset_name_hash;
88 result = g_hash_table_lookup (hash, font_name);
90 gdk_font_ref (result);
97 charset_name (DWORD charset)
101 case ANSI_CHARSET: return "ansi";
102 case DEFAULT_CHARSET: return "default";
103 case SYMBOL_CHARSET: return "symbol";
104 case SHIFTJIS_CHARSET: return "shiftjis";
105 case HANGEUL_CHARSET: return "hangeul";
106 case GB2312_CHARSET: return "gb2312";
107 case CHINESEBIG5_CHARSET: return "big5";
108 case JOHAB_CHARSET: return "johab";
109 case HEBREW_CHARSET: return "hebrew";
110 case ARABIC_CHARSET: return "arabic";
111 case GREEK_CHARSET: return "greek";
112 case TURKISH_CHARSET: return "turkish";
113 case VIETNAMESE_CHARSET: return "vietnamese";
114 case THAI_CHARSET: return "thai";
115 case EASTEUROPE_CHARSET: return "easteurope";
116 case RUSSIAN_CHARSET: return "russian";
117 case MAC_CHARSET: return "mac";
118 case BALTIC_CHARSET: return "baltic";
123 static gint num_fonts;
124 static gint font_names_size;
125 static gchar **xfontnames;
128 logfont_to_xlfd (const LOGFONT *lfp,
134 const gchar *registry, *encoding;
136 static int logpixelsy = 0;
137 gchar facename[LF_FACESIZE*3];
143 logpixelsy = GetDeviceCaps (gdk_DC, LOGPIXELSY);
146 if (lfp->lfWeight >= FW_HEAVY)
148 else if (lfp->lfWeight >= FW_EXTRABOLD)
149 weight = "extrabold";
150 else if (lfp->lfWeight >= FW_BOLD)
153 else if (lfp->lfWeight >= FW_DEMIBOLD)
156 else if (lfp->lfWeight >= FW_MEDIUM)
158 else if (lfp->lfWeight >= FW_NORMAL)
160 else if (lfp->lfWeight >= FW_LIGHT)
162 else if (lfp->lfWeight >= FW_EXTRALIGHT)
163 weight = "extralight";
164 else if (lfp->lfWeight >= FW_THIN)
169 switch (lfp->lfCharSet)
172 registry = "iso8859";
175 case SHIFTJIS_CHARSET:
176 registry = "jisx0208.1983";
179 case HANGEUL_CHARSET:
180 registry = "ksc5601.1987";
184 registry = "gb2312.1980";
187 case CHINESEBIG5_CHARSET:
192 registry = "iso8859";
195 case TURKISH_CHARSET:
196 registry = "iso8859";
199 #if 0 /* Not a good idea, I think, to use ISO8859-8 and -6 for the Windows
200 * hebrew and arabic codepages, they differ too much.
203 registry = "iso8859";
207 registry = "iso8859";
212 registry = "microsoft";
213 encoding = charset_name (lfp->lfCharSet);
216 point_size = (int) (((double) size/logpixelsy) * 720.);
221 /* Replace illegal characters with hex escapes. */
226 if (*q == '-' || *q == '*' || *q == '?' || *q == '%')
227 p += sprintf (p, "%%%.02x", *q);
234 return g_strdup_printf
235 ("-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d-%s-%s",
240 ((lfp->lfPitchAndFamily & 0xF0) == FF_ROMAN
241 || (lfp->lfPitchAndFamily & 0xF0) == FF_SCRIPT ?
249 ((lfp->lfPitchAndFamily & 0x03) == FIXED_PITCH ? "m" : "p"),
255 gdk_font_full_name_get (GdkFont *font)
257 GdkFontPrivateWin32 *private;
258 GdkWin32SingleFont *singlefont;
264 g_return_val_if_fail (font != NULL, NULL);
266 private = (GdkFontPrivateWin32 *) font;
268 list = private->fonts;
269 string = g_string_new ("");
273 singlefont = (GdkWin32SingleFont *) list->data;
275 if (GetObject (singlefont->xfont, sizeof (LOGFONT), &logfont) == 0)
277 g_warning ("gdk_font_full_name_get: GetObject failed");
282 g_string_append (string,
283 logfont_to_xlfd (&logfont, logfont.lfHeight, -1, 0));
286 string = g_string_append_c (string, ',');
288 result = string->str;
289 g_string_free (string, FALSE);
294 gdk_font_full_name_free (gchar *name)
300 pattern_match (const gchar *pattern,
303 const gchar *p = pattern, *n = string;
306 /* Common case first */
307 if ((pattern[0] == '*'
308 && pattern[1] == '\0')
309 || (pattern[0] == '-'
311 && pattern[2] == '\0'))
314 while ((c = *p++) != '\0')
326 for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
327 if (c == '?' && *n == '\0')
334 for (--p; *n != '\0'; ++n)
335 if (tolower (*n) == c1
336 && pattern_match (p, n))
341 if (c != tolower (*n))
355 InnerEnumFontFamExProc (const LOGFONT *lfp,
356 const TEXTMETRIC *metrics,
363 if (fontType == TRUETYPE_FONTTYPE)
369 size = lfp->lfHeight;
372 xlfd = logfont_to_xlfd (lfp, size, 0, 0);
374 if (!pattern_match ((gchar *) lParam, xlfd))
381 if (num_fonts == font_names_size)
383 font_names_size *= 2;
384 xfontnames = g_realloc (xfontnames, font_names_size * sizeof (gchar *));
386 xfontnames[num_fonts-1] = xlfd;
392 EnumFontFamExProc (const LOGFONT *lfp,
393 const TEXTMETRIC *metrics,
397 if (fontType == TRUETYPE_FONTTYPE)
403 EnumFontFamiliesEx (gdk_DC, &lf, InnerEnumFontFamExProc, lParam, 0);
406 InnerEnumFontFamExProc (lfp, metrics, fontType, lParam);
412 gdk_font_list_new (const gchar *font_pattern,
419 font_names_size = 100;
420 xfontnames = g_new (gchar *, font_names_size);
421 memset (&logfont, 0, sizeof (logfont));
422 logfont.lfCharSet = DEFAULT_CHARSET;
423 EnumFontFamiliesEx (gdk_DC, &logfont, EnumFontFamExProc,
424 (LPARAM) font_pattern, 0);
426 result = g_new (gchar *, num_fonts + 1);
427 memmove (result, xfontnames, num_fonts * sizeof (gchar *));
428 result[num_fonts] = NULL;
431 *n_returned = num_fonts;
436 gdk_font_list_free (gchar **font_list)
438 g_strfreev (font_list);
441 /* This table classifies Unicode characters according to the Microsoft
442 * Unicode subset numbering. This is from the table in "Developing
443 * International Software for Windows 95 and Windows NT". This is almost,
444 * but not quite, the same as the official Unicode block table in
445 * Blocks.txt from ftp.unicode.org. The bit number field is the bitfield
446 * number as in the FONTSIGNATURE struct's fsUsb field.
452 U_LATIN_1_SUPPLEMENT = 1,
453 U_LATIN_EXTENDED_A = 2,
454 U_LATIN_EXTENDED_B = 3,
455 U_IPA_EXTENSIONS = 4,
456 U_SPACING_MODIFIER_LETTERS = 5,
457 U_COMBINING_DIACRITICAL_MARKS = 6,
459 U_GREEK_SYMBOLS_AND_COPTIC = 8,
462 U_HEBREW_EXTENDED = 12,
465 U_ARABIC_EXTENDED = 14,
477 U_GEORGIAN_EXTENDED = 27,
478 U_BASIC_GEORGIAN = 26,
480 U_LATIN_EXTENDED_ADDITIONAL = 29,
481 U_GREEK_EXTENDED = 30,
482 U_GENERAL_PUNCTUATION = 31,
483 U_SUPERSCRIPTS_AND_SUBSCRIPTS = 32,
484 U_CURRENCY_SYMBOLS = 33,
485 U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS = 34,
486 U_LETTERLIKE_SYMBOLS = 35,
489 U_MATHEMATICAL_OPERATORS = 38,
490 U_MISCELLANEOUS_TECHNICAL = 39,
491 U_CONTROL_PICTURES = 40,
492 U_OPTICAL_CHARACTER_RECOGNITION = 41,
493 U_ENCLOSED_ALPHANUMERICS = 42,
495 U_BLOCK_ELEMENTS = 44,
496 U_GEOMETRIC_SHAPES = 45,
497 U_MISCELLANEOUS_SYMBOLS = 46,
499 U_CJK_SYMBOLS_AND_PUNCTUATION = 48,
503 U_HANGUL_COMPATIBILITY_JAMO = 52,
504 U_CJK_MISCELLANEOUS = 53,
506 U_CJK_COMPATIBILITY = 55,
508 U_HANGUL_SUPPLEMENTARY_A = 57,
509 U_HANGUL_SUPPLEMENTARY_B = 58,
510 U_CJK_UNIFIED_IDEOGRAPHS = 59,
511 U_PRIVATE_USE_AREA = 60,
512 U_CJK_COMPATIBILITY_IDEOGRAPHS = 61,
513 U_ALPHABETIC_PRESENTATION_FORMS = 62,
514 U_ARABIC_PRESENTATION_FORMS_A = 63,
515 U_COMBINING_HALF_MARKS = 64,
516 U_CJK_COMPATIBILITY_FORMS = 65,
517 U_SMALL_FORM_VARIANTS = 66,
518 U_ARABIC_PRESENTATION_FORMS_B = 67,
520 U_HALFWIDTH_AND_FULLWIDTH_FORMS = 68,
531 U_BASIC_LATIN, "Basic Latin" },
533 U_LATIN_1_SUPPLEMENT, "Latin-1 Supplement" },
535 U_LATIN_EXTENDED_A, "Latin Extended-A" },
537 U_LATIN_EXTENDED_B, "Latin Extended-B" },
539 U_IPA_EXTENSIONS, "IPA Extensions" },
541 U_SPACING_MODIFIER_LETTERS, "Spacing Modifier Letters" },
543 U_COMBINING_DIACRITICAL_MARKS, "Combining Diacritical Marks" },
545 U_BASIC_GREEK, "Basic Greek" },
547 U_GREEK_SYMBOLS_AND_COPTIC, "Greek Symbols and Coptic" },
549 U_CYRILLIC, "Cyrillic" },
551 U_ARMENIAN, "Armenian" },
553 U_HEBREW_EXTENDED, "Hebrew Extended" },
555 U_BASIC_HEBREW, "Basic Hebrew" },
557 U_BASIC_ARABIC, "Basic Arabic" },
559 U_ARABIC_EXTENDED, "Arabic Extended" },
561 U_DEVANAGARI, "Devanagari" },
563 U_BENGALI, "Bengali" },
565 U_GURMUKHI, "Gurmukhi" },
567 U_GUJARATI, "Gujarati" },
573 U_TELUGU, "Telugu" },
575 U_KANNADA, "Kannada" },
577 U_MALAYALAM, "Malayalam" },
583 U_GEORGIAN_EXTENDED, "Georgian Extended" },
585 U_BASIC_GEORGIAN, "Basic Georgian" },
587 U_HANGUL_JAMO, "Hangul Jamo" },
589 U_LATIN_EXTENDED_ADDITIONAL, "Latin Extended Additional" },
591 U_GREEK_EXTENDED, "Greek Extended" },
593 U_GENERAL_PUNCTUATION, "General Punctuation" },
595 U_SUPERSCRIPTS_AND_SUBSCRIPTS, "Superscripts and Subscripts" },
597 U_CURRENCY_SYMBOLS, "Currency Symbols" },
599 U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS, "Combining Diacritical Marks for Symbols" },
601 U_LETTERLIKE_SYMBOLS, "Letterlike Symbols" },
603 U_NUMBER_FORMS, "Number Forms" },
605 U_ARROWS, "Arrows" },
607 U_MATHEMATICAL_OPERATORS, "Mathematical Operators" },
609 U_MISCELLANEOUS_TECHNICAL, "Miscellaneous Technical" },
611 U_CONTROL_PICTURES, "Control Pictures" },
613 U_OPTICAL_CHARACTER_RECOGNITION, "Optical Character Recognition" },
615 U_ENCLOSED_ALPHANUMERICS, "Enclosed Alphanumerics" },
617 U_BOX_DRAWING, "Box Drawing" },
619 U_BLOCK_ELEMENTS, "Block Elements" },
621 U_GEOMETRIC_SHAPES, "Geometric Shapes" },
623 U_MISCELLANEOUS_SYMBOLS, "Miscellaneous Symbols" },
625 U_DINGBATS, "Dingbats" },
627 U_CJK_SYMBOLS_AND_PUNCTUATION, "CJK Symbols and Punctuation" },
629 U_HIRAGANA, "Hiragana" },
631 U_KATAKANA, "Katakana" },
633 U_BOPOMOFO, "Bopomofo" },
635 U_HANGUL_COMPATIBILITY_JAMO, "Hangul Compatibility Jamo" },
637 U_CJK_MISCELLANEOUS, "CJK Miscellaneous" },
639 U_ENCLOSED_CJK, "Enclosed CJK" },
641 U_CJK_COMPATIBILITY, "CJK Compatibility" },
643 U_HANGUL, "Hangul" },
645 U_HANGUL_SUPPLEMENTARY_A, "Hangul Supplementary-A" },
647 U_HANGUL_SUPPLEMENTARY_B, "Hangul Supplementary-B" },
649 U_CJK_UNIFIED_IDEOGRAPHS, "CJK Unified Ideographs" },
651 U_PRIVATE_USE_AREA, "Private Use Area" },
653 U_CJK_COMPATIBILITY_IDEOGRAPHS, "CJK Compatibility Ideographs" },
655 U_ALPHABETIC_PRESENTATION_FORMS, "Alphabetic Presentation Forms" },
657 U_ARABIC_PRESENTATION_FORMS_A, "Arabic Presentation Forms-A" },
659 U_COMBINING_HALF_MARKS, "Combining Half Marks" },
661 U_CJK_COMPATIBILITY_FORMS, "CJK Compatibility Forms" },
663 U_SMALL_FORM_VARIANTS, "Small Form Variants" },
665 U_ARABIC_PRESENTATION_FORMS_B, "Arabic Presentation Forms-B" },
667 U_SPECIALS, "Specials" },
669 U_HALFWIDTH_AND_FULLWIDTH_FORMS, "Halfwidth and Fullwidth Forms" },
671 U_SPECIALS, "Specials" }
675 print_unicode_subranges (FONTSIGNATURE *fsp)
678 gboolean checked[sizeof (utab) / sizeof (utab[0])];
679 gboolean need_comma = FALSE;
681 memset (checked, 0, sizeof (checked));
683 for (i = 0; i < sizeof (utab) / sizeof (utab[0]); i++)
685 && (fsp->fsUsb[utab[i].bit/32] & (1 << (utab[i].bit % 32))))
687 g_print ("%s %s", (need_comma ? "," : ""), utab[i].name);
697 check_unicode_subranges (UINT charset,
701 gboolean retval = FALSE;
703 /* If the fsUsb bit array has at least one of the bits set, trust it */
704 for (i = 0; i < U_LAST_PLUS_ONE; i++)
705 if (i != U_PRIVATE_USE_AREA && (fsp->fsUsb[i/32] & (1 << (i % 32))))
708 /* Otherwise, guess what subranges there should be in the font */
709 fsp->fsUsb[0] = fsp->fsUsb[1] = fsp->fsUsb[2] = fsp->fsUsb[3] = 0;
711 #define set_bit(bitno) (fsp->fsUsb[(bitno)/32] |= (1 << ((bitno) % 32)))
713 /* Set Unicode subrange bits based on code pages supported.
714 * This is mostly just guesswork.
717 #define check_cp(bit) (fsp->fsCsb[0] & (bit))
719 if (check_cp(FS_LATIN1))
721 set_bit (U_BASIC_LATIN);
722 set_bit (U_LATIN_1_SUPPLEMENT);
723 set_bit (U_CURRENCY_SYMBOLS);
726 if (check_cp (FS_LATIN2))
728 set_bit (U_BASIC_LATIN);
729 set_bit (U_LATIN_1_SUPPLEMENT);
730 set_bit (U_LATIN_EXTENDED_A);
731 set_bit (U_CURRENCY_SYMBOLS);
734 if (check_cp (FS_CYRILLIC))
736 set_bit (U_BASIC_LATIN);
737 set_bit (U_CYRILLIC);
740 if (check_cp (FS_GREEK))
742 set_bit (U_BASIC_LATIN);
743 set_bit (U_BASIC_GREEK);
746 if (check_cp (FS_TURKISH))
748 set_bit (U_BASIC_LATIN);
749 set_bit (U_LATIN_1_SUPPLEMENT);
750 set_bit (U_LATIN_EXTENDED_A);
751 set_bit (U_CURRENCY_SYMBOLS);
754 if (check_cp (FS_HEBREW))
756 set_bit (U_BASIC_LATIN);
757 set_bit (U_CURRENCY_SYMBOLS);
758 set_bit (U_BASIC_HEBREW);
759 set_bit (U_HEBREW_EXTENDED);
762 if (check_cp (FS_ARABIC))
764 set_bit (U_BASIC_LATIN);
765 set_bit (U_CURRENCY_SYMBOLS);
766 set_bit (U_BASIC_ARABIC);
767 set_bit (U_ARABIC_EXTENDED);
770 if (check_cp (FS_BALTIC))
772 set_bit (U_BASIC_LATIN);
773 set_bit (U_LATIN_1_SUPPLEMENT);
774 set_bit (U_CURRENCY_SYMBOLS);
775 set_bit (U_LATIN_EXTENDED_A);
776 set_bit (U_LATIN_EXTENDED_B);
779 if (check_cp (FS_VIETNAMESE))
782 set_bit (U_BASIC_LATIN);
785 if (check_cp (FS_THAI))
787 set_bit (U_BASIC_LATIN);
791 if (check_cp (FS_JISJAPAN))
793 /* Based on MS Gothic */
794 set_bit (U_BASIC_LATIN);
795 set_bit (U_CJK_SYMBOLS_AND_PUNCTUATION);
796 set_bit (U_HIRAGANA);
797 set_bit (U_KATAKANA);
798 set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
799 set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
802 if (check_cp (FS_CHINESESIMP))
804 /* Based on MS Hei */
805 set_bit (U_BASIC_LATIN);
806 set_bit (U_HIRAGANA);
807 set_bit (U_KATAKANA);
808 set_bit (U_BOPOMOFO);
809 set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
812 if (check_cp (FS_WANSUNG)
813 || check_cp (FS_JOHAB)) /* ??? */
815 /* Based on GulimChe. I wonder if all Korean fonts
816 * really support this large range of Unicode subranges?
818 set_bit (U_BASIC_LATIN);
819 set_bit (U_LATIN_1_SUPPLEMENT);
820 set_bit (U_LATIN_EXTENDED_A);
821 set_bit (U_SPACING_MODIFIER_LETTERS);
822 set_bit (U_BASIC_GREEK);
823 set_bit (U_CYRILLIC);
824 set_bit (U_GENERAL_PUNCTUATION);
825 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
826 set_bit (U_CURRENCY_SYMBOLS);
827 set_bit (U_LETTERLIKE_SYMBOLS);
828 set_bit (U_NUMBER_FORMS);
830 set_bit (U_MATHEMATICAL_OPERATORS);
831 set_bit (U_MISCELLANEOUS_TECHNICAL);
832 set_bit (U_ENCLOSED_ALPHANUMERICS);
833 set_bit (U_BOX_DRAWING);
834 set_bit (U_BLOCK_ELEMENTS);
835 set_bit (U_GEOMETRIC_SHAPES);
836 set_bit (U_MISCELLANEOUS_SYMBOLS);
837 set_bit (U_CJK_SYMBOLS_AND_PUNCTUATION);
838 set_bit (U_HIRAGANA);
839 set_bit (U_KATAKANA);
840 set_bit (U_HANGUL_COMPATIBILITY_JAMO);
841 set_bit (U_ENCLOSED_CJK);
842 set_bit (U_CJK_COMPATIBILITY_FORMS);
844 set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
845 set_bit (U_CJK_COMPATIBILITY_IDEOGRAPHS);
846 set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
849 if (check_cp (FS_CHINESETRAD))
851 /* Based on MingLiU */
852 set_bit (U_BASIC_LATIN);
853 set_bit (U_GENERAL_PUNCTUATION);
854 set_bit (U_BOX_DRAWING);
855 set_bit (U_BLOCK_ELEMENTS);
856 set_bit (U_CJK_SYMBOLS_AND_PUNCTUATION);
857 set_bit (U_BOPOMOFO);
858 set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
859 set_bit (U_CJK_COMPATIBILITY_IDEOGRAPHS);
860 set_bit (U_SMALL_FORM_VARIANTS);
861 set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
864 if (check_cp (FS_SYMBOL) || charset == MAC_CHARSET)
866 /* Non-Unicode encoding, I guess. Pretend it covers
867 * the single-byte range of values.
869 set_bit (U_BASIC_LATIN);
870 set_bit (U_LATIN_1_SUPPLEMENT);
877 GDK_NOTE (MISC, g_print ("... No code page bits set!\n"));
879 /* Sigh. Not even any code page bits were set. Guess based on
880 * charset, then. These somewhat optimistic guesses are based on the
881 * table in Appendix M in the book "Developing ..." mentioned
887 set_bit (U_BASIC_LATIN);
888 set_bit (U_LATIN_1_SUPPLEMENT);
889 set_bit (U_LATIN_EXTENDED_A);
890 set_bit (U_LATIN_EXTENDED_B);
891 set_bit (U_SPACING_MODIFIER_LETTERS);
892 set_bit (U_COMBINING_DIACRITICAL_MARKS);
893 set_bit (U_GENERAL_PUNCTUATION);
894 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
895 set_bit (U_CURRENCY_SYMBOLS);
896 #if 0 /* I find this too hard to believe... */
897 set_bit (U_BASIC_GREEK);
898 set_bit (U_CYRILLIC);
899 set_bit (U_BASIC_HEBREW);
900 set_bit (U_HEBREW_EXTENDED);
901 set_bit (U_BASIC_ARABIC);
902 set_bit (U_ARABIC_EXTENDED);
903 set_bit (U_LETTERLIKE_SYMBOLS);
904 set_bit (U_NUMBER_FORMS);
906 set_bit (U_MATHEMATICAL_OPERATORS);
907 set_bit (U_MISCELLANEOUS_TECHNICAL);
908 set_bit (U_ENCLOSED_ALPHANUMERICS);
909 set_bit (U_BOX_DRAWING);
910 set_bit (U_BLOCK_ELEMENTS);
911 set_bit (U_GEOMETRIC_SHAPES);
912 set_bit (U_MISCELLANEOUS_SYMBOLS);
913 set_bit (U_HIRAGANA);
914 set_bit (U_KATAKANA);
915 set_bit (U_BOPOMOFO);
916 set_bit (U_HANGUL_COMPATIBILITY_JAMO);
917 set_bit (U_CJK_MISCELLANEOUS);
918 set_bit (U_CJK_COMPATIBILITY);
920 set_bit (U_HANGUL_SUPPLEMENTARY_A);
921 set_bit (U_CJK_COMPATIBILITY_IDEOGRAPHS);
922 set_bit (U_ALPHABETIC_PRESENTATION_FORMS);
923 set_bit (U_SMALL_FORM_VARIANTS);
924 set_bit (U_ARABIC_PRESENTATION_FORMS_B);
925 set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
926 set_bit (U_SPECIALS);
932 set_bit (U_BASIC_LATIN);
933 set_bit (U_LATIN_1_SUPPLEMENT);
936 case SHIFTJIS_CHARSET:
937 case HANGEUL_CHARSET:
939 case CHINESEBIG5_CHARSET:
941 /* The table really does claim these "locales" (it doesn't
942 * talk about charsets per se) cover the same Unicode
945 set_bit (U_BASIC_LATIN);
946 set_bit (U_LATIN_1_SUPPLEMENT);
947 set_bit (U_LATIN_EXTENDED_A);
948 set_bit (U_LATIN_EXTENDED_B);
949 set_bit (U_SPACING_MODIFIER_LETTERS);
950 set_bit (U_COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS);
951 set_bit (U_BASIC_GREEK);
952 set_bit (U_CYRILLIC);
953 set_bit (U_GENERAL_PUNCTUATION);
954 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
955 set_bit (U_CURRENCY_SYMBOLS);
956 set_bit (U_LETTERLIKE_SYMBOLS);
957 set_bit (U_NUMBER_FORMS);
959 set_bit (U_MATHEMATICAL_OPERATORS);
960 set_bit (U_MISCELLANEOUS_TECHNICAL);
961 set_bit (U_ENCLOSED_ALPHANUMERICS);
962 set_bit (U_BOX_DRAWING);
963 set_bit (U_BLOCK_ELEMENTS);
964 set_bit (U_GEOMETRIC_SHAPES);
965 set_bit (U_MISCELLANEOUS_SYMBOLS);
966 set_bit (U_CJK_SYMBOLS_AND_PUNCTUATION);
967 set_bit (U_HIRAGANA);
968 set_bit (U_KATAKANA);
969 set_bit (U_BOPOMOFO);
970 set_bit (U_HANGUL_COMPATIBILITY_JAMO);
971 set_bit (U_CJK_MISCELLANEOUS);
972 set_bit (U_CJK_COMPATIBILITY);
974 set_bit (U_HANGUL_SUPPLEMENTARY_A);
975 set_bit (U_CJK_UNIFIED_IDEOGRAPHS);
976 set_bit (U_CJK_COMPATIBILITY_IDEOGRAPHS);
977 set_bit (U_ALPHABETIC_PRESENTATION_FORMS);
978 set_bit (U_SMALL_FORM_VARIANTS);
979 set_bit (U_ARABIC_PRESENTATION_FORMS_B);
980 set_bit (U_SPECIALS);
984 set_bit (U_BASIC_LATIN);
985 set_bit (U_LATIN_1_SUPPLEMENT);
986 set_bit (U_LATIN_EXTENDED_B);
987 set_bit (U_SPACING_MODIFIER_LETTERS);
988 set_bit (U_BASIC_HEBREW);
989 set_bit (U_HEBREW_EXTENDED);
990 set_bit (U_GENERAL_PUNCTUATION);
991 set_bit (U_LETTERLIKE_SYMBOLS);
995 set_bit (U_BASIC_LATIN);
996 set_bit (U_LATIN_1_SUPPLEMENT);
997 set_bit (U_LATIN_EXTENDED_A);
998 set_bit (U_LATIN_EXTENDED_B);
999 set_bit (U_SPACING_MODIFIER_LETTERS);
1000 set_bit (U_BASIC_GREEK);
1001 set_bit (U_BASIC_ARABIC);
1002 set_bit (U_ARABIC_EXTENDED);
1003 set_bit (U_GENERAL_PUNCTUATION);
1004 set_bit (U_LETTERLIKE_SYMBOLS);
1006 set_bit (U_MATHEMATICAL_OPERATORS);
1007 set_bit (U_MISCELLANEOUS_TECHNICAL);
1008 set_bit (U_BOX_DRAWING);
1009 set_bit (U_BLOCK_ELEMENTS);
1010 set_bit (U_GEOMETRIC_SHAPES);
1011 set_bit (U_MISCELLANEOUS_SYMBOLS);
1012 set_bit (U_HALFWIDTH_AND_FULLWIDTH_FORMS);
1016 set_bit (U_BASIC_LATIN);
1017 set_bit (U_LATIN_1_SUPPLEMENT);
1018 set_bit (U_LATIN_EXTENDED_B);
1019 set_bit (U_BASIC_GREEK);
1020 set_bit (U_GENERAL_PUNCTUATION);
1021 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
1022 set_bit (U_LETTERLIKE_SYMBOLS);
1024 set_bit (U_MATHEMATICAL_OPERATORS);
1025 set_bit (U_MISCELLANEOUS_TECHNICAL);
1026 set_bit (U_BOX_DRAWING);
1027 set_bit (U_BLOCK_ELEMENTS);
1028 set_bit (U_GEOMETRIC_SHAPES);
1029 set_bit (U_MISCELLANEOUS_SYMBOLS);
1032 case TURKISH_CHARSET:
1033 set_bit (U_BASIC_LATIN);
1034 set_bit (U_LATIN_1_SUPPLEMENT);
1035 set_bit (U_LATIN_EXTENDED_A);
1036 set_bit (U_LATIN_EXTENDED_B);
1037 set_bit (U_SPACING_MODIFIER_LETTERS);
1038 set_bit (U_BASIC_GREEK);
1039 set_bit (U_GENERAL_PUNCTUATION);
1040 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
1041 set_bit (U_CURRENCY_SYMBOLS);
1042 set_bit (U_LETTERLIKE_SYMBOLS);
1044 set_bit (U_MATHEMATICAL_OPERATORS);
1045 set_bit (U_MISCELLANEOUS_TECHNICAL);
1046 set_bit (U_BOX_DRAWING);
1047 set_bit (U_BLOCK_ELEMENTS);
1048 set_bit (U_GEOMETRIC_SHAPES);
1049 set_bit (U_MISCELLANEOUS_SYMBOLS);
1052 case VIETNAMESE_CHARSET:
1054 /* These are not in the table, so I have no idea */
1056 case BALTIC_CHARSET:
1057 set_bit (U_BASIC_LATIN);
1058 set_bit (U_LATIN_1_SUPPLEMENT);
1059 set_bit (U_LATIN_EXTENDED_A);
1060 set_bit (U_LATIN_EXTENDED_B);
1061 set_bit (U_SPACING_MODIFIER_LETTERS);
1062 set_bit (U_BASIC_GREEK);
1063 set_bit (U_GENERAL_PUNCTUATION);
1064 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
1065 set_bit (U_CURRENCY_SYMBOLS);
1066 set_bit (U_LETTERLIKE_SYMBOLS);
1068 set_bit (U_MATHEMATICAL_OPERATORS);
1069 set_bit (U_MISCELLANEOUS_TECHNICAL);
1070 set_bit (U_BOX_DRAWING);
1071 set_bit (U_BLOCK_ELEMENTS);
1072 set_bit (U_GEOMETRIC_SHAPES);
1073 set_bit (U_MISCELLANEOUS_SYMBOLS);
1076 case EASTEUROPE_CHARSET:
1077 set_bit (U_BASIC_LATIN);
1078 set_bit (U_LATIN_1_SUPPLEMENT);
1079 set_bit (U_LATIN_EXTENDED_A);
1080 set_bit (U_LATIN_EXTENDED_B);
1081 set_bit (U_SPACING_MODIFIER_LETTERS);
1082 set_bit (U_BASIC_GREEK);
1083 set_bit (U_GENERAL_PUNCTUATION);
1084 set_bit (U_SUPERSCRIPTS_AND_SUBSCRIPTS);
1085 set_bit (U_CURRENCY_SYMBOLS);
1086 set_bit (U_LETTERLIKE_SYMBOLS);
1088 set_bit (U_MATHEMATICAL_OPERATORS);
1089 set_bit (U_MISCELLANEOUS_TECHNICAL);
1090 set_bit (U_BOX_DRAWING);
1091 set_bit (U_BLOCK_ELEMENTS);
1092 set_bit (U_GEOMETRIC_SHAPES);
1093 set_bit (U_MISCELLANEOUS_SYMBOLS);
1096 case RUSSIAN_CHARSET:
1097 set_bit (U_BASIC_LATIN);
1098 set_bit (U_LATIN_1_SUPPLEMENT);
1099 set_bit (U_CYRILLIC);
1100 set_bit (U_GENERAL_PUNCTUATION);
1101 set_bit (U_LETTERLIKE_SYMBOLS);
1103 set_bit (U_MATHEMATICAL_OPERATORS);
1104 set_bit (U_MISCELLANEOUS_TECHNICAL);
1105 set_bit (U_BOX_DRAWING);
1106 set_bit (U_BLOCK_ELEMENTS);
1107 set_bit (U_GEOMETRIC_SHAPES);
1108 set_bit (U_MISCELLANEOUS_SYMBOLS);
1118 gdk_font_load_internal (const gchar *font_name)
1120 GdkWin32SingleFont *singlefont;
1124 DWORD fdwItalic, fdwUnderline, fdwStrikeOut, fdwCharSet,
1125 fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily;
1127 const char *lpszFace;
1130 int numfields, n1, n2, tries;
1131 char foundry[32], family[100], weight[32], slant[32], set_width[32],
1132 spacing[32], registry[32], encoding[32];
1133 char pixel_size[10], point_size[10], res_x[10], res_y[10], avg_width[10];
1136 int nHeight, nWidth, nEscapement, nOrientation, fnWeight;
1139 g_return_val_if_fail (font_name != NULL, NULL);
1141 GDK_NOTE (MISC, g_print ("gdk_font_load_internal: %s\n", font_name));
1143 numfields = sscanf (font_name,
1144 "-%30[^-]-%100[^-]-%30[^-]-%30[^-]-%30[^-]-%n",
1153 /* Probably a plain Windows font name */
1158 fnWeight = FW_DONTCARE;
1160 fdwUnderline = FALSE;
1161 fdwStrikeOut = FALSE;
1162 fdwCharSet = ANSI_CHARSET;
1163 fdwOutputPrecision = OUT_TT_PRECIS;
1164 fdwClipPrecision = CLIP_DEFAULT_PRECIS;
1165 fdwQuality = PROOF_QUALITY;
1166 fdwPitchAndFamily = DEFAULT_PITCH;
1167 lpszFace = font_name;
1169 else if (numfields != 5)
1171 g_warning ("gdk_font_load: font name %s illegal", font_name);
1176 /* It must be a XLFD name */
1178 /* Check for hex escapes in the font family,
1179 * put in there by gtkfontsel.
1184 if (*p == '%' && isxdigit (p[1]) && isxdigit (p[2]))
1186 sscanf (p+1, "%2x", &c);
1193 /* Skip add_style which often is empty in the requested font name */
1194 while (font_name[n1] && font_name[n1] != '-')
1198 numfields += sscanf (font_name + n1,
1199 "-%8[^-]-%8[^-]-%8[^-]-%8[^-]-%30[^-]-%8[^-]-%30[^-]-%30[^-]%n",
1210 if (numfields != 14 || font_name[n1 + n2] != '\0')
1212 g_warning ("gdk_font_load: font name %s illegal", font_name);
1216 logpixelsy = GetDeviceCaps (gdk_DC, LOGPIXELSY);
1218 if (strcmp (pixel_size, "*") == 0)
1219 if (strcmp (point_size, "*") == 0)
1222 nHeight = (int) (((double) atoi (point_size))/720.*logpixelsy);
1224 nHeight = atoi (pixel_size);
1230 if (g_strcasecmp (weight, "thin") == 0)
1232 else if (g_strcasecmp (weight, "extralight") == 0)
1233 fnWeight = FW_EXTRALIGHT;
1234 else if (g_strcasecmp (weight, "ultralight") == 0)
1235 #ifdef FW_ULTRALIGHT
1236 fnWeight = FW_ULTRALIGHT;
1238 fnWeight = FW_EXTRALIGHT; /* In fact, FW_ULTRALIGHT really is
1239 * defined as FW_EXTRALIGHT anyway.
1242 else if (g_strcasecmp (weight, "light") == 0)
1243 fnWeight = FW_LIGHT;
1244 else if (g_strcasecmp (weight, "normal") == 0)
1245 fnWeight = FW_NORMAL;
1246 else if (g_strcasecmp (weight, "regular") == 0)
1247 fnWeight = FW_REGULAR;
1248 else if (g_strcasecmp (weight, "medium") == 0)
1249 fnWeight = FW_MEDIUM;
1250 else if (g_strcasecmp (weight, "semibold") == 0)
1251 fnWeight = FW_SEMIBOLD;
1252 else if (g_strcasecmp (weight, "demibold") == 0)
1254 fnWeight = FW_DEMIBOLD;
1256 fnWeight = FW_SEMIBOLD; /* As above */
1258 else if (g_strcasecmp (weight, "bold") == 0)
1260 else if (g_strcasecmp (weight, "extrabold") == 0)
1261 fnWeight = FW_EXTRABOLD;
1262 else if (g_strcasecmp (weight, "ultrabold") == 0)
1264 fnWeight = FW_ULTRABOLD;
1266 fnWeight = FW_EXTRABOLD; /* As above */
1268 else if (g_strcasecmp (weight, "heavy") == 0)
1269 fnWeight = FW_HEAVY;
1270 else if (g_strcasecmp (weight, "black") == 0)
1272 fnWeight = FW_BLACK;
1274 fnWeight = FW_HEAVY; /* As above */
1277 fnWeight = FW_DONTCARE;
1279 if (g_strcasecmp (slant, "italic") == 0
1280 || g_strcasecmp (slant, "oblique") == 0
1281 || g_strcasecmp (slant, "i") == 0
1282 || g_strcasecmp (slant, "o") == 0)
1286 fdwUnderline = FALSE;
1287 fdwStrikeOut = FALSE;
1288 if (g_strcasecmp (registry, "iso8859") == 0)
1289 if (strcmp (encoding, "1") == 0)
1290 fdwCharSet = ANSI_CHARSET;
1291 else if (strcmp (encoding, "2") == 0)
1292 fdwCharSet = EASTEUROPE_CHARSET;
1293 else if (strcmp (encoding, "7") == 0)
1294 fdwCharSet = GREEK_CHARSET;
1295 else if (strcmp (encoding, "8") == 0)
1296 fdwCharSet = HEBREW_CHARSET;
1297 else if (strcmp (encoding, "9") == 0)
1298 fdwCharSet = TURKISH_CHARSET;
1300 fdwCharSet = ANSI_CHARSET; /* XXX ??? */
1301 else if (g_strcasecmp (registry, "jisx0208.1983") == 0)
1302 fdwCharSet = SHIFTJIS_CHARSET;
1303 else if (g_strcasecmp (registry, "ksc5601.1987") == 0)
1304 fdwCharSet = HANGEUL_CHARSET;
1305 else if (g_strcasecmp (registry, "gb2312.1980") == 0)
1306 fdwCharSet = GB2312_CHARSET;
1307 else if (g_strcasecmp (registry, "big5") == 0)
1308 fdwCharSet = CHINESEBIG5_CHARSET;
1309 else if (g_strcasecmp (registry, "windows") == 0
1310 || g_strcasecmp (registry, "microsoft") == 0)
1311 if (g_strcasecmp (encoding, "symbol") == 0)
1312 fdwCharSet = SYMBOL_CHARSET;
1313 else if (g_strcasecmp (encoding, "shiftjis") == 0)
1314 fdwCharSet = SHIFTJIS_CHARSET;
1315 else if (g_strcasecmp (encoding, "gb2312") == 0)
1316 fdwCharSet = GB2312_CHARSET;
1317 else if (g_strcasecmp (encoding, "hangeul") == 0)
1318 fdwCharSet = HANGEUL_CHARSET;
1319 else if (g_strcasecmp (encoding, "big5") == 0)
1320 fdwCharSet = CHINESEBIG5_CHARSET;
1321 else if (g_strcasecmp (encoding, "johab") == 0)
1322 fdwCharSet = JOHAB_CHARSET;
1323 else if (g_strcasecmp (encoding, "hebrew") == 0)
1324 fdwCharSet = HEBREW_CHARSET;
1325 else if (g_strcasecmp (encoding, "arabic") == 0)
1326 fdwCharSet = ARABIC_CHARSET;
1327 else if (g_strcasecmp (encoding, "greek") == 0)
1328 fdwCharSet = GREEK_CHARSET;
1329 else if (g_strcasecmp (encoding, "turkish") == 0)
1330 fdwCharSet = TURKISH_CHARSET;
1331 else if (g_strcasecmp (encoding, "easteurope") == 0)
1332 fdwCharSet = EASTEUROPE_CHARSET;
1333 else if (g_strcasecmp (encoding, "russian") == 0)
1334 fdwCharSet = RUSSIAN_CHARSET;
1335 else if (g_strcasecmp (encoding, "mac") == 0)
1336 fdwCharSet = MAC_CHARSET;
1337 else if (g_strcasecmp (encoding, "baltic") == 0)
1338 fdwCharSet = BALTIC_CHARSET;
1339 else if (g_strcasecmp (encoding, "cp1251") == 0)
1340 fdwCharSet = RUSSIAN_CHARSET;
1342 fdwCharSet = ANSI_CHARSET; /* XXX ??? */
1344 fdwCharSet = ANSI_CHARSET; /* XXX ??? */
1345 fdwOutputPrecision = OUT_TT_PRECIS;
1346 fdwClipPrecision = CLIP_DEFAULT_PRECIS;
1347 fdwQuality = PROOF_QUALITY;
1348 if (g_strcasecmp (spacing, "m") == 0)
1349 fdwPitchAndFamily = FIXED_PITCH;
1350 else if (g_strcasecmp (spacing, "p") == 0)
1351 fdwPitchAndFamily = VARIABLE_PITCH;
1353 fdwPitchAndFamily = DEFAULT_PITCH;
1357 for (tries = 0; ; tries++)
1359 GDK_NOTE (MISC, g_print ("...trying CreateFont(%d,%d,%d,%d,"
1362 "%d,%#.02x,\"%s\")\n",
1363 nHeight, nWidth, nEscapement, nOrientation,
1364 fnWeight, fdwItalic, fdwUnderline, fdwStrikeOut,
1365 fdwCharSet, fdwOutputPrecision, fdwClipPrecision,
1366 fdwQuality, fdwPitchAndFamily, lpszFace));
1368 CreateFont (nHeight, nWidth, nEscapement, nOrientation,
1369 fnWeight, fdwItalic, fdwUnderline, fdwStrikeOut,
1370 fdwCharSet, fdwOutputPrecision, fdwClipPrecision,
1371 fdwQuality, fdwPitchAndFamily, lpszFace)) != NULL)
1374 /* If we fail, try some similar fonts often found on Windows. */
1378 if (g_strcasecmp (family, "helvetica") == 0)
1380 else if (g_strcasecmp (family, "new century schoolbook") == 0)
1381 lpszFace = "century schoolbook";
1382 else if (g_strcasecmp (family, "courier") == 0)
1383 lpszFace = "courier new";
1384 else if (g_strcasecmp (family, "lucida") == 0)
1385 lpszFace = "lucida sans unicode";
1386 else if (g_strcasecmp (family, "lucidatypewriter") == 0)
1387 lpszFace = "lucida console";
1388 else if (g_strcasecmp (family, "times") == 0)
1389 lpszFace = "times new roman";
1391 else if (tries == 1)
1393 if (g_strcasecmp (family, "courier") == 0)
1396 fdwPitchAndFamily |= FF_MODERN;
1398 else if (g_strcasecmp (family, "times new roman") == 0)
1401 fdwPitchAndFamily |= FF_ROMAN;
1403 else if (g_strcasecmp (family, "helvetica") == 0
1404 || g_strcasecmp (family, "lucida") == 0)
1407 fdwPitchAndFamily |= FF_SWISS;
1412 fdwPitchAndFamily = (fdwPitchAndFamily & 0x0F) | FF_DONTCARE;
1423 singlefont = g_new (GdkWin32SingleFont, 1);
1424 singlefont->xfont = hfont;
1425 GetObject (singlefont->xfont, sizeof (logfont), &logfont);
1426 oldfont = SelectObject (gdk_DC, singlefont->xfont);
1427 memset (&singlefont->fs, 0, sizeof (singlefont->fs));
1428 singlefont->charset = GetTextCharsetInfo (gdk_DC, &singlefont->fs, 0);
1429 GetTextFace (gdk_DC, sizeof (face), face);
1430 SelectObject (gdk_DC, oldfont);
1431 if (TranslateCharsetInfo ((DWORD *) singlefont->charset, &csi,
1433 && singlefont->charset != MAC_CHARSET)
1434 singlefont->codepage = csi.ciACP;
1436 singlefont->codepage = 0;
1438 GDK_NOTE (MISC, (g_print ("... = %#x %s cs %s cp%d ",
1439 singlefont->xfont, face,
1440 charset_name (singlefont->charset),
1441 singlefont->codepage),
1442 g_print ("... Unicode subranges:"),
1443 print_unicode_subranges (&singlefont->fs)));
1444 if (check_unicode_subranges (singlefont->charset, &singlefont->fs))
1445 GDK_NOTE (MISC, (g_print ("... Guesstimated Unicode subranges:"),
1446 print_unicode_subranges (&singlefont->fs)));
1452 gdk_font_load (const gchar *font_name)
1455 GdkFontPrivateWin32 *private;
1456 GdkWin32SingleFont *singlefont;
1459 TEXTMETRIC textmetric;
1461 g_return_val_if_fail (font_name != NULL, NULL);
1463 font = gdk_font_hash_lookup (GDK_FONT_FONTSET, font_name);
1467 singlefont = gdk_font_load_internal (font_name);
1469 private = g_new (GdkFontPrivateWin32, 1);
1470 font = (GdkFont*) private;
1472 private->base.ref_count = 1;
1473 private->names = NULL;
1474 private->fonts = g_slist_append (NULL, singlefont);
1476 /* Pretend all fonts are fontsets... Gtktext and gtkentry work better
1477 * that way, they use wide chars, which is necessary for non-ASCII
1478 * chars to work. (Yes, even Latin-1, as we use Unicode internally.)
1480 font->type = GDK_FONT_FONTSET;
1481 oldfont = SelectObject (gdk_DC, singlefont->xfont);
1482 GetTextMetrics (gdk_DC, &textmetric);
1483 SelectObject (gdk_DC, oldfont);
1484 font->ascent = textmetric.tmAscent;
1485 font->descent = textmetric.tmDescent;
1487 GDK_NOTE (MISC, g_print ("... asc %d desc %d\n",
1488 font->ascent, font->descent));
1490 gdk_font_hash_insert (GDK_FONT_FONTSET, font, font_name);
1496 gdk_fontset_load (gchar *fontset_name)
1499 GdkFontPrivateWin32 *private;
1500 GdkWin32SingleFont *singlefont;
1503 TEXTMETRIC textmetric;
1504 GSList *base_font_list = NULL;
1508 g_return_val_if_fail (fontset_name != NULL, NULL);
1510 font = gdk_font_hash_lookup (GDK_FONT_FONTSET, fontset_name);
1514 s = fs = g_strdup (fontset_name);
1515 while (*s && isspace (*s))
1518 g_return_val_if_fail (*s, NULL);
1520 private = g_new (GdkFontPrivateWin32, 1);
1521 font = (GdkFont*) private;
1523 private->base.ref_count = 1;
1524 private->names = NULL;
1525 private->fonts = NULL;
1527 font->type = GDK_FONT_FONTSET;
1533 if ((p = strchr (s, ',')) != NULL)
1538 while (isspace (b[-1]))
1541 singlefont = gdk_font_load_internal (s);
1544 private->fonts = g_slist_append (private->fonts, singlefont);
1545 oldfont = SelectObject (gdk_DC, singlefont->xfont);
1546 GetTextMetrics (gdk_DC, &textmetric);
1547 SelectObject (gdk_DC, oldfont);
1548 font->ascent = MAX (font->ascent, textmetric.tmAscent);
1549 font->descent = MAX (font->descent, textmetric.tmDescent);
1554 while (*s && isspace (*s))
1565 gdk_font_hash_insert (GDK_FONT_FONTSET, font, fontset_name);
1571 _gdk_font_destroy (GdkFont *font)
1573 GdkFontPrivateWin32 *private = (GdkFontPrivateWin32 *) font;
1574 GdkWin32SingleFont *singlefont;
1577 singlefont = (GdkWin32SingleFont *) private->fonts->data;
1578 GDK_NOTE (MISC, g_print ("_gdk_font_destroy %#x\n",
1579 singlefont->xfont));
1581 gdk_font_hash_remove (font->type, font);
1586 DeleteObject (singlefont->xfont);
1589 case GDK_FONT_FONTSET:
1590 list = private->fonts;
1593 singlefont = (GdkWin32SingleFont *) list->data;
1594 DeleteObject (singlefont->xfont);
1598 g_slist_free (private->fonts);
1605 _gdk_font_strlen (GdkFont *font,
1608 g_return_val_if_fail (font != NULL, -1);
1609 g_return_val_if_fail (str != NULL, -1);
1611 return strlen (str);
1615 gdk_font_id (const GdkFont *font)
1617 const GdkFontPrivateWin32 *private;
1619 g_return_val_if_fail (font != NULL, 0);
1621 private = (const GdkFontPrivateWin32 *) font;
1623 if (font->type == GDK_FONT_FONT)
1624 return (gint) ((GdkWin32SingleFont *) private->fonts->data)->xfont;
1630 gdk_font_equal (const GdkFont *fonta,
1631 const GdkFont *fontb)
1633 const GdkFontPrivateWin32 *privatea;
1634 const GdkFontPrivateWin32 *privateb;
1636 g_return_val_if_fail (fonta != NULL, FALSE);
1637 g_return_val_if_fail (fontb != NULL, FALSE);
1639 privatea = (const GdkFontPrivateWin32 *) fonta;
1640 privateb = (const GdkFontPrivateWin32 *) fontb;
1642 if (fonta->type == GDK_FONT_FONT && fontb->type == GDK_FONT_FONT)
1643 return (((GdkWin32SingleFont *) privatea->fonts->data)->xfont
1644 == ((GdkWin32SingleFont *) privateb->fonts->data)->xfont);
1645 else if (fonta->type == GDK_FONT_FONTSET && fontb->type == GDK_FONT_FONTSET)
1647 GSList *lista = privatea->fonts;
1648 GSList *listb = privateb->fonts;
1650 while (lista && listb)
1652 if (((GdkWin32SingleFont *) lista->data)->xfont
1653 != ((GdkWin32SingleFont *) listb->data)->xfont)
1655 lista = lista->next;
1656 listb = listb->next;
1667 /* Return the Unicode Subset bitfield number for a Unicode character */
1670 unicode_classify (wchar_t wc)
1673 int max = sizeof (utab) / sizeof (utab[0]) - 1;
1678 mid = (min + max) / 2;
1679 if (utab[mid].high < wc)
1681 else if (wc < utab[mid].low)
1683 else if (utab[mid].low <= wc && wc <= utab[mid].high)
1684 return utab[mid].bit;
1691 gdk_wchar_text_handle (GdkFont *font,
1692 const wchar_t *wcstr,
1694 void (*handler)(GdkWin32SingleFont *,
1700 GdkFontPrivateWin32 *private;
1701 GdkWin32SingleFont *singlefont;
1704 const wchar_t *start, *end, *wcp;
1708 private = (GdkFontPrivateWin32 *) font;
1710 g_assert (private->base.ref_count > 0);
1714 /* Split Unicode string into pieces of the same class */
1716 block = unicode_classify (*wcp);
1717 while (wcp + 1 < end && unicode_classify (wcp[1]) == block)
1720 /* Find a font in the fontset that can handle this class */
1721 list = private->fonts;
1724 singlefont = (GdkWin32SingleFont *) list->data;
1726 if (singlefont->fs.fsUsb[block/32] & (1 << (block % 32)))
1735 /* Call the callback function */
1736 (*handler) (singlefont, start, wcp+1 - start, arg);
1744 } gdk_text_size_arg;
1747 gdk_text_size_handler (GdkWin32SingleFont *singlefont,
1748 const wchar_t *wcstr,
1754 gdk_text_size_arg *arg = (gdk_text_size_arg *) argp;
1759 if ((oldfont = SelectObject (gdk_DC, singlefont->xfont)) == NULL)
1761 g_warning ("gdk_text_size_handler: SelectObject failed");
1764 GetTextExtentPoint32W (gdk_DC, wcstr, wclen, &this_size);
1765 SelectObject (gdk_DC, oldfont);
1767 arg->total.cx += this_size.cx;
1768 arg->total.cy = MAX (arg->total.cy, this_size.cy);
1772 gdk_text_size (GdkFont *font,
1775 gdk_text_size_arg *arg)
1780 g_return_val_if_fail (font != NULL, FALSE);
1781 g_return_val_if_fail (text != NULL, FALSE);
1783 if (text_length == 0)
1786 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
1788 wcstr = g_new (wchar_t, text_length);
1789 if (text_length == 1)
1791 /* For single characters, don't try to interpret as UTF-8.
1793 wcstr[0] = (guchar) text[0];
1794 gdk_wchar_text_handle (font, wcstr, 1, gdk_text_size_handler, arg);
1798 if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
1799 g_warning ("gdk_text_size: gdk_nmbstowchar_ts failed");
1801 gdk_wchar_text_handle (font, wcstr, wlen, gdk_text_size_handler, arg);
1810 gdk_text_width (GdkFont *font,
1814 gdk_text_size_arg arg;
1816 arg.total.cx = arg.total.cy = 0;
1818 if (!gdk_text_size (font, text, text_length, &arg))
1821 return arg.total.cx;
1825 gdk_text_width_wc (GdkFont *font,
1826 const GdkWChar *text,
1829 gdk_text_size_arg arg;
1833 g_return_val_if_fail (font != NULL, -1);
1834 g_return_val_if_fail (text != NULL, -1);
1836 if (text_length == 0)
1839 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
1841 if (sizeof (wchar_t) != sizeof (GdkWChar))
1843 wcstr = g_new (wchar_t, text_length);
1844 for (i = 0; i < text_length; i++)
1848 wcstr = (wchar_t *) text;
1850 arg.total.cx = arg.total.cy = 0;
1852 gdk_wchar_text_handle (font, wcstr, text_length,
1853 gdk_text_size_handler, &arg);
1855 if (sizeof (wchar_t) != sizeof (GdkWChar))
1858 return arg.total.cx;
1862 gdk_text_extents (GdkFont *font,
1871 gdk_text_size_arg arg;
1875 g_return_if_fail (font != NULL);
1876 g_return_if_fail (text != NULL);
1878 if (text_length == 0)
1893 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
1895 arg.total.cx = arg.total.cy = 0;
1897 wcstr = g_new (wchar_t, text_length);
1898 if (text_length == 1)
1900 wcstr[0] = (guchar) text[0];
1901 gdk_wchar_text_handle (font, wcstr, 1, gdk_text_size_handler, &arg);
1905 if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
1906 g_warning ("gdk_text_extents: gdk_nmbstowchar_ts failed");
1908 gdk_wchar_text_handle (font, wcstr, wlen, gdk_text_size_handler, &arg);
1913 /* XXX This is quite bogus */
1917 *rbearing = arg.total.cx;
1918 /* What should be the difference between width and rbearing? */
1920 *width = arg.total.cx;
1922 *ascent = arg.total.cy + 1;
1924 *descent = font->descent + 1;
1928 gdk_text_extents_wc (GdkFont *font,
1929 const GdkWChar *text,
1937 gdk_text_size_arg arg;
1941 g_return_if_fail (font != NULL);
1942 g_return_if_fail (text != NULL);
1944 if (text_length == 0)
1959 g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
1961 if (sizeof (wchar_t) != sizeof (GdkWChar))
1963 wcstr = g_new (wchar_t, text_length);
1964 for (i = 0; i < text_length; i++)
1968 wcstr = (wchar_t *) text;
1970 arg.total.cx = arg.total.cy = 0;
1972 gdk_wchar_text_handle (font, wcstr, text_length,
1973 gdk_text_size_handler, &arg);
1975 if (sizeof (wchar_t) != sizeof (GdkWChar))
1978 /* XXX This is quite bogus */
1982 *rbearing = arg.total.cx;
1984 *width = arg.total.cx;
1986 *ascent = arg.total.cy + 1;
1988 *descent = font->descent + 1;