6084 |
|
|
6085 |
|
|
6086 |
/*********************************************************************** |
/*********************************************************************** |
6087 |
|
XLFD Pattern Match |
6088 |
|
***********************************************************************/ |
6089 |
|
|
6090 |
|
/* An XLFD pattern is divided into blocks delimited by '*'. This |
6091 |
|
structure holds information for each block. */ |
6092 |
|
struct xlfdpat_block |
6093 |
|
{ |
6094 |
|
/* Length of the pattern string in this block. Non-zero except for |
6095 |
|
the first and the last blocks. */ |
6096 |
|
int len; |
6097 |
|
|
6098 |
|
/* Pattern string except the last character in this block. The last |
6099 |
|
character is replaced with NUL in order to use it as a |
6100 |
|
sentinel. */ |
6101 |
|
unsigned char *pattern; |
6102 |
|
|
6103 |
|
/* Last character of the pattern string. Must not be '?'. */ |
6104 |
|
unsigned char last_char; |
6105 |
|
|
6106 |
|
/* One of the tables for the Boyer-Moore string search. It |
6107 |
|
specifies the number of positions to proceed for each character |
6108 |
|
with which the match fails. */ |
6109 |
|
int skip[256]; |
6110 |
|
|
6111 |
|
/* The skip value for the last character in the above `skip' is |
6112 |
|
assigned to `infinity' in order to simplify a loop condition. |
6113 |
|
The original value is saved here. */ |
6114 |
|
int last_char_skip; |
6115 |
|
}; |
6116 |
|
|
6117 |
|
struct xlfdpat |
6118 |
|
{ |
6119 |
|
/* Normalized pattern string. "Normalized" means that capital |
6120 |
|
letters are lowered, blocks are not empty except the first and |
6121 |
|
the last ones, and trailing '?'s in a block that is not the last |
6122 |
|
one are moved to the next one. The last character in each block |
6123 |
|
is replaced with NUL. */ |
6124 |
|
unsigned char *buf; |
6125 |
|
|
6126 |
|
/* Number of characters except '*'s and trailing '?'s in the |
6127 |
|
normalized pattern string. */ |
6128 |
|
int nchars; |
6129 |
|
|
6130 |
|
/* Number of trailing '?'s in the normalized pattern string. */ |
6131 |
|
int trailing_anychars; |
6132 |
|
|
6133 |
|
/* Number of blocks and information for each block. The latter is |
6134 |
|
NULL if the pattern is exact (no '*' or '?' in it). */ |
6135 |
|
int nblocks; |
6136 |
|
struct xlfdpat_block *blocks; |
6137 |
|
}; |
6138 |
|
|
6139 |
|
static void |
6140 |
|
xlfdpat_destroy (pat) |
6141 |
|
struct xlfdpat *pat; |
6142 |
|
{ |
6143 |
|
if (pat) |
6144 |
|
{ |
6145 |
|
if (pat->buf) |
6146 |
|
{ |
6147 |
|
if (pat->blocks) |
6148 |
|
xfree (pat->blocks); |
6149 |
|
xfree (pat->buf); |
6150 |
|
} |
6151 |
|
xfree (pat); |
6152 |
|
} |
6153 |
|
} |
6154 |
|
|
6155 |
|
static struct xlfdpat * |
6156 |
|
xlfdpat_create (pattern) |
6157 |
|
char *pattern; |
6158 |
|
{ |
6159 |
|
struct xlfdpat *pat; |
6160 |
|
int nblocks, i, skip; |
6161 |
|
unsigned char last_char, *p, *q, *anychar_head; |
6162 |
|
struct xlfdpat_block *blk; |
6163 |
|
|
6164 |
|
pat = xmalloc (sizeof (struct xlfdpat)); |
6165 |
|
if (pat == NULL) |
6166 |
|
goto error; |
6167 |
|
|
6168 |
|
pat->buf = xmalloc (strlen (pattern) + 1); |
6169 |
|
if (pat->buf == NULL) |
6170 |
|
goto error; |
6171 |
|
|
6172 |
|
/* Normalize the pattern string and store it to `pat->buf'. */ |
6173 |
|
nblocks = 0; |
6174 |
|
anychar_head = NULL; |
6175 |
|
q = pat->buf; |
6176 |
|
last_char = '\0'; |
6177 |
|
for (p = pattern; *p; p++) |
6178 |
|
{ |
6179 |
|
unsigned char c = *p; |
6180 |
|
|
6181 |
|
if (c == '*') |
6182 |
|
if (last_char == '*') |
6183 |
|
/* ...a** -> ...a* */ |
6184 |
|
continue; |
6185 |
|
else |
6186 |
|
{ |
6187 |
|
if (last_char == '?') |
6188 |
|
if (anychar_head > pat->buf && *(anychar_head - 1) == '*') |
6189 |
|
/* ...*??* -> ...*?? */ |
6190 |
|
continue; |
6191 |
|
else |
6192 |
|
/* ...a??* -> ...a*?? */ |
6193 |
|
{ |
6194 |
|
*anychar_head++ = '*'; |
6195 |
|
c = '?'; |
6196 |
|
} |
6197 |
|
nblocks++; |
6198 |
|
} |
6199 |
|
else if (c == '?') |
6200 |
|
{ |
6201 |
|
if (last_char != '?') |
6202 |
|
anychar_head = q; |
6203 |
|
} |
6204 |
|
else |
6205 |
|
/* On Mac OS X 10.3, tolower also converts non-ASCII |
6206 |
|
characters for some locales. */ |
6207 |
|
if (isascii (c)) |
6208 |
|
c = tolower (c); |
6209 |
|
|
6210 |
|
*q++ = last_char = c; |
6211 |
|
} |
6212 |
|
*q = '\0'; |
6213 |
|
nblocks++; |
6214 |
|
pat->nblocks = nblocks; |
6215 |
|
if (last_char != '?') |
6216 |
|
pat->trailing_anychars = 0; |
6217 |
|
else |
6218 |
|
{ |
6219 |
|
pat->trailing_anychars = q - anychar_head; |
6220 |
|
q = anychar_head; |
6221 |
|
} |
6222 |
|
pat->nchars = q - pat->buf - (nblocks - 1); |
6223 |
|
|
6224 |
|
if (anychar_head == NULL && nblocks == 1) |
6225 |
|
{ |
6226 |
|
/* The pattern is exact. */ |
6227 |
|
pat->blocks = NULL; |
6228 |
|
return pat; |
6229 |
|
} |
6230 |
|
|
6231 |
|
pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks); |
6232 |
|
if (pat->blocks == NULL) |
6233 |
|
goto error; |
6234 |
|
|
6235 |
|
/* Divide the normalized pattern into blocks. */ |
6236 |
|
p = pat->buf; |
6237 |
|
for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++) |
6238 |
|
{ |
6239 |
|
blk->pattern = p; |
6240 |
|
while (*p != '*') |
6241 |
|
p++; |
6242 |
|
blk->len = p - blk->pattern; |
6243 |
|
p++; |
6244 |
|
} |
6245 |
|
blk->pattern = p; |
6246 |
|
blk->len = q - blk->pattern; |
6247 |
|
|
6248 |
|
/* Setup a table for the Boyer-Moore string search. */ |
6249 |
|
for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++) |
6250 |
|
if (blk->len != 0) |
6251 |
|
{ |
6252 |
|
blk->last_char = blk->pattern[blk->len - 1]; |
6253 |
|
blk->pattern[blk->len - 1] = '\0'; |
6254 |
|
|
6255 |
|
for (skip = 1; skip < blk->len; skip++) |
6256 |
|
if (blk->pattern[blk->len - skip - 1] == '?') |
6257 |
|
break; |
6258 |
|
|
6259 |
|
for (i = 0; i < 256; i++) |
6260 |
|
blk->skip[i] = skip; |
6261 |
|
|
6262 |
|
p = blk->pattern + (blk->len - skip); |
6263 |
|
while (--skip > 0) |
6264 |
|
blk->skip[*p++] = skip; |
6265 |
|
|
6266 |
|
blk->last_char_skip = blk->skip[blk->last_char]; |
6267 |
|
} |
6268 |
|
|
6269 |
|
return pat; |
6270 |
|
|
6271 |
|
error: |
6272 |
|
xlfdpat_destroy (pat); |
6273 |
|
return NULL; |
6274 |
|
} |
6275 |
|
|
6276 |
|
static INLINE int |
6277 |
|
xlfdpat_exact_p (pat) |
6278 |
|
struct xlfdpat *pat; |
6279 |
|
{ |
6280 |
|
return (pat)->blocks == NULL; |
6281 |
|
} |
6282 |
|
|
6283 |
|
/* Return the first string in STRING + 0, ..., STRING + START_MAX such |
6284 |
|
that the pattern in *BLK matches with its prefix. Return NULL |
6285 |
|
there is no such strings. STRING must be lowered in advance. */ |
6286 |
|
|
6287 |
|
static char * |
6288 |
|
xlfdpat_block_match_1 (blk, string, start_max) |
6289 |
|
struct xlfdpat_block *blk; |
6290 |
|
unsigned char *string; |
6291 |
|
int start_max; |
6292 |
|
{ |
6293 |
|
int start, infinity; |
6294 |
|
unsigned char *p, *s; |
6295 |
|
|
6296 |
|
xassert (blk->len > 0); |
6297 |
|
xassert (start_max + blk->len <= strlen (string)); |
6298 |
|
xassert (blk->pattern[blk->len - 1] != '?'); |
6299 |
|
|
6300 |
|
/* See the comments in the function `boyer_moore' (search.c) for the |
6301 |
|
use of `infinity'. */ |
6302 |
|
infinity = start_max + blk->len + 1; |
6303 |
|
blk->skip[blk->last_char] = infinity; |
6304 |
|
|
6305 |
|
start = 0; |
6306 |
|
do |
6307 |
|
{ |
6308 |
|
/* Check the last character of the pattern. */ |
6309 |
|
s = string + blk->len - 1; |
6310 |
|
do |
6311 |
|
{ |
6312 |
|
start += blk->skip[*(s + start)]; |
6313 |
|
} |
6314 |
|
while (start <= start_max); |
6315 |
|
|
6316 |
|
if (start < infinity) |
6317 |
|
/* Couldn't find the last character. */ |
6318 |
|
return NULL; |
6319 |
|
|
6320 |
|
/* No less than `infinity' means we could find the last |
6321 |
|
character at `s[start - infinity]'. */ |
6322 |
|
start -= infinity; |
6323 |
|
|
6324 |
|
/* Check the remaining characters. We prefer making no-'?' |
6325 |
|
cases faster because the use of '?' is really rare. */ |
6326 |
|
p = blk->pattern; |
6327 |
|
s = string + start; |
6328 |
|
do |
6329 |
|
{ |
6330 |
|
while (*p++ == *s++) |
6331 |
|
; |
6332 |
|
} |
6333 |
|
while (*(p - 1) == '?'); |
6334 |
|
|
6335 |
|
if (*(p - 1) == '\0') |
6336 |
|
/* Matched. */ |
6337 |
|
return string + start; |
6338 |
|
|
6339 |
|
/* Didn't match. */ |
6340 |
|
start += blk->last_char_skip; |
6341 |
|
} |
6342 |
|
while (start <= start_max); |
6343 |
|
|
6344 |
|
return NULL; |
6345 |
|
} |
6346 |
|
|
6347 |
|
#define xlfdpat_block_match(b, s, m) \ |
6348 |
|
((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \ |
6349 |
|
: xlfdpat_block_match_1 (b, s, m)) |
6350 |
|
|
6351 |
|
/* Check if XLFD pattern PAT, which is generated by `xfldpat_create', |
6352 |
|
matches with STRING. STRING must be lowered in advance. */ |
6353 |
|
|
6354 |
|
static int |
6355 |
|
xlfdpat_match (pat, string) |
6356 |
|
struct xlfdpat *pat; |
6357 |
|
unsigned char *string; |
6358 |
|
{ |
6359 |
|
int str_len, nblocks, i, start_max; |
6360 |
|
struct xlfdpat_block *blk; |
6361 |
|
unsigned char *s; |
6362 |
|
|
6363 |
|
xassert (pat->nblocks > 0); |
6364 |
|
|
6365 |
|
if (xlfdpat_exact_p (pat)) |
6366 |
|
return strcmp (pat->buf, string) == 0; |
6367 |
|
|
6368 |
|
/* The number of the characters in the string must not be smaller |
6369 |
|
than that in the pattern. */ |
6370 |
|
str_len = strlen (string); |
6371 |
|
if (str_len < pat->nchars + pat->trailing_anychars) |
6372 |
|
return 0; |
6373 |
|
|
6374 |
|
/* Chop off the trailing '?'s. */ |
6375 |
|
str_len -= pat->trailing_anychars; |
6376 |
|
|
6377 |
|
/* The last block. When it is non-empty, it must match at the end |
6378 |
|
of the string. */ |
6379 |
|
nblocks = pat->nblocks; |
6380 |
|
blk = pat->blocks + (nblocks - 1); |
6381 |
|
if (nblocks == 1) |
6382 |
|
/* The last block is also the first one. */ |
6383 |
|
return (str_len == blk->len |
6384 |
|
&& (blk->len == 0 || xlfdpat_block_match (blk, string, 0))); |
6385 |
|
else if (blk->len != 0) |
6386 |
|
if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0)) |
6387 |
|
return 0; |
6388 |
|
|
6389 |
|
/* The first block. When it is non-empty, it must match at the |
6390 |
|
beginning of the string. */ |
6391 |
|
blk = pat->blocks; |
6392 |
|
if (blk->len != 0) |
6393 |
|
{ |
6394 |
|
s = xlfdpat_block_match (blk, string, 0); |
6395 |
|
if (s == NULL) |
6396 |
|
return 0; |
6397 |
|
string = s + blk->len; |
6398 |
|
} |
6399 |
|
|
6400 |
|
/* The rest of the blocks. */ |
6401 |
|
start_max = str_len - pat->nchars; |
6402 |
|
for (i = 1, blk++; i < nblocks - 1; i++, blk++) |
6403 |
|
{ |
6404 |
|
s = xlfdpat_block_match (blk, string, start_max); |
6405 |
|
if (s == NULL) |
6406 |
|
return 0; |
6407 |
|
start_max -= s - string; |
6408 |
|
string = s + blk->len; |
6409 |
|
} |
6410 |
|
|
6411 |
|
return 1; |
6412 |
|
} |
6413 |
|
|
6414 |
|
|
6415 |
|
/*********************************************************************** |
6416 |
Fonts |
Fonts |
6417 |
***********************************************************************/ |
***********************************************************************/ |
6418 |
|
|
6507 |
{ |
{ |
6508 |
Str31 foundry, cs; |
Str31 foundry, cs; |
6509 |
Str255 family; |
Str255 family; |
6510 |
char xf[256], *result, *p; |
char xf[256], *result; |
6511 |
|
unsigned char *p; |
6512 |
|
|
6513 |
if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3) |
if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3) |
6514 |
charset = cs; |
charset = cs; |
6525 |
result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1); |
result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1); |
6526 |
sprintf (result, "-%s-%s-%s", foundry, family, xf); |
sprintf (result, "-%s-%s-%s", foundry, family, xf); |
6527 |
for (p = result; *p; p++) |
for (p = result; *p; p++) |
6528 |
*p = tolower(*p); |
/* On Mac OS X 10.3, tolower also converts non-ASCII characters |
6529 |
|
for some locales. */ |
6530 |
|
if (isascii (*p)) |
6531 |
|
*p = tolower (*p); |
6532 |
return result; |
return result; |
6533 |
} |
} |
6534 |
|
|
6586 |
{ |
{ |
6587 |
setup_coding_system (coding_system, &coding); |
setup_coding_system (coding_system, &coding); |
6588 |
coding.src_multibyte = 1; |
coding.src_multibyte = 1; |
6589 |
coding.dst_multibyte = 1; |
coding.dst_multibyte = 0; |
6590 |
coding.mode |= CODING_MODE_LAST_BLOCK; |
coding.mode |= CODING_MODE_LAST_BLOCK; |
6591 |
encode_coding (&coding, mf_decoded, mf, |
encode_coding (&coding, mf_decoded, mf, |
6592 |
strlen (mf_decoded), sizeof (Str255) - 1); |
strlen (mf_decoded), sizeof (Str255) - 1); |
6600 |
{ |
{ |
6601 |
if (font_name_table_size == 0) |
if (font_name_table_size == 0) |
6602 |
{ |
{ |
6603 |
font_name_table_size = 16; |
font_name_table_size = 256; |
6604 |
font_name_table = (char **) |
font_name_table = (char **) |
6605 |
xmalloc (font_name_table_size * sizeof (char *)); |
xmalloc (font_name_table_size * sizeof (char *)); |
6606 |
} |
} |
6607 |
else if (font_name_count + 1 >= font_name_table_size) |
else if (font_name_count + 1 >= font_name_table_size) |
6608 |
{ |
{ |
6609 |
font_name_table_size += 16; |
font_name_table_size *= 2; |
6610 |
font_name_table = (char **) |
font_name_table = (char **) |
6611 |
xrealloc (font_name_table, |
xrealloc (font_name_table, |
6612 |
font_name_table_size * sizeof (char *)); |
font_name_table_size * sizeof (char *)); |
6831 |
}; |
}; |
6832 |
|
|
6833 |
static Lisp_Object |
static Lisp_Object |
|
mac_c_string_match (regexp, string, nonspecial, exact) |
|
|
Lisp_Object regexp; |
|
|
const char *string, *nonspecial; |
|
|
int exact; |
|
|
{ |
|
|
if (exact) |
|
|
{ |
|
|
if (strcmp (string, nonspecial) == 0) |
|
|
return build_string (string); |
|
|
} |
|
|
else if (strstr (string, nonspecial)) |
|
|
{ |
|
|
Lisp_Object str = build_string (string); |
|
|
|
|
|
if (fast_string_match (regexp, str) >= 0) |
|
|
return str; |
|
|
} |
|
|
|
|
|
return Qnil; |
|
|
} |
|
|
|
|
|
static Lisp_Object |
|
6834 |
mac_do_list_fonts (pattern, maxnames) |
mac_do_list_fonts (pattern, maxnames) |
6835 |
char *pattern; |
char *pattern; |
6836 |
int maxnames; |
int maxnames; |
6837 |
{ |
{ |
6838 |
int i, n_fonts = 0; |
int i, n_fonts = 0; |
6839 |
Lisp_Object font_list = Qnil, pattern_regex, fontname; |
Lisp_Object font_list = Qnil; |
6840 |
char *regex = (char *) alloca (strlen (pattern) * 2 + 3); |
struct xlfdpat *pat; |
6841 |
char *scaled, *ptr; |
char *scaled, *ptr; |
6842 |
int scl_val[XLFD_SCL_LAST], *field, *val; |
int scl_val[XLFD_SCL_LAST], *field, *val; |
6843 |
char *longest_start, *cur_start, *nonspecial; |
int exact; |
|
int longest_len, exact; |
|
6844 |
|
|
6845 |
if (font_name_table == NULL) /* Initialize when first used. */ |
if (font_name_table == NULL) /* Initialize when first used. */ |
6846 |
init_font_name_table (); |
init_font_name_table (); |
6898 |
else |
else |
6899 |
scl_val[XLFD_SCL_PIXEL_SIZE] = -1; |
scl_val[XLFD_SCL_PIXEL_SIZE] = -1; |
6900 |
|
|
6901 |
ptr = regex; |
pat = xlfdpat_create (pattern); |
6902 |
*ptr++ = '^'; |
if (pat == NULL) |
6903 |
|
return Qnil; |
6904 |
|
|
6905 |
longest_start = cur_start = ptr; |
exact = xlfdpat_exact_p (pat); |
|
longest_len = 0; |
|
|
exact = 1; |
|
|
|
|
|
/* Turn pattern into a regexp and do a regexp match. Also find the |
|
|
longest substring containing no special characters. */ |
|
|
for (; *pattern; pattern++) |
|
|
{ |
|
|
if (*pattern == '?' || *pattern == '*') |
|
|
{ |
|
|
if (ptr - cur_start > longest_len) |
|
|
{ |
|
|
longest_start = cur_start; |
|
|
longest_len = ptr - cur_start; |
|
|
} |
|
|
exact = 0; |
|
|
|
|
|
if (*pattern == '?') |
|
|
*ptr++ = '.'; |
|
|
else /* if (*pattern == '*') */ |
|
|
{ |
|
|
*ptr++ = '.'; |
|
|
*ptr++ = '*'; |
|
|
} |
|
|
cur_start = ptr; |
|
|
} |
|
|
else |
|
|
*ptr++ = tolower (*pattern); |
|
|
} |
|
|
|
|
|
if (ptr - cur_start > longest_len) |
|
|
{ |
|
|
longest_start = cur_start; |
|
|
longest_len = ptr - cur_start; |
|
|
} |
|
|
|
|
|
*ptr = '$'; |
|
|
*(ptr + 1) = '\0'; |
|
|
|
|
|
nonspecial = xmalloc (longest_len + 1); |
|
|
strncpy (nonspecial, longest_start, longest_len); |
|
|
nonspecial[longest_len] = '\0'; |
|
|
|
|
|
pattern_regex = build_string (regex); |
|
6906 |
|
|
6907 |
for (i = 0; i < font_name_count; i++) |
for (i = 0; i < font_name_count; i++) |
6908 |
{ |
{ |
6909 |
fontname = mac_c_string_match (pattern_regex, font_name_table[i], |
if (xlfdpat_match (pat, font_name_table[i])) |
|
nonspecial, exact); |
|
|
if (!NILP (fontname)) |
|
6910 |
{ |
{ |
6911 |
font_list = Fcons (fontname, font_list); |
font_list = Fcons (build_string (font_name_table[i]), font_list); |
6912 |
if (exact || maxnames > 0 && ++n_fonts >= maxnames) |
if (exact || maxnames > 0 && ++n_fonts >= maxnames) |
6913 |
break; |
break; |
6914 |
} |
} |
6918 |
int former_len = ptr - font_name_table[i]; |
int former_len = ptr - font_name_table[i]; |
6919 |
|
|
6920 |
scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1); |
scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1); |
6921 |
|
if (scaled == NULL) |
6922 |
|
continue; |
6923 |
memcpy (scaled, font_name_table[i], former_len); |
memcpy (scaled, font_name_table[i], former_len); |
6924 |
sprintf (scaled + former_len, |
sprintf (scaled + former_len, |
6925 |
"-%d-%d-75-75-m-%d-%s", |
"-%d-%d-75-75-m-%d-%s", |
6927 |
scl_val[XLFD_SCL_POINT_SIZE], |
scl_val[XLFD_SCL_POINT_SIZE], |
6928 |
scl_val[XLFD_SCL_AVGWIDTH], |
scl_val[XLFD_SCL_AVGWIDTH], |
6929 |
ptr + sizeof ("-0-0-0-0-m-0-") - 1); |
ptr + sizeof ("-0-0-0-0-m-0-") - 1); |
6930 |
fontname = mac_c_string_match (pattern_regex, scaled, |
|
6931 |
nonspecial, exact); |
if (xlfdpat_match (pat, scaled)) |
|
xfree (scaled); |
|
|
if (!NILP (fontname)) |
|
6932 |
{ |
{ |
6933 |
font_list = Fcons (fontname, font_list); |
font_list = Fcons (build_string (scaled), font_list); |
6934 |
|
xfree (scaled); |
6935 |
if (exact || maxnames > 0 && ++n_fonts >= maxnames) |
if (exact || maxnames > 0 && ++n_fonts >= maxnames) |
6936 |
break; |
break; |
6937 |
} |
} |
6938 |
|
else |
6939 |
|
xfree (scaled); |
6940 |
} |
} |
6941 |
} |
} |
6942 |
|
|
6943 |
xfree (nonspecial); |
xlfdpat_destroy (pat); |
6944 |
|
|
6945 |
return font_list; |
return font_list; |
6946 |
} |
} |