Blob Blame History Raw
/* m17n-gui.c -- body of the GUI API.
   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
     National Institute of Advanced Industrial Science and Technology (AIST)
     Registration Number H15PRO112

   This file is part of the m17n library.

   The m17n library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public License
   as published by the Free Software Foundation; either version 2.1 of
   the License, or (at your option) any later version.

   The m17n library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the m17n library; if not, write to the Free
   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301 USA.  */

/***en
    @addtogroup m17nGUI
    @brief GUI support for a window system.

    This section defines the m17n GUI API concerning M-text drawing
    and inputting under a window system.

    All the definitions here are independent of window systems.  An
    actual library file, however, can depend on a specific window
    system.  For instance, the library file m17n-X.so is an example of
    implementation of the m17n GUI API for the X Window System.

    Actually the GUI API is mainly for toolkit libraries or to
    implement XOM, not for direct use from application programs.
*/

/***ja
    @addtogroup m17nGUI
    @brief ウィンドウシステム上の GUI サポート.

    このセクションはウィンドウシステムのもとでの M-text の表示と入力にかかわる
    m17n GUI API を定義する。

    ここでのすべての定義はウィンドウシステムとは独立である。
    しかし、実際のライブラリファイルは個別のウィンドウシステムに依存する場合がある。
    たとえばライブラリファイル m17n-X.so は、m17n GUI API の X 
    ウィンドウ用の実装例である。

    現実には、GUI API は主にツールキットライブラリ向けであるか、または 
    XOM を実装するために用いられており、アプリケーションプログラムからの直接の利用を念頭においたものではない。
*/

/*=*/

#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
/*** @addtogroup m17nInternal
     @{ */

#include "config.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "config.h"
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif

#include "m17n-gui.h"
#include "m17n-misc.h"
#include "internal.h"
#include "plist.h"
#include "internal-gui.h"
#include "font.h"
#include "fontset.h"
#include "face.h"

#ifndef DLOPEN_SHLIB_EXT
#define DLOPEN_SHLIB_EXT ".so"
#endif

/** Information about a dynamic library supporting a specific graphic
    device.  */
typedef struct
{
  /** Name of the dynamic library (e.g. "libm17n-X.so").  */
  char *library;
  /** Handle of the dynamic library.  */
  void *handle;
  /** Function to call just after loading the library.  */
  int (*init) ();
  /** Function to call to open a frame on the graphic device.  */
  int (*open) (MFrame *frame, MPlist *param);
  /** Function to call just before unloading the library.  */
  int (*fini) ();
} MDeviceLibraryInterface;


/** Plist of device symbol vs MDeviceLibraryInterface.  */

static MPlist *device_library_list;

/** Close MFrame and free it.  */

static void
free_frame (void *object)
{
  MFrame *frame = (MFrame *) object;

  (*frame->driver->close) (frame);
  M17N_OBJECT_UNREF (frame->face);
  M17N_OBJECT_UNREF (frame->font_driver_list);
  free (object);
}


/** Register a dynamic library of name LIB by a key NAME.  */

static int
register_device_library (MSymbol name, char *lib)
{
  MDeviceLibraryInterface *interface;

  MSTRUCT_CALLOC (interface, MERROR_WIN);
  interface->library = malloc (strlen (M17N_MODULE_DIR) + 1
			       + strlen (lib) 
			       + strlen (DLOPEN_SHLIB_EXT) + 1);
  sprintf (interface->library, "%s/%s%s", M17N_MODULE_DIR, lib,
	   DLOPEN_SHLIB_EXT);
  if (! device_library_list)
    device_library_list = mplist ();
  mplist_add (device_library_list, name, interface);
  return 0;
}


#ifdef HAVE_FREETYPE
/** Null device support.  */

static struct {
  MPlist *realized_fontset_list;
  MPlist *realized_font_list;
  MPlist *realized_face_list;
} null_device;

static void
null_device_close (MFrame *frame)
{
}

static void *
null_device_get_prop (MFrame *frame, MSymbol key)
{
  return NULL;
}

static void
null_device_realize_face (MRealizedFace *rface)
{
  rface->info = NULL;
}

static void
null_device_free_realized_face (MRealizedFace *rface)
{
}

static MDeviceDriver null_driver =
  {
    null_device_close,
    null_device_get_prop,
    null_device_realize_face,
    null_device_free_realized_face
  };

static int
null_device_init ()
{
  null_device.realized_fontset_list = mplist ();
  null_device.realized_font_list = mplist ();
  null_device.realized_face_list = mplist ();  
  return 0;
}

static int
null_device_fini ()
{
  MPlist *plist;

  MPLIST_DO (plist, null_device.realized_fontset_list)
    mfont__free_realized_fontset ((MRealizedFontset *) MPLIST_VAL (plist));
  M17N_OBJECT_UNREF (null_device.realized_fontset_list);

  MPLIST_DO (plist, null_device.realized_face_list)
    mface__free_realized ((MRealizedFace *) MPLIST_VAL (plist));
  M17N_OBJECT_UNREF (null_device.realized_face_list);

  if (MPLIST_VAL (null_device.realized_font_list))
    mfont__free_realized (MPLIST_VAL (null_device.realized_font_list));
  M17N_OBJECT_UNREF (null_device.realized_font_list);
  return 0;
}

static int
null_device_open (MFrame *frame, MPlist *param)
{
  MFace *face;

  frame->device = NULL;
  frame->device_type = 0;
  frame->dpi = (int) mplist_get (param, Mresolution);
  if (frame->dpi == 0)
    frame->dpi = 100;
  frame->driver = &null_driver;
  frame->font_driver_list = mplist ();
  mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
  frame->realized_font_list = null_device.realized_font_list;
  frame->realized_face_list = null_device.realized_face_list;
  frame->realized_fontset_list = null_device.realized_fontset_list;
  face = mface_copy (mface__default);
  mplist_push (param, Mface, face);
  M17N_OBJECT_UNREF (face);
  return 0;
}

static MDeviceLibraryInterface null_interface =
  { NULL, NULL, null_device_init, null_device_open, null_device_fini };

#endif

/* Internal API */


/* External API */

void
m17n_init_win (void)
{
  int mdebug_flag = MDEBUG_INIT;

  merror_code = MERROR_NONE;
  if (m17n__gui_initialized++)
    return;
  m17n_init ();
  m17n_init_flt ();
  if (merror_code != MERROR_NONE)
    {
      m17n__gui_initialized--;
      return;
    }

  MDEBUG_PUSH_TIME ();

  Mgd = msymbol ("gd");

  Mfont = msymbol ("font");
  Mfont_width = msymbol ("font-width");
  Mfont_ascent = msymbol ("font-ascent");
  Mfont_descent = msymbol ("font-descent");
  Mdevice = msymbol ("device");

  Mdisplay = msymbol ("display");
  Mscreen = msymbol ("screen");
  Mdrawable = msymbol ("drawable");
  Mdepth = msymbol ("depth");
  Mwidget = msymbol ("widget");
  Mcolormap = msymbol ("colormap");

  MDEBUG_PUSH_TIME ();
  if (mfont__init () < 0)
    goto err;
  MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to initialize font module."));
  if (mfont__fontset_init () < 0)
    goto err;
  MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to initialize fontset module."));
  if (mface__init () < 0)
    goto err;
  MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to initialize face module."));
  if (mdraw__init () < 0)
    goto err;
  MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to initialize draw module."));
  if (minput__win_init () < 0)
    goto err;
  MDEBUG_PRINT_TIME ("INIT",
		     (mdebug__output, " to initialize input-win module."));
  mframe_default = NULL;

  register_device_library (Mx, "libm17n-X");
  register_device_library (Mgd, "libm17n-gd");
  return;

 err:
  MDEBUG_POP_TIME ();
  MDEBUG_PRINT_TIME ("INIT",
		     (mdebug__output, " to initialize the m17n GUI module."));
  MDEBUG_POP_TIME ();
}

void
m17n_fini_win (void)
{
  int mdebug_flag = MDEBUG_FINI;
  MPlist *plist;

  if (m17n__gui_initialized == 0
      || --m17n__gui_initialized > 0)
    return;

  MDEBUG_PUSH_TIME ();
  MDEBUG_PUSH_TIME ();
  MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize device modules."));
  MPLIST_DO (plist, device_library_list)
    {
      MDeviceLibraryInterface *interface = MPLIST_VAL (plist);

      if (interface->handle && interface->fini)
	{
	  (*interface->fini) ();
	  dlclose (interface->handle);
	}
      free (interface->library);
      free (interface);
    }
#ifdef HAVE_FREETYPE
  if (null_interface.handle)
    {
      (*null_interface.fini) ();
      null_interface.handle = NULL;
    }
#endif	/* not HAVE_FREETYPE */
  M17N_OBJECT_UNREF (device_library_list);
  minput__win_fini ();
  MDEBUG_PRINT_TIME ("FINI",
		     (mdebug__output, " to finalize input-gui module."));
  mdraw__fini ();
  MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize draw module."));
  mface__fini ();
  MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize face module."));
  mfont__fontset_fini ();
  MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize fontset module."));
  mfont__fini ();
  MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize font module."));
  mframe_default = NULL;
  MDEBUG_POP_TIME ();
  MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize the gui modules."));
  MDEBUG_POP_TIME ();
  m17n_fini_flt ();
  m17n_fini ();
}

/*** @} */ 
#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */

/*** @addtogroup m17nFrame */
/***en
    @brief A @e frame is an object corresponding to the graphic device.

    A @e frame is an object of the type #MFrame to hold various
    information about each display/input device.  Almost all m17n GUI
    functions require a pointer to a frame as an argument.  */
/***ja
    @brief @e フレーム とはグラフィックデバイスに対応するオブジェクトである.

    @e フレーム とは #MFrame 
    型のオブジェクトであり、個々の表示/入力デバイスの情報を格納するために用いられる。
    ほとんどすべての m17n GUI関数は、引数としてフレームへのポインタを要求する。  */

/*** @{ */
/*=*/

/***en
    @name Variables: Keys of frame parameter

    These are the symbols to use in a parameter to create a frame.  See
    the function mframe () for details.

    @b Mdevice, @b Mdisplay, @b Mscreen, @b Mdrawable, @b Mdepth, and
    @b Mcolormap are also keys of a frame property.  */

/***ja
    @name 変数: フレームパラメータ用キー

    フレームを生成する際のパラメータに用いるシンボル。詳しくは関数
    mframe () の説明参照。

    @b Mdevice、 @b Mdisplay、 @b Mscreen、 @b Mdrawable、 @b Mdepth、
    @b Mcolormap はフレームプロパティのキーでもある。  */

/*=*/

MSymbol Mdevice, Mdisplay, Mscreen, Mdrawable, Mdepth, Mcolormap, Mwidget; 

MSymbol Mgd;

/*=*/

/***en
    @name Variables: Keys of frame property

    These are the symbols to use as an argument to the function
    mframe_get_prop ().  */
/***ja
    @name 変数: フレームプロパティのキー

    関数 mframe_get_prop () の引数に用いられるシンボル。  */ 
/*** @{ */ 
/*=*/
MSymbol Mfont;
MSymbol Mfont_width;
MSymbol Mfont_ascent;
MSymbol Mfont_descent;

/*=*/

/*** @} */ 
/*=*/

/***en
    @brief Create a new frame.

    The mframe () function creates a new frame with parameters listed
    in $PLIST which may be @c NULL.

    The recognized keys in $PLIST are window system dependent.

    The following key is always recognized.

    <ul>

    <li> @b Mdevice, the value must be one of #Mx, @b Mgd, and #Mnil.

    If the value is #Mx, the frame is for X Window System.  The
    argument #MDrawWindow specified together with the frame must be of
    type @c Window.  The frame is both readable and writable, thus all
    GUI functions can be used.

    If the value is @b Mgd, the frame is for an image object of GD
    library.  The argument #MDrawWindow specified together with the
    frame must be of type @c gdImagePtr.  The frame is writable
    only, thus functions minput_XXX can't be used for the frame.

    If the value is #Mnil, the frame is for a null device.  The frame
    is not writable nor readable, thus functions mdraw_XXX that
    require the argument #MDrawWindow and functions minput_XXX can't
    be used for the frame.

    <li> #Mface, the value must be a pointer to #MFace.

    The value is used as the default face of the frame.

    </ul>

    In addition, if the value of the key @b Mdevice is #Mx, the
    following keys are recognized.  They are to specify the root
    window and the depth of drawables that can be used with the frame.

    <ul>

    <li> @b Mdrawable, the value type must be <tt>Drawable</tt>.

    A parameter of key @b Mdisplay must also be specified.  The
    created frame can be used for drawables whose root window and
    depth are the same as those of the specified drawable on the
    specified display.

    When this parameter is specified, the parameter of key @b Mscreen
    is ignored.

    <li> @b Mwidget, the value type must be <tt>Widget</tt>.

    The created frame can be used for drawables whose root window and
    depth are the same as those of the specified widget.

    If a parameter of key #Mface is not specified, the default face
    is created from the resources of the widget.

    When this parameter is specified, the parameters of key @b Mdisplay,
    @b Mscreen, @b Mdrawable, @b Mdepth are ignored.

    <li> @b Mdepth, the value type must be <tt>unsigned</tt>.

    The created frame can be used for drawables of the specified
    depth.

    <li> @b Mscreen, the value type must be <tt>(Screen *)</tt>.

    The created frame can be used for drawables whose root window is
    the same as the root window of the specified screen, and depth is
    the same at the default depth of the screen.

    When this parameter is specified, parameter of key @b Mdisplay is
    ignored.

    <li> @b Mdisplay, the value type must be <tt>(Display *)</tt>.

    The created frame can be used for drawables whose root window is
    the same as the root window for the default screen of the display,
    and depth is the same as the default depth of the screen.

    <li> @b Mcolormap, the value type must be <tt>(Colormap)</tt>.

    The created frame uses the specified colormap.

    <li> @b Mfont, the value must be #Mx, #Mfreetype, or #Mxft.

    The created frame uses the specified font backend.  The value #Mx
    instructs to use X core fonts, #Mfreetype to use local fonts
    supported by FreeType fonts, and #Mxft to use local fonts via Xft
    library.  You can specify this parameter more than once with
    different values if you want to use multiple font backends.  This
    is ignored if the specified font backend is not supported on the
    device.
    
    When this parameter is not specified, all font backend supported
    on the device are used.

    </ul>

    @return
    If the operation was successful, mframe () returns a pointer to a
    newly created frame.  Otherwise, it returns @c NULL.  */

/***ja
    @brief 新しいフレームを作る.

    関数 mframe () は $PLIST 中のパラメータを持つ新しいフレームを作る。
    $PLIST は @c NULL でも良い。

    $PLIST に現われるキーのうちどれが認識されるかはウィンドウシステムに依存する。

    以下のキーは常に認識される。

    <ul>

    <li> @b Mdevice. 値は #Mx, @b Mgd, #Mnil のいずれかでなくてはならない。

    値が #Mx ならば、新しいフレームは X ウィンドウシステム用である。
    このフレームと共に指定された引数 #MDrawWindow は、 @c Window
    型でなくてはならない。フレームは読み書きともに可能であり、すべてのGUI 
    関数が使用できる。

    値が @b Mgd ならば、新しいフレームは GD 
    ライブラリのイメージオブジェクト用である。このフレームと共に指定された引数
    #MDrawWindow は、 @c gdImagePtr 型でなくてはならない。フレームは書き出し専用であり、
    minput_ で始まる名前の関数は使用できない。

    値が #Mnil ならば、新しいフレームは, null 
    デバイス用である。このフレームは読み書きできないので、引数 #MDrawWindow 
    を必要とするmdraw_ で始まる名前の関数や、minput_ で始まる名前の関数は使用できない。

    <li> #Mface. 値は #MFace へのポインタでなくてはならない。

    この値はフレームのデフォルトのフェースとして用いられる。

    </ul>

    これらのキーに加え、@b Mdevice のキーが #Mx 
    である場合に限り以下のキーも認識される。以下のキーはルートウィンドウと、フレームで利用できる 
    drawable の深さを指定する。

    <ul>

    <li> @b Mdrawable. 値は <tt>Drawable</tt> 型でなくてはならない。

    キー @b Mdisplay を持つパラメータも指定されている必要がある。
    生成されたフレームは、指定されたディスプレイ上の指定された drawable 
    と同じルートウィンドウと深さを持つ drawable に用いられる。

    このパラメータがある場合には、@b Mscreen をキーとするパラメータは無視される。

    <li> @b Mwidget. 値は <tt>Widget</tt> 型でなくてはならない。

    生成されたフレームは、指定したウィジェットと同じルートウィンドウと深さを持つ
    drawable に用いられる。

    キー #Mface を持つパラメータがなければ、デフォルトのフェースはこの
    ウィジェットのリソースから作られる。

    このパラメータがある場合には、@b Mdisplay, @b Mscreen, @b Mdrawable,
    @b Mdepth をキーとするパラメータは無視される。

    <li> @b Mdepth. 値は <tt>unsigned</tt>  型でなくてはならない。

    生成されたフレームは、指定した深さの drawable に用いられる。

    <li> @b Mscreen. 値は <tt>(Screen *)</tt> 型でなくてはならない。

    生成したフレームは、指定したスクリーンと同じルートウィンドウを持ち、スクリーンのデフォルトの深さと同じ深さを持つ drawable に用いられる。

    このパラメータがある場合には、@b Mdisplay をキーとするパラメータは無視される。

    <li> @b Mdisplay. 値は <tt>(Display *)</tt> 型でなくてはならない。

    生成されたフレームは、指定したディスプレイのデフォルトスクリーンと同じルートウィンドウと同じ深さを持つdrawables に用いられる。

    <li> @b Mcolormap. 値は <tt>(Colormap)</tt> 型でなくてはならない。

    生成されたフレームは、指定したカラーマップを使用する。

    <li> #Mfont. 値は、#Mx, #Mfreetype, #Mxft のいずれか。

    生成されたフレームは指定したフォントバックエンドを使用する。値が 
    #Mx であれば X のコアフォント、#Mfreetype であれば FreeType 
    でサポートされているローカルフォント、#Mxft であれば Xft 
    ライブラリ経由で用いるローカルフォントを使用する。
    複数のフォントバックエンドを使用したい場合には、このパラメータを複数回、異なる値で指定することができる。
    指定したバックエンドがサポートされていないデバイスでは、このパラメータは無視される。

    このパラメータが無い場合には、デバイスでサポートされているすべてのフォントバックエンドを利用する。

    </ul>

    @return
    成功すれば mframe() は新しいフレームへのポインタを返す。そうでなければ
    @c NULL を返す。  */

MFrame *
mframe (MPlist *plist)
{
  MFrame *frame;
  int plist_created = 0;
  MPlist *pl;
  MSymbol device;
  MDeviceLibraryInterface *interface;

  if (plist)
    {
      pl = mplist_find_by_key (plist, Mdevice);
      if (pl)
	device = MPLIST_VAL (pl);
      else
	device = Mx;
    }
  else
    {
      plist = mplist ();
      plist_created = 1;
      device = Mx;
    }

  if (device == Mnil)
    {
#ifdef HAVE_FREETYPE
      interface = &null_interface;
      if (! interface->handle)
	{
	  (*interface->init) ();
	  interface->handle = (void *) 1;
	}
#else  /* not HAVE_FREETYPE */
      MERROR (MERROR_WIN, NULL);
#endif	/* not HAVE_FREETYPE */
    }
  else
    {
      interface = mplist_get (device_library_list, device);
      if (! interface)
	MERROR (MERROR_WIN, NULL);
      if (! interface->handle)
	{
	  if (! (interface->handle = dlopen (interface->library, RTLD_NOW))
	      || ! (interface->init
		    = (int (*) ()) dlsym (interface->handle, "device_init"))
	      || ! (interface->open
		    = (int (*) (MFrame *, MPlist *)) dlsym (interface->handle,
							    "device_open"))
	      || ! (interface->fini
		    = (int (*) ()) dlsym (interface->handle, "device_fini"))
	      || (*interface->init) () < 0)
	    {
	      fprintf (stderr, "%s\n", (char *) dlerror ());
	      if (interface->handle)
		dlclose (interface->handle);
	      MERROR (MERROR_WIN, NULL);
	    }
	}
    }

  M17N_OBJECT (frame, free_frame, MERROR_FRAME);
  if ((*interface->open) (frame, plist) < 0)
    {
      free (frame);
      MERROR (MERROR_WIN, NULL);
    }

  if (! mframe_default)
    mframe_default = frame;

  frame->face = mface ();
  MPLIST_DO (pl, plist)
    if (MPLIST_KEY (pl) == Mface)
      mface_merge (frame->face, (MFace *) MPLIST_VAL (pl));
  mface__update_frame_face (frame);
  frame->font
    = frame->rface->rfont ? (MFont *) frame->rface->rfont : NULL;
  if (plist_created)
    M17N_OBJECT_UNREF (plist);
  return frame;
}

/*=*/

/***en
    @brief Return property value of frame.

    The mframe_get_prop () function returns a value of property $KEY
    of frame $FRAME.  The valid keys and the corresponding return
    values are as follows.

@verbatim

        key             type of value   meaning of value
        ---             -------------   ----------------
        Mface           MFace *         The default face.

        Mfont           MFont *         The default font.

        Mfont_width     int             Width of the default font.

        Mfont_ascent    int             Ascent of the default font.

        Mfont_descent   int             Descent of the default font.

@endverbatim

    In the m17n-X library, the followings are also accepted.

@verbatim

        key             type of value   meaning of value
        ---             -------------   ----------------
        Mdisplay        Display *       Display associated with the frame.

        Mscreen         int             Screen number of a screen associated
                                        with the frame.

        Mcolormap       Colormap        Colormap of the frame.

        Mdepth          unsigned        Depth of the frame.
@endverbatim
*/

/***ja
    @brief フレームのプロパティの値を返す.

    関数 mframe_get_prop () はフレーム $FRAME のキー $KEY 
    を持つプロパティの値を返す。有効なキーとその値は以下の通り。

@verbatim

        キー            値の型          値の意味
        ---             -------------   ----------------
        Mface           MFace *         デフォルトのフェース

        Mfont           MFont *         デフォルトのフォント

        Mfont_width     int             デフォルトのフォントの幅

        Mfont_ascent    int             デフォルトのフォントの ascent

        Mfont_descent   int             デフォルトのフォントの descent

@endverbatim

     m17n-X ライブラリでは、以下のキーも使用できる。

@verbatim

        キー            値の型          値の意味
        ---             -------------   ----------------
        Mdisplay        Display *       フレームと関連付けられたディスプレイ

        Mscreen         int             フレームと関連付けられたスクリーン
                                        のスクリーンナンバ

        Mcolormap       Colormap        フレームのカラーマップ

        Mdepth          unsigned        フレームの深さ
@endverbatim

*/

void *
mframe_get_prop (MFrame *frame, MSymbol key)
{
  if (key == Mface)
    return frame->face;
  if (key == Mfont)
    return frame->font;
  if (key == Mfont_width)
    return (void *) (frame->average_width);
  if (key == Mfont_ascent)
    return (void *) (frame->ascent);
  if (key == Mfont_descent)
    return (void *) (frame->descent);
  return (*frame->driver->get_prop) (frame, key);
}

/*=*/

/***en
    @brief The default frame.

    The external variable #mframe_default contains a pointer to the
    default frame that is created by the first call of mframe ().  */

/***ja
    @brief デフォルトのフレーム.

    外部変数 #mframe_default は、デフォルトのフレームへのポインタを持つ。
    デフォルトのフレームは、最初に mframe () が呼び出されたときに作られる。  */

MFrame *mframe_default;

/*** @} */

/*
  Local Variables:
  coding: euc-japan
  End:
*/