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