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