(fontset_table): New variable.
[m17n/m17n-lib.git] / src / fontset.c
1 /* fontset.c -- fontset module.
2    Copyright (C) 2003, 2004
3      National Institute of Advanced Industrial Science and Technology (AIST)
4      Registration Number H15PRO112
5
6    This file is part of the m17n library.
7
8    The m17n library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public License
10    as published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12
13    The m17n library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public
19    License along with the m17n library; if not, write to the Free
20    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21    02111-1307, USA.  */
22
23 /***en
24     @addtogroup m17nFontset
25     @brief A fontset is an object that maps a character to fonts.
26
27     A @e fontset is an object of the type @c MFontset.  When drawing an
28     M-text, a fontset provides rules to select a font for each
29     character in the M-text according to the following information.
30
31     @li The script character property of a character.
32     @li The language text property of a character.
33     @li The charset text property of a character.
34
35     The documentation of mdraw_text () describes how that information is
36     used.  */
37
38 /***ja @addtogroup m17nFontset 
39
40     @brief ¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ïʸ»ú¤«¤é¥Õ¥©¥ó¥È¤Ø¤ÎÂбþÉÕ¤±¤ò¹Ô¤¦¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë.
41
42     @e ¥Õ¥©¥ó¥È¥»¥Ã¥È ¤Ï @c MFontset ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë¡£M-text 
43     ¤Îɽ¼¨¤ÎºÝ¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ï°Ê²¼¤Î¾ðÊó¤òÍѤ¤¤Æ M-text 
44     Ãæ¤Î¸Ä¡¹¤Îʸ»ú¤Ë¤É¤Î¥Õ¥©¥ó¥È¤òÍѤ¤¤ë¤«·è¤á¤ëµ¬Â§¤òÍ¿¤¨¤ë¡£
45
46     @li Ê¸»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "¥¹¥¯¥ê¥×¥È"
47     @li Ê¸»ú¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£ "¸À¸ì"
48     @li Ê¸»ú¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£ "ʸ»ú¥»¥Ã¥È"
49
50     ¤³¤ì¤é¤Î¾ðÊ󤬤ɤΤ褦¤ËÍѤ¤¤é¤ì¤ë¤«¤Ï mdraw_text () ¤ÎÀâÌÀ¤ò»²¾È¤Î¤³¤È¡£
51
52     */
53
54 /*=*/
55
56 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
57 /*** @addtogroup m17nInternal
58      @{ */
59
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <string.h>
63 #include <ctype.h>
64
65 #include "config.h"
66 #include "m17n-gui.h"
67 #include "m17n-misc.h"
68 #include "internal.h"
69 #include "symbol.h"
70 #include "plist.h"
71 #include "character.h"
72 #include "charset.h"
73 #include "internal-gui.h"
74 #include "font.h"
75 #include "fontset.h"
76
77 static M17NObjectArray fontset_table;
78
79 struct MFontset
80 {
81   M17NObject control;
82
83   /* Name of the fontset.  */
84   MSymbol name;
85
86   /* Initialized to 0, and incremented by one each time the fontset is
87      modified.  */
88   unsigned tick;
89
90   /* Database from which to load the contents of the fontset.  Once
91      loaded, this member is set to NULL.  */
92   MDatabase *mdb;
93
94   /* SCRIPT vs PER-LANGUAGE (which is a plist LANGUAGE vs FONT-GROUP) */
95   MPlist *per_script;
96
97   /* CHARSET vs FONT-GROUP */
98   MPlist *per_charset;
99
100   /* FONT-GROUP */
101   MPlist *fallback;
102 };
103
104 static MFontset *default_fontset;
105
106 static MPlist *fontset_list;
107
108 struct MRealizedFontset
109 {
110   /* Fontset from which the realized fontset is realized.  */
111   MFontset *fontset;
112
113   /* Initialized to <fontset>->tick.  */
114   unsigned tick;
115
116   /* Font spec that must be satisfied, or NULL.  */
117   MFont *spec;
118
119   /* Font spec requested by a face.  */
120   MFont request;
121
122   /* The frame on which the realized fontset is realized.  */
123   MFrame *frame;
124
125   MPlist *per_script;
126
127   MPlist *per_charset;
128
129   MPlist *fallback;
130 };
131
132
133 static MPlist *
134 load_font_group (MPlist *plist, MPlist *elt)
135 {
136   MPLIST_DO (elt, elt)
137     {
138       /* ELT ::= ( FONT-SPEC [ LAYOUTER ] ) ...  */
139       MPlist *elt2;
140       MFont *font;
141       MSymbol layouter_name;
142
143       if (! MPLIST_PLIST_P (elt))
144         MWARNING (MERROR_FONTSET);
145       elt2 = MPLIST_PLIST (elt);
146       if (! MPLIST_PLIST_P (elt2))
147         MWARNING (MERROR_FONTSET);
148       MSTRUCT_CALLOC (font, MERROR_FONTSET);
149       mfont__set_spec_from_plist (font, MPLIST_PLIST (elt2));
150       elt2 = MPLIST_NEXT (elt2);
151       layouter_name = Mt;
152       if (MPLIST_SYMBOL_P (elt2))
153         layouter_name = MPLIST_SYMBOL (elt2);
154       if (layouter_name == Mnil)
155         layouter_name = Mt;
156       plist = mplist_add (plist, layouter_name, font);
157       continue;
158     warning:
159       /* ANSI-C requires some statement after a label.  */
160       continue;
161     }
162   return plist;
163 }
164
165 /* Load FONTSET->per_script from the data in FONTSET->mdb.  */
166
167 static void
168 load_fontset_contents (MFontset *fontset)
169 {
170   MPlist *per_script, *per_charset, *font_group;
171   MPlist *fontset_def, *plist;
172
173   fontset->per_script = per_script = mplist ();
174   fontset->per_charset = per_charset = mplist ();
175   fontset->fallback = mplist ();
176   if (! (fontset_def = (MPlist *) mdatabase_load (fontset->mdb)))
177     return;
178
179   MPLIST_DO (plist, fontset_def)
180     {
181       /* PLIST ::=   ( SCRIPT ( LANGUAGE ( FONT-SPEC [LAYOUTER]) ... ) ... )
182                    | ( CHARSET ( FONT-SPEC [LAYOUTER] ) ...)
183                    | ( nil ( FONT-SPEC [LAYOUTER] ) ...)
184          FONT-SPEC :: = ( ... ) */
185       MPlist *elt;
186       MSymbol sym;
187
188       if (! MPLIST_PLIST_P (plist))
189         MWARNING (MERROR_FONTSET);
190       elt = MPLIST_PLIST (plist);
191       if (! MPLIST_SYMBOL_P (elt))
192         MWARNING (MERROR_FONTSET);
193       sym = MPLIST_SYMBOL (elt);
194       elt = MPLIST_NEXT (elt);
195       if (! MPLIST_PLIST_P (elt))
196         MWARNING (MERROR_FONTSET);
197       if (sym == Mnil)
198         load_font_group (fontset->fallback, elt);
199       else if (MPLIST_PLIST_P (MPLIST_PLIST (elt)))
200         {
201           /* SYM is a charset.  */
202           font_group = mplist ();
203           per_charset = mplist_add (per_charset, sym, font_group);
204           load_font_group (font_group, elt);
205         }
206       else
207         {
208           /* SYM is a script */
209           MPlist *per_lang = mplist ();
210
211           per_script = mplist_add (per_script, sym, per_lang);
212           MPLIST_DO (elt, elt)
213             {
214               /* ELT ::= ( LANGUAGE FONT-DEF ...) ... */
215               MPlist *elt2;
216               MSymbol lang;
217
218               if (! MPLIST_PLIST_P (elt))
219                 MWARNING (MERROR_FONTSET);
220               elt2 = MPLIST_PLIST (elt);
221               if (! MPLIST_SYMBOL_P (elt2))
222                 MWARNING (MERROR_FONTSET);
223               lang = MPLIST_SYMBOL (elt2);
224               if (lang == Mnil)
225                 lang = Mt;
226               font_group = mplist ();
227               mplist_add (per_lang, lang, font_group);
228               elt2 = MPLIST_NEXT (elt2);
229               load_font_group (font_group, elt2);
230             }
231         }
232       continue;
233
234     warning:
235       /* ANSI-C requires some statement after a label.  */
236       continue;
237     }
238
239   M17N_OBJECT_UNREF (fontset_def);
240   fontset->mdb = NULL;
241 }
242
243 static void
244 free_fontset (void *object)
245 {
246   MFontset *fontset = (MFontset *) object;
247   MPlist *plist, *pl, *p;
248
249   if (fontset->per_script)
250     {
251       MPLIST_DO (plist, fontset->per_script)
252         {
253           MPLIST_DO (pl, MPLIST_PLIST (plist))
254             {
255               MPLIST_DO (p, MPLIST_PLIST (pl))
256                 free (MPLIST_VAL (p));
257               p = MPLIST_PLIST (pl);
258               M17N_OBJECT_UNREF (p);
259             }
260           pl = MPLIST_PLIST (plist);
261           M17N_OBJECT_UNREF (pl);
262         }
263       M17N_OBJECT_UNREF (fontset->per_script);
264     }
265   if (fontset->per_charset)
266     {
267       MPLIST_DO (pl, fontset->per_charset)
268         {
269           MPLIST_DO (p, MPLIST_PLIST (pl))
270             free (MPLIST_VAL (p));
271           p = MPLIST_PLIST (p);
272           M17N_OBJECT_UNREF (p);
273         }
274       M17N_OBJECT_UNREF (fontset->per_charset);
275     }
276   if (fontset->fallback)
277     {
278       MPLIST_DO (p, fontset->fallback)
279         free (MPLIST_VAL (p));
280       M17N_OBJECT_UNREF (fontset->fallback);
281     }
282
283   plist = mplist_find_by_key (fontset_list, fontset->name);
284   if (! plist)
285     mdebug_hook ();
286   mplist_pop (plist);
287   if (MPLIST_TAIL_P (fontset_list))
288     {
289       M17N_OBJECT_UNREF (fontset_list);
290       fontset_list = NULL;
291     }
292   M17N_OBJECT_UNREGISTER (fontset_table, fontset);
293   free (object);
294 }
295
296 static void
297 realize_fontset_elements (MFrame *frame, MRealizedFontset *realized)
298 {
299   MFontset *fontset = realized->fontset;
300   MPlist *per_script, *per_charset, *font_group;
301   MPlist *plist, *pl, *p;
302
303   realized->per_script = per_script = mplist ();
304   /* The actual elements of per_script are realized on demand.  */
305 #if 0
306   MPLIST_DO (plist, fontset->per_script)
307     {
308       per_lang = mplist ();
309       per_script = mplist_add (per_script, MPLIST_KEY (plist), per_lang);
310       MPLIST_DO (pl, MPLIST_PLIST (plist))
311         {
312           font_group = mplist ();
313           per_lang = mplist_add (per_lang, MPLIST_KEY (pl), font_group);
314           MPLIST_DO (p, MPLIST_PLIST (pl))
315             font_group = mplist_add (font_group,
316                                      MPLIST_KEY (p), MPLIST_VAL (p));
317         }
318     }
319 #endif
320
321   realized->per_charset = per_charset = mplist ();
322   MPLIST_DO (pl, fontset->per_charset)
323     {
324       font_group = mplist ();
325       per_charset = mplist_add (per_charset, MPLIST_KEY (plist), font_group);
326       MPLIST_DO (p, MPLIST_PLIST (pl))
327         font_group = mplist_add (font_group, MPLIST_KEY (p), MPLIST_VAL (p));
328     }
329   realized->fallback = font_group = mplist ();
330   MPLIST_DO (p, fontset->fallback)
331     font_group = mplist_add (font_group, MPLIST_KEY (p), MPLIST_VAL (p));
332 }
333
334
335 /* Return a plist of fonts for SCRIPT in FONTSET.  The returned list
336    is acutally a plist of languages vs font groups (which is a plist).
337    If SCRIPT is nil, return a plist of fallback fonts.  If FONTSET
338    doesn't record any fonts for SCRIPT, generate a proper font spec
339    lists for X backend and FreeType backend.  */
340
341 MPlist *
342 get_per_script (MFontset *fontset, MSymbol script)
343 {
344   MPlist *plist;
345
346   if (script == Mnil)
347     return fontset->fallback;
348   plist = mplist_get (fontset->per_script, script);
349   if (! plist)
350     {
351       int len = MSYMBOL_NAMELEN (script);
352       char *cap = alloca (8 + len + 1);
353       MSymbol capability;
354       MFont *font;
355       MPlist *pl, *p;
356
357       sprintf (cap, ":script=%s", MSYMBOL_NAME (script));
358       capability = msymbol (cap);
359
360       pl = mplist ();
361       MPLIST_DO (p, fontset->fallback)
362         {
363           font = mfont_copy (MPLIST_VAL (p));
364           mfont_put_prop (font, Mregistry, Municode_bmp);
365           font->source = MFONT_SOURCE_FT;
366           font->capability = capability;
367           mplist_add (pl, Mt, font);
368
369           font = mfont_copy (MPLIST_VAL (p));
370           mfont_put_prop (font, Mregistry, Miso10646_1);
371           font->source = MFONT_SOURCE_X;
372           font->capability = capability;
373           mplist_add (pl, Mt, font);
374         }
375       plist = mplist ();
376       mplist_add (plist, Mt, pl);
377       mplist_add (fontset->per_script, script, plist);
378     }
379   return plist;
380 }
381
382 static void
383 free_realized_fontset_elements (MRealizedFontset *realized)
384 {
385   MPlist *plist, *pl, *p;
386   MFont *font;
387   MFontList *font_list;
388
389   if (realized->per_script)
390     {
391       MPLIST_DO (plist, realized->per_script)
392         {
393           MPLIST_DO (pl, MPLIST_PLIST (plist))
394             {
395               MPLIST_DO (p, MPLIST_PLIST (pl))
396                 {
397                   font = MPLIST_VAL (p);
398                   if (font->type == MFONT_TYPE_OBJECT)
399                     {
400                       font_list = (MFontList *) font;
401                       free (font_list->fonts);
402                       free (font_list);
403                     }
404                   /* This is to avoid freeing rfont again by the later
405                      M17N_OBJECT_UNREF (p) */
406                   MPLIST_KEY (p) = Mt;
407                 }
408               p = MPLIST_PLIST (pl);
409               M17N_OBJECT_UNREF (p);
410             }
411           pl = MPLIST_PLIST (plist);
412           M17N_OBJECT_UNREF (pl);
413         }
414       M17N_OBJECT_UNREF (realized->per_script);
415     }
416   if (realized->per_charset)
417     {
418       MPLIST_DO (plist, realized->per_charset)
419         {
420           MPLIST_DO (pl, MPLIST_PLIST (plist))
421             {
422               font = MPLIST_VAL (pl);
423               if (font->type == MFONT_TYPE_OBJECT)
424                 {
425                   font_list = (MFontList *) font;
426                   free (font_list->fonts);
427                   free (font_list);
428                 }
429               MPLIST_KEY (pl) = Mt;
430             }
431           pl = MPLIST_PLIST (plist);
432           M17N_OBJECT_UNREF (pl);
433         }
434       M17N_OBJECT_UNREF (realized->per_charset);
435     }
436   if (realized->fallback)
437     {
438       MPLIST_DO (plist, realized->fallback)
439         {
440           font = MPLIST_VAL (plist);
441           if (font->type == MFONT_TYPE_OBJECT)
442             {
443               font_list = (MFontList *) font;
444               free (font_list->fonts);
445               free (font_list);
446             }
447           MPLIST_KEY (plist) = Mt;
448         }
449       M17N_OBJECT_UNREF (realized->fallback);
450     }
451 }
452
453 static void
454 update_fontset_elements (MRealizedFontset *realized)
455 {
456   free_realized_fontset_elements (realized);
457   realize_fontset_elements (realized->frame, realized);
458 }
459
460
461 \f
462
463 /* Internal API */
464
465 int
466 mfont__fontset_init ()
467 {
468   M17N_OBJECT_ADD_ARRAY (fontset_table, "Fontset");
469
470   Mfontset = msymbol ("fontset");
471   Mfontset->managing_key = 1;
472   fontset_list = mplist ();
473   default_fontset = mfontset ("default");
474   if (! default_fontset->mdb)
475     {
476       MFont font;
477
478       MFONT_INIT (&font);
479       mfont_put_prop (&font, Mregistry, msymbol ("iso8859-1"));
480       mfontset_modify_entry (default_fontset, Mnil, Mnil, Mnil,
481                              &font, Mnil, 1);
482       mfont_put_prop (&font, Mregistry, msymbol ("iso10646-1"));
483       mfontset_modify_entry (default_fontset, Mnil, Mnil, Mnil,
484                              &font, Mnil, 1);
485     }
486   return 0;
487 }
488
489
490 void
491 mfont__fontset_fini ()
492 {
493   M17N_OBJECT_UNREF (default_fontset);
494   default_fontset = NULL;
495 }
496
497
498 MRealizedFontset *
499 mfont__realize_fontset (MFrame *frame, MFontset *fontset,
500                         MFace *face, MFont *spec)
501 {
502   MRealizedFontset *realized;
503   MFont request;
504   MPlist *plist;
505
506   if (fontset->mdb)
507     load_fontset_contents (fontset);
508
509   MFONT_INIT (&request);
510   mfont__set_spec_from_face (&request, face);
511   if (request.size <= 0)
512     {
513       mdebug_hook ();
514       request.size = 120;
515     }
516   MPLIST_DO (plist, frame->realized_fontset_list)
517     {
518       realized = (MRealizedFontset *) MPLIST_VAL (plist);
519       if (fontset->name == MPLIST_KEY (plist)
520           && ! memcmp (&request, &realized->request, sizeof (MFont))
521           && (realized->spec
522               ? (spec && ! memcmp (spec, &realized->spec, sizeof (MFont)))
523               : ! spec))
524         return realized;
525     }
526
527   MSTRUCT_CALLOC (realized, MERROR_FONTSET);
528   realized->fontset = fontset;
529   M17N_OBJECT_REF (fontset);
530   realized->tick = fontset->tick;
531   if (spec)
532     {
533       MSTRUCT_CALLOC (realized->spec, MERROR_FONTSET);
534       *realized->spec = *spec;
535     }
536   realized->request = request;
537   realized->frame = frame;
538   realize_fontset_elements (frame, realized);
539   mplist_add (frame->realized_fontset_list, fontset->name, realized);
540   return realized;
541 }
542
543
544 void
545 mfont__free_realized_fontset (MRealizedFontset *realized)
546 {
547   free_realized_fontset_elements (realized);
548   M17N_OBJECT_UNREF (realized->fontset);
549   if (realized->spec)
550     free (realized->spec);
551   free (realized);
552 }
553
554
555 static MRealizedFont *
556 try_font_list (MFrame *frame, MFontList *font_list, MFont *request,
557                MSymbol layouter, MGlyph *g, int *num, int all, int exact)
558 {
559   int i, j;
560   MFont *font;
561   MRealizedFont *rfont;
562
563   for (i = 0; i < font_list->nfonts; i++)
564     {
565       if (font_list->fonts[i].font->type == MFONT_TYPE_SPEC)
566         MFATAL (MERROR_FONT);
567       if (exact)
568         {
569           if (font_list->fonts[i].score > 0)
570             break;
571         }
572       else
573         {
574           if (font_list->fonts[i].score == 0)
575             continue;
576         }
577       font = font_list->fonts[i].font;
578       if (font->type == MFONT_TYPE_FAILURE)
579         continue;
580       /* Check if this font can display all glyphs.  */
581       for (j = 0; j < *num; j++)
582         {
583           int c = g[j].type == GLYPH_CHAR ? g[j].c : ' ';
584           if (layouter != Mt
585               ? mfont__flt_encode_char (layouter, c) == MCHAR_INVALID_CODE
586               : ! mfont__has_char (frame, font, &font_list->object, c))
587             break;
588         }
589       if (j == 0 && *num > 0)
590         continue;
591       if (j == *num || !all)
592         {
593           /* We found a font that can display the requested range of
594              glyphs.  */
595           if (font->type == MFONT_TYPE_REALIZED)
596             rfont = (MRealizedFont *) font;
597           else
598             {
599               rfont = mfont__open (frame, font, &font_list->object);
600               if (! rfont)
601                 continue;
602               font_list->fonts[i].font = (MFont *) rfont;
603             }
604           rfont->layouter = layouter == Mt ? Mnil : layouter;
605           *num = j;
606           for (j = 0; j < *num; j++)
607             {
608               int c = g[j].type == GLYPH_CHAR ? g[j].c : ' ';
609
610               g[j].code = (rfont->layouter
611                            ? mfont__flt_encode_char (rfont->layouter, c)
612                            : mfont__encode_char (frame, (MFont *) rfont,
613                                                  &font_list->object, c));
614             }
615           return rfont;
616         }
617     }
618   return NULL;
619 }
620
621
622 static MRealizedFont *
623 try_font_group (MRealizedFontset *realized, MFont *request,
624                 MPlist *font_group, MGlyph *g, int *num, int size)
625 {
626   MFrame *frame = realized->frame;
627   MFont *font;
628   MFontList *font_list;
629   MRealizedFont *rfont;
630   MPlist *plist;
631   MSymbol layouter;
632   int best_score = -1, worst_score;
633
634   for (plist = font_group; ! MPLIST_TAIL_P (plist); )
635     {
636       int this_score;
637
638       layouter = MPLIST_KEY (plist);
639       font = MPLIST_VAL (plist);
640       if (font->type == MFONT_TYPE_SPEC)
641         {
642           /* We have not yet made this entry a MFontList.  */
643           if (realized->spec)
644             {
645               MFont this = *font;
646               
647               if (mfont__merge (&this, realized->spec, 1) < 0)
648                 {
649                   mplist_pop (plist);
650                   continue;
651                 }
652               font_list = mfont__list (frame, &this, &this, size);
653             }
654           else
655             font_list = mfont__list (frame, font, request, size);
656           if (! font_list)
657             {
658               /* As there's no font matching this spec, remove this
659                  element from the font group.  */
660               mplist_pop (plist);
661               continue;
662             }
663           MPLIST_VAL (plist) = font_list;
664         }
665       else
666         font_list = (MFontList *) font;
667
668       this_score = font_list->fonts[0].score;
669       if ((this_score == 0)
670           && (rfont = try_font_list (frame, font_list, request,
671                                      layouter, g, num, 1, 1)))
672         return rfont;
673       if (best_score < 0)
674         {
675           best_score = worst_score = this_score;
676           plist = MPLIST_NEXT (plist);
677         }
678       else if (this_score >= worst_score)
679         {
680           worst_score = this_score;
681           plist = MPLIST_NEXT (plist);
682         }
683       else
684         {
685           MPlist *pl;
686
687           MPLIST_DO (pl, font_group)
688             if (this_score < ((MFontList *) MPLIST_VAL (pl))->fonts[0].score)
689               break;
690           mplist_pop (plist);
691           mplist_push (pl, layouter, font_list);
692         }
693     }
694
695   /* We couldn't find an exact matching font that can display all
696      glyphs.  Find one that can at least display all glyphs.  */
697   MPLIST_DO (plist, font_group)
698     {
699       rfont = try_font_list (frame, MPLIST_VAL (plist), request,
700                              MPLIST_KEY (plist), g, num, 1, 0);
701       if (rfont)
702         return rfont;
703     }
704
705   /* We couldn't find a font that can display all glyphs.  Find an
706      exact matching font that can at least display the first
707      glyph.  */
708   MPLIST_DO (plist, font_group)
709     {
710       rfont = try_font_list (frame, MPLIST_VAL (plist), request,
711                              MPLIST_KEY (plist), g, num, 0, 1);
712       if (rfont)
713         return rfont;
714     }
715
716   /* Find any font that can at least display the first glyph.  */
717   MPLIST_DO (plist, font_group)
718     {
719       rfont = try_font_list (frame, MPLIST_VAL (plist), request,
720                              MPLIST_KEY (plist), g, num, 0, 0);
721       if (rfont)
722         return rfont;
723     }
724
725   return NULL;
726 }
727
728 MRealizedFont *
729 mfont__lookup_fontset (MRealizedFontset *realized, MGlyph *g, int *num,
730                        MSymbol script, MSymbol language, MSymbol charset,
731                        int size, int ignore_fallback)
732 {
733   MCharset *preferred_charset = (charset == Mnil ? NULL : MCHARSET (charset));
734   MPlist *per_charset, *per_script, *per_lang;
735   MPlist *plist;
736   MRealizedFont *rfont = NULL;
737
738   if (realized->tick != realized->fontset->tick)
739     update_fontset_elements (realized);
740
741   if (preferred_charset
742       && (per_charset = mplist_get (realized->per_charset, charset)) != NULL
743       && (rfont = try_font_group (realized, &realized->request, per_charset,
744                                   g, num, size)))
745     return rfont;
746
747   if (script != Mnil)
748     {
749       MFont request = realized->request;
750
751       if (script != Mlatin)
752         /* These are not appropriate for non-Latin scripts.  */
753         request.property[MFONT_FOUNDRY]
754           = request.property[MFONT_FAMILY]
755           = request.property[MFONT_REGISTRY] = 0;
756
757       per_script = mplist_get (realized->per_script, script);
758       if (! per_script)
759         {
760           per_script = mplist_copy (get_per_script (realized->fontset, script));
761           /* PER_SCRIPT ::= (LANGUAGE:(LAYOUTER:FONT-SPEC ...) ...) */
762           MPLIST_DO (plist, per_script)
763             MPLIST_VAL (plist) = mplist_copy (MPLIST_VAL (plist));
764           mplist_add (realized->per_script, script, per_script);
765         }
766
767       /* We prefer font groups in this order:
768           (1) group matching with LANGUAGE if LANGUAGE is not Mnil
769           (2) group for generic language
770           (3) group not matching with LANGUAGE  */
771       if (language == Mnil)
772         language = Mt;
773       if ((per_lang = mplist_get (per_script, language))
774           && (rfont = try_font_group (realized, &request, per_lang,
775                                       g, num, size)))
776         return rfont;
777
778       if (language == Mt)
779         {
780           /* Try the above (3) */
781           MPLIST_DO (plist, per_script)
782             if (MPLIST_KEY (plist) != language
783                 && (rfont = try_font_group (realized, &request,
784                                             MPLIST_PLIST (plist),
785                                             g, num, size)))
786               return rfont;
787         }
788       else
789         {
790           /* At first try the above (2) */
791           if ((per_lang = mplist_get (per_script, Mt))
792               && (rfont = try_font_group (realized, &request, per_lang,
793                                           g, num, size)))
794             return rfont;
795
796           /* Then try the above (3) */
797           MPLIST_DO (plist, per_script)
798             if (MPLIST_KEY (plist) != language
799                 && MPLIST_KEY (plist) != Mt
800                 && (rfont = try_font_group (realized, &request,
801                                             MPLIST_PLIST (plist),
802                                             g, num, size)))
803               return rfont;
804         }
805       if (ignore_fallback)
806         return NULL;
807     }
808
809   if (language != Mnil)
810     /* Find a font group for this language from all scripts.  */
811     MPLIST_DO (plist, realized->per_script)
812       {
813         MFont request = realized->request;
814
815         if (MPLIST_KEY (plist) != Mlatin)
816           request.property[MFONT_FOUNDRY]
817             = request.property[MFONT_FAMILY]
818             = request.property[MFONT_FAMILY] = 0;
819         if ((per_lang = mplist_get (MPLIST_PLIST (plist), language))
820             && (rfont = try_font_group (realized, &request, per_lang,
821                                         g, num, size)))
822           return rfont;
823       }
824
825   /* Try fallback fonts.  */
826   if ((rfont = try_font_group (realized, &realized->request,
827                                realized->fallback, g, num, size)))
828     return rfont;
829
830   return NULL;
831
832   /* At last try all fonts.  */
833   MPLIST_DO (per_script, realized->per_script)
834     {
835       MPLIST_DO (per_lang, MPLIST_PLIST (per_script))
836         if ((rfont = try_font_group (realized, &realized->request,
837                                      MPLIST_PLIST (per_lang), g, num, size)))
838           return rfont;
839     }
840   MPLIST_DO (per_charset, realized->per_charset)
841     if ((rfont = try_font_group (realized, &realized->request,
842                                  MPLIST_PLIST (per_charset), g, num, size)))
843       return rfont;
844
845   return NULL;
846 }
847
848 /*** @} */
849 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
850
851 \f
852 /* External API */
853
854 /*** @addtogroup m17nFontset */
855 /*** @{ */
856
857 /*=*/
858 /***en
859     @brief Return a fontset.
860
861     The mfontset () function returns a pointer to a fontset object of
862     name $NAME.  If $NAME is @c NULL, it returns a pointer to the
863     default fontset.
864
865     If no fontset has the name $NAME, a new one is created.  At that
866     time, if there exists a data \<@c fontset, $NAME\> in the m17n
867     database, the fontset contents are initialized according to the
868     data.  If no such data exists, the fontset contents are left
869     vacant.
870
871     The macro M17N_INIT () creates the default fontset.  An
872     application program can modify it before the first call of 
873     mframe ().
874
875     @return
876     This function returns a pointer to the found or newly created
877     fontset.  */
878 /***ja 
879     @brief ¥Õ¥©¥ó¥È¥»¥Ã¥È¤òÊÖ¤¹.
880
881     ´Ø¿ô mfontset () ¤Ï̾Á° $NAME ¤ò»ý¤Ä¥Õ¥©¥ó¥È¥»¥Ã¥È¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£ 
882     $NAME ¤¬ @c NULL ¤Ê¤é¤Ð¡¢¥Ç¥Õ¥©¥ë¥È¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
883
884     $NAME ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥Õ¥©¥ó¥È¥»¥Ã¥È¤¬¤Ê¤±¤ì¤Ð¡¢¿·¤·¤¤¤â¤Î¤¬ºî¤é¤ì¤ë¡£¤½¤ÎºÝ¡¢
885     m17n ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë \<@c fontset, $NAME\> 
886     ¤È¤¤¤¦¥Ç¡¼¥¿¤¬¤¢¤ì¤Ð¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ï¤½¤Î¥Ç¡¼¥¿¤Ë±è¤Ã¤Æ½é´ü²½¤µ¤ì¤ë¡£
887     ¤Ê¤±¤ì¤Ð¡¢¶õ¤Î¤Þ¤Þ¤Ë¤µ¤ì¤ë¡£
888
889     ¥Þ¥¯¥í M17N_INIT () ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤òºî¤ë¡£¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï
890     mframe () ¤ò½é¤á¤Æ¸Æ¤Ö¤Þ¤Ç¤Î´Ö¤Ï¥Ç¥Õ¥©¥ë¥È¥Õ¥©¥ó¥È¥»¥Ã¥È¤òÊѹ¹¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡£
891
892     @return
893     ¤³¤Î´Ø¿ô¤Ï¸«¤Ä¤«¤Ã¤¿¡¢¤¢¤ë¤¤¤Ïºî¤Ã¤¿¥Õ¥©¥ó¥È¥»¥Ã¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
894      */
895
896 MFontset *
897 mfontset (char *name)
898 {
899   MSymbol sym;
900   MFontset *fontset;
901
902   if (! name)
903     {
904       fontset = default_fontset;
905       M17N_OBJECT_REF (fontset);
906     }
907   else
908     {
909       sym = msymbol (name);
910       fontset = mplist_get (fontset_list, sym);
911       if (fontset)
912         M17N_OBJECT_REF (fontset);
913       else
914         {
915           M17N_OBJECT (fontset, free_fontset, MERROR_FONTSET);
916           M17N_OBJECT_REGISTER (fontset_table, fontset);
917           fontset->name = sym;
918           fontset->mdb = mdatabase_find (Mfontset, sym, Mnil, Mnil);
919           if (! fontset->mdb)
920             {
921               fontset->per_script = mplist ();
922               fontset->per_charset = mplist ();
923               fontset->fallback = mplist ();
924             }
925           mplist_put (fontset_list, sym, fontset);
926         }
927     }
928   return fontset;
929 }
930
931 /*=*/
932
933 /***en
934     @brief Return the name of a fontset.
935
936     The mfontset_name () function returns the name of fontset $FONTSET.  */
937 /***ja
938     @brief ¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î̾Á°¤òÊÖ¤¹.
939
940     ´Ø¿ô mfontset_name () ¤Ï¥Õ¥©¥ó¥È¥»¥Ã¥È $FONTSET ¤Î̾Á°¤òÊÖ¤¹¡£  */
941 MSymbol
942 mfontset_name (MFontset *fontset)
943 {
944   return fontset->name;
945 }
946
947 /*=*/
948
949 /***en
950     @brief Make a copy of a fontset.
951
952     The mfontset_copy () function makes a copy of fontset $FONTSET, gives it a
953     name $NAME, and returns a pointer to the created copy.  $NAME must
954     not be a name of existing fontset.  In such case, this function
955     returns NULL without making a copy.  */
956 /***ja
957     @brief ¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥³¥Ô¡¼¤òºî¤ë.
958
959     ´Ø¿ô mfontset_copy () ¤Ï¥Õ¥©¥ó¥È¥»¥Ã¥È $FONTSET ¤Î¥³¥Ô¡¼¤òºî¤Ã¤Æ¡¢Ì¾Á°
960     $NAME ¤òÍ¿¤¨¡¢¤½¤Î¥³¥Ô¡¼¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£$NAME 
961     ¤Ï´û¸¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î̾Á°¤Ç¤¢¤Ã¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¤½¤Î¤è¤¦¤Ê¾ì¹ç¤Ë¤Ï¥³¥Ô¡¼¤òºî¤é¤º¤Ë
962     NULL ¤òÊÖ¤¹¡£  */
963
964 MFontset *
965 mfontset_copy (MFontset *fontset, char *name)
966 {
967   MSymbol sym = msymbol (name);
968   MFontset *copy = mplist_get (fontset_list, sym);
969   MPlist *plist, *pl, *p;
970
971   if (copy)
972     return NULL;
973   M17N_OBJECT (copy, free_fontset, MERROR_FONTSET);
974   M17N_OBJECT_REGISTER (fontset_table, copy);
975   copy->name = sym;
976
977   if (fontset->mdb)
978     load_fontset_contents (fontset);
979
980   if (fontset->per_script)
981     {
982       copy->per_script = mplist ();
983       MPLIST_DO (plist, fontset->per_script)
984         {
985           MPlist *per_lang = mplist ();
986
987           mplist_add (copy->per_script, MPLIST_KEY (plist), per_lang);
988           MPLIST_DO (pl, MPLIST_PLIST (plist))
989             {
990               MPlist *font_group = mplist ();
991
992               per_lang = mplist_add (per_lang, MPLIST_KEY (pl), font_group);
993               MPLIST_DO (p, MPLIST_PLIST (pl))
994                 font_group = mplist_add (font_group, MPLIST_KEY (p),
995                                          mfont_copy (MPLIST_VAL (p)));
996             }
997         }
998     }
999   if (fontset->per_charset)
1000     {
1001       MPlist *per_charset = mplist ();
1002
1003       copy->per_charset = per_charset;
1004       MPLIST_DO (pl, fontset->per_charset)
1005         {
1006           MPlist *font_group = mplist ();
1007
1008           per_charset = mplist_add (per_charset, MPLIST_KEY (pl), font_group);
1009           MPLIST_DO (p, MPLIST_PLIST (pl))
1010             font_group = mplist_add (font_group, MPLIST_KEY (p),
1011                                      mfont_copy (MPLIST_VAL (p)));
1012         }
1013     }
1014   if (fontset->fallback)
1015     {
1016       MPlist *font_group = mplist ();
1017
1018       copy->fallback = font_group;
1019       MPLIST_DO (p, fontset->fallback)
1020         font_group = mplist_add (font_group, MPLIST_KEY (p),
1021                                  mfont_copy (MPLIST_VAL (p)));
1022     }                            
1023
1024   mplist_put (fontset_list, sym, copy);
1025   return copy;
1026 }
1027
1028 /*=*/
1029
1030 /***en
1031     @brief Modify the contents of a fontset.
1032
1033     The mfontset_modify_entry () function associates, in fontset
1034     $FONTSET, a copy of $FONT with the $SCRIPT / $LANGUAGE pair or
1035     with $CHARSET.
1036
1037     Each font in a fontset is associated with a particular
1038     script/language pair, with a particular charset, or with the
1039     symbol @c Mnil.  The fonts that are associated with the same item
1040     make a group.
1041
1042     If $SCRIPT is not @c Mnil, it must be a symbol identifying a
1043     script.  In this case, $LANGUAGE is either a symbol identifying a
1044     language or @c Mnil, and $FONT is associated with the $SCRIPT /
1045     $LANGUAGE pair.
1046
1047     If $CHARSET is not @c Mnil, it must be a symbol representing a
1048     charset object.  In this case, $FONT is associated with that
1049     charset.
1050
1051     If both $SCRIPT and $CHARSET are not @c Mnil, two copies of $FONT
1052     are created.  Then one is associated with the $SCRIPT / $LANGUAGE
1053     pair and the other with that charset.
1054
1055     If both $SCRIPT and $CHARSET are @c Mnil, $FONT is associated with
1056     @c Mnil.  This kind of fonts are called @e fallback @e fonts.
1057
1058     The argument $HOW specifies the priority of $FONT.  If $HOW is
1059     positive, $FONT has the highest priority in the group of fonts
1060     that are associated with the same item.  If $HOW is negative,
1061     $FONT has the lowest priority.  If $HOW is zero, $FONT becomes the
1062     only available font for the associated item; all the other fonts
1063     are removed from the group.
1064
1065     If $LAYOUTER_NAME is not @c Mnil, it must be a symbol representing
1066     a @ref flt (font layout table).  In that case, if $FONT is
1067     selected for drawing an M-text, that font layout table is used to
1068     generate a glyph code sequence from a character sequence.
1069
1070     @return
1071     If the operation was successful, mfontset_modify_entry () returns 0.
1072     Otherwise it returns -1 and assigns an error code to the external
1073     variable #merror_code.  */
1074
1075 /***ja
1076     @brief ¥Õ¥©¥ó¥È¥»¥Ã¥È¤ÎÆâÍƤòÊѹ¹¤¹¤ë.
1077
1078     ´Ø¿ô mfontset_modify_entry () ¤Ï¡¢$LANGUAGE ¤È $SCRIPT ¤ÎÁȤ߹ç¤ï¤»¡¢¤Þ¤¿¤Ï
1079     $CHARSET ¤ËÂФ·¤Æ $FONT ¤Î¥³¥Ô¡¼¤ò»È¤¦¤è¤¦¤Ë¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È $FONTSET ¤òÀßÄꤹ¤ë¡£
1080
1081     ¥Õ¥©¥ó¥È¥»¥Ã¥ÈÃæ¤Î³Æ¥Õ¥©¥ó¥È¤Ï¡¢ÆÃÄê¤Î¥¹¥¯¥ê¥×¥È¤È¸À¸ì¤Î¥Ú¥¢¡¢ÆÃÄê¤Îʸ»ú¥»¥Ã¥È¡¢¥·¥ó¥Ü¥ë
1082     @c Mnil ¤Î¤¤¤º¤ì¤«¤È´ØÏ¢ÉÕ¤±¤é¤ì¤Æ¤¤¤ë¡£Æ±¤¸¤â¤Î¤È´ØÏ¢ÉÕ¤±¤é¤ì¤¿¥Õ¥©¥ó¥È¤Ï¥°¥ë¡¼¥×¤ò¹½À®¤¹¤ë¡£
1083
1084     $SCRIPT ¤Ï @c Mnil ¤Ç¤¢¤ë¤«¡¢¥¹¥¯¥ê¥×¥È¤òÆÃÄꤹ¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
1085     ¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¾ì¹ç¤Ë¤Ï¡¢$LANGUAGE ¤Ï¸À¸ì¤òÆÃÄꤹ¤ë¥·¥ó¥Ü¥ë¤« @c
1086     Mnil ¤Ç¤¢¤ê¡¢$FONT ¤Ïthe $SCRIPT / $LANGUAGE ¥Ú¥¢¤Ë´ØÏ¢ÉÕ¤±¤é¤ì¤ë¡£
1087
1088     $CHARSET ¤Ï @c Mnil ¤Ç¤¢¤ë¤«¡¢Ê¸»ú¥»¥Ã¥È¥ª¥Ö¥¸¥§¥¯¥È¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
1089     ¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¾ì¹ç¤Ë¤Ï $FONT ¤Ï¤½¤Îʸ»ú¥»¥Ã¥È¤È´ØÏ¢ÉÕ¤±¤é¤ì¤ë¡£
1090
1091     $SCRIPT ¤È $CHARSET ¤ÎÁÐÊý¤¬ @c Mnil ¤Ç¤Ê¤¤¾ì¹ç¤Ë¤Ï $FONT 
1092     ¤Î¥³¥Ô¡¼¤¬£²¤Äºî¤é¤ì¡¢¤½¤ì¤¾¤ì $SCRIPT / $LANGUAGE 
1093     ¥Ú¥¢¤Èʸ»ú¥»¥Ã¥È¤Ë´ØÏ¢ÉÕ¤±¤é¤ì¤ë¡£
1094
1095     $SCRIPT ¤È $CHARSET ¤ÎÁÐÊý¤¬ @c Mnil ¤Ê¤é¤Ð¡¢ $FONT ¤Ï @c Mnil 
1096     ¤È´ØÏ¢ÉÕ¤±¤é¤ì¤ë¡£¤³¤Î¼ï¤Î¥Õ¥©¥ó¥È¤Ï @e fallback @e font ¤È¸Æ¤Ð¤ì¤ë¡£
1097
1098     °ú¿ô $HOW ¤Ï $FONT ¤ÎÍ¥ÀèÅÙ¤ò»ØÄꤹ¤ë¡£$HOW ¤¬Àµ¤Ê¤é¤Ð¡¢$FONT 
1099     ¤ÏƱ¤¸¤â¤Î¤È´ØÏ¢ÉÕ¤±¤é¤ì¤¿¥°¥ë¡¼¥×Ãæ¤ÇºÇ¹â¤ÎÍ¥ÀèÅÙ¤ò»ý¤Ä¡£$HOW 
1100     ¤¬Éé¤Ê¤é¤Ð¡¢ºÇÄã¤ÎÍ¥ÀèÅÙ¤ò»ý¤Ä¡£$HOW ¤¬ 0 ¤Ê¤é¤Ð¡¢$FONT 
1101     ¤Ï´ØÏ¢ÉÕ¤±¤é¤ì¤¿¤â¤Î¤ËÂФ¹¤ëÍ£°ì¤ÎÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤È¤Ê¤ê¡¢Â¾¤Î¥Õ¥©¥ó¥È¤Ï¥°¥ë¡¼¥×¤«¤é¼è¤ê½ü¤«¤ì¤ë¡£
1102
1103     $LAYOUTER_NAME ¤Ï @c Mnil ¤Ç¤¢¤ë¤«¡¢@ref flt 
1104     ¡Ê¥Õ¥©¥ó¥È¥ì¥¤¥¢¥¦¥È¥Æ¡¼¥Ö¥ë¡Ë¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£¥·¥ó¥Ü¥ë¤Ç¤¢¤ì¤Ð¡¢$FONT ¤òÍѤ¤¤Æ
1105     M-text ¤òɽ¼¨¤¹¤ëºÝ¤Ë¤Ï¡¢¤½¤Î¥Õ¥©¥ó¥È¥ì¥¤¥¢¥¦¥È¥Æ¡¼¥Ö¥ë¤ò»È¤Ã¤Æʸ»úÎ󤫤饰¥ê¥Õ¥³¡¼¥ÉÎó¤òÀ¸À®¤¹¤ë¡£
1106
1107     @return 
1108     ½èÍý¤¬À®¸ù¤·¤¿¤È¤­¡¢mfontset_modify_entry () ¤Ï 0 ¤òÊÖ¤¹¡£
1109     ¼ºÇÔ¤·¤¿¤È¤­¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
1110
1111 /***
1112     @errors
1113     @c MERROR_SYMBOL  */
1114
1115 int
1116 mfontset_modify_entry (MFontset *fontset,
1117                        MSymbol script, MSymbol language, MSymbol charset,
1118                        MFont *spec, MSymbol layouter_name,
1119                        int how)
1120 {
1121   MPlist *per_lang, *plist[3];
1122   MFont *font = NULL;
1123   int i;
1124
1125   if (fontset->mdb)
1126     load_fontset_contents (fontset);
1127
1128   i = 0;
1129   if (script != Mnil)
1130     {
1131       if (language == Mnil)
1132         language = Mt;
1133       per_lang = mplist_get (fontset->per_script, script);
1134       if (! per_lang)
1135         mplist_add (fontset->per_script, script, per_lang = mplist ());
1136       plist[i] = mplist_get (per_lang, language);
1137       if (! plist[i])
1138         mplist_add (per_lang, language, plist[i] = mplist ());
1139       i++;
1140     }
1141   if (charset != Mnil)
1142     {
1143       plist[i] = mplist_get (fontset->per_charset, charset);
1144       if (! plist[i])
1145         mplist_add (fontset->per_charset, charset, plist[i] = mplist ());
1146       i++;
1147     }
1148   if (script == Mnil && charset == Mnil)
1149     {
1150       plist[i++] = fontset->fallback;
1151     }
1152
1153   if (layouter_name == Mnil)
1154     layouter_name = Mt;
1155   for (i--; i >= 0; i--)
1156     {
1157       font = mfont_copy (spec);
1158       font->type = MFONT_TYPE_SPEC;
1159       if (how == 1)
1160         mplist_push (plist[i], layouter_name, font);
1161       else if (how == -1)
1162         mplist_add (plist[i], layouter_name, font);
1163       else
1164         {
1165           MPlist *pl;
1166
1167           MPLIST_DO (pl, plist[i])
1168             free (MPLIST_VAL (pl));
1169           mplist_set (plist[i], Mnil, NULL);
1170           mplist_add (plist[i], layouter_name, font);
1171         }
1172     }
1173
1174   fontset->tick++;
1175   return 0;
1176 }
1177
1178 /*=*/
1179
1180 /***en
1181     @brief Lookup a fontset.
1182
1183     The mfontset_lookup () function lookups $FONTSET and returns a
1184     plist that describes the contents of $FONTSET corresponding to the
1185     specified script, language, and charset.
1186
1187     If $SCRIPT is @c Mt, keys of the returned plist are script name
1188     symbols for which some fonts are specified and values are NULL.
1189
1190     If $SCRIPT is a script name symbol, the returned plist is decided
1191     by $LANGUAGE.
1192     
1193     @li If $LANGUAGE is @c Mt, keys of the plist are language name
1194     symbols for which some fonts are specified and values are NULL.  A
1195     key may be @c Mt which means some fallback fonts are specified for
1196     the script.
1197
1198     @li If $LANGUAGE is a language name symbol, the plist is a @c
1199     FONT-GROUP for the specified script and language.  @c FONT-GROUP
1200     is a plist whose keys are FLT (FontLayoutTable) name symbols (@c
1201     Mt if no FLT is associated with the font) and values are pointers
1202     to #MFont.
1203
1204     @li If $LANGUAGE is @c Mnil, the plist is fallback @c FONT-GROUP
1205     for the script. 
1206
1207     If $SCRIPT is @c Mnil, the returned plist is decided as below.
1208
1209     @li If $CHARSET is @c Mt, keys of the returned plist are charset name
1210     symbols for which some fonts are specified and values are NULL.
1211
1212     @li If $CHARSET is a charset name symbol, the plist is a @c FONT-GROUP for
1213     the charset.
1214
1215     @li If $CHARSET is @c Mnil, the plist is a fallback @c FONT-GROUP.
1216
1217     @return
1218     It returns a plist describing the contents of a fontset.  The
1219     plist should be freed by m17n_object_unref ().  */
1220 /***ja
1221     @brief ¥Õ¥©¥ó¥È¥»¥Ã¥È¤ò¸¡º÷¤¹¤ë.
1222
1223     ´Ø¿ô mfontset_lookup () ¤Ï $FONTSET ¤ò¸¡º÷¤·¡¢$FONTSET 
1224     ¤ÎÆâÍƤΤ¦¤Á»ØÄꤷ¤¿¥¹¥¯¥ê¥×¥È¡¢¸À¸ì¡¢Ê¸»ú¥»¥Ã¥È¤ËÂбþ¤¹¤ëÉôʬ¤òɽ¤¹
1225     plist ¤òÊÖ¤¹¡£
1226
1227     $SCRIPT ¤¬ @c Mt ¤Ê¤é¤Ð¡¢ÊÖ¤¹ plist 
1228     ¤Î¥­¡¼¤Ï¥Õ¥©¥ó¥È¤¬»ØÄꤵ¤ì¤Æ¤¤¤ë¥¹¥¯¥ê¥×¥È̾¤Î¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢ÃͤÏ
1229     NULL ¤Ç¤¢¤ë¡£
1230
1231     $SCRIPT ¤¬¥¹¥¯¥ê¥×¥È̾¤Î¥·¥ó¥Ü¥ë¤Ç¤¢¤ì¤Ð¡¢ÊÖ¤¹ 
1232     plist ¤Ï $LANGUAGE¤Ë¤è¤Ã¤ÆÄê¤Þ¤ë¡£
1233     
1234     @li $LANGUAGE ¤¬ @c Mt ¤Ê¤é¤Ð¡¢plist 
1235     ¤Î¥­¡¼¤Ï¥Õ¥©¥ó¥È¤¬»ØÄꤵ¤ì¤Æ¤¤¤ë¸À¸ì̾¤Î¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢ÃͤÏ
1236     NULL ¤Ç¤¢¤ë¡£¥­¡¼¤Ï @c Mt
1237     ¤Ç¤¢¤ë¤³¤È¤â¤¢¤ê¡¢¤½¤Î¾ì¹ç¤½¤Î¥¹¥¯¥ê¥×¥È¤Ë¥Õ¥©¡¼¥ë¥Ð¥Ã¥¯¥Õ¥©¥ó¥È¤¬¤¢¤ë¤³¤È¤ò°ÕÌ£¤¹¤ë¡£
1238
1239     @li $LANGUAGE ¤¬¸À¸ì̾¤Î¥·¥ó¥Ü¥ë¤Ê¤é¤Ð¡¢plist ¤Ï»ØÄê¤Î¥¹¥¯¥ê¥×¥È¤È¸À¸ì¤ËÂФ¹¤ë
1240     @c FONT-GROUP ¤Ç¤¢¤ë¡£@c FONT-GROUP ¤È¤Ï¡¢¥­¡¼¤¬ FLT
1241     (FontLayoutTable) Ì¾¤Î¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢Ãͤ¬ #MFont 
1242     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¤è¤¦¤Ê plist ¤Ç¤¢¤ë¡£¤¿¤À¤·¥Õ¥©¥ó¥È¤Ë FLT 
1243     ¤¬ÂбþÉÕ¤±¤é¤ì¤Æ¤¤¤Ê¤¤»þ¤Ë¤Ï¡¢¥­¡¼¤Ï @c Mt ¤Ë¤Ê¤ë¡£
1244
1245     @li $LANGUAGE ¤¬ @c Mnil ¤Ê¤é¤Ð¡¢plist ¤Ï¤½¤Î¥¹¥¯¥ê¥×¥ÈÍѤΥե©¡¼¥ë¥Ð¥Ã¥¯
1246     @c FONT-GROUP ¤Ç¤¢¤ë¡£
1247
1248     $SCRIPT ¤¬ @c Mnil ¤Ê¤é¤Ð¡¢ÊÖ¤¹ plist ¤Ï°Ê²¼¤Î¤è¤¦¤ËÄê¤Þ¤ë¡£
1249
1250     @li $CHARSET ¤¬ @c Mt ¤Ê¤é¤Ð¡¢plist 
1251     ¤Î¥­¡¼¤Ï¥Õ¥©¥ó¥È¤¬»ØÄꤵ¤ì¤Æ¤¤¤ëʸ»ú¥»¥Ã¥È̾¤Î¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢ÃͤÏ
1252     NULL ¤Ç¤¢¤ë¡£
1253
1254     @li $CHARSET ¤¬Ê¸»ú¥»¥Ã¥È̾¤Î¥·¥ó¥Ü¥ë¤Ê¤é¤Ð¡¢plist ¤Ï¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΠ
1255     @c FONT-GROUP ¤Ç¤¢¤ë¡£
1256
1257     @li $CHARSET ¤¬ @c Mnil ¤Ê¤é¤Ð¡¢plist ¤Ï¥Õ¥©¡¼¥ë¥Ð¥Ã¥¯ @c FONT-GROUP ¤Ç¤¢¤ë¡£
1258
1259     @return
1260     ¤³¤Î´Ø¿ô¤Ï¥Õ¥©¥ó¥È¥»¥Ã¥È¤ÎÆâÍƤòɽ¤¹ plist ¤òÊÖ¤¹¡£
1261     plist ¤Ï m17n_object_unref () ¤Ç²òÊü¤µ¤ì¤ë¤Ù¤­¤Ç¤¢¤ë¡£  */
1262
1263 MPlist *
1264 mfontset_lookup (MFontset *fontset,
1265                  MSymbol script, MSymbol language, MSymbol charset)
1266 {
1267   MPlist *plist = mplist (), *pl, *p;
1268
1269   if (fontset->mdb)
1270     load_fontset_contents (fontset);
1271   if (script == Mt)
1272     {
1273       if (! fontset->per_script)
1274         return plist;
1275       p = plist;
1276       MPLIST_DO (pl, fontset->per_script)
1277         p = mplist_add (p, MPLIST_KEY (pl), NULL);
1278       return plist;
1279     }
1280   if (script != Mnil)
1281     {
1282       pl = get_per_script (fontset, script);
1283       if (MPLIST_TAIL_P (pl))
1284         return plist;
1285       if (language == Mt)
1286         {
1287           p = plist;
1288           MPLIST_DO (pl, pl)
1289             p = mplist_add (p, MPLIST_KEY (pl), NULL);
1290           return plist;
1291         }
1292       if (language == Mnil)
1293         language = Mt;
1294       pl = mplist_get (pl, language);
1295     }
1296   else if (charset != Mnil)
1297     {
1298       if (! fontset->per_charset)
1299         return plist;
1300       if (charset == Mt)
1301         {
1302           p = plist;
1303           MPLIST_DO (pl, fontset->per_charset)
1304             p = mplist_add (p, MPLIST_KEY (pl), NULL);
1305           return plist;
1306         }
1307       pl = mplist_get (fontset->per_charset, charset);
1308     }
1309   else
1310     pl = fontset->fallback;
1311   if (! pl)
1312     return plist;
1313   return mplist_copy (pl);
1314 }
1315
1316
1317 /*** @} */
1318
1319 /*** @addtogroup m17nDebug */
1320 /*=*/
1321 /*** @{  */
1322
1323 /***en
1324     @brief Dump a fontset.
1325
1326     The mdebug_dump_fontset () function prints fontset $FONTSET in a human readable
1327     way to the stderr.  $INDENT specifies how many columns to indent
1328     the lines but the first one.
1329
1330     @return
1331     This function returns $FONTSET.  */
1332 /***ja
1333     @brief ¥Õ¥©¥ó¥È¥»¥Ã¥È¤ò¥À¥ó¥×¤¹¤ë.
1334
1335     ´Ø¿ô mdebug_dump_face () ¤Ï¥Õ¥©¥ó¥È¥»¥Ã¥È $FONTSET ¤ò stderr 
1336     ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£ $INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
1337
1338     @return
1339     ¤³¤Î´Ø¿ô¤Ï $FONTSET ¤òÊÖ¤¹¡£  */
1340
1341 MFontset *
1342 mdebug_dump_fontset (MFontset *fontset, int indent)
1343 {
1344   char *prefix = (char *) alloca (indent + 1);
1345   MPlist *plist, *pl, *p;
1346
1347   memset (prefix, 32, indent);
1348   prefix[indent] = 0;
1349
1350   fprintf (stderr, "(fontset %s", fontset->name->name);
1351   if (fontset->per_script)
1352     MPLIST_DO (plist, fontset->per_script)
1353       {
1354         fprintf (stderr, "\n  %s(%s", prefix, MPLIST_KEY (plist)->name);
1355         MPLIST_DO (pl, MPLIST_PLIST (plist))
1356           {
1357             fprintf (stderr, "\n    %s(%s", prefix, MPLIST_KEY (pl)->name);
1358             MPLIST_DO (p, MPLIST_PLIST (pl))
1359               {
1360                 fprintf (stderr, "\n      %s(0x%X %s ", prefix,
1361                          (unsigned) MPLIST_VAL (p),
1362                          MPLIST_KEY (p)->name);
1363                 mdebug_dump_font (MPLIST_VAL (p));
1364                 fprintf (stderr, ")");
1365               }
1366             fprintf (stderr, ")");
1367           }
1368         fprintf (stderr, ")");
1369       }
1370   if (fontset->per_charset)
1371     MPLIST_DO (pl, fontset->per_charset)
1372       {
1373         fprintf (stderr, "\n  %s(%s", prefix, MPLIST_KEY (pl)->name);
1374         MPLIST_DO (p, MPLIST_PLIST (pl))
1375           {
1376             fprintf (stderr, "\n    %s(%s ", prefix, MPLIST_KEY (p)->name);
1377             mdebug_dump_font (MPLIST_VAL (p));
1378             fprintf (stderr, ")");
1379           }
1380         fprintf (stderr, ")");
1381       }
1382
1383   if (fontset->fallback)
1384     MPLIST_DO (p, fontset->fallback)
1385       {
1386         fprintf (stderr, "\n  %s(%s ", prefix, MPLIST_KEY (p)->name);
1387         mdebug_dump_font (MPLIST_VAL (p));
1388         fprintf (stderr, ")");
1389       }
1390
1391   fprintf (stderr, ")");
1392   return fontset;
1393 }
1394
1395 /*** @} */
1396
1397 /*
1398   Local Variables:
1399   coding: euc-japan
1400   End:
1401 */