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