+ else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
+ return Mnil;
+ if (key == Mnil)
+ {
+ char *str = XKeysymToString (keysym);
+
+ if (! str)
+ return Mnil;
+ key = msymbol (str);
+ if (((XKeyEvent *) event)->state & ShiftMask)
+ *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
+ if (((XKeyEvent *) event)->state & ControlMask)
+ *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
+ }
+ if (((XKeyEvent *) event)->state & disp_info->meta_mask)
+ *modifiers |= MINPUT_KEY_META_MODIFIER;
+ if (((XKeyEvent *) event)->state & disp_info->alt_mask)
+ *modifiers |= MINPUT_KEY_ALT_MODIFIER;
+ if (((XKeyEvent *) event)->state & disp_info->super_mask)
+ *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
+ if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
+ *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
+
+ return key;
+}
+
+
+void
+mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
+{
+ unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
+ XGCValues values;
+ Display *display = FRAME_DISPLAY (frame);
+ GCInfo *info = rface->info;
+ int i;
+
+ for (i = 0; i <= GC_INVERSE; i++)
+ {
+ XGetGCValues (display, info->gc[i], valuemask, &values);
+ fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
+ values.foreground, values.background);
+ fprintf (stderr, "\n");
+ }
+}
+
+static MDeviceDriver x_driver =
+ {
+ mwin__close_device,
+ mwin__device_get_prop,
+ mwin__realize_face,
+ mwin__free_realized_face,
+ mwin__fill_space,
+ mwin__draw_empty_boxes,
+ mwin__draw_hline,
+ mwin__draw_box,
+ mwin__draw_points,
+ mwin__region_from_rect,
+ mwin__union_rect_with_region,
+ mwin__intersect_region,
+ mwin__region_add_rect,
+ mwin__region_to_rect,
+ mwin__free_region,
+ mwin__dump_region,
+ mwin__create_window,
+ mwin__destroy_window,
+ mwin__map_window,
+ mwin__unmap_window,
+ mwin__window_geometry,
+ mwin__adjust_window,
+ mwin__parse_event
+ };
+
+/* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
+
+int
+device_init ()
+{
+ M_iso8859_1 = msymbol ("iso8859-1");
+ M_iso10646_1 = msymbol ("iso10646-1");
+
+ display_info_list = mplist ();
+ device_list = mplist ();
+
+#ifdef HAVE_XFT2
+ xft_driver.select = mfont__ft_driver.select;
+ xft_driver.encode_char = mfont__ft_driver.encode_char;
+ xft_driver.list = mfont__ft_driver.list;
+#endif
+
+ Mxim = msymbol ("xim");
+ msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
+
+ return 0;
+}
+
+int
+device_fini ()
+{
+ M17N_OBJECT_UNREF (display_info_list);
+ M17N_OBJECT_UNREF (device_list);
+ return 0;
+}
+
+/** Return an MWDevice object corresponding to a display specified in
+ PLIST.
+
+ It searches device_list for a device matching the display. If
+ found, return the found object. Otherwise, return a newly created
+ object. */
+
+int
+device_open (MFrame *frame, MPlist *param)
+{
+ Display *display = NULL;
+ Screen *screen = NULL;
+ int screen_num;
+ Drawable drawable = 0;
+ Widget widget = NULL;
+ Colormap cmap = 0;
+ int auto_display = 0;
+ MDisplayInfo *disp_info = NULL;
+ MWDevice *device = NULL;
+ MSymbol key;
+ XWindowAttributes attr;
+ unsigned depth = 0;
+ MPlist *plist;
+ AppData app_data;
+ MFace *face;
+ int use_xfont = 0, use_freetype = 0, use_xft = 0;
+
+ for (plist = param; (key = mplist_key (plist)) != Mnil;
+ plist = mplist_next (plist))
+ {
+ if (key == Mdisplay)
+ display = (Display *) mplist_value (plist);
+ else if (key == Mscreen)
+ screen = mplist_value (plist);
+ else if (key == Mdrawable)
+ drawable = (Drawable) mplist_value (plist);
+ else if (key == Mdepth)
+ depth = (unsigned) mplist_value (plist);
+ else if (key == Mwidget)
+ widget = (Widget) mplist_value (plist);
+ else if (key == Mcolormap)
+ cmap = (Colormap) mplist_value (plist);
+ else if (key == Mfont)
+ {
+ MSymbol val = MPLIST_SYMBOL (plist);
+
+ if (val == Mx)
+ use_xfont = 1;
+#ifdef HAVE_FREETYPE
+ else if (val == Mfreetype)
+ use_freetype = 1;
+#ifdef HAVE_XFT2
+ else if (val == Mxft)
+ use_xft = 1;
+#endif
+#endif
+ }
+ }
+
+ /* If none of them is specified, use all of them. */
+ if (! use_xfont && ! use_freetype && ! use_xft)
+ use_xfont = use_freetype = use_xft = 1;
+
+ if (widget)
+ {
+ display = XtDisplay (widget);
+ screen_num = XScreenNumberOfScreen (XtScreen (widget));
+ depth = DefaultDepth (display, screen_num);
+ }
+ else if (drawable)
+ {
+ Window root_window;
+ int x, y;
+ unsigned width, height, border_width;
+
+ if (! display)
+ MERROR (MERROR_WIN, -1);
+ XGetGeometry (display, drawable, &root_window,
+ &x, &y, &width, &height, &border_width, &depth);
+ XGetWindowAttributes (display, root_window, &attr);
+ screen_num = XScreenNumberOfScreen (attr.screen);
+ }
+ else
+ {
+ if (screen)
+ display = DisplayOfScreen (screen);
+ else
+ {
+ if (! display)
+ {
+ display = XOpenDisplay (NULL);
+ if (! display)
+ MERROR (MERROR_WIN, -1);
+ auto_display = 1;
+ }
+ screen = DefaultScreenOfDisplay (display);
+ }
+ screen_num = XScreenNumberOfScreen (screen);
+ if (! depth)
+ depth = DefaultDepth (display, screen_num);
+ }
+
+ if (! cmap)
+ cmap = DefaultColormap (display, screen_num);
+
+ for (plist = display_info_list; mplist_key (plist) != Mnil;
+ plist = mplist_next (plist))
+ {
+ disp_info = (MDisplayInfo *) mplist_value (plist);
+ if (disp_info->display == display)
+ break;
+ }
+
+ if (mplist_key (plist) != Mnil)
+ M17N_OBJECT_REF (disp_info);
+ else
+ {
+ M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
+ disp_info->display = display;
+ disp_info->auto_display = auto_display;
+ disp_info->font_list = mplist ();
+ disp_info->base_font_list = mplist ();
+ find_modifier_bits (disp_info);
+ mplist_add (display_info_list, Mt, disp_info);
+ }
+
+ for (plist = device_list; mplist_key (plist) != Mnil;
+ plist = mplist_next (plist))
+ {
+ device = (MWDevice *) mplist_value (plist);
+ if (device->display_info == disp_info
+ && device->depth == depth
+ && device->cmap == cmap)
+ break;
+ }
+
+ if (mplist_key (plist) != Mnil)
+ M17N_OBJECT_REF (device);
+ else
+ {
+ unsigned long valuemask = GCForeground;
+ XGCValues values;
+
+ M17N_OBJECT (device, free_device, MERROR_WIN);
+ device->display_info = disp_info;
+ device->screen_num = screen_num;
+ /* A drawable on which to create GCs. */
+ device->drawable = XCreatePixmap (display,
+ RootWindow (display, screen_num),
+ 1, 1, depth);
+ device->depth = depth;
+ device->cmap = cmap;
+ device->realized_face_list = mplist ();
+ device->realized_font_list = mplist ();
+ device->realized_fontset_list = mplist ();
+ device->gc_list = mplist ();
+ values.foreground = BlackPixel (display, screen_num);
+ device->scratch_gc = XCreateGC (display, device->drawable,
+ valuemask, &values);
+#ifdef HAVE_XFT2
+ device->xft_draw = XftDrawCreate (display, device->drawable,
+ DefaultVisual (display, screen_num),
+ cmap);
+#endif
+ }
+
+ frame->device = device;
+ frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
+ frame->driver = &x_driver;
+ frame->font_driver_list = mplist ();
+#ifdef HAVE_XFT2
+ if (use_xft)
+ {
+ mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
+ use_freetype = 0;
+ }
+#endif /* HAVE_XFT2 */
+#ifdef HAVE_FREETYPE
+ if (use_freetype)
+ mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
+#endif /* HAVE_FREETYPE */
+ if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list))
+ mplist_push (frame->font_driver_list, Mx, &xfont_driver);
+
+ frame->realized_font_list = device->realized_font_list;
+ frame->realized_face_list = device->realized_face_list;
+ frame->realized_fontset_list = device->realized_fontset_list;
+
+ if (widget)
+ {
+ XtResource resources[] = {
+ { XtNfont, XtCFont, XtRString, sizeof (String),
+ XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
+ { XtNforeground, XtCForeground, XtRString, sizeof (String),
+ XtOffset (AppDataPtr, foreground), XtRString, "black" },
+ { XtNbackground, XtCBackground, XtRString, sizeof (String),
+ XtOffset (AppDataPtr, background), XtRString, "white" },
+ { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
+ XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
+ };
+
+ XtGetApplicationResources (widget, &app_data,
+ resources, XtNumber (resources), NULL, 0);
+ frame->foreground = msymbol (app_data.foreground);
+ frame->background = msymbol (app_data.background);
+ frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
+ }
+ else
+ {
+ app_data.font = DEFAULT_FONT;
+ frame->foreground = msymbol ("black");
+ frame->background = msymbol ("white");
+ frame->videomode = Mnormal;
+ }
+
+ {
+ int nfonts, i;
+ /* Try at least 32 fonts to obtain a non-autoscaled font. */
+ char **names = XListFonts (display, app_data.font, 32, &nfonts);
+ MFont *font = NULL;
+
+ for (i = 0; ! font && i < nfonts; i++)
+ {
+ font = mfont_parse_name (names[i], Mx);
+ if (!font)
+ {
+ /* The font name does not conform to XLFD. Try to open the
+ font and get XA_FONT property. */
+ XFontStruct *xfont = XLoadQueryFont (display, names[i]);
+
+ if (xfont)
+ {
+ unsigned long value;
+ char *name;
+
+ if (XGetFontProperty (xfont, XA_FONT, &value)
+ && (name = ((char *)
+ XGetAtomName (display, (Atom) value))))
+ font = mfont_parse_name (name, Mx);
+ XFreeFont (display, xfont);
+ }
+ }
+ if (font &&
+ font->property[MFONT_SIZE] == 0 && font->property[MFONT_RESY] > 0)
+ {
+ free (font);
+ font = NULL;
+ }
+ }
+ if (nfonts)
+ XFreeFontNames (names);
+ frame->font = font ? font : mfont_parse_name (FALLBACK_FONT, Mx);
+ }
+
+ face = mface_from_font (frame->font);
+ face->property[MFACE_FONTSET] = mfontset (NULL);
+ face->property[MFACE_FOREGROUND] = frame->foreground;
+ face->property[MFACE_BACKGROUND] = frame->background;
+ mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
+ mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
+ face->property[MFACE_VIDEOMODE] = frame->videomode;
+ mface_put_prop (face, Mhook_func,
+ mface_get_prop (mface__default, Mhook_func));
+ face->property[MFACE_RATIO] = (void *) 100;
+ mplist_push (param, Mface, face);
+ M17N_OBJECT_UNREF (face);
+
+#ifdef X_SET_ERROR_HANDLER
+ XSetErrorHandler (x_error_handler);
+ XSetIOErrorHandler (x_io_error_handler);
+#endif
+
+ return 0;
+}
+
+\f
+
+/* XIM (X Input Method) handler */
+
+typedef struct MInputXIMMethodInfo
+{
+ Display *display;
+ XIM xim;
+ MSymbol language;
+ MSymbol coding;
+} MInputXIMMethodInfo;
+
+typedef struct MInputXIMContextInfo
+{
+ XIC xic;
+ Window win;
+ MConverter *converter;
+} MInputXIMContextInfo;
+
+static int
+xim_open_im (MInputMethod *im)
+{
+ MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
+ MLocale *saved, *this;
+ char *save_modifier_list;
+ XIM xim;
+ MInputXIMMethodInfo *im_info;
+
+ saved = mlocale_set (LC_CTYPE, NULL);
+ this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
+ if (! this)
+ /* The specified locale is not supported. */
+ MERROR (MERROR_LOCALE, -1);
+ if (mlocale_get_prop (this, Mcoding) == Mnil)
+ {
+ /* Unable to decode the output of XIM. */
+ mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
+ MERROR (MERROR_LOCALE, -1);
+ }
+
+ if (arg->modifier_list)
+ save_modifier_list = XSetLocaleModifiers (arg->modifier_list);