Include <dlfcn.h> and "config.h".
authorhanda <handa>
Thu, 27 May 2004 09:15:37 +0000 (09:15 +0000)
committerhanda <handa>
Thu, 27 May 2004 09:15:37 +0000 (09:15 +0000)
(free_frame): Call frame->driver->close instead of
mwin__close_device.
(DLOPEN_SHLIB_EXT): New macro.
(MDeviceLibraryInterface): New type.
(device_library_list): New variable.
(register_device_library): New function.
(null_device): New variable.
(null_device_close, null_device_get_prop)
(null_device_realize_face, null_device_free_realized_face): New
function.
(null_driver): New variable.
(null_device_init, null_device_fini, null_device_open): New
functions.
(null_interface): New variable.
(Mfreetype, Mdevice): Declare them.
(m17n_init_win): Increment win_initialized.  Initialize Mx, Mgd,
Mfreetype, Mdevice, Mdisplay, Mscreen, Mdrawable, Mdevice, and
Mwin__Close_Device.  Register drivers for Mx and Mgd.
(m17n_fini_win): Decremented win_initialized.  Call "fini"
function of all opened devices.  Don't call mwin__fini.
(Mdisplay, Mscreen, Mdrawable, Mdepth, Mwidget, Mcolormap):
Declare them here.
(mframe): Handle Mdevice key of PLIST.
(mframe_get_prop): Call frame->device->get_prop instead of
mwin__device_get_prop.

src/m17n-gui.c

index d81b891..a3f5620 100644 (file)
@@ -64,7 +64,9 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <dlfcn.h>
 
+#include "config.h"
 #include "m17n-gui.h"
 #include "m17n-misc.h"
 #include "internal.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.  */
+  void *(*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);
   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)
+{
+}
+
+void *
+null_device_get_prop (MFrame *frame, MSymbol key)
+{
+  return NULL;
+}
+
+void
+null_device_realize_face (MRealizedFace *rface)
+{
+  rface->info = NULL;
+}
+
+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 void *
+null_device_open (MFrame *frame, MPlist *param)
+{
+  frame->device_type = 0;
+  frame->driver = &null_driver;
+  frame->font_driver_list = mplist ();
+  mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
+  return &null_device;
+}
+
+static MDeviceLibraryInterface null_interface =
+  { NULL, NULL, null_device_init, null_device_open, null_device_fini };
+
+#endif
 \f
 /* Internal API */
 
+MSymbol Mfreetype;
+
 /*** @} */ 
 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
 
 \f
 /* External API */
 
+MSymbol Mdevice;
+
 void
 m17n_init_win (void)
 {
   int mdebug_mask = MDEBUG_INIT;
 
-  if (win_initialized)
+  if (win_initialized++)
     return;
   m17n_init ();
   if (merror_code != MERROR_NONE)
     return;
 
+  MDEBUG_PUSH_TIME ();
+
+  Mx = msymbol ("x");
+  Mgd = msymbol ("gd");
+
+  Mfreetype = msymbol ("freetype");
   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");
+
+  register_device_library (Mx, "libm17n-X");
+  register_device_library (Mgd, "libm17n-gd");
 
-  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;
@@ -133,7 +280,6 @@ m17n_init_win (void)
     goto err;
   MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize input-win module."));
   mframe_default = NULL;
-  win_initialized = 1;
 
  err:
   MDEBUG_POP_TIME ();
@@ -147,10 +293,31 @@ 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);
+         free (interface);
+       }
+      M17N_OBJECT_UNREF (device_library_list);
+      if (null_interface.handle)
+       (*null_interface.fini) ();
       MDEBUG_PRINT_TIME ("FINI", (stderr, " to finalize input-gui module."));
       minput__win_fini ();
       MDEBUG_PRINT_TIME ("FINI", (stderr, " to finalize draw module."));
@@ -159,15 +326,12 @@ 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 ();
 }
@@ -203,6 +367,28 @@ MSymbol Mfont_ascent;
 MSymbol Mfont_descent;
 
 /*=*/
+
+/***en
+    @name Variables: Keys of frame parameter (X specific).
+
+    These are the symbols to use as parameter keys for the function
+    mframe () (which see).  They are also keys of a frame property
+    except for #Mwidget.  */
+/***ja
+    @name ÊÑ¿ô¡§ ¥Õ¥ì¡¼¥à¥Ñ¥é¥á¡¼¥¿ÍÑ¥­¡¼ (X ¸ÇÍ­).
+
+    ´Ø¿ô mframe () ¤Î¥Ñ¥é¥á¡¼¥¿¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¥·¥ó¥Ü¥ë¡£( mframe
+    () ¤ÎÀâÌÀ»²¾È¡£) #Mwidget ¤ò½ü¤¤¤Æ¤Ï¥Õ¥ì¡¼¥à¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤Ç¤â¤¢
+    ¤ë¡£
+    */
+
+/*=*/
+
+MSymbol Mdisplay, Mscreen, Mdrawable, Mdepth, Mwidget, Mcolormap;
+
+MSymbol Mx, Mgd;
+
+/*=*/
 /*** @} */ 
 /*=*/
 
@@ -356,15 +542,57 @@ mframe (MPlist *plist)
   MFrame *frame;
   int plist_created = 0;
   MPlist *pl;
+  MSymbol device;
+  MDeviceLibraryInterface *interface;
 
-  M17N_OBJECT (frame, free_frame, MERROR_FRAME);
-  if (! plist)
+  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)
+    {
+      interface = &null_interface;
+      if (! interface->handle)
+       {
+         (*interface->init) ();
+         interface->handle = Mt;
+       }
+    }
+  else
+    {
+      interface = mplist_get (device_library_list, device);
+      if (! interface)
+       MERROR (MERROR_WIN, NULL);
+      if (! interface->handle)
+       {
+         interface->handle = dlopen (interface->library, RTLD_NOW);
+         if (! interface->handle)
+           MERROR (MERROR_WIN, NULL);
+         interface->init = dlsym (interface->handle, "device_init");
+         interface->open = dlsym (interface->handle, "device_open");
+         interface->fini = dlsym (interface->handle, "device_fini");
+         if (! interface->init || ! interface->open || ! interface->fini
+             || (*interface->init) () < 0)
+           {
+             dlclose (interface->handle);
+             MERROR (MERROR_WIN, NULL);
+           }
+       }
     }
-  frame->device = mwin__open_device (frame, plist);
-  if (! frame->device)
+
+  M17N_OBJECT (frame, free_frame, MERROR_FRAME);
+  if (! (frame->device = (*interface->open) (frame, plist)))
     {
       free (frame);
       MERROR (MERROR_WIN, NULL);
@@ -375,8 +603,6 @@ mframe (MPlist *plist)
     if (MPLIST_KEY (pl) == Mface)
       mface_merge (frame->face, (MFace *) MPLIST_VAL (pl));
   mface__update_frame_face (frame);
-  if (! frame->rface->rfont)
-    MERROR (MERROR_WIN, NULL);
 
   if (! mframe_default)
     mframe_default = frame;
@@ -481,7 +707,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);
 }
 
 /*=*/