(x-set-cut-buffer): Cancel previous change.
[bpt/emacs.git] / src / fontset.c
CommitLineData
4ed46869 1/* Fontset handler.
85b0dba0 2 Copyright (C) 2004 Free Software Foundation, Inc.
0d407d77 3 Copyright (C) 1995, 1997, 2000 Electrotechnical Laboratory, JAPAN.
75c8c592 4 Licensed to the Free Software Foundation.
4ed46869 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 22
0d407d77
KH
23/* #define FONTSET_DEBUG */
24
4ed46869 25#include <config.h>
0d407d77
KH
26
27#ifdef FONTSET_DEBUG
28#include <stdio.h>
29#endif
30
4ed46869 31#include "lisp.h"
1ff005e1 32#include "buffer.h"
4ed46869
KH
33#include "charset.h"
34#include "ccl.h"
2538fae4 35#include "keyboard.h"
4ed46869 36#include "frame.h"
0d407d77 37#include "dispextern.h"
3541bb8f 38#include "fontset.h"
0d407d77 39#include "window.h"
e5bc082b
KH
40#ifdef HAVE_X_WINDOWS
41#include "xterm.h"
42#endif
43#ifdef WINDOWSNT
44#include "w32term.h"
45#endif
46#ifdef MAC_OS
47#include "macterm.h"
48#endif
0d407d77
KH
49
50#ifdef FONTSET_DEBUG
51#undef xassert
52#define xassert(X) do {if (!(X)) abort ();} while (0)
53#undef INLINE
54#define INLINE
55#endif
56
57
58/* FONTSET
59
60 A fontset is a collection of font related information to give
61 similar appearance (style, size, etc) of characters. There are two
62 kinds of fontsets; base and realized. A base fontset is created by
63 new-fontset from Emacs Lisp explicitly. A realized fontset is
64 created implicitly when a face is realized for ASCII characters. A
65 face is also realized for multibyte characters based on an ASCII
66 face. All of the multibyte faces based on the same ASCII face
67 share the same realized fontset.
fc8865fc 68
0d407d77
KH
69 A fontset object is implemented by a char-table.
70
71 An element of a base fontset is:
72 (INDEX . FONTNAME) or
73 (INDEX . (FOUNDRY . REGISTRY ))
74 FONTNAME is a font name pattern for the corresponding character.
fc8865fc 75 FOUNDRY and REGISTRY are respectively foundry and registry fields of
0d407d77
KH
76 a font name for the corresponding character. INDEX specifies for
77 which character (or generic character) the element is defined. It
78 may be different from an index to access this element. For
79 instance, if a fontset defines some font for all characters of
80 charset `japanese-jisx0208', INDEX is the generic character of this
81 charset. REGISTRY is the
82
83 An element of a realized fontset is FACE-ID which is a face to use
fc8865fc 84 for displaying the corresponding character.
0d407d77 85
fc8865fc 86 All single byte characters (ASCII and 8bit-unibyte) share the same
11d9bd93
KH
87 element in a fontset. The element is stored in the first element
88 of the fontset.
0d407d77
KH
89
90 To access or set each element, use macros FONTSET_REF and
91 FONTSET_SET respectively for efficiency.
92
93 A fontset has 3 extra slots.
94
95 The 1st slot is an ID number of the fontset.
96
97 The 2nd slot is a name of the fontset. This is nil for a realized
98 face.
99
100 The 3rd slot is a frame that the fontset belongs to. This is nil
101 for a default face.
102
103 A parent of a base fontset is nil. A parent of a realized fontset
104 is a base fontset.
105
afe93d01 106 All fontsets are recorded in Vfontset_table.
0d407d77
KH
107
108
109 DEFAULT FONTSET
110
111 There's a special fontset named `default fontset' which defines a
afe93d01
KH
112 default fontname pattern. When a base fontset doesn't specify a
113 font for a specific character, the corresponding value in the
114 default fontset is used. The format is the same as a base fontset.
0d407d77 115
afe93d01
KH
116 The parent of a realized fontset created for such a face that has
117 no fontset is the default fontset.
0d407d77
KH
118
119
120 These structures are hidden from the other codes than this file.
121 The other codes handle fontsets only by their ID numbers. They
122 usually use variable name `fontset' for IDs. But, in this file, we
fc8865fc 123 always use variable name `id' for IDs, and name `fontset' for the
0d407d77
KH
124 actual fontset objects.
125
126*/
127
128/********** VARIABLES and FUNCTION PROTOTYPES **********/
129
130extern Lisp_Object Qfont;
131Lisp_Object Qfontset;
132
133/* Vector containing all fontsets. */
134static Lisp_Object Vfontset_table;
135
fc8865fc 136/* Next possibly free fontset ID. Usually this keeps the minimum
0d407d77
KH
137 fontset ID not yet used. */
138static int next_fontset_id;
139
140/* The default fontset. This gives default FAMILY and REGISTRY of
141 font for each characters. */
142static Lisp_Object Vdefault_fontset;
4ed46869 143
2f65c7b5
KH
144/* Alist of font specifications. It override the font specification
145 in the default fontset. */
146static Lisp_Object Voverriding_fontspec_alist;
147
4ed46869 148Lisp_Object Vfont_encoding_alist;
6a7e6d80 149Lisp_Object Vuse_default_ascent;
2aeafb78 150Lisp_Object Vignore_relative_composition;
01d4b817 151Lisp_Object Valternate_fontname_alist;
1c283e35 152Lisp_Object Vfontset_alias_alist;
810abb87 153Lisp_Object Vvertical_centering_font_regexp;
4ed46869 154
0d407d77
KH
155/* The following six are declarations of callback functions depending
156 on window system. See the comments in src/fontset.h for more
157 detail. */
4ed46869
KH
158
159/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5771dcf4 160struct font_info *(*get_font_info_func) P_ ((FRAME_PTR f, int font_idx));
4ed46869 161
fc8865fc
PJ
162/* Return a list of font names which matches PATTERN. See the documentation
163 of `x-list-fonts' for more details. */
3541bb8f
KH
164Lisp_Object (*list_fonts_func) P_ ((struct frame *f,
165 Lisp_Object pattern,
166 int size,
167 int maxnames));
4ed46869
KH
168
169/* Load a font named NAME for frame F and return a pointer to the
170 information of the loaded font. If loading is failed, return 0. */
5771dcf4 171struct font_info *(*load_font_func) P_ ((FRAME_PTR f, char *name, int));
4ed46869
KH
172
173/* Return a pointer to struct font_info of a font named NAME for frame F. */
5771dcf4 174struct font_info *(*query_font_func) P_ ((FRAME_PTR f, char *name));
4ed46869
KH
175
176/* Additional function for setting fontset or changing fontset
177 contents of frame F. */
5771dcf4
AS
178void (*set_frame_fontset_func) P_ ((FRAME_PTR f, Lisp_Object arg,
179 Lisp_Object oldval));
4ed46869 180
727fb790
KH
181/* To find a CCL program, fs_load_font calls this function.
182 The argument is a pointer to the struct font_info.
fc8865fc 183 This function set the member `encoder' of the structure. */
727fb790
KH
184void (*find_ccl_program_func) P_ ((struct font_info *));
185
4ed46869 186/* Check if any window system is used now. */
5771dcf4 187void (*check_window_system_func) P_ ((void));
4ed46869 188
0d407d77
KH
189
190/* Prototype declarations for static functions. */
191static Lisp_Object fontset_ref P_ ((Lisp_Object, int));
2f65c7b5 192static Lisp_Object lookup_overriding_fontspec P_ ((Lisp_Object, int));
0d407d77
KH
193static void fontset_set P_ ((Lisp_Object, int, Lisp_Object));
194static Lisp_Object make_fontset P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
195static int fontset_id_valid_p P_ ((int));
196static Lisp_Object fontset_pattern_regexp P_ ((Lisp_Object));
8d04974a 197static Lisp_Object font_family_registry P_ ((Lisp_Object, int));
4ce2719d 198static Lisp_Object regularize_fontname P_ ((Lisp_Object));
0d407d77
KH
199
200\f
201/********** MACROS AND FUNCTIONS TO HANDLE FONTSET **********/
202
0d407d77
KH
203/* Return the fontset with ID. No check of ID's validness. */
204#define FONTSET_FROM_ID(id) AREF (Vfontset_table, id)
205
afe93d01 206/* Macros to access special values of FONTSET. */
0d407d77
KH
207#define FONTSET_ID(fontset) XCHAR_TABLE (fontset)->extras[0]
208#define FONTSET_NAME(fontset) XCHAR_TABLE (fontset)->extras[1]
209#define FONTSET_FRAME(fontset) XCHAR_TABLE (fontset)->extras[2]
11d9bd93 210#define FONTSET_ASCII(fontset) XCHAR_TABLE (fontset)->contents[0]
0d407d77
KH
211#define FONTSET_BASE(fontset) XCHAR_TABLE (fontset)->parent
212
213#define BASE_FONTSET_P(fontset) NILP (FONTSET_BASE(fontset))
214
215
216/* Return the element of FONTSET (char-table) at index C (character). */
217
218#define FONTSET_REF(fontset, c) fontset_ref (fontset, c)
219
afe93d01 220static Lisp_Object
0d407d77
KH
221fontset_ref (fontset, c)
222 Lisp_Object fontset;
223 int c;
224{
225 int charset, c1, c2;
226 Lisp_Object elt, defalt;
0d407d77
KH
227
228 if (SINGLE_BYTE_CHAR_P (c))
229 return FONTSET_ASCII (fontset);
230
f55d03b1 231 SPLIT_CHAR (c, charset, c1, c2);
0d407d77
KH
232 elt = XCHAR_TABLE (fontset)->contents[charset + 128];
233 if (!SUB_CHAR_TABLE_P (elt))
234 return elt;
235 defalt = XCHAR_TABLE (elt)->defalt;
236 if (c1 < 32
237 || (elt = XCHAR_TABLE (elt)->contents[c1],
238 NILP (elt)))
239 return defalt;
240 if (!SUB_CHAR_TABLE_P (elt))
241 return elt;
242 defalt = XCHAR_TABLE (elt)->defalt;
243 if (c2 < 32
244 || (elt = XCHAR_TABLE (elt)->contents[c2],
245 NILP (elt)))
246 return defalt;
247 return elt;
248}
249
250
2f65c7b5
KH
251static Lisp_Object
252lookup_overriding_fontspec (frame, c)
253 Lisp_Object frame;
254 int c;
255{
256 Lisp_Object tail;
257
258 for (tail = Voverriding_fontspec_alist; CONSP (tail); tail = XCDR (tail))
259 {
260 Lisp_Object val, target, elt;
261
262 val = XCAR (tail);
263 target = XCAR (val);
264 val = XCDR (val);
265 /* Now VAL is (NO-FRAME-LIST OK-FRAME-LIST CHAR FONTNAME). */
266 if (NILP (Fmemq (frame, XCAR (val)))
267 && (CHAR_TABLE_P (target)
268 ? ! NILP (CHAR_TABLE_REF (target, c))
269 : XINT (target) == CHAR_CHARSET (c)))
270 {
271 val = XCDR (val);
272 elt = XCDR (val);
273 if (NILP (Fmemq (frame, XCAR (val))))
274 {
275 if (! face_font_available_p (XFRAME (frame), XCDR (elt)))
276 {
277 val = XCDR (XCAR (tail));
278 XSETCAR (val, Fcons (frame, XCAR (val)));
279 continue;
280 }
281 XSETCAR (val, Fcons (frame, XCAR (val)));
282 }
283 if (NILP (XCAR (elt)))
284 XSETCAR (elt, make_number (c));
285 return elt;
286 }
287 }
288 return Qnil;
289}
290
0d407d77
KH
291#define FONTSET_REF_VIA_BASE(fontset, c) fontset_ref_via_base (fontset, &c)
292
afe93d01 293static Lisp_Object
0d407d77
KH
294fontset_ref_via_base (fontset, c)
295 Lisp_Object fontset;
296 int *c;
297{
298 int charset, c1, c2;
299 Lisp_Object elt;
0d407d77
KH
300
301 if (SINGLE_BYTE_CHAR_P (*c))
302 return FONTSET_ASCII (fontset);
303
2f65c7b5
KH
304 elt = Qnil;
305 if (! EQ (FONTSET_BASE (fontset), Vdefault_fontset))
306 elt = FONTSET_REF (FONTSET_BASE (fontset), *c);
307 if (NILP (elt))
308 elt = lookup_overriding_fontspec (FONTSET_FRAME (fontset), *c);
9da88f37 309 if (NILP (elt))
11d9bd93 310 elt = FONTSET_REF (Vdefault_fontset, *c);
0d407d77
KH
311 if (NILP (elt))
312 return Qnil;
313
314 *c = XINT (XCAR (elt));
f55d03b1 315 SPLIT_CHAR (*c, charset, c1, c2);
0d407d77
KH
316 elt = XCHAR_TABLE (fontset)->contents[charset + 128];
317 if (c1 < 32)
318 return (SUB_CHAR_TABLE_P (elt) ? XCHAR_TABLE (elt)->defalt : elt);
319 if (!SUB_CHAR_TABLE_P (elt))
320 return Qnil;
321 elt = XCHAR_TABLE (elt)->contents[c1];
322 if (c2 < 32)
323 return (SUB_CHAR_TABLE_P (elt) ? XCHAR_TABLE (elt)->defalt : elt);
324 if (!SUB_CHAR_TABLE_P (elt))
325 return Qnil;
326 elt = XCHAR_TABLE (elt)->contents[c2];
327 return elt;
328}
329
330
afe93d01 331/* Store into the element of FONTSET at index C the value NEWELT. */
0d407d77
KH
332#define FONTSET_SET(fontset, c, newelt) fontset_set(fontset, c, newelt)
333
334static void
335fontset_set (fontset, c, newelt)
336 Lisp_Object fontset;
337 int c;
338 Lisp_Object newelt;
339{
340 int charset, code[3];
1337ac77
EZ
341 Lisp_Object *elt;
342 int i;
0d407d77
KH
343
344 if (SINGLE_BYTE_CHAR_P (c))
345 {
346 FONTSET_ASCII (fontset) = newelt;
347 return;
348 }
349
f55d03b1 350 SPLIT_CHAR (c, charset, code[0], code[1]);
0d407d77
KH
351 code[2] = 0; /* anchor */
352 elt = &XCHAR_TABLE (fontset)->contents[charset + 128];
353 for (i = 0; code[i] > 0; i++)
354 {
355 if (!SUB_CHAR_TABLE_P (*elt))
356 *elt = make_sub_char_table (*elt);
357 elt = &XCHAR_TABLE (*elt)->contents[code[i]];
358 }
359 if (SUB_CHAR_TABLE_P (*elt))
360 XCHAR_TABLE (*elt)->defalt = newelt;
361 else
362 *elt = newelt;
363}
364
365
366/* Return a newly created fontset with NAME. If BASE is nil, make a
367 base fontset. Otherwise make a realized fontset whose parent is
368 BASE. */
369
370static Lisp_Object
371make_fontset (frame, name, base)
372 Lisp_Object frame, name, base;
4ed46869 373{
1337ac77 374 Lisp_Object fontset;
0d407d77
KH
375 int size = ASIZE (Vfontset_table);
376 int id = next_fontset_id;
0d407d77
KH
377
378 /* Find a free slot in Vfontset_table. Usually, next_fontset_id is
379 the next available fontset ID. So it is expected that this loop
380 terminates quickly. In addition, as the last element of
fc8865fc 381 Vfontset_table is always nil, we don't have to check the range of
0d407d77
KH
382 id. */
383 while (!NILP (AREF (Vfontset_table, id))) id++;
384
385 if (id + 1 == size)
386 {
387 Lisp_Object tem;
fc8865fc 388 int i;
4ed46869 389
0d407d77
KH
390 tem = Fmake_vector (make_number (size + 8), Qnil);
391 for (i = 0; i < size; i++)
392 AREF (tem, i) = AREF (Vfontset_table, i);
393 Vfontset_table = tem;
394 }
4ed46869 395
11d9bd93 396 fontset = Fmake_char_table (Qfontset, Qnil);
0d407d77
KH
397
398 FONTSET_ID (fontset) = make_number (id);
399 FONTSET_NAME (fontset) = name;
400 FONTSET_FRAME (fontset) = frame;
401 FONTSET_BASE (fontset) = base;
402
403 AREF (Vfontset_table, id) = fontset;
404 next_fontset_id = id + 1;
405 return fontset;
4ed46869
KH
406}
407
0d407d77
KH
408
409/* Return 1 if ID is a valid fontset id, else return 0. */
410
411static INLINE int
412fontset_id_valid_p (id)
413 int id;
414{
415 return (id >= 0 && id < ASIZE (Vfontset_table) - 1);
416}
417
418
8d04974a
KH
419/* Extract `family' and `registry' string from FONTNAME and a cons of
420 them. Actually, `family' may also contain `foundry', `registry'
421 may also contain `encoding' of FONTNAME. But, if FONTNAME doesn't
422 conform to XLFD nor explicitely specifies the other fields
423 (i.e. not using wildcard `*'), return FONTNAME. If FORCE is
424 nonzero, specifications of the other fields are ignored, and return
425 a cons as far as FONTNAME conform to XLFD. */
0d407d77
KH
426
427static Lisp_Object
8d04974a 428font_family_registry (fontname, force)
0d407d77 429 Lisp_Object fontname;
8d04974a 430 int force;
0d407d77
KH
431{
432 Lisp_Object family, registry;
637ddd32
KR
433 const char *p = SDATA (fontname);
434 const char *sep[15];
0d407d77 435 int i = 0;
fc8865fc 436
8d04974a
KH
437 while (*p && i < 15)
438 if (*p++ == '-')
439 {
440 if (!force && i >= 2 && i <= 11 && *p != '*' && p[1] != '-')
441 return fontname;
442 sep[i++] = p;
443 }
0d407d77
KH
444 if (i != 14)
445 return fontname;
446
447 family = make_unibyte_string (sep[0], sep[2] - 1 - sep[0]);
448 registry = make_unibyte_string (sep[12], p - sep[12]);
449 return Fcons (family, registry);
450}
451
452\f
fc8865fc 453/********** INTERFACES TO xfaces.c and dispextern.h **********/
0d407d77
KH
454
455/* Return name of the fontset with ID. */
456
457Lisp_Object
458fontset_name (id)
459 int id;
460{
461 Lisp_Object fontset;
462 fontset = FONTSET_FROM_ID (id);
463 return FONTSET_NAME (fontset);
464}
465
466
467/* Return ASCII font name of the fontset with ID. */
468
469Lisp_Object
470fontset_ascii (id)
471 int id;
472{
473 Lisp_Object fontset, elt;
474 fontset= FONTSET_FROM_ID (id);
475 elt = FONTSET_ASCII (fontset);
476 return XCDR (elt);
477}
478
479
480/* Free fontset of FACE. Called from free_realized_face. */
481
4ed46869 482void
0d407d77
KH
483free_face_fontset (f, face)
484 FRAME_PTR f;
485 struct face *face;
4ed46869 486{
0d407d77 487 if (fontset_id_valid_p (face->fontset))
4ed46869 488 {
0d407d77
KH
489 AREF (Vfontset_table, face->fontset) = Qnil;
490 if (face->fontset < next_fontset_id)
491 next_fontset_id = face->fontset;
492 }
493}
18998710 494
0d407d77
KH
495
496/* Return 1 iff FACE is suitable for displaying character C.
497 Otherwise return 0. Called from the macro FACE_SUITABLE_FOR_CHAR_P
498 when C is not a single byte character.. */
499
500int
501face_suitable_for_char_p (face, c)
502 struct face *face;
503 int c;
504{
505 Lisp_Object fontset, elt;
506
507 if (SINGLE_BYTE_CHAR_P (c))
508 return (face == face->ascii_face);
509
510 xassert (fontset_id_valid_p (face->fontset));
511 fontset = FONTSET_FROM_ID (face->fontset);
512 xassert (!BASE_FONTSET_P (fontset));
513
514 elt = FONTSET_REF_VIA_BASE (fontset, c);
515 return (!NILP (elt) && face->id == XFASTINT (elt));
516}
517
518
519/* Return ID of face suitable for displaying character C on frame F.
520 The selection of face is done based on the fontset of FACE. FACE
521 should already have been realized for ASCII characters. Called
522 from the macro FACE_FOR_CHAR when C is not a single byte character. */
523
524int
525face_for_char (f, face, c)
526 FRAME_PTR f;
527 struct face *face;
528 int c;
529{
530 Lisp_Object fontset, elt;
531 int face_id;
532
533 xassert (fontset_id_valid_p (face->fontset));
534 fontset = FONTSET_FROM_ID (face->fontset);
535 xassert (!BASE_FONTSET_P (fontset));
536
537 elt = FONTSET_REF_VIA_BASE (fontset, c);
538 if (!NILP (elt))
539 return XINT (elt);
540
541 /* No face is recorded for C in the fontset of FACE. Make a new
542 realized face for C that has the same fontset. */
543 face_id = lookup_face (f, face->lface, c, face);
fc8865fc 544
0d407d77
KH
545 /* Record the face ID in FONTSET at the same index as the
546 information in the base fontset. */
547 FONTSET_SET (fontset, c, make_number (face_id));
548 return face_id;
549}
550
551
552/* Make a realized fontset for ASCII face FACE on frame F from the
553 base fontset BASE_FONTSET_ID. If BASE_FONTSET_ID is -1, use the
554 default fontset as the base. Value is the id of the new fontset.
555 Called from realize_x_face. */
556
557int
558make_fontset_for_ascii_face (f, base_fontset_id)
559 FRAME_PTR f;
560 int base_fontset_id;
561{
1337ac77 562 Lisp_Object base_fontset, fontset, frame;
0d407d77
KH
563
564 XSETFRAME (frame, f);
565 if (base_fontset_id >= 0)
566 {
567 base_fontset = FONTSET_FROM_ID (base_fontset_id);
568 if (!BASE_FONTSET_P (base_fontset))
569 base_fontset = FONTSET_BASE (base_fontset);
570 xassert (BASE_FONTSET_P (base_fontset));
4ed46869 571 }
0d407d77
KH
572 else
573 base_fontset = Vdefault_fontset;
574
575 fontset = make_fontset (frame, Qnil, base_fontset);
f3231837 576 return XINT (FONTSET_ID (fontset));
0d407d77
KH
577}
578
579
580/* Return the font name pattern for C that is recorded in the fontset
8d04974a
KH
581 with ID. If a font name pattern is specified (instead of a cons of
582 family and registry), check if a font can be opened by that pattern
583 to get the fullname. If a font is opened, return that name.
584 Otherwise, return nil. If ID is -1, or the fontset doesn't contain
0d407d77
KH
585 information about C, get the registry and encoding of C from the
586 default fontset. Called from choose_face_font. */
587
588Lisp_Object
589fontset_font_pattern (f, id, c)
590 FRAME_PTR f;
591 int id, c;
592{
593 Lisp_Object fontset, elt;
594 struct font_info *fontp;
fc8865fc 595
0d407d77
KH
596 elt = Qnil;
597 if (fontset_id_valid_p (id))
598 {
599 fontset = FONTSET_FROM_ID (id);
600 xassert (!BASE_FONTSET_P (fontset));
601 fontset = FONTSET_BASE (fontset);
07836f47
KH
602 if (! EQ (fontset, Vdefault_fontset))
603 elt = FONTSET_REF (fontset, c);
0d407d77 604 }
2f65c7b5
KH
605 if (NILP (elt))
606 {
607 Lisp_Object frame;
608
609 XSETFRAME (frame, f);
610 elt = lookup_overriding_fontspec (frame, c);
611 }
11d9bd93 612 if (NILP (elt))
0d407d77
KH
613 elt = FONTSET_REF (Vdefault_fontset, c);
614
615 if (!CONSP (elt))
616 return Qnil;
617 if (CONSP (XCDR (elt)))
618 return XCDR (elt);
619
620 /* The fontset specifies only a font name pattern (not cons of
8d04974a
KH
621 family and registry). If a font can be opened by that pattern,
622 return the name of opened font. Otherwise return nil. The
623 exception is a font for single byte characters. In that case, we
624 return a cons of FAMILY and REGISTRY extracted from the opened
625 font name. */
0d407d77
KH
626 elt = XCDR (elt);
627 xassert (STRINGP (elt));
d5db4077 628 fontp = FS_LOAD_FONT (f, c, SDATA (elt), -1);
0d407d77
KH
629 if (!fontp)
630 return Qnil;
4ed46869 631
8d04974a
KH
632 return font_family_registry (build_string (fontp->full_name),
633 SINGLE_BYTE_CHAR_P (c));
4ed46869
KH
634}
635
d5e7d534 636
97f4db8c
AI
637#if defined(WINDOWSNT) && defined (_MSC_VER)
638#pragma optimize("", off)
639#endif
640
0d407d77
KH
641/* Load a font named FONTNAME to display character C on frame F.
642 Return a pointer to the struct font_info of the loaded font. If
643 loading fails, return NULL. If FACE is non-zero and a fontset is
644 assigned to it, record FACE->id in the fontset for C. If FONTNAME
645 is NULL, the name is taken from the fontset of FACE or what
646 specified by ID. */
4ed46869
KH
647
648struct font_info *
0d407d77 649fs_load_font (f, c, fontname, id, face)
4ed46869 650 FRAME_PTR f;
0d407d77 651 int c;
4ed46869 652 char *fontname;
0d407d77
KH
653 int id;
654 struct face *face;
4ed46869 655{
0d407d77 656 Lisp_Object fontset;
6e1b0d8c 657 Lisp_Object list, elt, fullname;
4ed46869 658 int size = 0;
4ed46869 659 struct font_info *fontp;
0d407d77
KH
660 int charset = CHAR_CHARSET (c);
661
662 if (face)
663 id = face->fontset;
664 if (id < 0)
665 fontset = Qnil;
666 else
667 fontset = FONTSET_FROM_ID (id);
4ed46869 668
0d407d77
KH
669 if (!NILP (fontset)
670 && !BASE_FONTSET_P (fontset))
4ed46869 671 {
0d407d77
KH
672 elt = FONTSET_REF_VIA_BASE (fontset, c);
673 if (!NILP (elt))
674 {
675 /* A suitable face for C is already recorded, which means
676 that a proper font is already loaded. */
677 int face_id = XINT (elt);
4ed46869 678
0d407d77
KH
679 xassert (face_id == face->id);
680 face = FACE_FROM_ID (f, face_id);
681 return (*get_font_info_func) (f, face->font_info_id);
682 }
4ed46869 683
0d407d77 684 if (!fontname && charset == CHARSET_ASCII)
afbee0fa 685 {
0d407d77 686 elt = FONTSET_ASCII (fontset);
d5db4077 687 fontname = SDATA (XCDR (elt));
afbee0fa 688 }
afbee0fa 689 }
4ed46869 690
0d407d77
KH
691 if (!fontname)
692 /* No way to get fontname. */
693 return 0;
4ed46869 694
0d407d77 695 fontp = (*load_font_func) (f, fontname, size);
4ed46869 696 if (!fontp)
0d407d77 697 return 0;
4ed46869 698
0d407d77
KH
699 /* Fill in members (charset, vertical_centering, encoding, etc) of
700 font_info structure that are not set by (*load_font_func). */
4ed46869
KH
701 fontp->charset = charset;
702
6e1b0d8c 703 fullname = build_string (fontp->full_name);
810abb87
KH
704 fontp->vertical_centering
705 = (STRINGP (Vvertical_centering_font_regexp)
6e1b0d8c
KH
706 && (fast_string_match_ignore_case
707 (Vvertical_centering_font_regexp, fullname) >= 0));
810abb87 708
afbee0fa 709 if (fontp->encoding[1] != FONT_ENCODING_NOT_DECIDED)
4ed46869
KH
710 {
711 /* The font itself tells which code points to be used. Use this
712 encoding for all other charsets. */
713 int i;
714
715 fontp->encoding[0] = fontp->encoding[1];
467e7675 716 for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i <= MAX_CHARSET; i++)
4ed46869
KH
717 fontp->encoding[i] = fontp->encoding[1];
718 }
719 else
720 {
0d407d77 721 /* The font itself doesn't have information about encoding. */
4ed46869
KH
722 int i;
723
40292c8a
KH
724 /* By default, encoding of ASCII chars is 0 (i.e. 0x00..0x7F),
725 others is 1 (i.e. 0x80..0xFF). */
726 fontp->encoding[0] = 0;
467e7675 727 for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i <= MAX_CHARSET; i++)
4ed46869
KH
728 fontp->encoding[i] = 1;
729 /* Then override them by a specification in Vfont_encoding_alist. */
7539e11f 730 for (list = Vfont_encoding_alist; CONSP (list); list = XCDR (list))
4ed46869 731 {
7539e11f 732 elt = XCAR (list);
4ed46869 733 if (CONSP (elt)
7539e11f 734 && STRINGP (XCAR (elt)) && CONSP (XCDR (elt))
6e1b0d8c 735 && (fast_string_match_ignore_case (XCAR (elt), fullname) >= 0))
4ed46869
KH
736 {
737 Lisp_Object tmp;
738
7539e11f
KR
739 for (tmp = XCDR (elt); CONSP (tmp); tmp = XCDR (tmp))
740 if (CONSP (XCAR (tmp))
741 && ((i = get_charset_id (XCAR (XCAR (tmp))))
4ed46869 742 >= 0)
7539e11f
KR
743 && INTEGERP (XCDR (XCAR (tmp)))
744 && XFASTINT (XCDR (XCAR (tmp))) < 4)
4ed46869 745 fontp->encoding[i]
7539e11f 746 = XFASTINT (XCDR (XCAR (tmp)));
4ed46869
KH
747 }
748 }
749 }
750
de5c0f39 751 if (! fontp->font_encoder && find_ccl_program_func)
727fb790 752 (*find_ccl_program_func) (fontp);
4ed46869 753
1ff005e1
KH
754 /* If we loaded a font for a face that has fontset, record the face
755 ID in the fontset for C. */
756 if (face
757 && !NILP (fontset)
758 && !BASE_FONTSET_P (fontset))
759 FONTSET_SET (fontset, c, make_number (face->id));
4ed46869
KH
760 return fontp;
761}
762
97f4db8c
AI
763#if defined(WINDOWSNT) && defined (_MSC_VER)
764#pragma optimize("", on)
765#endif
766
0d407d77 767\f
4ed46869
KH
768/* Cache data used by fontset_pattern_regexp. The car part is a
769 pattern string containing at least one wild card, the cdr part is
770 the corresponding regular expression. */
771static Lisp_Object Vcached_fontset_data;
772
d5db4077 773#define CACHED_FONTSET_NAME (SDATA (XCAR (Vcached_fontset_data)))
7539e11f 774#define CACHED_FONTSET_REGEX (XCDR (Vcached_fontset_data))
4ed46869
KH
775
776/* If fontset name PATTERN contains any wild card, return regular
777 expression corresponding to PATTERN. */
778
0d407d77 779static Lisp_Object
4ed46869
KH
780fontset_pattern_regexp (pattern)
781 Lisp_Object pattern;
782{
d5db4077
KR
783 if (!index (SDATA (pattern), '*')
784 && !index (SDATA (pattern), '?'))
4ed46869 785 /* PATTERN does not contain any wild cards. */
1c283e35 786 return Qnil;
4ed46869
KH
787
788 if (!CONSP (Vcached_fontset_data)
d5db4077 789 || strcmp (SDATA (pattern), CACHED_FONTSET_NAME))
4ed46869
KH
790 {
791 /* We must at first update the cached data. */
d5db4077 792 char *regex = (char *) alloca (SCHARS (pattern) * 2 + 3);
4ed46869
KH
793 char *p0, *p1 = regex;
794
1c283e35
KH
795 /* Convert "*" to ".*", "?" to ".". */
796 *p1++ = '^';
d5db4077 797 for (p0 = (char *) SDATA (pattern); *p0; p0++)
4ed46869 798 {
1c283e35 799 if (*p0 == '*')
4ed46869 800 {
1c283e35
KH
801 *p1++ = '.';
802 *p1++ = '*';
4ed46869 803 }
1c283e35 804 else if (*p0 == '?')
d96d677d 805 *p1++ = '.';
1c283e35
KH
806 else
807 *p1++ = *p0;
4ed46869
KH
808 }
809 *p1++ = '$';
810 *p1++ = 0;
811
d5db4077 812 Vcached_fontset_data = Fcons (build_string (SDATA (pattern)),
4ed46869
KH
813 build_string (regex));
814 }
815
816 return CACHED_FONTSET_REGEX;
817}
818
0d407d77
KH
819/* Return ID of the base fontset named NAME. If there's no such
820 fontset, return -1. */
821
822int
823fs_query_fontset (name, regexpp)
824 Lisp_Object name;
825 int regexpp;
826{
1337ac77 827 Lisp_Object tem;
0d407d77
KH
828 int i;
829
830 name = Fdowncase (name);
831 if (!regexpp)
832 {
833 tem = Frassoc (name, Vfontset_alias_alist);
834 if (CONSP (tem) && STRINGP (XCAR (tem)))
835 name = XCAR (tem);
836 else
837 {
838 tem = fontset_pattern_regexp (name);
839 if (STRINGP (tem))
840 {
841 name = tem;
842 regexpp = 1;
843 }
844 }
845 }
846
847 for (i = 0; i < ASIZE (Vfontset_table); i++)
848 {
6e1b0d8c 849 Lisp_Object fontset, this_name;
0d407d77
KH
850
851 fontset = FONTSET_FROM_ID (i);
852 if (NILP (fontset)
853 || !BASE_FONTSET_P (fontset))
854 continue;
855
6e1b0d8c 856 this_name = FONTSET_NAME (fontset);
0d407d77 857 if (regexpp
6e1b0d8c
KH
858 ? fast_string_match (name, this_name) >= 0
859 : !strcmp (SDATA (name), SDATA (this_name)))
0d407d77
KH
860 return i;
861 }
862 return -1;
863}
864
865
727fb790 866DEFUN ("query-fontset", Fquery_fontset, Squery_fontset, 1, 2, 0,
335c5470
PJ
867 doc: /* Return the name of a fontset that matches PATTERN.
868The value is nil if there is no matching fontset.
869PATTERN can contain `*' or `?' as a wildcard
870just as X font name matching algorithm allows.
871If REGEXPP is non-nil, PATTERN is a regular expression. */)
872 (pattern, regexpp)
727fb790 873 Lisp_Object pattern, regexpp;
4ed46869 874{
0d407d77
KH
875 Lisp_Object fontset;
876 int id;
4ed46869
KH
877
878 (*check_window_system_func) ();
879
b7826503 880 CHECK_STRING (pattern);
4ed46869 881
d5db4077 882 if (SCHARS (pattern) == 0)
4ed46869
KH
883 return Qnil;
884
0d407d77
KH
885 id = fs_query_fontset (pattern, !NILP (regexpp));
886 if (id < 0)
887 return Qnil;
4ed46869 888
0d407d77
KH
889 fontset = FONTSET_FROM_ID (id);
890 return FONTSET_NAME (fontset);
4ed46869
KH
891}
892
0d407d77
KH
893/* Return a list of base fontset names matching PATTERN on frame F.
894 If SIZE is not 0, it is the size (maximum bound width) of fontsets
fc8865fc 895 to be listed. */
4ed46869
KH
896
897Lisp_Object
898list_fontsets (f, pattern, size)
899 FRAME_PTR f;
900 Lisp_Object pattern;
901 int size;
902{
1337ac77 903 Lisp_Object frame, regexp, val;
0d407d77 904 int id;
4ed46869 905
0d407d77 906 XSETFRAME (frame, f);
4ed46869 907
0d407d77 908 regexp = fontset_pattern_regexp (pattern);
4ed46869 909 val = Qnil;
4ed46869 910
0d407d77
KH
911 for (id = 0; id < ASIZE (Vfontset_table); id++)
912 {
6e1b0d8c 913 Lisp_Object fontset, name;
0d407d77
KH
914
915 fontset = FONTSET_FROM_ID (id);
916 if (NILP (fontset)
917 || !BASE_FONTSET_P (fontset)
918 || !EQ (frame, FONTSET_FRAME (fontset)))
919 continue;
6e1b0d8c 920 name = FONTSET_NAME (fontset);
0d407d77
KH
921
922 if (!NILP (regexp)
6e1b0d8c
KH
923 ? (fast_string_match (regexp, name) < 0)
924 : strcmp (SDATA (pattern), SDATA (name)))
0d407d77
KH
925 continue;
926
927 if (size)
4ed46869 928 {
0d407d77
KH
929 struct font_info *fontp;
930 fontp = FS_LOAD_FONT (f, 0, NULL, id);
931 if (!fontp || size != fontp->size)
932 continue;
4ed46869 933 }
0d407d77 934 val = Fcons (Fcopy_sequence (FONTSET_NAME (fontset)), val);
4ed46869
KH
935 }
936
937 return val;
938}
939
940DEFUN ("new-fontset", Fnew_fontset, Snew_fontset, 2, 2, 0,
335c5470
PJ
941 doc: /* Create a new fontset NAME that contains font information in FONTLIST.
942FONTLIST is an alist of charsets vs corresponding font name patterns. */)
943 (name, fontlist)
4ed46869
KH
944 Lisp_Object name, fontlist;
945{
0d407d77
KH
946 Lisp_Object fontset, elements, ascii_font;
947 Lisp_Object tem, tail, elt;
4ed46869
KH
948
949 (*check_window_system_func) ();
950
b7826503
PJ
951 CHECK_STRING (name);
952 CHECK_LIST (fontlist);
4ed46869 953
0d407d77
KH
954 name = Fdowncase (name);
955 tem = Fquery_fontset (name, Qnil);
956 if (!NILP (tem))
9af3dc47 957 error ("Fontset `%s' matches the existing fontset `%s'",
d5db4077 958 SDATA (name), SDATA (tem));
4ed46869 959
0d407d77
KH
960 /* Check the validity of FONTLIST while creating a template for
961 fontset elements. */
962 elements = ascii_font = Qnil;
7539e11f 963 for (tail = fontlist; CONSP (tail); tail = XCDR (tail))
4ed46869 964 {
0d407d77 965 int c, charset;
4ed46869 966
0d407d77 967 tem = XCAR (tail);
4ed46869 968 if (!CONSP (tem)
7539e11f 969 || (charset = get_charset_id (XCAR (tem))) < 0
41d79f4d
KH
970 || (!STRINGP (XCDR (tem)) && !CONSP (XCDR (tem))))
971 error ("Elements of fontlist must be a cons of charset and font name pattern");
0d407d77 972
41d79f4d
KH
973 tem = XCDR (tem);
974 if (STRINGP (tem))
975 tem = Fdowncase (tem);
976 else
977 tem = Fcons (Fdowncase (Fcar (tem)), Fdowncase (Fcdr (tem)));
0d407d77
KH
978 if (charset == CHARSET_ASCII)
979 ascii_font = tem;
980 else
981 {
982 c = MAKE_CHAR (charset, 0, 0);
983 elements = Fcons (Fcons (make_number (c), tem), elements);
984 }
4ed46869
KH
985 }
986
0d407d77
KH
987 if (NILP (ascii_font))
988 error ("No ASCII font in the fontlist");
4ed46869 989
0d407d77
KH
990 fontset = make_fontset (Qnil, name, Qnil);
991 FONTSET_ASCII (fontset) = Fcons (make_number (0), ascii_font);
992 for (; CONSP (elements); elements = XCDR (elements))
993 {
994 elt = XCAR (elements);
41d79f4d
KH
995 tem = XCDR (elt);
996 if (STRINGP (tem))
997 tem = font_family_registry (tem, 0);
998 tem = Fcons (XCAR (elt), tem);
0d407d77
KH
999 FONTSET_SET (fontset, XINT (XCAR (elt)), tem);
1000 }
4ed46869
KH
1001
1002 return Qnil;
1003}
1004
4ed46869 1005
0d407d77
KH
1006/* Clear all elements of FONTSET for multibyte characters. */
1007
1008static void
1009clear_fontset_elements (fontset)
1010 Lisp_Object fontset;
4ed46869 1011{
0d407d77 1012 int i;
4ed46869 1013
0d407d77
KH
1014 for (i = CHAR_TABLE_SINGLE_BYTE_SLOTS; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
1015 XCHAR_TABLE (fontset)->contents[i] = Qnil;
1016}
4ed46869 1017
4ed46869 1018
0d407d77
KH
1019/* Check validity of NAME as a fontset name and return the
1020 corresponding fontset. If not valid, signal an error.
e2b45cf9 1021 If NAME is nil, return Vdefault_fontset. */
0d407d77
KH
1022
1023static Lisp_Object
1024check_fontset_name (name)
1025 Lisp_Object name;
1026{
1027 int id;
1028
e2b45cf9 1029 if (EQ (name, Qnil))
0d407d77 1030 return Vdefault_fontset;
4ed46869 1031
b7826503 1032 CHECK_STRING (name);
0d407d77
KH
1033 id = fs_query_fontset (name, 0);
1034 if (id < 0)
d5db4077 1035 error ("Fontset `%s' does not exist", SDATA (name));
0d407d77
KH
1036 return FONTSET_FROM_ID (id);
1037}
4ed46869 1038
2f65c7b5
KH
1039/* Downcase FONTNAME or car and cdr of FONTNAME. If FONTNAME is a
1040 string, maybe change FONTNAME to (FAMILY . REGISTRY). */
1041
1042static Lisp_Object
4ce2719d 1043regularize_fontname (Lisp_Object fontname)
2f65c7b5
KH
1044{
1045 Lisp_Object family, registry;
1046
1047 if (STRINGP (fontname))
1048 return font_family_registry (Fdowncase (fontname), 0);
1049
1050 CHECK_CONS (fontname);
1051 family = XCAR (fontname);
1052 registry = XCDR (fontname);
1053 if (!NILP (family))
1054 {
1055 CHECK_STRING (family);
1056 family = Fdowncase (family);
1057 }
1058 if (!NILP (registry))
1059 {
1060 CHECK_STRING (registry);
1061 registry = Fdowncase (registry);
1062 }
1063 return Fcons (family, registry);
1064}
1065
bad421f7 1066DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 4, 0,
335c5470
PJ
1067 doc: /* Modify fontset NAME to use FONTNAME for CHARACTER.
1068
0134e6da 1069If NAME is nil, modify the default fontset.
335c5470
PJ
1070CHARACTER may be a cons; (FROM . TO), where FROM and TO are
1071non-generic characters. In that case, use FONTNAME
1072for all characters in the range FROM and TO (inclusive).
f83d92b2 1073CHARACTER may be a charset. In that case, use FONTNAME
335c5470
PJ
1074for all character in the charsets.
1075
1076FONTNAME may be a cons; (FAMILY . REGISTRY), where FAMILY is a family
fc8865fc 1077name of a font, REGISTRY is a registry name of a font. */)
335c5470 1078 (name, character, fontname, frame)
4ea5775b 1079 Lisp_Object name, character, fontname, frame;
0d407d77
KH
1080{
1081 Lisp_Object fontset, elt;
1082 Lisp_Object realized;
1083 int from, to;
1084 int id;
1085
1086 fontset = check_fontset_name (name);
1087
4ea5775b 1088 if (CONSP (character))
0d407d77
KH
1089 {
1090 /* CH should be (FROM . TO) where FROM and TO are non-generic
1091 characters. */
b7826503
PJ
1092 CHECK_NUMBER_CAR (character);
1093 CHECK_NUMBER_CDR (character);
4ea5775b
KH
1094 from = XINT (XCAR (character));
1095 to = XINT (XCDR (character));
0d407d77 1096 if (!char_valid_p (from, 0) || !char_valid_p (to, 0))
7c402969 1097 error ("Character range should be by non-generic characters");
0d407d77
KH
1098 if (!NILP (name)
1099 && (SINGLE_BYTE_CHAR_P (from) || SINGLE_BYTE_CHAR_P (to)))
1100 error ("Can't change font for a single byte character");
1101 }
0890801b
KH
1102 else if (SYMBOLP (character))
1103 {
1104 elt = Fget (character, Qcharset);
1105 if (!VECTORP (elt) || ASIZE (elt) < 1 || !NATNUMP (AREF (elt, 0)))
20cddf4e 1106 error ("Invalid charset: %s", SDATA (SYMBOL_NAME (character)));
0890801b
KH
1107 from = MAKE_CHAR (XINT (AREF (elt, 0)), 0, 0);
1108 to = from;
1109 }
0d407d77 1110 else
4ed46869 1111 {
b7826503 1112 CHECK_NUMBER (character);
4ea5775b 1113 from = XINT (character);
0d407d77
KH
1114 to = from;
1115 }
1116 if (!char_valid_p (from, 1))
1117 invalid_character (from);
1118 if (SINGLE_BYTE_CHAR_P (from))
1119 error ("Can't change font for a single byte character");
1120 if (from < to)
1121 {
1122 if (!char_valid_p (to, 1))
1123 invalid_character (to);
1124 if (SINGLE_BYTE_CHAR_P (to))
1125 error ("Can't change font for a single byte character");
1126 }
4ed46869 1127
0d407d77
KH
1128 /* The arg FRAME is kept for backward compatibility. We only check
1129 the validity. */
1130 if (!NILP (frame))
b7826503 1131 CHECK_LIVE_FRAME (frame);
4ed46869 1132
4ce2719d 1133 elt = Fcons (make_number (from), regularize_fontname (fontname));
0d407d77
KH
1134 for (; from <= to; from++)
1135 FONTSET_SET (fontset, from, elt);
1136 Foptimize_char_table (fontset);
4ed46869 1137
0d407d77
KH
1138 /* If there's a realized fontset REALIZED whose parent is FONTSET,
1139 clear all the elements of REALIZED and free all multibyte faces
1140 whose fontset is REALIZED. This way, the specified character(s)
1141 are surely redisplayed by a correct font. */
1142 for (id = 0; id < ASIZE (Vfontset_table); id++)
1143 {
1144 realized = AREF (Vfontset_table, id);
1145 if (!NILP (realized)
1146 && !BASE_FONTSET_P (realized)
1147 && EQ (FONTSET_BASE (realized), fontset))
4ed46869 1148 {
0d407d77
KH
1149 FRAME_PTR f = XFRAME (FONTSET_FRAME (realized));
1150 clear_fontset_elements (realized);
1151 free_realized_multibyte_face (f, id);
4ed46869 1152 }
0d407d77 1153 }
4ed46869
KH
1154
1155 return Qnil;
1156}
1157
1158DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
335c5470
PJ
1159 doc: /* Return information about a font named NAME on frame FRAME.
1160If FRAME is omitted or nil, use the selected frame.
1161The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,
1162 HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
1163where
1164 OPENED-NAME is the name used for opening the font,
1165 FULL-NAME is the full name of the font,
1166 SIZE is the maximum bound width of the font,
1167 HEIGHT is the height of the font,
1168 BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
1169 RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
1170 how to compose characters.
1171If the named font is not yet loaded, return nil. */)
1172 (name, frame)
4ed46869
KH
1173 Lisp_Object name, frame;
1174{
1175 FRAME_PTR f;
1176 struct font_info *fontp;
1177 Lisp_Object info;
1178
1179 (*check_window_system_func) ();
1180
b7826503 1181 CHECK_STRING (name);
0d407d77 1182 name = Fdowncase (name);
4ed46869 1183 if (NILP (frame))
18f39d0e 1184 frame = selected_frame;
b7826503 1185 CHECK_LIVE_FRAME (frame);
18f39d0e 1186 f = XFRAME (frame);
4ed46869
KH
1187
1188 if (!query_font_func)
1189 error ("Font query function is not supported");
1190
d5db4077 1191 fontp = (*query_font_func) (f, SDATA (name));
4ed46869
KH
1192 if (!fontp)
1193 return Qnil;
1194
0d407d77 1195 info = Fmake_vector (make_number (7), Qnil);
4ed46869
KH
1196
1197 XVECTOR (info)->contents[0] = build_string (fontp->name);
1198 XVECTOR (info)->contents[1] = build_string (fontp->full_name);
0d407d77
KH
1199 XVECTOR (info)->contents[2] = make_number (fontp->size);
1200 XVECTOR (info)->contents[3] = make_number (fontp->height);
1201 XVECTOR (info)->contents[4] = make_number (fontp->baseline_offset);
1202 XVECTOR (info)->contents[5] = make_number (fontp->relative_compose);
1203 XVECTOR (info)->contents[6] = make_number (fontp->default_ascent);
4ed46869
KH
1204
1205 return info;
1206}
1207
1ff005e1 1208
e5bc082b
KH
1209/* Return a cons (FONT-NAME . GLYPH-CODE).
1210 FONT-NAME is the font name for the character at POSITION in the current
1ff005e1 1211 buffer. This is computed from all the text properties and overlays
cf14fd6e
KH
1212 that apply to POSITION. POSTION may be nil, in which case,
1213 FONT-NAME is the font name for display the character CH with the
1214 default face.
1215
e5bc082b
KH
1216 GLYPH-CODE is the glyph code in the font to use for the character.
1217
1218 If the 2nd optional arg CH is non-nil, it is a character to check
1219 the font instead of the character at POSITION.
1220
1221 It returns nil in the following cases:
1ff005e1
KH
1222
1223 (1) The window system doesn't have a font for the character (thus
1224 it is displayed by an empty box).
1225
1226 (2) The character code is invalid.
1227
cf14fd6e
KH
1228 (3) If POSITION is not nil, and the current buffer is not displayed
1229 in any window.
1ff005e1
KH
1230
1231 In addition, the returned font name may not take into account of
1232 such redisplay engine hooks as what used in jit-lock-mode if
1233 POSITION is currently not visible. */
1234
1235
e5bc082b 1236DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
335c5470 1237 doc: /* For internal use only. */)
e5bc082b
KH
1238 (position, ch)
1239 Lisp_Object position, ch;
1ff005e1
KH
1240{
1241 int pos, pos_byte, dummy;
1242 int face_id;
e5bc082b 1243 int c, code;
1ff005e1
KH
1244 struct frame *f;
1245 struct face *face;
1246
cf14fd6e 1247 if (NILP (position))
e5bc082b
KH
1248 {
1249 CHECK_NATNUM (ch);
1250 c = XINT (ch);
cf14fd6e
KH
1251 f = XFRAME (selected_frame);
1252 face_id = DEFAULT_FACE_ID;
1253 }
1254 else
1255 {
1256 Lisp_Object window;
1257 struct window *w;
1258
1259 CHECK_NUMBER_COERCE_MARKER (position);
1260 pos = XINT (position);
1261 if (pos < BEGV || pos >= ZV)
1262 args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
1263 pos_byte = CHAR_TO_BYTE (pos);
1264 if (NILP (ch))
1265 c = FETCH_CHAR (pos_byte);
1266 else
1267 {
1268 CHECK_NATNUM (ch);
1269 c = XINT (ch);
1270 }
1271 window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
1272 if (NILP (window))
1273 return Qnil;
1274 w = XWINDOW (window);
1275 f = XFRAME (w->frame);
1276 face_id = face_at_buffer_position (w, pos, -1, -1, &dummy, pos + 100, 0);
e5bc082b 1277 }
1ff005e1
KH
1278 if (! CHAR_VALID_P (c, 0))
1279 return Qnil;
1ff005e1
KH
1280 face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c);
1281 face = FACE_FROM_ID (f, face_id);
e5bc082b
KH
1282 if (! face->font || ! face->font_name)
1283 return Qnil;
1284
1285 {
1286 struct font_info *fontp = (*get_font_info_func) (f, face->font_info_id);
1287 XChar2b char2b;
1288 int c1, c2, charset;
1289
1290 SPLIT_CHAR (c, charset, c1, c2);
1291 if (c2 > 0)
1292 STORE_XCHAR2B (&char2b, c1, c2);
1293 else
1294 STORE_XCHAR2B (&char2b, 0, c1);
1295 rif->encode_char (c, &char2b, fontp, NULL);
1296 code = (XCHAR2B_BYTE1 (&char2b) << 8) | XCHAR2B_BYTE2 (&char2b);
1297 }
1298 return Fcons (build_string (face->font_name), make_number (code));
1ff005e1
KH
1299}
1300
1301
e2b45cf9
KH
1302/* Called from Ffontset_info via map_char_table on each leaf of
1303 fontset. ARG is a copy of the default fontset. The current leaf
1304 is indexed by CHARACTER and has value ELT. This function override
1305 the copy by ELT if ELT is not nil. */
1306
1307static void
1308override_font_info (fontset, character, elt)
1309 Lisp_Object fontset, character, elt;
1310{
1311 if (! NILP (elt))
1312 Faset (fontset, character, elt);
1313}
1314
1ff005e1
KH
1315/* Called from Ffontset_info via map_char_table on each leaf of
1316 fontset. ARG is a list (LAST FONT-INFO ...), where LAST is `(last
1317 ARG)' and FONT-INFOs have this form:
1318 (CHAR FONT-SPEC) or ((FROM . TO) FONT-SPEC)
1319 The current leaf is indexed by CHARACTER and has value ELT. This
1320 function add the information of the current leaf to ARG by
e2b45cf9 1321 appending a new element or modifying the last element. */
1ff005e1
KH
1322
1323static void
1324accumulate_font_info (arg, character, elt)
1325 Lisp_Object arg, character, elt;
1326{
1337ac77 1327 Lisp_Object last, last_char, last_elt;
1ff005e1 1328
11d9bd93
KH
1329 if (!CONSP (elt) && !SINGLE_BYTE_CHAR_P (XINT (character)))
1330 elt = FONTSET_REF (Vdefault_fontset, XINT (character));
1ff005e1
KH
1331 if (!CONSP (elt))
1332 return;
1333 last = XCAR (arg);
1334 last_char = XCAR (XCAR (last));
1335 last_elt = XCAR (XCDR (XCAR (last)));
1336 elt = XCDR (elt);
1337 if (!NILP (Fequal (elt, last_elt)))
1338 {
1339 int this_charset = CHAR_CHARSET (XINT (character));
1340
1341 if (CONSP (last_char)) /* LAST_CHAR == (FROM . TO) */
1342 {
1343 if (this_charset == CHAR_CHARSET (XINT (XCAR (last_char))))
1344 {
f3fbd155 1345 XSETCDR (last_char, character);
1ff005e1
KH
1346 return;
1347 }
1348 }
11d9bd93
KH
1349 else if (XINT (last_char) == XINT (character))
1350 return;
1351 else if (this_charset == CHAR_CHARSET (XINT (last_char)))
1ff005e1 1352 {
f3fbd155 1353 XSETCAR (XCAR (last), Fcons (last_char, character));
11d9bd93 1354 return;
1ff005e1
KH
1355 }
1356 }
f3fbd155
KR
1357 XSETCDR (last, Fcons (Fcons (character, Fcons (elt, Qnil)), Qnil));
1358 XSETCAR (arg, XCDR (last));
1ff005e1
KH
1359}
1360
1361
4ed46869 1362DEFUN ("fontset-info", Ffontset_info, Sfontset_info, 1, 2, 0,
335c5470 1363 doc: /* Return information about a fontset named NAME on frame FRAME.
0134e6da 1364If NAME is nil, return information about the default fontset.
335c5470
PJ
1365The value is a vector:
1366 [ SIZE HEIGHT ((CHARSET-OR-RANGE FONT-SPEC OPENED ...) ...) ],
1367where,
1368 SIZE is the maximum bound width of ASCII font in the fontset,
1369 HEIGHT is the maximum bound height of ASCII font in the fontset,
1370 CHARSET-OR-RANGE is a charset, a character (may be a generic character)
1371 or a cons of two characters specifying the range of characters.
1372 FONT-SPEC is a fontname pattern string or a cons (FAMILY . REGISTRY),
1373 where FAMILY is a `FAMILY' field of a XLFD font name,
fc8865fc
PJ
1374 REGISTRY is a `CHARSET_REGISTRY' field of a XLFD font name.
1375 FAMILY may contain a `FOUNDRY' field at the head.
335c5470
PJ
1376 REGISTRY may contain a `CHARSET_ENCODING' field at the tail.
1377 OPENEDs are names of fonts actually opened.
1378If the ASCII font is not yet opened, SIZE and HEIGHT are 0.
1379If FRAME is omitted, it defaults to the currently selected frame. */)
1380 (name, frame)
4ed46869
KH
1381 Lisp_Object name, frame;
1382{
1ff005e1 1383 Lisp_Object fontset;
4ed46869 1384 FRAME_PTR f;
1ff005e1
KH
1385 Lisp_Object indices[3];
1386 Lisp_Object val, tail, elt;
1387 Lisp_Object *realized;
a921395d 1388 struct font_info *fontp = NULL;
1ff005e1 1389 int n_realized = 0;
4ed46869 1390 int i;
fc8865fc 1391
4ed46869
KH
1392 (*check_window_system_func) ();
1393
0d407d77
KH
1394 fontset = check_fontset_name (name);
1395
4ed46869 1396 if (NILP (frame))
18f39d0e 1397 frame = selected_frame;
b7826503 1398 CHECK_LIVE_FRAME (frame);
18f39d0e 1399 f = XFRAME (frame);
4ed46869 1400
11d9bd93 1401 /* Recode realized fontsets whose base is FONTSET in the table
1ff005e1
KH
1402 `realized'. */
1403 realized = (Lisp_Object *) alloca (sizeof (Lisp_Object)
1404 * ASIZE (Vfontset_table));
0d407d77
KH
1405 for (i = 0; i < ASIZE (Vfontset_table); i++)
1406 {
1ff005e1
KH
1407 elt = FONTSET_FROM_ID (i);
1408 if (!NILP (elt)
1409 && EQ (FONTSET_BASE (elt), fontset))
1410 realized[n_realized++] = elt;
0d407d77 1411 }
4ed46869 1412
e2b45cf9
KH
1413 if (! EQ (fontset, Vdefault_fontset))
1414 {
1415 /* Merge FONTSET onto the default fontset. */
1416 val = Fcopy_sequence (Vdefault_fontset);
6117a9cd 1417 map_char_table (override_font_info, Qnil, fontset, fontset, val, 0, indices);
e2b45cf9
KH
1418 fontset = val;
1419 }
1420
1ff005e1
KH
1421 /* Accumulate information of the fontset in VAL. The format is
1422 (LAST FONT-INFO FONT-INFO ...), where FONT-INFO is (CHAR-OR-RANGE
1423 FONT-SPEC). See the comment for accumulate_font_info for the
1424 detail. */
1425 val = Fcons (Fcons (make_number (0),
1426 Fcons (XCDR (FONTSET_ASCII (fontset)), Qnil)),
0d407d77 1427 Qnil);
1ff005e1 1428 val = Fcons (val, val);
6117a9cd 1429 map_char_table (accumulate_font_info, Qnil, fontset, fontset, val, 0, indices);
1ff005e1
KH
1430 val = XCDR (val);
1431
1432 /* For each FONT-INFO, if CHAR_OR_RANGE (car part) is a generic
11d9bd93 1433 character for a charset, replace it with the charset symbol. If
1ff005e1
KH
1434 fonts are opened for FONT-SPEC, append the names of the fonts to
1435 FONT-SPEC. */
1436 for (tail = val; CONSP (tail); tail = XCDR (tail))
0d407d77 1437 {
1ff005e1
KH
1438 int c;
1439 elt = XCAR (tail);
1440 if (INTEGERP (XCAR (elt)))
0d407d77 1441 {
1ff005e1
KH
1442 int charset, c1, c2;
1443 c = XINT (XCAR (elt));
1444 SPLIT_CHAR (c, charset, c1, c2);
1445 if (c1 == 0)
f3fbd155 1446 XSETCAR (elt, CHARSET_SYMBOL (charset));
1ff005e1
KH
1447 }
1448 else
1449 c = XINT (XCAR (XCAR (elt)));
1450 for (i = 0; i < n_realized; i++)
1451 {
1452 Lisp_Object face_id, font;
0d407d77
KH
1453 struct face *face;
1454
1ff005e1
KH
1455 face_id = FONTSET_REF_VIA_BASE (realized[i], c);
1456 if (INTEGERP (face_id))
0d407d77 1457 {
1ff005e1 1458 face = FACE_FROM_ID (f, XINT (face_id));
dbcf3c03 1459 if (face && face->font && face->font_name)
1ff005e1
KH
1460 {
1461 font = build_string (face->font_name);
1462 if (NILP (Fmember (font, XCDR (XCDR (elt)))))
f3fbd155 1463 XSETCDR (XCDR (elt), Fcons (font, XCDR (XCDR (elt))));
1ff005e1 1464 }
0d407d77 1465 }
0d407d77
KH
1466 }
1467 }
a921395d
KH
1468
1469 elt = Fcdr (Fcdr (Fassq (CHARSET_SYMBOL (CHARSET_ASCII), val)));
1470 if (CONSP (elt))
1471 {
1472 elt = XCAR (elt);
d5db4077 1473 fontp = (*query_font_func) (f, SDATA (elt));
a921395d
KH
1474 }
1475 val = Fmake_vector (make_number (3), val);
1476 AREF (val, 0) = fontp ? make_number (fontp->size) : make_number (0);
1477 AREF (val, 1) = fontp ? make_number (fontp->height) : make_number (0);
1478 return val;
4ed46869
KH
1479}
1480
0d407d77 1481DEFUN ("fontset-font", Ffontset_font, Sfontset_font, 2, 2, 0,
335c5470 1482 doc: /* Return a font name pattern for character CH in fontset NAME.
0134e6da 1483If NAME is nil, find a font name pattern in the default fontset. */)
335c5470 1484 (name, ch)
0d407d77
KH
1485 Lisp_Object name, ch;
1486{
1337ac77 1487 int c;
0d407d77
KH
1488 Lisp_Object fontset, elt;
1489
1490 fontset = check_fontset_name (name);
1491
b7826503 1492 CHECK_NUMBER (ch);
0d407d77
KH
1493 c = XINT (ch);
1494 if (!char_valid_p (c, 1))
1495 invalid_character (c);
1496
1497 elt = FONTSET_REF (fontset, c);
1498 if (CONSP (elt))
1499 elt = XCDR (elt);
1500
1501 return elt;
1502}
0d407d77
KH
1503
1504DEFUN ("fontset-list", Ffontset_list, Sfontset_list, 0, 0, 0,
335c5470
PJ
1505 doc: /* Return a list of all defined fontset names. */)
1506 ()
0d407d77
KH
1507{
1508 Lisp_Object fontset, list;
1509 int i;
1510
1511 list = Qnil;
1512 for (i = 0; i < ASIZE (Vfontset_table); i++)
1513 {
1514 fontset = FONTSET_FROM_ID (i);
1515 if (!NILP (fontset)
1516 && BASE_FONTSET_P (fontset))
1517 list = Fcons (FONTSET_NAME (fontset), list);
1518 }
1ff005e1 1519
0d407d77
KH
1520 return list;
1521}
1522
2f65c7b5
KH
1523DEFUN ("set-overriding-fontspec-internal", Fset_overriding_fontspec_internal,
1524 Sset_overriding_fontspec_internal, 1, 1, 0,
1525 doc: /* Internal use only.
1526
1527FONTLIST is an alist of TARGET vs FONTNAME, where TARGET is a charset
1528or a char-table, FONTNAME have the same meanings as in
1529`set-fontset-font'.
1530
1531It overrides the font specifications for each TARGET in the default
1532fontset by the corresponding FONTNAME.
1533
1534If TARGET is a charset, targets are all characters in the charset. If
1535TARGET is a char-table, targets are characters whose value is non-nil
1536in the table.
1537
1538It is intended that this function is called only from
1539`set-language-environment'. */)
1540 (fontlist)
1541 Lisp_Object fontlist;
1542{
1543 Lisp_Object tail;
1544
1545 fontlist = Fcopy_sequence (fontlist);
1546 /* Now FONTLIST is ((TARGET . FONTNAME) ...). Reform it to ((TARGET
1547 nil nil nil FONTSPEC) ...), where TARGET is a charset-id or a
1548 char-table. */
1549 for (tail = fontlist; CONSP (tail); tail = XCDR (tail))
1550 {
1551 Lisp_Object elt, target;
1552
1553 elt = XCAR (tail);
1554 target = Fcar (elt);
4ce2719d 1555 elt = Fcons (Qnil, regularize_fontname (Fcdr (elt)));
2f65c7b5
KH
1556 if (! CHAR_TABLE_P (target))
1557 {
1558 int charset, c;
1559
1560 CHECK_SYMBOL (target);
1561 charset = get_charset_id (target);
1562 if (charset < 0)
1563 error ("Invalid charset %s", SDATA (SYMBOL_NAME (target)));
1564 target = make_number (charset);
1565 c = MAKE_CHAR (charset, 0, 0);
1566 XSETCAR (elt, make_number (c));
1567 }
1568 elt = Fcons (target, Fcons (Qnil, Fcons (Qnil, elt)));
1569 XSETCAR (tail, elt);
1570 }
1571 Voverriding_fontspec_alist = fontlist;
1572 clear_face_cache (0);
1573 ++windows_or_buffers_changed;
1574 return Qnil;
1575}
1576
dfcf069d 1577void
4ed46869
KH
1578syms_of_fontset ()
1579{
4ed46869
KH
1580 if (!load_font_func)
1581 /* Window system initializer should have set proper functions. */
1582 abort ();
1583
6a7e6d80 1584 Qfontset = intern ("fontset");
4ed46869 1585 staticpro (&Qfontset);
0d407d77 1586 Fput (Qfontset, Qchar_table_extra_slots, make_number (3));
4ed46869
KH
1587
1588 Vcached_fontset_data = Qnil;
1589 staticpro (&Vcached_fontset_data);
1590
0d407d77
KH
1591 Vfontset_table = Fmake_vector (make_number (32), Qnil);
1592 staticpro (&Vfontset_table);
0d407d77
KH
1593
1594 Vdefault_fontset = Fmake_char_table (Qfontset, Qnil);
1595 staticpro (&Vdefault_fontset);
1ff005e1
KH
1596 FONTSET_ID (Vdefault_fontset) = make_number (0);
1597 FONTSET_NAME (Vdefault_fontset)
1598 = build_string ("-*-*-*-*-*-*-*-*-*-*-*-*-fontset-default");
e0f712ba 1599#if defined (MAC_OS)
1a578e9b
AC
1600 FONTSET_ASCII (Vdefault_fontset)
1601 = Fcons (make_number (0),
f00691a3 1602 build_string ("-apple-monaco-medium-r-*--*-120-*-*-*-*-mac-roman"));
82d9a3b9
JR
1603#elif defined (WINDOWSNT)
1604 FONTSET_ASCII (Vdefault_fontset)
1605 = Fcons (make_number (0),
842c80a3 1606 build_string ("-*-courier new-normal-r-*-*-*-100-*-*-*-*-iso8859-1"));
1a578e9b 1607#else
0d407d77 1608 FONTSET_ASCII (Vdefault_fontset)
afc125e1
KH
1609 = Fcons (make_number (0),
1610 build_string ("-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1"));
1a578e9b 1611#endif
1ff005e1
KH
1612 AREF (Vfontset_table, 0) = Vdefault_fontset;
1613 next_fontset_id = 1;
4ed46869 1614
2f65c7b5
KH
1615 Voverriding_fontspec_alist = Qnil;
1616 staticpro (&Voverriding_fontspec_alist);
1617
4ed46869 1618 DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist,
335c5470
PJ
1619 doc: /* Alist of fontname patterns vs corresponding encoding info.
1620Each element looks like (REGEXP . ENCODING-INFO),
1621 where ENCODING-INFO is an alist of CHARSET vs ENCODING.
1622ENCODING is one of the following integer values:
1623 0: code points 0x20..0x7F or 0x2020..0x7F7F are used,
1624 1: code points 0xA0..0xFF or 0xA0A0..0xFFFF are used,
1625 2: code points 0x20A0..0x7FFF are used,
1626 3: code points 0xA020..0xFF7F are used. */);
4ed46869 1627 Vfont_encoding_alist = Qnil;
77c49b4c
KH
1628 Vfont_encoding_alist
1629 = Fcons (Fcons (build_string ("JISX0201"),
1630 Fcons (Fcons (intern ("latin-jisx0201"), make_number (0)),
1631 Qnil)),
1632 Vfont_encoding_alist);
1633 Vfont_encoding_alist
1634 = Fcons (Fcons (build_string ("ISO8859-1"),
1635 Fcons (Fcons (intern ("ascii"), make_number (0)),
1636 Qnil)),
1637 Vfont_encoding_alist);
4ed46869 1638
6a7e6d80 1639 DEFVAR_LISP ("use-default-ascent", &Vuse_default_ascent,
335c5470
PJ
1640 doc: /* Char table of characters whose ascent values should be ignored.
1641If an entry for a character is non-nil, the ascent value of the glyph
1642is assumed to be what specified by _MULE_DEFAULT_ASCENT property of a font.
1643
1644This affects how a composite character which contains
1645such a character is displayed on screen. */);
2aeafb78
KH
1646 Vuse_default_ascent = Qnil;
1647
1648 DEFVAR_LISP ("ignore-relative-composition", &Vignore_relative_composition,
335c5470
PJ
1649 doc: /* Char table of characters which is not composed relatively.
1650If an entry for a character is non-nil, a composition sequence
1651which contains that character is displayed so that
1652the glyph of that character is put without considering
1653an ascent and descent value of a previous character. */);
810abb87 1654 Vignore_relative_composition = Qnil;
6a7e6d80 1655
01d4b817 1656 DEFVAR_LISP ("alternate-fontname-alist", &Valternate_fontname_alist,
335c5470
PJ
1657 doc: /* Alist of fontname vs list of the alternate fontnames.
1658When a specified font name is not found, the corresponding
1659alternate fontnames (if any) are tried instead. */);
01d4b817 1660 Valternate_fontname_alist = Qnil;
8c83e4f9 1661
1c283e35 1662 DEFVAR_LISP ("fontset-alias-alist", &Vfontset_alias_alist,
335c5470 1663 doc: /* Alist of fontset names vs the aliases. */);
1ff005e1
KH
1664 Vfontset_alias_alist = Fcons (Fcons (FONTSET_NAME (Vdefault_fontset),
1665 build_string ("fontset-default")),
1666 Qnil);
1c283e35 1667
810abb87
KH
1668 DEFVAR_LISP ("vertical-centering-font-regexp",
1669 &Vvertical_centering_font_regexp,
335c5470
PJ
1670 doc: /* *Regexp matching font names that require vertical centering on display.
1671When a character is displayed with such fonts, the character is displayed
fc8865fc 1672at the vertical center of lines. */);
810abb87
KH
1673 Vvertical_centering_font_regexp = Qnil;
1674
4ed46869
KH
1675 defsubr (&Squery_fontset);
1676 defsubr (&Snew_fontset);
1677 defsubr (&Sset_fontset_font);
1678 defsubr (&Sfont_info);
1ff005e1 1679 defsubr (&Sinternal_char_font);
4ed46869 1680 defsubr (&Sfontset_info);
0d407d77
KH
1681 defsubr (&Sfontset_font);
1682 defsubr (&Sfontset_list);
2f65c7b5 1683 defsubr (&Sset_overriding_fontspec_internal);
4ed46869 1684}
ab5796a9
MB
1685
1686/* arch-tag: ea861585-2f5f-4e5b-9849-d04a9c3a3537
1687 (do not change this comment) */