(list_fontsets, fs_load_font): fast_c_string_match_ignore_case renamed.
[bpt/emacs.git] / src / fontset.c
1 /* Fontset handler.
2 Ver.1.0
3 Copyright (C) 1995 Free Software Foundation, Inc.
4 Copyright (C) 1995 Electrotechnical Laboratory, JAPAN.
5
6 This file is part of GNU Emacs.
7
8 GNU Emacs is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
22
23 #include <config.h>
24 #if HAVE_ALLOCA_H
25 #include <alloca.h>
26 #endif /* HAVE_ALLOCA_H */
27 #include "lisp.h"
28 #include "charset.h"
29 #include "ccl.h"
30 #include "fontset.h"
31 #include "frame.h"
32
33 Lisp_Object Vglobal_fontset_alist;
34 Lisp_Object Vfont_encoding_alist;
35 Lisp_Object Vuse_default_ascent;
36 Lisp_Object Valternative_fontname_alist;
37 Lisp_Object Vfontset_alias_alist;
38 Lisp_Object Vhighlight_wrong_size_font;
39 Lisp_Object Vclip_large_size_font;
40
41 /* We had better have our own strcasecmp function because some system
42 doesn't have it. */
43 static char my_strcasetbl[256];
44
45 /* Compare two strings S0 and S1 while ignoring differences in case.
46 Return 1 if they differ, else return 0. */
47 static int
48 my_strcasecmp (s0, s1)
49 unsigned char *s0, *s1;
50 {
51 while (*s0)
52 if (my_strcasetbl[*s0++] != my_strcasetbl[*s1++]) return 1;
53 return (int) *s1;
54 }
55
56 /* The following six are window system dependent functions. See
57 the comments in src/fontset.h for more detail. */
58
59 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
60 struct font_info *(*get_font_info_func) (/* FRAME_PTR f; int font_idx */);
61
62 /* Return a list of font names which matches PATTERN. See the document of
63 `x-list-fonts' for more detail. */
64 Lisp_Object (*list_fonts_func) (/* Lisp_Object pattern, face, frame, width */);
65
66 /* Load a font named NAME for frame F and return a pointer to the
67 information of the loaded font. If loading is failed, return 0. */
68 struct font_info *(*load_font_func) (/* FRAME_PTR f; char *name */);
69
70 /* Return a pointer to struct font_info of a font named NAME for frame F. */
71 struct font_info *(*query_font_func) (/* FRAME_PTR f; char *name */);
72
73 /* Additional function for setting fontset or changing fontset
74 contents of frame F. */
75 void (*set_frame_fontset_func) (/* FRAME_PTR f; Lisp_Object arg, oldval */);
76
77 /* Check if any window system is used now. */
78 void (*check_window_system_func) ();
79
80 struct fontset_data *
81 alloc_fontset_data ()
82 {
83 struct fontset_data *fontset_data
84 = (struct fontset_data *) xmalloc (sizeof (struct fontset_data));
85
86 bzero (fontset_data, sizeof (struct fontset_data));
87
88 return fontset_data;
89 }
90
91 void
92 free_fontset_data (fontset_data)
93 struct fontset_data *fontset_data;
94 {
95 int i;
96
97 for (i = 0; i < fontset_data->n_fontsets; i++)
98 {
99 int j;
100
101 xfree (fontset_data->fontset_table[i]->name);
102 for (j = 0; j <= MAX_CHARSET; j++)
103 if (fontset_data->fontset_table[i]->fontname[j])
104 xfree (fontset_data->fontset_table[i]->fontname[j]);
105 xfree (fontset_data->fontset_table[i]);
106 }
107 xfree (fontset_data->fontset_table);
108
109 xfree (fontset_data);
110 }
111
112 /* Load a font named FONTNAME for displaying CHARSET on frame F.
113 All fonts for frame F is stored in a table pointed by FONT_TABLE.
114 Return a pointer to the struct font_info of the loaded font.
115 If loading fails, return 0;
116 If FONTNAME is NULL, the name is taken from the information of FONTSET.
117 If FONTSET is given, try to load a font whose size matches that of
118 FONTSET, and, the font index is stored in the table for FONTSET. */
119
120 struct font_info *
121 fs_load_font (f, font_table, charset, fontname, fontset)
122 FRAME_PTR f;
123 struct font_info *font_table;
124 int charset, fontset;
125 char *fontname;
126 {
127 Lisp_Object font_list;
128 Lisp_Object list, elt;
129 int font_idx;
130 int size = 0;
131 struct fontset_info *fontsetp = 0;
132 struct font_info *fontp;
133
134 if (fontset >= 0 && fontset < FRAME_FONTSET_DATA (f)->n_fontsets)
135 {
136 fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
137 font_idx = fontsetp->font_indexes[charset];
138 if (font_idx >= 0)
139 /* We have already loaded a font. */
140 return font_table + font_idx;
141 else if (font_idx == FONT_NOT_FOUND)
142 /* We have already tried loading a font and failed. */
143 return 0;
144 if (!fontname)
145 fontname = fontsetp->fontname[charset];
146 }
147
148 if (!fontname)
149 /* No way to get fontname. */
150 return 0;
151
152 /* If CHARSET is not ASCII and FONTSET is specified, we must load a
153 font of appropriate size to be used with other fonts in this
154 fontset. */
155 if (charset != CHARSET_ASCII && fontsetp)
156 {
157 /* If we have not yet loaded ASCII font of FONTSET, we must load
158 it now to decided the size and height of this fontset. */
159 if (fontsetp->size == 0)
160 {
161 fontp = fs_load_font (f, font_table, CHARSET_ASCII, 0, fontset);
162 if (!fontp)
163 /* Any fontset should contain avairable ASCII. */
164 return 0;
165 }
166 /* Now we have surely decided the size of this fontset. */
167 size = fontsetp->size * CHARSET_WIDTH (charset);
168 }
169
170 fontp = (*load_font_func) (f, fontname, size);
171
172 if (!fontp)
173 {
174 if (fontsetp)
175 fontsetp->font_indexes[charset] = FONT_NOT_FOUND;
176 return 0;
177 }
178
179 /* Fill in fields (CHARSET, ENCODING, and FONT_ENCODER) which are
180 not set by (*load_font_func). */
181 fontp->charset = charset;
182
183 if (fontp->encoding[1] != FONT_ENCODING_NOT_DECIDED)
184 {
185 /* The font itself tells which code points to be used. Use this
186 encoding for all other charsets. */
187 int i;
188
189 fontp->encoding[0] = fontp->encoding[1];
190 for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i <= MAX_CHARSET; i++)
191 fontp->encoding[i] = fontp->encoding[1];
192 }
193 else
194 {
195 /* The font itself doesn't tell which code points to be used. */
196 int i;
197
198 /* At first, set 1 (means 0xA0..0xFF) as the default. */
199 fontp->encoding[0] = 1;
200 for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i <= MAX_CHARSET; i++)
201 fontp->encoding[i] = 1;
202 /* Then override them by a specification in Vfont_encoding_alist. */
203 for (list = Vfont_encoding_alist; CONSP (list); list = XCONS (list)->cdr)
204 {
205 elt = XCONS (list)->car;
206 if (CONSP (elt)
207 && STRINGP (XCONS (elt)->car) && CONSP (XCONS (elt)->cdr)
208 && (fast_c_string_match_ignore_case (XCONS (elt)->car, fontname)
209 >= 0))
210 {
211 Lisp_Object tmp;
212
213 for (tmp = XCONS (elt)->cdr; CONSP (tmp); tmp = XCONS (tmp)->cdr)
214 if (CONSP (XCONS (tmp)->car)
215 && ((i = get_charset_id (XCONS (XCONS (tmp)->car)->car))
216 >= 0)
217 && INTEGERP (XCONS (XCONS (tmp)->car)->cdr)
218 && XFASTINT (XCONS (XCONS (tmp)->car)->cdr) < 4)
219 fontp->encoding[i]
220 = XFASTINT (XCONS (XCONS (tmp)->car)->cdr);
221 }
222 }
223 }
224
225 fontp->font_encoder = (struct ccl_program *) 0;
226 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCONS (list)->cdr)
227 {
228 elt = XCONS (list)->car;
229 if (CONSP (elt)
230 && STRINGP (XCONS (elt)->car) && VECTORP (XCONS (elt)->cdr)
231 && fast_c_string_match_ignore_case (XCONS (elt)->car, fontname) >= 0)
232 {
233 fontp->font_encoder
234 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
235 setup_ccl_program (fontp->font_encoder, XCONS (elt)->cdr);
236 break;
237 }
238 }
239
240 /* If FONTSET is specified, setup various fields of it. */
241 if (fontsetp)
242 {
243 fontsetp->font_indexes[charset] = fontp->font_idx;
244 if (charset == CHARSET_ASCII)
245 {
246 /* Decide or change the size and height of this fontset. */
247 if (fontsetp->size == 0)
248 {
249 fontsetp->size = fontp->size;
250 fontsetp->height = fontp->height;
251 }
252 else if (fontsetp->size != fontp->size
253 || fontsetp->height != fontp->height)
254 {
255 /* When loading ASCII font of the different size from
256 the size of FONTSET, we have to update the size of
257 FONTSET. Since changing the size of FONTSET may make
258 some fonts already loaded inappropriate to be used in
259 FONTSET, we must delete the record of such fonts. In
260 that case, we also have to calculate the height of
261 FONTSET from the remaining fonts. */
262 int i;
263
264 fontsetp->size = fontp->size;
265 fontsetp->height = fontp->height;
266 for (i = CHARSET_ASCII + 1; i <= MAX_CHARSET; i++)
267 {
268 font_idx = fontsetp->font_indexes[i];
269 if (font_idx >= 0)
270 {
271 struct font_info *fontp2 = font_table + font_idx;
272
273 if (fontp2->size != fontp->size * CHARSET_WIDTH (i))
274 fontsetp->font_indexes[i] = FONT_NOT_OPENED;
275 /* The following code should be disabled until
276 Emacs supports variable height lines. */
277 #if 0
278 else if (fontsetp->height < fontp->height)
279 fontsetp->height = fontp->height;
280 #endif
281 }
282 }
283 }
284 }
285 }
286
287 return fontp;
288 }
289
290 /* Return ID of the fontset named NAME on frame F. */
291
292 int
293 fs_query_fontset (f, name)
294 FRAME_PTR f;
295 char *name;
296 {
297 struct fontset_data *fontset_data = FRAME_FONTSET_DATA (f);
298 int i;
299
300 for (i = 0; i < fontset_data->n_fontsets; i++)
301 if (!my_strcasecmp(name, fontset_data->fontset_table[i]->name))
302 return i;
303 return -1;
304 }
305
306 /* Register a fontset specified by FONTSET_INFO for frame FRAME.
307 Return the fontset ID if successfully registered, else return -1.
308 FONTSET_INFO is a cons of name of the fontset and FONTLIST, where
309 FONTLIST is an alist of charsets vs fontnames. */
310
311 int
312 fs_register_fontset (f, fontset_info)
313 FRAME_PTR f;
314 Lisp_Object fontset_info;
315 {
316 struct fontset_data *fontset_data = FRAME_FONTSET_DATA (f);
317 Lisp_Object name, fontlist;
318 int fontset;
319 struct fontset_info *fontsetp;
320 int i;
321
322 if (!CONSP (fontset_info)
323 || !STRINGP (XCONS (fontset_info)->car)
324 || !CONSP (XCONS (fontset_info)->cdr))
325 /* Invalid data in FONTSET_INFO. */
326 return -1;
327
328 name = XCONS (fontset_info)->car;
329 if ((fontset = fs_query_fontset (f, XSTRING (name)->data)) >= 0)
330 /* This fontset already exists on frame F. */
331 return fontset;
332
333 fontsetp = (struct fontset_info *) xmalloc (sizeof (struct fontset_info));
334
335 fontsetp->name = (char *) xmalloc (XSTRING (name)->size + 1);
336 bcopy(XSTRING (name)->data, fontsetp->name, XSTRING (name)->size + 1);
337
338 fontsetp->size = fontsetp->height = 0;
339
340 for (i = 0; i <= MAX_CHARSET; i++)
341 {
342 fontsetp->fontname[i] = (char *) 0;
343 fontsetp->font_indexes[i] = FONT_NOT_OPENED;
344 }
345
346 for (fontlist = XCONS (fontset_info)->cdr; CONSP (fontlist);
347 fontlist = XCONS (fontlist)->cdr)
348 {
349 Lisp_Object tem = Fcar (fontlist);
350 int charset;
351
352 if (CONSP (tem)
353 && (charset = get_charset_id (XCONS (tem)->car)) >= 0
354 && STRINGP (XCONS (tem)->cdr))
355 {
356 fontsetp->fontname[charset]
357 = (char *) xmalloc (XSTRING (XCONS (tem)->cdr)->size + 1);
358 bcopy (XSTRING (XCONS (tem)->cdr)->data,
359 fontsetp->fontname[charset],
360 XSTRING (XCONS (tem)->cdr)->size + 1);
361 }
362 else
363 /* Broken or invalid data structure. */
364 return -1;
365 }
366
367 /* Do we need to create the table? */
368 if (fontset_data->fontset_table_size == 0)
369 {
370 fontset_data->fontset_table_size = 8;
371 fontset_data->fontset_table
372 = (struct fontset_info **) xmalloc (fontset_data->fontset_table_size
373 * sizeof (struct fontset_info *));
374 }
375 /* Do we need to grow the table? */
376 else if (fontset_data->n_fontsets >= fontset_data->fontset_table_size)
377 {
378 fontset_data->fontset_table_size += 8;
379 fontset_data->fontset_table
380 = (struct fontset_info **) xrealloc (fontset_data->fontset_table,
381 fontset_data->fontset_table_size
382 * sizeof (struct fontset_info *));
383 }
384 fontset = fontset_data->n_fontsets++;
385 fontset_data->fontset_table[fontset] = fontsetp;
386
387 return fontset;
388 }
389
390 /* Cache data used by fontset_pattern_regexp. The car part is a
391 pattern string containing at least one wild card, the cdr part is
392 the corresponding regular expression. */
393 static Lisp_Object Vcached_fontset_data;
394
395 #define CACHED_FONTSET_NAME (XSTRING (XCONS (Vcached_fontset_data)->car)->data)
396 #define CACHED_FONTSET_REGEX (XCONS (Vcached_fontset_data)->cdr)
397
398 /* If fontset name PATTERN contains any wild card, return regular
399 expression corresponding to PATTERN. */
400
401 Lisp_Object
402 fontset_pattern_regexp (pattern)
403 Lisp_Object pattern;
404 {
405 if (!index (XSTRING (pattern)->data, '*')
406 && !index (XSTRING (pattern)->data, '?'))
407 /* PATTERN does not contain any wild cards. */
408 return Qnil;
409
410 if (!CONSP (Vcached_fontset_data)
411 || strcmp (XSTRING (pattern)->data, CACHED_FONTSET_NAME))
412 {
413 /* We must at first update the cached data. */
414 char *regex = (char *) alloca (XSTRING (pattern)->size * 2);
415 char *p0, *p1 = regex;
416
417 /* Convert "*" to ".*", "?" to ".". */
418 *p1++ = '^';
419 for (p0 = (char *) XSTRING (pattern)->data; *p0; p0++)
420 {
421 if (*p0 == '*')
422 {
423 *p1++ = '.';
424 *p1++ = '*';
425 }
426 else if (*p0 == '?')
427 *p1++ == '.';
428 else
429 *p1++ = *p0;
430 }
431 *p1++ = '$';
432 *p1++ = 0;
433
434 Vcached_fontset_data = Fcons (build_string (XSTRING (pattern)->data),
435 build_string (regex));
436 }
437
438 return CACHED_FONTSET_REGEX;
439 }
440
441 DEFUN ("query-fontset", Fquery_fontset, Squery_fontset, 1, 1, 0,
442 "Return a fontset name which matches PATTERN, nil if no matching fontset.\n\
443 PATTERN can contain `*' or `?' as a wild card\n\
444 just like X's font name matching algorithm allows.")
445 (pattern)
446 Lisp_Object pattern;
447 {
448 Lisp_Object regexp, tem;
449
450 (*check_window_system_func) ();
451
452 CHECK_STRING (pattern, 0);
453
454 if (XSTRING (pattern)->size == 0)
455 return Qnil;
456
457 tem = Frassoc (pattern, Vfontset_alias_alist);
458 if (!NILP (tem))
459 return Fcar (tem);
460
461 regexp = fontset_pattern_regexp (pattern);
462
463 for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCONS (tem)->cdr)
464 {
465 Lisp_Object fontset_name = XCONS (XCONS (tem)->car)->car;
466 if (!NILP (regexp))
467 {
468 if (fast_c_string_match_ignore_case (regexp,
469 XSTRING (fontset_name)->data)
470 >= 0)
471 return fontset_name;
472 }
473 else
474 {
475 if (!my_strcasecmp (XSTRING (pattern)->data,
476 XSTRING (fontset_name)->data))
477 return fontset_name;
478 }
479 }
480
481 return Qnil;
482 }
483
484 Lisp_Object Fframe_char_width ();
485
486 /* Return a list of names of available fontsets matching PATTERN on
487 frame F. If SIZE is not 0, it is the size (maximum bound width) of
488 fontsets to be listed. */
489
490 Lisp_Object
491 list_fontsets (f, pattern, size)
492 FRAME_PTR f;
493 Lisp_Object pattern;
494 int size;
495 {
496 int i;
497 Lisp_Object regexp, val;
498
499 regexp = fontset_pattern_regexp (pattern);
500
501 val = Qnil;
502 for (i = 0; i < FRAME_FONTSET_DATA (f)->n_fontsets; i++)
503 {
504 struct fontset_info *fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[i];
505 int name_matched = 0;
506 int size_matched = 0;
507
508 if (!NILP (regexp))
509 {
510 if (fast_c_string_match_ignore_case (regexp, fontsetp->name) >= 0)
511 name_matched = 1;
512 }
513 else
514 {
515 if (!my_strcasecmp (XSTRING (pattern)->data, fontsetp->name))
516 name_matched = 1;
517 }
518
519 if (name_matched)
520 {
521 if (!size || fontsetp->size == size)
522 size_matched = 1;
523 else if (fontsetp->size == 0)
524 {
525 /* No font of this fontset has loaded yet. Try loading
526 one with SIZE. */
527 int j;
528
529 for (j = 0; j <= MAX_CHARSET; j++)
530 if (fontsetp->fontname[j])
531 {
532 if ((*load_font_func) (f, fontsetp->fontname[j], size))
533 size_matched = 1;
534 break;
535 }
536 }
537
538 if (size_matched)
539 val = Fcons (build_string (fontsetp->name), val);
540 }
541 }
542
543 return val;
544 }
545
546 DEFUN ("new-fontset", Fnew_fontset, Snew_fontset, 2, 2, 0,
547 "Create a new fontset NAME which contains fonts in FONTLIST.\n\
548 FONTLIST is an alist of charsets vs corresponding font names.")
549 (name, fontlist)
550 Lisp_Object name, fontlist;
551 {
552 Lisp_Object fullname, fontset_info;
553 Lisp_Object tail;
554
555 (*check_window_system_func) ();
556
557 CHECK_STRING (name, 0);
558 CHECK_LIST (fontlist, 1);
559
560 fullname = Fquery_fontset (name);
561 if (!NILP (fullname))
562 error ("Fontset \"%s\" matches the existing fontset \"%s\"",
563 XSTRING (name)->data, XSTRING (fullname)->data);
564
565 /* Check the validity of FONTLIST. */
566 for (tail = fontlist; CONSP (tail); tail = XCONS (tail)->cdr)
567 {
568 Lisp_Object tem = XCONS (tail)->car;
569 int charset;
570
571 if (!CONSP (tem)
572 || (charset = get_charset_id (XCONS (tem)->car)) < 0
573 || !STRINGP (XCONS (tem)->cdr))
574 error ("Elements of fontlist must be a cons of charset and font name");
575 }
576
577 fontset_info = Fcons (name, fontlist);
578 Vglobal_fontset_alist = Fcons (fontset_info, Vglobal_fontset_alist);
579
580 /* Register this fontset for all existing frames. */
581 {
582 Lisp_Object framelist, frame;
583
584 FOR_EACH_FRAME (framelist, frame)
585 if (!FRAME_TERMCAP_P (XFRAME (frame)))
586 fs_register_fontset (XFRAME (frame), fontset_info);
587 }
588
589 return Qnil;
590 }
591
592 extern Lisp_Object Fframe_parameters ();
593 extern Lisp_Object Qfont;
594 Lisp_Object Qfontset;
595
596 DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 4, 0,
597 "Set FONTNAME for a font of CHARSET in fontset NAME on frame FRAME.\n\
598 If FRAME is omitted or nil, all frames are affected.")
599 (name, charset_symbol, fontname, frame)
600 Lisp_Object name, charset_symbol, fontname, frame;
601 {
602 int charset;
603 Lisp_Object fullname, fontlist;
604
605 (*check_window_system_func) ();
606
607 CHECK_STRING (name, 0);
608 CHECK_SYMBOL (charset_symbol, 1);
609 CHECK_STRING (fontname, 2);
610 if (!NILP (frame))
611 CHECK_LIVE_FRAME (frame, 3);
612
613 if ((charset = get_charset_id (charset_symbol)) < 0)
614 error ("Invalid charset: %s", XSYMBOL (charset_symbol)->name->data);
615
616 fullname = Fquery_fontset (name);
617 if (NILP (fullname))
618 error ("Fontset \"%s\" does not exist", XSTRING (name)->data);
619
620 /* If FRAME is not specified, we must, at first, update contents of
621 `global-fontset-alist' for a frame created in the future. */
622 if (NILP (frame))
623 {
624 Lisp_Object fontset_info = Fassoc (fullname, Vglobal_fontset_alist);
625 Lisp_Object tem = Fassq (charset_symbol, XCONS (fontset_info)->cdr);
626
627 if (NILP (tem))
628 XCONS (fontset_info)->cdr
629 = Fcons (Fcons (charset_symbol, fontname),
630 XCONS (fontset_info)->cdr);
631 else
632 XCONS (tem)->cdr = fontname;
633 }
634
635 /* Then, update information in the specified frame or all existing
636 frames. */
637 {
638 Lisp_Object framelist, tem;
639
640 FOR_EACH_FRAME (framelist, tem)
641 if (!FRAME_TERMCAP_P (XFRAME (tem))
642 && (NILP (frame) || EQ (frame, tem)))
643 {
644 FRAME_PTR f = XFRAME (tem);
645 int fontset = fs_query_fontset (f, XSTRING (fullname)->data);
646 struct fontset_info *fontsetp
647 = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
648
649 if (fontsetp->fontname[charset])
650 xfree (fontsetp->fontname[charset]);
651 fontsetp->fontname[charset]
652 = (char *) xmalloc (XSTRING (fontname)->size + 1);
653 bcopy (XSTRING (fontname)->data, fontsetp->fontname[charset],
654 XSTRING (fontname)->size + 1);
655 fontsetp->font_indexes[charset] = FONT_NOT_OPENED;
656
657 if (charset == CHARSET_ASCII)
658 {
659 Lisp_Object font_param = Fassq (Qfont, Fframe_parameters (tem));
660
661 if (set_frame_fontset_func
662 && !NILP (font_param)
663 && !strcmp (XSTRING (fullname)->data,
664 XSTRING (XCONS (font_param)->cdr)->data))
665 /* This fontset is the default fontset on frame TEM.
666 We may have to resize this frame because of new
667 ASCII font. */
668 (*set_frame_fontset_func) (f, fullname, Qnil);
669 }
670 }
671 }
672
673 return Qnil;
674 }
675
676 DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
677 "Return information about a font named NAME on frame FRAME.\n\
678 If FRAME is omitted or nil, use the selected frame.\n\
679 The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,\n\
680 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,\n\
681 where\n\
682 OPENED-NAME is the name used for opening the font,\n\
683 FULL-NAME is the full name of the font,\n\
684 CHARSET is the charset displayed by the font,\n\
685 SIZE is the minimum bound width of the font,\n\
686 HEIGHT is the height of the font,\n\
687 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,\n\
688 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling\n\
689 how to compose characters.\n\
690 If the named font is not yet loaded, return nil.")
691 (name, frame)
692 Lisp_Object name, frame;
693 {
694 FRAME_PTR f;
695 struct font_info *fontp;
696 Lisp_Object info;
697
698 (*check_window_system_func) ();
699
700 CHECK_STRING (name, 0);
701 if (NILP (frame))
702 f = selected_frame;
703 else
704 {
705 CHECK_LIVE_FRAME (frame, 1);
706 f = XFRAME (frame);
707 }
708
709 if (!query_font_func)
710 error ("Font query function is not supported");
711
712 fontp = (*query_font_func) (f, XSTRING (name)->data);
713 if (!fontp)
714 return Qnil;
715
716 info = Fmake_vector (make_number (7), Qnil);
717
718 XVECTOR (info)->contents[0] = build_string (fontp->name);
719 XVECTOR (info)->contents[1] = build_string (fontp->full_name);
720 XVECTOR (info)->contents[2] = CHARSET_SYMBOL (fontp->charset);
721 XVECTOR (info)->contents[3] = make_number (fontp->size);
722 XVECTOR (info)->contents[4] = make_number (fontp->height);
723 XVECTOR (info)->contents[5] = make_number (fontp->baseline_offset);
724 XVECTOR (info)->contents[6] = make_number (fontp->relative_compose);
725 XVECTOR (info)->contents[7] = make_number (fontp->default_ascent);
726
727 return info;
728 }
729
730 DEFUN ("fontset-info", Ffontset_info, Sfontset_info, 1, 2, 0,
731 "Return information about a fontset named NAME on frame FRAME.\n\
732 If FRAME is omitted or nil, use the selected frame.\n\
733 The returned value is a vector of SIZE, HEIGHT, and FONT-LIST,\n\
734 where\n\
735 SIZE is the minimum bound width of ASCII font of the fontset,\n\
736 HEIGHT is the height of the tallest font in the fontset, and\n\
737 FONT-LIST is an alist of the format:\n\
738 (CHARSET REQUESTED-FONT-NAME LOADED-FONT-NAME).\n\
739 LOADED-FONT-NAME t means the font is not yet loaded, nil means the\n\
740 loading failed.")
741 (name, frame)
742 Lisp_Object name, frame;
743 {
744 FRAME_PTR f;
745 int fontset;
746 struct fontset_info *fontsetp;
747 Lisp_Object info, val;
748 int i;
749
750 (*check_window_system_func) ();
751
752 CHECK_STRING(name, 0);
753 if (NILP (frame))
754 f = selected_frame;
755 else
756 {
757 CHECK_LIVE_FRAME (frame, 1);
758 f = XFRAME (frame);
759 }
760
761 fontset = fs_query_fontset (f, XSTRING (name)->data);
762 if (fontset < 0)
763 error ("Fontset \"%s\" does not exist", XSTRING (name)->data);
764
765 info = Fmake_vector (make_number (3), Qnil);
766
767 fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
768
769 XVECTOR (info)->contents[0] = make_number (fontsetp->size);
770 XVECTOR (info)->contents[1] = make_number (fontsetp->height);
771 val = Qnil;
772 for (i = 0; i <= MAX_CHARSET; i++)
773 if (fontsetp->fontname[i])
774 {
775 int font_idx = fontsetp->font_indexes[i];
776 Lisp_Object loaded;
777
778 if (font_idx == FONT_NOT_OPENED)
779 loaded = Qt;
780 else if (font_idx == FONT_NOT_FOUND)
781 loaded = Qnil;
782 else
783 loaded
784 = build_string ((*get_font_info_func) (f, font_idx)->full_name);
785 val = Fcons (Fcons (CHARSET_SYMBOL (i),
786 Fcons (build_string (fontsetp->fontname[i]),
787 Fcons (loaded, Qnil))),
788 val);
789 }
790 XVECTOR (info)->contents[2] = val;
791 return info;
792 }
793
794 syms_of_fontset ()
795 {
796 int i;
797
798 for (i = 0; i < 256; i++)
799 my_strcasetbl[i] = (i >= 'A' && i <= 'Z') ? i + 'a' - 'A' : i;
800
801 if (!load_font_func)
802 /* Window system initializer should have set proper functions. */
803 abort ();
804
805 Qfontset = intern ("fontset");
806 staticpro (&Qfontset);
807
808 Vcached_fontset_data = Qnil;
809 staticpro (&Vcached_fontset_data);
810
811 DEFVAR_LISP ("global-fontset-alist", &Vglobal_fontset_alist,
812 "Internal data for fontset. Not for external use.\n\
813 This is an alist associating fontset names with the lists of fonts\n\
814 contained in them.\n\
815 Newly created frames make their own fontset database from here.");
816 Vglobal_fontset_alist = Qnil;
817
818 DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist,
819 "Alist of fontname patterns vs corresponding encoding info.\n\
820 Each element looks like (REGEXP . ENCODING-INFO),\n\
821 where ENCODING-INFO is an alist of CHARSET vs ENCODING.\n\
822 ENCODING is one of the following integer values:\n\
823 0: code points 0x20..0x7F or 0x2020..0x7F7F are used,\n\
824 1: code points 0xA0..0xFF or 0xA0A0..0xFFFF are used,\n\
825 2: code points 0x20A0..0x7FFF are used,\n\
826 3: code points 0xA020..0xFF7F are used.");
827 Vfont_encoding_alist = Qnil;
828
829 DEFVAR_LISP ("use-default-ascent", &Vuse_default_ascent,
830 "Char table of characters of which ascent values should be ignored.\n\
831 If an entry for a character is non-nil, the ascent value of the glyph\n\
832 is assumed to be what specified by _MULE_DEFAULT_ASCENT property of a font.");
833 Vuse_default_ascent = Qnil;
834
835 DEFVAR_LISP ("alternative-fontname-alist", &Valternative_fontname_alist,
836 "Alist of fontname vs list of the alternative fontnames.\n\
837 When no font can be opened by a fontname, the corresponding\n\
838 alternative fontnames are tried.");
839 Valternative_fontname_alist = Qnil;
840
841 DEFVAR_LISP ("fontset-alias-alist", &Vfontset_alias_alist,
842 "Alist of fontset names vs the aliases.");
843 Vfontset_alias_alist = Qnil;
844
845 DEFVAR_LISP ("highlight-wrong-size-font", &Vhighlight_wrong_size_font,
846 "*Non-nil means highlight characters shown in wrong size fonts somehow.\n\
847 The way to highlight them depends on window system on which Emacs runs.\n\
848 On X window, a rectangle is shown around each such character.");
849 Vhighlight_wrong_size_font = Qt;
850
851 DEFVAR_LISP ("clip-large-size-font", &Vclip_large_size_font,
852 "*Non-nil means characters shown in large size fonts are clipped.\n\
853 The height of clipping area is the same as that of an ASCII character.\n\
854 The width of the area is the same as that of an ASCII character or\n\
855 twice wider than that of an ASCII character depending on\n\
856 the width (i.e. column numbers occupied on screen) of the character set\n\
857 of the character.\n\
858 \n\
859 In the case that you only have too large size font for a specific\n\
860 charscter set, and clipping characters of the character set makes them\n\
861 almost unreadable, you can set this variable to t to see the\n\
862 characters in exchage for garbage dots left on your screen.");
863 Vclip_large_size_font = Qt;
864
865 defsubr (&Squery_fontset);
866 defsubr (&Snew_fontset);
867 defsubr (&Sset_fontset_font);
868 defsubr (&Sfont_info);
869 defsubr (&Sfontset_info);
870 }