fontset.c 71 KB
Newer Older
Karl Heuer's avatar
Karl Heuer committed
1
/* Fontset handler.
Glenn Morris's avatar
Glenn Morris committed
2
   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
3
     Free Software Foundation, Inc.
Kenichi Handa's avatar
Kenichi Handa committed
4
   Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
Glenn Morris's avatar
Glenn Morris committed
5
     2005, 2006, 2007, 2008
Kenichi Handa's avatar
Kenichi Handa committed
6 7
     National Institute of Advanced Industrial Science and Technology (AIST)
     Registration Number H14PRO021
Kenichi Handa's avatar
Kenichi Handa committed
8
   Copyright (C) 2003, 2006
Kenichi Handa's avatar
Kenichi Handa committed
9 10
     National Institute of Advanced Industrial Science and Technology (AIST)
     Registration Number H13PRO009
11
 
Karl Heuer's avatar
Karl Heuer committed
12 13 14 15
This file is part of GNU Emacs.

GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
16
the Free Software Foundation; either version 3, or (at your option)
Karl Heuer's avatar
Karl Heuer committed
17
any later version.
Karl Heuer's avatar
Karl Heuer committed
18

Karl Heuer's avatar
Karl Heuer committed
19 20 21 22
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
Karl Heuer's avatar
Karl Heuer committed
23

Karl Heuer's avatar
Karl Heuer committed
24 25
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING.  If not, write to
Lute Kamstra's avatar
Lute Kamstra committed
26 27
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.  */
Karl Heuer's avatar
Karl Heuer committed
28

29 30
/* #define FONTSET_DEBUG */

Karl Heuer's avatar
Karl Heuer committed
31
#include <config.h>
32 33 34 35 36

#ifdef FONTSET_DEBUG
#include <stdio.h>
#endif

Karl Heuer's avatar
Karl Heuer committed
37
#include "lisp.h"
Kenichi Handa's avatar
Kenichi Handa committed
38
#include "blockinput.h"
Kenichi Handa's avatar
Kenichi Handa committed
39
#include "buffer.h"
Kenichi Handa's avatar
Kenichi Handa committed
40
#include "character.h"
Karl Heuer's avatar
Karl Heuer committed
41 42
#include "charset.h"
#include "ccl.h"
43
#include "keyboard.h"
Karl Heuer's avatar
Karl Heuer committed
44
#include "frame.h"
45
#include "dispextern.h"
Kenichi Handa's avatar
Kenichi Handa committed
46
#include "intervals.h"
47
#include "fontset.h"
48
#include "window.h"
Kenichi Handa's avatar
Kenichi Handa committed
49 50 51 52 53 54 55 56 57
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#endif
#ifdef WINDOWSNT
#include "w32term.h"
#endif
#ifdef MAC_OS
#include "macterm.h"
#endif
58
#include "termhooks.h"
59

Kenichi Handa's avatar
Kenichi Handa committed
60 61
#include "font.h"

62
#undef xassert
Kenichi Handa's avatar
Kenichi Handa committed
63
#ifdef FONTSET_DEBUG
64 65 66
#define xassert(X)	do {if (!(X)) abort ();} while (0)
#undef INLINE
#define INLINE
Kenichi Handa's avatar
Kenichi Handa committed
67 68 69
#else   /* not FONTSET_DEBUG */
#define xassert(X)	(void) 0
#endif	/* not FONTSET_DEBUG */
70

Dave Love's avatar
Dave Love committed
71
EXFUN (Fclear_face_cache, 1);
72 73 74 75

/* FONTSET

   A fontset is a collection of font related information to give
76 77 78 79 80 81 82 83 84 85 86 87 88 89
   similar appearance (style, etc) of characters.  A fontset has two
   roles.  One is to use for the frame parameter `font' as if it is an
   ASCII font.  In that case, Emacs uses the font specified for
   `ascii' script for the frame's default font.

   Another role, the more important one, is to provide information
   about which font to use for each non-ASCII character.

   There are two kinds of fontsets; base and realized.  A base fontset
   is created by `new-fontset' from Emacs Lisp explicitly.  A realized
   fontset is created implicitly when a face is realized for ASCII
   characters.  A face is also realized for non-ASCII characters based
   on an ASCII face.  All of non-ASCII faces based on the same ASCII
   face share the same realized fontset.
Kenichi Handa's avatar
Kenichi Handa committed
90

Kenichi Handa's avatar
Kenichi Handa committed
91 92
   A fontset object is implemented by a char-table whose default value
   and parent are always nil.
93

94 95 96
   An element of a base fontset is a vector of FONT-DEFs which itself
   is a vector [ FONT-SPEC ENCODING REPERTORY ].

97 98
   FONT-SPEC is a font-spec created by `font-spec' or
	( FAMILY . REGISTRY )
Kenichi Handa's avatar
Kenichi Handa committed
99
   or
100
	FONT-NAME
101
   where FAMILY, REGISTRY, and FONT-NAME are strings.
102

103 104
   ENCODING is a charset ID that can convert characters to glyph codes
   of the corresponding font.
105

106 107 108 109 110
   REPERTORY is a charset ID, a char-table, or nil.  If REPERTORY is a
   charset ID, the repertory of the charset exactly matches with that
   of the font.  If REPERTORY is a char-table, all characters who have
   a non-nil value in the table are supported.  If REPERTORY is nil,
   we consult with the font itself to get the repertory.
111 112

   ENCODING and REPERTORY are extracted from the variable
113
   Vfont_encoding_alist by using a font name generated from FONT-SPEC
114
   (if it is a vector) or FONT-NAME as a matching target.
115 116 117


   An element of a realized fontset is nil or t, or has this form:
118

119 120
	[CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID PREFERRED-FAMILY
	 RFONT-DEF0 RFONT-DEF1 ...].
121

122
   RFONT-DEFn (i.e. Realized FONT-DEF) has this form:
123

124
	[ FACE-ID FONT-INDEX FONT-DEF OPENED-FONT-NAME ]
125

126
   RFONT-DEFn is automatically reordered by the current charset
127
   priority list.
128

129 130
   The value nil means that we have not yet generated the above vector
   from the base of the fontset.
131

132 133
   The value t means that no font is available for the corresponding
   range of characters.
134 135


Kenichi Handa's avatar
Kenichi Handa committed
136
   A fontset has 9 extra slots.
137

138
   The 1st slot: the ID number of the fontset
139

140 141 142
   The 2nd slot:
	base: the name of the fontset
	realized: nil
143

144
   The 3rd slot:
145
	base: nil
146
	realized: the base fontset
Kenichi Handa's avatar
Kenichi Handa committed
147

148 149 150
   The 4th slot:
	base: nil
	realized: the frame that the fontset belongs to
151

152 153 154
   The 5th slot:
	base: the font name for ASCII characters
	realized: nil
155

156 157 158 159
   The 6th slot:
	base: nil
	realized: the ID number of a face to use for characters that
		  has no font in a realized fontset.
160

161 162 163 164 165
   The 7th slot:
	base: nil
	realized: Alist of font index vs the corresponding repertory
	char-table.
	
166 167 168 169
   The 8th slot:
	base: nil
	realized: If the base is not the default fontset, a fontset
	realized from the default fontset, else nil.
170

Kenichi Handa's avatar
Kenichi Handa committed
171
   The 9th slot:
172 173
	base: Same as element value (but for fallback fonts).
	realized: Likewise.
Kenichi Handa's avatar
Kenichi Handa committed
174

175
   All fontsets are recorded in the vector Vfontset_table.
176 177 178 179


   DEFAULT FONTSET

180 181 182 183
   There's a special base fontset named `default fontset' which
   defines the default font specifications.  When a base fontset
   doesn't specify a font for a specific character, the corresponding
   value in the default fontset is used.
184

185 186
   The parent of a realized fontset created for such a face that has
   no fontset is the default fontset.
187 188 189 190


   These structures are hidden from the other codes than this file.
   The other codes handle fontsets only by their ID numbers.  They
Kenichi Handa's avatar
Kenichi Handa committed
191 192
   usually use the variable name `fontset' for IDs.  But, in this
   file, we always use varialbe name `id' for IDs, and name `fontset'
193
   for an actual fontset object, i.e., char-table.
194 195 196 197 198 199

*/

/********** VARIABLES and FUNCTION PROTOTYPES **********/

extern Lisp_Object Qfont;
200 201
static Lisp_Object Qfontset;
static Lisp_Object Qfontset_info;
202
static Lisp_Object Qprepend, Qappend;
Kenichi Handa's avatar
Kenichi Handa committed
203
static Lisp_Object Qlatin;
204 205 206 207

/* Vector containing all fontsets.  */
static Lisp_Object Vfontset_table;

208
/* Next possibly free fontset ID.  Usually this keeps the minimum
209 210 211 212
   fontset ID not yet used.  */
static int next_fontset_id;

/* The default fontset.  This gives default FAMILY and REGISTRY of
Kenichi Handa's avatar
Kenichi Handa committed
213
   font for each character.  */
214
static Lisp_Object Vdefault_fontset;
Karl Heuer's avatar
Karl Heuer committed
215 216

Lisp_Object Vfont_encoding_alist;
217
Lisp_Object Vfont_encoding_charset_alist;
218
Lisp_Object Vuse_default_ascent;
219
Lisp_Object Vignore_relative_composition;
220
Lisp_Object Valternate_fontname_alist;
221
Lisp_Object Vfontset_alias_alist;
222
Lisp_Object Vvertical_centering_font_regexp;
223
Lisp_Object Votf_script_alist;
Karl Heuer's avatar
Karl Heuer committed
224

225 226 227
/* The following six are declarations of callback functions depending
   on window system.  See the comments in src/fontset.h for more
   detail.  */
Karl Heuer's avatar
Karl Heuer committed
228 229

/* Return a pointer to struct font_info of font FONT_IDX of frame F.  */
230
struct font_info *(*get_font_info_func) P_ ((FRAME_PTR f, int font_idx));
Karl Heuer's avatar
Karl Heuer committed
231

232 233
/* Return a list of font names which matches PATTERN.  See the documentation
   of `x-list-fonts' for more details.  */
234 235 236 237
Lisp_Object (*list_fonts_func) P_ ((struct frame *f,
				    Lisp_Object pattern,
				    int size,
				    int maxnames));
Karl Heuer's avatar
Karl Heuer committed
238 239 240

/* Load a font named NAME for frame F and return a pointer to the
   information of the loaded font.  If loading is failed, return 0.  */
241
struct font_info *(*load_font_func) P_ ((FRAME_PTR f, char *name, int));
Karl Heuer's avatar
Karl Heuer committed
242 243

/* Return a pointer to struct font_info of a font named NAME for frame F.  */
244
struct font_info *(*query_font_func) P_ ((FRAME_PTR f, char *name));
Karl Heuer's avatar
Karl Heuer committed
245 246 247

/* Additional function for setting fontset or changing fontset
   contents of frame F.  */
248 249
void (*set_frame_fontset_func) P_ ((FRAME_PTR f, Lisp_Object arg,
				    Lisp_Object oldval));
Karl Heuer's avatar
Karl Heuer committed
250

251 252
/* To find a CCL program, fs_load_font calls this function.
   The argument is a pointer to the struct font_info.
253
   This function set the member `encoder' of the structure.  */
254 255
void (*find_ccl_program_func) P_ ((struct font_info *));

256 257 258
Lisp_Object (*get_font_repertory_func) P_ ((struct frame *,
					    struct font_info *));

Karl Heuer's avatar
Karl Heuer committed
259
/* Check if any window system is used now.  */
260
void (*check_window_system_func) P_ ((void));
Karl Heuer's avatar
Karl Heuer committed
261

262 263

/* Prototype declarations for static functions.  */
Dave Love's avatar
Dave Love committed
264 265
static Lisp_Object fontset_add P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
				    Lisp_Object));
266
static void reorder_font_vector P_ ((Lisp_Object, int, Lisp_Object));
267
static Lisp_Object fontset_font P_ ((Lisp_Object, int, struct face *, int));
268 269
static Lisp_Object make_fontset P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
static Lisp_Object fontset_pattern_regexp P_ ((Lisp_Object));
270 271
static void accumulate_script_ranges P_ ((Lisp_Object, Lisp_Object,
					  Lisp_Object));
Kenichi Handa's avatar
Kenichi Handa committed
272
Lisp_Object find_font_encoding P_ ((Lisp_Object));
273

274 275
static void set_fontset_font P_ ((Lisp_Object, Lisp_Object));

276 277 278 279 280 281 282 283 284 285 286 287 288
#ifdef FONTSET_DEBUG

/* Return 1 if ID is a valid fontset id, else return 0.  */

static int
fontset_id_valid_p (id)
     int id;
{
  return (id >= 0 && id < ASIZE (Vfontset_table) - 1);
}

#endif

289 290 291 292 293 294 295


/********** MACROS AND FUNCTIONS TO HANDLE FONTSET **********/

/* Return the fontset with ID.  No check of ID's validness.  */
#define FONTSET_FROM_ID(id) AREF (Vfontset_table, id)

296
/* Macros to access special values of FONTSET.  */
297
#define FONTSET_ID(fontset)		XCHAR_TABLE (fontset)->extras[0]
Kenichi Handa's avatar
Kenichi Handa committed
298 299

/* Macros to access special values of (base) FONTSET.  */
300
#define FONTSET_NAME(fontset)		XCHAR_TABLE (fontset)->extras[1]
Kenichi Handa's avatar
Kenichi Handa committed
301 302 303 304 305
#define FONTSET_ASCII(fontset)		XCHAR_TABLE (fontset)->extras[4]

/* Macros to access special values of (realized) FONTSET.  */
#define FONTSET_BASE(fontset)		XCHAR_TABLE (fontset)->extras[2]
#define FONTSET_FRAME(fontset)		XCHAR_TABLE (fontset)->extras[3]
306 307
#define FONTSET_NOFONT_FACE(fontset)	XCHAR_TABLE (fontset)->extras[5]
#define FONTSET_REPERTORY(fontset)	XCHAR_TABLE (fontset)->extras[6]
Kenichi Handa's avatar
Kenichi Handa committed
308 309
#define FONTSET_DEFAULT(fontset)	XCHAR_TABLE (fontset)->extras[7]

310
/* For both base and realized fontset.  */
Kenichi Handa's avatar
Kenichi Handa committed
311
#define FONTSET_FALLBACK(fontset)	XCHAR_TABLE (fontset)->extras[8]
312

313
#define BASE_FONTSET_P(fontset)		(NILP (FONTSET_BASE (fontset)))
314 315


316 317 318 319
/* Return the element of FONTSET for the character C.  If FONTSET is a
   base fontset other then the default fontset and FONTSET doesn't
   contain information for C, return the information in the default
   fontset.  */
320

321 322 323 324
#define FONTSET_REF(fontset, c)		\
  (EQ (fontset, Vdefault_fontset)	\
   ? CHAR_TABLE_REF (fontset, c)	\
   : fontset_ref ((fontset), (c)))
325

326
static Lisp_Object
327 328 329 330
fontset_ref (fontset, c)
     Lisp_Object fontset;
     int c;
{
Kenichi Handa's avatar
Kenichi Handa committed
331 332
  Lisp_Object elt;

333 334 335 336 337
  elt = CHAR_TABLE_REF (fontset, c);
  if (NILP (elt) && ! EQ (fontset, Vdefault_fontset)
      /* Don't check Vdefault_fontset for a realized fontset.  */
      && NILP (FONTSET_BASE (fontset)))
    elt = CHAR_TABLE_REF (Vdefault_fontset, c);
338 339 340
  return elt;
}

341 342 343 344 345 346 347
/* Set elements of FONTSET for characters in RANGE to the value ELT.
   RANGE is a cons (FROM . TO), where FROM and TO are character codes
   specifying a range.  */

#define FONTSET_SET(fontset, range, elt)	\
  Fset_char_table_range ((fontset), (range), (elt))

348

349
/* Modify the elements of FONTSET for characters in RANGE by replacing
350
   with ELT or adding ELT.  RANGE is a cons (FROM . TO), where FROM
351 352 353 354
   and TO are character codes specifying a range.  If ADD is nil,
   replace with ELT, if ADD is `prepend', prepend ELT, otherwise,
   append ELT.  */

355 356 357 358 359 360
#define FONTSET_ADD(fontset, range, elt, add)				     \
  (NILP (add)								     \
   ? (NILP (range)							     \
      ? (FONTSET_FALLBACK (fontset) = Fmake_vector (make_number (1), (elt))) \
      : Fset_char_table_range ((fontset), (range),			     \
			       Fmake_vector (make_number (1), (elt))))	     \
361
   : fontset_add ((fontset), (range), (elt), (add)))
362

Dave Love's avatar
Dave Love committed
363
static Lisp_Object
364
fontset_add (fontset, range, elt, add)
365
     Lisp_Object fontset, range, elt, add;
Kenichi Handa's avatar
Kenichi Handa committed
366
{
Kenichi Handa's avatar
Kenichi Handa committed
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
  Lisp_Object args[2];
  int idx = (EQ (add, Qappend) ? 0 : 1);

  args[1 - idx] = Fmake_vector (make_number (1), elt);

  if (CONSP (range))
    {
      int from = XINT (XCAR (range));
      int to = XINT (XCDR (range));
      int from1, to1;

      do {
	args[idx] = char_table_ref_and_range (fontset, from, &from1, &to1);
	if (to < to1)
	  to1 = to;
	char_table_set_range (fontset, from, to1,
			      NILP (args[idx]) ? args[1 - idx]
			      : Fvconcat (2, args));
	from = to1 + 1;
      } while (from < to);
    }
  else
    {
      args[idx] = FONTSET_FALLBACK (fontset);
      FONTSET_FALLBACK (fontset)
	= NILP (args[idx]) ? args[1 - idx] : Fvconcat (2, args);
    }
Dave Love's avatar
Dave Love committed
394
  return Qnil;
395 396 397
}


398 399
/* Update FONT-GROUP which has this form:
	[CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID PREFERRED-FAMILY
400 401 402
	 RFONT-DEF0 RFONT-DEF1 ...].
   Reorder RFONT-DEFs according to the current order of charset
   (Vcharset_ordered_list), and update CHARSET-ORDERED-LIST-TICK to
403
   the latest value.  */
404 405

static void
406 407 408 409
reorder_font_vector (font_group, charset_id, family)
     Lisp_Object font_group;
     int charset_id;
     Lisp_Object family;
410
{
411
  Lisp_Object list, *new_vec;
412 413 414
  int size;
  int *charset_id_table;
  int i, idx;
415
  Lisp_Object preferred_by_charset, preferred_by_family;
416

417
  size = ASIZE (font_group) - 3;
418 419
  /* Exclude the tailing nil elements from the reordering.  */
  while (NILP (AREF (font_group, size - 1))) size--;
420 421
  charset_id_table = (int *) alloca (sizeof (int) * size);
  new_vec = (Lisp_Object *) alloca (sizeof (Lisp_Object) * size);
422

423 424 425 426 427 428
  /* At first, extract ENCODING (a chaset ID) from RFONT_DEF which
     has this form:
	[FACE-ID FONT-INDEX [ FONT-SPEC ENCODING REPERTORY ]]
     In addtion, if RFONT_DEF is preferred by family or charset, store
     it from the start of new_vec.  */
  for (i = 0, idx = 0; i < size; i++)
429
    {
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
      Lisp_Object rfont_def = AREF (font_group, i + 3);
      Lisp_Object font_spec = AREF (AREF (rfont_def, 2), 0);
      Lisp_Object this_family = AREF (font_spec, FONT_FAMILY_INDEX);
      int id = XINT (AREF (AREF (rfont_def, 2), 1));
      struct charset *charset = CHARSET_FROM_ID (id);

      charset_id_table[i] = -1;
      if (! NILP (this_family)
	  && (fast_string_match_ignore_case (family, SYMBOL_NAME (this_family))
	      >= 0))
	{
	  if (idx > 0)
	    memmove (new_vec + 1, new_vec, sizeof (Lisp_Object) * idx);
	  new_vec[0] = rfont_def;
	  idx++;
	  ASET (font_group, i + 3, Qnil);
	}
      else if (id == charset_id)
	{
	  new_vec[idx++] = rfont_def;
	  ASET (font_group, i + 3, Qnil);
	}
      else if (! charset->supplementary_p)
	charset_id_table[i] = id;
454
    }
455

456 457 458 459 460 461 462 463 464
  if (idx == 0
      && (XINT (AREF (font_group, 0)) == charset_ordered_list_tick))
    /* No need of reordering.  */
    return;

  ASET (font_group, 0, make_number (charset_ordered_list_tick));
  ASET (font_group, 1, make_number (charset_id));
  ASET (font_group, 2, family);

465 466 467
  /* Then, store the remaining RFONT-DEFs in NEW_VEC in the correct
     order.  */
  for (list = Vcharset_ordered_list; idx < size; list = XCDR (list))
Kenichi Handa's avatar
Kenichi Handa committed
468
    {
469 470 471 472 473
      int id = XINT (XCAR (list));
      struct charset *charset = CHARSET_FROM_ID (id);

      if (charset->supplementary_p)
	break;
474
      for (i = 0; i < size; i++)
475
	if (charset_id_table[i] == XINT (XCAR (list))
476
	    && ! NILP (AREF (font_group, i + 3)))
477 478 479 480
	  {
	    new_vec[idx++] = AREF (font_group, i + 3);
	    ASET (font_group, i + 3, Qnil);
	  }
Kenichi Handa's avatar
Kenichi Handa committed
481
    }
482
  for (i = 0; i < size; i++)
483 484
    if (! NILP (AREF (font_group, i + 3)))
      new_vec[idx++] = AREF (font_group, i + 3);
485

486
  /* At last, update elements of FONT-GROUP.  */
487
  for (i = 0; i < size; i++)
488
    ASET (font_group, i + 3, new_vec[i]);
489 490 491 492 493 494 495 496 497 498
}


/* Load a font matching the font related attributes in FACE->lface and
   font pattern in FONT_DEF of FONTSET, and return an index of the
   font.  FONT_DEF has this form:
	[ FONT-SPEC ENCODING REPERTORY ]
   If REPERTORY is nil, generate a char-table representing the font
   repertory by looking into the font itself.  */

499 500
extern Lisp_Object QCname;

501 502 503 504 505 506 507 508 509
static int
load_font_get_repertory (f, face, font_def, fontset)
     FRAME_PTR f;
     struct face *face;
     Lisp_Object font_def;
     Lisp_Object fontset;
{
  char *font_name;
  struct font_info *font_info;
510
  int charset;
511
  Lisp_Object font_spec, name;
512

513 514 515 516 517 518
  font_spec = AREF (font_def, 0);
  name = Ffont_get (font_spec, QCname);
  if (! NILP (name))
    font_name = choose_face_font (f, face->lface, name, NULL);
  else
    font_name = choose_face_font (f, face->lface, font_spec, NULL);
519
  charset = XINT (AREF (font_def, 1));
520
  if (! (font_info = fs_load_font (f, font_name, charset)))
521 522 523 524 525 526 527 528 529 530 531 532 533
    return -1;

  if (NILP (AREF (font_def, 2))
      && NILP (Fassq (make_number (font_info->font_idx),
		      FONTSET_REPERTORY (fontset))))
    {
      /* We must look into the font to get the correct repertory as a
	 char-table.  */
      Lisp_Object repertory;

      repertory = (*get_font_repertory_func) (f, font_info);
      FONTSET_REPERTORY (fontset)
	= Fcons (Fcons (make_number (font_info->font_idx), repertory),
Kenichi Handa's avatar
Kenichi Handa committed
534
		 FONTSET_REPERTORY (fontset));
Kenichi Handa's avatar
Kenichi Handa committed
535
    }
536 537
	
  return font_info->font_idx;
538 539
}

540 541
static Lisp_Object fontset_find_font P_ ((Lisp_Object, int, struct face *,
					  int, int));
542

543
/* Return RFONT-DEF (vector) in the realized fontset FONTSET for the
544 545 546 547 548 549 550
   character C.  If no font is found, return Qnil if there's a
   possibility that the default fontset or the fallback font groups
   have a proper font, and return Qt if not.

   If a font is found but is not yet opened, open it (if FACE is not
   NULL) or return Qnil (if FACE is NULL).

551 552
   ID is a charset-id that must be preferred, or -1 meaning no
   preference.
553

554
   If FALLBACK is nonzero, search only fallback fonts.  */
555

556
static Lisp_Object
557
fontset_find_font (fontset, c, face, id, fallback)
558 559
     Lisp_Object fontset;
     int c;
560
     struct face *face;
561
     int id, fallback;
562
{
563
  Lisp_Object base_fontset, elt, vec, font_def;
564 565 566
  int i, from, to;
  int font_idx;
  FRAME_PTR f = XFRAME (FONTSET_FRAME (fontset));
567

568
  base_fontset = FONTSET_BASE (fontset);
569 570 571 572
  if (! fallback)
    vec = CHAR_TABLE_REF (fontset, c);
  else
    vec = FONTSET_FALLBACK (fontset);
573

574
  if (NILP (vec))
575
    {
576
      Lisp_Object range;
577

578
      /* We have not yet decided a font for C.  */
579
      if (! face)
580
	return Qnil;
581
      if (! fallback)
582
	{
583
	  elt = char_table_ref_and_range (base_fontset, c, &from, &to);
584 585
	  range = Fcons (make_number (from), make_number (to));
	}
586
      else
587 588 589
	{
	  elt = FONTSET_FALLBACK (base_fontset);
	}
590 591
      if (NILP (elt))
	{
592
	  /* This fontset doesn't specify any font for C. */
593
	  vec = make_number (0);
594
	}
595 596 597 598 599
      else if (ASIZE (elt) == 1 && NILP (AREF (elt, 0)))
	{
	  /* Explicitly specified no font.  */
	  vec = Qt;
	}
600
      else
601
	{
602 603 604
	  /* Build a vector [ -1 -1 nil NEW-ELT0 NEW-ELT1 NEW-ELT2 ... ],
	     where the first -1 is to force reordering of NEW-ELTn,
	     NEW-ELTn is [nil nil AREF (elt, n) nil].  */
605 606 607 608
	  int size = ASIZE (elt);
	  int j;

	  vec = Fmake_vector (make_number (size + 3), Qnil);
609 610
	  ASET (vec, 0, make_number (-1));
	  ASET (vec, 1, make_number (-1));
611 612 613 614 615 616 617 618 619
	  for (i = j = 0; i < size; i++)
	    if (! NILP (AREF (elt, i)))
	      {
		Lisp_Object tmp;
		tmp = Fmake_vector (make_number (5), Qnil);
		ASET (tmp, 2, AREF (elt, i));
		ASET (vec, j + 3, tmp);
		j++;
	      }
620
	}
621 622 623 624 625
      /* Then store it in the fontset.  */
      if (! fallback)
	FONTSET_SET (fontset, range, vec);
      else
	FONTSET_FALLBACK (fontset) = vec;
626

627
    }
628
  if (! VECTORP (vec))
629
    return (EQ (vec, Qt) ? Qt : Qnil);
630

631 632
  if (ASIZE (vec) > 4
      && (XINT (AREF (vec, 0)) != charset_ordered_list_tick
633
	  || (id >= 0 && XINT (AREF (vec, 1)) != id)
634
	  || NILP (Fequal (AREF (vec, 2), face->lface[LFACE_FAMILY_INDEX]))))
635 636 637 638 639
    /* We have just created VEC,
       or the charset priorities were changed,
       or the preferred charset was changed,
       or the preferred family was changed.  */
    reorder_font_vector (vec, id, face->lface[LFACE_FAMILY_INDEX]);
640

641
  /* Find the first available font in the vector of RFONT-DEF.  */
642
  for (i = 3; i < ASIZE (vec); i++)
643
    {
644
      elt = AREF (vec, i);
645
      if (NILP (elt))
646 647
	/* This is the sign of not to try fallback fonts.  */
	return Qt;
648
      /* ELT == [ FACE-ID FONT-INDEX FONT-DEF ... ] */
649 650 651 652
      if (INTEGERP (AREF (elt, 1)) && XINT (AREF (elt, 1)) < 0)
	/* We couldn't open this font last time.  */
	continue;

653 654 655
      if (!face && NILP (AREF (elt, 1)))
	/* We have not yet opened the font.  */
	return Qnil;
656

657 658
      font_def = AREF (elt, 2);
      /* FONT_DEF == [ FONT-SPEC ENCODING REPERTORY ] */
Kenichi Handa's avatar
Kenichi Handa committed
659 660 661 662

#ifdef USE_FONT_BACKEND
      if (enable_font_backend)
	{
663 664 665 666 667 668
	  /* ELT == [ FACE-ID FONT-INDEX FONT-DEF FONT-ENTITY ]
	     where FONT-ENTITY turns to a font-object once opened.  */
	  Lisp_Object font_entity = AREF (elt, 3);
	  int has_char = 0;

	  if (NILP (font_entity))
669
	    {
670
	      font_entity = font_find_for_lface (f, face->lface,
671
						 AREF (font_def, 0), -1);
672
	      if (NILP (font_entity))
673 674 675 676
		{
		  ASET (elt, 1, make_number (-1));
		  continue;
		}
677 678 679 680 681 682
	      ASET (elt, 3, font_entity);
	    }
	  else if (FONT_ENTITY_P (font_entity))
	    {
	      if (FONT_ENTITY_NOT_LOADABLE (font_entity))
		continue;
Kenichi Handa's avatar
Kenichi Handa committed
683
	    }
684 685 686
	  has_char = font_has_char (f, font_entity, c);
	  if (! has_char)
	    continue;
687
	  if (! FONT_OBJECT_P (font_entity))
Kenichi Handa's avatar
Kenichi Handa committed
688
	    {
689 690 691 692
	      Lisp_Object font_object
		= font_open_for_lface (f, font_entity, face->lface, Qnil);

	      if (NILP (font_object))
693
		{
694
		  FONT_ENTITY_SET_NOT_LOADABLE (font_entity);
695 696
		  continue;
		}
697 698 699 700 701 702 703
	      ASET (elt, 3, font_object);
	      if (has_char < 0)
		{
		  has_char = font_has_char (f, font_object, c);
		  if (! has_char)
		    continue;
		}
Kenichi Handa's avatar
Kenichi Handa committed
704
	    }
705
	  /* Decide to use this font.  */
Kenichi Handa's avatar
Kenichi Handa committed
706 707 708 709 710
	  ASET (elt, 1, make_number (0));
	}
      else
#endif	/* USE_FONT_BACKEND */

711 712 713 714 715 716 717
      if (INTEGERP (AREF (font_def, 2)))
	{
	  /* The repertory is specified by charset ID.  */
	  struct charset *charset
	    = CHARSET_FROM_ID (XINT (AREF (font_def, 2)));

	  if (! CHAR_CHARSET_P (c, charset))
718
	    /* This font can't display C.  */
719 720
	    continue;
	}
721 722 723 724 725 726 727
      else if (CHAR_TABLE_P (AREF (font_def, 2)))
	{
	  /* The repertory is specified by a char table.  */
	  if (NILP (CHAR_TABLE_REF (AREF (font_def, 2), c)))
	    /* This font can't display C.  */
	    continue;
	}
728 729 730 731 732 733 734 735 736
      else
	{
	  Lisp_Object slot;

	  if (! INTEGERP (AREF (elt, 1)))
	    {
	      /* We have not yet opened a font matching this spec.
		 Open the best matching font now and register the
		 repertory.  */
737 738
	      struct font_info *font_info;

739 740 741 742 743 744
	      font_idx = load_font_get_repertory (f, face, font_def, fontset);
	      ASET (elt, 1, make_number (font_idx));
	      if (font_idx < 0)
		/* This means that we couldn't find a font matching
		   FONT_DEF.  */
		continue;
745 746
	      font_info = (*get_font_info_func) (f, font_idx);
	      ASET (elt, 3, build_string (font_info->full_name));
747 748 749
	    }

	  slot = Fassq (AREF (elt, 1), FONTSET_REPERTORY (fontset));
750
	  xassert (CONSP (slot));
751
	  if (NILP (CHAR_TABLE_REF (XCDR (slot), c)))
752
	    /* This font can't display C.  */
753 754 755 756
	    continue;
	}

      /* Now we have decided to use this font spec to display C.  */
757
      if (! INTEGERP (AREF (elt, 1)))
758 759
	{
	  /* But not yet opened the best matching font.  */
760 761
	  struct font_info *font_info;

762 763 764
	  font_idx = load_font_get_repertory (f, face, font_def, fontset);
	  ASET (elt, 1, make_number (font_idx));
	  if (font_idx < 0)
765
	    /* Can't open it.  Try the other one.  */
766
	    continue;
767 768
	  font_info = (*get_font_info_func) (f, font_idx);
	  ASET (elt, 3, build_string (font_info->full_name));
769
	}
770
      return elt;
771
    }
772

773
  return Qnil;
774
}
775

776

777 778 779 780 781 782 783 784 785
static Lisp_Object
fontset_font (fontset, c, face, id)
     Lisp_Object fontset;
     int c;
     struct face *face;
     int id;
{
  Lisp_Object rfont_def;
  Lisp_Object base_fontset;
786

787 788
  /* Try a font-group for C. */
  rfont_def = fontset_find_font (fontset, c, face, id, 0);
789 790 791 792
  if (VECTORP (rfont_def))
    return rfont_def;
  if (EQ (rfont_def, Qt))
    return Qnil;
793 794
  base_fontset = FONTSET_BASE (fontset);
  /* Try a font-group for C of the default fontset. */
795
  if (! EQ (base_fontset, Vdefault_fontset))
796
    {
Kenichi Handa's avatar
Kenichi Handa committed
797 798
      if (NILP (FONTSET_DEFAULT (fontset)))
	FONTSET_DEFAULT (fontset)
799
	  = make_fontset (FONTSET_FRAME (fontset), Qnil, Vdefault_fontset);
800
      rfont_def = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 0);
801 802
      if (VECTORP (rfont_def))
	return (rfont_def);
803
      if (! NILP (rfont_def))
804 805
	/* Remeber that we have no font for C.  */
	FONTSET_SET (fontset, make_number (c), Qt);
806
    }
807

808 809
  /* Try a fallback font-group. */
  rfont_def = fontset_find_font (fontset, c, face, id, 1);
810 811 812
  if (! VECTORP (rfont_def)
      && ! EQ (base_fontset, Vdefault_fontset))
    /* Try a fallback font-group of the default fontset . */
813
    rfont_def = fontset_find_font (FONTSET_DEFAULT (fontset), c, face, id, 1);
814 815 816 817 818

  if (! VECTORP (rfont_def))
    /* Remeber that we have no font for C.  */
    FONTSET_SET (fontset, make_number (c), Qt);

819
  return rfont_def;
820 821 822
}

/* Return a newly created fontset with NAME.  If BASE is nil, make a
Kenichi Handa's avatar
Kenichi Handa committed
823
   base fontset.  Otherwise make a realized fontset whose base is
824 825 826 827 828
   BASE.  */

static Lisp_Object
make_fontset (frame, name, base)
     Lisp_Object frame, name, base;
Karl Heuer's avatar
Karl Heuer committed
829
{
830
  Lisp_Object fontset;
831 832 833 834 835 836
  int size = ASIZE (Vfontset_table);
  int id = next_fontset_id;

  /* Find a free slot in Vfontset_table.  Usually, next_fontset_id is
     the next available fontset ID.  So it is expected that this loop
     terminates quickly.  In addition, as the last element of
837
     Vfontset_table is always nil, we don't have to check the range of
838 839 840 841
     id.  */
  while (!NILP (AREF (Vfontset_table, id))) id++;

  if (id + 1 == size)
Miles Bader's avatar
Miles Bader committed
842
    Vfontset_table = larger_vector (Vfontset_table, size + 32, Qnil);
Karl Heuer's avatar
Karl Heuer committed
843

844
  fontset = Fmake_char_table (Qfontset, Qnil);
845 846

  FONTSET_ID (fontset) = make_number (id);
Kenichi Handa's avatar
Kenichi Handa committed
847 848 849 850 851 852 853 854 855 856
  if (NILP (base))
    {
      FONTSET_NAME (fontset) = name;
    }
  else
    {
      FONTSET_NAME (fontset) = Qnil;
      FONTSET_FRAME (fontset) = frame;
      FONTSET_BASE (fontset) = base;
    }
857

Kenichi Handa's avatar
Kenichi Handa committed
858
  ASET (Vfontset_table, id, fontset);
859 860
  next_fontset_id = id + 1;
  return fontset;
Karl Heuer's avatar
Karl Heuer committed
861 862
}

863

864 865 866 867
/* Set the ASCII font of the default fontset to FONTNAME if that is
   not yet set.  */
void
set_default_ascii_font (fontname)
868 869
     Lisp_Object fontname;
{
870
  if (! STRINGP (FONTSET_ASCII (Vdefault_fontset)))
871 872 873 874
    {
      int id = fs_query_fontset (fontname, 2);

      if (id >= 0)
875 876
	fontname = FONTSET_ASCII (FONTSET_FROM_ID (id));
      FONTSET_ASCII (Vdefault_fontset)= fontname;
877
    }
878 879 880
}


881
/********** INTERFACES TO xfaces.c, xfns.c, and dispextern.h **********/
882

883
/* Return the name of the fontset who has ID.  */
884 885 886 887 888 889

Lisp_Object
fontset_name (id)
     int id;
{
  Lisp_Object fontset;
Kenichi Handa's avatar
Kenichi Handa committed
890

891 892 893 894 895
  fontset = FONTSET_FROM_ID (id);
  return FONTSET_NAME (fontset);
}


896
/* Return the ASCII font name of the fontset who has ID.  */