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