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