#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;
goto err;
MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize input-win module."));
mframe_default = NULL;
- win_initialized = 1;
err:
MDEBUG_POP_TIME ();
{
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."));
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 ();
}
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;
+
+/*=*/
/*** @} */
/*=*/
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);
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;
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);
}
/*=*/