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
27 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
28 /*** @addtogroup m17nInternal
38 #include <X11/keysym.h>
39 #include <X11/Xlocale.h>
40 #include <X11/Xutil.h>
41 #include <X11/Xresource.h>
42 #include <X11/Xatom.h>
43 #include <X11/StringDefs.h>
44 #include <X11/Intrinsic.h>
47 #include <X11/Xft/Xft.h>
48 #include <fontconfig/fcfreetype.h>
49 #endif /* HAVE_XFT2 */
53 #include "m17n-misc.h"
55 #include "internal-gui.h"
62 typedef struct _MFontX MFontX;
66 /* Record a font of the smallest pixel size. */
68 /* Nth bit tells the existence of a font of size N + 5. So this is
69 for 5..36 pixel size fonts. Usually this covers all sizes. */
70 unsigned int size5_36;
71 /* Fonts of (size < 5 || size > 36) are listed here (except for a
72 scalable whose size is 0). */
76 /* S must satisfy the condition (S >= 5 && S < 36). */
78 #define SET_SIZE(FONTX, S) ((FONTX)->size5_36 |= (1 << ((S) - 5)))
80 #define HAVE_SIZE(FONTX, S) ((FONTX)->size5_36 & (1 << ((S) - 5)))
84 /* Common header for the m17n object. */
89 /* If nonzero, <display> is opened by this library. Thus it should
90 be closed on freeing this structure. */
93 /** List of available X-core fonts on the display. Keys are
94 registries and values are plists whose keys are families and
95 values are pointers to MFontX. */
98 /** Nonzero means that <font_list> already contains all available
99 fonts on the display. */
100 int all_fonts_scaned;
102 /** Modifier bit masks of the display. */
109 /* Anchor of the chain of MDisplayInfo objects. */
110 static MPlist *display_info_list;
113 /* Color value and the corresponding GC. */
116 unsigned int rgb; /* (red << 16) | (green << 8) | blue */
123 GC_NORMAL = GC_INVERSE + 7,
136 /* The first 8 elements are indexed by an intensity for
137 anti-aliasing. The 2nd to 7th are created on demand. */
140 XftColor xft_color_fore, xft_color_back;
146 /* Common header for the m17n object. */
149 MDisplayInfo *display_info;
167 /** List of pointers to realized faces on the frame. */
168 MPlist *realized_face_list;
170 /* List of single element whose value is a root of chain of realized
172 MPlist *realized_font_list;
174 /** List of pointers to realized fontsets on the frame. */
175 MPlist *realized_fontset_list;
177 /** List of XColors vs GCs on the frame. */
181 static MPlist *device_list;
183 static MSymbol M_iso8859_1, M_iso10646_1;
185 #define FRAME_DEVICE(frame) ((MWDevice *) (frame)->device)
186 #define FRAME_DISPLAY(frame) (FRAME_DEVICE (frame)->display_info->display)
187 #define FRAME_SCREEN(frame) (FRAME_DEVICE (frame)->screen_num)
188 #define FRAME_CMAP(frame) (FRAME_DEVICE (frame)->cmap)
189 #define FRAME_VISUAL(frame) DefaultVisual (FRAME_DISPLAY (frame), \
190 FRAME_SCREEN (frame))
192 #define DEFAULT_FONT "-*-*-medium-r-normal--13-*-*-*-c-*-iso8859-1"
199 Boolean reverse_video;
200 } AppData, *AppDataPtr;
203 free_display_info (void *object)
205 MDisplayInfo *disp_info = (MDisplayInfo *) object;
208 MPLIST_DO (plist, disp_info->font_list)
210 MPLIST_DO (pl, MPLIST_VAL (plist))
212 MFontX *fontx, *next;
214 for (fontx = MPLIST_VAL (pl); fontx; fontx = next)
220 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
222 M17N_OBJECT_UNREF (disp_info->font_list);
224 if (disp_info->auto_display)
225 XCloseDisplay (disp_info->display);
231 free_device (void *object)
233 MWDevice *device = object;
236 for (plist = device->realized_fontset_list;
237 mplist_key (plist) != Mnil; plist = mplist_next (plist))
238 mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist));
239 M17N_OBJECT_UNREF (device->realized_fontset_list);
241 if (MPLIST_VAL (device->realized_font_list))
242 mfont__free_realized (MPLIST_VAL (device->realized_font_list));
243 M17N_OBJECT_UNREF (device->realized_font_list);
245 MPLIST_DO (plist, device->realized_face_list)
247 MRealizedFace *rface = MPLIST_VAL (plist);
250 mface__free_realized (rface);
252 M17N_OBJECT_UNREF (device->realized_face_list);
254 MPLIST_DO (plist, device->gc_list)
256 XFreeGC (device->display_info->display,
257 ((RGB_GC *) MPLIST_VAL (plist))->gc);
258 free (MPLIST_VAL (plist));
260 M17N_OBJECT_UNREF (device->gc_list);
261 XFreeGC (device->display_info->display, device->scratch_gc);
264 XftDrawDestroy (device->xft_draw);
267 XFreePixmap (device->display_info->display, device->drawable);
268 M17N_OBJECT_UNREF (device->display_info);
274 find_modifier_bits (MDisplayInfo *disp_info)
276 Display *display = disp_info->display;
277 XModifierKeymap *mods;
278 KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L);
279 KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R);
280 KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L);
281 KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R);
282 KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
283 KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
284 KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
285 KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
288 mods = XGetModifierMapping (display);
289 /* We skip the first three sets for Shift, Lock, and Control. The
290 remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
291 for (i = 3; i < 8; i++)
292 for (j = 0; j < mods->max_keypermod; j++)
294 KeyCode code = mods->modifiermap[i * mods->max_keypermod + j];
298 if (code == meta_l || code == meta_r)
299 disp_info->meta_mask |= (1 << i);
300 else if (code == alt_l || code == alt_r)
301 disp_info->alt_mask |= (1 << i);
302 else if (code == super_l || code == super_r)
303 disp_info->super_mask |= (1 << i);
304 else if (code == hyper_l || code == hyper_r)
305 disp_info->hyper_mask |= (1 << i);
308 /* If meta keys are not in any modifier, use alt keys as meta
310 if (! disp_info->meta_mask)
312 disp_info->meta_mask = disp_info->alt_mask;
313 disp_info->alt_mask = 0;
315 /* If both meta and alt are assigned to the same modifier, give meta
317 if (disp_info->meta_mask & disp_info->alt_mask)
318 disp_info->alt_mask &= ~disp_info->meta_mask;
320 XFreeModifiermap (mods);
324 get_rgb_gc (MWDevice *device, XColor *xcolor)
326 int rgb = (((xcolor->red >> 8) << 16) | ((xcolor->green >> 8) << 8)
327 | (xcolor->blue >> 8));
330 unsigned long valuemask = GCForeground;
333 MPLIST_DO (plist, device->gc_list)
335 rgb_gc = MPLIST_VAL (plist);
337 if (rgb_gc->rgb == rgb)
339 if (rgb_gc->rgb > rgb)
343 if (! XAllocColor (device->display_info->display, device->cmap, xcolor))
346 rgb_gc = malloc (sizeof (RGB_GC));
348 values.foreground = xcolor->pixel;
349 rgb_gc->gc = XCreateGC (device->display_info->display,
350 device->drawable, valuemask, &values);
351 mplist_push (plist, Mt, rgb_gc);
356 get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret)
358 MWDevice *device = FRAME_DEVICE (frame);
366 color = for_foreground ? frame->foreground : frame->background;
368 if (! XParseColor (FRAME_DISPLAY (frame), device->cmap,
369 msymbol_name (color), &xcolor))
371 rgb_gc = get_rgb_gc (device, &xcolor);
375 *rgb_ret = rgb_gc->rgb;
380 GCInfo *info = frame->rface->info;
385 rgb = info->rgb_fore, gc = info->gc[GC_NORMAL];
387 rgb = info->rgb_back, gc = info->gc[GC_INVERSE];
395 get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity)
397 int rgb_fore, rgb_back;
402 if (info->gc[intensity])
403 return info->gc[intensity];
405 rgb_fore = info->rgb_fore, rgb_back = info->rgb_back;
406 xcolor.red = ((((rgb_fore & 0xFF0000) >> 16) * intensity
407 + ((rgb_back & 0xFF0000) >> 16) * (7 - intensity)) / 7) << 8;
408 xcolor.green = ((((rgb_fore & 0xFF00) >> 8) * intensity
409 + ((rgb_back & 0xFF00) >> 8) * (7 - intensity)) / 7) << 8;
410 xcolor.blue = (((rgb_fore & 0xFF) * intensity
411 + (rgb_back & 0xFF) * (7 - intensity)) / 7) << 8;
412 rgb_gc = get_rgb_gc (device, &xcolor);
416 gc =get_gc_for_anti_alias (device, info,
417 intensity < 4 ? intensity - 1 : intensity + 1);
418 return (info->gc[intensity] = gc);
422 set_region (MFrame *frame, GC gc, MDrawRegion region)
424 unsigned long valuemask = GCForeground;
426 XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
427 FRAME_DEVICE (frame)->scratch_gc);
428 XSetRegion (FRAME_DISPLAY (frame), FRAME_DEVICE (frame)->scratch_gc, region);
429 return FRAME_DEVICE (frame)->scratch_gc;
433 /** X font handler */
435 static MFont *xfont_select (MFrame *, MFont *, int);
436 static MRealizedFont *xfont_open (MFrame *, MFont *, MFont *, MRealizedFont *);
437 static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int);
438 static int xfont_has_char (MFrame *, MFont *, MFont *, int, unsigned);
439 static unsigned xfont_encode_char (MFrame *, MFont *, MFont *, unsigned);
440 static void xfont_render (MDrawWindow, int, int, MGlyphString *,
441 MGlyph *, MGlyph *, int, MDrawRegion);
442 static int xfont_list (MFrame *, MPlist *, MFont *, int);
445 static MFontDriver xfont_driver =
446 { xfont_select, xfont_open,
447 xfont_find_metric, xfont_has_char, xfont_encode_char,
448 xfont_render, xfont_list };
451 font_compare (const void *p1, const void *p2)
453 return strcmp (*(char **) p1, *(char **) p2);
457 xfont_registry_list (MFrame *frame, MSymbol registry)
459 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
460 MPlist *font_list = disp_info->font_list;
463 char **font_names, **names;
469 plist = mplist_get (font_list, registry);
473 mplist_add (font_list, registry, plist);
474 sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", msymbol_name (registry));
475 font_names = XListFonts (disp_info->display, pattern, 0x8000, &nfonts);
479 char *reg_name = msymbol_name (registry);
481 for_full_width = (strncmp (reg_name, "jis", 3) == 0
482 || strncmp (reg_name, "gb", 2) == 0
483 || strncmp (reg_name, "big5", 4) == 0
484 || strncmp (reg_name, "ksc", 3) == 0);
486 names = alloca (sizeof (char *) * nfonts);
487 memcpy (names, font_names, sizeof (char *) * nfonts);
488 qsort (names, nfonts, sizeof (char *), font_compare);
490 for (i = 0, p = NULL; i < nfonts; i++)
491 if (mfont__parse_name_into_font (names[i], Mx, &font) == 0
492 && (font.size >= 50 || font.property[MFONT_RESY] == 0))
494 MSymbol family = FONT_PROPERTY (&font, MFONT_FAMILY);
495 MFontX *fontx, *fontx2;
503 if (p && MPLIST_KEY (p) != family)
504 p = mplist_find_by_key (plist, family);
506 p = mplist_push (plist, family, NULL);
508 /* Calculate how many bytes to compare to detect fonts of the
510 for (base_end = names[i], fields = 0; *base_end; base_end++)
512 && ++fields == 7 /* PIXEL_SIZE */)
514 base_len = base_end - names[i] + 1;
516 size = smallest = font.size / 10;
517 sizes[nsizes++] = size;
518 for (j = i + 1; j < nfonts && ! strncmp (names[i], names[j], base_len);
520 if (mfont__parse_name_into_font (names[j], Mx, &font) == 0
521 && (font.size >= 50 || font.property[MFONT_RESY] == 0))
523 size = font.size / 10;
527 sizes[nsizes++] = size;
530 font.for_full_width = for_full_width;
531 font.type = MFONT_TYPE_OBJECT;
532 font.source = MFONT_SOURCE_X;
533 MSTRUCT_CALLOC (fontx, MERROR_WIN);
535 fontx->core.size = smallest * 10;
536 fontx->next = MPLIST_VAL (p);
537 MPLIST_VAL (p) = fontx;
539 for (j = 0; j < nsizes; j++)
543 if (sizes[j] != smallest)
544 SET_SIZE (fontx, sizes[j]);
548 MSTRUCT_CALLOC (fontx2, MERROR_WIN);
550 fontx2->core.size = sizes[j] * 10;
551 fontx2->next = MPLIST_VAL (p);
552 MPLIST_VAL (p) = fontx2;
556 XFreeFontNames (font_names);
561 xfont_list_all (MFrame *frame)
563 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
564 MPlist *font_encoding_list, *p;
566 if (disp_info->all_fonts_scaned)
568 disp_info->all_fonts_scaned = 1;
569 font_encoding_list = mfont__encoding_list ();
570 if (! font_encoding_list)
572 MPLIST_DO (p, font_encoding_list)
573 xfont_registry_list (frame, MPLIST_KEY (p));
583 /* The X font driver function SELECT. */
586 xfont_select (MFrame *frame, MFont *font, int limited_size)
588 MPlist *plist = mplist (), *pl;
589 int num = xfont_list (frame, plist, font, 0);
593 MPLIST_DO (pl, plist)
595 font = MPLIST_VAL (pl);
596 if (limited_size == 0
598 || font->size <= limited_size)
604 M17N_OBJECT_UNREF (plist);
608 /* The X font driver function CLOSE. */
611 close_xfont (void *object)
613 MRealizedFontX *x_rfont = object;
615 XFreeFont (x_rfont->display, x_rfont->xfont);
619 /* The X font driver function OPEN. */
621 static MRealizedFont *
622 xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
624 int size = spec->size;
625 MRealizedFontX *x_rfont;
627 Display *display = FRAME_DISPLAY (frame);
629 int mdebug_mask = MDEBUG_FONT;
634 for (; rfont; rfont = rfont->next)
635 if (rfont->font == font && rfont->spec.size == size)
641 /* This never fail to generate a valid fontname. */
642 name = mfont_unparse_name (&this, Mx);
643 xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
646 MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
648 font->type = MFONT_TYPE_FAILURE;
651 MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
653 M17N_OBJECT (x_rfont, close_xfont, MERROR_FONT_X);
654 x_rfont->display = display;
655 x_rfont->xfont = xfont;
656 MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
658 rfont->spec.type = MFONT_TYPE_REALIZED;
659 rfont->spec.source = MFONT_SOURCE_X;
660 rfont->frame = frame;
662 rfont->driver = &xfont_driver;
663 rfont->info = x_rfont;
664 rfont->ascent = xfont->ascent;
665 rfont->descent = xfont->descent;
666 rfont->max_advance = xfont->max_bounds.width;
667 rfont->fontp = xfont;
668 rfont->next = MPLIST_VAL (frame->realized_font_list);
669 MPLIST_VAL (frame->realized_font_list) = rfont;
674 /* The X font driver function FIND_METRIC. */
677 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
680 XFontStruct *xfont = rfont->fontp;
681 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
683 for (; g != gend; g++)
685 if (g->code == MCHAR_INVALID_CODE)
687 g->lbearing = xfont->max_bounds.lbearing;
688 g->rbearing = xfont->max_bounds.rbearing;
689 g->width = xfont->max_bounds.width;
690 g->ascent = xfont->ascent;
691 g->descent = xfont->descent;
695 int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
696 XCharStruct *pcm = NULL;
698 if (xfont->per_char != NULL)
700 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
703 && byte2 >= xfont->min_char_or_byte2
704 && byte2 <= xfont->max_char_or_byte2)
705 pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
709 if (byte1 >= xfont->min_byte1
710 && byte1 <= xfont->max_byte1
711 && byte2 >= xfont->min_char_or_byte2
712 && byte2 <= xfont->max_char_or_byte2)
714 pcm = (xfont->per_char
715 + ((xfont->max_char_or_byte2
716 - xfont->min_char_or_byte2 + 1)
717 * (byte1 - xfont->min_byte1))
718 + (byte2 - xfont->min_char_or_byte2));
725 g->lbearing = pcm->lbearing;
726 g->rbearing = pcm->rbearing;
727 g->width = pcm->width;
728 g->ascent = pcm->ascent;
729 g->descent = pcm->descent;
733 /* If the per_char pointer is null, all glyphs between
734 the first and last character indexes inclusive have
735 the same information, as given by both min_bounds and
738 g->rbearing = xfont->max_bounds.width;
739 g->width = xfont->max_bounds.width;
740 g->ascent = xfont->ascent;
741 g->descent = xfont->descent;
749 xfont_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
751 return (xfont_encode_char (frame, font, spec, code) != MCHAR_INVALID_CODE);
754 /* The X font driver function GET_GLYPH_ID. */
757 xfont_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
759 MRealizedFont *rfont;
761 unsigned min_byte1, max_byte1, min_byte2, max_byte2;
764 if (font->type == MFONT_TYPE_REALIZED)
765 rfont = (MRealizedFont *) font;
766 else if (font->type == MFONT_TYPE_OBJECT)
768 int size = spec->size;
770 for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
772 if (rfont->font == font && rfont->spec.size == size)
776 rfont = xfont_open (frame, font, spec, NULL);
778 return MCHAR_INVALID_CODE;
782 MFATAL (MERROR_FONT_X);
783 xfont = rfont->fontp;
784 all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
785 min_byte1 = xfont->min_byte1;
786 max_byte1 = xfont->max_byte1;
787 min_byte2 = xfont->min_char_or_byte2;
788 max_byte2 = xfont->max_char_or_byte2;
790 if (min_byte1 == 0 && max_byte1 == 0)
794 if (code < min_byte2 || code > max_byte2)
795 return MCHAR_INVALID_CODE;
798 pcm = xfont->per_char + (code - min_byte2);
799 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
800 ? code : MCHAR_INVALID_CODE);
804 unsigned byte1 = code >> 8, byte2 = code & 0xFF;
807 if (byte1 < min_byte1 || byte1 > max_byte1
808 || byte2 < min_byte2 || byte2 > max_byte2)
809 return MCHAR_INVALID_CODE;
813 pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
814 + (byte2 - min_byte2));
815 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
816 ? code : MCHAR_INVALID_CODE);
820 /* The X font driver function RENDER. */
823 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
824 MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
826 MRealizedFace *rface = from->rface;
827 Display *display = FRAME_DISPLAY (rface->frame);
829 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
837 gc = set_region (rface->frame, gc, region);
838 XSetFont (display, gc, ((XFontStruct *) rface->rfont->fontp)->fid);
839 code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
840 for (i = 0, g = from; g < to; i++, g++)
842 code[i].byte1 = g->code >> 8;
843 code[i].byte2 = g->code & 0xFF;
849 if (g->type == GLYPH_PAD)
851 else if (g->type == GLYPH_SPACE)
852 for (; g < to && g->type == GLYPH_SPACE; g++)
854 else if (! g->rface->rfont)
856 if ((g->c >= 0x200B && g->c <= 0x200F)
857 || (g->c >= 0x202A && g->c <= 0x202E))
861 /* As a font is not found for this character, draw an
863 int box_width = g->width;
864 int box_height = gstring->ascent + gstring->descent;
870 XDrawRectangle (display, (Window) win, gc,
871 x, y - gstring->ascent, box_width, box_height);
875 else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
877 XDrawString16 (display, (Window) win, gc,
878 x + g->xoff, y + g->yoff, code + (g - from), 1);
885 int code_idx = g - from;
888 g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
891 XDrawString16 (display, (Window) win, gc, orig_x, y,
898 xfont_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum)
900 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
901 MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil;
902 MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil;
903 int size = font ? font->size : 0;
906 int mdebug_mask = MDEBUG_FONT;
908 MDEBUG_PRINT2 (" [X-FONT] listing %s-%s...",
909 family ? msymbol_name (family) : "*",
910 registry ? msymbol_name (registry) : "*");
912 if (registry == Mnil)
913 xfont_list_all (frame);
915 xfont_registry_list (frame, registry);
917 MPLIST_DO (pl, disp_info->font_list)
919 if (registry != Mnil && registry != MPLIST_KEY (pl))
921 MPLIST_DO (p, MPLIST_VAL (pl))
925 if (family != Mnil && family != MPLIST_KEY (p))
927 for (fontx = MPLIST_VAL (p); fontx; fontx = fontx->next)
929 || (mfont__match_p (&fontx->core, font, MFONT_REGISTRY)))
931 if (fontx->core.size == size
932 || fontx->core.size == 0)
934 mplist_push (plist, MPLIST_KEY (p), fontx);
938 || (size <= 360 && HAVE_SIZE (fontx, (size / 10))))
940 unsigned size5_36 = fontx->size5_36;
945 for (i = fontx->core.size / 10; i <= 36; i++)
946 if (size5_36 & (1 << (i - 5)))
948 MSTRUCT_CALLOC (fontx2, MERROR_WIN);
949 fontx2->core = fontx->core;
950 fontx2->core.size = i * 10;
951 fontx2->next = fontx->next;
952 fontx->next = fontx2;
954 if ((size == 0 || size == fontx->core.size)
955 && (maxnum == 0 || num < maxnum))
957 mplist_push (plist, MPLIST_KEY (p), fontx);
962 if (maxnum > 0 && maxnum == num)
965 if (maxnum > 0 && maxnum == num)
968 if (maxnum > 0 && maxnum == num)
972 MDEBUG_PRINT1 (" %d found\n", num);
988 /* Pointer to MRealizedFontFT */
992 static MRealizedFont *xft_open (MFrame *frame, MFont *font, MFont *spec,
994 static int xft_has_char (MFrame *frame, MFont *font, MFont *spec,
995 int c, unsigned code);
996 static unsigned xft_encode_char (MFrame *frame, MFont *font, MFont *spec,
998 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
999 static void xft_render (MDrawWindow, int, int, MGlyphString *,
1000 MGlyph *, MGlyph *, int, MDrawRegion);
1002 MFontDriver xft_driver =
1004 xft_find_metric, xft_has_char, xft_encode_char, xft_render, NULL };
1007 close_xft (void *object)
1009 MRealizedFontXft *rfont_xft = object;
1011 if (rfont_xft->font_aa)
1012 XftFontClose (rfont_xft->display, rfont_xft->font_aa);
1013 if (rfont_xft->font_no_aa)
1014 XftFontClose (rfont_xft->display, rfont_xft->font_no_aa);
1015 M17N_OBJECT_UNREF (rfont_xft->info);
1021 xft_open_font (Display *display, MSymbol file, double size,
1027 pattern = FcPatternCreate ();
1028 FcPatternAddString (pattern, FC_FILE, (FcChar8 *) msymbol_name (file));
1029 FcPatternAddDouble (pattern, FC_PIXEL_SIZE, size);
1030 FcPatternAddBool (pattern, FC_ANTIALIAS, anti_alias);
1031 font = XftFontOpenPattern (display, pattern);
1036 static MRealizedFont *
1037 xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
1039 Display *display = FRAME_DISPLAY (frame);
1040 int reg = spec->property[MFONT_REGISTRY];
1042 MRealizedFontXft *rfont_xft;
1043 FcBool anti_alias = FRAME_DEVICE (frame)->depth > 1 ? FcTrue : FcFalse;
1044 double size = font->size ? font->size : spec->size;
1049 MRealizedFont *save = NULL;
1051 for (; rfont; rfont = rfont->next)
1052 if (rfont->font == font
1053 && (rfont->font->size ? rfont->font->size == size
1054 : rfont->spec.size == size)
1055 && rfont->spec.property[MFONT_REGISTRY] == reg)
1059 if (rfont->driver == &xft_driver)
1064 rfont = (mfont__ft_driver.open) (frame, font, spec, rfont);
1067 spec = &rfont->spec;
1068 ft_face = rfont->fontp;
1069 xft_font = xft_open_font (display, font->file, size / 10, anti_alias);
1072 M17N_OBJECT (rfont_xft, close_xft, MERROR_WIN);
1073 rfont_xft->display = display;
1074 if (anti_alias == FcTrue)
1075 rfont_xft->font_aa = xft_font;
1077 rfont_xft->font_no_aa = xft_font;
1078 rfont_xft->ft_face = ft_face;
1079 rfont_xft->info = rfont->info;
1080 M17N_OBJECT_REF (rfont->info);
1081 MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
1082 rfont->spec = *spec;
1083 rfont->frame = frame;
1085 rfont->driver = &xft_driver;
1086 rfont->info = rfont_xft;
1087 rfont->ascent = ft_face->size->metrics.ascender >> 6;
1088 rfont->descent = - ft_face->size->metrics.descender >> 6;
1089 rfont->max_advance = ft_face->size->metrics.max_advance >> 6;
1090 rfont->fontp = xft_font;
1091 rfont->next = MPLIST_VAL (frame->realized_font_list);
1092 MPLIST_VAL (frame->realized_font_list) = rfont;
1097 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1100 Display *display = FRAME_DISPLAY (rfont->frame);
1101 XftFont *xft_font = rfont->fontp;
1102 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1104 for (; g != gend; g++)
1106 if (g->code == MCHAR_INVALID_CODE)
1109 g->rbearing = xft_font->max_advance_width;
1110 g->width = g->rbearing;
1111 g->ascent = xft_font->ascent;
1112 g->descent = xft_font->descent;
1118 XftGlyphExtents (display, xft_font, &g->code, 1, &extents);
1119 g->lbearing = - extents.x;
1120 g->rbearing = extents.width - extents.x;
1121 g->width = extents.xOff;
1122 g->ascent = extents.y;
1123 g->descent = extents.height - extents.y;
1129 xft_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
1133 if (font->type == MFONT_TYPE_REALIZED)
1135 MRealizedFont *rfont = (MRealizedFont *) font;
1136 MRealizedFontXft *rfont_xft = rfont->info;
1138 rfont->info = rfont_xft->info;
1139 result = mfont__ft_driver.has_char (frame, font, spec, c, code);
1140 rfont->info = rfont_xft;
1143 result = mfont__ft_driver.has_char (frame, font, spec, c, code);
1148 xft_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
1150 if (font->type == MFONT_TYPE_REALIZED)
1152 MRealizedFont *rfont = (MRealizedFont *) font;
1153 MRealizedFontXft *rfont_xft = rfont->info;
1155 rfont->info = rfont_xft->info;
1156 code = mfont__ft_driver.encode_char (frame, font, spec, code);
1157 rfont->info = rfont_xft;
1160 code = mfont__ft_driver.encode_char (frame, font, spec, code);
1165 xft_render (MDrawWindow win, int x, int y,
1166 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1167 int reverse, MDrawRegion region)
1169 MRealizedFace *rface = from->rface;
1170 MFrame *frame = rface->frame;
1171 Display *display = FRAME_DISPLAY (frame);
1172 MRealizedFont *rfont = rface->rfont;
1173 MRealizedFontXft *rfont_xft = rfont->info;
1174 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1175 XftColor *xft_color = (! reverse
1176 ? &((GCInfo *) rface->info)->xft_color_fore
1177 : &((GCInfo *) rface->info)->xft_color_back);
1178 int anti_alias = (gstring->control.anti_alias
1179 && FRAME_DEVICE (frame)->depth > 1);
1191 if (rfont_xft->font_aa)
1192 xft_font = rfont_xft->font_aa;
1195 double size = rfont->spec.size;
1197 xft_font = xft_open_font (display, rfont->spec.file, size / 10,
1200 rfont_xft->font_aa = xft_font;
1202 xft_font = rfont->fontp;
1207 if (rfont_xft->font_no_aa)
1208 xft_font = rfont_xft->font_no_aa;
1211 double size = rfont->spec.size;
1213 xft_font = xft_open_font (display, rfont->spec.file, size / 10,
1216 rfont_xft->font_no_aa = xft_font;
1218 xft_font = rfont->fontp;
1222 XftDrawChange (xft_draw, (Drawable) win);
1223 XftDrawSetClip (xft_draw, (Region) region);
1225 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1226 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1228 if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1229 glyphs[nglyphs++] = g->code;
1233 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1234 last_x, y, glyphs, nglyphs);
1236 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1237 x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1238 last_x = x + g->width;
1242 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1245 #endif /* HAVE_XFT2 */
1248 /* Functions for the device driver. */
1251 mwin__close_device (MFrame *frame)
1253 MWDevice *device = FRAME_DEVICE (frame);
1255 M17N_OBJECT_UNREF (device);
1259 mwin__device_get_prop (MFrame *frame, MSymbol key)
1261 MWDevice *device = FRAME_DEVICE (frame);
1263 if (key == Mdisplay)
1264 return (void *) device->display_info->display;
1266 return (void *) ScreenOfDisplay(device->display_info->display,
1267 device->screen_num);
1268 if (key == Mcolormap)
1269 return (void *) device->cmap;
1271 return (void *) device->depth;
1276 mwin__realize_face (MRealizedFace *rface)
1279 MSymbol foreground, background, videomode;
1280 MFaceHLineProp *hline;
1284 if (rface != rface->ascii_rface)
1286 rface->info = rface->ascii_rface->info;
1290 frame = rface->frame;
1291 MSTRUCT_CALLOC (info, MERROR_WIN);
1293 foreground = rface->face.property[MFACE_FOREGROUND];
1294 background = rface->face.property[MFACE_BACKGROUND];
1295 videomode = rface->face.property[MFACE_VIDEOMODE];
1297 videomode = frame->videomode;
1298 if (videomode != Mreverse)
1300 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1301 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1305 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1306 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1309 if (foreground == Mnil)
1310 foreground = frame->foreground;
1311 if (background == Mnil)
1312 background = frame->background;
1313 if (videomode == Mreverse)
1315 MSymbol temp = foreground;
1316 foreground = background;
1319 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1320 FRAME_VISUAL (frame),
1322 MSYMBOL_NAME (foreground),
1323 &info->xft_color_fore))
1325 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1326 FRAME_VISUAL (frame),
1328 MSYMBOL_NAME (background),
1329 &info->xft_color_back))
1331 #endif /* HAVE_XFT2 */
1333 hline = rface->hline;
1337 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1339 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1346 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1348 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1350 if (box->color_left && box->color_left != box->color_top)
1351 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1353 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1355 if (box->color_bottom && box->color_bottom != box->color_top)
1356 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1358 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1360 if (box->color_right && box->color_right != box->color_bottom)
1361 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1363 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1371 mwin__free_realized_face (MRealizedFace *rface)
1373 if (rface == rface->ascii_rface)
1379 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1381 int x, int y, int width, int height, MDrawRegion region)
1383 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1386 gc = set_region (frame, gc, region);
1388 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1389 x, y, width, height);
1394 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1395 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1396 int reverse, MDrawRegion region)
1398 MRealizedFace *rface = from->rface;
1399 Display *display = FRAME_DISPLAY (rface->frame);
1400 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1406 gc = set_region (rface->frame, gc, region);
1407 for (; from < to; from++)
1409 XDrawRectangle (display, (Window) win, gc,
1410 x, y - gstring->ascent + 1, from->width - 1,
1411 gstring->ascent + gstring->descent - 2);
1418 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1419 MRealizedFace *rface, int reverse,
1420 int x, int y, int width, MDrawRegion region)
1422 enum MFaceHLineType type = rface->hline->type;
1423 GCInfo *info = rface->info;
1424 GC gc = gc = info->gc[GC_HLINE];
1427 y = (type == MFACE_HLINE_BOTTOM
1428 ? y + gstring->text_descent - rface->hline->width
1429 : type == MFACE_HLINE_UNDER
1431 : type == MFACE_HLINE_STRIKE_THROUGH
1432 ? y - ((gstring->ascent + gstring->descent) / 2)
1433 : y - gstring->text_ascent);
1435 gc = set_region (frame, gc, region);
1437 for (i = 0; i < rface->hline->width; i++)
1438 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1439 x, y + i, x + width - 1, y + i);
1444 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1445 MGlyph *g, int x, int y, int width, MDrawRegion region)
1447 Display *display = FRAME_DISPLAY (frame);
1448 MRealizedFace *rface = g->rface;
1449 MFaceBoxProp *box = rface->box;
1450 GCInfo *info = rface->info;
1451 GC gc_top, gc_left, gc_right, gc_btm;
1455 y0 = y - (gstring->text_ascent
1456 + rface->box->inner_vmargin + rface->box->width);
1457 y1 = y + (gstring->text_descent
1458 + rface->box->inner_vmargin + rface->box->width - 1);
1460 gc_top = info->gc[GC_BOX_TOP];
1462 gc_top = set_region (frame, gc_top, region);
1463 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1466 gc_btm = info->gc[GC_BOX_BOTTOM];
1468 if (g->type == GLYPH_BOX)
1472 if (g->left_padding)
1473 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1475 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1477 /* Draw the top side. */
1478 for (i = 0; i < box->width; i++)
1479 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1481 /* Draw the bottom side. */
1482 if (region && gc_btm != gc_top)
1483 gc_btm = set_region (frame, gc_btm, region);
1484 for (i = 0; i < box->width; i++)
1485 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1487 if (g->left_padding > 0)
1489 /* Draw the left side. */
1490 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1494 gc_left = info->gc[GC_BOX_LEFT];
1496 gc_left = set_region (frame, gc_left, region);
1498 for (i = 0; i < rface->box->width; i++)
1499 XDrawLine (display, (Window) win, gc_left,
1500 x0 + i, y0 + i, x0 + i, y1 - i);
1504 /* Draw the right side. */
1505 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1509 gc_right = info->gc[GC_BOX_RIGHT];
1511 gc_right = set_region (frame, gc_right, region);
1513 for (i = 0; i < rface->box->width; i++)
1514 XDrawLine (display, (Window) win, gc_right,
1515 x1 - i, y0 + i, x1 - i, y1 - i);
1520 /* Draw the top side. */
1521 for (i = 0; i < box->width; i++)
1522 XDrawLine (display, (Window) win, gc_top,
1523 x, y0 + i, x + width - 1, y0 + i);
1525 /* Draw the bottom side. */
1526 if (region && gc_btm != gc_top)
1527 gc_btm = set_region (frame, gc_btm, region);
1528 for (i = 0; i < box->width; i++)
1529 XDrawLine (display, (Window) win, gc_btm,
1530 x, y1 - i, x + width - 1, y1 - i);
1537 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1538 int reverse, int x, int y,
1539 int width, int height, int row_bytes, unsigned char *bmp,
1542 Display *display = FRAME_DISPLAY (frame);
1544 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1547 gc = set_region (frame, gc, region);
1549 for (i = 0; i < height; i++, bmp += row_bytes)
1550 for (j = 0; j < width; j++)
1551 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1552 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1557 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1558 int intensity, MDrawPoint *points, int num,
1561 GCInfo *info = rface->info;
1564 if (! (gc = info->gc[intensity]))
1565 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1568 gc = set_region (frame, gc, region);
1570 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1571 (XPoint *) points, num, CoordModeOrigin);
1576 mwin__region_from_rect (MDrawMetric *rect)
1578 MDrawRegion region1 = XCreateRegion ();
1579 MDrawRegion region2 = XCreateRegion ();
1584 xrect.width = rect->width;
1585 xrect.height = rect->height;
1586 XUnionRectWithRegion (&xrect, region1, region2);
1587 XDestroyRegion (region1);
1592 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1594 MDrawRegion region1 = XCreateRegion ();
1599 xrect.width = rect->width;
1600 xrect.height = rect->height;
1602 XUnionRegion (region, region, region1);
1603 XUnionRectWithRegion (&xrect, region1, region);
1604 XDestroyRegion (region1);
1608 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1610 MDrawRegion region = XCreateRegion ();
1612 XUnionRegion (region1, region1, region);
1613 XIntersectRegion (region, region2, region1);
1614 XDestroyRegion (region);
1618 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1620 MDrawRegion region1 = XCreateRegion ();
1625 xrect.width = rect->width;
1626 xrect.height = rect->height;
1627 XUnionRectWithRegion (&xrect, region1, region);
1628 XDestroyRegion (region1);
1632 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1636 XClipBox (region, &xrect);
1639 rect->width = xrect.width;
1640 rect->height = xrect.height;
1644 mwin__free_region (MDrawRegion region)
1646 XDestroyRegion (region);
1650 mwin__dump_region (MDrawRegion region)
1653 XClipBox (region, &rect);
1654 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1659 mwin__create_window (MFrame *frame, MDrawWindow parent)
1661 Display *display = FRAME_DISPLAY (frame);
1663 XWMHints wm_hints = { InputHint, False };
1664 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1665 XSetWindowAttributes set_attrs;
1668 GCInfo *info = frame->rface->info;
1671 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1672 mask = GCForeground;
1673 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1674 set_attrs.background_pixel = values.foreground;
1675 set_attrs.backing_store = Always;
1676 set_attrs.override_redirect = True;
1677 set_attrs.save_under = True;
1678 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1679 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1680 CopyFromParent, InputOutput, CopyFromParent,
1682 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1683 NULL, &wm_hints, &class_hints);
1684 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1685 return (MDrawWindow) win;
1689 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1691 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1696 mwin__event_window (void *event)
1698 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1702 mwin__print_event (void *arg, char *win_name)
1705 XEvent *event = (XEvent *) arg;
1707 switch (event->xany.type)
1709 case 2: event_name = "KeyPress"; break;
1710 case 3: event_name = "KeyRelease"; break;
1711 case 4: event_name = "ButtonPress"; break;
1712 case 5: event_name = "ButtonRelease"; break;
1713 case 6: event_name = "MotionNotify"; break;
1714 case 7: event_name = "EnterNotify"; break;
1715 case 8: event_name = "LeaveNotify"; break;
1716 case 9: event_name = "FocusIn"; break;
1717 case 10: event_name = "FocusOut"; break;
1718 case 11: event_name = "KeymapNotify"; break;
1719 case 12: event_name = "Expose"; break;
1720 case 13: event_name = "GraphicsExpose"; break;
1721 case 14: event_name = "NoExpose"; break;
1722 case 15: event_name = "VisibilityNotify"; break;
1723 case 16: event_name = "CreateNotify"; break;
1724 case 17: event_name = "DestroyNotify"; break;
1725 case 18: event_name = "UnmapNotify"; break;
1726 case 19: event_name = "MapNotify"; break;
1727 case 20: event_name = "MapRequest"; break;
1728 case 21: event_name = "ReparentNotify"; break;
1729 case 22: event_name = "ConfigureNotify"; break;
1730 case 23: event_name = "ConfigureRequest"; break;
1731 case 24: event_name = "GravityNotify"; break;
1732 case 25: event_name = "ResizeRequest"; break;
1733 case 26: event_name = "CirculateNotify"; break;
1734 case 27: event_name = "CirculateRequest"; break;
1735 case 28: event_name = "PropertyNotify"; break;
1736 case 29: event_name = "SelectionClear"; break;
1737 case 30: event_name = "SelectionRequest"; break;
1738 case 31: event_name = "SelectionNotify"; break;
1739 case 32: event_name = "ColormapNotify"; break;
1740 case 33: event_name = "ClientMessage"; break;
1741 case 34: event_name = "MappingNotify"; break;
1742 default: event_name = "unknown";
1745 fprintf (stderr, "%s: %s\n", win_name, event_name);
1750 mwin__map_window (MFrame *frame, MDrawWindow win)
1752 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1756 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1758 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1762 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1763 MDrawMetric *geometry)
1765 Display *display = FRAME_DISPLAY (frame);
1766 XWindowAttributes attr;
1767 Window parent = (Window) parent_win, root;
1769 XGetWindowAttributes (display, (Window) win, &attr);
1770 geometry->x = attr.x + attr.border_width;
1771 geometry->y = attr.y + attr.border_width;
1772 geometry->width = attr.width;
1773 geometry->height = attr.height;
1776 parent = RootWindow (display, FRAME_SCREEN (frame));
1779 Window this_parent, *children;
1782 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1785 if (this_parent == parent || this_parent == root)
1787 win = (MDrawWindow) this_parent;
1788 XGetWindowAttributes (display, (Window) win, &attr);
1789 geometry->x += attr.x + attr.border_width;
1790 geometry->y += attr.y + attr.border_width;
1795 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1796 MDrawMetric *current, MDrawMetric *new)
1798 Display *display = FRAME_DISPLAY (frame);
1799 unsigned int mask = 0;
1800 XWindowChanges values;
1802 if (current->width != new->width)
1805 if (new->width <= 0)
1807 values.width = current->width = new->width;
1809 if (current->height != new->height)
1812 if (new->height <= 0)
1814 values.height = current->height = new->height;
1816 if (current->x != new->x)
1819 values.x = current->x = new->x;
1821 if (current->y != new->y)
1824 current->y = new->y;
1825 values.y = current->y = new->y;
1828 XConfigureWindow (display, (Window) win, mask, &values);
1829 XClearWindow (display, (Window) win);
1833 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1835 XEvent *event = (XEvent *) arg;
1836 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1843 if (event->xany.type != KeyPress
1844 /* && event->xany.type != KeyRelease */
1847 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1854 if (c < XK_space || c > XK_asciitilde)
1856 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1857 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1858 if (((XKeyEvent *) event)->state & ControlMask)
1860 if (c >= 'a' && c <= 'z')
1862 if (c >= ' ' && c < 127)
1863 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1865 key = minput__char_to_key (c);
1867 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1871 char *str = XKeysymToString (keysym);
1875 key = msymbol (str);
1876 if (((XKeyEvent *) event)->state & ShiftMask)
1877 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1878 if (((XKeyEvent *) event)->state & ControlMask)
1879 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1881 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1882 *modifiers |= MINPUT_KEY_META_MODIFIER;
1883 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1884 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1885 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1886 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1887 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1888 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1895 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1897 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1899 Display *display = FRAME_DISPLAY (frame);
1900 GCInfo *info = rface->info;
1903 for (i = 0; i <= GC_INVERSE; i++)
1905 XGetGCValues (display, info->gc[i], valuemask, &values);
1906 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1907 values.foreground, values.background);
1908 fprintf (stderr, "\n");
1912 static MDeviceDriver x_driver =
1915 mwin__device_get_prop,
1917 mwin__free_realized_face,
1919 mwin__draw_empty_boxes,
1923 mwin__region_from_rect,
1924 mwin__union_rect_with_region,
1925 mwin__intersect_region,
1926 mwin__region_add_rect,
1927 mwin__region_to_rect,
1930 mwin__create_window,
1931 mwin__destroy_window,
1934 mwin__window_geometry,
1935 mwin__adjust_window,
1939 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1944 M_iso8859_1 = msymbol ("iso8859-1");
1945 M_iso10646_1 = msymbol ("iso10646-1");
1947 display_info_list = mplist ();
1948 device_list = mplist ();
1951 xft_driver.select = mfont__ft_driver.select;
1952 xft_driver.list = mfont__ft_driver.list;
1955 Mxim = msymbol ("xim");
1956 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1964 M17N_OBJECT_UNREF (display_info_list);
1965 M17N_OBJECT_UNREF (device_list);
1970 #ifdef X_SET_ERROR_HANDLER
1972 x_error_handler (Display *display, XErrorEvent *error)
1979 x_io_error_handler (Display *display)
1986 /** Return an MWDevice object corresponding to a display specified in
1989 It searches device_list for a device matching the display. If
1990 found, return the found object. Otherwise, return a newly created
1994 device_open (MFrame *frame, MPlist *param)
1996 Display *display = NULL;
1997 Screen *screen = NULL;
1999 Drawable drawable = 0;
2000 Widget widget = NULL;
2002 int auto_display = 0;
2003 MDisplayInfo *disp_info = NULL;
2004 MWDevice *device = NULL;
2006 XWindowAttributes attr;
2012 int use_xfont = 0, use_freetype = 0, use_xft = 0;
2014 for (plist = param; (key = mplist_key (plist)) != Mnil;
2015 plist = mplist_next (plist))
2017 if (key == Mdisplay)
2018 display = (Display *) mplist_value (plist);
2019 else if (key == Mscreen)
2020 screen = mplist_value (plist);
2021 else if (key == Mdrawable)
2022 drawable = (Drawable) mplist_value (plist);
2023 else if (key == Mdepth)
2024 depth = (unsigned) mplist_value (plist);
2025 else if (key == Mwidget)
2026 widget = (Widget) mplist_value (plist);
2027 else if (key == Mcolormap)
2028 cmap = (Colormap) mplist_value (plist);
2029 else if (key == Mfont)
2031 MSymbol val = MPLIST_SYMBOL (plist);
2035 #ifdef HAVE_FREETYPE
2036 else if (val == Mfreetype)
2039 else if (val == Mxft)
2046 /* If none of them is specified, use all of them. */
2047 if (! use_xfont && ! use_freetype && ! use_xft)
2048 use_xfont = use_freetype = use_xft = 1;
2052 display = XtDisplay (widget);
2053 screen_num = XScreenNumberOfScreen (XtScreen (widget));
2054 depth = DefaultDepth (display, screen_num);
2060 unsigned width, height, border_width;
2063 MERROR (MERROR_WIN, -1);
2064 XGetGeometry (display, drawable, &root_window,
2065 &x, &y, &width, &height, &border_width, &depth);
2066 XGetWindowAttributes (display, root_window, &attr);
2067 screen_num = XScreenNumberOfScreen (attr.screen);
2072 display = DisplayOfScreen (screen);
2077 display = XOpenDisplay (NULL);
2079 MERROR (MERROR_WIN, -1);
2082 screen = DefaultScreenOfDisplay (display);
2084 screen_num = XScreenNumberOfScreen (screen);
2086 depth = DefaultDepth (display, screen_num);
2090 cmap = DefaultColormap (display, screen_num);
2092 for (plist = display_info_list; mplist_key (plist) != Mnil;
2093 plist = mplist_next (plist))
2095 disp_info = (MDisplayInfo *) mplist_value (plist);
2096 if (disp_info->display == display)
2100 if (mplist_key (plist) != Mnil)
2101 M17N_OBJECT_REF (disp_info);
2104 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
2105 disp_info->display = display;
2106 disp_info->auto_display = auto_display;
2107 disp_info->font_list = mplist ();
2108 find_modifier_bits (disp_info);
2109 mplist_add (display_info_list, Mt, disp_info);
2112 for (plist = device_list; mplist_key (plist) != Mnil;
2113 plist = mplist_next (plist))
2115 device = (MWDevice *) mplist_value (plist);
2116 if (device->display_info == disp_info
2117 && device->depth == depth
2118 && device->cmap == cmap
2119 && device->screen_num == screen_num)
2123 if (mplist_key (plist) != Mnil)
2124 M17N_OBJECT_REF (device);
2127 unsigned long valuemask = GCForeground;
2131 M17N_OBJECT (device, free_device, MERROR_WIN);
2132 device->display_info = disp_info;
2133 device->screen_num = screen_num;
2134 /* A drawable on which to create GCs. */
2135 device->drawable = XCreatePixmap (display,
2136 RootWindow (display, screen_num),
2138 device->depth = depth;
2139 device->cmap = cmap;
2140 pixels = DisplayHeight (display, screen_num);
2141 mm = DisplayHeightMM (display, screen_num);
2142 device->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
2143 device->realized_face_list = mplist ();
2144 device->realized_font_list = mplist ();
2145 mplist_add (device->realized_font_list, Mt, NULL);
2146 device->realized_fontset_list = mplist ();
2147 device->gc_list = mplist ();
2148 values.foreground = BlackPixel (display, screen_num);
2149 device->scratch_gc = XCreateGC (display, device->drawable,
2150 valuemask, &values);
2152 device->xft_draw = XftDrawCreate (display, device->drawable,
2153 DefaultVisual (display, screen_num),
2158 frame->device = device;
2159 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2160 frame->dpi = device->resy;
2161 frame->driver = &x_driver;
2162 frame->font_driver_list = mplist ();
2166 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2169 #endif /* HAVE_XFT2 */
2170 #ifdef HAVE_FREETYPE
2172 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2173 #endif /* HAVE_FREETYPE */
2174 if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list))
2175 mplist_push (frame->font_driver_list, Mx, &xfont_driver);
2177 frame->realized_font_list = device->realized_font_list;
2178 frame->realized_face_list = device->realized_face_list;
2179 frame->realized_fontset_list = device->realized_fontset_list;
2183 XtResource resources[] = {
2184 { XtNfont, XtCFont, XtRString, sizeof (String),
2185 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2186 { XtNforeground, XtCForeground, XtRString, sizeof (String),
2187 XtOffset (AppDataPtr, foreground), XtRString, "black" },
2188 { XtNbackground, XtCBackground, XtRString, sizeof (String),
2189 XtOffset (AppDataPtr, background), XtRString, "white" },
2190 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2191 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2194 XtGetApplicationResources (widget, &app_data,
2195 resources, XtNumber (resources), NULL, 0);
2196 frame->foreground = msymbol (app_data.foreground);
2197 frame->background = msymbol (app_data.background);
2198 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2202 app_data.font = DEFAULT_FONT;
2203 frame->foreground = msymbol ("black");
2204 frame->background = msymbol ("white");
2205 frame->videomode = Mnormal;
2208 if (strcmp (app_data.font, DEFAULT_FONT) != 0)
2210 XFontStruct *xfont = XLoadQueryFont (display, app_data.font);
2211 unsigned long value;
2216 font = mfont_parse_name (app_data.font, Mx);
2218 && XGetFontProperty (xfont, XA_FONT, &value)
2219 && (name = ((char *) XGetAtomName (display, (Atom) value))))
2220 font = mfont_parse_name (name, Mx);
2221 XFreeFont (display, xfont);
2225 font = mfont_parse_name (DEFAULT_FONT, Mx);
2226 else if (! font->size)
2228 face = mface_from_font (font);
2230 face->property[MFACE_FONTSET] = mfontset (NULL);
2231 face->property[MFACE_FOREGROUND] = frame->foreground;
2232 face->property[MFACE_BACKGROUND] = frame->background;
2233 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2234 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2235 face->property[MFACE_VIDEOMODE] = frame->videomode;
2236 mface_put_prop (face, Mhook_func,
2237 mface_get_prop (mface__default, Mhook_func));
2238 face->property[MFACE_RATIO] = (void *) 100;
2239 mplist_push (param, Mface, face);
2240 M17N_OBJECT_UNREF (face);
2242 #ifdef X_SET_ERROR_HANDLER
2243 XSetErrorHandler (x_error_handler);
2244 XSetIOErrorHandler (x_io_error_handler);
2251 /* XIM (X Input Method) handler */
2253 typedef struct MInputXIMMethodInfo
2259 } MInputXIMMethodInfo;
2261 typedef struct MInputXIMContextInfo
2265 MConverter *converter;
2266 } MInputXIMContextInfo;
2269 xim_open_im (MInputMethod *im)
2271 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2272 MLocale *saved, *this;
2273 char *save_modifier_list;
2275 MInputXIMMethodInfo *im_info;
2277 saved = mlocale_set (LC_CTYPE, NULL);
2278 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2280 /* The specified locale is not supported. */
2281 MERROR (MERROR_LOCALE, -1);
2282 if (mlocale_get_prop (this, Mcoding) == Mnil)
2284 /* Unable to decode the output of XIM. */
2285 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2286 MERROR (MERROR_LOCALE, -1);
2289 if (arg->modifier_list)
2290 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2292 save_modifier_list = XSetLocaleModifiers ("");
2293 if (! save_modifier_list)
2295 /* The specified locale is not supported by X. */
2296 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2297 MERROR (MERROR_LOCALE, -1);
2300 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2303 /* No input method is available in the current locale. */
2304 XSetLocaleModifiers (save_modifier_list);
2305 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2306 MERROR (MERROR_WIN, -1);
2309 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2310 im_info->display = arg->display;
2312 im_info->language = mlocale_get_prop (this, Mlanguage);
2313 im_info->coding = mlocale_get_prop (this, Mcoding);
2316 XSetLocaleModifiers (save_modifier_list);
2317 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2323 xim_close_im (MInputMethod *im)
2325 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2327 XCloseIM (im_info->xim);
2332 xim_create_ic (MInputContext *ic)
2334 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2335 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2336 MInputXIMContextInfo *ic_info;
2339 if (! arg->input_style)
2341 /* By default, use Root style. */
2342 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2343 arg->preedit_attrs = NULL;
2344 arg->status_attrs = NULL;
2347 if (! arg->preedit_attrs && ! arg->status_attrs)
2348 xic = XCreateIC (im_info->xim,
2349 XNInputStyle, arg->input_style,
2350 XNClientWindow, arg->client_win,
2351 XNFocusWindow, arg->focus_win,
2353 else if (arg->preedit_attrs && ! arg->status_attrs)
2354 xic = XCreateIC (im_info->xim,
2355 XNInputStyle, arg->input_style,
2356 XNClientWindow, arg->client_win,
2357 XNFocusWindow, arg->focus_win,
2358 XNPreeditAttributes, arg->preedit_attrs,
2360 else if (! arg->preedit_attrs && arg->status_attrs)
2361 xic = XCreateIC (im_info->xim,
2362 XNInputStyle, arg->input_style,
2363 XNClientWindow, arg->client_win,
2364 XNFocusWindow, arg->focus_win,
2365 XNStatusAttributes, arg->status_attrs,
2368 xic = XCreateIC (im_info->xim,
2369 XNInputStyle, arg->input_style,
2370 XNClientWindow, arg->client_win,
2371 XNFocusWindow, arg->focus_win,
2372 XNPreeditAttributes, arg->preedit_attrs,
2373 XNStatusAttributes, arg->status_attrs,
2376 MERROR (MERROR_WIN, -1);
2378 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2380 ic_info->win = arg->focus_win;
2381 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2387 xim_destroy_ic (MInputContext *ic)
2389 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2391 XDestroyIC (ic_info->xic);
2392 mconv_free_converter (ic_info->converter);
2398 xim_filter (MInputContext *ic, MSymbol key, void *event)
2400 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2402 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2407 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2409 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2410 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2411 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2417 buf = (char *) alloca (512);
2418 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2419 if (status == XBufferOverflow)
2421 buf = (char *) alloca (len);
2422 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2425 mtext_reset (ic->produced);
2429 mconv_reset_converter (ic_info->converter);
2430 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2431 mconv_decode (ic_info->converter, ic->produced);
2432 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2433 Mlanguage, (void *) im_info->language);
2434 mtext_cpy (mt, ic->produced);
2435 mtext_reset (ic->produced);
2443 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2447 /*** @addtogroup m17nInputMethodWin */
2452 @brief Input method driver for XIM.
2454 The driver #minput_xim_driver is for the foreign input method of
2455 name #Mxim. It uses XIM (X Input Methods) as a background input
2458 As the symbol #Mxim has property #Minput_driver whose value is
2459 a pointer to this driver, the input method of language #Mnil
2460 and name #Mxim uses this driver.
2462 Therefore, for such input methods, the driver dependent arguments
2463 to the functions whose name begin with minput_ must be as follows.
2465 The argument $ARG of the function minput_open_im () must be a
2466 pointer to the structure #MInputXIMArgIM. See the documentation
2467 of #MInputXIMArgIM for more details.
2469 The argument $ARG of the function minput_create_ic () must be a
2470 pointer to the structure #MInputXIMArgIC. See the documentation
2471 of #MInputXIMArgIC for more details.
2473 The argument $ARG of the function minput_filter () must be a
2474 pointer to the structure @c XEvent. The argument $KEY is ignored.
2476 The argument $ARG of the function minput_lookup () must be the
2477 same one as that of the function minput_filter (). The argument
2481 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2483 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ê¡¢
2484 XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
2486 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2487 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim
2488 ¤Ç¤¢¤ëÆþÎϥ᥽¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2490 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_
2491 ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2493 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM
2494 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò»²¾È¡£
2496 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC
2497 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ¤ò»²¾È¡£
2499 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent
2500 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2502 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2503 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì¤ë¡£ */
2505 MInputDriver minput_xim_driver =
2506 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2507 xim_filter, xim_lookup, NULL };
2511 #else /* not HAVE_X11 */
2513 int device_open () { return -1; }
2515 #endif /* not HAVE_X11 */