+static void
+mwin__adjust_window (MFrame *frame, MDrawWindow win,
+ MDrawMetric *current, MDrawMetric *new)
+{
+ Display *display = FRAME_DISPLAY (frame);
+ unsigned int mask = 0;
+ XWindowChanges values;
+
+ if (current->width != new->width)
+ {
+ mask |= CWWidth;
+ if (new->width <= 0)
+ new->width = 1;
+ values.width = current->width = new->width;
+ }
+ if (current->height != new->height)
+ {
+ mask |= CWHeight;
+ if (new->height <= 0)
+ new->height = 1;
+ values.height = current->height = new->height;
+ }
+ if (current->x != new->x)
+ {
+ mask |= CWX;
+ values.x = current->x = new->x;
+ }
+ if (current->y != new->y)
+ {
+ mask |= CWY;
+ current->y = new->y;
+ values.y = current->y = new->y;
+ }
+ if (mask)
+ XConfigureWindow (display, (Window) win, mask, &values);
+ XClearWindow (display, (Window) win);
+}
+
+static MSymbol
+mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
+{
+ XEvent *event = (XEvent *) arg;
+ MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
+ int len;
+ char buf[512];
+ KeySym keysym;
+ MSymbol key;
+
+ *modifiers = 0;
+ if (event->xany.type != KeyPress
+ /* && event->xany.type != KeyRelease */
+ )
+ return Mnil;
+ len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
+ if (len > 1)
+ return Mnil;
+ if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
+ return Mnil;
+ if (len == 1 && keysym >= XK_space && keysym <= XK_asciitilde)
+ {
+ int c = keysym;
+
+ key = minput__char_to_key (c);
+ if (c == ' ' && ((XKeyEvent *) event)->state & ShiftMask)
+ *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
+ }
+ else
+ {
+ 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.list = mfont__ft_driver.list;
+ xft_driver.list_family_names = mfont__ft_driver.list_family_names;
+#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;
+}
+
+
+#ifdef X_SET_ERROR_HANDLER
+static int
+x_error_handler (Display *display, XErrorEvent *error)
+{
+ mdebug_hook ();
+ return 0;
+}
+
+static int
+x_io_error_handler (Display *display)
+{
+ mdebug_hook ();
+ return 0;
+}
+#endif
+
+/** 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;
+ MFont *font = NULL;
+ 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 ();
+ find_modifier_bits (disp_info);
+ disp_info->MULE_BASELINE_OFFSET
+ = XInternAtom (display, "_MULE_BASELINE_OFFSET", False);
+ disp_info->AVERAGE_WIDTH
+ = XInternAtom (display, "AVERAGE_WIDTH", False);
+ 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
+ && device->screen_num == screen_num)
+ break;
+ }
+
+ if (mplist_key (plist) != Mnil)
+ M17N_OBJECT_REF (device);
+ else
+ {
+ unsigned long valuemask = GCForeground;
+ XGCValues values;
+ double pixels, mm;
+
+ 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;
+ pixels = DisplayHeight (display, screen_num);
+ mm = DisplayHeightMM (display, screen_num);
+ device->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
+ device->realized_face_list = mplist ();
+ device->realized_font_list = mplist ();
+ mplist_add (device->realized_font_list, Mt, NULL);
+ 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->dpi = device->resy;
+ 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;
+ }
+
+ if (strcmp (app_data.font, DEFAULT_FONT) != 0)
+ {
+ XFontStruct *xfont = XLoadQueryFont (display, app_data.font);
+ unsigned long value;
+ char *name;
+
+ if (xfont)
+ {
+ font = mfont_parse_name (app_data.font, Mx);
+ if (! font
+ && XGetFontProperty (xfont, XA_FONT, &value)
+ && (name = ((char *) XGetAtomName (display, (Atom) value))))
+ font = mfont_parse_name (name, Mx);
+ XFreeFont (display, xfont);
+ }
+ }
+ if (! font)
+ font = mfont_parse_name (DEFAULT_FONT, Mx);
+ else if (! font->size)
+ font->size = 130;
+ face = mface_from_font (font);
+ free (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