aboutsummaryrefslogtreecommitdiffstats
path: root/src/macterm.c
diff options
context:
space:
mode:
authorMiles Bader2005-09-11 22:21:01 +0000
committerMiles Bader2005-09-11 22:21:01 +0000
commitff8d296438e69b8cf701d95b6ccd271c416c46fd (patch)
tree44b388101b40592656ad4c5033aabe2a1ae4b462 /src/macterm.c
parent389cb481135145b80a679beec8cdc8fed75682c5 (diff)
parenta8f6d239d2d541ec874a22000e0542c20fd55a67 (diff)
downloademacs-ff8d296438e69b8cf701d95b6ccd271c416c46fd.tar.gz
emacs-ff8d296438e69b8cf701d95b6ccd271c416c46fd.zip
Revision: miles@gnu.org--gnu-2005/emacs--unicode--0--patch-81
Merge from emacs--cvs-trunk--0 Patches applied: * emacs--cvs-trunk--0 (patch 532-541) - Update from CVS - Merge from gnus--rel--5.10 * gnus--rel--5.10 (patch 112-115) - Update from CVS
Diffstat (limited to 'src/macterm.c')
-rw-r--r--src/macterm.c445
1 files changed, 357 insertions, 88 deletions
diff --git a/src/macterm.c b/src/macterm.c
index 099b69bfb09..d9b533a9b8c 100644
--- a/src/macterm.c
+++ b/src/macterm.c
@@ -6100,6 +6100,335 @@ x_wm_set_icon_position (f, icon_x, icon_y)
6100 6100
6101 6101
6102/*********************************************************************** 6102/***********************************************************************
6103 XLFD Pattern Match
6104 ***********************************************************************/
6105
6106/* An XLFD pattern is divided into blocks delimited by '*'. This
6107 structure holds information for each block. */
6108struct xlfdpat_block
6109{
6110 /* Length of the pattern string in this block. Non-zero except for
6111 the first and the last blocks. */
6112 int len;
6113
6114 /* Pattern string except the last character in this block. The last
6115 character is replaced with NUL in order to use it as a
6116 sentinel. */
6117 unsigned char *pattern;
6118
6119 /* Last character of the pattern string. Must not be '?'. */
6120 unsigned char last_char;
6121
6122 /* One of the tables for the Boyer-Moore string search. It
6123 specifies the number of positions to proceed for each character
6124 with which the match fails. */
6125 int skip[256];
6126
6127 /* The skip value for the last character in the above `skip' is
6128 assigned to `infinity' in order to simplify a loop condition.
6129 The original value is saved here. */
6130 int last_char_skip;
6131};
6132
6133struct xlfdpat
6134{
6135 /* Normalized pattern string. "Normalized" means that capital
6136 letters are lowered, blocks are not empty except the first and
6137 the last ones, and trailing '?'s in a block that is not the last
6138 one are moved to the next one. The last character in each block
6139 is replaced with NUL. */
6140 unsigned char *buf;
6141
6142 /* Number of characters except '*'s and trailing '?'s in the
6143 normalized pattern string. */
6144 int nchars;
6145
6146 /* Number of trailing '?'s in the normalized pattern string. */
6147 int trailing_anychars;
6148
6149 /* Number of blocks and information for each block. The latter is
6150 NULL if the pattern is exact (no '*' or '?' in it). */
6151 int nblocks;
6152 struct xlfdpat_block *blocks;
6153};
6154
6155static void
6156xlfdpat_destroy (pat)
6157 struct xlfdpat *pat;
6158{
6159 if (pat)
6160 {
6161 if (pat->buf)
6162 {
6163 if (pat->blocks)
6164 xfree (pat->blocks);
6165 xfree (pat->buf);
6166 }
6167 xfree (pat);
6168 }
6169}
6170
6171static struct xlfdpat *
6172xlfdpat_create (pattern)
6173 char *pattern;
6174{
6175 struct xlfdpat *pat;
6176 int nblocks, i, skip;
6177 unsigned char last_char, *p, *q, *anychar_head;
6178 struct xlfdpat_block *blk;
6179
6180 pat = xmalloc (sizeof (struct xlfdpat));
6181 if (pat == NULL)
6182 goto error;
6183
6184 pat->buf = xmalloc (strlen (pattern) + 1);
6185 if (pat->buf == NULL)
6186 goto error;
6187
6188 /* Normalize the pattern string and store it to `pat->buf'. */
6189 nblocks = 0;
6190 anychar_head = NULL;
6191 q = pat->buf;
6192 last_char = '\0';
6193 for (p = pattern; *p; p++)
6194 {
6195 unsigned char c = *p;
6196
6197 if (c == '*')
6198 if (last_char == '*')
6199 /* ...a** -> ...a* */
6200 continue;
6201 else
6202 {
6203 if (last_char == '?')
6204 if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
6205 /* ...*??* -> ...*?? */
6206 continue;
6207 else
6208 /* ...a??* -> ...a*?? */
6209 {
6210 *anychar_head++ = '*';
6211 c = '?';
6212 }
6213 nblocks++;
6214 }
6215 else if (c == '?')
6216 {
6217 if (last_char != '?')
6218 anychar_head = q;
6219 }
6220 else
6221 /* On Mac OS X 10.3, tolower also converts non-ASCII
6222 characters for some locales. */
6223 if (isascii (c))
6224 c = tolower (c);
6225
6226 *q++ = last_char = c;
6227 }
6228 *q = '\0';
6229 nblocks++;
6230 pat->nblocks = nblocks;
6231 if (last_char != '?')
6232 pat->trailing_anychars = 0;
6233 else
6234 {
6235 pat->trailing_anychars = q - anychar_head;
6236 q = anychar_head;
6237 }
6238 pat->nchars = q - pat->buf - (nblocks - 1);
6239
6240 if (anychar_head == NULL && nblocks == 1)
6241 {
6242 /* The pattern is exact. */
6243 pat->blocks = NULL;
6244 return pat;
6245 }
6246
6247 pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
6248 if (pat->blocks == NULL)
6249 goto error;
6250
6251 /* Divide the normalized pattern into blocks. */
6252 p = pat->buf;
6253 for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
6254 {
6255 blk->pattern = p;
6256 while (*p != '*')
6257 p++;
6258 blk->len = p - blk->pattern;
6259 p++;
6260 }
6261 blk->pattern = p;
6262 blk->len = q - blk->pattern;
6263
6264 /* Setup a table for the Boyer-Moore string search. */
6265 for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
6266 if (blk->len != 0)
6267 {
6268 blk->last_char = blk->pattern[blk->len - 1];
6269 blk->pattern[blk->len - 1] = '\0';
6270
6271 for (skip = 1; skip < blk->len; skip++)
6272 if (blk->pattern[blk->len - skip - 1] == '?')
6273 break;
6274
6275 for (i = 0; i < 256; i++)
6276 blk->skip[i] = skip;
6277
6278 p = blk->pattern + (blk->len - skip);
6279 while (--skip > 0)
6280 blk->skip[*p++] = skip;
6281
6282 blk->last_char_skip = blk->skip[blk->last_char];
6283 }
6284
6285 return pat;
6286
6287 error:
6288 xlfdpat_destroy (pat);
6289 return NULL;
6290}
6291
6292static INLINE int
6293xlfdpat_exact_p (pat)
6294 struct xlfdpat *pat;
6295{
6296 return (pat)->blocks == NULL;
6297}
6298
6299/* Return the first string in STRING + 0, ..., STRING + START_MAX such
6300 that the pattern in *BLK matches with its prefix. Return NULL
6301 there is no such strings. STRING must be lowered in advance. */
6302
6303static char *
6304xlfdpat_block_match_1 (blk, string, start_max)
6305 struct xlfdpat_block *blk;
6306 unsigned char *string;
6307 int start_max;
6308{
6309 int start, infinity;
6310 unsigned char *p, *s;
6311
6312 xassert (blk->len > 0);
6313 xassert (start_max + blk->len <= strlen (string));
6314 xassert (blk->pattern[blk->len - 1] != '?');
6315
6316 /* See the comments in the function `boyer_moore' (search.c) for the
6317 use of `infinity'. */
6318 infinity = start_max + blk->len + 1;
6319 blk->skip[blk->last_char] = infinity;
6320
6321 start = 0;
6322 do
6323 {
6324 /* Check the last character of the pattern. */
6325 s = string + blk->len - 1;
6326 do
6327 {
6328 start += blk->skip[*(s + start)];
6329 }
6330 while (start <= start_max);
6331
6332 if (start < infinity)
6333 /* Couldn't find the last character. */
6334 return NULL;
6335
6336 /* No less than `infinity' means we could find the last
6337 character at `s[start - infinity]'. */
6338 start -= infinity;
6339
6340 /* Check the remaining characters. We prefer making no-'?'
6341 cases faster because the use of '?' is really rare. */
6342 p = blk->pattern;
6343 s = string + start;
6344 do
6345 {
6346 while (*p++ == *s++)
6347 ;
6348 }
6349 while (*(p - 1) == '?');
6350
6351 if (*(p - 1) == '\0')
6352 /* Matched. */
6353 return string + start;
6354
6355 /* Didn't match. */
6356 start += blk->last_char_skip;
6357 }
6358 while (start <= start_max);
6359
6360 return NULL;
6361}
6362
6363#define xlfdpat_block_match(b, s, m) \
6364 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6365 : xlfdpat_block_match_1 (b, s, m))
6366
6367/* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
6368 matches with STRING. STRING must be lowered in advance. */
6369
6370static int
6371xlfdpat_match (pat, string)
6372 struct xlfdpat *pat;
6373 unsigned char *string;
6374{
6375 int str_len, nblocks, i, start_max;
6376 struct xlfdpat_block *blk;
6377 unsigned char *s;
6378
6379 xassert (pat->nblocks > 0);
6380
6381 if (xlfdpat_exact_p (pat))
6382 return strcmp (pat->buf, string) == 0;
6383
6384 /* The number of the characters in the string must not be smaller
6385 than that in the pattern. */
6386 str_len = strlen (string);
6387 if (str_len < pat->nchars + pat->trailing_anychars)
6388 return 0;
6389
6390 /* Chop off the trailing '?'s. */
6391 str_len -= pat->trailing_anychars;
6392
6393 /* The last block. When it is non-empty, it must match at the end
6394 of the string. */
6395 nblocks = pat->nblocks;
6396 blk = pat->blocks + (nblocks - 1);
6397 if (nblocks == 1)
6398 /* The last block is also the first one. */
6399 return (str_len == blk->len
6400 && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
6401 else if (blk->len != 0)
6402 if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
6403 return 0;
6404
6405 /* The first block. When it is non-empty, it must match at the
6406 beginning of the string. */
6407 blk = pat->blocks;
6408 if (blk->len != 0)
6409 {
6410 s = xlfdpat_block_match (blk, string, 0);
6411 if (s == NULL)
6412 return 0;
6413 string = s + blk->len;
6414 }
6415
6416 /* The rest of the blocks. */
6417 start_max = str_len - pat->nchars;
6418 for (i = 1, blk++; i < nblocks - 1; i++, blk++)
6419 {
6420 s = xlfdpat_block_match (blk, string, start_max);
6421 if (s == NULL)
6422 return 0;
6423 start_max -= s - string;
6424 string = s + blk->len;
6425 }
6426
6427 return 1;
6428}
6429
6430
6431/***********************************************************************
6103 Fonts 6432 Fonts
6104 ***********************************************************************/ 6433 ***********************************************************************/
6105 6434
@@ -6198,7 +6527,8 @@ mac_to_x_fontname (name, size, style, charset)
6198{ 6527{
6199 Str31 foundry, cs; 6528 Str31 foundry, cs;
6200 Str255 family; 6529 Str255 family;
6201 char xf[256], *result, *p; 6530 char xf[256], *result;
6531 unsigned char *p;
6202 6532
6203 if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3) 6533 if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
6204 charset = cs; 6534 charset = cs;
@@ -6215,7 +6545,10 @@ mac_to_x_fontname (name, size, style, charset)
6215 result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1); 6545 result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
6216 sprintf (result, "-%s-%s-%s", foundry, family, xf); 6546 sprintf (result, "-%s-%s-%s", foundry, family, xf);
6217 for (p = result; *p; p++) 6547 for (p = result; *p; p++)
6218 *p = tolower(*p); 6548 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6549 for some locales. */
6550 if (isascii (*p))
6551 *p = tolower (*p);
6219 return result; 6552 return result;
6220} 6553}
6221 6554
@@ -6275,7 +6608,7 @@ x_font_name_to_mac_font_name (xf, mf, mf_decoded, style, cs)
6275 { 6608 {
6276 setup_coding_system (coding_system, &coding); 6609 setup_coding_system (coding_system, &coding);
6277 coding.src_multibyte = 1; 6610 coding.src_multibyte = 1;
6278 coding.dst_multibyte = 1; 6611 coding.dst_multibyte = 0;
6279 coding.mode |= CODING_MODE_LAST_BLOCK; 6612 coding.mode |= CODING_MODE_LAST_BLOCK;
6280 encode_coding (&coding, mf_decoded, mf, 6613 encode_coding (&coding, mf_decoded, mf,
6281 strlen (mf_decoded), sizeof (Str255) - 1); 6614 strlen (mf_decoded), sizeof (Str255) - 1);
@@ -6290,13 +6623,13 @@ add_font_name_table_entry (char *font_name)
6290{ 6623{
6291 if (font_name_table_size == 0) 6624 if (font_name_table_size == 0)
6292 { 6625 {
6293 font_name_table_size = 16; 6626 font_name_table_size = 256;
6294 font_name_table = (char **) 6627 font_name_table = (char **)
6295 xmalloc (font_name_table_size * sizeof (char *)); 6628 xmalloc (font_name_table_size * sizeof (char *));
6296 } 6629 }
6297 else if (font_name_count + 1 >= font_name_table_size) 6630 else if (font_name_count + 1 >= font_name_table_size)
6298 { 6631 {
6299 font_name_table_size += 16; 6632 font_name_table_size *= 2;
6300 font_name_table = (char **) 6633 font_name_table = (char **)
6301 xrealloc (font_name_table, 6634 xrealloc (font_name_table,
6302 font_name_table_size * sizeof (char *)); 6635 font_name_table_size * sizeof (char *));
@@ -6521,39 +6854,16 @@ static int xlfd_scalable_fields[] =
6521 }; 6854 };
6522 6855
6523static Lisp_Object 6856static Lisp_Object
6524mac_c_string_match (regexp, string, nonspecial, exact)
6525 Lisp_Object regexp;
6526 const char *string, *nonspecial;
6527 int exact;
6528{
6529 if (exact)
6530 {
6531 if (strcmp (string, nonspecial) == 0)
6532 return build_string (string);
6533 }
6534 else if (strstr (string, nonspecial))
6535 {
6536 Lisp_Object str = build_string (string);
6537
6538 if (fast_string_match (regexp, str) >= 0)
6539 return str;
6540 }
6541
6542 return Qnil;
6543}
6544
6545static Lisp_Object
6546mac_do_list_fonts (pattern, maxnames) 6857mac_do_list_fonts (pattern, maxnames)
6547 char *pattern; 6858 char *pattern;
6548 int maxnames; 6859 int maxnames;
6549{ 6860{
6550 int i, n_fonts = 0; 6861 int i, n_fonts = 0;
6551 Lisp_Object font_list = Qnil, pattern_regex, fontname; 6862 Lisp_Object font_list = Qnil;
6552 char *regex = (char *) alloca (strlen (pattern) * 2 + 3); 6863 struct xlfdpat *pat;
6553 char *scaled, *ptr; 6864 char *scaled, *ptr;
6554 int scl_val[XLFD_SCL_LAST], *field, *val; 6865 int scl_val[XLFD_SCL_LAST], *field, *val;
6555 char *longest_start, *cur_start, *nonspecial; 6866 int exact;
6556 int longest_len, exact;
6557 6867
6558 if (font_name_table == NULL) /* Initialize when first used. */ 6868 if (font_name_table == NULL) /* Initialize when first used. */
6559 init_font_name_table (); 6869 init_font_name_table ();
@@ -6611,61 +6921,17 @@ mac_do_list_fonts (pattern, maxnames)
6611 else 6921 else
6612 scl_val[XLFD_SCL_PIXEL_SIZE] = -1; 6922 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
6613 6923
6614 ptr = regex; 6924 pat = xlfdpat_create (pattern);
6615 *ptr++ = '^'; 6925 if (pat == NULL)
6616 6926 return Qnil;
6617 longest_start = cur_start = ptr;
6618 longest_len = 0;
6619 exact = 1;
6620
6621 /* Turn pattern into a regexp and do a regexp match. Also find the
6622 longest substring containing no special characters. */
6623 for (; *pattern; pattern++)
6624 {
6625 if (*pattern == '?' || *pattern == '*')
6626 {
6627 if (ptr - cur_start > longest_len)
6628 {
6629 longest_start = cur_start;
6630 longest_len = ptr - cur_start;
6631 }
6632 exact = 0;
6633
6634 if (*pattern == '?')
6635 *ptr++ = '.';
6636 else /* if (*pattern == '*') */
6637 {
6638 *ptr++ = '.';
6639 *ptr++ = '*';
6640 }
6641 cur_start = ptr;
6642 }
6643 else
6644 *ptr++ = tolower (*pattern);
6645 }
6646
6647 if (ptr - cur_start > longest_len)
6648 {
6649 longest_start = cur_start;
6650 longest_len = ptr - cur_start;
6651 }
6652
6653 *ptr = '$';
6654 *(ptr + 1) = '\0';
6655
6656 nonspecial = xmalloc (longest_len + 1);
6657 strncpy (nonspecial, longest_start, longest_len);
6658 nonspecial[longest_len] = '\0';
6659 6927
6660 pattern_regex = build_string (regex); 6928 exact = xlfdpat_exact_p (pat);
6661 6929
6662 for (i = 0; i < font_name_count; i++) 6930 for (i = 0; i < font_name_count; i++)
6663 { 6931 {
6664 fontname = mac_c_string_match (pattern_regex, font_name_table[i], 6932 if (xlfdpat_match (pat, font_name_table[i]))
6665 nonspecial, exact);
6666 if (!NILP (fontname))
6667 { 6933 {
6668 font_list = Fcons (fontname, font_list); 6934 font_list = Fcons (build_string (font_name_table[i]), font_list);
6669 if (exact || maxnames > 0 && ++n_fonts >= maxnames) 6935 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
6670 break; 6936 break;
6671 } 6937 }
@@ -6675,6 +6941,8 @@ mac_do_list_fonts (pattern, maxnames)
6675 int former_len = ptr - font_name_table[i]; 6941 int former_len = ptr - font_name_table[i];
6676 6942
6677 scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1); 6943 scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
6944 if (scaled == NULL)
6945 continue;
6678 memcpy (scaled, font_name_table[i], former_len); 6946 memcpy (scaled, font_name_table[i], former_len);
6679 sprintf (scaled + former_len, 6947 sprintf (scaled + former_len,
6680 "-%d-%d-75-75-m-%d-%s", 6948 "-%d-%d-75-75-m-%d-%s",
@@ -6682,19 +6950,20 @@ mac_do_list_fonts (pattern, maxnames)
6682 scl_val[XLFD_SCL_POINT_SIZE], 6950 scl_val[XLFD_SCL_POINT_SIZE],
6683 scl_val[XLFD_SCL_AVGWIDTH], 6951 scl_val[XLFD_SCL_AVGWIDTH],
6684 ptr + sizeof ("-0-0-0-0-m-0-") - 1); 6952 ptr + sizeof ("-0-0-0-0-m-0-") - 1);
6685 fontname = mac_c_string_match (pattern_regex, scaled, 6953
6686 nonspecial, exact); 6954 if (xlfdpat_match (pat, scaled))
6687 xfree (scaled);
6688 if (!NILP (fontname))
6689 { 6955 {
6690 font_list = Fcons (fontname, font_list); 6956 font_list = Fcons (build_string (scaled), font_list);
6957 xfree (scaled);
6691 if (exact || maxnames > 0 && ++n_fonts >= maxnames) 6958 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
6692 break; 6959 break;
6693 } 6960 }
6961 else
6962 xfree (scaled);
6694 } 6963 }
6695 } 6964 }
6696 6965
6697 xfree (nonspecial); 6966 xlfdpat_destroy (pat);
6698 6967
6699 return font_list; 6968 return font_list;
6700} 6969}