# HG changeset patch # User YAMAMOTO Mitsuharu # Date 1129001736 0 # Node ID f455f022b7997b152cb9c1c0d5e379124a619dba # Parent 12bd2d0d9bb24e992f696150c39c78c44c9d3580 (PER_CHAR_METRIC): Remove unused macro. (fm_font_family_alist): New variable. (syms_of_macterm): Initialize and staticpro it. (decode_mac_font_name): Replace '-' in family name with '_' if it occurs just once. Lower family name. (parse_x_font_name): Rename from x_font_name_to_mac_font_name. All uses changed. Remove argument MF and code conversion for it. Add argument SIZE. Rename argument MF_DECODED to FAMILY, and CS to CHARSET. Parse font size. Lower family name. Return integer value for status of parsing. (init_font_name_table) [USE_ATSUI]: Use decode_mac_font_name. Don't use Fdowncase because family name is already lowered by decode_mac_font_name. (init_font_name_table): Always call decode_mac_font_name. Add pair of family name and its reference to fm_font_family_alist. (mac_clear_font_name_table): Clear fm_font_family_alist. (XLoadQueryFont): Move font size parsing part to parse_x_font_name. Lookup fm_font_family_alist to get font family reference. (XLoadQueryFont) [USE_ATSUI]: Don't use Fdowncase because family name is already lowered by parse_x_font_name. diff -r 12bd2d0d9bb2 -r f455f022b799 src/macterm.c --- a/src/macterm.c Tue Oct 11 00:29:35 2005 +0000 +++ b/src/macterm.c Tue Oct 11 03:35:36 2005 +0000 @@ -1766,19 +1766,6 @@ static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *)); -/* Return a pointer to per-char metric information in FONT of a - character pointed by B which is a pointer to an XChar2b. */ - -#define PER_CHAR_METRIC(font, b) \ - ((font)->per_char \ - ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \ - + (((font)->min_byte1 || (font)->max_byte1) \ - ? (((b)->byte1 - (font)->min_byte1) \ - * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \ - : 0)) \ - : &((font)->max_bounds)) - - /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B is not contained in the font. */ @@ -6843,7 +6830,13 @@ static int font_name_table_size = 0; static int font_name_count = 0; +/* Alist linking font family names to Font Manager font family + references (which can also be used as QuickDraw font IDs). We use + an alist because hash tables are not ready when the terminal frame + for Mac OS Classic is created. */ +static Lisp_Object fm_font_family_alist; #if USE_ATSUI +/* Hash table linking font family names to ATSU font IDs. */ static Lisp_Object atsu_font_id_hash; #endif @@ -6893,24 +6886,39 @@ struct coding_system coding; char *buf, *p; + if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system))) + { + for (p = name; *p; p++) + if (!isascii (*p) || iscntrl (*p)) + break; + + if (*p) + { + setup_coding_system (coding_system, &coding); + coding.src_multibyte = 0; + coding.dst_multibyte = 1; + coding.mode |= CODING_MODE_LAST_BLOCK; + coding.composing = COMPOSITION_DISABLED; + buf = (char *) alloca (size); + + decode_coding (&coding, name, buf, strlen (name), size - 1); + bcopy (buf, name, coding.produced); + name[coding.produced] = '\0'; + } + } + + /* If there's just one occurrence of '-' in the family name, it is + replaced with '_'. (More than one occurrence of '-' means a + "FOUNDRY-FAMILY-CHARSET"-style name.) */ + p = strchr (name, '-'); + if (p && strchr (p + 1, '-') == NULL) + *p = '_'; + for (p = name; *p; p++) - if (!isascii (*p) || iscntrl (*p)) - break; - - if (*p == '\0' - || NILP (coding_system) || NILP (Fcoding_system_p (coding_system))) - return; - - setup_coding_system (coding_system, &coding); - coding.src_multibyte = 0; - coding.dst_multibyte = 1; - coding.mode |= CODING_MODE_LAST_BLOCK; - coding.composing = COMPOSITION_DISABLED; - buf = (char *) alloca (size); - - decode_coding (&coding, name, buf, strlen (name), size - 1); - bcopy (buf, name, coding.produced); - name[coding.produced] = '\0'; + /* On Mac OS X 10.3, tolower also converts non-ASCII characters + for some locales. */ + if (isascii (*p)) + *p = tolower (*p); } @@ -6949,32 +6957,46 @@ } -/* Convert an X font spec to the corresponding mac font name, which - can then be passed to GetFNum after conversion to a Pascal string. - For ordinary Mac fonts, this should just be their names, like - "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts - collection contain their charset designation in their names, like - "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font - names are handled accordingly. */ -static void -x_font_name_to_mac_font_name (xf, mf, mf_decoded, style, cs) - char *xf, *mf, *mf_decoded; +/* Parse fully-specified and instantiated X11 font spec XF, and store + the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the + parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the + caller must allocate at least 256 and 32 bytes respectively. For + ordinary Mac fonts, the value stored to FAMILY should just be their + names, like "monaco", "Taipei", etc. Fonts converted from the GNU + intlfonts collection contain their charset designation in their + names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both + types of font names are handled accordingly. */ + +const int kDefaultFontSize = 12; + +static int +parse_x_font_name (xf, family, size, style, charset) + char *xf, *family; + int *size; Style *style; - char *cs; -{ - Str31 foundry; - Str255 family; - char weight[20], slant[2], *p; - Lisp_Object charset_info, coding_system = Qnil; - struct coding_system coding; - - strcpy (mf, ""); - - if (sscanf (xf, "-%31[^-]-%255[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s", - foundry, family, weight, slant, cs) != 5 && - sscanf (xf, "-%31[^-]-%255[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s", - foundry, family, weight, slant, cs) != 5) - return; + char *charset; +{ + Str31 foundry, weight; + int point_size, avgwidth; + char slant[2], *p; + + if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s", + foundry, family, weight, slant, size, + &point_size, &avgwidth, charset) != 8 + && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s", + foundry, family, weight, slant, size, + &point_size, &avgwidth, charset) != 8) + return 0; + + if (*size == 0) + { + if (point_size > 0) + *size = point_size / 10; + else if (avgwidth > 0) + *size = avgwidth / 10; + } + if (*size == 0) + *size = kDefaultFontSize; *style = normal; if (strcmp (weight, "bold") == 0) @@ -6982,32 +7004,31 @@ if (*slant == 'i') *style |= italic; - charset_info = Fassoc (build_string (cs), Vmac_charset_info_alist); - if (!NILP (charset_info)) - { - strcpy (mf_decoded, family); - coding_system = Fcar (Fcdr (Fcdr (charset_info))); - } - else - sprintf (mf_decoded, "%s-%s-%s", foundry, family, cs); - - for (p = mf_decoded; *p; p++) - if (!isascii (*p) || iscntrl (*p)) - break; - - if (*p == '\0' - || NILP (coding_system) || NILP (Fcoding_system_p (coding_system))) - strcpy (mf, mf_decoded); - else - { - setup_coding_system (coding_system, &coding); - coding.src_multibyte = 1; - coding.dst_multibyte = 0; - coding.mode |= CODING_MODE_LAST_BLOCK; - encode_coding (&coding, mf_decoded, mf, - strlen (mf_decoded), sizeof (Str255) - 1); - mf[coding.produced] = '\0'; - } + if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist))) + { + int foundry_len = strlen (foundry), family_len = strlen (family); + + if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255)) + { + /* Like sprintf (family, "%s-%s-%s", foundry, family, charset), + but take overlap into account. */ + memmove (family + foundry_len + 1, family, family_len); + memcpy (family, foundry, foundry_len); + family[foundry_len] = '-'; + family[foundry_len + 1 + family_len] = '-'; + strcpy (family + foundry_len + 1 + family_len + 1, charset); + } + else + return 0; + } + + for (p = family; *p; p++) + /* On Mac OS X 10.3, tolower also converts non-ASCII characters + for some locales. */ + if (isascii (*p)) + *p = tolower (*p); + + return 1; } @@ -7084,6 +7105,8 @@ kFontMacintoshPlatform, kFontNoScript, kFontNoLanguage, name_len, name, NULL, NULL); + if (err == noErr) + decode_mac_font_name (name, name_len + 1, Qnil); if (err == noErr && *name != '.' && (prev_name == NULL @@ -7099,7 +7122,7 @@ bold, cs)); add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold, cs)); - Fputhash (Fdowncase (make_unibyte_string (name, name_len)), + Fputhash (make_unibyte_string (name, name_len), long_to_cons (font_ids[i]), atsu_font_id_hash); xfree (prev_name); prev_name = name; @@ -7149,12 +7172,14 @@ sc = GetTextEncodingBase (encoding); text_encoding_info = assq_no_quit (make_number (sc), text_encoding_info_alist); - if (!NILP (text_encoding_info)) - decode_mac_font_name (name, sizeof (name), - XCAR (XCDR (text_encoding_info))); - else + if (NILP (text_encoding_info)) text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman), text_encoding_info_alist); + decode_mac_font_name (name, sizeof (name), + XCAR (XCDR (text_encoding_info))); + fm_font_family_alist = Fcons (Fcons (build_string (name), + make_number (ff)), + fm_font_family_alist); /* Point the instance iterator at the current font family. */ if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr) @@ -7233,12 +7258,14 @@ scriptcode = FontToScript (fontnum); text_encoding_info = assq_no_quit (make_number (scriptcode), text_encoding_info_alist); - if (!NILP (text_encoding_info)) - decode_mac_font_name (name, sizeof (name), - XCAR (XCDR (text_encoding_info))); - else + if (NILP (text_encoding_info)) text_encoding_info = assq_no_quit (make_number (smRoman), text_encoding_info_alist); + decode_mac_font_name (name, sizeof (name), + XCAR (XCDR (text_encoding_info))); + fm_font_family_alist = Fcons (Fcons (build_string (name), + make_number (fontnum)), + fm_font_family_alist); do { HLock (font_handle); @@ -7294,6 +7321,7 @@ xfree (font_name_table); font_name_table = NULL; font_name_table_size = font_name_count = 0; + fm_font_family_alist = Qnil; } @@ -7602,9 +7630,6 @@ } -const int kDefaultFontSize = 12; - - /* XLoadQueryFont creates and returns an internal representation for a font in a MacFontStruct struct. There is really no concept corresponding to "loading" a font on the Mac. But we check its @@ -7614,12 +7639,9 @@ static MacFontStruct * XLoadQueryFont (Display *dpy, char *fontname) { - int i, size, point_size, avgwidth, is_two_byte_font, char_width; + int i, size, char_width; char *name; - GrafPtr port; - SInt16 old_fontnum, old_fontsize; - Style old_fontface; - Str255 mfontname, mfontname_decoded; + Str255 family; Str31 charset; SInt16 fontnum; #if USE_ATSUI @@ -7633,10 +7655,6 @@ short scriptcode; #endif MacFontStruct *font; - FontInfo the_fontinfo; -#ifdef MAC_OSX - UInt32 old_flags, new_flags; -#endif if (is_fully_specified_xlfd (fontname)) name = fontname; @@ -7650,32 +7668,9 @@ name = SDATA (XCAR (matched_fonts)); } - GetPort (&port); /* save the current font number used */ -#if TARGET_API_MAC_CARBON - old_fontnum = GetPortTextFont (port); - old_fontsize = GetPortTextSize (port); - old_fontface = GetPortTextFace (port); -#else - old_fontnum = port->txFont; - old_fontsize = port->txSize; - old_fontface = port->txFace; -#endif - - if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%*s", &size, &point_size, &avgwidth) != 3) - size = 0; - else - { - if (size == 0) - if (point_size > 0) - size = point_size / 10; - else if (avgwidth > 0) - size = avgwidth / 10; - } - if (size == 0) - size = kDefaultFontSize; - - x_font_name_to_mac_font_name (name, mfontname, mfontname_decoded, - &fontface, charset); + if (parse_x_font_name (name, family, &size, &fontface, charset) == 0) + return NULL; + #if USE_ATSUI if (strcmp (charset, "iso10646-1") == 0) /* XXX */ { @@ -7693,9 +7688,7 @@ ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector}; Lisp_Object font_id_cons; - font_id_cons = Fgethash (Fdowncase - (make_unibyte_string (mfontname, - strlen (mfontname))), + font_id_cons = Fgethash (make_unibyte_string (family, strlen (family)), atsu_font_id_hash, Qnil); if (NILP (font_id_cons)) return NULL; @@ -7716,24 +7709,21 @@ scriptcode = kTextEncodingMacUnicode; } else - { -#endif - c2pstr (mfontname); +#endif + { + Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist); + + if (NILP (tmp)) + return NULL; + fontnum = XINT (XCDR (tmp)); #if TARGET_API_MAC_CARBON - fontnum = FMGetFontFamilyFromName (mfontname); - if (fontnum == kInvalidFontFamily - || FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr) - return NULL; - scriptcode = GetTextEncodingBase (encoding); + if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr) + return NULL; + scriptcode = GetTextEncodingBase (encoding); #else - GetFNum (mfontname, &fontnum); - if (fontnum == 0) - return NULL; - scriptcode = FontToScript (fontnum); -#endif -#if USE_ATSUI - } -#endif + scriptcode = FontToScript (fontnum); +#endif + } font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct)); @@ -7752,7 +7742,7 @@ if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0) font->mac_scriptcode = smRoman; - font->full_name = mac_to_x_fontname (mfontname_decoded, size, fontface, charset); + font->full_name = mac_to_x_fontname (family, size, fontface, charset); #if USE_ATSUI if (font->mac_style) @@ -7837,130 +7827,149 @@ font->max_char_or_byte2 = 0xff; } else - { -#endif - is_two_byte_font = font->mac_scriptcode == smJapanese || - font->mac_scriptcode == smTradChinese || - font->mac_scriptcode == smSimpChinese || - font->mac_scriptcode == smKorean; - - TextFont (fontnum); - TextSize (size); - TextFace (fontface); - - GetFontInfo (&the_fontinfo); - - font->ascent = the_fontinfo.ascent; - font->descent = the_fontinfo.descent; - - if (is_two_byte_font) - { - font->min_byte1 = 0xa1; - font->max_byte1 = 0xfe; - font->min_char_or_byte2 = 0xa1; - font->max_char_or_byte2 = 0xfe; - - /* Use the width of an "ideographic space" of that font because - the_fontinfo.widMax returns the wrong width for some fonts. */ - switch (font->mac_scriptcode) - { - case smJapanese: - font->min_byte1 = 0x81; - font->max_byte1 = 0xfc; - font->min_char_or_byte2 = 0x40; - font->max_char_or_byte2 = 0xfc; - char_width = StringWidth("\p\x81\x40"); - break; - case smTradChinese: - font->min_char_or_byte2 = 0x40; - char_width = StringWidth("\p\xa1\x40"); - break; - case smSimpChinese: - char_width = StringWidth("\p\xa1\xa1"); - break; - case smKorean: - char_width = StringWidth("\p\xa1\xa1"); - break; - } - } - else - { - font->min_byte1 = font->max_byte1 = 0; - font->min_char_or_byte2 = 0x20; - font->max_char_or_byte2 = 0xff; - - /* Do this instead of use the_fontinfo.widMax, which incorrectly - returns 15 for 12-point Monaco! */ - char_width = CharWidth ('m'); - } - - if (is_two_byte_font) - { - font->per_char = NULL; - - if (fontface & italic) - font->max_bounds.rbearing = char_width + 1; - else - font->max_bounds.rbearing = char_width; - font->max_bounds.lbearing = 0; - font->max_bounds.width = char_width; - font->max_bounds.ascent = the_fontinfo.ascent; - font->max_bounds.descent = the_fontinfo.descent; - - font->min_bounds = font->max_bounds; - } - else - { - int c, min_width, max_width; - Rect char_bounds, min_bounds, max_bounds; - char ch; - - font->per_char = xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1)); - - min_width = max_width = char_width; - SetRect (&min_bounds, -32767, -32767, 32767, 32767); - SetRect (&max_bounds, 0, 0, 0, 0); - for (c = 0x20; c <= 0xff; c++) +#endif + { + GrafPtr port; + SInt16 old_fontnum, old_fontsize; + Style old_fontface; + FontInfo the_fontinfo; + int is_two_byte_font; + + /* Save the current font number used. */ + GetPort (&port); +#if TARGET_API_MAC_CARBON + old_fontnum = GetPortTextFont (port); + old_fontsize = GetPortTextSize (port); + old_fontface = GetPortTextFace (port); +#else + old_fontnum = port->txFont; + old_fontsize = port->txSize; + old_fontface = port->txFace; +#endif + + TextFont (fontnum); + TextSize (size); + TextFace (fontface); + + GetFontInfo (&the_fontinfo); + + font->ascent = the_fontinfo.ascent; + font->descent = the_fontinfo.descent; + + is_two_byte_font = (font->mac_scriptcode == smJapanese + || font->mac_scriptcode == smTradChinese + || font->mac_scriptcode == smSimpChinese + || font->mac_scriptcode == smKorean); + + if (is_two_byte_font) { - ch = c; - char_width = CharWidth (ch); - QDTextBounds (1, &ch, &char_bounds); - STORE_XCHARSTRUCT (font->per_char[c - 0x20], - char_width, char_bounds); - /* Some Japanese fonts (in SJIS encoding) return 0 as the - character width of 0x7f. */ - if (char_width > 0) + font->min_byte1 = 0xa1; + font->max_byte1 = 0xfe; + font->min_char_or_byte2 = 0xa1; + font->max_char_or_byte2 = 0xfe; + + /* Use the width of an "ideographic space" of that font + because the_fontinfo.widMax returns the wrong width for + some fonts. */ + switch (font->mac_scriptcode) { - min_width = min (min_width, char_width); - max_width = max (max_width, char_width); - } - if (!EmptyRect (&char_bounds)) - { - SetRect (&min_bounds, - max (min_bounds.left, char_bounds.left), - max (min_bounds.top, char_bounds.top), - min (min_bounds.right, char_bounds.right), - min (min_bounds.bottom, char_bounds.bottom)); - UnionRect (&max_bounds, &char_bounds, &max_bounds); + case smJapanese: + font->min_byte1 = 0x81; + font->max_byte1 = 0xfc; + font->min_char_or_byte2 = 0x40; + font->max_char_or_byte2 = 0xfc; + char_width = StringWidth("\p\x81\x40"); + break; + case smTradChinese: + font->min_char_or_byte2 = 0x40; + char_width = StringWidth("\p\xa1\x40"); + break; + case smSimpChinese: + char_width = StringWidth("\p\xa1\xa1"); + break; + case smKorean: + char_width = StringWidth("\p\xa1\xa1"); + break; } } - STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds); - STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds); - if (min_width == max_width - && max_bounds.left >= 0 && max_bounds.right <= max_width) + else + { + font->min_byte1 = font->max_byte1 = 0; + font->min_char_or_byte2 = 0x20; + font->max_char_or_byte2 = 0xff; + + /* Do this instead of use the_fontinfo.widMax, which + incorrectly returns 15 for 12-point Monaco! */ + char_width = CharWidth ('m'); + } + + if (is_two_byte_font) { - /* Fixed width and no overhangs. */ - xfree (font->per_char); font->per_char = NULL; + + if (fontface & italic) + font->max_bounds.rbearing = char_width + 1; + else + font->max_bounds.rbearing = char_width; + font->max_bounds.lbearing = 0; + font->max_bounds.width = char_width; + font->max_bounds.ascent = the_fontinfo.ascent; + font->max_bounds.descent = the_fontinfo.descent; + + font->min_bounds = font->max_bounds; } - } - - TextFont (old_fontnum); /* restore previous font number, size and face */ - TextSize (old_fontsize); - TextFace (old_fontface); -#if USE_ATSUI - } -#endif + else + { + int c, min_width, max_width; + Rect char_bounds, min_bounds, max_bounds; + char ch; + + font->per_char = xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1)); + bzero (font->per_char, sizeof (XCharStruct) * (0xff - 0x20 + 1)); + + min_width = max_width = char_width; + SetRect (&min_bounds, -32767, -32767, 32767, 32767); + SetRect (&max_bounds, 0, 0, 0, 0); + for (c = 0x20; c <= 0xff; c++) + { + ch = c; + char_width = CharWidth (ch); + QDTextBounds (1, &ch, &char_bounds); + STORE_XCHARSTRUCT (font->per_char[c - 0x20], + char_width, char_bounds); + /* Some Japanese fonts (in SJIS encoding) return 0 as + the character width of 0x7f. */ + if (char_width > 0) + { + min_width = min (min_width, char_width); + max_width = max (max_width, char_width); + } + if (!EmptyRect (&char_bounds)) + { + SetRect (&min_bounds, + max (min_bounds.left, char_bounds.left), + max (min_bounds.top, char_bounds.top), + min (min_bounds.right, char_bounds.right), + min (min_bounds.bottom, char_bounds.bottom)); + UnionRect (&max_bounds, &char_bounds, &max_bounds); + } + } + STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds); + STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds); + if (min_width == max_width + && max_bounds.left >= 0 && max_bounds.right <= max_width) + { + /* Fixed width and no overhangs. */ + xfree (font->per_char); + font->per_char = NULL; + } + } + + /* Restore previous font number, size and face. */ + TextFont (old_fontnum); + TextSize (old_fontsize); + TextFace (old_fontface); + } return font; } @@ -10988,14 +10997,17 @@ staticpro (&Qreverse); Qreverse = intern ("reverse"); + staticpro (&Qmac_ready_for_drag_n_drop); + Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop"); + staticpro (&x_display_name_list); x_display_name_list = Qnil; staticpro (&last_mouse_scroll_bar); last_mouse_scroll_bar = Qnil; - Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop"); - staticpro (&Qmac_ready_for_drag_n_drop); + staticpro (&fm_font_family_alist); + fm_font_family_alist = Qnil; #if USE_ATSUI staticpro (&atsu_font_id_hash);