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