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