comparison src/objects-msw.c @ 788:026c5bf9c134

[xemacs-hg @ 2002-03-21 07:29:57 by ben] chartab.c: Fix bugs in implementation and doc strings. config.h.in: Add foo_checking_assert_at_line() macros. Not clear whether these are actually useful, though; I'll take them out if not. symsinit.h, emacs.c: Some improvements to the timeline. Rearrange a bit the init calls. Add call for reinit_vars_of_object_mswindows() and declare in symsinit.h. event-Xt.c, event-gtk.c, event-msw.c, event-stream.c, event-tty.c, events.c, events.h: Introduce new event methods for printing, comparing, and hashing magic events, to avoid event-type-specific stuff that had crept into events.c. (And was crashing, since the channel in MS Windows magic events may be nil.) Implement the methods in event-{tty,gtk,Xt,mswindows}.c. Make wrapping functions event_stream_{compare,hash,format}_magic_event() to check if everything's OK and call the actual callback. Fix events.c to use the new methods. Add a new event-stream-operation EVENT_STREAM_NOTHING -- event stream not actually required to be able to do anything, just be open. (#### This event-stream-operation stuff needs to be rethought.) Fixed describe_event() in event-Xt.c to print its output to a stream, not always to stderr, so it can be used elsewhere. (e.g. in print-event when a magic event is encountered?) lisp.h, lrecord.h: Define new assert_at_line(), for use in asserts inside of inline functions. The assert will report the line and file of the inline function, which is almost certainly not what you want as it's useless. what you want to see is where the pseudo-macro was called from. So, when error-checking is on, we pass in the line and file into the macros, for accurate printout using assert_at_line(). Happens only when error-checking is defined so doesn't slow down non-error-checking builds. Fix XCHAR, XINT, XCHAR_OR_INT, XFOO, and wrap_foo() in this fashion. lstream.c, lstream.h: Add resizing_buffer_to_lisp_string(). objects-gtk.c: Fix typo. objects-msw.c: Implement a smarter way of determining whether a font matches a charset. Formerly we just looked at the "script" element of the font spec, converted it to a code page, and compared it with the code page derived from the charset. Now, as well as doing this, we ask the font for the list of unicode ranges it supports, see what range the charset falls into (#### bogus! need to do this char-by-char), and see if any of the font's supported ranges include the charset's range. also do some caching in Vfont_signature_data of previous inquiries. charset.h, text.c, mule-charset.c: New fun; extracted out of Fmake_char() and declare prototype in charset.h. text.h: introduce assert_by_line() to make REP_BYTES_BY_FIRST_BYTE report the file and line more accurately in an assertion failure. unicode.c: make non-static (used in objects-msw.c), declare in charset.h. mule\mule-category.el: Start implementing a category API compatible with FSF. Not there yet. We need improvements to char-tables. mule\mule-charset.el: Copy translation table code from FSF 21.1 and fix up. Eventually we'll have them in XEmacs. (used in ccl) Not here quite yet, and we need some improvements to char-tables. mule\cyril-util.el, mule\cyrillic.el, mule\devan-util.el, mule\ethio-util.el, mule\korea-util.el, mule\mule-tty-init.el, mule\tibet-util.el, mule\viet-util.el, mule\vietnamese.el: Fix numerous compilation warnings. Fix up code related to translation tables and other types of char-tables. menubar-items.el: Move the frame commands from the View menu to the File menu, to be consistent with how most other programs do things. Move less-used revert/recover items to a submenu. Make "recover" not prompt for a file, but recover the current buffer. TODO.ben-mule-21-5: Create bug list for latest problems.
author ben
date Thu, 21 Mar 2002 07:31:30 +0000
parents 943eaba38521
children e38acbeb1cae
comparison
equal deleted inserted replaced
787:242b62e9fc59 788:026c5bf9c134
1 /* mswindows-specific Lisp objects. 1 /* mswindows-specific Lisp objects.
2 Copyright (C) 1993, 1994 Free Software Foundation, Inc. 2 Copyright (C) 1993, 1994 Free Software Foundation, Inc.
3 Copyright (C) 1995 Board of Trustees, University of Illinois. 3 Copyright (C) 1995 Board of Trustees, University of Illinois.
4 Copyright (C) 1995 Tinker Systems. 4 Copyright (C) 1995 Tinker Systems.
5 Copyright (C) 1995, 1996, 2000, 2001 Ben Wing. 5 Copyright (C) 1995, 1996, 2000, 2001, 2002 Ben Wing.
6 Copyright (C) 1995 Sun Microsystems, Inc. 6 Copyright (C) 1995 Sun Microsystems, Inc.
7 Copyright (C) 1997 Jonathan Harris. 7 Copyright (C) 1997 Jonathan Harris.
8 8
9 This file is part of XEmacs. 9 This file is part of XEmacs.
10 10
36 36
37 /* TODO: palette handling */ 37 /* TODO: palette handling */
38 38
39 #include <config.h> 39 #include <config.h>
40 #include "lisp.h" 40 #include "lisp.h"
41 #include "hash.h"
42 41
43 #include "console-msw.h" 42 #include "console-msw.h"
44 #include "objects-msw.h" 43 #include "objects-msw.h"
45 #include "buffer.h" 44 #include "buffer.h"
46 #include "charset.h" 45 #include "charset.h"
47 #include "device.h" 46 #include "device.h"
47 #include "elhash.h"
48 #include "insdel.h" 48 #include "insdel.h"
49 #include "opaque.h"
49 50
50 typedef struct colormap_t 51 typedef struct colormap_t
51 { 52 {
52 const Char_ASCII *name; 53 const Char_ASCII *name;
53 COLORREF colorref; 54 COLORREF colorref;
773 {"Mac" , MAC_CHARSET}, 774 {"Mac" , MAC_CHARSET},
774 {"Korean Johab" , JOHAB_CHARSET}, 775 {"Korean Johab" , JOHAB_CHARSET},
775 {"OEM/DOS" , OEM_CHARSET} 776 {"OEM/DOS" , OEM_CHARSET}
776 }; 777 };
777 778
779 #ifdef MULE
780
781 typedef struct unicode_subrange_raw_t
782 {
783 int subrange_bit;
784 int start; /* first Unicode codepoint */
785 int end; /* last Unicode codepoint */
786 } unicode_subrange_raw_t;
787
788 /* This table comes from MSDN, Unicode Subset Bitfields [Platform SDK
789 Documentation, Base Services, International Features, Unicode and
790 Character Sets, Unicode and Character Set Reference, Unicode and
791 Character Set Constants]. We preprocess it at startup time into an
792 array of unicode_subrange_t.
793 */
794
795 static const unicode_subrange_raw_t unicode_subrange_raw_map[] =
796 {
797 {0, 0x0020, 0x007e}, /* Basic Latin */
798 {1, 0x00a0, 0x00ff}, /* Latin-1 Supplement */
799 {2, 0x0100, 0x017f}, /* Latin Extended-A */
800 {3, 0x0180, 0x024f}, /* Latin Extended-B */
801 {4, 0x0250, 0x02af}, /* IPA Extensions */
802 {5, 0x02b0, 0x02ff}, /* Spacing Modifier Letters */
803 {6, 0x0300, 0x036f}, /* Combining Diacritical Marks */
804 {7, 0x0370, 0x03ff}, /* Basic Greek */
805 /* 8 Reserved */
806 {9, 0x0400, 0x04ff}, /* Cyrillic */
807 {10, 0x0530, 0x058f}, /* Armenian */
808 {11, 0x0590, 0x05ff}, /* Basic Hebrew */
809 /* 12 Reserved */
810 {13, 0x0600, 0x06ff}, /* Basic Arabic */
811 /* 14 Reserved */
812 {15, 0x0900, 0x097f}, /* Devanagari */
813 {16, 0x0980, 0x09ff}, /* Bengali */
814 {17, 0x0a00, 0x0a7f}, /* Gurmukhi */
815 {18, 0x0a80, 0x0aff}, /* Gujarati */
816 {19, 0x0b00, 0x0b7f}, /* Oriya */
817 {20, 0x0b80, 0x0bff}, /* Tamil */
818 {21, 0x0c00, 0x0c7f}, /* Telugu */
819 {22, 0x0c80, 0x0cff}, /* Kannada */
820 {23, 0x0d00, 0x0d7f}, /* Malayalam */
821 {24, 0x0e00, 0x0e7f}, /* Thai */
822 {25, 0x0e80, 0x0eff}, /* Lao */
823 {26, 0x10a0, 0x10ff}, /* Basic Georgian */
824 /* 27 Reserved */
825 {28, 0x1100, 0x11ff}, /* Hangul Jamo */
826 {29, 0x1e00, 0x1eff}, /* Latin Extended Additional */
827 {30, 0x1f00, 0x1fff}, /* Greek Extended */
828 {31, 0x2000, 0x206f}, /* General Punctuation */
829 {32, 0x2070, 0x209f}, /* Subscripts and Superscripts */
830 {33, 0x20a0, 0x20cf}, /* Currency Symbols */
831 {34, 0x20d0, 0x20ff}, /* Combining Diacritical Marks for Symbols */
832 {35, 0x2100, 0x214f}, /* Letter-like Symbols */
833 {36, 0x2150, 0x218f}, /* Number Forms */
834 {37, 0x2190, 0x21ff}, /* Arrows */
835 {38, 0x2200, 0x22ff}, /* Mathematical Operators */
836 {39, 0x2300, 0x23ff}, /* Miscellaneous Technical */
837 {40, 0x2400, 0x243f}, /* Control Pictures */
838 {41, 0x2440, 0x245f}, /* Optical Character Recognition */
839 {42, 0x2460, 0x24ff}, /* Enclosed Alphanumerics */
840 {43, 0x2500, 0x257f}, /* Box Drawing */
841 {44, 0x2580, 0x259f}, /* Block Elements */
842 {45, 0x25a0, 0x25ff}, /* Geometric Shapes */
843 {46, 0x2600, 0x26ff}, /* Miscellaneous Symbols */
844 {47, 0x2700, 0x27bf}, /* Dingbats */
845 {48, 0x3000, 0x303f}, /* Chinese, Japanese, and Korean (CJK) Symbols and Punctuation */
846 {49, 0x3040, 0x309f}, /* Hiragana */
847 {50, 0x30a0, 0x30ff}, /* Katakana */
848 {51, 0x3100, 0x312f}, /* Bopomofo */
849 {51, 0x31a0, 0x31bf}, /* Extended Bopomofo */
850 {52, 0x3130, 0x318f}, /* Hangul Compatibility Jamo */
851 {53, 0x3190, 0x319f}, /* CJK Miscellaneous */
852 {54, 0x3200, 0x32ff}, /* Enclosed CJK Letters and Months */
853 {55, 0x3300, 0x33ff}, /* CJK Compatibility */
854 {56, 0xac00, 0xd7a3}, /* Hangul */
855 {57, 0xd800, 0xdfff}, /* Surrogates. Note that setting this bit implies that there is at least one codepoint beyond the Basic Multilingual Plane that is supported by this font. */
856 /* 58 Reserved */
857 {59, 0x4e00, 0x9fff}, /* CJK Unified Ideographs */
858 {59, 0x2e80, 0x2eff}, /* CJK Radicals Supplement */
859 {59, 0x2f00, 0x2fdf}, /* Kangxi Radicals */
860 {59, 0x2ff0, 0x2fff}, /* Ideographic Description */
861 {59, 0x3400, 0x4dbf}, /* CJK Unified Ideograph Extension A */
862 {60, 0xe000, 0xf8ff}, /* Private Use Area */
863 {61, 0xf900, 0xfaff}, /* CJK Compatibility Ideographs */
864 {62, 0xfb00, 0xfb4f}, /* Alphabetic Presentation Forms */
865 {63, 0xfb50, 0xfdff}, /* Arabic Presentation Forms-A */
866 {64, 0xfe20, 0xfe2f}, /* Combining Half Marks */
867 {65, 0xfe30, 0xfe4f}, /* CJK Compatibility Forms */
868 {66, 0xfe50, 0xfe6f}, /* Small Form Variants */
869 {67, 0xfe70, 0xfefe}, /* Arabic Presentation Forms-B */
870 {68, 0xff00, 0xffef}, /* Halfwidth and Fullwidth Forms */
871 {69, 0xfff0, 0xfffd}, /* Specials */
872 {70, 0x0f00, 0x0fcf}, /* Tibetan */
873 {71, 0x0700, 0x074f}, /* Syriac */
874 {72, 0x0780, 0x07bf}, /* Thaana */
875 {73, 0x0d80, 0x0dff}, /* Sinhala */
876 {74, 0x1000, 0x109f}, /* Myanmar */
877 {75, 0x1200, 0x12bf}, /* Ethiopic */
878 {76, 0x13a0, 0x13ff}, /* Cherokee */
879 {77, 0x1400, 0x14df}, /* Canadian Aboriginal Syllabics */
880 {78, 0x1680, 0x169f}, /* Ogham */
881 {79, 0x16a0, 0x16ff}, /* Runic */
882 {80, 0x1780, 0x17ff}, /* Khmer */
883 {81, 0x1800, 0x18af}, /* Mongolian */
884 {82, 0x2800, 0x28ff}, /* Braille */
885 {83, 0xa000, 0xa48c}, /* Yi, Yi Radicals */
886 /* 84-122 Reserved */
887 /* 123 Windows 2000/XP: Layout progress: horizontal from right to left */
888 /* 124 Windows 2000/XP: Layout progress: vertical before horizontal */
889 /* 125 Windows 2000/XP: Layout progress: vertical bottom to top */
890 /* 126 Reserved; must be 0 */
891 /* 127 Reserved; must be 1 */
892 };
893
894 typedef struct unicode_subrange_t
895 {
896 int no_subranges;
897 const unicode_subrange_raw_t *subranges;
898 } unicode_subrange_t;
899
900 unicode_subrange_t *unicode_subrange_table;
901
902 /* Hash table mapping font specs (strings) to font signature data
903 (FONTSIGNATURE structures stored in opaques), as determined by
904 GetTextCharsetInfo(). I presume this is somewhat expensive because it
905 involves creating a font object. At the very least, with no hashing, it
906 definitely took awhile (a few seconds) when encountering characters from
907 charsets needing stage 2 processing. */
908 Lisp_Object Vfont_signature_data;
909
910 #endif /* MULE */
911
778 912
779 /************************************************************************/ 913 /************************************************************************/
780 /* helpers */ 914 /* helpers */
781 /************************************************************************/ 915 /************************************************************************/
782 916
1185 1319
1186 1320
1187 static void 1321 static void
1188 mswindows_finalize_font_instance (Lisp_Font_Instance *f); 1322 mswindows_finalize_font_instance (Lisp_Font_Instance *f);
1189 1323
1190 /* 1324 static HFONT
1191 * This is a work horse for both mswindows_initialize_font_instance and 1325 create_hfont_from_font_spec (const Intbyte *namestr,
1192 * msprinter_initialize_font_instance. 1326 HDC hdc,
1193 */ 1327 Lisp_Object name_for_errors,
1194 static int 1328 Lisp_Object device_font_list,
1195 initialize_font_instance (Lisp_Font_Instance *f, Lisp_Object name, 1329 Error_Behavior errb)
1196 Lisp_Object device_font_list, HDC hdc,
1197 Error_Behavior errb)
1198 { 1330 {
1199 LOGFONTW logfont; 1331 LOGFONTW logfont;
1200 int fields, i; 1332 int fields, i;
1201 int pt; 1333 int pt;
1202 Intbyte fontname[LF_FACESIZE], weight[LF_FACESIZE], *style, points[8]; 1334 Intbyte fontname[LF_FACESIZE], weight[LF_FACESIZE], *style, points[8];
1203 Intbyte effects[LF_FACESIZE], charset[LF_FACESIZE]; 1335 Intbyte effects[LF_FACESIZE], charset[LF_FACESIZE];
1204 Intbyte *c; 1336 Intbyte *c;
1205 HFONT hfont, hfont2; 1337 HFONT hfont;
1206 TEXTMETRICW metrics;
1207 Intbyte *namestr = XSTRING_DATA (name);
1208 1338
1209 /* 1339 /*
1210 * mswindows fonts look like: 1340 * mswindows fonts look like:
1211 * fontname[:[weight ][style][:pointsize[:effects]]][:charset] 1341 * fontname[:[weight ][style][:pointsize[:effects]]][:charset]
1212 * The font name field shouldn't be empty. 1342 * The font name field shouldn't be empty.
1228 * us to use match_font() on a canonicalized font string to check the 1358 * us to use match_font() on a canonicalized font string to check the
1229 * availability of the requested font */ 1359 * availability of the requested font */
1230 1360
1231 if (fields < 0) 1361 if (fields < 0)
1232 { 1362 {
1233 maybe_signal_error (Qinvalid_argument, "Invalid font", name, 1363 maybe_signal_error (Qinvalid_argument, "Invalid font", name_for_errors,
1234 Qfont, errb); 1364 Qfont, errb);
1235 return (0); 1365 return NULL;
1236 } 1366 }
1237 1367
1238 if (fields > 0 && qxestrlen (fontname)) 1368 if (fields > 0 && qxestrlen (fontname))
1239 { 1369 {
1240 Extbyte *extfontname; 1370 Extbyte *extfontname;
1244 logfont.lfFaceName[LF_FACESIZE - 1] = 0; 1374 logfont.lfFaceName[LF_FACESIZE - 1] = 0;
1245 } 1375 }
1246 else 1376 else
1247 { 1377 {
1248 maybe_signal_error (Qinvalid_argument, "Must specify a font name", 1378 maybe_signal_error (Qinvalid_argument, "Must specify a font name",
1249 name, Qfont, errb); 1379 name_for_errors, Qfont, errb);
1250 return (0); 1380 return NULL;
1251 } 1381 }
1252 1382
1253 /* weight */ 1383 /* weight */
1254 if (fields < 2) 1384 if (fields < 2)
1255 qxestrcpy_c (weight, fontweight_map[0].name); 1385 qxestrcpy_c (weight, fontweight_map[0].name);
1276 logfont.lfWeight = FW_REGULAR; 1406 logfont.lfWeight = FW_REGULAR;
1277 style = weight; /* May have specified style without weight */ 1407 style = weight; /* May have specified style without weight */
1278 } 1408 }
1279 else 1409 else
1280 { 1410 {
1281 maybe_signal_error (Qinvalid_constant, "Invalid font weight", name, 1411 maybe_signal_error (Qinvalid_constant, "Invalid font weight",
1282 Qfont, errb); 1412 name_for_errors, Qfont, errb);
1283 return (0); 1413 return NULL;
1284 } 1414 }
1285 } 1415 }
1286 1416
1287 if (style) 1417 if (style)
1288 { 1418 {
1289 /* #### what about oblique? */ 1419 /* #### what about oblique? */
1290 if (qxestrcasecmp_c (style, "italic") == 0) 1420 if (qxestrcasecmp_c (style, "italic") == 0)
1291 logfont.lfItalic = TRUE; 1421 logfont.lfItalic = TRUE;
1292 else 1422 else
1293 { 1423 {
1294 maybe_signal_error (Qinvalid_constant, "Invalid font weight or style", 1424 maybe_signal_error (Qinvalid_constant,
1295 name, Qfont, errb); 1425 "Invalid font weight or style",
1296 return (0); 1426 name_for_errors, Qfont, errb);
1427 return NULL;
1297 } 1428 }
1298 1429
1299 /* Glue weight and style together again */ 1430 /* Glue weight and style together again */
1300 if (weight != style) 1431 if (weight != style)
1301 *c = ' '; 1432 *c = ' ';
1305 1436
1306 if (fields < 3) 1437 if (fields < 3)
1307 pt = 10; /* #### Should we reject strings that don't specify a size? */ 1438 pt = 10; /* #### Should we reject strings that don't specify a size? */
1308 else if ((pt = qxeatoi (points)) == 0) 1439 else if ((pt = qxeatoi (points)) == 0)
1309 { 1440 {
1310 maybe_signal_error (Qinvalid_argument, "Invalid font pointsize", name, 1441 maybe_signal_error (Qinvalid_argument, "Invalid font pointsize",
1311 Qfont, errb); 1442 name_for_errors, Qfont, errb);
1312 return (0); 1443 return NULL;
1313 } 1444 }
1314 1445
1315 /* Formula for pointsize->height from LOGFONT docs in MSVC5 Platform SDK */ 1446 /* Formula for pointsize->height from LOGFONT docs in MSVC5 Platform SDK */
1316 logfont.lfHeight = -MulDiv (pt, GetDeviceCaps (hdc, LOGPIXELSY), 72); 1447 logfont.lfHeight = -MulDiv (pt, GetDeviceCaps (hdc, LOGPIXELSY), 72);
1317 logfont.lfWidth = 0; 1448 logfont.lfWidth = 0;
1336 logfont.lfUnderline = TRUE; 1467 logfont.lfUnderline = TRUE;
1337 else if (qxestrcasecmp_c (effects, "strikeout") == 0) 1468 else if (qxestrcasecmp_c (effects, "strikeout") == 0)
1338 logfont.lfStrikeOut = TRUE; 1469 logfont.lfStrikeOut = TRUE;
1339 else 1470 else
1340 { 1471 {
1341 maybe_signal_error (Qinvalid_constant, "Invalid font effect", name, 1472 maybe_signal_error (Qinvalid_constant, "Invalid font effect",
1342 Qfont, errb); 1473 name_for_errors, Qfont, errb);
1343 return (0); 1474 return NULL;
1344 } 1475 }
1345 1476
1346 if (effects2 && effects2[0] != '\0') 1477 if (effects2 && effects2[0] != '\0')
1347 { 1478 {
1348 if (qxestrcasecmp_c (effects2, "underline") == 0) 1479 if (qxestrcasecmp_c (effects2, "underline") == 0)
1350 else if (qxestrcasecmp_c (effects2, "strikeout") == 0) 1481 else if (qxestrcasecmp_c (effects2, "strikeout") == 0)
1351 logfont.lfStrikeOut = TRUE; 1482 logfont.lfStrikeOut = TRUE;
1352 else 1483 else
1353 { 1484 {
1354 maybe_signal_error (Qinvalid_constant, "Invalid font effect", 1485 maybe_signal_error (Qinvalid_constant, "Invalid font effect",
1355 name, Qfont, errb); 1486 name_for_errors, Qfont, errb);
1356 return (0); 1487 return NULL;
1357 } 1488 }
1358 } 1489 }
1359 1490
1360 /* Regenerate sanitised effects string */ 1491 /* Regenerate sanitised effects string */
1361 if (logfont.lfUnderline) 1492 if (logfont.lfUnderline)
1392 break; 1523 break;
1393 } 1524 }
1394 1525
1395 if (i == countof (charset_map)) /* No matching charset */ 1526 if (i == countof (charset_map)) /* No matching charset */
1396 { 1527 {
1397 maybe_signal_error (Qinvalid_argument, "Invalid charset", name, Qfont, 1528 maybe_signal_error (Qinvalid_argument, "Invalid charset",
1398 errb); 1529 name_for_errors, Qfont, errb);
1399 return 0; 1530 return NULL;
1400 } 1531 }
1401 1532
1402 /* Misc crud */ 1533 /* Misc crud */
1403 logfont.lfEscapement = logfont.lfOrientation = 0; 1534 logfont.lfEscapement = logfont.lfOrientation = 0;
1404 #if 1 1535 #if 1
1432 NULL)) 1563 NULL))
1433 break; 1564 break;
1434 } 1565 }
1435 if (NILP (fonttail)) 1566 if (NILP (fonttail))
1436 { 1567 {
1437 maybe_signal_error (Qinvalid_argument, "No matching font", name, 1568 maybe_signal_error (Qinvalid_argument, "No matching font",
1438 Qfont, errb); 1569 name_for_errors, Qfont, errb);
1439 return 0; 1570 return NULL;
1440 } 1571 }
1441 } 1572 }
1442 1573
1443 if ((hfont = qxeCreateFontIndirect (&logfont)) == NULL) 1574 if ((hfont = qxeCreateFontIndirect (&logfont)) == NULL)
1444 { 1575 {
1445 maybe_signal_error (Qgui_error, "Couldn't create font", name, Qfont, errb); 1576 maybe_signal_error (Qgui_error, "Couldn't create font",
1446 return 0; 1577 name_for_errors, Qfont, errb);
1447 } 1578 return NULL;
1448 1579 }
1580
1581 return hfont;
1582 }
1583
1584
1585 /*
1586 * This is a work horse for both mswindows_initialize_font_instance and
1587 * msprinter_initialize_font_instance.
1588 */
1589 static int
1590 initialize_font_instance (Lisp_Font_Instance *f, Lisp_Object name,
1591 Lisp_Object device_font_list, HDC hdc,
1592 Error_Behavior errb)
1593 {
1594 HFONT hfont, hfont2;
1595 TEXTMETRICW metrics;
1596 Intbyte *namestr = XSTRING_DATA (name);
1597
1598 hfont = create_hfont_from_font_spec (namestr, hdc, name, device_font_list,
1599 errb);
1449 f->data = xnew_and_zero (struct mswindows_font_instance_data); 1600 f->data = xnew_and_zero (struct mswindows_font_instance_data);
1450 FONT_INSTANCE_MSWINDOWS_HFONT_VARIANT (f,0,0) = hfont; 1601 FONT_INSTANCE_MSWINDOWS_HFONT_VARIANT (f,0,0) = hfont;
1451 1602
1452 /* Some underlined fonts have the descent of one pixel more than their 1603 /* Some underlined fonts have the descent of one pixel more than their
1453 non-underlined counterparts. Font variants though are assumed to have 1604 non-underlined counterparts. Font variants though are assumed to have
1610 } 1761 }
1611 1762
1612 #ifdef MULE 1763 #ifdef MULE
1613 1764
1614 static int 1765 static int
1766 mswindows_font_spec_matches_charset_stage_1 (const Intbyte *font_charset,
1767 Lisp_Object charset)
1768 {
1769 int i, ms_charset = 0;
1770 CHARSETINFO info;
1771 int font_code_page;
1772 Lisp_Object charset_code_page;
1773
1774 /* Get code page from the font spec */
1775
1776 for (i = 0; i < countof (charset_map); i++)
1777 if (qxestrcasecmp_c (font_charset, charset_map[i].name) == 0)
1778 {
1779 ms_charset = charset_map[i].value;
1780 break;
1781 }
1782 if (i == countof (charset_map))
1783 return 0;
1784
1785 /* For border-glyph use */
1786 if (ms_charset == SYMBOL_CHARSET)
1787 ms_charset = ANSI_CHARSET;
1788
1789 if (!TranslateCharsetInfo ((DWORD *) ms_charset, &info, TCI_SRCCHARSET))
1790 return 0;
1791
1792 font_code_page = info.ciACP;
1793
1794 /* Get code page for the charset */
1795 charset_code_page = Fmswindows_charset_code_page (charset);
1796 if (!INTP (charset_code_page))
1797 return 0;
1798
1799 return font_code_page == XINT (charset_code_page);
1800 }
1801
1802 static int
1615 mswindows_font_spec_matches_charset (struct device *d, Lisp_Object charset, 1803 mswindows_font_spec_matches_charset (struct device *d, Lisp_Object charset,
1616 const Intbyte *nonreloc, 1804 const Intbyte *nonreloc,
1617 Lisp_Object reloc, 1805 Lisp_Object reloc,
1618 Bytecount offset, Bytecount length) 1806 Bytecount offset, Bytecount length)
1619 { 1807 {
1620 const Intbyte *the_nonreloc = nonreloc; 1808 const Intbyte *the_nonreloc = nonreloc;
1621 int i, ms_charset = 0; 1809 int i;
1622 const Intbyte *c; 1810 const Intbyte *c;
1623 Bytecount the_length = length; 1811 Bytecount the_length = length;
1624 CHARSETINFO info; 1812
1625 int font_code_page; 1813 /* The idea is that, when trying to find a suitable font for a character,
1626 Lisp_Object charset_code_page; 1814 we first see if the character comes from one of the known charsets
1815 listed above; if so, we try to find a font which is declared as being of
1816 that charset (that's the last element of the font spec). If so, this
1817 means that the font is specifically designed for the charset, and we
1818 prefer it. However, there are only a limited number of defined
1819 charsets, and new ones aren't being defined; so if we fail the first
1820 stage, we search through each font looking at the Unicode subranges it
1821 supports, to see if the character comes from that subrange.
1822 */
1627 1823
1628 if (UNBOUNDP (charset)) 1824 if (UNBOUNDP (charset))
1629 return 1; 1825 return 1;
1630 1826
1631 if (!the_nonreloc) 1827 if (!the_nonreloc)
1632 the_nonreloc = XSTRING_DATA (reloc); 1828 the_nonreloc = XSTRING_DATA (reloc);
1633 fixup_internal_substring (nonreloc, reloc, offset, &the_length); 1829 fixup_internal_substring (nonreloc, reloc, offset, &the_length);
1634 the_nonreloc += offset; 1830 the_nonreloc += offset;
1635 1831
1636 /* Get code page from the font spec */
1637
1638 c = the_nonreloc; 1832 c = the_nonreloc;
1639 for (i = 0; i < 4; i++) 1833 for (i = 0; i < 4; i++)
1640 { 1834 {
1641 Intbyte *newc = (Intbyte *) memchr (c, ':', the_length); 1835 Intbyte *newc = (Intbyte *) memchr (c, ':', the_length);
1642 if (!newc) 1836 if (!newc)
1644 newc++; 1838 newc++;
1645 the_length -= (newc - c); 1839 the_length -= (newc - c);
1646 c = newc; 1840 c = newc;
1647 } 1841 }
1648 1842
1649 if (i < 4) 1843 if (i >= 4 && mswindows_font_spec_matches_charset_stage_1 (c, charset))
1650 return 0; 1844 return 1;
1651 1845
1652 for (i = 0; i < countof (charset_map); i++) 1846 /* Stage 2. */
1653 if (qxestrcasecmp_c (c, charset_map[i].name) == 0) 1847 {
1848 FONTSIGNATURE fs;
1849 FONTSIGNATURE *fsp = &fs;
1850 struct gcpro gcpro1;
1851 Lisp_Object fontsig;
1852
1853 /* Get the list of Unicode subranges corresponding to the font. This
1854 is contained inside of FONTSIGNATURE data, obtained by calling
1855 GetTextCharsetInfo on a font object, which we need to create from the
1856 spec. See if the FONTSIGNATURE data is already cached. If not, get
1857 it and cache it. */
1858 if (!STRINGP (reloc) || the_nonreloc != XSTRING_DATA (reloc))
1859 reloc = build_intstring (the_nonreloc);
1860 GCPRO1 (reloc);
1861 fontsig = Fgethash (reloc, Vfont_signature_data, Qunbound);
1862
1863 if (!UNBOUNDP (fontsig))
1654 { 1864 {
1655 ms_charset = charset_map[i].value; 1865 fsp = (FONTSIGNATURE *) XOPAQUE_DATA (fontsig);
1656 break; 1866 UNGCPRO;
1657 } 1867 }
1658 if (i == countof (charset_map)) 1868 else
1659 return 0; 1869 {
1660 1870 HDC hdc = CreateCompatibleDC (NULL);
1661 /* For border-glyph use */ 1871 Lisp_Object font_list = DEVICE_MSWINDOWS_FONTLIST (d);
1662 if (ms_charset == SYMBOL_CHARSET) 1872 HFONT hfont = create_hfont_from_font_spec (the_nonreloc, hdc, Qnil,
1663 ms_charset = ANSI_CHARSET; 1873 font_list, ERROR_ME_NOT);
1664 1874
1665 if (!TranslateCharsetInfo ((DWORD *) ms_charset, &info, TCI_SRCCHARSET)) 1875 if (!hfont || !(hfont = (HFONT) SelectObject (hdc, hfont)))
1666 return 0; 1876 {
1667 1877 nope:
1668 font_code_page = info.ciACP; 1878 DeleteDC (hdc);
1669 1879 UNGCPRO;
1670 /* Get code page for the charset */ 1880 return 0;
1671 charset_code_page = Fmswindows_charset_code_page (charset); 1881 }
1672 if (!INTP (charset_code_page)) 1882
1673 return 0; 1883 if (GetTextCharsetInfo (hdc, &fs, 0) == DEFAULT_CHARSET)
1674 1884 {
1675 return font_code_page == XINT (charset_code_page); 1885 SelectObject (hdc, hfont);
1886 goto nope;
1887 }
1888 SelectObject (hdc, hfont);
1889 DeleteDC (hdc);
1890 Fputhash (reloc, make_opaque (&fs, sizeof (fs)), Vfont_signature_data);
1891 UNGCPRO;
1892 }
1893
1894 {
1895 int lowlim, highlim;
1896 int dim, j, cp = -1;
1897
1898 /* Try to find a Unicode char in the charset. #### This is somewhat
1899 bogus. We should really be doing these checks on the char level,
1900 not the charset level. There's no guarantee that a charset covers
1901 a single Unicode range. Furthermore, this is extremely wasteful.
1902 We should be doing this when we're about to redisplay and already
1903 have the Unicode codepoints in hand.
1904
1905 #### Cache me baby!!!!!!!!!!!!!
1906 */
1907 get_charset_limits (charset, &lowlim, &highlim);
1908 dim = XCHARSET_DIMENSION (charset);
1909
1910 if (dim == 1)
1911 {
1912 for (i = lowlim; i <= highlim; i++)
1913 if ((cp = char_to_unicode (MAKE_CHAR (charset, i, 0))) >= 0)
1914 break;
1915 }
1916 else
1917 {
1918 for (i = lowlim; i <= highlim; i++)
1919 for (j = lowlim; j <= highlim; j++)
1920 if ((cp = char_to_unicode (MAKE_CHAR (charset, i, j))) >= 0)
1921 break;
1922 }
1923
1924 if (cp < 0)
1925 return 0;
1926
1927 /* Check to see, for each subrange supported by the font,
1928 whether the Unicode char is within that subrange. If any match,
1929 the font supports the char (whereby, the charset, bogusly). */
1930
1931 for (i = 0; i < 128; i++)
1932 {
1933 if (fsp->fsUsb[i >> 5] & (1 << (i & 32)))
1934 {
1935 for (j = 0; j < unicode_subrange_table[i].no_subranges; j++)
1936 if (cp >= unicode_subrange_table[i].subranges[j].start &&
1937 cp <= unicode_subrange_table[i].subranges[j].end)
1938 return 1;
1939 }
1940 }
1941
1942 return 0;
1943 }
1944 }
1676 } 1945 }
1677 1946
1678 /* find a font spec that matches font spec FONT and also matches 1947 /* find a font spec that matches font spec FONT and also matches
1679 (the registry of) CHARSET. */ 1948 (the registry of) CHARSET. */
1680 static Lisp_Object 1949 static Lisp_Object
1773 CONSOLE_INHERITS_METHOD (msprinter, mswindows, find_charset_font); 2042 CONSOLE_INHERITS_METHOD (msprinter, mswindows, find_charset_font);
1774 #endif 2043 #endif
1775 } 2044 }
1776 2045
1777 void 2046 void
2047 reinit_vars_of_object_mswindows (void)
2048 {
2049 #ifdef MULE
2050 int i;
2051
2052 unicode_subrange_table = xnew_array_and_zero (unicode_subrange_t, 128);
2053 for (i = 0; i < countof (unicode_subrange_raw_map); i++)
2054 {
2055 const unicode_subrange_raw_t *el = &unicode_subrange_raw_map[i];
2056 if (unicode_subrange_table[el->subrange_bit].subranges == 0)
2057 unicode_subrange_table[el->subrange_bit].subranges = el;
2058 unicode_subrange_table[el->subrange_bit].no_subranges++;
2059 }
2060
2061 Fclrhash (Vfont_signature_data);
2062 #endif /* MULE */
2063 }
2064
2065 void
1778 vars_of_objects_mswindows (void) 2066 vars_of_objects_mswindows (void)
1779 { 2067 {
1780 } 2068 #ifdef MULE
2069 Vfont_signature_data =
2070 make_lisp_hash_table (100, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
2071 staticpro (&Vfont_signature_data);
2072 #endif /* MULE */
2073
2074 reinit_vars_of_object_mswindows ();
2075 }