1 /* m17n-X.c -- implementation of the GUI API on X Windows.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
24 /*** @addtogroup m17nInternal
36 #include <X11/keysym.h>
37 #include <X11/Xlocale.h>
38 #include <X11/Xutil.h>
39 #include <X11/Xresource.h>
40 #include <X11/Xatom.h>
41 #include <X11/StringDefs.h>
42 #include <X11/Intrinsic.h>
45 #include <X11/Xft/Xft.h>
46 #endif /* HAVE_XFT2 */
50 #include "m17n-misc.h"
52 #include "internal-gui.h"
61 /* Common header for the m17n object. */
66 /* If nonzero, <display> is opened by this library. Thus it should
67 be closed on freeing this structure. */
70 /** List of available fonts on the display (except for iso8859-1 and
71 iso10646-1 fonts). Keys are font registries, values are
73 MPlist *font_registry_list;
75 MPlist *iso8859_1_family_list;
77 MPlist *iso10646_1_family_list;
79 /* List of information about each font. Keys are font registries,
80 values are (MFontInfo *). */
81 MPlist *realized_font_list;
83 /** Modifier bit masks of the display. */
90 /* Anchor of the chain of MDisplayInfo objects. */
91 static MPlist *display_info_list;
94 /* Color value and the corresponding GC. */
97 unsigned int rgb; /* (red << 16) | (green << 8) | blue */
104 GC_NORMAL = GC_INVERSE + 7,
117 /* The first 8 elements are indexed by an intensity for
118 anti-aliasing. The 2nd to 7th are created on demand. */
121 XftColor xft_color_fore, xft_color_back;
127 /* Common header for the m17n object. */
130 MDisplayInfo *display_info;
146 /** List of pointers to realized faces on the frame. */
147 MPlist *realized_face_list;
149 /** List of pointers to realized fontsets on the frame. */
150 MPlist *realized_fontset_list;
152 /** List of XColors vs GCs on the frame. */
156 static MPlist *device_list;
158 static MSymbol M_iso8859_1, M_iso10646_1;
160 #define FRAME_DEVICE(frame) ((MWDevice *) (frame)->device)
161 #define FRAME_DISPLAY(frame) (FRAME_DEVICE (frame)->display_info->display)
162 #define FRAME_SCREEN(frame) (FRAME_DEVICE (frame)->screen_num)
163 #define FRAME_CMAP(frame) (FRAME_DEVICE (frame)->cmap)
164 #define FRAME_VISUAL(frame) DefaultVisual (FRAME_DISPLAY (frame), \
165 FRAME_SCREEN (frame))
167 #define DEFAULT_FONT "-misc-fixed-medium-r-normal--*-120-*-*-*-*-iso8859-1"
168 #define FALLBACK_FONT "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1"
175 Boolean reverse_video;
176 } AppData, *AppDataPtr;
179 free_display_info (void *object)
181 MDisplayInfo *disp_info = (MDisplayInfo *) object;
184 MPLIST_DO (plist, disp_info->font_registry_list)
186 MFontList *registry_list = MPLIST_VAL (plist);
188 if (registry_list->fonts)
189 free (registry_list->fonts);
190 free (registry_list);
192 M17N_OBJECT_UNREF (disp_info->font_registry_list);
194 MPLIST_DO (plist, disp_info->iso8859_1_family_list)
196 MFontList *family_list = MPLIST_VAL (plist);
198 if (family_list->fonts)
199 free (family_list->fonts);
202 M17N_OBJECT_UNREF (disp_info->iso8859_1_family_list);
204 MPLIST_DO (plist, disp_info->iso10646_1_family_list)
206 MFontList *family_list = MPLIST_VAL (plist);
208 if (family_list->fonts)
209 free (family_list->fonts);
212 M17N_OBJECT_UNREF (disp_info->iso10646_1_family_list);
214 MPLIST_DO (plist, disp_info->realized_font_list)
215 mfont__free_realized ((MRealizedFont *) MPLIST_VAL (plist));
216 M17N_OBJECT_UNREF (disp_info->realized_font_list);
218 if (disp_info->auto_display)
219 XCloseDisplay (disp_info->display);
225 free_device (void *object)
227 MWDevice *device = object;
230 for (plist = device->realized_fontset_list;
231 mplist_key (plist) != Mnil; plist = mplist_next (plist))
232 mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist));
233 M17N_OBJECT_UNREF (device->realized_fontset_list);
235 MPLIST_DO (plist, device->realized_face_list)
237 MRealizedFace *rface = MPLIST_VAL (plist);
240 mface__free_realized (rface);
242 M17N_OBJECT_UNREF (device->realized_face_list);
244 MPLIST_DO (plist, device->gc_list)
246 XFreeGC (device->display_info->display,
247 ((RGB_GC *) MPLIST_VAL (plist))->gc);
248 free (MPLIST_VAL (plist));
250 M17N_OBJECT_UNREF (device->gc_list);
251 XFreeGC (device->display_info->display, device->scratch_gc);
254 XftDrawDestroy (device->xft_draw);
257 XFreePixmap (device->display_info->display, device->drawable);
258 M17N_OBJECT_UNREF (device->display_info);
264 find_modifier_bits (MDisplayInfo *disp_info)
266 Display *display = disp_info->display;
267 XModifierKeymap *mods;
268 KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L);
269 KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R);
270 KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L);
271 KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R);
272 KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
273 KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
274 KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
275 KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
278 mods = XGetModifierMapping (display);
279 /* We skip the first three sets for Shift, Lock, and Control. The
280 remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
281 for (i = 3; i < 8; i++)
282 for (j = 0; j < mods->max_keypermod; j++)
284 KeyCode code = mods->modifiermap[i * mods->max_keypermod + j];
288 if (code == meta_l || code == meta_r)
289 disp_info->meta_mask |= (1 << i);
290 else if (code == alt_l || code == alt_r)
291 disp_info->alt_mask |= (1 << i);
292 else if (code == super_l || code == super_r)
293 disp_info->super_mask |= (1 << i);
294 else if (code == hyper_l || code == hyper_r)
295 disp_info->hyper_mask |= (1 << i);
298 /* If meta keys are not in any modifier, use alt keys as meta
300 if (! disp_info->meta_mask)
302 disp_info->meta_mask = disp_info->alt_mask;
303 disp_info->alt_mask = 0;
305 /* If both meta and alt are assigned to the same modifier, give meta
307 if (disp_info->meta_mask & disp_info->alt_mask)
308 disp_info->alt_mask &= ~disp_info->meta_mask;
310 XFreeModifiermap (mods);
314 get_rgb_gc (MWDevice *device, XColor *xcolor)
316 int rgb = (((xcolor->red >> 8) << 16) | ((xcolor->green >> 8) << 8)
317 | (xcolor->blue >> 8));
320 unsigned long valuemask = GCForeground;
323 MPLIST_DO (plist, device->gc_list)
325 rgb_gc = MPLIST_VAL (plist);
327 if (rgb_gc->rgb == rgb)
329 if (rgb_gc->rgb > rgb)
333 if (! XAllocColor (device->display_info->display, device->cmap, xcolor))
336 rgb_gc = malloc (sizeof (RGB_GC));
338 values.foreground = xcolor->pixel;
339 rgb_gc->gc = XCreateGC (device->display_info->display,
340 device->drawable, valuemask, &values);
341 mplist_push (plist, Mt, rgb_gc);
346 get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret)
348 MWDevice *device = FRAME_DEVICE (frame);
356 color = for_foreground ? frame->foreground : frame->background;
358 if (! XParseColor (FRAME_DISPLAY (frame), device->cmap,
359 msymbol_name (color), &xcolor))
361 rgb_gc = get_rgb_gc (device, &xcolor);
365 *rgb_ret = rgb_gc->rgb;
370 GCInfo *info = frame->rface->info;
375 rgb = info->rgb_fore, gc = info->gc[GC_NORMAL];
377 rgb = info->rgb_back, gc = info->gc[GC_INVERSE];
385 get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity)
387 int rgb_fore, rgb_back;
392 if (info->gc[intensity])
393 return info->gc[intensity];
395 rgb_fore = info->rgb_fore, rgb_back = info->rgb_back;
396 xcolor.red = ((((rgb_fore & 0xFF0000) >> 16) * intensity
397 + ((rgb_back & 0xFF0000) >> 16) * (7 - intensity)) / 7) << 8;
398 xcolor.green = ((((rgb_fore & 0xFF00) >> 8) * intensity
399 + ((rgb_back & 0xFF00) >> 8) * (7 - intensity)) / 7) << 8;
400 xcolor.blue = (((rgb_fore & 0xFF) * intensity
401 + (rgb_back & 0xFF) * (7 - intensity)) / 7) << 8;
402 rgb_gc = get_rgb_gc (device, &xcolor);
406 gc =get_gc_for_anti_alias (device, info,
407 intensity < 4 ? intensity - 1 : intensity + 1);
408 return (info->gc[intensity] = gc);
412 set_region (MFrame *frame, GC gc, MDrawRegion region)
414 unsigned long valuemask = GCForeground;
416 XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
417 FRAME_DEVICE (frame)->scratch_gc);
418 XSetRegion (FRAME_DISPLAY (frame), FRAME_DEVICE (frame)->scratch_gc, region);
419 return FRAME_DEVICE (frame)->scratch_gc;
423 /* Functions for the device driver. */
426 mwin__close_device (MFrame *frame)
428 M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
432 mwin__device_get_prop (MFrame *frame, MSymbol key)
434 MWDevice *device = FRAME_DEVICE (frame);
437 return (void *) device->display_info->display;
439 return (void *) ScreenOfDisplay(device->display_info->display,
441 if (key == Mcolormap)
442 return (void *) device->cmap;
444 return (void *) device->depth;
449 mwin__realize_face (MRealizedFace *rface)
452 MSymbol foreground, background, videomode;
453 MFaceHLineProp *hline;
457 if (rface != rface->ascii_rface)
459 rface->info = rface->ascii_rface->info;
463 frame = rface->frame;
464 MSTRUCT_CALLOC (info, MERROR_WIN);
466 foreground = rface->face.property[MFACE_FOREGROUND];
467 background = rface->face.property[MFACE_BACKGROUND];
468 videomode = rface->face.property[MFACE_VIDEOMODE];
470 videomode = frame->videomode;
471 if (videomode != Mreverse)
473 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
474 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
478 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
479 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
482 if (foreground == Mnil)
483 foreground = frame->foreground;
484 if (background == Mnil)
485 background = frame->background;
486 if (videomode == Mreverse)
488 MSymbol temp = foreground;
489 foreground = background;
492 if (! XftColorAllocName (FRAME_DISPLAY (frame),
493 FRAME_VISUAL (frame),
495 MSYMBOL_NAME (foreground),
496 &info->xft_color_fore))
498 if (! XftColorAllocName (FRAME_DISPLAY (frame),
499 FRAME_VISUAL (frame),
501 MSYMBOL_NAME (background),
502 &info->xft_color_back))
506 hline = rface->hline;
510 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
512 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
519 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
521 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
523 if (box->color_left && box->color_left != box->color_top)
524 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
526 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
528 if (box->color_bottom && box->color_bottom != box->color_top)
529 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
531 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
533 if (box->color_right && box->color_right != box->color_bottom)
534 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
536 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
544 mwin__free_realized_face (MRealizedFace *rface)
546 if (rface == rface->ascii_rface)
552 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
554 int x, int y, int width, int height, MDrawRegion region)
556 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
559 gc = set_region (frame, gc, region);
561 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
562 x, y, width, height);
566 void mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
567 MGlyphString *gstring, MGlyph *from, MGlyph *to,
568 int reverse, MDrawRegion region)
570 MRealizedFace *rface = from->rface;
571 Display *display = FRAME_DISPLAY (rface->frame);
572 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
578 gc = set_region (rface->frame, gc, region);
579 for (; from < to; from++)
581 XDrawRectangle (display, (Window) win, gc,
582 x, y - gstring->ascent + 1, from->width - 1,
583 gstring->ascent + gstring->descent - 2);
590 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
591 MRealizedFace *rface, int reverse,
592 int x, int y, int width, MDrawRegion region)
594 enum MFaceHLineType type = rface->hline->type;
595 GCInfo *info = rface->info;
596 GC gc = gc = info->gc[GC_HLINE];
599 y = (type == MFACE_HLINE_BOTTOM
600 ? y + gstring->text_descent - rface->hline->width
601 : type == MFACE_HLINE_UNDER
603 : type == MFACE_HLINE_STRIKE_THROUGH
604 ? y - ((gstring->ascent + gstring->descent) / 2)
605 : y - gstring->text_ascent);
607 gc = set_region (frame, gc, region);
609 for (i = 0; i < rface->hline->width; i++)
610 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
611 x, y + i, x + width - 1, y + i);
616 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
617 MGlyph *g, int x, int y, int width, MDrawRegion region)
619 Display *display = FRAME_DISPLAY (frame);
620 MRealizedFace *rface = g->rface;
621 MFaceBoxProp *box = rface->box;
622 GCInfo *info = rface->info;
623 GC gc_top, gc_left, gc_right, gc_btm;
627 y0 = y - (gstring->text_ascent
628 + rface->box->inner_vmargin + rface->box->width);
629 y1 = y + (gstring->text_descent
630 + rface->box->inner_vmargin + rface->box->width - 1);
632 gc_top = info->gc[GC_BOX_TOP];
634 gc_top = set_region (frame, gc_top, region);
635 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
638 gc_btm = info->gc[GC_BOX_BOTTOM];
640 if (g->type == GLYPH_BOX)
645 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
647 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
649 /* Draw the top side. */
650 for (i = 0; i < box->width; i++)
651 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
653 /* Draw the bottom side. */
654 if (region && gc_btm != gc_top)
655 gc_btm = set_region (frame, gc_btm, region);
656 for (i = 0; i < box->width; i++)
657 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
659 if (g->left_padding > 0)
661 /* Draw the left side. */
662 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
666 gc_left = info->gc[GC_BOX_LEFT];
668 gc_left = set_region (frame, gc_left, region);
670 for (i = 0; i < rface->box->width; i++)
671 XDrawLine (display, (Window) win, gc_left,
672 x0 + i, y0 + i, x0 + i, y1 - i);
676 /* Draw the right side. */
677 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
681 gc_right = info->gc[GC_BOX_RIGHT];
683 gc_right = set_region (frame, gc_right, region);
685 for (i = 0; i < rface->box->width; i++)
686 XDrawLine (display, (Window) win, gc_right,
687 x1 - i, y0 + i, x1 - i, y1 - i);
692 /* Draw the top side. */
693 for (i = 0; i < box->width; i++)
694 XDrawLine (display, (Window) win, gc_top,
695 x, y0 + i, x + width - 1, y0 + i);
697 /* Draw the bottom side. */
698 if (region && gc_btm != gc_top)
699 gc_btm = set_region (frame, gc_btm, region);
700 for (i = 0; i < box->width; i++)
701 XDrawLine (display, (Window) win, gc_btm,
702 x, y1 - i, x + width - 1, y1 - i);
709 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
710 int reverse, int x, int y,
711 int width, int height, int row_bytes, unsigned char *bmp,
714 Display *display = FRAME_DISPLAY (frame);
716 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
719 gc = set_region (frame, gc, region);
721 for (i = 0; i < height; i++, bmp += row_bytes)
722 for (j = 0; j < width; j++)
723 if (bmp[j / 8] & (1 << (7 - (j % 8))))
724 XDrawPoint (display, (Window) win, gc, x + j, y + i);
729 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
730 int intensity, MDrawPoint *points, int num,
733 GCInfo *info = rface->info;
736 if (! (gc = info->gc[intensity]))
737 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
740 gc = set_region (frame, gc, region);
742 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
743 (XPoint *) points, num, CoordModeOrigin);
748 mwin__region_from_rect (MDrawMetric *rect)
750 MDrawRegion region1 = XCreateRegion ();
751 MDrawRegion region2 = XCreateRegion ();
756 xrect.width = rect->width;
757 xrect.height = rect->height;
758 XUnionRectWithRegion (&xrect, region1, region2);
759 XDestroyRegion (region1);
764 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
766 MDrawRegion region1 = XCreateRegion ();
771 xrect.width = rect->width;
772 xrect.height = rect->height;
774 XUnionRegion (region, region, region1);
775 XUnionRectWithRegion (&xrect, region1, region);
776 XDestroyRegion (region1);
780 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
782 MDrawRegion region = XCreateRegion ();
784 XUnionRegion (region1, region1, region);
785 XIntersectRegion (region, region2, region1);
786 XDestroyRegion (region);
790 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
792 MDrawRegion region1 = XCreateRegion ();
797 xrect.width = rect->width;
798 xrect.height = rect->height;
799 XUnionRectWithRegion (&xrect, region1, region);
800 XDestroyRegion (region1);
804 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
808 XClipBox (region, &xrect);
811 rect->width = xrect.width;
812 rect->height = xrect.height;
816 mwin__free_region (MDrawRegion region)
818 XDestroyRegion (region);
822 mwin__dump_region (MDrawRegion region)
825 XClipBox (region, &rect);
826 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
831 mwin__create_window (MFrame *frame, MDrawWindow parent)
833 Display *display = FRAME_DISPLAY (frame);
835 XWMHints wm_hints = { InputHint, False };
836 XClassHint class_hints = { "M17N-IM", "m17n-im" };
837 XSetWindowAttributes set_attrs;
840 GCInfo *info = frame->rface->info;
843 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
845 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
846 set_attrs.background_pixel = values.foreground;
847 set_attrs.backing_store = Always;
848 set_attrs.override_redirect = True;
849 set_attrs.save_under = True;
850 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
851 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
852 CopyFromParent, InputOutput, CopyFromParent,
854 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
855 NULL, &wm_hints, &class_hints);
856 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
857 return (MDrawWindow) win;
861 mwin__destroy_window (MFrame *frame, MDrawWindow win)
863 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
868 mwin__event_window (void *event)
870 return ((MDrawWindow) ((XEvent *) event)->xany.window);
874 mwin__print_event (void *arg, char *win_name)
877 XEvent *event = (XEvent *) arg;
879 switch (event->xany.type)
881 case 2: event_name = "KeyPress"; break;
882 case 3: event_name = "KeyRelease"; break;
883 case 4: event_name = "ButtonPress"; break;
884 case 5: event_name = "ButtonRelease"; break;
885 case 6: event_name = "MotionNotify"; break;
886 case 7: event_name = "EnterNotify"; break;
887 case 8: event_name = "LeaveNotify"; break;
888 case 9: event_name = "FocusIn"; break;
889 case 10: event_name = "FocusOut"; break;
890 case 11: event_name = "KeymapNotify"; break;
891 case 12: event_name = "Expose"; break;
892 case 13: event_name = "GraphicsExpose"; break;
893 case 14: event_name = "NoExpose"; break;
894 case 15: event_name = "VisibilityNotify"; break;
895 case 16: event_name = "CreateNotify"; break;
896 case 17: event_name = "DestroyNotify"; break;
897 case 18: event_name = "UnmapNotify"; break;
898 case 19: event_name = "MapNotify"; break;
899 case 20: event_name = "MapRequest"; break;
900 case 21: event_name = "ReparentNotify"; break;
901 case 22: event_name = "ConfigureNotify"; break;
902 case 23: event_name = "ConfigureRequest"; break;
903 case 24: event_name = "GravityNotify"; break;
904 case 25: event_name = "ResizeRequest"; break;
905 case 26: event_name = "CirculateNotify"; break;
906 case 27: event_name = "CirculateRequest"; break;
907 case 28: event_name = "PropertyNotify"; break;
908 case 29: event_name = "SelectionClear"; break;
909 case 30: event_name = "SelectionRequest"; break;
910 case 31: event_name = "SelectionNotify"; break;
911 case 32: event_name = "ColormapNotify"; break;
912 case 33: event_name = "ClientMessage"; break;
913 case 34: event_name = "MappingNotify"; break;
914 default: event_name = "unknown";
917 fprintf (stderr, "%s: %s\n", win_name, event_name);
922 mwin__map_window (MFrame *frame, MDrawWindow win)
924 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
928 mwin__unmap_window (MFrame *frame, MDrawWindow win)
930 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
934 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
935 MDrawMetric *geometry)
937 Display *display = FRAME_DISPLAY (frame);
938 XWindowAttributes attr;
939 Window parent = (Window) parent_win, root;
941 XGetWindowAttributes (display, (Window) win, &attr);
942 geometry->x = attr.x + attr.border_width;
943 geometry->y = attr.y + attr.border_width;
944 geometry->width = attr.width;
945 geometry->height = attr.height;
948 parent = RootWindow (display, FRAME_SCREEN (frame));
951 Window this_parent, *children;
954 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
957 if (this_parent == parent || this_parent == root)
959 win = (MDrawWindow) this_parent;
960 XGetWindowAttributes (display, (Window) win, &attr);
961 geometry->x += attr.x + attr.border_width;
962 geometry->y += attr.y + attr.border_width;
967 mwin__adjust_window (MFrame *frame, MDrawWindow win,
968 MDrawMetric *current, MDrawMetric *new)
970 Display *display = FRAME_DISPLAY (frame);
971 unsigned int mask = 0;
972 XWindowChanges values;
974 if (current->width != new->width)
979 values.width = current->width = new->width;
981 if (current->height != new->height)
984 if (new->height <= 0)
986 values.height = current->height = new->height;
988 if (current->x != new->x)
991 values.x = current->x = new->x;
993 if (current->y != new->y)
997 values.y = current->y = new->y;
1000 XConfigureWindow (display, (Window) win, mask, &values);
1001 XClearWindow (display, (Window) win);
1005 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1007 XEvent *event = (XEvent *) arg;
1008 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1015 if (event->xany.type != KeyPress
1016 /* && event->xany.type != KeyRelease */
1019 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1026 if (c < XK_space || c > XK_asciitilde)
1028 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1029 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1030 if (((XKeyEvent *) event)->state & ControlMask)
1032 if (c >= 'a' && c <= 'z')
1034 if (c >= ' ' && c < 127)
1035 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1037 key = minput__char_to_key (c);
1039 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1043 char *str = XKeysymToString (keysym);
1047 key = msymbol (str);
1048 if (((XKeyEvent *) event)->state & ShiftMask)
1049 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1050 if (((XKeyEvent *) event)->state & ControlMask)
1051 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1053 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1054 *modifiers |= MINPUT_KEY_META_MODIFIER;
1055 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1056 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1057 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1058 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1059 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1060 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1067 mwin__get_selection_text (MFrame *frame)
1074 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1076 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1078 Display *display = FRAME_DISPLAY (frame);
1079 GCInfo *info = rface->info;
1082 for (i = 0; i <= GC_INVERSE; i++)
1084 XGetGCValues (display, info->gc[i], valuemask, &values);
1085 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1086 values.foreground, values.background);
1087 fprintf (stderr, "\n");
1091 static MDeviceDriver x_driver =
1094 mwin__device_get_prop,
1096 mwin__free_realized_face,
1098 mwin__draw_empty_boxes,
1102 mwin__region_from_rect,
1103 mwin__union_rect_with_region,
1104 mwin__intersect_region,
1105 mwin__region_add_rect,
1106 mwin__region_to_rect,
1109 mwin__create_window,
1110 mwin__destroy_window,
1113 mwin__window_geometry,
1114 mwin__adjust_window,
1119 /** X font handler */
1121 static MRealizedFont *xfont_select (MFrame *, MFont *, MFont *, int);
1122 static int xfont_open (MRealizedFont *);
1123 static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int);
1124 static unsigned xfont_encode_char (MRealizedFont *, int, unsigned);
1125 static void xfont_render (MDrawWindow, int, int, MGlyphString *,
1126 MGlyph *, MGlyph *, int, MDrawRegion);
1128 static MFontDriver xfont_driver =
1129 { xfont_select, xfont_open,
1130 xfont_find_metric, xfont_encode_char, xfont_render };
1140 build_font_list (MFrame *frame, MSymbol family, MSymbol registry,
1144 MFontList *font_list;
1149 MSTRUCT_CALLOC (font_list, MERROR_WIN);
1153 sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s",
1154 msymbol_name (registry));
1155 font_list->tag = registry;
1159 sprintf (pattern, "-*-%s-*-*-*-*-*-*-*-*-*-*-%s",
1160 msymbol_name (family), msymbol_name (registry));
1161 font_list->tag = family;
1164 fontnames = XListFonts (FRAME_DISPLAY (frame), pattern, 0x8000, &nfonts);
1167 MTABLE_MALLOC (font_list->fonts, nfonts, MERROR_WIN);
1168 for (i = j = 0; i < nfonts; i++)
1169 if ((mfont__parse_name_into_font (fontnames[i], Mx,
1170 font_list->fonts + j)
1172 && (font_list->fonts[j].property[MFONT_SIZE] != 0
1173 || font_list->fonts[j].property[MFONT_RESY] == 0))
1175 XFreeFontNames (fontnames);
1176 font_list->nfonts = j;
1178 mplist_add (plist, font_list->tag, font_list);
1179 return (nfonts > 0 ? font_list : NULL);
1182 /* The X font driver function SELECT. */
1184 static MRealizedFont *
1185 xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
1187 MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
1188 MRealizedFont *rfont;
1189 MFontList *font_list = NULL;
1192 int best_score, score;
1194 if (registry == Mnil
1195 || ! strchr (MSYMBOL_NAME (registry), '-'))
1198 /* We handles iso8859-1 and iso10646-1 fonts specially because there
1199 exists so many such fonts. */
1200 if (registry == M_iso8859_1 || registry == M_iso10646_1)
1203 = (registry == M_iso8859_1
1204 ? FRAME_DEVICE (frame)->display_info->iso8859_1_family_list
1205 : FRAME_DEVICE (frame)->display_info->iso10646_1_family_list);
1206 MSymbol family = FONT_PROPERTY (spec, MFONT_FAMILY);
1210 font_list = (MFontList *) mplist_get (family_list, family);
1212 font_list = build_font_list (frame, family, registry, family_list);
1216 family = FONT_PROPERTY (request, MFONT_FAMILY);
1217 font_list = (MFontList *) mplist_get (family_list, family);
1219 font_list = build_font_list (frame, family, registry, family_list);
1224 MPlist *registry_list
1225 = FRAME_DEVICE (frame)->display_info->font_registry_list;
1227 font_list = (MFontList *) mplist_get (registry_list, registry);
1229 font_list = build_font_list (frame, Mnil, registry, registry_list);
1234 for (i = 0, best_score = -1, best_font = NULL; i < font_list->nfonts; i++)
1235 if ((best_score = mfont__score (font_list->fonts + i, spec, request,
1236 limited_size)) >= 0)
1240 best_font = font_list->fonts + i;
1241 for (; best_score > 0 && i < font_list->nfonts ; i++)
1243 score = mfont__score (font_list->fonts + i, spec, request,
1245 if (score >= 0 && score < best_score)
1247 best_font = font_list->fonts + i;
1252 MSTRUCT_CALLOC (rfont, MERROR_WIN);
1253 rfont->frame = frame;
1254 rfont->spec = *spec;
1255 rfont->request = *request;
1256 rfont->font = *best_font;
1257 if (best_font->property[MFONT_SIZE] == 0)
1258 rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE];
1259 rfont->score = best_score;
1264 /* The X font driver function CLOSE. */
1267 close_xfont (void *object)
1269 MXFontInfo *xfont_info = object;
1271 XFreeFont (xfont_info->display, xfont_info->xfont);
1276 /* The X font driver function OPEN. */
1279 xfont_open (MRealizedFont *rfont)
1282 MXFontInfo *xfont_info;
1283 MFrame *frame = rfont->frame;
1284 int mdebug_mask = MDEBUG_FONT;
1286 /* This never fail to generate a valid fontname because open_spec
1287 should correspond to a font available on the system. */
1288 name = mfont_unparse_name (&rfont->font, Mx);
1289 M17N_OBJECT (xfont_info, close_xfont, MERROR_WIN);
1290 xfont_info->display = FRAME_DISPLAY (frame);
1291 xfont_info->xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
1292 if (! xfont_info->xfont)
1296 MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
1300 rfont->info = xfont_info;
1301 MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
1304 rfont->ascent = xfont_info->xfont->ascent;
1305 rfont->descent = xfont_info->xfont->descent;
1310 /* The X font driver function FIND_METRIC. */
1313 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1316 MXFontInfo *xfont_info = rfont->info;
1317 XFontStruct *xfont = xfont_info->xfont;
1318 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1320 for (; g != gend; g++)
1322 if (g->code == MCHAR_INVALID_CODE)
1324 g->lbearing = xfont->max_bounds.lbearing;
1325 g->rbearing = xfont->max_bounds.rbearing;
1326 g->width = xfont->max_bounds.width;
1327 g->ascent = xfont->ascent;
1328 g->descent = xfont->descent;
1332 int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
1333 XCharStruct *pcm = NULL;
1335 if (xfont->per_char != NULL)
1337 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
1340 && byte2 >= xfont->min_char_or_byte2
1341 && byte2 <= xfont->max_char_or_byte2)
1342 pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
1346 if (byte1 >= xfont->min_byte1
1347 && byte1 <= xfont->max_byte1
1348 && byte2 >= xfont->min_char_or_byte2
1349 && byte2 <= xfont->max_char_or_byte2)
1351 pcm = (xfont->per_char
1352 + ((xfont->max_char_or_byte2
1353 - xfont->min_char_or_byte2 + 1)
1354 * (byte1 - xfont->min_byte1))
1355 + (byte2 - xfont->min_char_or_byte2));
1362 g->lbearing = pcm->lbearing;
1363 g->rbearing = pcm->rbearing;
1364 g->width = pcm->width;
1365 g->ascent = pcm->ascent;
1366 g->descent = pcm->descent;
1370 /* If the per_char pointer is null, all glyphs between
1371 the first and last character indexes inclusive have
1372 the same information, as given by both min_bounds and
1375 g->rbearing = xfont->max_bounds.width;
1376 g->width = xfont->max_bounds.width;
1377 g->ascent = xfont->ascent;
1378 g->descent = xfont->descent;
1385 /* The X font driver function ENCODE_CHAR. */
1388 xfont_encode_char (MRealizedFont *rfont, int c, unsigned code)
1390 MXFontInfo *xfont_info;
1392 unsigned min_byte1, max_byte1, min_byte2, max_byte2;
1393 int all_chars_exist;
1395 if (rfont->status < 0 || code >= 0x10000)
1396 return MCHAR_INVALID_CODE;
1397 if (rfont->status == 0)
1399 if (xfont_open (rfont) < 0)
1400 return MCHAR_INVALID_CODE;
1402 xfont_info = rfont->info;
1403 xfont = xfont_info->xfont;
1404 all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
1405 min_byte1 = xfont->min_byte1;
1406 max_byte1 = xfont->max_byte1;
1407 min_byte2 = xfont->min_char_or_byte2;
1408 max_byte2 = xfont->max_char_or_byte2;
1410 if (min_byte1 == 0 && max_byte1 == 0)
1414 if (code < min_byte2 || code > max_byte2)
1415 return MCHAR_INVALID_CODE;
1416 if (all_chars_exist)
1418 pcm = xfont->per_char + (code - min_byte2);
1419 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
1420 ? code : MCHAR_INVALID_CODE);
1424 unsigned byte1 = code >> 8, byte2 = code & 0xFF;
1427 if (byte1 < min_byte1 || byte1 > max_byte1
1428 || byte2 < min_byte2 || byte2 > max_byte2)
1429 return MCHAR_INVALID_CODE;
1431 if (all_chars_exist)
1433 pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
1434 + (byte2 - min_byte2));
1435 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
1436 ? code : MCHAR_INVALID_CODE);
1440 /* The X font driver function RENDER. */
1443 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
1444 MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
1446 MRealizedFace *rface = from->rface;
1447 MXFontInfo *xfont_info = rface->rfont->info;
1450 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1457 /* It is assured that the all glyphs in the current range use the
1458 same realized face. */
1459 display = FRAME_DISPLAY (rface->frame);
1462 gc = set_region (rface->frame, gc, region);
1463 XSetFont (display, gc, xfont_info->xfont->fid);
1464 code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
1465 for (i = 0, g = from; g < to; i++, g++)
1467 code[i].byte1 = g->code >> 8;
1468 code[i].byte2 = g->code & 0xFF;
1474 if (g->type == GLYPH_PAD)
1476 else if (g->type == GLYPH_SPACE)
1477 for (; g < to && g->type == GLYPH_SPACE; g++)
1479 else if (! g->rface->rfont)
1481 if ((g->c >= 0x200B && g->c <= 0x200F)
1482 || (g->c >= 0x202A && g->c <= 0x202E))
1486 /* As a font is not found for this character, draw an
1488 int box_width = g->width;
1489 int box_height = gstring->ascent + gstring->descent;
1495 XDrawRectangle (display, (Window) win, gc,
1496 x, y - gstring->ascent, box_width, box_height);
1500 else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
1502 XDrawString16 (display, (Window) win, gc,
1503 x + g->xoff, y + g->yoff, code + (g - from), 1);
1510 int code_idx = g - from;
1513 g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
1516 XDrawString16 (display, (Window) win, gc, orig_x, y,
1517 code + code_idx, i);
1532 XftFont *font_no_aa;
1535 static int xft_open (MRealizedFont *);
1536 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
1537 static void xft_render (MDrawWindow, int, int, MGlyphString *,
1538 MGlyph *, MGlyph *, int, MDrawRegion);
1540 MFontDriver xft_driver =
1541 { NULL, /* Set to ft_select in mwin__init (). */
1542 xft_open, xft_find_metric,
1543 NULL, /* Set to ft_encode_char in mwin__init (). */
1548 close_xft (void *object)
1550 MXftFontInfo *font_info = object;
1552 XftFontClose (font_info->display, font_info->font_aa);
1553 XftFontClose (font_info->display, font_info->font_no_aa);
1559 xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
1561 XftPattern *pattern;
1562 XftFontInfo *xft_font_info;
1565 pattern = XftPatternCreate ();
1566 XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
1567 XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
1568 XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
1569 xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
1570 if (! xft_font_info)
1572 font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
1573 XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
1579 xft_open (MRealizedFont *rfont)
1583 MXftFontInfo *font_info;
1586 if ((mfont__ft_driver.open) (rfont) < 0)
1589 size = rfont->font.property[MFONT_SIZE] / 10;
1590 frame = rfont->frame;
1592 ft_info = rfont->info;
1593 M17N_OBJECT (font_info, close_xft, MERROR_WIN);
1594 ft_info->extra_info = font_info;
1595 font_info->display = FRAME_DISPLAY (frame);
1596 font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
1597 if (font_info->font_aa)
1599 font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
1600 if (font_info->font_no_aa)
1602 XftFontClose (FRAME_DISPLAY (rfont->frame), font_info->font_aa);
1605 ft_info->extra_info = NULL;
1612 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1615 MFTInfo *ft_info = rfont->info;
1616 MXftFontInfo *font_info = ft_info->extra_info;
1617 FT_Face ft_face = ft_info->ft_face;
1618 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1620 for (; g != gend; g++)
1622 if (g->code == MCHAR_INVALID_CODE)
1624 MGlyph *start = g++;
1626 while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
1627 (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
1639 code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
1641 XftGlyphExtents (FRAME_DISPLAY (rfont->frame),
1642 font_info->font_aa, &code, 1, &extents);
1643 g->lbearing = - extents.x;
1644 g->rbearing = extents.width - extents.x;
1645 g->width = extents.xOff;
1646 g->ascent = extents.y;
1647 g->descent = extents.height - extents.y;
1654 xft_render (MDrawWindow win, int x, int y,
1655 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1656 int reverse, MDrawRegion region)
1658 MRealizedFace *rface = from->rface;
1659 MFrame *frame = rface->frame;
1660 MFTInfo *ft_info = rface->rfont->info;
1661 MXftFontInfo *font_info = ft_info->extra_info;
1662 FT_Face ft_face = ft_info->ft_face;
1663 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1664 XftColor *xft_color = (! reverse
1665 ? &((GCInfo *) rface->info)->xft_color_fore
1666 : &((GCInfo *) rface->info)->xft_color_back);
1667 XftFont *xft_font = (gstring->control.anti_alias
1668 && FRAME_DEVICE (frame)->depth > 1
1669 ? font_info->font_aa : font_info->font_no_aa);
1678 XftDrawChange (xft_draw, (Drawable) win);
1679 XftDrawSetClip (xft_draw, (Region) region);
1681 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1682 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1689 code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
1690 if (g->xoff == 0 && g->yoff == 0)
1691 glyphs[nglyphs++] = code;
1695 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1696 last_x, y, glyphs, nglyphs);
1698 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1699 x + g->xoff, y + g->yoff, (FT_UInt *) &code, 1);
1700 last_x = x + g->width;
1704 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1711 /* XIM (X Input Method) handler */
1713 typedef struct MInputXIMMethodInfo
1719 } MInputXIMMethodInfo;
1721 typedef struct MInputXIMContextInfo
1725 MConverter *converter;
1726 } MInputXIMContextInfo;
1729 xim_open_im (MInputMethod *im)
1731 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
1732 MLocale *saved, *this;
1733 char *save_modifier_list;
1735 MInputXIMMethodInfo *im_info;
1737 saved = mlocale_set (LC_CTYPE, NULL);
1738 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
1740 /* The specified locale is not supported. */
1741 MERROR (MERROR_LOCALE, -1);
1742 if (mlocale_get_prop (this, Mcoding) == Mnil)
1744 /* Unable to decode the output of XIM. */
1745 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
1746 MERROR (MERROR_LOCALE, -1);
1749 if (arg->modifier_list)
1750 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
1752 save_modifier_list = XSetLocaleModifiers ("");
1753 if (! save_modifier_list)
1755 /* The specified locale is not supported by X. */
1756 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
1757 MERROR (MERROR_LOCALE, -1);
1760 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
1763 /* No input method is available in the current locale. */
1764 XSetLocaleModifiers (save_modifier_list);
1765 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
1766 MERROR (MERROR_WIN, -1);
1769 MSTRUCT_MALLOC (im_info, MERROR_WIN);
1770 im_info->display = arg->display;
1772 im_info->language = mlocale_get_prop (this, Mlanguage);
1773 im_info->coding = mlocale_get_prop (this, Mcoding);
1776 XSetLocaleModifiers (save_modifier_list);
1777 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
1783 xim_close_im (MInputMethod *im)
1785 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
1787 XCloseIM (im_info->xim);
1792 xim_create_ic (MInputContext *ic)
1794 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
1795 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
1796 MInputXIMContextInfo *ic_info;
1799 if (! arg->input_style)
1801 /* By default, use Root style. */
1802 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
1803 arg->preedit_attrs = NULL;
1804 arg->status_attrs = NULL;
1807 if (! arg->preedit_attrs && ! arg->status_attrs)
1808 xic = XCreateIC (im_info->xim,
1809 XNInputStyle, arg->input_style,
1810 XNClientWindow, arg->client_win,
1811 XNFocusWindow, arg->focus_win,
1813 else if (arg->preedit_attrs && ! arg->status_attrs)
1814 xic = XCreateIC (im_info->xim,
1815 XNInputStyle, arg->input_style,
1816 XNClientWindow, arg->client_win,
1817 XNFocusWindow, arg->focus_win,
1818 XNPreeditAttributes, arg->preedit_attrs,
1820 else if (! arg->preedit_attrs && arg->status_attrs)
1821 xic = XCreateIC (im_info->xim,
1822 XNInputStyle, arg->input_style,
1823 XNClientWindow, arg->client_win,
1824 XNFocusWindow, arg->focus_win,
1825 XNStatusAttributes, arg->status_attrs,
1828 xic = XCreateIC (im_info->xim,
1829 XNInputStyle, arg->input_style,
1830 XNClientWindow, arg->client_win,
1831 XNFocusWindow, arg->focus_win,
1832 XNPreeditAttributes, arg->preedit_attrs,
1833 XNStatusAttributes, arg->status_attrs,
1836 MERROR (MERROR_WIN, -1);
1838 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
1840 ic_info->win = arg->focus_win;
1841 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
1847 xim_destroy_ic (MInputContext *ic)
1849 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
1851 XDestroyIC (ic_info->xic);
1852 mconv_free_converter (ic_info->converter);
1858 xim_filter (MInputContext *ic, MSymbol key, void *event)
1860 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
1862 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
1867 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
1869 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
1870 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
1871 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
1877 buf = (char *) alloca (512);
1878 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
1879 if (status == XBufferOverflow)
1881 buf = (char *) alloca (len);
1882 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
1885 mtext_reset (ic->produced);
1889 mconv_reset_converter (ic_info->converter);
1890 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
1891 mconv_decode (ic_info->converter, ic->produced);
1892 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
1893 Mlanguage, (void *) im_info->language);
1894 mtext_cpy (mt, ic->produced);
1895 mtext_reset (ic->produced);
1901 #ifdef X_SET_ERROR_HANDLER
1903 x_error_handler (Display *display, XErrorEvent *error)
1910 x_io_error_handler (Display *display)
1919 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1924 M_iso8859_1 = msymbol ("iso8859-1");
1925 M_iso10646_1 = msymbol ("iso10646-1");
1927 display_info_list = mplist ();
1928 device_list = mplist ();
1931 xft_driver.select = mfont__ft_driver.select;
1932 xft_driver.encode_char = mfont__ft_driver.encode_char;
1935 Mxim = msymbol ("xim");
1936 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1944 M17N_OBJECT_UNREF (display_info_list);
1945 M17N_OBJECT_UNREF (device_list);
1949 /** Return an MWDevice object corresponding to a display specified in
1952 It searches device_list for a device matching the display. If
1953 found, return the found object. Otherwise, return a newly created
1957 device_open (MFrame *frame, MPlist *param)
1959 Display *display = NULL;
1960 Screen *screen = NULL;
1962 Drawable drawable = 0;
1963 Widget widget = NULL;
1965 int auto_display = 0;
1966 MDisplayInfo *disp_info = NULL;
1967 MWDevice *device = NULL;
1969 XWindowAttributes attr;
1975 for (plist = param; (key = mplist_key (plist)) != Mnil;
1976 plist = mplist_next (plist))
1978 if (key == Mdisplay)
1979 display = (Display *) mplist_value (plist);
1980 else if (key == Mscreen)
1981 screen = mplist_value (plist);
1982 else if (key == Mdrawable)
1983 drawable = (Drawable) mplist_value (plist);
1984 else if (key == Mdepth)
1985 depth = (unsigned) mplist_value (plist);
1986 else if (key == Mwidget)
1987 widget = (Widget) mplist_value (plist);
1988 else if (key == Mcolormap)
1989 cmap = (Colormap) mplist_value (plist);
1994 display = XtDisplay (widget);
1995 screen_num = XScreenNumberOfScreen (XtScreen (widget));
1996 depth = DefaultDepth (display, screen_num);
2002 unsigned width, height, border_width;
2005 MERROR (MERROR_WIN, NULL);
2006 XGetGeometry (display, drawable, &root_window,
2007 &x, &y, &width, &height, &border_width, &depth);
2008 XGetWindowAttributes (display, root_window, &attr);
2009 screen_num = XScreenNumberOfScreen (attr.screen);
2014 display = DisplayOfScreen (screen);
2019 display = XOpenDisplay (NULL);
2021 MERROR (MERROR_WIN, NULL);
2024 screen = DefaultScreenOfDisplay (display);
2026 screen_num = XScreenNumberOfScreen (screen);
2028 depth = DefaultDepth (display, screen_num);
2032 cmap = DefaultColormap (display, screen_num);
2034 for (plist = display_info_list; mplist_key (plist) != Mnil;
2035 plist = mplist_next (plist))
2037 disp_info = (MDisplayInfo *) mplist_value (plist);
2038 if (disp_info->display == display)
2042 if (mplist_key (plist) != Mnil)
2043 M17N_OBJECT_REF (disp_info);
2046 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
2047 disp_info->display = display;
2048 disp_info->auto_display = auto_display;
2049 disp_info->font_registry_list = mplist ();
2050 disp_info->iso8859_1_family_list = mplist ();
2051 disp_info->iso10646_1_family_list = mplist ();
2052 disp_info->realized_font_list = mplist ();
2053 find_modifier_bits (disp_info);
2054 mplist_add (display_info_list, Mt, disp_info);
2057 for (plist = device_list; mplist_key (plist) != Mnil;
2058 plist = mplist_next (plist))
2060 device = (MWDevice *) mplist_value (plist);
2061 if (device->display_info == disp_info
2062 && device->depth == depth
2063 && device->cmap == cmap)
2067 if (mplist_key (plist) != Mnil)
2068 M17N_OBJECT_REF (device);
2071 unsigned long valuemask = GCForeground;
2074 M17N_OBJECT (device, free_device, MERROR_WIN);
2075 device->display_info = disp_info;
2076 device->screen_num = screen_num;
2077 /* A drawable on which to create GCs. */
2078 device->drawable = XCreatePixmap (display,
2079 RootWindow (display, screen_num),
2081 device->depth = depth;
2082 device->cmap = cmap;
2083 device->realized_face_list = mplist ();
2084 device->realized_fontset_list = mplist ();
2085 device->gc_list = mplist ();
2086 values.foreground = BlackPixel (display, screen_num);
2087 device->scratch_gc = XCreateGC (display, device->drawable,
2088 valuemask, &values);
2090 device->xft_draw = XftDrawCreate (display, device->drawable,
2091 DefaultVisual (display, screen_num),
2096 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2097 frame->driver = &x_driver;
2098 frame->font_driver_list = mplist ();
2099 mplist_add (frame->font_driver_list, Mx, &xfont_driver);
2101 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2103 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2105 frame->realized_font_list = disp_info->realized_font_list;
2106 frame->realized_face_list = device->realized_face_list;
2107 frame->realized_fontset_list = device->realized_fontset_list;
2111 XtResource resources[] = {
2112 { XtNfont, XtCFont, XtRString, sizeof (String),
2113 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2114 { XtNforeground, XtCForeground, XtRString, sizeof (String),
2115 XtOffset (AppDataPtr, foreground), XtRString, "black" },
2116 { XtNbackground, XtCBackground, XtRString, sizeof (String),
2117 XtOffset (AppDataPtr, background), XtRString, "white" },
2118 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2119 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2122 XtGetApplicationResources (widget, &app_data,
2123 resources, XtNumber (resources), NULL, 0);
2124 frame->foreground = msymbol (app_data.foreground);
2125 frame->background = msymbol (app_data.background);
2126 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2130 app_data.font = DEFAULT_FONT;
2131 frame->foreground = msymbol ("black");
2132 frame->background = msymbol ("white");
2133 frame->videomode = Mnormal;
2138 char **names = XListFonts (display, app_data.font, 1, &nfonts);
2142 if (! (frame->font = mfont_parse_name (names[0], Mx)))
2144 /* The font name does not conform to XLFD. Try to open the
2145 font and get XA_FONT property. */
2146 XFontStruct *xfont = XLoadQueryFont (display, names[0]);
2151 unsigned long value;
2154 if (XGetFontProperty (xfont, XA_FONT, &value)
2155 && (name = ((char *)
2156 XGetAtomName (display, (Atom) value))))
2158 if (frame->font = mfont_parse_name (name, Mx))
2161 XFreeFont (display, xfont);
2164 XFreeFontNames (names);
2167 frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
2170 face = mface_from_font (frame->font);
2171 face->property[MFACE_FONTSET] = mfontset (NULL);
2172 face->property[MFACE_FOREGROUND] = frame->foreground;
2173 face->property[MFACE_BACKGROUND] = frame->background;
2174 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2175 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2176 face->property[MFACE_VIDEOMODE] = frame->videomode;
2177 mface_put_prop (face, Mhook_func,
2178 mface_get_prop (mface__default, Mhook_func));
2179 face->property[MFACE_RATIO] = (void *) 100;
2180 mplist_push (param, Mface, face);
2181 M17N_OBJECT_UNREF (face);
2183 #ifdef X_SET_ERROR_HANDLER
2184 XSetErrorHandler (x_error_handler);
2185 XSetIOErrorHandler (x_io_error_handler);
2192 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2197 /*** @addtogroup m17nInputMethodWin */
2202 @brief Input method driver for XIM.
2204 The driver #minput_xim_driver is for the foreign input method of
2205 name #Mxim. It uses XIM (X Input Methods) as a background input
2208 As the symbol #Mxim has property #Minput_driver whose value is
2209 a pointer to this driver, the input method of language #Mnil
2210 and name #Mxim uses this driver.
2212 Therefore, for such input methods, the driver dependent arguments
2213 to the functions whose name begin with minput_ must be as follows.
2215 The argument $ARG of the function minput_open_im () must be a
2216 pointer to the structure #MInputXIMArgIM. See the documentation
2217 of #MInputXIMArgIM for more details.
2219 The argument $ARG of the function minput_create_ic () must be a
2220 pointer to the structure #MInputXIMArgIC. See the documentation
2221 of #MInputXIMArgIC for more details.
2223 The argument $ARG of the function minput_filter () must be a
2224 pointer to the structure @c XEvent. The argument $KEY is ignored.
2226 The argument $ARG of the function minput_lookup () must be the
2227 same one as that of the function minput_filter (). The argument
2231 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2233 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
2234 ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
2237 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2238 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
2239 ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2241 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
2242 ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2244 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM ¤Ø¤Î¥Ý
2245 ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
2248 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC ¤Ø¤Î
2249 ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
2252 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2253 ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2255 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2256 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2259 MInputDriver minput_xim_driver =
2260 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2261 xim_filter, xim_lookup, NULL };