Blame src/fontset.c

Packit Service a721b1
/* fontset.c -- fontset module.
Packit Service a721b1
   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Packit Service a721b1
     National Institute of Advanced Industrial Science and Technology (AIST)
Packit Service a721b1
     Registration Number H15PRO112
Packit Service a721b1
Packit Service a721b1
   This file is part of the m17n library.
Packit Service a721b1
Packit Service a721b1
   The m17n library is free software; you can redistribute it and/or
Packit Service a721b1
   modify it under the terms of the GNU Lesser General Public License
Packit Service a721b1
   as published by the Free Software Foundation; either version 2.1 of
Packit Service a721b1
   the License, or (at your option) any later version.
Packit Service a721b1
Packit Service a721b1
   The m17n library is distributed in the hope that it will be useful,
Packit Service a721b1
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service a721b1
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service a721b1
   Lesser General Public License for more details.
Packit Service a721b1
Packit Service a721b1
   You should have received a copy of the GNU Lesser General Public
Packit Service a721b1
   License along with the m17n library; if not, write to the Free
Packit Service a721b1
   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit Service a721b1
   Boston, MA 02110-1301 USA.  */
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @addtogroup m17nFontset
Packit Service a721b1
    @brief A fontset is an object that maps a character to fonts.
Packit Service a721b1
Packit Service a721b1
    A @e fontset is an object of the type @c MFontset.  When drawing an
Packit Service a721b1
    M-text, a fontset provides rules to select a font for each
Packit Service a721b1
    character in the M-text according to the following information.
Packit Service a721b1
Packit Service a721b1
    @li The script character property of a character.
Packit Service a721b1
    @li The language text property of a character.
Packit Service a721b1
    @li The charset text property of a character.
Packit Service a721b1
Packit Service a721b1
    The documentation of mdraw_text () describes how that information is
Packit Service a721b1
    used.  */
Packit Service a721b1
Packit Service a721b1
/***ja @addtogroup m17nFontset 
Packit Service a721b1
Packit Service a721b1
    @brief フォントセットは文字からフォントへの対応付けを行うオブジェクトである.
Packit Service a721b1
Packit Service a721b1
    @e フォントセット は @c MFontset 型のオブジェクトである。M-text 
Packit Service a721b1
    の表示の際、フォントセットは以下の情報を用いて M-text 
Packit Service a721b1
    中の個々の文字にどのフォントを用いるか決める規則を与える。
Packit Service a721b1
Packit Service a721b1
    @li 文字の文字プロパティ "スクリプト"
Packit Service a721b1
    @li 文字のテキストプロパティ "言語"
Packit Service a721b1
    @li 文字のテキストプロパティ "文字セット"
Packit Service a721b1
Packit Service a721b1
    これらの情報がどのように用いられるかは mdraw_text () の説明を参照のこと。
Packit Service a721b1
Packit Service a721b1
    */
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
Packit Service a721b1
/*** @addtogroup m17nInternal
Packit Service a721b1
     @{ */
Packit Service a721b1
Packit Service a721b1
#include <stdio.h>
Packit Service a721b1
#include <stdlib.h>
Packit Service a721b1
#include <string.h>
Packit Service a721b1
#include <ctype.h>
Packit Service a721b1
Packit Service a721b1
#include "config.h"
Packit Service a721b1
#include "m17n-gui.h"
Packit Service a721b1
#include "m17n-misc.h"
Packit Service a721b1
#include "internal.h"
Packit Service a721b1
#include "symbol.h"
Packit Service a721b1
#include "plist.h"
Packit Service a721b1
#include "character.h"
Packit Service a721b1
#include "charset.h"
Packit Service a721b1
#include "internal-gui.h"
Packit Service a721b1
#include "font.h"
Packit Service a721b1
#include "fontset.h"
Packit Service a721b1
Packit Service a721b1
static int mdebug_flag = MDEBUG_FONTSET;
Packit Service a721b1
Packit Service a721b1
static M17NObjectArray fontset_table;
Packit Service a721b1
Packit Service a721b1
struct MFontset
Packit Service a721b1
{
Packit Service a721b1
  M17NObject control;
Packit Service a721b1
Packit Service a721b1
  /* Name of the fontset.  */
Packit Service a721b1
  MSymbol name;
Packit Service a721b1
Packit Service a721b1
  /* Initialized to 0, and incremented by one each time the fontset is
Packit Service a721b1
     modified.  */
Packit Service a721b1
  unsigned tick;
Packit Service a721b1
Packit Service a721b1
  /* Database from which to load the contents of the fontset.  Once
Packit Service a721b1
     loaded, this member is set to NULL.  */
Packit Service a721b1
  MDatabase *mdb;
Packit Service a721b1
Packit Service a721b1
  /* SCRIPT vs PER-LANGUAGE (which is a plist LANGUAGE vs FONT-GROUP) */
Packit Service a721b1
  MPlist *per_script;
Packit Service a721b1
Packit Service a721b1
  /* CHARSET vs FONT-GROUP */
Packit Service a721b1
  MPlist *per_charset;
Packit Service a721b1
Packit Service a721b1
  /* FONT-GROUP */
Packit Service a721b1
  MPlist *fallback;
Packit Service a721b1
};
Packit Service a721b1
Packit Service a721b1
static MFontset *default_fontset;
Packit Service a721b1
Packit Service a721b1
static MPlist *fontset_list;
Packit Service a721b1
Packit Service a721b1
struct MRealizedFontset
Packit Service a721b1
{
Packit Service a721b1
  /* Fontset from which the realized fontset is realized.  */
Packit Service a721b1
  MFontset *fontset;
Packit Service a721b1
Packit Service a721b1
  /* Initialized to <fontset>->tick.  */
Packit Service a721b1
  unsigned tick;
Packit Service a721b1
Packit Service a721b1
  /* Font spec that must be satisfied, or NULL.  */
Packit Service a721b1
  MFont *spec;
Packit Service a721b1
Packit Service a721b1
  /* Font spec requested by a face.  */
Packit Service a721b1
  MFont request;
Packit Service a721b1
Packit Service a721b1
  /* The frame on which the realized fontset is realized.  */
Packit Service a721b1
  MFrame *frame;
Packit Service a721b1
Packit Service a721b1
  MPlist *per_script;
Packit Service a721b1
Packit Service a721b1
  MPlist *per_charset;
Packit Service a721b1
Packit Service a721b1
  MPlist *fallback;
Packit Service a721b1
};
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
static MPlist *
Packit Service a721b1
load_font_group (MPlist *plist, MPlist *elt)
Packit Service a721b1
{
Packit Service a721b1
  MPLIST_DO (elt, elt)
Packit Service a721b1
    {
Packit Service a721b1
      /* ELT ::= ( FONT-SPEC [ LAYOUTER ] ) ...  */
Packit Service a721b1
      MPlist *elt2;
Packit Service a721b1
      MFont *font;
Packit Service a721b1
      MSymbol layouter_name;
Packit Service a721b1
Packit Service a721b1
      if (! MPLIST_PLIST_P (elt))
Packit Service a721b1
	MWARNING (MERROR_FONTSET);
Packit Service a721b1
      elt2 = MPLIST_PLIST (elt);
Packit Service a721b1
      if (! MPLIST_PLIST_P (elt2))
Packit Service a721b1
	MWARNING (MERROR_FONTSET);
Packit Service a721b1
      MSTRUCT_CALLOC (font, MERROR_FONTSET);
Packit Service a721b1
      mfont__set_spec_from_plist (font, MPLIST_PLIST (elt2));
Packit Service a721b1
      elt2 = MPLIST_NEXT (elt2);
Packit Service a721b1
      layouter_name = Mt;
Packit Service a721b1
      if (MPLIST_SYMBOL_P (elt2))
Packit Service a721b1
	layouter_name = MPLIST_SYMBOL (elt2);
Packit Service a721b1
      if (layouter_name == Mnil)
Packit Service a721b1
	layouter_name = Mt;
Packit Service a721b1
      plist = mplist_add (plist, layouter_name, font);
Packit Service a721b1
      continue;
Packit Service a721b1
    warning:
Packit Service a721b1
      /* ANSI-C requires some statement after a label.  */
Packit Service a721b1
      continue;
Packit Service a721b1
    }
Packit Service a721b1
  return plist;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/* Load FONTSET->per_script from the data in FONTSET->mdb.  */
Packit Service a721b1
Packit Service a721b1
static void
Packit Service a721b1
load_fontset_contents (MFontset *fontset)
Packit Service a721b1
{
Packit Service a721b1
  MPlist *per_script, *per_charset, *font_group;
Packit Service a721b1
  MPlist *fontset_def, *plist;
Packit Service a721b1
Packit Service a721b1
  fontset->per_script = per_script = mplist ();
Packit Service a721b1
  fontset->per_charset = per_charset = mplist ();
Packit Service a721b1
  fontset->fallback = mplist ();
Packit Service a721b1
  if (! (fontset_def = (MPlist *) mdatabase_load (fontset->mdb)))
Packit Service a721b1
    return;
Packit Service a721b1
Packit Service a721b1
  MPLIST_DO (plist, fontset_def)
Packit Service a721b1
    {
Packit Service a721b1
      /* PLIST ::=   ( SCRIPT ( LANGUAGE ( FONT-SPEC [LAYOUTER]) ... ) ... )
Packit Service a721b1
		   | ( CHARSET ( FONT-SPEC [LAYOUTER] ) ...)
Packit Service a721b1
		   | ( nil ( FONT-SPEC [LAYOUTER] ) ...)
Packit Service a721b1
	 FONT-SPEC :: = ( ... ) */
Packit Service a721b1
      MPlist *elt;
Packit Service a721b1
      MSymbol sym;
Packit Service a721b1
Packit Service a721b1
      if (! MPLIST_PLIST_P (plist))
Packit Service a721b1
	MWARNING (MERROR_FONTSET);
Packit Service a721b1
      elt = MPLIST_PLIST (plist);
Packit Service a721b1
      if (! MPLIST_SYMBOL_P (elt))
Packit Service a721b1
	MWARNING (MERROR_FONTSET);
Packit Service a721b1
      sym = MPLIST_SYMBOL (elt);
Packit Service a721b1
      elt = MPLIST_NEXT (elt);
Packit Service a721b1
      if (! MPLIST_PLIST_P (elt))
Packit Service a721b1
	MWARNING (MERROR_FONTSET);
Packit Service a721b1
      if (sym == Mnil)
Packit Service a721b1
	load_font_group (fontset->fallback, elt);
Packit Service a721b1
      else if (MPLIST_PLIST_P (MPLIST_PLIST (elt)))
Packit Service a721b1
	{
Packit Service a721b1
	  /* SYM is a charset.  */
Packit Service a721b1
	  font_group = mplist ();
Packit Service a721b1
	  per_charset = mplist_add (per_charset, sym, font_group);
Packit Service a721b1
	  load_font_group (font_group, elt);
Packit Service a721b1
	}
Packit Service a721b1
      else
Packit Service a721b1
	{
Packit Service a721b1
	  /* SYM is a script */
Packit Service a721b1
	  MPlist *per_lang = mplist ();
Packit Service a721b1
Packit Service a721b1
	  per_script = mplist_add (per_script, sym, per_lang);
Packit Service a721b1
	  MPLIST_DO (elt, elt)
Packit Service a721b1
	    {
Packit Service a721b1
	      /* ELT ::= ( LANGUAGE FONT-DEF ...) ... */
Packit Service a721b1
	      MPlist *elt2;
Packit Service a721b1
	      MSymbol lang;
Packit Service a721b1
Packit Service a721b1
	      if (! MPLIST_PLIST_P (elt))
Packit Service a721b1
		MWARNING (MERROR_FONTSET);
Packit Service a721b1
	      elt2 = MPLIST_PLIST (elt);
Packit Service a721b1
	      if (! MPLIST_SYMBOL_P (elt2))
Packit Service a721b1
		MWARNING (MERROR_FONTSET);
Packit Service a721b1
	      lang = MPLIST_SYMBOL (elt2);
Packit Service a721b1
	      if (lang == Mnil)
Packit Service a721b1
		lang = Mt;
Packit Service a721b1
	      font_group = mplist ();
Packit Service a721b1
	      mplist_add (per_lang, lang, font_group);
Packit Service a721b1
	      elt2 = MPLIST_NEXT (elt2);
Packit Service a721b1
	      load_font_group (font_group, elt2);
Packit Service a721b1
	    }
Packit Service a721b1
	}
Packit Service a721b1
      continue;
Packit Service a721b1
Packit Service a721b1
    warning:
Packit Service a721b1
      /* ANSI-C requires some statement after a label.  */
Packit Service a721b1
      continue;
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  M17N_OBJECT_UNREF (fontset_def);
Packit Service a721b1
  fontset->mdb = NULL;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
static void
Packit Service a721b1
free_fontset (void *object)
Packit Service a721b1
{
Packit Service a721b1
  MFontset *fontset = (MFontset *) object;
Packit Service a721b1
  MPlist *plist, *pl, *p;
Packit Service a721b1
Packit Service a721b1
  if (fontset->per_script)
Packit Service a721b1
    {
Packit Service a721b1
      MPLIST_DO (plist, fontset->per_script)
Packit Service a721b1
	{
Packit Service a721b1
	  MPLIST_DO (pl, MPLIST_PLIST (plist))
Packit Service a721b1
	    {
Packit Service a721b1
	      MPLIST_DO (p, MPLIST_PLIST (pl))
Packit Service a721b1
		free (MPLIST_VAL (p));
Packit Service a721b1
	      p = MPLIST_PLIST (pl);
Packit Service a721b1
	      M17N_OBJECT_UNREF (p);
Packit Service a721b1
	    }
Packit Service a721b1
	  pl = MPLIST_PLIST (plist);
Packit Service a721b1
	  M17N_OBJECT_UNREF (pl);
Packit Service a721b1
	}
Packit Service a721b1
      M17N_OBJECT_UNREF (fontset->per_script);
Packit Service a721b1
    }
Packit Service a721b1
  if (fontset->per_charset)
Packit Service a721b1
    {
Packit Service a721b1
      MPLIST_DO (pl, fontset->per_charset)
Packit Service a721b1
	{
Packit Service a721b1
	  MPLIST_DO (p, MPLIST_PLIST (pl))
Packit Service a721b1
	    free (MPLIST_VAL (p));
Packit Service a721b1
	  p = MPLIST_PLIST (p);
Packit Service a721b1
	  M17N_OBJECT_UNREF (p);
Packit Service a721b1
	}
Packit Service a721b1
      M17N_OBJECT_UNREF (fontset->per_charset);
Packit Service a721b1
    }
Packit Service a721b1
  if (fontset->fallback)
Packit Service a721b1
    {
Packit Service a721b1
      MPLIST_DO (p, fontset->fallback)
Packit Service a721b1
	free (MPLIST_VAL (p));
Packit Service a721b1
      M17N_OBJECT_UNREF (fontset->fallback);
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  plist = mplist_find_by_key (fontset_list, fontset->name);
Packit Service a721b1
  if (! plist)
Packit Service a721b1
    mdebug_hook ();
Packit Service a721b1
  mplist_pop (plist);
Packit Service a721b1
  if (MPLIST_TAIL_P (fontset_list))
Packit Service a721b1
    {
Packit Service a721b1
      M17N_OBJECT_UNREF (fontset_list);
Packit Service a721b1
      fontset_list = NULL;
Packit Service a721b1
    }
Packit Service a721b1
  M17N_OBJECT_UNREGISTER (fontset_table, fontset);
Packit Service a721b1
  free (object);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
static void
Packit Service a721b1
realize_fontset_elements (MFrame *frame, MRealizedFontset *realized)
Packit Service a721b1
{
Packit Service a721b1
  MFontset *fontset = realized->fontset;
Packit Service a721b1
  MPlist *per_script, *per_charset, *font_group;
Packit Service a721b1
  MPlist *plist, *p;
Packit Service a721b1
Packit Service a721b1
  realized->per_script = per_script = mplist ();
Packit Service a721b1
  /* The actual elements of per_script are realized on demand.  */
Packit Service a721b1
#if 0
Packit Service a721b1
  MPLIST_DO (plist, fontset->per_script)
Packit Service a721b1
    {
Packit Service a721b1
      MPlist *pl;
Packit Service a721b1
Packit Service a721b1
      per_lang = mplist ();
Packit Service a721b1
      per_script = mplist_add (per_script, MPLIST_KEY (plist), per_lang);
Packit Service a721b1
      MPLIST_DO (pl, MPLIST_PLIST (plist))
Packit Service a721b1
	{
Packit Service a721b1
	  font_group = mplist ();
Packit Service a721b1
	  per_lang = mplist_add (per_lang, MPLIST_KEY (pl), font_group);
Packit Service a721b1
	  MPLIST_DO (p, MPLIST_PLIST (pl))
Packit Service a721b1
	    font_group = mplist_add (font_group,
Packit Service a721b1
				     MPLIST_KEY (p), MPLIST_VAL (p));
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
#endif
Packit Service a721b1
Packit Service a721b1
  realized->per_charset = per_charset = mplist ();
Packit Service a721b1
  MPLIST_DO (plist, fontset->per_charset)
Packit Service a721b1
    {
Packit Service a721b1
      font_group = mplist ();
Packit Service a721b1
      per_charset = mplist_add (per_charset, MPLIST_KEY (plist), font_group);
Packit Service a721b1
      MPLIST_DO (p, MPLIST_PLIST (plist))
Packit Service a721b1
	font_group = mplist_add (font_group, MPLIST_KEY (p), MPLIST_VAL (p));
Packit Service a721b1
    }
Packit Service a721b1
  realized->fallback = font_group = mplist ();
Packit Service a721b1
  MPLIST_DO (p, fontset->fallback)
Packit Service a721b1
    font_group = mplist_add (font_group, MPLIST_KEY (p), MPLIST_VAL (p));
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
/* Return a plist of fonts for SCRIPT in FONTSET.  The returned list
Packit Service a721b1
   is acutally a plist of languages vs font groups (which is a plist).
Packit Service a721b1
   If SCRIPT is nil, return a plist of fallback fonts.  If FONTSET
Packit Service a721b1
   doesn't record any fonts for SCRIPT, generate a proper font spec
Packit Service a721b1
   lists for X backend and FreeType backend.  */
Packit Service a721b1
Packit Service a721b1
MPlist *
Packit Service a721b1
get_per_script (MFontset *fontset, MSymbol script)
Packit Service a721b1
{
Packit Service a721b1
  MPlist *plist;
Packit Service a721b1
Packit Service a721b1
  if (script == Mnil)
Packit Service a721b1
    return fontset->fallback;
Packit Service a721b1
  plist = mplist_get (fontset->per_script, script);
Packit Service a721b1
  if (! plist)
Packit Service a721b1
    {
Packit Service a721b1
      int len = MSYMBOL_NAMELEN (script);
Packit Service a721b1
      char *cap = alloca (8 + len + 1);
Packit Service a721b1
      MSymbol capability;
Packit Service a721b1
      MFont *font;
Packit Service a721b1
      MPlist *pl, *p;
Packit Service a721b1
Packit Service a721b1
      sprintf (cap, ":script=%s", MSYMBOL_NAME (script));
Packit Service a721b1
      capability = msymbol (cap);
Packit Service a721b1
Packit Service a721b1
      pl = mplist ();
Packit Service a721b1
      MPLIST_DO (p, fontset->fallback)
Packit Service a721b1
	{
Packit Service a721b1
	  font = mfont_copy (MPLIST_VAL (p));
Packit Service a721b1
	  mfont_put_prop (font, Mregistry, Municode_bmp);
Packit Service a721b1
	  font->source = MFONT_SOURCE_FT;
Packit Service a721b1
	  font->capability = capability;
Packit Service a721b1
	  mplist_add (pl, Mt, font);
Packit Service a721b1
Packit Service a721b1
	  font = mfont_copy (MPLIST_VAL (p));
Packit Service a721b1
	  mfont_put_prop (font, Mregistry, Miso10646_1);
Packit Service a721b1
	  font->source = MFONT_SOURCE_X;
Packit Service a721b1
	  font->capability = capability;
Packit Service a721b1
	  mplist_add (pl, Mt, font);
Packit Service a721b1
	}
Packit Service a721b1
      plist = mplist ();
Packit Service a721b1
      mplist_add (plist, Mt, pl);
Packit Service a721b1
      mplist_add (fontset->per_script, script, plist);
Packit Service a721b1
    }
Packit Service a721b1
  return plist;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
static void
Packit Service a721b1
free_realized_fontset_elements (MRealizedFontset *realized)
Packit Service a721b1
{
Packit Service a721b1
  MPlist *plist, *pl, *p;
Packit Service a721b1
  MFont *font;
Packit Service a721b1
  MFontList *font_list;
Packit Service a721b1
Packit Service a721b1
  if (realized->per_script)
Packit Service a721b1
    {
Packit Service a721b1
      MPLIST_DO (plist, realized->per_script)
Packit Service a721b1
	{
Packit Service a721b1
	  MPLIST_DO (pl, MPLIST_PLIST (plist))
Packit Service a721b1
	    {
Packit Service a721b1
	      MPLIST_DO (p, MPLIST_PLIST (pl))
Packit Service a721b1
		{
Packit Service a721b1
		  font = MPLIST_VAL (p);
Packit Service a721b1
		  if (font->type == MFONT_TYPE_OBJECT)
Packit Service a721b1
		    {
Packit Service a721b1
		      font_list = (MFontList *) font;
Packit Service a721b1
		      free (font_list->fonts);
Packit Service a721b1
		      free (font_list);
Packit Service a721b1
		    }
Packit Service a721b1
		  /* This is to avoid freeing rfont again by the later
Packit Service a721b1
		     M17N_OBJECT_UNREF (p) */
Packit Service a721b1
		  MPLIST_KEY (p) = Mt;
Packit Service a721b1
		}
Packit Service a721b1
	      p = MPLIST_PLIST (pl);
Packit Service a721b1
	      M17N_OBJECT_UNREF (p);
Packit Service a721b1
	    }
Packit Service a721b1
	  pl = MPLIST_PLIST (plist);
Packit Service a721b1
	  M17N_OBJECT_UNREF (pl);
Packit Service a721b1
	}
Packit Service a721b1
      M17N_OBJECT_UNREF (realized->per_script);
Packit Service a721b1
    }
Packit Service a721b1
  if (realized->per_charset)
Packit Service a721b1
    {
Packit Service a721b1
      MPLIST_DO (plist, realized->per_charset)
Packit Service a721b1
	{
Packit Service a721b1
	  MPLIST_DO (pl, MPLIST_PLIST (plist))
Packit Service a721b1
	    {
Packit Service a721b1
	      font = MPLIST_VAL (pl);
Packit Service a721b1
	      if (font->type == MFONT_TYPE_OBJECT)
Packit Service a721b1
		{
Packit Service a721b1
		  font_list = (MFontList *) font;
Packit Service a721b1
		  free (font_list->fonts);
Packit Service a721b1
		  free (font_list);
Packit Service a721b1
		}
Packit Service a721b1
	      MPLIST_KEY (pl) = Mt;
Packit Service a721b1
	    }
Packit Service a721b1
	  pl = MPLIST_PLIST (plist);
Packit Service a721b1
	  M17N_OBJECT_UNREF (pl);
Packit Service a721b1
	}
Packit Service a721b1
      M17N_OBJECT_UNREF (realized->per_charset);
Packit Service a721b1
    }
Packit Service a721b1
  if (realized->fallback)
Packit Service a721b1
    {
Packit Service a721b1
      MPLIST_DO (plist, realized->fallback)
Packit Service a721b1
	{
Packit Service a721b1
	  font = MPLIST_VAL (plist);
Packit Service a721b1
	  if (font->type == MFONT_TYPE_OBJECT)
Packit Service a721b1
	    {
Packit Service a721b1
	      font_list = (MFontList *) font;
Packit Service a721b1
	      free (font_list->fonts);
Packit Service a721b1
	      free (font_list);
Packit Service a721b1
	    }
Packit Service a721b1
	  MPLIST_KEY (plist) = Mt;
Packit Service a721b1
	}
Packit Service a721b1
      M17N_OBJECT_UNREF (realized->fallback);
Packit Service a721b1
    }
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
static void
Packit Service a721b1
update_fontset_elements (MRealizedFontset *realized)
Packit Service a721b1
{
Packit Service a721b1
  free_realized_fontset_elements (realized);
Packit Service a721b1
  realize_fontset_elements (realized->frame, realized);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1

Packit Service a721b1
Packit Service a721b1
/* Internal API */
Packit Service a721b1
Packit Service a721b1
int
Packit Service a721b1
mfont__fontset_init ()
Packit Service a721b1
{
Packit Service a721b1
  M17N_OBJECT_ADD_ARRAY (fontset_table, "Fontset");
Packit Service a721b1
Packit Service a721b1
  Mfontset = msymbol ("fontset");
Packit Service a721b1
  Mfontset->managing_key = 1;
Packit Service a721b1
  fontset_list = mplist ();
Packit Service a721b1
  default_fontset = mfontset ("default");
Packit Service a721b1
  if (! default_fontset->mdb)
Packit Service a721b1
    {
Packit Service a721b1
      MFont font;
Packit Service a721b1
Packit Service a721b1
      MFONT_INIT (&font);
Packit Service a721b1
      mfont_put_prop (&font, Mregistry, msymbol ("iso8859-1"));
Packit Service a721b1
      mfontset_modify_entry (default_fontset, Mnil, Mnil, Mnil,
Packit Service a721b1
			     &font, Mnil, 1);
Packit Service a721b1
      mfont_put_prop (&font, Mregistry, msymbol ("iso10646-1"));
Packit Service a721b1
      mfontset_modify_entry (default_fontset, Mnil, Mnil, Mnil,
Packit Service a721b1
			     &font, Mnil, 1);
Packit Service a721b1
    }
Packit Service a721b1
  return 0;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
void
Packit Service a721b1
mfont__fontset_fini ()
Packit Service a721b1
{
Packit Service a721b1
  M17N_OBJECT_UNREF (default_fontset);
Packit Service a721b1
  default_fontset = NULL;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
MRealizedFontset *
Packit Service a721b1
mfont__realize_fontset (MFrame *frame, MFontset *fontset,
Packit Service a721b1
			MFace *face, MFont *spec)
Packit Service a721b1
{
Packit Service a721b1
  MRealizedFontset *realized;
Packit Service a721b1
  MFont request;
Packit Service a721b1
  MPlist *plist;
Packit Service a721b1
Packit Service a721b1
  if (fontset->mdb)
Packit Service a721b1
    load_fontset_contents (fontset);
Packit Service a721b1
Packit Service a721b1
  MFONT_INIT (&request);
Packit Service a721b1
  mfont__set_spec_from_face (&request, face);
Packit Service a721b1
  if (request.size <= 0)
Packit Service a721b1
    {
Packit Service a721b1
      mdebug_hook ();
Packit Service a721b1
      request.size = 120;
Packit Service a721b1
    }
Packit Service a721b1
  MPLIST_DO (plist, frame->realized_fontset_list)
Packit Service a721b1
    {
Packit Service a721b1
      realized = (MRealizedFontset *) MPLIST_VAL (plist);
Packit Service a721b1
      if (fontset->name == MPLIST_KEY (plist)
Packit Service a721b1
	  && ! memcmp (&request, &realized->request, sizeof (MFont))
Packit Service a721b1
	  && (realized->spec
Packit Service a721b1
	      ? (spec && ! memcmp (spec, &realized->spec, sizeof (MFont)))
Packit Service a721b1
	      : ! spec))
Packit Service a721b1
	return realized;
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  MSTRUCT_CALLOC (realized, MERROR_FONTSET);
Packit Service a721b1
  realized->fontset = fontset;
Packit Service a721b1
  M17N_OBJECT_REF (fontset);
Packit Service a721b1
  realized->tick = fontset->tick;
Packit Service a721b1
  if (spec)
Packit Service a721b1
    {
Packit Service a721b1
      MSTRUCT_CALLOC (realized->spec, MERROR_FONTSET);
Packit Service a721b1
      *realized->spec = *spec;
Packit Service a721b1
    }
Packit Service a721b1
  realized->request = request;
Packit Service a721b1
  realized->frame = frame;
Packit Service a721b1
  realize_fontset_elements (frame, realized);
Packit Service a721b1
  mplist_add (frame->realized_fontset_list, fontset->name, realized);
Packit Service a721b1
  return realized;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
void
Packit Service a721b1
mfont__free_realized_fontset (MRealizedFontset *realized)
Packit Service a721b1
{
Packit Service a721b1
  free_realized_fontset_elements (realized);
Packit Service a721b1
  M17N_OBJECT_UNREF (realized->fontset);
Packit Service a721b1
  if (realized->spec)
Packit Service a721b1
    free (realized->spec);
Packit Service a721b1
  free (realized);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
static MRealizedFont *
Packit Service a721b1
try_font_list (MFrame *frame, MFontList *font_list, MFont *request,
Packit Service a721b1
	       MSymbol layouter, MGlyph *g, int *num, int all, int exact)
Packit Service a721b1
{
Packit Service a721b1
  int i, j;
Packit Service a721b1
  MFont *font;
Packit Service a721b1
  MRealizedFont *rfont;
Packit Service a721b1
Packit Service a721b1
  for (i = 0; i < font_list->nfonts; i++)
Packit Service a721b1
    {
Packit Service a721b1
      if (font_list->fonts[i].font->type == MFONT_TYPE_SPEC)
Packit Service a721b1
	MFATAL (MERROR_FONT);
Packit Service a721b1
      if (exact)
Packit Service a721b1
	{
Packit Service a721b1
	  if (font_list->fonts[i].score > 0)
Packit Service a721b1
	    break;
Packit Service a721b1
	}
Packit Service a721b1
      else
Packit Service a721b1
	{
Packit Service a721b1
	  if (font_list->fonts[i].score == 0)
Packit Service a721b1
	    continue;
Packit Service a721b1
	}
Packit Service a721b1
      font = font_list->fonts[i].font;
Packit Service a721b1
      if (font->type == MFONT_TYPE_FAILURE)
Packit Service a721b1
	continue;
Packit Service a721b1
      /* Check if this font can display all glyphs.  */
Packit Service a721b1
      for (j = 0; j < *num; j++)
Packit Service a721b1
	{
Packit Service a721b1
	  int c = g[j].type == GLYPH_CHAR ? g[j].g.c : ' ';
Packit Service a721b1
	  MFLT *flt;
Packit Service a721b1
	  MCharTable *coverage;
Packit Service a721b1
Packit Service a721b1
	  if (layouter != Mt
Packit Service a721b1
	      ? ((flt = mflt_get (layouter))
Packit Service a721b1
		 ? (coverage = mflt_coverage (flt),
Packit Service a721b1
		    ! mchartable_lookup (coverage, c))
Packit Service a721b1
		 : 0)
Packit Service a721b1
	      : ! mfont__has_char (frame, font, &font_list->object, c))
Packit Service a721b1
	    break;
Packit Service a721b1
	}
Packit Service a721b1
      if (j == 0 && *num > 0)
Packit Service a721b1
	continue;
Packit Service a721b1
      if (j == *num || !all)
Packit Service a721b1
	{
Packit Service a721b1
	  MCharTable *coverage = NULL;
Packit Service a721b1
Packit Service a721b1
	  /* We found a font that can display the requested range of
Packit Service a721b1
	     glyphs.  */
Packit Service a721b1
	  if (font->type == MFONT_TYPE_REALIZED)
Packit Service a721b1
	    rfont = (MRealizedFont *) font;
Packit Service a721b1
	  else
Packit Service a721b1
	    {
Packit Service a721b1
	      rfont = mfont__open (frame, font, &font_list->object);
Packit Service a721b1
	      if (! rfont)
Packit Service a721b1
		continue;
Packit Service a721b1
	      font_list->fonts[i].font = (MFont *) rfont;
Packit Service a721b1
	    }
Packit Service a721b1
	  rfont->layouter = layouter == Mt ? Mnil : layouter;
Packit Service a721b1
	  if (rfont->layouter)
Packit Service a721b1
	    {
Packit Service a721b1
	      MFLT *flt = mflt_get (rfont->layouter);
Packit Service a721b1
Packit Service a721b1
	      if (flt)
Packit Service a721b1
		coverage = mflt_coverage (flt);
Packit Service a721b1
	    }
Packit Service a721b1
	  *num = j;
Packit Service a721b1
	  for (j = 0; j < *num; j++)
Packit Service a721b1
	    {
Packit Service a721b1
	      int c = g[j].type == GLYPH_CHAR ? g[j].g.c : ' ';
Packit Service a721b1
Packit Service a721b1
	      g[j].g.code = (coverage
Packit Service a721b1
			     ? (unsigned ) mchartable_lookup (coverage, c)
Packit Service a721b1
			     : mfont__encode_char (frame, (MFont *) rfont,
Packit Service a721b1
						   &font_list->object, c));
Packit Service a721b1
	    }
Packit Service a721b1
	  return rfont;
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
  return NULL;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
static MRealizedFont *
Packit Service a721b1
try_font_group (MRealizedFontset *realized, MFont *request,
Packit Service a721b1
		MPlist *font_group, MGlyph *g, int *num, int size)
Packit Service a721b1
{
Packit Service a721b1
  MFrame *frame = realized->frame;
Packit Service a721b1
  MFont *font;
Packit Service a721b1
  MFontList *font_list;
Packit Service a721b1
  MRealizedFont *rfont;
Packit Service a721b1
  MPlist *plist;
Packit Service a721b1
  MSymbol layouter;
Packit Service a721b1
  int best_score = -1, worst_score;
Packit Service a721b1
Packit Service a721b1
  for (plist = font_group; ! MPLIST_TAIL_P (plist); )
Packit Service a721b1
    {
Packit Service a721b1
      int this_score;
Packit Service a721b1
Packit Service a721b1
      layouter = MPLIST_KEY (plist);
Packit Service a721b1
      font = MPLIST_VAL (plist);
Packit Service a721b1
      if (font->type == MFONT_TYPE_SPEC)
Packit Service a721b1
	{
Packit Service a721b1
	  /* We have not yet made this entry a MFontList.  */
Packit Service a721b1
	  if (realized->spec)
Packit Service a721b1
	    {
Packit Service a721b1
	      MFont this = *font;
Packit Service a721b1
	      
Packit Service a721b1
	      if (mfont__merge (&this, realized->spec, 1) < 0)
Packit Service a721b1
		{
Packit Service a721b1
		  mplist_pop (plist);
Packit Service a721b1
		  continue;
Packit Service a721b1
		}
Packit Service a721b1
	      font_list = mfont__list (frame, &this, &this, size);
Packit Service a721b1
	    }
Packit Service a721b1
	  else
Packit Service a721b1
	    font_list = mfont__list (frame, font, request, size);
Packit Service a721b1
	  if (! font_list)
Packit Service a721b1
	    {
Packit Service a721b1
	      /* As there's no font matching this spec, remove this
Packit Service a721b1
		 element from the font group.  */
Packit Service a721b1
	      mplist_pop (plist);
Packit Service a721b1
	      continue;
Packit Service a721b1
	    }
Packit Service a721b1
	  MPLIST_VAL (plist) = font_list;
Packit Service a721b1
	}
Packit Service a721b1
      else
Packit Service a721b1
	font_list = (MFontList *) font;
Packit Service a721b1
Packit Service a721b1
      this_score = font_list->fonts[0].score;
Packit Service a721b1
      if ((this_score == 0)
Packit Service a721b1
	  && (rfont = try_font_list (frame, font_list, request,
Packit Service a721b1
				     layouter, g, num, 1, 1)))
Packit Service a721b1
	return rfont;
Packit Service a721b1
      if (best_score < 0)
Packit Service a721b1
	{
Packit Service a721b1
	  best_score = worst_score = this_score;
Packit Service a721b1
	  plist = MPLIST_NEXT (plist);
Packit Service a721b1
	}
Packit Service a721b1
      else if (this_score >= worst_score)
Packit Service a721b1
	{
Packit Service a721b1
	  worst_score = this_score;
Packit Service a721b1
	  plist = MPLIST_NEXT (plist);
Packit Service a721b1
	}
Packit Service a721b1
      else
Packit Service a721b1
	{
Packit Service a721b1
	  MPlist *pl;
Packit Service a721b1
Packit Service a721b1
	  MPLIST_DO (pl, font_group)
Packit Service a721b1
	    if (this_score < ((MFontList *) MPLIST_VAL (pl))->fonts[0].score)
Packit Service a721b1
	      break;
Packit Service a721b1
	  mplist_pop (plist);
Packit Service a721b1
	  mplist_push (pl, layouter, font_list);
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  /* We couldn't find an exact matching font that can display all
Packit Service a721b1
     glyphs.  Find one that can at least display all glyphs.  */
Packit Service a721b1
  MPLIST_DO (plist, font_group)
Packit Service a721b1
    {
Packit Service a721b1
      rfont = try_font_list (frame, MPLIST_VAL (plist), request,
Packit Service a721b1
			     MPLIST_KEY (plist), g, num, 1, 0);
Packit Service a721b1
      if (rfont)
Packit Service a721b1
	return rfont;
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  /* We couldn't find a font that can display all glyphs.  Find an
Packit Service a721b1
     exact matching font that can at least display the first
Packit Service a721b1
     glyph.  */
Packit Service a721b1
  MPLIST_DO (plist, font_group)
Packit Service a721b1
    {
Packit Service a721b1
      rfont = try_font_list (frame, MPLIST_VAL (plist), request,
Packit Service a721b1
			     MPLIST_KEY (plist), g, num, 0, 1);
Packit Service a721b1
      if (rfont)
Packit Service a721b1
	return rfont;
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  /* Find any font that can at least display the first glyph.  */
Packit Service a721b1
  MPLIST_DO (plist, font_group)
Packit Service a721b1
    {
Packit Service a721b1
      rfont = try_font_list (frame, MPLIST_VAL (plist), request,
Packit Service a721b1
			     MPLIST_KEY (plist), g, num, 0, 0);
Packit Service a721b1
      if (rfont)
Packit Service a721b1
	return rfont;
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  return NULL;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
MRealizedFont *
Packit Service a721b1
mfont__lookup_fontset (MRealizedFontset *realized, MGlyph *g, int *num,
Packit Service a721b1
		       MSymbol script, MSymbol language, MSymbol charset,
Packit Service a721b1
		       int size, int ignore_fallback)
Packit Service a721b1
{
Packit Service a721b1
  MCharset *preferred_charset = (charset == Mnil ? NULL : MCHARSET (charset));
Packit Service a721b1
  MPlist *per_charset, *per_script, *per_lang;
Packit Service a721b1
  MPlist *plist;
Packit Service a721b1
  MRealizedFont *rfont = NULL;
Packit Service a721b1
Packit Service a721b1
  if (MDEBUG_FLAG ())
Packit Service a721b1
    {
Packit Service a721b1
      int i;
Packit Service a721b1
Packit Service a721b1
      MDEBUG_PRINT1 (" [FONTSET] fontset looking up for %s:",
Packit Service a721b1
		     script ? script->name : "none");
Packit Service a721b1
      for (i = 0; i < *num; i++)
Packit Service a721b1
	MDEBUG_PRINT1 (" U+%04X", g[i].g.c);
Packit Service a721b1
      MDEBUG_PRINT ("\n");
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  if (realized->tick != realized->fontset->tick)
Packit Service a721b1
    update_fontset_elements (realized);
Packit Service a721b1
Packit Service a721b1
  if (preferred_charset
Packit Service a721b1
      && (per_charset = mplist_get (realized->per_charset, charset)) != NULL
Packit Service a721b1
      && (rfont = try_font_group (realized, &realized->request, per_charset,
Packit Service a721b1
				  g, num, size)))
Packit Service a721b1
    goto done;
Packit Service a721b1
Packit Service a721b1
  if (script != Mnil)
Packit Service a721b1
    {
Packit Service a721b1
      MFont request = realized->request;
Packit Service a721b1
Packit Service a721b1
      if (script != Mlatin)
Packit Service a721b1
	/* This is not appropriate for non-Latin scripts.  */
Packit Service a721b1
	request.property[MFONT_REGISTRY] = 0;
Packit Service a721b1
Packit Service a721b1
      per_script = mplist_get (realized->per_script, script);
Packit Service a721b1
      if (! per_script)
Packit Service a721b1
	{
Packit Service a721b1
	  per_script = mplist_copy (get_per_script (realized->fontset, script));
Packit Service a721b1
	  /* PER_SCRIPT ::= (LANGUAGE:(LAYOUTER:FONT-SPEC ...) ...) */
Packit Service a721b1
	  MPLIST_DO (plist, per_script)
Packit Service a721b1
	    MPLIST_VAL (plist) = mplist_copy (MPLIST_VAL (plist));
Packit Service a721b1
	  mplist_add (realized->per_script, script, per_script);
Packit Service a721b1
	}
Packit Service a721b1
Packit Service a721b1
      /* We prefer font groups in this order:
Packit Service a721b1
	  (1) group matching with LANGUAGE if LANGUAGE is not Mnil
Packit Service a721b1
	  (2) group for generic language
Packit Service a721b1
	  (3) group not matching with LANGUAGE  */
Packit Service a721b1
      if (language == Mnil)
Packit Service a721b1
	language = Mt;
Packit Service a721b1
      if ((per_lang = mplist_get (per_script, language))
Packit Service a721b1
	  && (rfont = try_font_group (realized, &request, per_lang,
Packit Service a721b1
				      g, num, size)))
Packit Service a721b1
	goto done;
Packit Service a721b1
Packit Service a721b1
      if (per_lang && *num > 1)
Packit Service a721b1
	*num = 1;
Packit Service a721b1
      if (language == Mt)
Packit Service a721b1
	{
Packit Service a721b1
	  /* Try the above (3) */
Packit Service a721b1
	  MPLIST_DO (plist, per_script)
Packit Service a721b1
	    if (MPLIST_KEY (plist) != language
Packit Service a721b1
		&& (rfont = try_font_group (realized, &request,
Packit Service a721b1
					    MPLIST_PLIST (plist),
Packit Service a721b1
					    g, num, size)))
Packit Service a721b1
	      goto done;
Packit Service a721b1
	}
Packit Service a721b1
      else
Packit Service a721b1
	{
Packit Service a721b1
	  /* At first try the above (2) */
Packit Service a721b1
	  if ((per_lang = mplist_get (per_script, Mt))
Packit Service a721b1
	      && (rfont = try_font_group (realized, &request, per_lang,
Packit Service a721b1
					  g, num, size)))
Packit Service a721b1
	    goto done;
Packit Service a721b1
Packit Service a721b1
	  if (per_lang && *num > 1)
Packit Service a721b1
	    *num = 1;
Packit Service a721b1
	  /* Then try the above (3) */
Packit Service a721b1
	  MPLIST_DO (plist, per_script)
Packit Service a721b1
	    if (MPLIST_KEY (plist) != language
Packit Service a721b1
		&& MPLIST_KEY (plist) != Mt
Packit Service a721b1
		&& (rfont = try_font_group (realized, &request,
Packit Service a721b1
					    MPLIST_PLIST (plist),
Packit Service a721b1
					    g, num, size)))
Packit Service a721b1
	      goto done;
Packit Service a721b1
	}
Packit Service a721b1
      if (ignore_fallback)
Packit Service a721b1
	goto done;
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  if (language != Mnil)
Packit Service a721b1
    /* Find a font group for this language from all scripts.  */
Packit Service a721b1
    MPLIST_DO (plist, realized->per_script)
Packit Service a721b1
      {
Packit Service a721b1
	MFont request = realized->request;
Packit Service a721b1
Packit Service a721b1
	if (MPLIST_KEY (plist) != Mlatin)
Packit Service a721b1
	  request.property[MFONT_FOUNDRY]
Packit Service a721b1
	    = request.property[MFONT_FAMILY]
Packit Service a721b1
	    = request.property[MFONT_FAMILY] = 0;
Packit Service a721b1
	if ((per_lang = mplist_get (MPLIST_PLIST (plist), language))
Packit Service a721b1
	    && (rfont = try_font_group (realized, &request, per_lang,
Packit Service a721b1
					g, num, size)))
Packit Service a721b1
	  goto done;
Packit Service a721b1
      }
Packit Service a721b1
Packit Service a721b1
  /* Try fallback fonts.  */
Packit Service a721b1
  rfont = try_font_group (realized, &realized->request,
Packit Service a721b1
			  realized->fallback, g, num, size);
Packit Service a721b1
 done:
Packit Service a721b1
  if (MDEBUG_FLAG ())
Packit Service a721b1
    {
Packit Service a721b1
      if (rfont)
Packit Service a721b1
	{
Packit Service a721b1
	  MSymbol family = mfont_get_prop (rfont->font, Mfamily);
Packit Service a721b1
	  MDEBUG_PRINT1 (" [FONTSET] found %s\n", family->name);
Packit Service a721b1
	}
Packit Service a721b1
      else
Packit Service a721b1
	MDEBUG_PRINT (" [FONTSET] not found\n");
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  return rfont;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
MRealizedFont *
Packit Service a721b1
get_font_from_group (MFrame *frame, MPlist *plist, MFont *font)
Packit Service a721b1
{
Packit Service a721b1
  MRealizedFont *rfont;
Packit Service a721b1
Packit Service a721b1
  MPLIST_DO (plist, plist)
Packit Service a721b1
    {
Packit Service a721b1
      MFont spec = *(MFont *) MPLIST_VAL (plist);
Packit Service a721b1
      if (mfont__merge (&spec, font, 1) < 0)
Packit Service a721b1
	continue;
Packit Service a721b1
      if (font->type == MFONT_TYPE_SPEC)
Packit Service a721b1
	rfont = (MRealizedFont *) mfont_find (frame, &spec, NULL, 0);
Packit Service a721b1
      else if (font->type == MFONT_TYPE_OBJECT)
Packit Service a721b1
	rfont = mfont__open (frame, font, &spec);
Packit Service a721b1
      else
Packit Service a721b1
	rfont = (MRealizedFont *) font;
Packit Service a721b1
      if (rfont
Packit Service a721b1
	  && (spec.capability == Mnil
Packit Service a721b1
	      || mfont__check_capability (rfont, spec.capability) == 0))
Packit Service a721b1
	{
Packit Service a721b1
	  rfont->layouter
Packit Service a721b1
	    = MPLIST_KEY (plist) == Mt ? Mnil : MPLIST_KEY (plist);
Packit Service a721b1
	  return rfont;
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
  return NULL;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
MRealizedFont *
Packit Service a721b1
mfontset__get_font (MFrame *frame, MFontset *fontset,
Packit Service a721b1
		    MSymbol script, MSymbol language, MFont *font,
Packit Service a721b1
		    int *best)
Packit Service a721b1
{
Packit Service a721b1
  MPlist *per_script, *per_lang;
Packit Service a721b1
  MRealizedFont *rfont;
Packit Service a721b1
Packit Service a721b1
  if (best)
Packit Service a721b1
    *best = 0;
Packit Service a721b1
Packit Service a721b1
  if (language == Mnil)
Packit Service a721b1
    language = Mt;
Packit Service a721b1
Packit Service a721b1
  if (script != Mnil)
Packit Service a721b1
    {
Packit Service a721b1
      per_script = get_per_script (fontset, script);
Packit Service a721b1
      if ((per_lang = mplist_get (per_script, language))
Packit Service a721b1
	  && (rfont = get_font_from_group (frame, per_lang, font)))
Packit Service a721b1
	{
Packit Service a721b1
	  if (best)
Packit Service a721b1
	    *best = 1;
Packit Service a721b1
	  return rfont;
Packit Service a721b1
	}
Packit Service a721b1
      if (best)
Packit Service a721b1
	*best = per_lang ? 0 : 1;
Packit Service a721b1
      if (language == Mt)
Packit Service a721b1
	{
Packit Service a721b1
	  MPLIST_DO (per_script, per_script)
Packit Service a721b1
	    if (MPLIST_KEY (per_script) != language
Packit Service a721b1
		&& (rfont = get_font_from_group (frame,
Packit Service a721b1
						 MPLIST_PLIST (per_script),
Packit Service a721b1
						 font)))
Packit Service a721b1
	      return rfont;
Packit Service a721b1
	}
Packit Service a721b1
      else
Packit Service a721b1
	{
Packit Service a721b1
	  if ((per_lang = mplist_get (per_script, Mt))
Packit Service a721b1
	      && (rfont = get_font_from_group (frame, per_lang, font)))
Packit Service a721b1
	    return rfont;
Packit Service a721b1
	  if (best)
Packit Service a721b1
	    *best = 0;
Packit Service a721b1
	  MPLIST_DO (per_script, per_script)
Packit Service a721b1
	    if (MPLIST_KEY (per_script) != language
Packit Service a721b1
		&& MPLIST_KEY (per_script) != Mt
Packit Service a721b1
		&& (rfont = get_font_from_group (frame,
Packit Service a721b1
						 MPLIST_PLIST (per_script),
Packit Service a721b1
						 font)))
Packit Service a721b1
	      return rfont;
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  if (language != Mt)
Packit Service a721b1
    MPLIST_DO (per_script, fontset->per_script)
Packit Service a721b1
      {
Packit Service a721b1
	if ((per_lang = mplist_get (MPLIST_PLIST (per_script), language))
Packit Service a721b1
	    && (rfont = get_font_from_group (frame, per_lang, font)))
Packit Service a721b1
	  {
Packit Service a721b1
	    if (best)
Packit Service a721b1
	      *best = 1;
Packit Service a721b1
	    return rfont;
Packit Service a721b1
	  }
Packit Service a721b1
      }
Packit Service a721b1
Packit Service a721b1
  if (best)
Packit Service a721b1
    *best = 0;
Packit Service a721b1
  if ((rfont = get_font_from_group (frame, fontset->fallback, font)))
Packit Service a721b1
    return rfont;
Packit Service a721b1
  return NULL;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
/*** @} */
Packit Service a721b1
#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
Packit Service a721b1
Packit Service a721b1

Packit Service a721b1
/* External API */
Packit Service a721b1
Packit Service a721b1
/*** @addtogroup m17nFontset */
Packit Service a721b1
/*** @{ */
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Return a fontset.
Packit Service a721b1
Packit Service a721b1
    The mfontset () function returns a pointer to a fontset object of
Packit Service a721b1
    name $NAME.  If $NAME is @c NULL, it returns a pointer to the
Packit Service a721b1
    default fontset.
Packit Service a721b1
Packit Service a721b1
    If no fontset has the name $NAME, a new one is created.  At that
Packit Service a721b1
    time, if there exists a data \<@c fontset, $NAME\> in the m17n
Packit Service a721b1
    database, the fontset contents are initialized according to the
Packit Service a721b1
    data.  If no such data exists, the fontset contents are left
Packit Service a721b1
    vacant.
Packit Service a721b1
Packit Service a721b1
    The macro M17N_INIT () creates the default fontset.  An
Packit Service a721b1
    application program can modify it before the first call of 
Packit Service a721b1
    mframe ().
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    This function returns a pointer to the found or newly created
Packit Service a721b1
    fontset.  */
Packit Service a721b1
/***ja 
Packit Service a721b1
    @brief フォントセットを返す.
Packit Service a721b1
Packit Service a721b1
    関数 mfontset () は名前 $NAME を持つフォントセットオブジェクトへのポインタを返す。 
Packit Service a721b1
    $NAME が @c NULL ならば、デフォルトフォントセットへのポインタを返す。
Packit Service a721b1
Packit Service a721b1
    $NAME という名前を持つフォントセットがなければ、新しいものが作られる。その際、
Packit Service a721b1
    m17n データベースに \<@c fontset, $NAME\> 
Packit Service a721b1
    というデータがあれば、フォントセットはそのデータに沿って初期化される。
Packit Service a721b1
    なければ、空のままにされる。
Packit Service a721b1
Packit Service a721b1
    マクロ M17N_INIT () はデフォルトのフォントセットを作る。アプリケーションプログラムは
Packit Service a721b1
    mframe () を初めて呼ぶまでの間はデフォルトフォントセットを変更することができる。
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    この関数は見つかった、あるいは作ったフォントセットへのポインタを返す。
Packit Service a721b1
     */
Packit Service a721b1
Packit Service a721b1
MFontset *
Packit Service a721b1
mfontset (char *name)
Packit Service a721b1
{
Packit Service a721b1
  MSymbol sym;
Packit Service a721b1
  MFontset *fontset;
Packit Service a721b1
Packit Service a721b1
  if (! name)
Packit Service a721b1
    {
Packit Service a721b1
      fontset = default_fontset;
Packit Service a721b1
      M17N_OBJECT_REF (fontset);
Packit Service a721b1
    }
Packit Service a721b1
  else
Packit Service a721b1
    {
Packit Service a721b1
      sym = msymbol (name);
Packit Service a721b1
      fontset = mplist_get (fontset_list, sym);
Packit Service a721b1
      if (fontset)
Packit Service a721b1
	M17N_OBJECT_REF (fontset);
Packit Service a721b1
      else
Packit Service a721b1
	{
Packit Service a721b1
	  M17N_OBJECT (fontset, free_fontset, MERROR_FONTSET);
Packit Service a721b1
	  M17N_OBJECT_REGISTER (fontset_table, fontset);
Packit Service a721b1
	  fontset->name = sym;
Packit Service a721b1
	  fontset->mdb = mdatabase_find (Mfontset, sym, Mnil, Mnil);
Packit Service a721b1
	  if (! fontset->mdb)
Packit Service a721b1
	    {
Packit Service a721b1
	      fontset->per_script = mplist ();
Packit Service a721b1
	      fontset->per_charset = mplist ();
Packit Service a721b1
	      fontset->fallback = mplist ();
Packit Service a721b1
	    }
Packit Service a721b1
	  mplist_put (fontset_list, sym, fontset);
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
  return fontset;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Return the name of a fontset.
Packit Service a721b1
Packit Service a721b1
    The mfontset_name () function returns the name of fontset $FONTSET.  */
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief フォントセットの名前を返す.
Packit Service a721b1
Packit Service a721b1
    関数 mfontset_name () はフォントセット $FONTSET の名前を返す。  */
Packit Service a721b1
MSymbol
Packit Service a721b1
mfontset_name (MFontset *fontset)
Packit Service a721b1
{
Packit Service a721b1
  return fontset->name;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Make a copy of a fontset.
Packit Service a721b1
Packit Service a721b1
    The mfontset_copy () function makes a copy of fontset $FONTSET, gives it a
Packit Service a721b1
    name $NAME, and returns a pointer to the created copy.  $NAME must
Packit Service a721b1
    not be a name of existing fontset.  In such case, this function
Packit Service a721b1
    returns NULL without making a copy.  */
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief フォントセットのコピーを作る.
Packit Service a721b1
Packit Service a721b1
    関数 mfontset_copy () はフォントセット $FONTSET のコピーを作って、名前
Packit Service a721b1
    $NAME を与え、そのコピーへのポインタを返す。$NAME 
Packit Service a721b1
    は既存のフォントセットの名前であってはならない。そのような場合にはコピーを作らずに
Packit Service a721b1
    NULL を返す。  */
Packit Service a721b1
Packit Service a721b1
MFontset *
Packit Service a721b1
mfontset_copy (MFontset *fontset, char *name)
Packit Service a721b1
{
Packit Service a721b1
  MSymbol sym = msymbol (name);
Packit Service a721b1
  MFontset *copy = mplist_get (fontset_list, sym);
Packit Service a721b1
  MPlist *plist, *pl, *p;
Packit Service a721b1
Packit Service a721b1
  if (copy)
Packit Service a721b1
    return NULL;
Packit Service a721b1
  M17N_OBJECT (copy, free_fontset, MERROR_FONTSET);
Packit Service a721b1
  M17N_OBJECT_REGISTER (fontset_table, copy);
Packit Service a721b1
  copy->name = sym;
Packit Service a721b1
Packit Service a721b1
  if (fontset->mdb)
Packit Service a721b1
    load_fontset_contents (fontset);
Packit Service a721b1
Packit Service a721b1
  if (fontset->per_script)
Packit Service a721b1
    {
Packit Service a721b1
      copy->per_script = mplist ();
Packit Service a721b1
      MPLIST_DO (plist, fontset->per_script)
Packit Service a721b1
        {
Packit Service a721b1
	  MPlist *per_lang = mplist ();
Packit Service a721b1
Packit Service a721b1
	  mplist_add (copy->per_script, MPLIST_KEY (plist), per_lang);
Packit Service a721b1
	  MPLIST_DO (pl, MPLIST_PLIST (plist))
Packit Service a721b1
	    {
Packit Service a721b1
	      MPlist *font_group = mplist ();
Packit Service a721b1
Packit Service a721b1
	      per_lang = mplist_add (per_lang, MPLIST_KEY (pl), font_group);
Packit Service a721b1
	      MPLIST_DO (p, MPLIST_PLIST (pl))
Packit Service a721b1
		font_group = mplist_add (font_group, MPLIST_KEY (p),
Packit Service a721b1
					 mfont_copy (MPLIST_VAL (p)));
Packit Service a721b1
	    }
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
  if (fontset->per_charset)
Packit Service a721b1
    {
Packit Service a721b1
      MPlist *per_charset = mplist ();
Packit Service a721b1
Packit Service a721b1
      copy->per_charset = per_charset;
Packit Service a721b1
      MPLIST_DO (pl, fontset->per_charset)
Packit Service a721b1
	{
Packit Service a721b1
	  MPlist *font_group = mplist ();
Packit Service a721b1
Packit Service a721b1
	  per_charset = mplist_add (per_charset, MPLIST_KEY (pl), font_group);
Packit Service a721b1
	  MPLIST_DO (p, MPLIST_PLIST (pl))
Packit Service a721b1
	    font_group = mplist_add (font_group, MPLIST_KEY (p),
Packit Service a721b1
				     mfont_copy (MPLIST_VAL (p)));
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
  if (fontset->fallback)
Packit Service a721b1
    {
Packit Service a721b1
      MPlist *font_group = mplist ();
Packit Service a721b1
Packit Service a721b1
      copy->fallback = font_group;
Packit Service a721b1
      MPLIST_DO (p, fontset->fallback)
Packit Service a721b1
	font_group = mplist_add (font_group, MPLIST_KEY (p),
Packit Service a721b1
				 mfont_copy (MPLIST_VAL (p)));
Packit Service a721b1
    }				 
Packit Service a721b1
Packit Service a721b1
  mplist_put (fontset_list, sym, copy);
Packit Service a721b1
  return copy;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Modify the contents of a fontset.
Packit Service a721b1
Packit Service a721b1
    The mfontset_modify_entry () function associates, in fontset
Packit Service a721b1
    $FONTSET, a copy of $FONT with the $SCRIPT / $LANGUAGE pair or
Packit Service a721b1
    with $CHARSET.
Packit Service a721b1
Packit Service a721b1
    Each font in a fontset is associated with a particular
Packit Service a721b1
    script/language pair, with a particular charset, or with the
Packit Service a721b1
    symbol @c Mnil.  The fonts that are associated with the same item
Packit Service a721b1
    make a group.
Packit Service a721b1
Packit Service a721b1
    If $SCRIPT is not @c Mnil, it must be a symbol identifying a
Packit Service a721b1
    script.  In this case, $LANGUAGE is either a symbol identifying a
Packit Service a721b1
    language or @c Mnil, and $FONT is associated with the $SCRIPT /
Packit Service a721b1
    $LANGUAGE pair.
Packit Service a721b1
Packit Service a721b1
    If $CHARSET is not @c Mnil, it must be a symbol representing a
Packit Service a721b1
    charset object.  In this case, $FONT is associated with that
Packit Service a721b1
    charset.
Packit Service a721b1
Packit Service a721b1
    If both $SCRIPT and $CHARSET are not @c Mnil, two copies of $FONT
Packit Service a721b1
    are created.  Then one is associated with the $SCRIPT / $LANGUAGE
Packit Service a721b1
    pair and the other with that charset.
Packit Service a721b1
Packit Service a721b1
    If both $SCRIPT and $CHARSET are @c Mnil, $FONT is associated with
Packit Service a721b1
    @c Mnil.  This kind of fonts are called @e fallback @e fonts.
Packit Service a721b1
Packit Service a721b1
    The argument $HOW specifies the priority of $FONT.  If $HOW is
Packit Service a721b1
    positive, $FONT has the highest priority in the group of fonts
Packit Service a721b1
    that are associated with the same item.  If $HOW is negative,
Packit Service a721b1
    $FONT has the lowest priority.  If $HOW is zero, $FONT becomes the
Packit Service a721b1
    only available font for the associated item; all the other fonts
Packit Service a721b1
    are removed from the group.
Packit Service a721b1
Packit Service a721b1
    If $LAYOUTER_NAME is not @c Mnil, it must be a symbol representing
Packit Service a721b1
    a @ref mdbFLT (font layout table).  In that case, if $FONT is
Packit Service a721b1
    selected for drawing an M-text, that font layout table is used to
Packit Service a721b1
    generate a glyph code sequence from a character sequence.
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    If the operation was successful, mfontset_modify_entry () returns 0.
Packit Service a721b1
    Otherwise it returns -1 and assigns an error code to the external
Packit Service a721b1
    variable #merror_code.  */
Packit Service a721b1
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief フォントセットの内容を変更する.
Packit Service a721b1
Packit Service a721b1
    関数 mfontset_modify_entry () は、$LANGUAGE と $SCRIPT の組み合わせ、または
Packit Service a721b1
    $CHARSET に対して $FONT のコピーを使うように、フォントセット $FONTSET を設定する。
Packit Service a721b1
Packit Service a721b1
    フォントセット中の各フォントは、特定のスクリプトと言語のペア、特定の文字セット、シンボル
Packit Service a721b1
    @c Mnil のいずれかと関連付けられている。同じものと関連付けられたフォントはグループを構成する。
Packit Service a721b1
Packit Service a721b1
    $SCRIPT は @c Mnil であるか、スクリプトを特定するシンボルである。
Packit Service a721b1
    シンボルである場合には、$LANGUAGE は言語を特定するシンボルか @c
Packit Service a721b1
    Mnil であり、$FONT はthe $SCRIPT / $LANGUAGE ペアに関連付けられる。
Packit Service a721b1
Packit Service a721b1
    $CHARSET は @c Mnil であるか、文字セットオブジェクトを表すシンボルである。
Packit Service a721b1
    シンボルである場合には $FONT はその文字セットと関連付けられる。
Packit Service a721b1
Packit Service a721b1
    $SCRIPT と $CHARSET の双方が @c Mnil でない場合には $FONT 
Packit Service a721b1
    のコピーが2つ作られ、それぞれ $SCRIPT / $LANGUAGE 
Packit Service a721b1
    ペアと文字セットに関連付けられる。
Packit Service a721b1
Packit Service a721b1
    $SCRIPT と $CHARSET の双方が @c Mnil ならば、 $FONT は @c Mnil 
Packit Service a721b1
    と関連付けられる。この種のフォントは @e fallback @e font と呼ばれる。
Packit Service a721b1
Packit Service a721b1
    引数 $HOW は $FONT の優先度を指定する。$HOW が正ならば、$FONT 
Packit Service a721b1
    は同じものと関連付けられたグループ中で最高の優先度を持つ。$HOW 
Packit Service a721b1
    が負ならば、最低の優先度を持つ。$HOW が 0 ならば、$FONT 
Packit Service a721b1
    は関連付けられたものに対する唯一の利用可能なフォントとなり、他のフォントはグループから取り除かれる。
Packit Service a721b1
Packit Service a721b1
    $LAYOUTER_NAME は @c Mnil であるか、@ref mdbFLT 
Packit Service a721b1
    (フォントレイアウトテーブル)を示すシンボルである。シンボルであれば、$FONT を用いて
Packit Service a721b1
    M-text を表示する際には、そのフォントレイアウトテーブルを使って文字列からグリフコード列を生成する。
Packit Service a721b1
Packit Service a721b1
    @return 
Packit Service a721b1
    処理が成功したとき、mfontset_modify_entry () は 0 を返す。
Packit Service a721b1
    失敗したときは -1 を返し、外部変数 #merror_code にエラーコードを設定する。  */
Packit Service a721b1
Packit Service a721b1
/***
Packit Service a721b1
    @errors
Packit Service a721b1
    @c MERROR_SYMBOL  */
Packit Service a721b1
Packit Service a721b1
int
Packit Service a721b1
mfontset_modify_entry (MFontset *fontset,
Packit Service a721b1
		       MSymbol script, MSymbol language, MSymbol charset,
Packit Service a721b1
		       MFont *spec, MSymbol layouter_name,
Packit Service a721b1
		       int how)
Packit Service a721b1
{
Packit Service a721b1
  MPlist *per_lang, *plist[3];
Packit Service a721b1
  MFont *font = NULL;
Packit Service a721b1
  int i;
Packit Service a721b1
Packit Service a721b1
  if (fontset->mdb)
Packit Service a721b1
    load_fontset_contents (fontset);
Packit Service a721b1
Packit Service a721b1
  i = 0;
Packit Service a721b1
  if (script != Mnil)
Packit Service a721b1
    {
Packit Service a721b1
      if (language == Mnil)
Packit Service a721b1
	language = Mt;
Packit Service a721b1
      per_lang = mplist_get (fontset->per_script, script);
Packit Service a721b1
      if (! per_lang)
Packit Service a721b1
	mplist_add (fontset->per_script, script, per_lang = mplist ());
Packit Service a721b1
      plist[i] = mplist_get (per_lang, language);
Packit Service a721b1
      if (! plist[i])
Packit Service a721b1
	mplist_add (per_lang, language, plist[i] = mplist ());
Packit Service a721b1
      i++;
Packit Service a721b1
    }
Packit Service a721b1
  if (charset != Mnil)
Packit Service a721b1
    {
Packit Service a721b1
      plist[i] = mplist_get (fontset->per_charset, charset);
Packit Service a721b1
      if (! plist[i])
Packit Service a721b1
	mplist_add (fontset->per_charset, charset, plist[i] = mplist ());
Packit Service a721b1
      i++;
Packit Service a721b1
    }
Packit Service a721b1
  if (script == Mnil && charset == Mnil)
Packit Service a721b1
    {
Packit Service a721b1
      plist[i++] = fontset->fallback;
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  if (layouter_name == Mnil)
Packit Service a721b1
    layouter_name = Mt;
Packit Service a721b1
  for (i--; i >= 0; i--)
Packit Service a721b1
    {
Packit Service a721b1
      font = mfont_copy (spec);
Packit Service a721b1
      font->type = MFONT_TYPE_SPEC;
Packit Service a721b1
      if (how == 1)
Packit Service a721b1
	mplist_push (plist[i], layouter_name, font);
Packit Service a721b1
      else if (how == -1)
Packit Service a721b1
	mplist_add (plist[i], layouter_name, font);
Packit Service a721b1
      else
Packit Service a721b1
	{
Packit Service a721b1
	  MPlist *pl;
Packit Service a721b1
Packit Service a721b1
	  MPLIST_DO (pl, plist[i])
Packit Service a721b1
	    free (MPLIST_VAL (pl));
Packit Service a721b1
	  mplist_set (plist[i], Mnil, NULL);
Packit Service a721b1
	  mplist_add (plist[i], layouter_name, font);
Packit Service a721b1
	}
Packit Service a721b1
    }
Packit Service a721b1
Packit Service a721b1
  fontset->tick++;
Packit Service a721b1
  return 0;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*=*/
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Lookup a fontset.
Packit Service a721b1
Packit Service a721b1
    The mfontset_lookup () function lookups $FONTSET and returns a
Packit Service a721b1
    plist that describes the contents of $FONTSET corresponding to the
Packit Service a721b1
    specified script, language, and charset.
Packit Service a721b1
Packit Service a721b1
    If $SCRIPT is @c Mt, keys of the returned plist are script name
Packit Service a721b1
    symbols for which some fonts are specified and values are NULL.
Packit Service a721b1
Packit Service a721b1
    If $SCRIPT is a script name symbol, the returned plist is decided
Packit Service a721b1
    by $LANGUAGE.
Packit Service a721b1
    
Packit Service a721b1
    @li If $LANGUAGE is @c Mt, keys of the plist are language name
Packit Service a721b1
    symbols for which some fonts are specified and values are NULL.  A
Packit Service a721b1
    key may be @c Mt which means some fallback fonts are specified for
Packit Service a721b1
    the script.
Packit Service a721b1
Packit Service a721b1
    @li If $LANGUAGE is a language name symbol, the plist is a @c
Packit Service a721b1
    FONT-GROUP for the specified script and language.  @c FONT-GROUP
Packit Service a721b1
    is a plist whose keys are FLT (FontLayoutTable) name symbols (@c
Packit Service a721b1
    Mt if no FLT is associated with the font) and values are pointers
Packit Service a721b1
    to #MFont.
Packit Service a721b1
Packit Service a721b1
    @li If $LANGUAGE is @c Mnil, the plist is fallback @c FONT-GROUP
Packit Service a721b1
    for the script. 
Packit Service a721b1
Packit Service a721b1
    If $SCRIPT is @c Mnil, the returned plist is decided as below.
Packit Service a721b1
Packit Service a721b1
    @li If $CHARSET is @c Mt, keys of the returned plist are charset name
Packit Service a721b1
    symbols for which some fonts are specified and values are NULL.
Packit Service a721b1
Packit Service a721b1
    @li If $CHARSET is a charset name symbol, the plist is a @c FONT-GROUP for
Packit Service a721b1
    the charset.
Packit Service a721b1
Packit Service a721b1
    @li If $CHARSET is @c Mnil, the plist is a fallback @c FONT-GROUP.
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    It returns a plist describing the contents of a fontset.  The
Packit Service a721b1
    plist should be freed by m17n_object_unref ().  */
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief フォントセットを検索する.
Packit Service a721b1
Packit Service a721b1
    関数 mfontset_lookup () は $FONTSET を検索し、$FONTSET 
Packit Service a721b1
    の内容のうち指定したスクリプト、言語、文字セットに対応する部分を表す
Packit Service a721b1
    plist を返す。
Packit Service a721b1
Packit Service a721b1
    $SCRIPT が @c Mt ならば、返す plist 
Packit Service a721b1
    のキーはフォントが指定されているスクリプト名のシンボルであり、値は
Packit Service a721b1
    NULL である。
Packit Service a721b1
Packit Service a721b1
    $SCRIPT がスクリプト名のシンボルであれば、返す 
Packit Service a721b1
    plist は $LANGUAGEによって定まる。
Packit Service a721b1
    
Packit Service a721b1
    @li $LANGUAGE が @c Mt ならば、plist 
Packit Service a721b1
    のキーはフォントが指定されている言語名のシンボルであり、値は
Packit Service a721b1
    NULL である。キーは @c Mt
Packit Service a721b1
    であることもあり、その場合そのスクリプトにフォールバックフォントがあることを意味する。
Packit Service a721b1
Packit Service a721b1
    @li $LANGUAGE が言語名のシンボルならば、plist は指定のスクリプトと言語に対する
Packit Service a721b1
    @c FONT-GROUP である。@c FONT-GROUP とは、キーが FLT
Packit Service a721b1
    (FontLayoutTable) 名のシンボルであり、値が #MFont 
Packit Service a721b1
    へのポインタであるような plist である。ただしフォントに FLT 
Packit Service a721b1
    が対応付けられていない時には、キーは @c Mt になる。
Packit Service a721b1
Packit Service a721b1
    @li $LANGUAGE が @c Mnil ならば、plist はそのスクリプト用のフォールバック
Packit Service a721b1
    @c FONT-GROUP である。
Packit Service a721b1
Packit Service a721b1
    $SCRIPT が @c Mnil ならば、返す plist は以下のように定まる。
Packit Service a721b1
Packit Service a721b1
    @li $CHARSET が @c Mt ならば、plist 
Packit Service a721b1
    のキーはフォントが指定されている文字セット名のシンボルであり、値は
Packit Service a721b1
    NULL である。
Packit Service a721b1
Packit Service a721b1
    @li $CHARSET が文字セット名のシンボルならば、plist はその文字セット用の 
Packit Service a721b1
    @c FONT-GROUP である。
Packit Service a721b1
Packit Service a721b1
    @li $CHARSET が @c Mnil ならば、plist はフォールバック @c FONT-GROUP である。
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    この関数はフォントセットの内容を表す plist を返す。
Packit Service a721b1
    plist は m17n_object_unref () で解放されるべきである。  */
Packit Service a721b1
Packit Service a721b1
MPlist *
Packit Service a721b1
mfontset_lookup (MFontset *fontset,
Packit Service a721b1
		 MSymbol script, MSymbol language, MSymbol charset)
Packit Service a721b1
{
Packit Service a721b1
  MPlist *plist = mplist (), *pl, *p;
Packit Service a721b1
Packit Service a721b1
  if (fontset->mdb)
Packit Service a721b1
    load_fontset_contents (fontset);
Packit Service a721b1
  if (script == Mt)
Packit Service a721b1
    {
Packit Service a721b1
      if (! fontset->per_script)
Packit Service a721b1
	return plist;
Packit Service a721b1
      p = plist;
Packit Service a721b1
      MPLIST_DO (pl, fontset->per_script)
Packit Service a721b1
	p = mplist_add (p, MPLIST_KEY (pl), NULL);
Packit Service a721b1
      return plist;
Packit Service a721b1
    }
Packit Service a721b1
  if (script != Mnil)
Packit Service a721b1
    {
Packit Service a721b1
      pl = get_per_script (fontset, script);
Packit Service a721b1
      if (MPLIST_TAIL_P (pl))
Packit Service a721b1
	return plist;
Packit Service a721b1
      if (language == Mt)
Packit Service a721b1
	{
Packit Service a721b1
	  p = plist;
Packit Service a721b1
	  MPLIST_DO (pl, pl)
Packit Service a721b1
	    p = mplist_add (p, MPLIST_KEY (pl), NULL);
Packit Service a721b1
	  return plist;
Packit Service a721b1
	}
Packit Service a721b1
      if (language == Mnil)
Packit Service a721b1
	language = Mt;
Packit Service a721b1
      pl = mplist_get (pl, language);
Packit Service a721b1
    }
Packit Service a721b1
  else if (charset != Mnil)
Packit Service a721b1
    {
Packit Service a721b1
      if (! fontset->per_charset)
Packit Service a721b1
	return plist;
Packit Service a721b1
      if (charset == Mt)
Packit Service a721b1
	{
Packit Service a721b1
	  p = plist;
Packit Service a721b1
	  MPLIST_DO (pl, fontset->per_charset)
Packit Service a721b1
	    p = mplist_add (p, MPLIST_KEY (pl), NULL);
Packit Service a721b1
	  return plist;
Packit Service a721b1
	}
Packit Service a721b1
      pl = mplist_get (fontset->per_charset, charset);
Packit Service a721b1
    }
Packit Service a721b1
  else
Packit Service a721b1
    pl = fontset->fallback;
Packit Service a721b1
  if (! pl)
Packit Service a721b1
    return plist;
Packit Service a721b1
  return mplist_copy (pl);
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
Packit Service a721b1
/*** @} */
Packit Service a721b1
Packit Service a721b1
/*** @addtogroup m17nDebug */
Packit Service a721b1
/*=*/
Packit Service a721b1
/*** @{  */
Packit Service a721b1
Packit Service a721b1
/***en
Packit Service a721b1
    @brief Dump a fontset.
Packit Service a721b1
Packit Service a721b1
    The mdebug_dump_fontset () function prints fontset $FONTSET in a
Packit Service a721b1
    human readable way to the stderr or to what specified by the
Packit Service a721b1
    environment variable MDEBUG_OUTPUT_FILE.  $INDENT specifies how
Packit Service a721b1
    many columns to indent the lines but the first one.
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    This function returns $FONTSET.  */
Packit Service a721b1
/***ja
Packit Service a721b1
    @brief フォントセットをダンプする.
Packit Service a721b1
Packit Service a721b1
    関数 mdebug_dump_face () はフォントセット $FONTSET を標準エラー出力
Packit Service a721b1
    もしくは環境変数 MDEBUG_DUMP_FONT で指定されたファイルに人間に可読
Packit Service a721b1
    な形で出力する。 $INDENT は2行目以降のインデントを指定する。
Packit Service a721b1
Packit Service a721b1
    @return
Packit Service a721b1
    この関数は $FONTSET を返す。  */
Packit Service a721b1
Packit Service a721b1
MFontset *
Packit Service a721b1
mdebug_dump_fontset (MFontset *fontset, int indent)
Packit Service a721b1
{
Packit Service a721b1
  char *prefix = (char *) alloca (indent + 1);
Packit Service a721b1
  MPlist *plist, *pl, *p;
Packit Service a721b1
Packit Service a721b1
  memset (prefix, 32, indent);
Packit Service a721b1
  prefix[indent] = 0;
Packit Service a721b1
Packit Service a721b1
  fprintf (mdebug__output, "(fontset %s", fontset->name->name);
Packit Service a721b1
  if (fontset->per_script)
Packit Service a721b1
    MPLIST_DO (plist, fontset->per_script)
Packit Service a721b1
      {
Packit Service a721b1
	fprintf (mdebug__output, "\n  %s(%s", prefix, MPLIST_KEY (plist)->name);
Packit Service a721b1
	MPLIST_DO (pl, MPLIST_PLIST (plist))
Packit Service a721b1
	  {
Packit Service a721b1
	    fprintf (mdebug__output, "\n    %s(%s", prefix,
Packit Service a721b1
		     MPLIST_KEY (pl)->name);
Packit Service a721b1
	    MPLIST_DO (p, MPLIST_PLIST (pl))
Packit Service a721b1
	      {
Packit Service a721b1
		fprintf (mdebug__output, "\n      %s(0x%X %s ", prefix,
Packit Service a721b1
			 (unsigned) MPLIST_VAL (p),
Packit Service a721b1
			 MPLIST_KEY (p)->name);
Packit Service a721b1
		mdebug_dump_font (MPLIST_VAL (p));
Packit Service a721b1
		fprintf (mdebug__output, ")");
Packit Service a721b1
	      }
Packit Service a721b1
	    fprintf (mdebug__output, ")");
Packit Service a721b1
	  }
Packit Service a721b1
	fprintf (mdebug__output, ")");
Packit Service a721b1
      }
Packit Service a721b1
  if (fontset->per_charset)
Packit Service a721b1
    MPLIST_DO (pl, fontset->per_charset)
Packit Service a721b1
      {
Packit Service a721b1
	fprintf (mdebug__output, "\n  %s(%s", prefix, MPLIST_KEY (pl)->name);
Packit Service a721b1
	MPLIST_DO (p, MPLIST_PLIST (pl))
Packit Service a721b1
	  {
Packit Service a721b1
	    fprintf (mdebug__output, "\n    %s(%s ", prefix,
Packit Service a721b1
		     MPLIST_KEY (p)->name);
Packit Service a721b1
	    mdebug_dump_font (MPLIST_VAL (p));
Packit Service a721b1
	    fprintf (mdebug__output, ")");
Packit Service a721b1
	  }
Packit Service a721b1
	fprintf (mdebug__output, ")");
Packit Service a721b1
      }
Packit Service a721b1
Packit Service a721b1
  if (fontset->fallback)
Packit Service a721b1
    MPLIST_DO (p, fontset->fallback)
Packit Service a721b1
      {
Packit Service a721b1
	fprintf (mdebug__output, "\n  %s(%s ", prefix, MPLIST_KEY (p)->name);
Packit Service a721b1
	mdebug_dump_font (MPLIST_VAL (p));
Packit Service a721b1
	fprintf (mdebug__output, ")");
Packit Service a721b1
      }
Packit Service a721b1
Packit Service a721b1
  fprintf (mdebug__output, ")");
Packit Service a721b1
  return fontset;
Packit Service a721b1
}
Packit Service a721b1
Packit Service a721b1
/*** @} */
Packit Service a721b1
Packit Service a721b1
/*
Packit Service a721b1
  Local Variables:
Packit Service a721b1
  coding: euc-japan
Packit Service a721b1
  End:
Packit Service a721b1
*/