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;
466 plist = mplist_get (font_list, registry);
470 mplist_add (font_list, registry, plist);
471 sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", msymbol_name (registry));
472 font_names = XListFonts (disp_info->display, pattern, 0x8000, &nfonts);
475 names = alloca (sizeof (char *) * nfonts);
476 memcpy (names, font_names, sizeof (char *) * nfonts);
477 qsort (names, nfonts, sizeof (char *), font_compare);
479 for (i = 0, p = NULL; i < nfonts; i++)
480 if (mfont__parse_name_into_font (names[i], Mx, &font) == 0
481 && (font.size >= 50 || font.property[MFONT_RESY] == 0))
483 MSymbol family = FONT_PROPERTY (&font, MFONT_FAMILY);
484 MFontX *fontx, *fontx2;
492 if (p && MPLIST_KEY (p) != family)
493 p = mplist_find_by_key (plist, family);
495 p = mplist_push (plist, family, NULL);
497 /* Calculate how many bytes to compare to detect fonts of the
499 for (base_end = names[i], fields = 0; *base_end; base_end++)
501 && ++fields == 7 /* PIXEL_SIZE */)
503 base_len = base_end - names[i] + 1;
505 size = smallest = font.size / 10;
506 sizes[nsizes++] = size;
507 for (j = i + 1; j < nfonts && ! strncmp (names[i], names[j], base_len);
509 if (mfont__parse_name_into_font (names[j], Mx, &font) == 0
510 && (font.size >= 50 || font.property[MFONT_RESY] == 0))
512 size = font.size / 10;
516 sizes[nsizes++] = size;
519 font.type = MFONT_TYPE_OBJECT;
520 font.source = MFONT_SOURCE_X;
521 MSTRUCT_CALLOC (fontx, MERROR_WIN);
523 fontx->core.size = smallest * 10;
524 fontx->next = MPLIST_VAL (p);
525 MPLIST_VAL (p) = fontx;
527 for (j = 0; j < nsizes; j++)
531 if (sizes[j] != smallest)
532 SET_SIZE (fontx, sizes[j]);
536 MSTRUCT_CALLOC (fontx2, MERROR_WIN);
538 fontx2->core.size = sizes[j] * 10;
539 fontx2->next = MPLIST_VAL (p);
540 MPLIST_VAL (p) = fontx2;
544 XFreeFontNames (font_names);
549 xfont_list_all (MFrame *frame)
551 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
552 MPlist *font_encoding_list, *p;
554 if (disp_info->all_fonts_scaned)
556 disp_info->all_fonts_scaned = 1;
557 font_encoding_list = mfont__encoding_list ();
558 if (! font_encoding_list)
560 MPLIST_DO (p, font_encoding_list)
561 xfont_registry_list (frame, MPLIST_KEY (p));
571 /* The X font driver function SELECT. */
574 xfont_select (MFrame *frame, MFont *font, int limited_size)
576 MPlist *plist = mplist (), *pl;
577 int num = xfont_list (frame, plist, font, 0);
581 MPLIST_DO (pl, plist)
583 font = MPLIST_VAL (pl);
584 if (limited_size == 0
586 || font->size <= limited_size)
592 M17N_OBJECT_UNREF (plist);
596 /* The X font driver function CLOSE. */
599 close_xfont (void *object)
601 MRealizedFontX *x_rfont = object;
603 XFreeFont (x_rfont->display, x_rfont->xfont);
607 /* The X font driver function OPEN. */
609 static MRealizedFont *
610 xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
612 int size = spec->size;
613 MRealizedFontX *x_rfont;
615 Display *display = FRAME_DISPLAY (frame);
617 int mdebug_mask = MDEBUG_FONT;
622 for (; rfont; rfont = rfont->next)
623 if (rfont->font == font && rfont->spec.size == size)
629 /* This never fail to generate a valid fontname. */
630 name = mfont_unparse_name (&this, Mx);
631 xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
634 MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
636 font->type = MFONT_TYPE_FAILURE;
639 MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
641 M17N_OBJECT (x_rfont, close_xfont, MERROR_FONT_X);
642 x_rfont->display = display;
643 x_rfont->xfont = xfont;
644 MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
646 rfont->spec.type = MFONT_TYPE_REALIZED;
647 rfont->spec.source = MFONT_SOURCE_X;
648 rfont->frame = frame;
650 rfont->driver = &xfont_driver;
651 rfont->info = x_rfont;
652 rfont->ascent = xfont->ascent;
653 rfont->descent = xfont->descent;
654 rfont->max_advance = xfont->max_bounds.width;
655 rfont->fontp = xfont;
656 rfont->next = MPLIST_VAL (frame->realized_font_list);
657 MPLIST_VAL (frame->realized_font_list) = rfont;
662 /* The X font driver function FIND_METRIC. */
665 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
668 XFontStruct *xfont = rfont->fontp;
669 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
671 for (; g != gend; g++)
673 if (g->code == MCHAR_INVALID_CODE)
675 g->lbearing = xfont->max_bounds.lbearing;
676 g->rbearing = xfont->max_bounds.rbearing;
677 g->width = xfont->max_bounds.width;
678 g->ascent = xfont->ascent;
679 g->descent = xfont->descent;
683 int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
684 XCharStruct *pcm = NULL;
686 if (xfont->per_char != NULL)
688 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
691 && byte2 >= xfont->min_char_or_byte2
692 && byte2 <= xfont->max_char_or_byte2)
693 pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
697 if (byte1 >= xfont->min_byte1
698 && byte1 <= xfont->max_byte1
699 && byte2 >= xfont->min_char_or_byte2
700 && byte2 <= xfont->max_char_or_byte2)
702 pcm = (xfont->per_char
703 + ((xfont->max_char_or_byte2
704 - xfont->min_char_or_byte2 + 1)
705 * (byte1 - xfont->min_byte1))
706 + (byte2 - xfont->min_char_or_byte2));
713 g->lbearing = pcm->lbearing;
714 g->rbearing = pcm->rbearing;
715 g->width = pcm->width;
716 g->ascent = pcm->ascent;
717 g->descent = pcm->descent;
721 /* If the per_char pointer is null, all glyphs between
722 the first and last character indexes inclusive have
723 the same information, as given by both min_bounds and
726 g->rbearing = xfont->max_bounds.width;
727 g->width = xfont->max_bounds.width;
728 g->ascent = xfont->ascent;
729 g->descent = xfont->descent;
737 xfont_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
739 return (xfont_encode_char (frame, font, spec, code) != MCHAR_INVALID_CODE);
742 /* The X font driver function GET_GLYPH_ID. */
745 xfont_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
747 MRealizedFont *rfont;
749 unsigned min_byte1, max_byte1, min_byte2, max_byte2;
752 if (font->type == MFONT_TYPE_REALIZED)
753 rfont = (MRealizedFont *) font;
754 else if (font->type == MFONT_TYPE_OBJECT)
756 int size = spec->size;
758 for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
760 if (rfont->font == font && rfont->spec.size == size)
764 rfont = xfont_open (frame, font, spec, NULL);
766 return MCHAR_INVALID_CODE;
770 MFATAL (MERROR_FONT_X);
771 xfont = rfont->fontp;
772 all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
773 min_byte1 = xfont->min_byte1;
774 max_byte1 = xfont->max_byte1;
775 min_byte2 = xfont->min_char_or_byte2;
776 max_byte2 = xfont->max_char_or_byte2;
778 if (min_byte1 == 0 && max_byte1 == 0)
782 if (code < min_byte2 || code > max_byte2)
783 return MCHAR_INVALID_CODE;
786 pcm = xfont->per_char + (code - min_byte2);
787 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
788 ? code : MCHAR_INVALID_CODE);
792 unsigned byte1 = code >> 8, byte2 = code & 0xFF;
795 if (byte1 < min_byte1 || byte1 > max_byte1
796 || byte2 < min_byte2 || byte2 > max_byte2)
797 return MCHAR_INVALID_CODE;
801 pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
802 + (byte2 - min_byte2));
803 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
804 ? code : MCHAR_INVALID_CODE);
808 /* The X font driver function RENDER. */
811 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
812 MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
814 MRealizedFace *rface = from->rface;
815 Display *display = FRAME_DISPLAY (rface->frame);
817 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
825 gc = set_region (rface->frame, gc, region);
826 XSetFont (display, gc, ((XFontStruct *) rface->rfont->fontp)->fid);
827 code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
828 for (i = 0, g = from; g < to; i++, g++)
830 code[i].byte1 = g->code >> 8;
831 code[i].byte2 = g->code & 0xFF;
837 if (g->type == GLYPH_PAD)
839 else if (g->type == GLYPH_SPACE)
840 for (; g < to && g->type == GLYPH_SPACE; g++)
842 else if (! g->rface->rfont)
844 if ((g->c >= 0x200B && g->c <= 0x200F)
845 || (g->c >= 0x202A && g->c <= 0x202E))
849 /* As a font is not found for this character, draw an
851 int box_width = g->width;
852 int box_height = gstring->ascent + gstring->descent;
858 XDrawRectangle (display, (Window) win, gc,
859 x, y - gstring->ascent, box_width, box_height);
863 else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
865 XDrawString16 (display, (Window) win, gc,
866 x + g->xoff, y + g->yoff, code + (g - from), 1);
873 int code_idx = g - from;
876 g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
879 XDrawString16 (display, (Window) win, gc, orig_x, y,
886 xfont_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum)
888 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
889 MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil;
890 MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil;
891 int size = font ? font->size : 0;
894 int mdebug_mask = MDEBUG_FONT;
896 MDEBUG_PRINT2 (" [X-FONT] listing %s-%s...",
897 family ? msymbol_name (family) : "*",
898 registry ? msymbol_name (registry) : "*");
900 if (registry == Mnil)
901 xfont_list_all (frame);
903 xfont_registry_list (frame, registry);
905 MPLIST_DO (pl, disp_info->font_list)
907 if (registry != Mnil && registry != MPLIST_KEY (pl))
909 MPLIST_DO (p, MPLIST_VAL (pl))
913 if (family != Mnil && family != MPLIST_KEY (p))
915 for (fontx = MPLIST_VAL (p); fontx; fontx = fontx->next)
917 || (mfont__match_p (&fontx->core, font, MFONT_REGISTRY)))
919 if (fontx->core.size == size
920 || fontx->core.size == 0)
922 mplist_push (plist, MPLIST_KEY (p), fontx);
926 || (size <= 360 && HAVE_SIZE (fontx, (size / 10))))
928 unsigned size5_36 = fontx->size5_36;
933 for (i = fontx->core.size / 10; i <= 36; i++)
934 if (size5_36 & (1 << (i - 5)))
936 MSTRUCT_CALLOC (fontx2, MERROR_WIN);
937 fontx2->core = fontx->core;
938 fontx2->core.size = i * 10;
939 fontx2->next = fontx->next;
940 fontx->next = fontx2;
942 if ((size == 0 || size == fontx->core.size)
943 && (maxnum == 0 || num < maxnum))
945 mplist_push (plist, MPLIST_KEY (p), fontx);
950 if (maxnum > 0 && maxnum == num)
953 if (maxnum > 0 && maxnum == num)
956 if (maxnum > 0 && maxnum == num)
960 MDEBUG_PRINT1 (" %d found\n", num);
976 /* Pointer to MRealizedFontFT */
980 static MRealizedFont *xft_open (MFrame *frame, MFont *font, MFont *spec,
982 static int xft_has_char (MFrame *frame, MFont *font, MFont *spec,
983 int c, unsigned code);
984 static unsigned xft_encode_char (MFrame *frame, MFont *font, MFont *spec,
986 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
987 static void xft_render (MDrawWindow, int, int, MGlyphString *,
988 MGlyph *, MGlyph *, int, MDrawRegion);
990 MFontDriver xft_driver =
992 xft_find_metric, xft_has_char, xft_encode_char, xft_render, NULL };
995 close_xft (void *object)
997 MRealizedFontXft *rfont_xft = object;
999 if (rfont_xft->font_aa)
1000 XftFontClose (rfont_xft->display, rfont_xft->font_aa);
1001 if (rfont_xft->font_no_aa)
1002 XftFontClose (rfont_xft->display, rfont_xft->font_no_aa);
1003 M17N_OBJECT_UNREF (rfont_xft->info);
1009 xft_open_font (Display *display, MSymbol file, double size,
1015 pattern = FcPatternCreate ();
1016 FcPatternAddString (pattern, FC_FILE, (FcChar8 *) msymbol_name (file));
1017 FcPatternAddDouble (pattern, FC_PIXEL_SIZE, size);
1018 FcPatternAddBool (pattern, FC_ANTIALIAS, anti_alias);
1019 font = XftFontOpenPattern (display, pattern);
1024 static MRealizedFont *
1025 xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
1027 Display *display = FRAME_DISPLAY (frame);
1028 int reg = spec->property[MFONT_REGISTRY];
1030 MRealizedFontXft *rfont_xft;
1031 FcBool anti_alias = FRAME_DEVICE (frame)->depth > 1 ? FcTrue : FcFalse;
1032 double size = font->size ? font->size : spec->size;
1037 MRealizedFont *save = NULL;
1039 for (; rfont; rfont = rfont->next)
1040 if (rfont->font == font
1041 && (rfont->font->size ? rfont->font->size == size
1042 : rfont->spec.size == size)
1043 && rfont->spec.property[MFONT_REGISTRY] == reg)
1047 if (rfont->driver == &xft_driver)
1052 rfont = (mfont__ft_driver.open) (frame, font, spec, rfont);
1055 spec = &rfont->spec;
1056 ft_face = rfont->fontp;
1057 xft_font = xft_open_font (display, font->file, size / 10, anti_alias);
1060 M17N_OBJECT (rfont_xft, close_xft, MERROR_WIN);
1061 rfont_xft->display = display;
1062 if (anti_alias == FcTrue)
1063 rfont_xft->font_aa = xft_font;
1065 rfont_xft->font_no_aa = xft_font;
1066 rfont_xft->ft_face = ft_face;
1067 rfont_xft->info = rfont->info;
1068 M17N_OBJECT_REF (rfont->info);
1069 MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
1070 rfont->spec = *spec;
1071 rfont->frame = frame;
1073 rfont->driver = &xft_driver;
1074 rfont->info = rfont_xft;
1075 rfont->ascent = ft_face->size->metrics.ascender >> 6;
1076 rfont->descent = - ft_face->size->metrics.descender >> 6;
1077 rfont->max_advance = ft_face->size->metrics.max_advance >> 6;
1078 rfont->fontp = xft_font;
1079 rfont->next = MPLIST_VAL (frame->realized_font_list);
1080 MPLIST_VAL (frame->realized_font_list) = rfont;
1085 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1088 Display *display = FRAME_DISPLAY (rfont->frame);
1089 XftFont *xft_font = rfont->fontp;
1090 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1092 for (; g != gend; g++)
1094 if (g->code == MCHAR_INVALID_CODE)
1097 g->rbearing = xft_font->max_advance_width;
1098 g->width = g->rbearing;
1099 g->ascent = xft_font->ascent;
1100 g->descent = xft_font->descent;
1106 XftGlyphExtents (display, xft_font, &g->code, 1, &extents);
1107 g->lbearing = - extents.x;
1108 g->rbearing = extents.width - extents.x;
1109 g->width = extents.xOff;
1110 g->ascent = extents.y;
1111 g->descent = extents.height - extents.y;
1117 xft_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
1121 if (font->type == MFONT_TYPE_REALIZED)
1123 MRealizedFont *rfont = (MRealizedFont *) font;
1124 MRealizedFontXft *rfont_xft = rfont->info;
1126 rfont->info = rfont_xft->info;
1127 result = mfont__ft_driver.has_char (frame, font, spec, c, code);
1128 rfont->info = rfont_xft;
1131 result = mfont__ft_driver.has_char (frame, font, spec, c, code);
1136 xft_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
1138 if (font->type == MFONT_TYPE_REALIZED)
1140 MRealizedFont *rfont = (MRealizedFont *) font;
1141 MRealizedFontXft *rfont_xft = rfont->info;
1143 rfont->info = rfont_xft->info;
1144 code = mfont__ft_driver.encode_char (frame, font, spec, code);
1145 rfont->info = rfont_xft;
1148 code = mfont__ft_driver.encode_char (frame, font, spec, code);
1153 xft_render (MDrawWindow win, int x, int y,
1154 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1155 int reverse, MDrawRegion region)
1157 MRealizedFace *rface = from->rface;
1158 MFrame *frame = rface->frame;
1159 Display *display = FRAME_DISPLAY (frame);
1160 MRealizedFont *rfont = rface->rfont;
1161 MRealizedFontXft *rfont_xft = rfont->info;
1162 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1163 XftColor *xft_color = (! reverse
1164 ? &((GCInfo *) rface->info)->xft_color_fore
1165 : &((GCInfo *) rface->info)->xft_color_back);
1166 int anti_alias = (gstring->control.anti_alias
1167 && FRAME_DEVICE (frame)->depth > 1);
1179 if (rfont_xft->font_aa)
1180 xft_font = rfont_xft->font_aa;
1183 double size = rfont->spec.size;
1185 xft_font = xft_open_font (display, rfont->spec.file, size / 10,
1188 rfont_xft->font_aa = xft_font;
1190 xft_font = rfont->fontp;
1195 if (rfont_xft->font_no_aa)
1196 xft_font = rfont_xft->font_no_aa;
1199 double size = rfont->spec.size;
1201 xft_font = xft_open_font (display, rfont->spec.file, size / 10,
1204 rfont_xft->font_no_aa = xft_font;
1206 xft_font = rfont->fontp;
1210 XftDrawChange (xft_draw, (Drawable) win);
1211 XftDrawSetClip (xft_draw, (Region) region);
1213 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1214 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1216 if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1217 glyphs[nglyphs++] = g->code;
1221 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1222 last_x, y, glyphs, nglyphs);
1224 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1225 x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1226 last_x = x + g->width;
1230 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1233 #endif /* HAVE_XFT2 */
1236 /* Functions for the device driver. */
1239 mwin__close_device (MFrame *frame)
1241 MWDevice *device = FRAME_DEVICE (frame);
1243 M17N_OBJECT_UNREF (device);
1247 mwin__device_get_prop (MFrame *frame, MSymbol key)
1249 MWDevice *device = FRAME_DEVICE (frame);
1251 if (key == Mdisplay)
1252 return (void *) device->display_info->display;
1254 return (void *) ScreenOfDisplay(device->display_info->display,
1255 device->screen_num);
1256 if (key == Mcolormap)
1257 return (void *) device->cmap;
1259 return (void *) device->depth;
1264 mwin__realize_face (MRealizedFace *rface)
1267 MSymbol foreground, background, videomode;
1268 MFaceHLineProp *hline;
1272 if (rface != rface->ascii_rface)
1274 rface->info = rface->ascii_rface->info;
1278 frame = rface->frame;
1279 MSTRUCT_CALLOC (info, MERROR_WIN);
1281 foreground = rface->face.property[MFACE_FOREGROUND];
1282 background = rface->face.property[MFACE_BACKGROUND];
1283 videomode = rface->face.property[MFACE_VIDEOMODE];
1285 videomode = frame->videomode;
1286 if (videomode != Mreverse)
1288 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1289 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1293 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1294 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1297 if (foreground == Mnil)
1298 foreground = frame->foreground;
1299 if (background == Mnil)
1300 background = frame->background;
1301 if (videomode == Mreverse)
1303 MSymbol temp = foreground;
1304 foreground = background;
1307 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1308 FRAME_VISUAL (frame),
1310 MSYMBOL_NAME (foreground),
1311 &info->xft_color_fore))
1313 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1314 FRAME_VISUAL (frame),
1316 MSYMBOL_NAME (background),
1317 &info->xft_color_back))
1319 #endif /* HAVE_XFT2 */
1321 hline = rface->hline;
1325 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1327 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1334 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1336 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1338 if (box->color_left && box->color_left != box->color_top)
1339 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1341 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1343 if (box->color_bottom && box->color_bottom != box->color_top)
1344 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1346 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1348 if (box->color_right && box->color_right != box->color_bottom)
1349 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1351 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1359 mwin__free_realized_face (MRealizedFace *rface)
1361 if (rface == rface->ascii_rface)
1367 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1369 int x, int y, int width, int height, MDrawRegion region)
1371 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1374 gc = set_region (frame, gc, region);
1376 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1377 x, y, width, height);
1382 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1383 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1384 int reverse, MDrawRegion region)
1386 MRealizedFace *rface = from->rface;
1387 Display *display = FRAME_DISPLAY (rface->frame);
1388 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1394 gc = set_region (rface->frame, gc, region);
1395 for (; from < to; from++)
1397 XDrawRectangle (display, (Window) win, gc,
1398 x, y - gstring->ascent + 1, from->width - 1,
1399 gstring->ascent + gstring->descent - 2);
1406 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1407 MRealizedFace *rface, int reverse,
1408 int x, int y, int width, MDrawRegion region)
1410 enum MFaceHLineType type = rface->hline->type;
1411 GCInfo *info = rface->info;
1412 GC gc = gc = info->gc[GC_HLINE];
1415 y = (type == MFACE_HLINE_BOTTOM
1416 ? y + gstring->text_descent - rface->hline->width
1417 : type == MFACE_HLINE_UNDER
1419 : type == MFACE_HLINE_STRIKE_THROUGH
1420 ? y - ((gstring->ascent + gstring->descent) / 2)
1421 : y - gstring->text_ascent);
1423 gc = set_region (frame, gc, region);
1425 for (i = 0; i < rface->hline->width; i++)
1426 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1427 x, y + i, x + width - 1, y + i);
1432 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1433 MGlyph *g, int x, int y, int width, MDrawRegion region)
1435 Display *display = FRAME_DISPLAY (frame);
1436 MRealizedFace *rface = g->rface;
1437 MFaceBoxProp *box = rface->box;
1438 GCInfo *info = rface->info;
1439 GC gc_top, gc_left, gc_right, gc_btm;
1443 y0 = y - (gstring->text_ascent
1444 + rface->box->inner_vmargin + rface->box->width);
1445 y1 = y + (gstring->text_descent
1446 + rface->box->inner_vmargin + rface->box->width - 1);
1448 gc_top = info->gc[GC_BOX_TOP];
1450 gc_top = set_region (frame, gc_top, region);
1451 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1454 gc_btm = info->gc[GC_BOX_BOTTOM];
1456 if (g->type == GLYPH_BOX)
1460 if (g->left_padding)
1461 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1463 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1465 /* Draw the top side. */
1466 for (i = 0; i < box->width; i++)
1467 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1469 /* Draw the bottom side. */
1470 if (region && gc_btm != gc_top)
1471 gc_btm = set_region (frame, gc_btm, region);
1472 for (i = 0; i < box->width; i++)
1473 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1475 if (g->left_padding > 0)
1477 /* Draw the left side. */
1478 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1482 gc_left = info->gc[GC_BOX_LEFT];
1484 gc_left = set_region (frame, gc_left, region);
1486 for (i = 0; i < rface->box->width; i++)
1487 XDrawLine (display, (Window) win, gc_left,
1488 x0 + i, y0 + i, x0 + i, y1 - i);
1492 /* Draw the right side. */
1493 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1497 gc_right = info->gc[GC_BOX_RIGHT];
1499 gc_right = set_region (frame, gc_right, region);
1501 for (i = 0; i < rface->box->width; i++)
1502 XDrawLine (display, (Window) win, gc_right,
1503 x1 - i, y0 + i, x1 - i, y1 - i);
1508 /* Draw the top side. */
1509 for (i = 0; i < box->width; i++)
1510 XDrawLine (display, (Window) win, gc_top,
1511 x, y0 + i, x + width - 1, y0 + i);
1513 /* Draw the bottom side. */
1514 if (region && gc_btm != gc_top)
1515 gc_btm = set_region (frame, gc_btm, region);
1516 for (i = 0; i < box->width; i++)
1517 XDrawLine (display, (Window) win, gc_btm,
1518 x, y1 - i, x + width - 1, y1 - i);
1525 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1526 int reverse, int x, int y,
1527 int width, int height, int row_bytes, unsigned char *bmp,
1530 Display *display = FRAME_DISPLAY (frame);
1532 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1535 gc = set_region (frame, gc, region);
1537 for (i = 0; i < height; i++, bmp += row_bytes)
1538 for (j = 0; j < width; j++)
1539 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1540 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1545 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1546 int intensity, MDrawPoint *points, int num,
1549 GCInfo *info = rface->info;
1552 if (! (gc = info->gc[intensity]))
1553 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1556 gc = set_region (frame, gc, region);
1558 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1559 (XPoint *) points, num, CoordModeOrigin);
1564 mwin__region_from_rect (MDrawMetric *rect)
1566 MDrawRegion region1 = XCreateRegion ();
1567 MDrawRegion region2 = XCreateRegion ();
1572 xrect.width = rect->width;
1573 xrect.height = rect->height;
1574 XUnionRectWithRegion (&xrect, region1, region2);
1575 XDestroyRegion (region1);
1580 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1582 MDrawRegion region1 = XCreateRegion ();
1587 xrect.width = rect->width;
1588 xrect.height = rect->height;
1590 XUnionRegion (region, region, region1);
1591 XUnionRectWithRegion (&xrect, region1, region);
1592 XDestroyRegion (region1);
1596 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1598 MDrawRegion region = XCreateRegion ();
1600 XUnionRegion (region1, region1, region);
1601 XIntersectRegion (region, region2, region1);
1602 XDestroyRegion (region);
1606 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1608 MDrawRegion region1 = XCreateRegion ();
1613 xrect.width = rect->width;
1614 xrect.height = rect->height;
1615 XUnionRectWithRegion (&xrect, region1, region);
1616 XDestroyRegion (region1);
1620 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1624 XClipBox (region, &xrect);
1627 rect->width = xrect.width;
1628 rect->height = xrect.height;
1632 mwin__free_region (MDrawRegion region)
1634 XDestroyRegion (region);
1638 mwin__dump_region (MDrawRegion region)
1641 XClipBox (region, &rect);
1642 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1647 mwin__create_window (MFrame *frame, MDrawWindow parent)
1649 Display *display = FRAME_DISPLAY (frame);
1651 XWMHints wm_hints = { InputHint, False };
1652 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1653 XSetWindowAttributes set_attrs;
1656 GCInfo *info = frame->rface->info;
1659 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1660 mask = GCForeground;
1661 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1662 set_attrs.background_pixel = values.foreground;
1663 set_attrs.backing_store = Always;
1664 set_attrs.override_redirect = True;
1665 set_attrs.save_under = True;
1666 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1667 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1668 CopyFromParent, InputOutput, CopyFromParent,
1670 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1671 NULL, &wm_hints, &class_hints);
1672 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1673 return (MDrawWindow) win;
1677 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1679 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1684 mwin__event_window (void *event)
1686 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1690 mwin__print_event (void *arg, char *win_name)
1693 XEvent *event = (XEvent *) arg;
1695 switch (event->xany.type)
1697 case 2: event_name = "KeyPress"; break;
1698 case 3: event_name = "KeyRelease"; break;
1699 case 4: event_name = "ButtonPress"; break;
1700 case 5: event_name = "ButtonRelease"; break;
1701 case 6: event_name = "MotionNotify"; break;
1702 case 7: event_name = "EnterNotify"; break;
1703 case 8: event_name = "LeaveNotify"; break;
1704 case 9: event_name = "FocusIn"; break;
1705 case 10: event_name = "FocusOut"; break;
1706 case 11: event_name = "KeymapNotify"; break;
1707 case 12: event_name = "Expose"; break;
1708 case 13: event_name = "GraphicsExpose"; break;
1709 case 14: event_name = "NoExpose"; break;
1710 case 15: event_name = "VisibilityNotify"; break;
1711 case 16: event_name = "CreateNotify"; break;
1712 case 17: event_name = "DestroyNotify"; break;
1713 case 18: event_name = "UnmapNotify"; break;
1714 case 19: event_name = "MapNotify"; break;
1715 case 20: event_name = "MapRequest"; break;
1716 case 21: event_name = "ReparentNotify"; break;
1717 case 22: event_name = "ConfigureNotify"; break;
1718 case 23: event_name = "ConfigureRequest"; break;
1719 case 24: event_name = "GravityNotify"; break;
1720 case 25: event_name = "ResizeRequest"; break;
1721 case 26: event_name = "CirculateNotify"; break;
1722 case 27: event_name = "CirculateRequest"; break;
1723 case 28: event_name = "PropertyNotify"; break;
1724 case 29: event_name = "SelectionClear"; break;
1725 case 30: event_name = "SelectionRequest"; break;
1726 case 31: event_name = "SelectionNotify"; break;
1727 case 32: event_name = "ColormapNotify"; break;
1728 case 33: event_name = "ClientMessage"; break;
1729 case 34: event_name = "MappingNotify"; break;
1730 default: event_name = "unknown";
1733 fprintf (stderr, "%s: %s\n", win_name, event_name);
1738 mwin__map_window (MFrame *frame, MDrawWindow win)
1740 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1744 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1746 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1750 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1751 MDrawMetric *geometry)
1753 Display *display = FRAME_DISPLAY (frame);
1754 XWindowAttributes attr;
1755 Window parent = (Window) parent_win, root;
1757 XGetWindowAttributes (display, (Window) win, &attr);
1758 geometry->x = attr.x + attr.border_width;
1759 geometry->y = attr.y + attr.border_width;
1760 geometry->width = attr.width;
1761 geometry->height = attr.height;
1764 parent = RootWindow (display, FRAME_SCREEN (frame));
1767 Window this_parent, *children;
1770 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1773 if (this_parent == parent || this_parent == root)
1775 win = (MDrawWindow) this_parent;
1776 XGetWindowAttributes (display, (Window) win, &attr);
1777 geometry->x += attr.x + attr.border_width;
1778 geometry->y += attr.y + attr.border_width;
1783 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1784 MDrawMetric *current, MDrawMetric *new)
1786 Display *display = FRAME_DISPLAY (frame);
1787 unsigned int mask = 0;
1788 XWindowChanges values;
1790 if (current->width != new->width)
1793 if (new->width <= 0)
1795 values.width = current->width = new->width;
1797 if (current->height != new->height)
1800 if (new->height <= 0)
1802 values.height = current->height = new->height;
1804 if (current->x != new->x)
1807 values.x = current->x = new->x;
1809 if (current->y != new->y)
1812 current->y = new->y;
1813 values.y = current->y = new->y;
1816 XConfigureWindow (display, (Window) win, mask, &values);
1817 XClearWindow (display, (Window) win);
1821 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1823 XEvent *event = (XEvent *) arg;
1824 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1831 if (event->xany.type != KeyPress
1832 /* && event->xany.type != KeyRelease */
1835 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1842 if (c < XK_space || c > XK_asciitilde)
1844 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1845 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1846 if (((XKeyEvent *) event)->state & ControlMask)
1848 if (c >= 'a' && c <= 'z')
1850 if (c >= ' ' && c < 127)
1851 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1853 key = minput__char_to_key (c);
1855 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1859 char *str = XKeysymToString (keysym);
1863 key = msymbol (str);
1864 if (((XKeyEvent *) event)->state & ShiftMask)
1865 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1866 if (((XKeyEvent *) event)->state & ControlMask)
1867 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1869 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1870 *modifiers |= MINPUT_KEY_META_MODIFIER;
1871 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1872 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1873 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1874 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1875 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1876 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1883 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1885 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1887 Display *display = FRAME_DISPLAY (frame);
1888 GCInfo *info = rface->info;
1891 for (i = 0; i <= GC_INVERSE; i++)
1893 XGetGCValues (display, info->gc[i], valuemask, &values);
1894 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1895 values.foreground, values.background);
1896 fprintf (stderr, "\n");
1900 static MDeviceDriver x_driver =
1903 mwin__device_get_prop,
1905 mwin__free_realized_face,
1907 mwin__draw_empty_boxes,
1911 mwin__region_from_rect,
1912 mwin__union_rect_with_region,
1913 mwin__intersect_region,
1914 mwin__region_add_rect,
1915 mwin__region_to_rect,
1918 mwin__create_window,
1919 mwin__destroy_window,
1922 mwin__window_geometry,
1923 mwin__adjust_window,
1927 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1932 M_iso8859_1 = msymbol ("iso8859-1");
1933 M_iso10646_1 = msymbol ("iso10646-1");
1935 display_info_list = mplist ();
1936 device_list = mplist ();
1939 xft_driver.select = mfont__ft_driver.select;
1940 xft_driver.list = mfont__ft_driver.list;
1943 Mxim = msymbol ("xim");
1944 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1952 M17N_OBJECT_UNREF (display_info_list);
1953 M17N_OBJECT_UNREF (device_list);
1958 #ifdef X_SET_ERROR_HANDLER
1960 x_error_handler (Display *display, XErrorEvent *error)
1967 x_io_error_handler (Display *display)
1974 /** Return an MWDevice object corresponding to a display specified in
1977 It searches device_list for a device matching the display. If
1978 found, return the found object. Otherwise, return a newly created
1982 device_open (MFrame *frame, MPlist *param)
1984 Display *display = NULL;
1985 Screen *screen = NULL;
1987 Drawable drawable = 0;
1988 Widget widget = NULL;
1990 int auto_display = 0;
1991 MDisplayInfo *disp_info = NULL;
1992 MWDevice *device = NULL;
1994 XWindowAttributes attr;
2000 int use_xfont = 0, use_freetype = 0, use_xft = 0;
2002 for (plist = param; (key = mplist_key (plist)) != Mnil;
2003 plist = mplist_next (plist))
2005 if (key == Mdisplay)
2006 display = (Display *) mplist_value (plist);
2007 else if (key == Mscreen)
2008 screen = mplist_value (plist);
2009 else if (key == Mdrawable)
2010 drawable = (Drawable) mplist_value (plist);
2011 else if (key == Mdepth)
2012 depth = (unsigned) mplist_value (plist);
2013 else if (key == Mwidget)
2014 widget = (Widget) mplist_value (plist);
2015 else if (key == Mcolormap)
2016 cmap = (Colormap) mplist_value (plist);
2017 else if (key == Mfont)
2019 MSymbol val = MPLIST_SYMBOL (plist);
2023 #ifdef HAVE_FREETYPE
2024 else if (val == Mfreetype)
2027 else if (val == Mxft)
2034 /* If none of them is specified, use all of them. */
2035 if (! use_xfont && ! use_freetype && ! use_xft)
2036 use_xfont = use_freetype = use_xft = 1;
2040 display = XtDisplay (widget);
2041 screen_num = XScreenNumberOfScreen (XtScreen (widget));
2042 depth = DefaultDepth (display, screen_num);
2048 unsigned width, height, border_width;
2051 MERROR (MERROR_WIN, -1);
2052 XGetGeometry (display, drawable, &root_window,
2053 &x, &y, &width, &height, &border_width, &depth);
2054 XGetWindowAttributes (display, root_window, &attr);
2055 screen_num = XScreenNumberOfScreen (attr.screen);
2060 display = DisplayOfScreen (screen);
2065 display = XOpenDisplay (NULL);
2067 MERROR (MERROR_WIN, -1);
2070 screen = DefaultScreenOfDisplay (display);
2072 screen_num = XScreenNumberOfScreen (screen);
2074 depth = DefaultDepth (display, screen_num);
2078 cmap = DefaultColormap (display, screen_num);
2080 for (plist = display_info_list; mplist_key (plist) != Mnil;
2081 plist = mplist_next (plist))
2083 disp_info = (MDisplayInfo *) mplist_value (plist);
2084 if (disp_info->display == display)
2088 if (mplist_key (plist) != Mnil)
2089 M17N_OBJECT_REF (disp_info);
2092 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
2093 disp_info->display = display;
2094 disp_info->auto_display = auto_display;
2095 disp_info->font_list = mplist ();
2096 find_modifier_bits (disp_info);
2097 mplist_add (display_info_list, Mt, disp_info);
2100 for (plist = device_list; mplist_key (plist) != Mnil;
2101 plist = mplist_next (plist))
2103 device = (MWDevice *) mplist_value (plist);
2104 if (device->display_info == disp_info
2105 && device->depth == depth
2106 && device->cmap == cmap
2107 && device->screen_num == screen_num)
2111 if (mplist_key (plist) != Mnil)
2112 M17N_OBJECT_REF (device);
2115 unsigned long valuemask = GCForeground;
2119 M17N_OBJECT (device, free_device, MERROR_WIN);
2120 device->display_info = disp_info;
2121 device->screen_num = screen_num;
2122 /* A drawable on which to create GCs. */
2123 device->drawable = XCreatePixmap (display,
2124 RootWindow (display, screen_num),
2126 device->depth = depth;
2127 device->cmap = cmap;
2128 pixels = DisplayHeight (display, screen_num);
2129 mm = DisplayHeightMM (display, screen_num);
2130 device->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
2131 device->realized_face_list = mplist ();
2132 device->realized_font_list = mplist ();
2133 mplist_add (device->realized_font_list, Mt, NULL);
2134 device->realized_fontset_list = mplist ();
2135 device->gc_list = mplist ();
2136 values.foreground = BlackPixel (display, screen_num);
2137 device->scratch_gc = XCreateGC (display, device->drawable,
2138 valuemask, &values);
2140 device->xft_draw = XftDrawCreate (display, device->drawable,
2141 DefaultVisual (display, screen_num),
2146 frame->device = device;
2147 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2148 frame->dpi = device->resy;
2149 frame->driver = &x_driver;
2150 frame->font_driver_list = mplist ();
2154 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2157 #endif /* HAVE_XFT2 */
2158 #ifdef HAVE_FREETYPE
2160 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2161 #endif /* HAVE_FREETYPE */
2162 if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list))
2163 mplist_push (frame->font_driver_list, Mx, &xfont_driver);
2165 frame->realized_font_list = device->realized_font_list;
2166 frame->realized_face_list = device->realized_face_list;
2167 frame->realized_fontset_list = device->realized_fontset_list;
2171 XtResource resources[] = {
2172 { XtNfont, XtCFont, XtRString, sizeof (String),
2173 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2174 { XtNforeground, XtCForeground, XtRString, sizeof (String),
2175 XtOffset (AppDataPtr, foreground), XtRString, "black" },
2176 { XtNbackground, XtCBackground, XtRString, sizeof (String),
2177 XtOffset (AppDataPtr, background), XtRString, "white" },
2178 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2179 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2182 XtGetApplicationResources (widget, &app_data,
2183 resources, XtNumber (resources), NULL, 0);
2184 frame->foreground = msymbol (app_data.foreground);
2185 frame->background = msymbol (app_data.background);
2186 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2190 app_data.font = DEFAULT_FONT;
2191 frame->foreground = msymbol ("black");
2192 frame->background = msymbol ("white");
2193 frame->videomode = Mnormal;
2196 if (strcmp (app_data.font, DEFAULT_FONT) != 0)
2198 XFontStruct *xfont = XLoadQueryFont (display, app_data.font);
2199 unsigned long value;
2204 font = mfont_parse_name (app_data.font, Mx);
2206 && XGetFontProperty (xfont, XA_FONT, &value)
2207 && (name = ((char *) XGetAtomName (display, (Atom) value))))
2208 font = mfont_parse_name (name, Mx);
2209 XFreeFont (display, xfont);
2213 font = mfont_parse_name (DEFAULT_FONT, Mx);
2214 else if (! font->size)
2216 face = mface_from_font (font);
2218 face->property[MFACE_FONTSET] = mfontset (NULL);
2219 face->property[MFACE_FOREGROUND] = frame->foreground;
2220 face->property[MFACE_BACKGROUND] = frame->background;
2221 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2222 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2223 face->property[MFACE_VIDEOMODE] = frame->videomode;
2224 mface_put_prop (face, Mhook_func,
2225 mface_get_prop (mface__default, Mhook_func));
2226 face->property[MFACE_RATIO] = (void *) 100;
2227 mplist_push (param, Mface, face);
2228 M17N_OBJECT_UNREF (face);
2230 #ifdef X_SET_ERROR_HANDLER
2231 XSetErrorHandler (x_error_handler);
2232 XSetIOErrorHandler (x_io_error_handler);
2239 /* XIM (X Input Method) handler */
2241 typedef struct MInputXIMMethodInfo
2247 } MInputXIMMethodInfo;
2249 typedef struct MInputXIMContextInfo
2253 MConverter *converter;
2254 } MInputXIMContextInfo;
2257 xim_open_im (MInputMethod *im)
2259 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2260 MLocale *saved, *this;
2261 char *save_modifier_list;
2263 MInputXIMMethodInfo *im_info;
2265 saved = mlocale_set (LC_CTYPE, NULL);
2266 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2268 /* The specified locale is not supported. */
2269 MERROR (MERROR_LOCALE, -1);
2270 if (mlocale_get_prop (this, Mcoding) == Mnil)
2272 /* Unable to decode the output of XIM. */
2273 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2274 MERROR (MERROR_LOCALE, -1);
2277 if (arg->modifier_list)
2278 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2280 save_modifier_list = XSetLocaleModifiers ("");
2281 if (! save_modifier_list)
2283 /* The specified locale is not supported by X. */
2284 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2285 MERROR (MERROR_LOCALE, -1);
2288 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2291 /* No input method is available in the current locale. */
2292 XSetLocaleModifiers (save_modifier_list);
2293 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2294 MERROR (MERROR_WIN, -1);
2297 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2298 im_info->display = arg->display;
2300 im_info->language = mlocale_get_prop (this, Mlanguage);
2301 im_info->coding = mlocale_get_prop (this, Mcoding);
2304 XSetLocaleModifiers (save_modifier_list);
2305 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2311 xim_close_im (MInputMethod *im)
2313 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2315 XCloseIM (im_info->xim);
2320 xim_create_ic (MInputContext *ic)
2322 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2323 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2324 MInputXIMContextInfo *ic_info;
2327 if (! arg->input_style)
2329 /* By default, use Root style. */
2330 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2331 arg->preedit_attrs = NULL;
2332 arg->status_attrs = NULL;
2335 if (! arg->preedit_attrs && ! arg->status_attrs)
2336 xic = XCreateIC (im_info->xim,
2337 XNInputStyle, arg->input_style,
2338 XNClientWindow, arg->client_win,
2339 XNFocusWindow, arg->focus_win,
2341 else if (arg->preedit_attrs && ! arg->status_attrs)
2342 xic = XCreateIC (im_info->xim,
2343 XNInputStyle, arg->input_style,
2344 XNClientWindow, arg->client_win,
2345 XNFocusWindow, arg->focus_win,
2346 XNPreeditAttributes, arg->preedit_attrs,
2348 else if (! arg->preedit_attrs && arg->status_attrs)
2349 xic = XCreateIC (im_info->xim,
2350 XNInputStyle, arg->input_style,
2351 XNClientWindow, arg->client_win,
2352 XNFocusWindow, arg->focus_win,
2353 XNStatusAttributes, arg->status_attrs,
2356 xic = XCreateIC (im_info->xim,
2357 XNInputStyle, arg->input_style,
2358 XNClientWindow, arg->client_win,
2359 XNFocusWindow, arg->focus_win,
2360 XNPreeditAttributes, arg->preedit_attrs,
2361 XNStatusAttributes, arg->status_attrs,
2364 MERROR (MERROR_WIN, -1);
2366 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2368 ic_info->win = arg->focus_win;
2369 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2375 xim_destroy_ic (MInputContext *ic)
2377 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2379 XDestroyIC (ic_info->xic);
2380 mconv_free_converter (ic_info->converter);
2386 xim_filter (MInputContext *ic, MSymbol key, void *event)
2388 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2390 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2395 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2397 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2398 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2399 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2405 buf = (char *) alloca (512);
2406 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2407 if (status == XBufferOverflow)
2409 buf = (char *) alloca (len);
2410 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2413 mtext_reset (ic->produced);
2417 mconv_reset_converter (ic_info->converter);
2418 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2419 mconv_decode (ic_info->converter, ic->produced);
2420 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2421 Mlanguage, (void *) im_info->language);
2422 mtext_cpy (mt, ic->produced);
2423 mtext_reset (ic->produced);
2431 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2435 /*** @addtogroup m17nInputMethodWin */
2440 @brief Input method driver for XIM.
2442 The driver #minput_xim_driver is for the foreign input method of
2443 name #Mxim. It uses XIM (X Input Methods) as a background input
2446 As the symbol #Mxim has property #Minput_driver whose value is
2447 a pointer to this driver, the input method of language #Mnil
2448 and name #Mxim uses this driver.
2450 Therefore, for such input methods, the driver dependent arguments
2451 to the functions whose name begin with minput_ must be as follows.
2453 The argument $ARG of the function minput_open_im () must be a
2454 pointer to the structure #MInputXIMArgIM. See the documentation
2455 of #MInputXIMArgIM for more details.
2457 The argument $ARG of the function minput_create_ic () must be a
2458 pointer to the structure #MInputXIMArgIC. See the documentation
2459 of #MInputXIMArgIC for more details.
2461 The argument $ARG of the function minput_filter () must be a
2462 pointer to the structure @c XEvent. The argument $KEY is ignored.
2464 The argument $ARG of the function minput_lookup () must be the
2465 same one as that of the function minput_filter (). The argument
2469 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2471 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ê¡¢
2472 XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
2474 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2475 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim
2476 ¤Ç¤¢¤ëÆþÎϥ᥽¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2478 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_
2479 ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2481 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM
2482 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò»²¾È¡£
2484 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC
2485 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ¤ò»²¾È¡£
2487 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent
2488 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2490 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2491 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì¤ë¡£ */
2493 MInputDriver minput_xim_driver =
2494 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2495 xim_filter, xim_lookup, NULL };