(mface_put_prop): If the new value is the same as the
[m17n/m17n-lib.git] / src / m17n-gui.c
index 6086b23..917462b 100644 (file)
@@ -22,7 +22,7 @@
 
 /***en
     @addtogroup m17nGUI
-    @brief GUI support for a window system
+    @brief GUI support for a window system.
 
     This section defines the m17n GUI API concerning M-text drawing
     and inputting under a window system.
 
 /***ja
     @addtogroup m17nGUI
-    @brief ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à´ØÏ¢¤Î¿¸À¸ìÂбþ 
+    @brief ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¾å¤Î GUI ¥µ¥Ý¡¼¥È.
 
-    ¤³¤Î¥»¥¯¥·¥ç¥ó¤Ï¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¾å¤Ç¤Î M-text ¤Îɽ¼¨¤ÈÆþÎϤò°·¤¦ 
-    m17n-win API ¤òÄêµÁ¤¹¤ë¡£
+    ¤³¤Î¥»¥¯¥·¥ç¥ó¤Ï¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¤Î¤â¤È¤Ç¤Î M-text ¤Îɽ¼¨¤ÈÆþÎϤË
+    ¤«¤«¤ï¤ë m17n GUI API ¤òÄêµÁ¤¹¤ë¡£
 
-    ¤³¤³¤Ç¤Î¤¹¤Ù¤Æ¤ÎÄêµÁ¤Ï¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¤È¤ÏÆÈΩ¤Ç¤¢¤ë¡£¤·¤«¤·¼ÂÁõ
-    ¤Ï¸ÄÊ̤Υ¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¤Ë°Í¸¤¹¤ë¾ì¹ç¤¬¤¢¤ë¡£m17n-X ¥é¥¤¥Ö¥é¥ê
-    ¤Ï X ¥¦¥£¥ó¥É¥¦ÍѤμÂÁõÎã¤Ç¤¢¤ë¡£  */
+    ¤³¤³¤Ç¤Î¤¹¤Ù¤Æ¤ÎÄêµÁ¤Ï¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¤È¤ÏÆÈΩ¤Ç¤¢¤ë¡£¤·¤«¤·¡¢¼Â
+    ºÝ¤Î¥é¥¤¥Ö¥é¥ê¥Õ¥¡¥¤¥ë¤Ï¸ÄÊ̤Υ¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¤Ë°Í¸¤¹¤ë¾ì¹ç¤¬¤¢
+    ¤ë¡£¤¿¤È¤¨¤Ð¥é¥¤¥Ö¥é¥ê¥Õ¥¡¥¤¥ë m17n-X.so ¤Ï¡¢m17n GUI API ¤Î X ¥¦¥£
+    ¥ó¥É¥¦ÍѤμÂÁõÎã¤Ç¤¢¤ë¡£
+
+    ¸½¼Â¤Ë¤Ï¡¢GUI API ¤Ï¼ç¤Ë¥Ä¡¼¥ë¥­¥Ã¥È¥é¥¤¥Ö¥é¥ê¸þ¤±¤Ç¤¢¤ë¤«¡¢¤Þ¤¿¤Ï 
+    XOM ¤ò¼ÂÁõ¤¹¤ë¤¿¤á¤ËÍѤ¤¤é¤ì¤Æ¤ª¤ê¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤«¤é
+    ¤ÎľÀܤÎÍøÍѤòǰƬ¤Ë¤ª¤¤¤¿¤â¤Î¤Ç¤Ï¤Ê¤¤¡£
+*/
 
 /*=*/
 
 #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"
 
 static int win_initialized;
 
+#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 fo 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);
-  mwin__close_device ((MFrame *) object);
   free (frame->font);
+  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 (lib) 
+                              + strlen (DLOPEN_SHLIB_EXT) + 1);
+  sprintf (interface->library, "%s%s", lib, DLOPEN_SHLIB_EXT);
+  if (! device_library_list)
+    device_library_list = mplist ();
+  mplist_add (device_library_list, name, interface);
+  return 0;
+}
+
+\f
+#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);
+
+  MPLIST_DO (plist, null_device.realized_font_list)
+    mfont__free_realized ((MRealizedFont *) MPLIST_VAL (plist));
+  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->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
 \f
 /* Internal API */
 
@@ -89,30 +238,37 @@ free_frame (void *object)
 \f
 /* External API */
 
-void
+int
 m17n_init_win (void)
 {
   int mdebug_mask = MDEBUG_INIT;
 
-  if (win_initialized)
-    return;
+  if (win_initialized++)
+    return 0;
   m17n_init ();
   if (merror_code != MERROR_NONE)
-    return;
+    return -1;
+
+  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");
 
-  MDEBUG_PUSH_TIME ();
   MDEBUG_PUSH_TIME ();
   if (mfont__init () < 0)
     goto err;
   MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize font module."));
-  if (mwin__init () < 0)
-    goto err;
-  MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize win module."));
   if (mfont__fontset_init () < 0)
     goto err;
   MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize fontset module."));
@@ -126,13 +282,16 @@ m17n_init_win (void)
     goto err;
   MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize input-win module."));
   mframe_default = NULL;
-  win_initialized = 1;
+
+  register_device_library (Mx, "libm17n-X");
+  register_device_library (Mgd, "libm17n-gd");
+  return 0;
 
  err:
   MDEBUG_POP_TIME ();
   MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize the m17n GUI module."));
   MDEBUG_POP_TIME ();
-  return;
+  return -1;
 }
 
 void
@@ -140,10 +299,32 @@ m17n_fini_win (void)
 {
   int mdebug_mask = MDEBUG_FINI;
 
-  if (win_initialized)
+  if (win_initialized > 1)
+    win_initialized--;
+  else
     {
+      MPlist *plist;
+
+      win_initialized = 0;
       MDEBUG_PUSH_TIME ();
       MDEBUG_PUSH_TIME ();
+      MDEBUG_PRINT_TIME ("FINI", (stderr, " 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);
+       }
+#ifdef HAVE_FREETYPE
+      if (null_interface.handle)
+       (*null_interface.fini) ();
+#endif /* not HAVE_FREETYPE */
+      M17N_OBJECT_UNREF (device_library_list);
       MDEBUG_PRINT_TIME ("FINI", (stderr, " to finalize input-gui module."));
       minput__win_fini ();
       MDEBUG_PRINT_TIME ("FINI", (stderr, " to finalize draw module."));
@@ -152,41 +333,69 @@ m17n_fini_win (void)
       mface__fini ();
       MDEBUG_PRINT_TIME ("FINI", (stderr, " to finalize fontset module."));
       mfont__fontset_fini ();
-      MDEBUG_PRINT_TIME ("FINI", (stderr, " to finalize window module."));
-      mwin__fini ();
       MDEBUG_PRINT_TIME ("FINI", (stderr, " to finalize font module."));
       mfont__fini ();
       mframe_default = NULL;
       MDEBUG_POP_TIME ();
       MDEBUG_PRINT_TIME ("FINI", (stderr, " to finalize the gui modules."));
       MDEBUG_POP_TIME ();
-      win_initialized = 0;
     }
   m17n_fini ();
 }
 
 /*** @addtogroup m17nFrame */
 /***en
-    @brief A @e frame is an object corresponding to the physical device.
+    @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 physical display/input device.  Almost all
-    m17n GUI functions require a pointer to a frame as an
-    argument.  */
+    information about each display/input device.  Almost all m17n GUI
+    functions require a pointer to a frame as an argument.  */
 
 /***ja
-    @brief ¥Õ¥ì¡¼¥à¤È¤ÏʪÍýŪ¥Ç¥Ð¥¤¥¹¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë
+    @brief @e ¥Õ¥ì¡¼¥à ¤È¤Ï¥°¥é¥Õ¥£¥Ã¥¯¥Ç¥Ð¥¤¥¹¤ËÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ë.
 
-    ¥Õ¥ì¡¼¥à¤È¤Ï #MFrame ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ê¡¢¸Ä¡¹¤ÎʪÍýŪ¤Êɽ¼¨¡¿
-    ÆþÎϥǥХ¤¥¹¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤¿¤á¤ËÍѤ¤¤é¤ì¤ë¡£¤Û¤È¤ó¤É¤¹¤Ù¤Æ¤Î 
-    m17n-win API ¤Ï¡¢°ú¿ô¤È¤·¤Æ¥Õ¥ì¡¼¥à¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÍ׵᤹¤ë¡£  */
+    @e ¥Õ¥ì¡¼¥à ¤È¤Ï #MFrame ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ê¡¢¸Ä¡¹¤Îɽ¼¨¡¿ÆþÎÏ¥Ç
+    ¥Ð¥¤¥¹¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤¿¤á¤ËÍѤ¤¤é¤ì¤ë¡£¤Û¤È¤ó¤É¤¹¤Ù¤Æ¤Î m17n GUI
+    ´Ø¿ô¤Ï¡¢°ú¿ô¤È¤·¤Æ¥Õ¥ì¡¼¥à¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÍ׵᤹¤ë¡£  */
 
 /*** @{ */
 /*=*/
 
 /***en
-    @name Variables: Keys of frame property (common).
- */ 
+    @name Variables: Keys of frame parameter
+
+    These are the symbols to use in a parameter to creat a frame.  See
+    the function mframe () for details.
+
+    #Mdevice, #Mdisplay, #Mscreen, #Mdrawable, #Mdepth, and #Mcolormap
+    are also keys of a frame property.  */
+
+/***ja
+    @name ÊÑ¿ô¡§ ¥Õ¥ì¡¼¥à¥Ñ¥é¥á¡¼¥¿ÍÑ¥­¡¼
+
+    ¥Õ¥ì¡¼¥à¤òÀ¸À®¤¹¤ëºÝ¤Î¥Ñ¥é¥á¡¼¥¿¤ËÍѤ¤¤ë¥·¥ó¥Ü¥ë¡£¾Ü¤·¤¯¤Ï´Ø¿ô
+    mframe () ¤ÎÀâÌÀ»²¾È¡£
+
+    #Mdevice¡¢ #Mdisplay¡¢ #Mscreen¡¢ #Mdrawable¡¢ #Mdepth¡¢#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;
@@ -195,6 +404,7 @@ MSymbol Mfont_ascent;
 MSymbol Mfont_descent;
 
 /*=*/
+
 /*** @} */ 
 /*=*/
 
@@ -202,7 +412,7 @@ MSymbol Mfont_descent;
     @brief Create a new frame.
 
     The mframe () function creates a new frame with parameters listed
-    in $PLIST.
+    in $PLIST which may be @c NULL.
 
     The recognized keys in $PLIST are window system dependent.
 
@@ -210,19 +420,36 @@ MSymbol Mfont_descent;
 
     <ul>
 
-    <li> #Mface, the value type must be <tt>(MFace *)</tt>.
+    <li> #Mdevice, the value must be one of #Mx, #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 #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, in the m17n-X library, the following keys are
-    recognized.  They are to specify the root window and the depth of
-    drawables that can be used with the frame.
+    In addition, if the value of the key #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> #Mdrawable, the value type must be <tt>Drawable</tt>
+    <li> #Mdrawable, the value type must be <tt>Drawable</tt>.
 
     A parameter of key #Mdisplay must also be specified.  The
     created frame can be used for drawables whose root window and
@@ -274,27 +501,88 @@ MSymbol Mfont_descent;
     newly created frame.  Otherwise, it returns @c NULL.  */
 
 /***ja
-    @brief  ¿·¤·¤¤¥Õ¥ì¡¼¥à¤òºî¤ë
+    @brief ¿·¤·¤¤¥Õ¥ì¡¼¥à¤òºî¤ë.
 
-    ´Ø¿ô mframe () ¤Ï¿·¤·¤¤¥Õ¥ì¡¼¥à¤òºî¤ë¡£°ìÈ̤ˡ¢°ú¿ô $ARGC ¤È $ARGV 
-    ¤Ï³Æ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Î <tt>main ()</tt> ´Ø¿ô¤ËÍ¿¤¨¤é¤ì¤ë¤â¤Î¤ÈƱ¤¸
-    ¤â¤Î¤Ç¤¢¤ë¡£¤Ä¤Þ¤ê¥³¥Þ¥ó¥É¥é¥¤¥ó°ú¿ô¤ò´Þ¤ó¤Ç¤¤¤ëɬÍפ¬¤¢¤ë¡£»ÈÍѤÇ
-    ¤­¤ë°ú¿ô¤Ï¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à¤Ë°Í¸¤¹¤ë¡£
+    ´Ø¿ô mframe () ¤Ï $PLIST Ãæ¤Î¥Ñ¥é¥á¡¼¥¿¤ò»ý¤Ä¿·¤·¤¤¥Õ¥ì¡¼¥à¤òºî¤ë¡£
+    $PLIST ¤Ï @c NULL ¤Ç¤âÎɤ¤¡£
 
-    m17n-X ¥é¥¤¥Ö¥é¥ê¤Ë¤ª¤±¤ë¤³¤Î´Ø¿ô¤Ï¡¢<tt>XOpenDisplay (NULL)</tt> 
-    ¤ò»È¤Ã¤Æ¥Ç¥Õ¥©¥ë¥È¤Î¥Ç¥£¥¹¥×¥ì¥¤¤ò³«¤­¡¢¼¡¤¤¤Ç <tt>DefaultScreen
-    (DISPLAY)</tt> ¤ò»È¤Ã¤Æ¥Ç¥Õ¥©¥ë¥È¤Î¥¹¥¯¥ê¡¼¥ó¤òÆÀ¤¿¸å¡¢ºî¤é¤ì¤¿¥Õ¥ì¡¼¥à
-    ¤Ë¤³¤Îξ¼Ô¤ò´ØÏ¢ÉÕ¤±¤ë¡£
+    $PLIST ¤Ë¸½¤ï¤ì¤ë¥­¡¼¤Î¤¦¤Á¤É¤ì¤¬Ç§¼±¤µ¤ì¤ë¤«¤Ï¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥à
+    ¤Ë°Í¸¤¹¤ë¡£
 
-    m17n-X ¥é¥¤¥Ö¥é¥ê¤Ï°Ê²¼¤Î°ú¿ô¤ò¼õ¤±ÉÕ¤±¤ë¡£
+    °Ê²¼¤Î¥­¡¼¤Ï¾ï¤Ëǧ¼±¤µ¤ì¤ë¡£
+
+    <ul>
 
-       @li @c -fn @e font : ¥Õ¥ì¡¼¥à¤Î¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥©¥ó¥È¤ò @e font 
-                            ¤Ë¥»¥Ã¥È¤¹¤ë
-       @li @c -fg @e color : ¥Õ¥ì¡¼¥à¤Î¥Ç¥Õ¥©¥ë¥È¤ÎÁ°·Ê¿§¤ò @e color 
-                             ¤Ë¥»¥Ã¥È¤¹¤ë
-       @li @c -bg @e color : ¥Õ¥ì¡¼¥à¤Î¥Ç¥Õ¥©¥ë¥È¤ÎÇØ·Ê¿§¤ò @e color 
-                             ¤Ë¥»¥Ã¥È¤¹¤ë
-       @li @c -rv : Á°·Ê¿§¤ÈÇØ·Ê¿§¤ò¸ò´¹¤¹¤ë
+    <li> #Mdevice. ÃͤϠ#Mx, #Mgd, #Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+
+    Ãͤ¬ #Mx ¤Ê¤é¤Ð¡¢¿·¤·¤¤¥Õ¥ì¡¼¥à¤Ï X ¥¦¥£¥ó¥É¥¦¥·¥¹¥Æ¥àÍѤǤ¢¤ë¡£¤³
+    ¤Î¥Õ¥ì¡¼¥à¤È¶¦¤Ë»ØÄꤵ¤ì¤¿°ú¿ô #MDrawWindow ¤Ï¡¢ @c Window ·¿¤Ç¤Ê
+    ¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¥Õ¥ì¡¼¥à¤ÏÆɤ߽ñ¤­¤È¤â¤Ë²Äǽ¤Ç¤¢¤ê¡¢¤¹¤Ù¤Æ¤ÎGUI ´Ø
+    ¿ô¤¬»ÈÍѤǤ­¤ë¡£
+
+    Ãͤ¬ #Mgd ¤Ê¤é¤Ð¡¢¿·¤·¤¤¥Õ¥ì¡¼¥à¤Ï GD ¥é¥¤¥Ö¥é¥ê¤Î¥¤¥á¡¼¥¸¥ª¥Ö¥¸¥§
+    ¥¯¥ÈÍѤǤ¢¤ë¡£¤³¤Î¥Õ¥ì¡¼¥à¤È¶¦¤Ë»ØÄꤵ¤ì¤¿°ú¿ô #MDrawWindow ¤Ï¡¢ 
+    @c gdImagePtr ·¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¥Õ¥ì¡¼¥à¤Ï½ñ¤­½Ð¤·ÀìÍѤǤ¢¤ê¡¢
+    minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤Î´Ø¿ô¤Ï»ÈÍѤǤ­¤Ê¤¤¡£
+
+    Ãͤ¬ #Mnil ¤Ê¤é¤Ð¡¢¿·¤·¤¤¥Õ¥ì¡¼¥à¤Ï, null ¥Ç¥Ð¥¤¥¹ÍѤǤ¢¤ë¡£¤³¤Î¥Õ
+    ¥ì¡¼¥à¤ÏÆɤ߽ñ¤­¤Ç¤­¤Ê¤¤¤Î¤Ç¡¢°ú¿ô #MDrawWindow ¤òɬÍפȤ¹¤ëmdraw_ 
+    ¤Ç»Ï¤Þ¤ë̾Á°¤Î´Ø¿ô¤ä¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤Î´Ø¿ô¤Ï»ÈÍѤǤ­¤Ê¤¤¡£
+
+    <li> #Mface. ÃͤϠ#MFace ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+
+    ¤³¤ÎÃͤϥե졼¥à¤Î¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£
+
+    </ul>
+
+    ¤³¤ì¤é¤Î¥­¡¼¤Ë²Ã¤¨¡¢#Mdevice ¤Î¥­¡¼¤¬ #Mx ¤Ç¤¢¤ë¾ì¹ç¤Ë¸Â¤ê°Ê²¼¤Î¥­¡¼
+    ¤âǧ¼±¤µ¤ì¤ë¡£°Ê²¼¤Î¥­¡¼¤Ï¥ë¡¼¥È¥¦¥£¥ó¥É¥¦¤È¡¢¥Õ¥ì¡¼¥à¤ÇÍøÍѤǤ­¤ë 
+    drawable ¤Î¿¼¤µ¤ò»ØÄꤹ¤ë¡£
+
+    <ul>
+
+    <li> #Mdrawable. ÃͤϠ<tt>Drawable</tt> ·¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+
+    ¥­¡¼ #Mdisplay ¤ò»ý¤Ä¥Ñ¥é¥á¡¼¥¿¤â»ØÄꤵ¤ì¤Æ¤¤¤ëɬÍפ¬¤¢¤ë¡£À¸À®¤µ
+    ¤ì¤¿¥Õ¥ì¡¼¥à¤Ï¡¢»ØÄꤵ¤ì¤¿¥Ç¥£¥¹¥×¥ì¥¤¾å¤Î»ØÄꤵ¤ì¤¿ drawable ¤ÈƱ
+    ¤¸¥ë¡¼¥È¥¦¥£¥ó¥É¥¦¤È¿¼¤µ¤ò»ý¤Ä drawable ¤ËÍѤ¤¤é¤ì¤ë¡£
+
+    ¤³¤Î¥Ñ¥é¥á¡¼¥¿¤¬¤¢¤ë¾ì¹ç¤Ë¤Ï¡¢#Mscreen ¤ò¥­¡¼¤È¤¹¤ë¥Ñ¥é¥á¡¼¥¿¤Ï̵
+    »ë¤µ¤ì¤ë¡£
+
+    <li> #Mwidget. ÃͤϠ<tt>Widget</tt> ·¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+
+    À¸À®¤µ¤ì¤¿¥Õ¥ì¡¼¥à¤Ï¡¢»ØÄꤷ¤¿¥¦¥£¥¸¥§¥Ã¥È¤ÈƱ¤¸¥ë¡¼¥È¥¦¥£¥ó¥É¥¦¤È
+    ¿¼¤µ¤ò»ý¤Ä drawable ¤ËÍѤ¤¤é¤ì¤ë¡£
+
+    ¥­¡¼ #Mface ¤ò»ý¤Ä¥Ñ¥é¥á¡¼¥¿¤¬¤Ê¤±¤ì¤Ð¡¢¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Ï¤³¤Î
+    ¥¦¥£¥¸¥§¥Ã¥È¤Î¥ê¥½¡¼¥¹¤«¤éºî¤é¤ì¤ë¡£
+
+    ¤³¤Î¥Ñ¥é¥á¡¼¥¿¤¬¤¢¤ë¾ì¹ç¤Ë¤Ï¡¢#Mdisplay, #Mscreen, #Mdrawable,
+    #Mdepth ¤ò¥­¡¼¤È¤¹¤ë¥Ñ¥é¥á¡¼¥¿¤Ï̵»ë¤µ¤ì¤ë¡£
+
+    <li> #Mdepth. ÃͤϠ<tt>unsigned</tt>  ·¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+
+    À¸À®¤µ¤ì¤¿¥Õ¥ì¡¼¥à¤Ï¡¢»ØÄꤷ¤¿¿¼¤µ¤Î drawable ¤ËÍѤ¤¤é¤ì¤ë¡£
+
+    <li> #Mscreen. ÃͤϠ<tt>(Screen *)</tt> ·¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+
+    À¸À®¤·¤¿¥Õ¥ì¡¼¥à¤Ï¡¢»ØÄꤷ¤¿¥¹¥¯¥ê¡¼¥ó¤ÈƱ¤¸¥ë¡¼¥È¥¦¥£¥ó¥É¥¦¤ò»ý¤Á¡¢
+    ¥¹¥¯¥ê¡¼¥ó¤Î¥Ç¥Õ¥©¥ë¥È¤Î¿¼¤µ¤ÈƱ¤¸¿¼¤µ¤ò»ý¤Ä drawable ¤ËÍѤ¤¤é¤ì¤ë¡£
+
+    ¤³¤Î¥Ñ¥é¥á¡¼¥¿¤¬¤¢¤ë¾ì¹ç¤Ë¤Ï¡¢#Mdisplay ¤ò¥­¡¼¤È¤¹¤ë¥Ñ¥é¥á¡¼¥¿¤Ï̵
+    »ë¤µ¤ì¤ë¡£
+
+    <li> #Mdisplay. ÃͤϠ<tt>(Display *)</tt> ·¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+
+    À¸À®¤µ¤ì¤¿¥Õ¥ì¡¼¥à¤Ï¡¢»ØÄꤷ¤¿¥Ç¥£¥¹¥×¥ì¥¤¤Î¥Ç¥Õ¥©¥ë¥È¥¹¥¯¥ê¡¼¥ó¤È
+    Æ±¤¸¥ë¡¼¥È¥¦¥£¥ó¥É¥¦¤ÈƱ¤¸¿¼¤µ¤ò»ý¤Ädrawables ¤ËÍѤ¤¤é¤ì¤ë¡£
+
+    <li> #Mcolormap. ÃͤϠ<tt>(Colormap)</tt> ·¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+
+    À¸À®¤µ¤ì¤¿¥Õ¥ì¡¼¥à¤Ï¡¢»ØÄꤷ¤¿¥«¥é¡¼¥Þ¥Ã¥×¤ò»ÈÍѤ¹¤ë¡£
+
+    </ul>
 
     @return
     À®¸ù¤¹¤ì¤Ð mframe() ¤Ï¿·¤·¤¤¥Õ¥ì¡¼¥à¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±
@@ -304,34 +592,78 @@ MFrame *
 mframe (MPlist *plist)
 {
   MFrame *frame;
-  MSymbol key;
+  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 = dlsym (interface->handle, "device_init"))
+             || ! (interface->open = dlsym (interface->handle, "device_open"))
+             || ! (interface->fini = 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);
-  frame->device = mwin__open_device (frame, plist);
-  if (! frame->device)
+  if ((*interface->open) (frame, plist) < 0)
     {
       free (frame);
       MERROR (MERROR_WIN, NULL);
     }
 
-  frame->face = mface_from_font (frame->font);
-  frame->face->property[MFACE_FONTSET] = mfontset (NULL);
-  M17N_OBJECT_REF (mface__default->property[MFACE_FONTSET]);
-  if (plist)
-    for (; (key = mplist_key (plist)) != Mnil; plist = mplist_next (plist))
-      if (key == Mface)
-       mface_merge (frame->face, (MFace *) mplist_value (plist));
-
-  frame->rface = mface__realize (frame, NULL, 0, Mnil, Mnil, 0);
-  if (! frame->rface->rfont)
-    MERROR (MERROR_WIN, NULL);
-  frame->space_width = frame->rface->space_width;
-  frame->ascent = frame->rface->ascent;
-  frame->descent = frame->rface->descent;
-
   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);
+
+  if (plist_created)
+    M17N_OBJECT_UNREF (plist);
   return frame;
 }
 
@@ -346,17 +678,17 @@ mframe (MPlist *plist)
 
 @verbatim
 
-       key             type of value   meaning of value
-       ---             -------------   ----------------
-       Mface           MFace *         The default face.
+        key             type of value   meaning of value
+        ---             -------------   ----------------
+        Mface           MFace *         The default face.
 
-       Mfont           MFont *         The default font.
+        Mfont           MFont *         The default font.
 
-       Mfont_width     int             Width of the default font.
+        Mfont_width     int             Width of the default font.
 
-       Mfont_ascent    int             Ascent of the default font.
+        Mfont_ascent    int             Ascent of the default font.
 
-       Mfont_descent   int             Descent of the default font.
+        Mfont_descent   int             Descent of the default font.
 
 @endverbatim
 
@@ -364,25 +696,58 @@ mframe (MPlist *plist)
 
 @verbatim
 
-       key             type of value   meaning of value
-       ---             -------------   ----------------
-       Mdisplay        Display *       Display associated with the frame.
+        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.
+        Mscreen         int             Screen number of a screen associated
+                                        with the frame.
 
-       Mcolormap       Colormap        Colormap of the frame.
+        Mcolormap       Colormap        Colormap of the frame.
 
-       Mdepth          unsigned                Depth of the frame.
+        Mdepth          unsigned        Depth of the frame.
 @endverbatim
 */
 
 /***ja
-    @brief ¥Õ¥ì¡¼¥à¤ÎMWDevice¤òÊÖ¤¹
+    @brief ¥Õ¥ì¡¼¥à¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹.
+
+    ´Ø¿ô mframe_get_prop () ¤Ï¥Õ¥ì¡¼¥à $FRAME ¤Î¥­¡¼ $KEY ¤ò»ý¤Ä¥×¥í¥Ñ
+    ¥Æ¥£¤ÎÃͤòÊÖ¤¹¡£Í­¸ú¤Ê¥­¡¼¤È¤½¤ÎÃͤϰʲ¼¤ÎÄ̤ꡣ
 
-    ´Ø¿ô mframe_device () ¤Ï¥Õ¥ì¡¼¥à $FRAME ¤Ë³ÊǼ¤µ¤ì¤Æ¤¤¤ë @c
-    MWDevice ¹½Â¤ÂΤؤΥݥ¤¥¿¤òÊÖ¤¹¡£#MWDevice ¤Î·Á¼°¤Ï¥¦¥£¥ó¥É¥¦¥·
-    ¥¹¥Æ¥à¤Ë°Í¸¤¹¤ë¡£  */
+@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)
@@ -397,7 +762,7 @@ mframe_get_prop (MFrame *frame, MSymbol key)
     return (void *) (frame->ascent);
   if (key == Mfont_descent)
     return (void *) (frame->descent);
-  return mwin__device_get_prop (frame->device, key);
+  return (*frame->driver->get_prop) (frame, key);
 }
 
 /*=*/
@@ -409,10 +774,10 @@ mframe_get_prop (MFrame *frame, MSymbol key)
     default frame that is created by the first call of mframe ().  */
 
 /***ja
-    ¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥ì¡¼¥à 
+    @brief ¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥ì¡¼¥à.
 
-    ³°ÉôÊÑ¿ô #mframe_default ¤Ï¡¢¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥ì¡¼¥à¤Ø¤Î¥Ý¥¤¥ó¥¿¤ò
-    »ý¤Ä¡£¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥ì¡¼¥à¤Ï¡¢ºÇ½é¤Ë mframe () ¤¬¸Æ¤Ó½Ð¤µ¤ì¤¿¤È¤­¤Ë
+    ³°ÉôÊÑ¿ô #mframe_default ¤Ï¡¢¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥ì¡¼¥à¤Ø¤Î¥Ý¥¤¥ó¥¿¤ò»ý
+    ¤Ä¡£¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥ì¡¼¥à¤Ï¡¢ºÇ½é¤Ë mframe () ¤¬¸Æ¤Ó½Ð¤µ¤ì¤¿¤È¤­¤Ë
     ºî¤é¤ì¤ë¡£  */
 
 MFrame *mframe_default;