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 #include <fontconfig/fcfreetype.h>
47 #endif /* HAVE_XFT2 */
51 #include "m17n-misc.h"
53 #include "internal-gui.h"
60 typedef struct _MFontX MFontX;
64 /* Record a font of the smallest pixel size. */
66 /* Nth bit tells the existence of a font of size N + 5. So this is
67 for 5..36 pixel size fonts. Usually this covers all sizes. */
68 unsigned int size5_36;
69 /* Fonts of (size < 5 || size > 36) are listed here (except for a
70 scalable whose size is 0). */
74 /* S must satisfy the condition (S >= 5 && S < 36). */
76 #define SET_SIZE(FONTX, S) ((FONTX)->size5_36 |= (1 << ((S) - 5)))
78 #define HAVE_SIZE(FONTX, S) ((FONTX)->size5_36 & (1 << ((S) - 5)))
82 /* Common header for the m17n object. */
87 /* If nonzero, <display> is opened by this library. Thus it should
88 be closed on freeing this structure. */
91 /** List of available X-core fonts on the display. Keys are
92 registries and values are plists whose keys are families and
93 values are pointers to MFontX. */
96 /** Nonzero means that <font_list> already contains all available
97 fonts on the display. */
100 /** Modifier bit masks of the display. */
107 /* Anchor of the chain of MDisplayInfo objects. */
108 static MPlist *display_info_list;
111 /* Color value and the corresponding GC. */
114 unsigned int rgb; /* (red << 16) | (green << 8) | blue */
121 GC_NORMAL = GC_INVERSE + 7,
134 /* The first 8 elements are indexed by an intensity for
135 anti-aliasing. The 2nd to 7th are created on demand. */
138 XftColor xft_color_fore, xft_color_back;
144 /* Common header for the m17n object. */
147 MDisplayInfo *display_info;
165 /** List of pointers to realized faces on the frame. */
166 MPlist *realized_face_list;
168 /* List of single element whose value is a root of chain of realized
170 MPlist *realized_font_list;
172 /** List of pointers to realized fontsets on the frame. */
173 MPlist *realized_fontset_list;
175 /** List of XColors vs GCs on the frame. */
179 static MPlist *device_list;
181 static MSymbol M_iso8859_1, M_iso10646_1;
183 #define FRAME_DEVICE(frame) ((MWDevice *) (frame)->device)
184 #define FRAME_DISPLAY(frame) (FRAME_DEVICE (frame)->display_info->display)
185 #define FRAME_SCREEN(frame) (FRAME_DEVICE (frame)->screen_num)
186 #define FRAME_CMAP(frame) (FRAME_DEVICE (frame)->cmap)
187 #define FRAME_VISUAL(frame) DefaultVisual (FRAME_DISPLAY (frame), \
188 FRAME_SCREEN (frame))
190 #define DEFAULT_FONT "-*-*-medium-r-normal--13-*-*-*-c-*-iso8859-1"
197 Boolean reverse_video;
198 } AppData, *AppDataPtr;
201 free_display_info (void *object)
203 MDisplayInfo *disp_info = (MDisplayInfo *) object;
206 MPLIST_DO (plist, disp_info->font_list)
208 MPLIST_DO (pl, MPLIST_VAL (plist))
210 MFontX *fontx, *next;
212 for (fontx = MPLIST_VAL (pl); fontx; fontx = next)
218 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
220 M17N_OBJECT_UNREF (disp_info->font_list);
222 if (disp_info->auto_display)
223 XCloseDisplay (disp_info->display);
229 free_device (void *object)
231 MWDevice *device = object;
234 for (plist = device->realized_fontset_list;
235 mplist_key (plist) != Mnil; plist = mplist_next (plist))
236 mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist));
237 M17N_OBJECT_UNREF (device->realized_fontset_list);
239 if (MPLIST_VAL (device->realized_font_list))
240 mfont__free_realized (MPLIST_VAL (device->realized_font_list));
241 M17N_OBJECT_UNREF (device->realized_font_list);
243 MPLIST_DO (plist, device->realized_face_list)
245 MRealizedFace *rface = MPLIST_VAL (plist);
248 mface__free_realized (rface);
250 M17N_OBJECT_UNREF (device->realized_face_list);
252 MPLIST_DO (plist, device->gc_list)
254 XFreeGC (device->display_info->display,
255 ((RGB_GC *) MPLIST_VAL (plist))->gc);
256 free (MPLIST_VAL (plist));
258 M17N_OBJECT_UNREF (device->gc_list);
259 XFreeGC (device->display_info->display, device->scratch_gc);
262 XftDrawDestroy (device->xft_draw);
265 XFreePixmap (device->display_info->display, device->drawable);
266 M17N_OBJECT_UNREF (device->display_info);
272 find_modifier_bits (MDisplayInfo *disp_info)
274 Display *display = disp_info->display;
275 XModifierKeymap *mods;
276 KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L);
277 KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R);
278 KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L);
279 KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R);
280 KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
281 KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
282 KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
283 KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
286 mods = XGetModifierMapping (display);
287 /* We skip the first three sets for Shift, Lock, and Control. The
288 remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
289 for (i = 3; i < 8; i++)
290 for (j = 0; j < mods->max_keypermod; j++)
292 KeyCode code = mods->modifiermap[i * mods->max_keypermod + j];
296 if (code == meta_l || code == meta_r)
297 disp_info->meta_mask |= (1 << i);
298 else if (code == alt_l || code == alt_r)
299 disp_info->alt_mask |= (1 << i);
300 else if (code == super_l || code == super_r)
301 disp_info->super_mask |= (1 << i);
302 else if (code == hyper_l || code == hyper_r)
303 disp_info->hyper_mask |= (1 << i);
306 /* If meta keys are not in any modifier, use alt keys as meta
308 if (! disp_info->meta_mask)
310 disp_info->meta_mask = disp_info->alt_mask;
311 disp_info->alt_mask = 0;
313 /* If both meta and alt are assigned to the same modifier, give meta
315 if (disp_info->meta_mask & disp_info->alt_mask)
316 disp_info->alt_mask &= ~disp_info->meta_mask;
318 XFreeModifiermap (mods);
322 get_rgb_gc (MWDevice *device, XColor *xcolor)
324 int rgb = (((xcolor->red >> 8) << 16) | ((xcolor->green >> 8) << 8)
325 | (xcolor->blue >> 8));
328 unsigned long valuemask = GCForeground;
331 MPLIST_DO (plist, device->gc_list)
333 rgb_gc = MPLIST_VAL (plist);
335 if (rgb_gc->rgb == rgb)
337 if (rgb_gc->rgb > rgb)
341 if (! XAllocColor (device->display_info->display, device->cmap, xcolor))
344 rgb_gc = malloc (sizeof (RGB_GC));
346 values.foreground = xcolor->pixel;
347 rgb_gc->gc = XCreateGC (device->display_info->display,
348 device->drawable, valuemask, &values);
349 mplist_push (plist, Mt, rgb_gc);
354 get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret)
356 MWDevice *device = FRAME_DEVICE (frame);
364 color = for_foreground ? frame->foreground : frame->background;
366 if (! XParseColor (FRAME_DISPLAY (frame), device->cmap,
367 msymbol_name (color), &xcolor))
369 rgb_gc = get_rgb_gc (device, &xcolor);
373 *rgb_ret = rgb_gc->rgb;
378 GCInfo *info = frame->rface->info;
383 rgb = info->rgb_fore, gc = info->gc[GC_NORMAL];
385 rgb = info->rgb_back, gc = info->gc[GC_INVERSE];
393 get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity)
395 int rgb_fore, rgb_back;
400 if (info->gc[intensity])
401 return info->gc[intensity];
403 rgb_fore = info->rgb_fore, rgb_back = info->rgb_back;
404 xcolor.red = ((((rgb_fore & 0xFF0000) >> 16) * intensity
405 + ((rgb_back & 0xFF0000) >> 16) * (7 - intensity)) / 7) << 8;
406 xcolor.green = ((((rgb_fore & 0xFF00) >> 8) * intensity
407 + ((rgb_back & 0xFF00) >> 8) * (7 - intensity)) / 7) << 8;
408 xcolor.blue = (((rgb_fore & 0xFF) * intensity
409 + (rgb_back & 0xFF) * (7 - intensity)) / 7) << 8;
410 rgb_gc = get_rgb_gc (device, &xcolor);
414 gc =get_gc_for_anti_alias (device, info,
415 intensity < 4 ? intensity - 1 : intensity + 1);
416 return (info->gc[intensity] = gc);
420 set_region (MFrame *frame, GC gc, MDrawRegion region)
422 unsigned long valuemask = GCForeground;
424 XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
425 FRAME_DEVICE (frame)->scratch_gc);
426 XSetRegion (FRAME_DISPLAY (frame), FRAME_DEVICE (frame)->scratch_gc, region);
427 return FRAME_DEVICE (frame)->scratch_gc;
431 /** X font handler */
433 static MFont *xfont_select (MFrame *, MFont *, int);
434 static MRealizedFont *xfont_open (MFrame *, MFont *, MFont *, MRealizedFont *);
435 static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int);
436 static int xfont_has_char (MFrame *, MFont *, MFont *, int, unsigned);
437 static unsigned xfont_encode_char (MFrame *, MFont *, MFont *, unsigned);
438 static void xfont_render (MDrawWindow, int, int, MGlyphString *,
439 MGlyph *, MGlyph *, int, MDrawRegion);
440 static int xfont_list (MFrame *, MPlist *, MFont *, int);
443 static MFontDriver xfont_driver =
444 { xfont_select, xfont_open,
445 xfont_find_metric, xfont_has_char, xfont_encode_char,
446 xfont_render, xfont_list };
449 font_compare (const void *p1, const void *p2)
451 return strcmp (*(char **) p1, *(char **) p2);
455 xfont_registry_list (MFrame *frame, MSymbol registry)
457 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
458 MPlist *font_list = disp_info->font_list;
461 char **font_names, **names;
467 plist = mplist_get (font_list, registry);
471 mplist_add (font_list, registry, plist);
472 sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", msymbol_name (registry));
473 font_names = XListFonts (disp_info->display, pattern, 0x8000, &nfonts);
477 char *reg_name = msymbol_name (registry);
479 for_full_width = (strncmp (reg_name, "jis", 3) == 0
480 || strncmp (reg_name, "gb", 2) == 0
481 || strncmp (reg_name, "big5", 4) == 0
482 || strncmp (reg_name, "ksc", 3) == 0);
484 names = alloca (sizeof (char *) * nfonts);
485 memcpy (names, font_names, sizeof (char *) * nfonts);
486 qsort (names, nfonts, sizeof (char *), font_compare);
488 for (i = 0, p = NULL; i < nfonts; i++)
489 if (mfont__parse_name_into_font (names[i], Mx, &font) == 0
490 && (font.size >= 50 || font.property[MFONT_RESY] == 0))
492 MSymbol family = FONT_PROPERTY (&font, MFONT_FAMILY);
493 MFontX *fontx, *fontx2;
501 if (p && MPLIST_KEY (p) != family)
502 p = mplist_find_by_key (plist, family);
504 p = mplist_push (plist, family, NULL);
506 /* Calculate how many bytes to compare to detect fonts of the
508 for (base_end = names[i], fields = 0; *base_end; base_end++)
510 && ++fields == 7 /* PIXEL_SIZE */)
512 base_len = base_end - names[i] + 1;
514 size = smallest = font.size / 10;
515 sizes[nsizes++] = size;
516 for (j = i + 1; j < nfonts && ! strncmp (names[i], names[j], base_len);
518 if (mfont__parse_name_into_font (names[j], Mx, &font) == 0
519 && (font.size >= 50 || font.property[MFONT_RESY] == 0))
521 size = font.size / 10;
525 sizes[nsizes++] = size;
528 font.for_full_width = for_full_width;
529 font.type = MFONT_TYPE_OBJECT;
530 font.source = MFONT_SOURCE_X;
531 MSTRUCT_CALLOC (fontx, MERROR_WIN);
533 fontx->core.size = smallest * 10;
534 fontx->next = MPLIST_VAL (p);
535 MPLIST_VAL (p) = fontx;
537 for (j = 0; j < nsizes; j++)
541 if (sizes[j] != smallest)
542 SET_SIZE (fontx, sizes[j]);
546 MSTRUCT_CALLOC (fontx2, MERROR_WIN);
548 fontx2->core.size = sizes[j] * 10;
549 fontx2->next = MPLIST_VAL (p);
550 MPLIST_VAL (p) = fontx2;
554 XFreeFontNames (font_names);
559 xfont_list_all (MFrame *frame)
561 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
562 MPlist *font_encoding_list, *p;
564 if (disp_info->all_fonts_scaned)
566 disp_info->all_fonts_scaned = 1;
567 font_encoding_list = mfont__encoding_list ();
568 if (! font_encoding_list)
570 MPLIST_DO (p, font_encoding_list)
571 xfont_registry_list (frame, MPLIST_KEY (p));
581 /* The X font driver function SELECT. */
584 xfont_select (MFrame *frame, MFont *font, int limited_size)
586 MPlist *plist = mplist (), *pl;
587 int num = xfont_list (frame, plist, font, 0);
591 MPLIST_DO (pl, plist)
593 font = MPLIST_VAL (pl);
594 if (limited_size == 0
596 || font->size <= limited_size)
602 M17N_OBJECT_UNREF (plist);
606 /* The X font driver function CLOSE. */
609 close_xfont (void *object)
611 MRealizedFontX *x_rfont = object;
613 XFreeFont (x_rfont->display, x_rfont->xfont);
617 /* The X font driver function OPEN. */
619 static MRealizedFont *
620 xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
622 int size = spec->size;
623 MRealizedFontX *x_rfont;
625 Display *display = FRAME_DISPLAY (frame);
627 int mdebug_mask = MDEBUG_FONT;
632 for (; rfont; rfont = rfont->next)
633 if (rfont->font == font && rfont->spec.size == size)
639 /* This never fail to generate a valid fontname. */
640 name = mfont_unparse_name (&this, Mx);
641 xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
644 MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
646 font->type = MFONT_TYPE_FAILURE;
649 MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
651 M17N_OBJECT (x_rfont, close_xfont, MERROR_FONT_X);
652 x_rfont->display = display;
653 x_rfont->xfont = xfont;
654 MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
656 rfont->spec.type = MFONT_TYPE_REALIZED;
657 rfont->spec.source = MFONT_SOURCE_X;
658 rfont->frame = frame;
660 rfont->driver = &xfont_driver;
661 rfont->info = x_rfont;
662 rfont->ascent = xfont->ascent;
663 rfont->descent = xfont->descent;
664 rfont->max_advance = xfont->max_bounds.width;
665 rfont->fontp = xfont;
666 rfont->next = MPLIST_VAL (frame->realized_font_list);
667 MPLIST_VAL (frame->realized_font_list) = rfont;
672 /* The X font driver function FIND_METRIC. */
675 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
678 XFontStruct *xfont = rfont->fontp;
679 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
681 for (; g != gend; g++)
683 if (g->code == MCHAR_INVALID_CODE)
685 g->lbearing = xfont->max_bounds.lbearing;
686 g->rbearing = xfont->max_bounds.rbearing;
687 g->width = xfont->max_bounds.width;
688 g->ascent = xfont->ascent;
689 g->descent = xfont->descent;
693 int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
694 XCharStruct *pcm = NULL;
696 if (xfont->per_char != NULL)
698 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
701 && byte2 >= xfont->min_char_or_byte2
702 && byte2 <= xfont->max_char_or_byte2)
703 pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
707 if (byte1 >= xfont->min_byte1
708 && byte1 <= xfont->max_byte1
709 && byte2 >= xfont->min_char_or_byte2
710 && byte2 <= xfont->max_char_or_byte2)
712 pcm = (xfont->per_char
713 + ((xfont->max_char_or_byte2
714 - xfont->min_char_or_byte2 + 1)
715 * (byte1 - xfont->min_byte1))
716 + (byte2 - xfont->min_char_or_byte2));
723 g->lbearing = pcm->lbearing;
724 g->rbearing = pcm->rbearing;
725 g->width = pcm->width;
726 g->ascent = pcm->ascent;
727 g->descent = pcm->descent;
731 /* If the per_char pointer is null, all glyphs between
732 the first and last character indexes inclusive have
733 the same information, as given by both min_bounds and
736 g->rbearing = xfont->max_bounds.width;
737 g->width = xfont->max_bounds.width;
738 g->ascent = xfont->ascent;
739 g->descent = xfont->descent;
747 xfont_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
749 return (xfont_encode_char (frame, font, spec, code) != MCHAR_INVALID_CODE);
752 /* The X font driver function GET_GLYPH_ID. */
755 xfont_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
757 MRealizedFont *rfont;
759 unsigned min_byte1, max_byte1, min_byte2, max_byte2;
762 if (font->type == MFONT_TYPE_REALIZED)
763 rfont = (MRealizedFont *) font;
764 else if (font->type == MFONT_TYPE_OBJECT)
766 int size = spec->size;
768 for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
770 if (rfont->font == font && rfont->spec.size == size)
774 rfont = xfont_open (frame, font, spec, NULL);
776 return MCHAR_INVALID_CODE;
780 MFATAL (MERROR_FONT_X);
781 xfont = rfont->fontp;
782 all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
783 min_byte1 = xfont->min_byte1;
784 max_byte1 = xfont->max_byte1;
785 min_byte2 = xfont->min_char_or_byte2;
786 max_byte2 = xfont->max_char_or_byte2;
788 if (min_byte1 == 0 && max_byte1 == 0)
792 if (code < min_byte2 || code > max_byte2)
793 return MCHAR_INVALID_CODE;
796 pcm = xfont->per_char + (code - min_byte2);
797 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
798 ? code : MCHAR_INVALID_CODE);
802 unsigned byte1 = code >> 8, byte2 = code & 0xFF;
805 if (byte1 < min_byte1 || byte1 > max_byte1
806 || byte2 < min_byte2 || byte2 > max_byte2)
807 return MCHAR_INVALID_CODE;
811 pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
812 + (byte2 - min_byte2));
813 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
814 ? code : MCHAR_INVALID_CODE);
818 /* The X font driver function RENDER. */
821 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
822 MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
824 MRealizedFace *rface = from->rface;
825 Display *display = FRAME_DISPLAY (rface->frame);
827 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
835 gc = set_region (rface->frame, gc, region);
836 XSetFont (display, gc, ((XFontStruct *) rface->rfont->fontp)->fid);
837 code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
838 for (i = 0, g = from; g < to; i++, g++)
840 code[i].byte1 = g->code >> 8;
841 code[i].byte2 = g->code & 0xFF;
847 if (g->type == GLYPH_PAD)
849 else if (g->type == GLYPH_SPACE)
850 for (; g < to && g->type == GLYPH_SPACE; g++)
852 else if (! g->rface->rfont)
854 if ((g->c >= 0x200B && g->c <= 0x200F)
855 || (g->c >= 0x202A && g->c <= 0x202E))
859 /* As a font is not found for this character, draw an
861 int box_width = g->width;
862 int box_height = gstring->ascent + gstring->descent;
868 XDrawRectangle (display, (Window) win, gc,
869 x, y - gstring->ascent, box_width, box_height);
873 else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
875 XDrawString16 (display, (Window) win, gc,
876 x + g->xoff, y + g->yoff, code + (g - from), 1);
883 int code_idx = g - from;
886 g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
889 XDrawString16 (display, (Window) win, gc, orig_x, y,
896 xfont_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum)
898 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
899 MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil;
900 MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil;
901 int size = font ? font->size : 0;
904 int mdebug_mask = MDEBUG_FONT;
906 MDEBUG_PRINT2 (" [X-FONT] listing %s-%s...",
907 family ? msymbol_name (family) : "*",
908 registry ? msymbol_name (registry) : "*");
910 if (registry == Mnil)
911 xfont_list_all (frame);
913 xfont_registry_list (frame, registry);
915 MPLIST_DO (pl, disp_info->font_list)
917 if (registry != Mnil && registry != MPLIST_KEY (pl))
919 MPLIST_DO (p, MPLIST_VAL (pl))
923 if (family != Mnil && family != MPLIST_KEY (p))
925 for (fontx = MPLIST_VAL (p); fontx; fontx = fontx->next)
927 || (mfont__match_p (&fontx->core, font, MFONT_REGISTRY)))
929 if (fontx->core.size == size
930 || fontx->core.size == 0)
932 mplist_push (plist, MPLIST_KEY (p), fontx);
936 || (size <= 360 && HAVE_SIZE (fontx, (size / 10))))
938 unsigned size5_36 = fontx->size5_36;
943 for (i = fontx->core.size / 10; i <= 36; i++)
944 if (size5_36 & (1 << (i - 5)))
946 MSTRUCT_CALLOC (fontx2, MERROR_WIN);
947 fontx2->core = fontx->core;
948 fontx2->core.size = i * 10;
949 fontx2->next = fontx->next;
950 fontx->next = fontx2;
952 if ((size == 0 || size == fontx->core.size)
953 && (maxnum == 0 || num < maxnum))
955 mplist_push (plist, MPLIST_KEY (p), fontx);
960 if (maxnum > 0 && maxnum == num)
963 if (maxnum > 0 && maxnum == num)
966 if (maxnum > 0 && maxnum == num)
970 MDEBUG_PRINT1 (" %d found\n", num);
986 /* Pointer to MRealizedFontFT */
990 static MRealizedFont *xft_open (MFrame *frame, MFont *font, MFont *spec,
992 static int xft_has_char (MFrame *frame, MFont *font, MFont *spec,
993 int c, unsigned code);
994 static unsigned xft_encode_char (MFrame *frame, MFont *font, MFont *spec,
996 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
997 static void xft_render (MDrawWindow, int, int, MGlyphString *,
998 MGlyph *, MGlyph *, int, MDrawRegion);
1000 MFontDriver xft_driver =
1002 xft_find_metric, xft_has_char, xft_encode_char, xft_render, NULL };
1005 close_xft (void *object)
1007 MRealizedFontXft *rfont_xft = object;
1009 if (rfont_xft->font_aa)
1010 XftFontClose (rfont_xft->display, rfont_xft->font_aa);
1011 if (rfont_xft->font_no_aa)
1012 XftFontClose (rfont_xft->display, rfont_xft->font_no_aa);
1013 M17N_OBJECT_UNREF (rfont_xft->info);
1019 xft_open_font (Display *display, MSymbol file, double size,
1025 pattern = FcPatternCreate ();
1026 FcPatternAddString (pattern, FC_FILE, (FcChar8 *) msymbol_name (file));
1027 FcPatternAddDouble (pattern, FC_PIXEL_SIZE, size);
1028 FcPatternAddBool (pattern, FC_ANTIALIAS, anti_alias);
1029 font = XftFontOpenPattern (display, pattern);
1034 static MRealizedFont *
1035 xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
1037 Display *display = FRAME_DISPLAY (frame);
1038 int reg = spec->property[MFONT_REGISTRY];
1040 MRealizedFontXft *rfont_xft;
1041 FcBool anti_alias = FRAME_DEVICE (frame)->depth > 1 ? FcTrue : FcFalse;
1042 double size = font->size ? font->size : spec->size;
1047 MRealizedFont *save = NULL;
1049 for (; rfont; rfont = rfont->next)
1050 if (rfont->font == font
1051 && (rfont->font->size ? rfont->font->size == size
1052 : rfont->spec.size == size)
1053 && rfont->spec.property[MFONT_REGISTRY] == reg)
1057 if (rfont->driver == &xft_driver)
1062 rfont = (mfont__ft_driver.open) (frame, font, spec, rfont);
1065 spec = &rfont->spec;
1066 ft_face = rfont->fontp;
1067 xft_font = xft_open_font (display, font->file, size / 10, anti_alias);
1070 M17N_OBJECT (rfont_xft, close_xft, MERROR_WIN);
1071 rfont_xft->display = display;
1072 if (anti_alias == FcTrue)
1073 rfont_xft->font_aa = xft_font;
1075 rfont_xft->font_no_aa = xft_font;
1076 rfont_xft->ft_face = ft_face;
1077 rfont_xft->info = rfont->info;
1078 M17N_OBJECT_REF (rfont->info);
1079 MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
1080 rfont->spec = *spec;
1081 rfont->frame = frame;
1083 rfont->driver = &xft_driver;
1084 rfont->info = rfont_xft;
1085 rfont->ascent = ft_face->size->metrics.ascender >> 6;
1086 rfont->descent = - ft_face->size->metrics.descender >> 6;
1087 rfont->max_advance = ft_face->size->metrics.max_advance >> 6;
1088 rfont->fontp = xft_font;
1089 rfont->next = MPLIST_VAL (frame->realized_font_list);
1090 MPLIST_VAL (frame->realized_font_list) = rfont;
1095 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1098 Display *display = FRAME_DISPLAY (rfont->frame);
1099 XftFont *xft_font = rfont->fontp;
1100 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1102 for (; g != gend; g++)
1104 if (g->code == MCHAR_INVALID_CODE)
1107 g->rbearing = xft_font->max_advance_width;
1108 g->width = g->rbearing;
1109 g->ascent = xft_font->ascent;
1110 g->descent = xft_font->descent;
1116 XftGlyphExtents (display, xft_font, &g->code, 1, &extents);
1117 g->lbearing = - extents.x;
1118 g->rbearing = extents.width - extents.x;
1119 g->width = extents.xOff;
1120 g->ascent = extents.y;
1121 g->descent = extents.height - extents.y;
1127 xft_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
1131 if (font->type == MFONT_TYPE_REALIZED)
1133 MRealizedFont *rfont = (MRealizedFont *) font;
1134 MRealizedFontXft *rfont_xft = rfont->info;
1136 rfont->info = rfont_xft->info;
1137 result = mfont__ft_driver.has_char (frame, font, spec, c, code);
1138 rfont->info = rfont_xft;
1141 result = mfont__ft_driver.has_char (frame, font, spec, c, code);
1146 xft_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
1148 if (font->type == MFONT_TYPE_REALIZED)
1150 MRealizedFont *rfont = (MRealizedFont *) font;
1151 MRealizedFontXft *rfont_xft = rfont->info;
1153 rfont->info = rfont_xft->info;
1154 code = mfont__ft_driver.encode_char (frame, font, spec, code);
1155 rfont->info = rfont_xft;
1158 code = mfont__ft_driver.encode_char (frame, font, spec, code);
1163 xft_render (MDrawWindow win, int x, int y,
1164 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1165 int reverse, MDrawRegion region)
1167 MRealizedFace *rface = from->rface;
1168 MFrame *frame = rface->frame;
1169 Display *display = FRAME_DISPLAY (frame);
1170 MRealizedFont *rfont = rface->rfont;
1171 MRealizedFontXft *rfont_xft = rfont->info;
1172 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1173 XftColor *xft_color = (! reverse
1174 ? &((GCInfo *) rface->info)->xft_color_fore
1175 : &((GCInfo *) rface->info)->xft_color_back);
1176 int anti_alias = (gstring->control.anti_alias
1177 && FRAME_DEVICE (frame)->depth > 1);
1189 if (rfont_xft->font_aa)
1190 xft_font = rfont_xft->font_aa;
1193 double size = rfont->spec.size;
1195 xft_font = xft_open_font (display, rfont->spec.file, size / 10,
1198 rfont_xft->font_aa = xft_font;
1200 xft_font = rfont->fontp;
1205 if (rfont_xft->font_no_aa)
1206 xft_font = rfont_xft->font_no_aa;
1209 double size = rfont->spec.size;
1211 xft_font = xft_open_font (display, rfont->spec.file, size / 10,
1214 rfont_xft->font_no_aa = xft_font;
1216 xft_font = rfont->fontp;
1220 XftDrawChange (xft_draw, (Drawable) win);
1221 XftDrawSetClip (xft_draw, (Region) region);
1223 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1224 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1226 if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1227 glyphs[nglyphs++] = g->code;
1231 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1232 last_x, y, glyphs, nglyphs);
1234 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1235 x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1236 last_x = x + g->width;
1240 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1243 #endif /* HAVE_XFT2 */
1246 /* Functions for the device driver. */
1249 mwin__close_device (MFrame *frame)
1251 MWDevice *device = FRAME_DEVICE (frame);
1253 M17N_OBJECT_UNREF (device);
1257 mwin__device_get_prop (MFrame *frame, MSymbol key)
1259 MWDevice *device = FRAME_DEVICE (frame);
1261 if (key == Mdisplay)
1262 return (void *) device->display_info->display;
1264 return (void *) ScreenOfDisplay(device->display_info->display,
1265 device->screen_num);
1266 if (key == Mcolormap)
1267 return (void *) device->cmap;
1269 return (void *) device->depth;
1274 mwin__realize_face (MRealizedFace *rface)
1277 MSymbol foreground, background, videomode;
1278 MFaceHLineProp *hline;
1282 if (rface != rface->ascii_rface)
1284 rface->info = rface->ascii_rface->info;
1288 frame = rface->frame;
1289 MSTRUCT_CALLOC (info, MERROR_WIN);
1291 foreground = rface->face.property[MFACE_FOREGROUND];
1292 background = rface->face.property[MFACE_BACKGROUND];
1293 videomode = rface->face.property[MFACE_VIDEOMODE];
1295 videomode = frame->videomode;
1296 if (videomode != Mreverse)
1298 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1299 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1303 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1304 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1307 if (foreground == Mnil)
1308 foreground = frame->foreground;
1309 if (background == Mnil)
1310 background = frame->background;
1311 if (videomode == Mreverse)
1313 MSymbol temp = foreground;
1314 foreground = background;
1317 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1318 FRAME_VISUAL (frame),
1320 MSYMBOL_NAME (foreground),
1321 &info->xft_color_fore))
1323 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1324 FRAME_VISUAL (frame),
1326 MSYMBOL_NAME (background),
1327 &info->xft_color_back))
1329 #endif /* HAVE_XFT2 */
1331 hline = rface->hline;
1335 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1337 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1344 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1346 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1348 if (box->color_left && box->color_left != box->color_top)
1349 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1351 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1353 if (box->color_bottom && box->color_bottom != box->color_top)
1354 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1356 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1358 if (box->color_right && box->color_right != box->color_bottom)
1359 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1361 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1369 mwin__free_realized_face (MRealizedFace *rface)
1371 if (rface == rface->ascii_rface)
1377 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1379 int x, int y, int width, int height, MDrawRegion region)
1381 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1384 gc = set_region (frame, gc, region);
1386 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1387 x, y, width, height);
1392 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1393 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1394 int reverse, MDrawRegion region)
1396 MRealizedFace *rface = from->rface;
1397 Display *display = FRAME_DISPLAY (rface->frame);
1398 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1404 gc = set_region (rface->frame, gc, region);
1405 for (; from < to; from++)
1407 XDrawRectangle (display, (Window) win, gc,
1408 x, y - gstring->ascent + 1, from->width - 1,
1409 gstring->ascent + gstring->descent - 2);
1416 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1417 MRealizedFace *rface, int reverse,
1418 int x, int y, int width, MDrawRegion region)
1420 enum MFaceHLineType type = rface->hline->type;
1421 GCInfo *info = rface->info;
1422 GC gc = gc = info->gc[GC_HLINE];
1425 y = (type == MFACE_HLINE_BOTTOM
1426 ? y + gstring->text_descent - rface->hline->width
1427 : type == MFACE_HLINE_UNDER
1429 : type == MFACE_HLINE_STRIKE_THROUGH
1430 ? y - ((gstring->ascent + gstring->descent) / 2)
1431 : y - gstring->text_ascent);
1433 gc = set_region (frame, gc, region);
1435 for (i = 0; i < rface->hline->width; i++)
1436 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1437 x, y + i, x + width - 1, y + i);
1442 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1443 MGlyph *g, int x, int y, int width, MDrawRegion region)
1445 Display *display = FRAME_DISPLAY (frame);
1446 MRealizedFace *rface = g->rface;
1447 MFaceBoxProp *box = rface->box;
1448 GCInfo *info = rface->info;
1449 GC gc_top, gc_left, gc_right, gc_btm;
1453 y0 = y - (gstring->text_ascent
1454 + rface->box->inner_vmargin + rface->box->width);
1455 y1 = y + (gstring->text_descent
1456 + rface->box->inner_vmargin + rface->box->width - 1);
1458 gc_top = info->gc[GC_BOX_TOP];
1460 gc_top = set_region (frame, gc_top, region);
1461 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1464 gc_btm = info->gc[GC_BOX_BOTTOM];
1466 if (g->type == GLYPH_BOX)
1470 if (g->left_padding)
1471 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1473 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1475 /* Draw the top side. */
1476 for (i = 0; i < box->width; i++)
1477 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1479 /* Draw the bottom side. */
1480 if (region && gc_btm != gc_top)
1481 gc_btm = set_region (frame, gc_btm, region);
1482 for (i = 0; i < box->width; i++)
1483 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1485 if (g->left_padding > 0)
1487 /* Draw the left side. */
1488 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1492 gc_left = info->gc[GC_BOX_LEFT];
1494 gc_left = set_region (frame, gc_left, region);
1496 for (i = 0; i < rface->box->width; i++)
1497 XDrawLine (display, (Window) win, gc_left,
1498 x0 + i, y0 + i, x0 + i, y1 - i);
1502 /* Draw the right side. */
1503 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1507 gc_right = info->gc[GC_BOX_RIGHT];
1509 gc_right = set_region (frame, gc_right, region);
1511 for (i = 0; i < rface->box->width; i++)
1512 XDrawLine (display, (Window) win, gc_right,
1513 x1 - i, y0 + i, x1 - i, y1 - i);
1518 /* Draw the top side. */
1519 for (i = 0; i < box->width; i++)
1520 XDrawLine (display, (Window) win, gc_top,
1521 x, y0 + i, x + width - 1, y0 + i);
1523 /* Draw the bottom side. */
1524 if (region && gc_btm != gc_top)
1525 gc_btm = set_region (frame, gc_btm, region);
1526 for (i = 0; i < box->width; i++)
1527 XDrawLine (display, (Window) win, gc_btm,
1528 x, y1 - i, x + width - 1, y1 - i);
1535 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1536 int reverse, int x, int y,
1537 int width, int height, int row_bytes, unsigned char *bmp,
1540 Display *display = FRAME_DISPLAY (frame);
1542 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1545 gc = set_region (frame, gc, region);
1547 for (i = 0; i < height; i++, bmp += row_bytes)
1548 for (j = 0; j < width; j++)
1549 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1550 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1555 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1556 int intensity, MDrawPoint *points, int num,
1559 GCInfo *info = rface->info;
1562 if (! (gc = info->gc[intensity]))
1563 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1566 gc = set_region (frame, gc, region);
1568 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1569 (XPoint *) points, num, CoordModeOrigin);
1574 mwin__region_from_rect (MDrawMetric *rect)
1576 MDrawRegion region1 = XCreateRegion ();
1577 MDrawRegion region2 = XCreateRegion ();
1582 xrect.width = rect->width;
1583 xrect.height = rect->height;
1584 XUnionRectWithRegion (&xrect, region1, region2);
1585 XDestroyRegion (region1);
1590 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1592 MDrawRegion region1 = XCreateRegion ();
1597 xrect.width = rect->width;
1598 xrect.height = rect->height;
1600 XUnionRegion (region, region, region1);
1601 XUnionRectWithRegion (&xrect, region1, region);
1602 XDestroyRegion (region1);
1606 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1608 MDrawRegion region = XCreateRegion ();
1610 XUnionRegion (region1, region1, region);
1611 XIntersectRegion (region, region2, region1);
1612 XDestroyRegion (region);
1616 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1618 MDrawRegion region1 = XCreateRegion ();
1623 xrect.width = rect->width;
1624 xrect.height = rect->height;
1625 XUnionRectWithRegion (&xrect, region1, region);
1626 XDestroyRegion (region1);
1630 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1634 XClipBox (region, &xrect);
1637 rect->width = xrect.width;
1638 rect->height = xrect.height;
1642 mwin__free_region (MDrawRegion region)
1644 XDestroyRegion (region);
1648 mwin__dump_region (MDrawRegion region)
1651 XClipBox (region, &rect);
1652 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1657 mwin__create_window (MFrame *frame, MDrawWindow parent)
1659 Display *display = FRAME_DISPLAY (frame);
1661 XWMHints wm_hints = { InputHint, False };
1662 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1663 XSetWindowAttributes set_attrs;
1666 GCInfo *info = frame->rface->info;
1669 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1670 mask = GCForeground;
1671 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1672 set_attrs.background_pixel = values.foreground;
1673 set_attrs.backing_store = Always;
1674 set_attrs.override_redirect = True;
1675 set_attrs.save_under = True;
1676 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1677 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1678 CopyFromParent, InputOutput, CopyFromParent,
1680 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1681 NULL, &wm_hints, &class_hints);
1682 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1683 return (MDrawWindow) win;
1687 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1689 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1694 mwin__event_window (void *event)
1696 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1700 mwin__print_event (void *arg, char *win_name)
1703 XEvent *event = (XEvent *) arg;
1705 switch (event->xany.type)
1707 case 2: event_name = "KeyPress"; break;
1708 case 3: event_name = "KeyRelease"; break;
1709 case 4: event_name = "ButtonPress"; break;
1710 case 5: event_name = "ButtonRelease"; break;
1711 case 6: event_name = "MotionNotify"; break;
1712 case 7: event_name = "EnterNotify"; break;
1713 case 8: event_name = "LeaveNotify"; break;
1714 case 9: event_name = "FocusIn"; break;
1715 case 10: event_name = "FocusOut"; break;
1716 case 11: event_name = "KeymapNotify"; break;
1717 case 12: event_name = "Expose"; break;
1718 case 13: event_name = "GraphicsExpose"; break;
1719 case 14: event_name = "NoExpose"; break;
1720 case 15: event_name = "VisibilityNotify"; break;
1721 case 16: event_name = "CreateNotify"; break;
1722 case 17: event_name = "DestroyNotify"; break;
1723 case 18: event_name = "UnmapNotify"; break;
1724 case 19: event_name = "MapNotify"; break;
1725 case 20: event_name = "MapRequest"; break;
1726 case 21: event_name = "ReparentNotify"; break;
1727 case 22: event_name = "ConfigureNotify"; break;
1728 case 23: event_name = "ConfigureRequest"; break;
1729 case 24: event_name = "GravityNotify"; break;
1730 case 25: event_name = "ResizeRequest"; break;
1731 case 26: event_name = "CirculateNotify"; break;
1732 case 27: event_name = "CirculateRequest"; break;
1733 case 28: event_name = "PropertyNotify"; break;
1734 case 29: event_name = "SelectionClear"; break;
1735 case 30: event_name = "SelectionRequest"; break;
1736 case 31: event_name = "SelectionNotify"; break;
1737 case 32: event_name = "ColormapNotify"; break;
1738 case 33: event_name = "ClientMessage"; break;
1739 case 34: event_name = "MappingNotify"; break;
1740 default: event_name = "unknown";
1743 fprintf (stderr, "%s: %s\n", win_name, event_name);
1748 mwin__map_window (MFrame *frame, MDrawWindow win)
1750 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1754 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1756 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1760 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1761 MDrawMetric *geometry)
1763 Display *display = FRAME_DISPLAY (frame);
1764 XWindowAttributes attr;
1765 Window parent = (Window) parent_win, root;
1767 XGetWindowAttributes (display, (Window) win, &attr);
1768 geometry->x = attr.x + attr.border_width;
1769 geometry->y = attr.y + attr.border_width;
1770 geometry->width = attr.width;
1771 geometry->height = attr.height;
1774 parent = RootWindow (display, FRAME_SCREEN (frame));
1777 Window this_parent, *children;
1780 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1783 if (this_parent == parent || this_parent == root)
1785 win = (MDrawWindow) this_parent;
1786 XGetWindowAttributes (display, (Window) win, &attr);
1787 geometry->x += attr.x + attr.border_width;
1788 geometry->y += attr.y + attr.border_width;
1793 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1794 MDrawMetric *current, MDrawMetric *new)
1796 Display *display = FRAME_DISPLAY (frame);
1797 unsigned int mask = 0;
1798 XWindowChanges values;
1800 if (current->width != new->width)
1803 if (new->width <= 0)
1805 values.width = current->width = new->width;
1807 if (current->height != new->height)
1810 if (new->height <= 0)
1812 values.height = current->height = new->height;
1814 if (current->x != new->x)
1817 values.x = current->x = new->x;
1819 if (current->y != new->y)
1822 current->y = new->y;
1823 values.y = current->y = new->y;
1826 XConfigureWindow (display, (Window) win, mask, &values);
1827 XClearWindow (display, (Window) win);
1831 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1833 XEvent *event = (XEvent *) arg;
1834 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1841 if (event->xany.type != KeyPress
1842 /* && event->xany.type != KeyRelease */
1845 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1852 if (c < XK_space || c > XK_asciitilde)
1854 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1855 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1856 if (((XKeyEvent *) event)->state & ControlMask)
1858 if (c >= 'a' && c <= 'z')
1860 if (c >= ' ' && c < 127)
1861 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1863 key = minput__char_to_key (c);
1865 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1869 char *str = XKeysymToString (keysym);
1873 key = msymbol (str);
1874 if (((XKeyEvent *) event)->state & ShiftMask)
1875 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1876 if (((XKeyEvent *) event)->state & ControlMask)
1877 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1879 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1880 *modifiers |= MINPUT_KEY_META_MODIFIER;
1881 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1882 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1883 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1884 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1885 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1886 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1893 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1895 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1897 Display *display = FRAME_DISPLAY (frame);
1898 GCInfo *info = rface->info;
1901 for (i = 0; i <= GC_INVERSE; i++)
1903 XGetGCValues (display, info->gc[i], valuemask, &values);
1904 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1905 values.foreground, values.background);
1906 fprintf (stderr, "\n");
1910 static MDeviceDriver x_driver =
1913 mwin__device_get_prop,
1915 mwin__free_realized_face,
1917 mwin__draw_empty_boxes,
1921 mwin__region_from_rect,
1922 mwin__union_rect_with_region,
1923 mwin__intersect_region,
1924 mwin__region_add_rect,
1925 mwin__region_to_rect,
1928 mwin__create_window,
1929 mwin__destroy_window,
1932 mwin__window_geometry,
1933 mwin__adjust_window,
1937 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1942 M_iso8859_1 = msymbol ("iso8859-1");
1943 M_iso10646_1 = msymbol ("iso10646-1");
1945 display_info_list = mplist ();
1946 device_list = mplist ();
1949 xft_driver.select = mfont__ft_driver.select;
1950 xft_driver.list = mfont__ft_driver.list;
1953 Mxim = msymbol ("xim");
1954 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1962 M17N_OBJECT_UNREF (display_info_list);
1963 M17N_OBJECT_UNREF (device_list);
1968 #ifdef X_SET_ERROR_HANDLER
1970 x_error_handler (Display *display, XErrorEvent *error)
1977 x_io_error_handler (Display *display)
1984 /** Return an MWDevice object corresponding to a display specified in
1987 It searches device_list for a device matching the display. If
1988 found, return the found object. Otherwise, return a newly created
1992 device_open (MFrame *frame, MPlist *param)
1994 Display *display = NULL;
1995 Screen *screen = NULL;
1997 Drawable drawable = 0;
1998 Widget widget = NULL;
2000 int auto_display = 0;
2001 MDisplayInfo *disp_info = NULL;
2002 MWDevice *device = NULL;
2004 XWindowAttributes attr;
2010 int use_xfont = 0, use_freetype = 0, use_xft = 0;
2012 for (plist = param; (key = mplist_key (plist)) != Mnil;
2013 plist = mplist_next (plist))
2015 if (key == Mdisplay)
2016 display = (Display *) mplist_value (plist);
2017 else if (key == Mscreen)
2018 screen = mplist_value (plist);
2019 else if (key == Mdrawable)
2020 drawable = (Drawable) mplist_value (plist);
2021 else if (key == Mdepth)
2022 depth = (unsigned) mplist_value (plist);
2023 else if (key == Mwidget)
2024 widget = (Widget) mplist_value (plist);
2025 else if (key == Mcolormap)
2026 cmap = (Colormap) mplist_value (plist);
2027 else if (key == Mfont)
2029 MSymbol val = MPLIST_SYMBOL (plist);
2033 #ifdef HAVE_FREETYPE
2034 else if (val == Mfreetype)
2037 else if (val == Mxft)
2044 /* If none of them is specified, use all of them. */
2045 if (! use_xfont && ! use_freetype && ! use_xft)
2046 use_xfont = use_freetype = use_xft = 1;
2050 display = XtDisplay (widget);
2051 screen_num = XScreenNumberOfScreen (XtScreen (widget));
2052 depth = DefaultDepth (display, screen_num);
2058 unsigned width, height, border_width;
2061 MERROR (MERROR_WIN, -1);
2062 XGetGeometry (display, drawable, &root_window,
2063 &x, &y, &width, &height, &border_width, &depth);
2064 XGetWindowAttributes (display, root_window, &attr);
2065 screen_num = XScreenNumberOfScreen (attr.screen);
2070 display = DisplayOfScreen (screen);
2075 display = XOpenDisplay (NULL);
2077 MERROR (MERROR_WIN, -1);
2080 screen = DefaultScreenOfDisplay (display);
2082 screen_num = XScreenNumberOfScreen (screen);
2084 depth = DefaultDepth (display, screen_num);
2088 cmap = DefaultColormap (display, screen_num);
2090 for (plist = display_info_list; mplist_key (plist) != Mnil;
2091 plist = mplist_next (plist))
2093 disp_info = (MDisplayInfo *) mplist_value (plist);
2094 if (disp_info->display == display)
2098 if (mplist_key (plist) != Mnil)
2099 M17N_OBJECT_REF (disp_info);
2102 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
2103 disp_info->display = display;
2104 disp_info->auto_display = auto_display;
2105 disp_info->font_list = mplist ();
2106 find_modifier_bits (disp_info);
2107 mplist_add (display_info_list, Mt, disp_info);
2110 for (plist = device_list; mplist_key (plist) != Mnil;
2111 plist = mplist_next (plist))
2113 device = (MWDevice *) mplist_value (plist);
2114 if (device->display_info == disp_info
2115 && device->depth == depth
2116 && device->cmap == cmap
2117 && device->screen_num == screen_num)
2121 if (mplist_key (plist) != Mnil)
2122 M17N_OBJECT_REF (device);
2125 unsigned long valuemask = GCForeground;
2129 M17N_OBJECT (device, free_device, MERROR_WIN);
2130 device->display_info = disp_info;
2131 device->screen_num = screen_num;
2132 /* A drawable on which to create GCs. */
2133 device->drawable = XCreatePixmap (display,
2134 RootWindow (display, screen_num),
2136 device->depth = depth;
2137 device->cmap = cmap;
2138 pixels = DisplayHeight (display, screen_num);
2139 mm = DisplayHeightMM (display, screen_num);
2140 device->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
2141 device->realized_face_list = mplist ();
2142 device->realized_font_list = mplist ();
2143 mplist_add (device->realized_font_list, Mt, NULL);
2144 device->realized_fontset_list = mplist ();
2145 device->gc_list = mplist ();
2146 values.foreground = BlackPixel (display, screen_num);
2147 device->scratch_gc = XCreateGC (display, device->drawable,
2148 valuemask, &values);
2150 device->xft_draw = XftDrawCreate (display, device->drawable,
2151 DefaultVisual (display, screen_num),
2156 frame->device = device;
2157 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2158 frame->dpi = device->resy;
2159 frame->driver = &x_driver;
2160 frame->font_driver_list = mplist ();
2164 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2167 #endif /* HAVE_XFT2 */
2168 #ifdef HAVE_FREETYPE
2170 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2171 #endif /* HAVE_FREETYPE */
2172 if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list))
2173 mplist_push (frame->font_driver_list, Mx, &xfont_driver);
2175 frame->realized_font_list = device->realized_font_list;
2176 frame->realized_face_list = device->realized_face_list;
2177 frame->realized_fontset_list = device->realized_fontset_list;
2181 XtResource resources[] = {
2182 { XtNfont, XtCFont, XtRString, sizeof (String),
2183 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2184 { XtNforeground, XtCForeground, XtRString, sizeof (String),
2185 XtOffset (AppDataPtr, foreground), XtRString, "black" },
2186 { XtNbackground, XtCBackground, XtRString, sizeof (String),
2187 XtOffset (AppDataPtr, background), XtRString, "white" },
2188 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2189 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2192 XtGetApplicationResources (widget, &app_data,
2193 resources, XtNumber (resources), NULL, 0);
2194 frame->foreground = msymbol (app_data.foreground);
2195 frame->background = msymbol (app_data.background);
2196 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2200 app_data.font = DEFAULT_FONT;
2201 frame->foreground = msymbol ("black");
2202 frame->background = msymbol ("white");
2203 frame->videomode = Mnormal;
2206 if (strcmp (app_data.font, DEFAULT_FONT) != 0)
2208 XFontStruct *xfont = XLoadQueryFont (display, app_data.font);
2209 unsigned long value;
2214 font = mfont_parse_name (app_data.font, Mx);
2216 && XGetFontProperty (xfont, XA_FONT, &value)
2217 && (name = ((char *) XGetAtomName (display, (Atom) value))))
2218 font = mfont_parse_name (name, Mx);
2219 XFreeFont (display, xfont);
2223 font = mfont_parse_name (DEFAULT_FONT, Mx);
2224 else if (! font->size)
2226 face = mface_from_font (font);
2228 face->property[MFACE_FONTSET] = mfontset (NULL);
2229 face->property[MFACE_FOREGROUND] = frame->foreground;
2230 face->property[MFACE_BACKGROUND] = frame->background;
2231 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2232 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2233 face->property[MFACE_VIDEOMODE] = frame->videomode;
2234 mface_put_prop (face, Mhook_func,
2235 mface_get_prop (mface__default, Mhook_func));
2236 face->property[MFACE_RATIO] = (void *) 100;
2237 mplist_push (param, Mface, face);
2238 M17N_OBJECT_UNREF (face);
2240 #ifdef X_SET_ERROR_HANDLER
2241 XSetErrorHandler (x_error_handler);
2242 XSetIOErrorHandler (x_io_error_handler);
2249 /* XIM (X Input Method) handler */
2251 typedef struct MInputXIMMethodInfo
2257 } MInputXIMMethodInfo;
2259 typedef struct MInputXIMContextInfo
2263 MConverter *converter;
2264 } MInputXIMContextInfo;
2267 xim_open_im (MInputMethod *im)
2269 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2270 MLocale *saved, *this;
2271 char *save_modifier_list;
2273 MInputXIMMethodInfo *im_info;
2275 saved = mlocale_set (LC_CTYPE, NULL);
2276 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2278 /* The specified locale is not supported. */
2279 MERROR (MERROR_LOCALE, -1);
2280 if (mlocale_get_prop (this, Mcoding) == Mnil)
2282 /* Unable to decode the output of XIM. */
2283 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2284 MERROR (MERROR_LOCALE, -1);
2287 if (arg->modifier_list)
2288 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2290 save_modifier_list = XSetLocaleModifiers ("");
2291 if (! save_modifier_list)
2293 /* The specified locale is not supported by X. */
2294 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2295 MERROR (MERROR_LOCALE, -1);
2298 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2301 /* No input method is available in the current locale. */
2302 XSetLocaleModifiers (save_modifier_list);
2303 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2304 MERROR (MERROR_WIN, -1);
2307 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2308 im_info->display = arg->display;
2310 im_info->language = mlocale_get_prop (this, Mlanguage);
2311 im_info->coding = mlocale_get_prop (this, Mcoding);
2314 XSetLocaleModifiers (save_modifier_list);
2315 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2321 xim_close_im (MInputMethod *im)
2323 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2325 XCloseIM (im_info->xim);
2330 xim_create_ic (MInputContext *ic)
2332 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2333 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2334 MInputXIMContextInfo *ic_info;
2337 if (! arg->input_style)
2339 /* By default, use Root style. */
2340 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2341 arg->preedit_attrs = NULL;
2342 arg->status_attrs = NULL;
2345 if (! arg->preedit_attrs && ! arg->status_attrs)
2346 xic = XCreateIC (im_info->xim,
2347 XNInputStyle, arg->input_style,
2348 XNClientWindow, arg->client_win,
2349 XNFocusWindow, arg->focus_win,
2351 else if (arg->preedit_attrs && ! arg->status_attrs)
2352 xic = XCreateIC (im_info->xim,
2353 XNInputStyle, arg->input_style,
2354 XNClientWindow, arg->client_win,
2355 XNFocusWindow, arg->focus_win,
2356 XNPreeditAttributes, arg->preedit_attrs,
2358 else if (! arg->preedit_attrs && arg->status_attrs)
2359 xic = XCreateIC (im_info->xim,
2360 XNInputStyle, arg->input_style,
2361 XNClientWindow, arg->client_win,
2362 XNFocusWindow, arg->focus_win,
2363 XNStatusAttributes, arg->status_attrs,
2366 xic = XCreateIC (im_info->xim,
2367 XNInputStyle, arg->input_style,
2368 XNClientWindow, arg->client_win,
2369 XNFocusWindow, arg->focus_win,
2370 XNPreeditAttributes, arg->preedit_attrs,
2371 XNStatusAttributes, arg->status_attrs,
2374 MERROR (MERROR_WIN, -1);
2376 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2378 ic_info->win = arg->focus_win;
2379 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2385 xim_destroy_ic (MInputContext *ic)
2387 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2389 XDestroyIC (ic_info->xic);
2390 mconv_free_converter (ic_info->converter);
2396 xim_filter (MInputContext *ic, MSymbol key, void *event)
2398 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2400 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2405 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2407 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2408 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2409 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2415 buf = (char *) alloca (512);
2416 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2417 if (status == XBufferOverflow)
2419 buf = (char *) alloca (len);
2420 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2423 mtext_reset (ic->produced);
2427 mconv_reset_converter (ic_info->converter);
2428 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2429 mconv_decode (ic_info->converter, ic->produced);
2430 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2431 Mlanguage, (void *) im_info->language);
2432 mtext_cpy (mt, ic->produced);
2433 mtext_reset (ic->produced);
2441 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2445 /*** @addtogroup m17nInputMethodWin */
2450 @brief Input method driver for XIM.
2452 The driver #minput_xim_driver is for the foreign input method of
2453 name #Mxim. It uses XIM (X Input Methods) as a background input
2456 As the symbol #Mxim has property #Minput_driver whose value is
2457 a pointer to this driver, the input method of language #Mnil
2458 and name #Mxim uses this driver.
2460 Therefore, for such input methods, the driver dependent arguments
2461 to the functions whose name begin with minput_ must be as follows.
2463 The argument $ARG of the function minput_open_im () must be a
2464 pointer to the structure #MInputXIMArgIM. See the documentation
2465 of #MInputXIMArgIM for more details.
2467 The argument $ARG of the function minput_create_ic () must be a
2468 pointer to the structure #MInputXIMArgIC. See the documentation
2469 of #MInputXIMArgIC for more details.
2471 The argument $ARG of the function minput_filter () must be a
2472 pointer to the structure @c XEvent. The argument $KEY is ignored.
2474 The argument $ARG of the function minput_lookup () must be the
2475 same one as that of the function minput_filter (). The argument
2479 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2481 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ê¡¢
2482 XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
2484 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2485 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim
2486 ¤Ç¤¢¤ëÆþÎϥ᥽¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2488 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_
2489 ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2491 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM
2492 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò»²¾È¡£
2494 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC
2495 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ¤ò»²¾È¡£
2497 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent
2498 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2500 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2501 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì¤ë¡£ */
2503 MInputDriver minput_xim_driver =
2504 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2505 xim_filter, xim_lookup, NULL };