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., 51 Franklin Street, Fifth Floor,
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"
64 /* Common header for the m17n object. */
69 /* If nonzero, <display> is opened by this library. Thus it should
70 be closed on freeing this structure. */
73 /** List of available X-core fonts on the display. Keys are
74 registries and values are plists whose keys are families and
75 values are pointers to MFont. */
78 /** Nonzero means that <font_list> already contains all available
79 fonts on the display. */
82 /** Modifier bit masks of the display. */
88 Atom MULE_BASELINE_OFFSET;
92 /* Anchor of the chain of MDisplayInfo objects. */
93 static MPlist *display_info_list;
96 /* Color value and the corresponding GC. */
99 unsigned int rgb; /* (red << 16) | (green << 8) | blue */
106 GC_NORMAL = GC_INVERSE + 7,
119 /* The first 8 elements are indexed by an intensity for
120 anti-aliasing. The 2nd to 7th are created on demand. */
123 XftColor xft_color_fore, xft_color_back;
129 /* Common header for the m17n object. */
132 MDisplayInfo *display_info;
150 /** List of pointers to realized faces on the frame. */
151 MPlist *realized_face_list;
153 /* List of single element whose value is a root of chain of realized
155 MPlist *realized_font_list;
157 /** List of pointers to realized fontsets on the frame. */
158 MPlist *realized_fontset_list;
160 /** List of XColors vs GCs on the frame. */
164 static MPlist *device_list;
166 static MSymbol M_iso8859_1, M_iso10646_1;
168 #define FRAME_DEVICE(frame) ((MWDevice *) (frame)->device)
169 #define FRAME_DISPLAY(frame) (FRAME_DEVICE (frame)->display_info->display)
170 #define FRAME_SCREEN(frame) (FRAME_DEVICE (frame)->screen_num)
171 #define FRAME_CMAP(frame) (FRAME_DEVICE (frame)->cmap)
172 #define FRAME_VISUAL(frame) DefaultVisual (FRAME_DISPLAY (frame), \
173 FRAME_SCREEN (frame))
175 #define DEFAULT_FONT "-*-*-medium-r-normal--13-*-*-*-c-*-iso8859-1"
182 Boolean reverse_video;
183 } AppData, *AppDataPtr;
186 free_display_info (void *object)
188 MDisplayInfo *disp_info = (MDisplayInfo *) object;
191 MPLIST_DO (plist, disp_info->font_list)
193 MPLIST_DO (pl, MPLIST_VAL (plist))
194 free (MPLIST_VAL (pl));
195 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
197 M17N_OBJECT_UNREF (disp_info->font_list);
199 if (disp_info->auto_display)
200 XCloseDisplay (disp_info->display);
206 free_device (void *object)
208 MWDevice *device = object;
211 for (plist = device->realized_fontset_list;
212 mplist_key (plist) != Mnil; plist = mplist_next (plist))
213 mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist));
214 M17N_OBJECT_UNREF (device->realized_fontset_list);
216 if (MPLIST_VAL (device->realized_font_list))
217 mfont__free_realized (MPLIST_VAL (device->realized_font_list));
218 M17N_OBJECT_UNREF (device->realized_font_list);
220 MPLIST_DO (plist, device->realized_face_list)
222 MRealizedFace *rface = MPLIST_VAL (plist);
225 mface__free_realized (rface);
227 M17N_OBJECT_UNREF (device->realized_face_list);
229 MPLIST_DO (plist, device->gc_list)
231 XFreeGC (device->display_info->display,
232 ((RGB_GC *) MPLIST_VAL (plist))->gc);
233 free (MPLIST_VAL (plist));
235 M17N_OBJECT_UNREF (device->gc_list);
236 XFreeGC (device->display_info->display, device->scratch_gc);
239 XftDrawDestroy (device->xft_draw);
242 XFreePixmap (device->display_info->display, device->drawable);
243 M17N_OBJECT_UNREF (device->display_info);
249 find_modifier_bits (MDisplayInfo *disp_info)
251 Display *display = disp_info->display;
252 XModifierKeymap *mods;
253 KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L);
254 KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R);
255 KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L);
256 KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R);
257 KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
258 KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
259 KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
260 KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
263 mods = XGetModifierMapping (display);
264 /* We skip the first three sets for Shift, Lock, and Control. The
265 remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
266 for (i = 3; i < 8; i++)
267 for (j = 0; j < mods->max_keypermod; j++)
269 KeyCode code = mods->modifiermap[i * mods->max_keypermod + j];
273 if (code == meta_l || code == meta_r)
274 disp_info->meta_mask |= (1 << i);
275 else if (code == alt_l || code == alt_r)
276 disp_info->alt_mask |= (1 << i);
277 else if (code == super_l || code == super_r)
278 disp_info->super_mask |= (1 << i);
279 else if (code == hyper_l || code == hyper_r)
280 disp_info->hyper_mask |= (1 << i);
283 /* If meta keys are not in any modifier, use alt keys as meta
285 if (! disp_info->meta_mask)
287 disp_info->meta_mask = disp_info->alt_mask;
288 disp_info->alt_mask = 0;
290 /* If both meta and alt are assigned to the same modifier, give meta
292 if (disp_info->meta_mask & disp_info->alt_mask)
293 disp_info->alt_mask &= ~disp_info->meta_mask;
295 XFreeModifiermap (mods);
299 get_rgb_gc (MWDevice *device, XColor *xcolor)
301 int rgb = (((xcolor->red >> 8) << 16) | ((xcolor->green >> 8) << 8)
302 | (xcolor->blue >> 8));
305 unsigned long valuemask = GCForeground;
308 MPLIST_DO (plist, device->gc_list)
310 rgb_gc = MPLIST_VAL (plist);
312 if (rgb_gc->rgb == rgb)
314 if (rgb_gc->rgb > rgb)
318 if (! XAllocColor (device->display_info->display, device->cmap, xcolor))
321 rgb_gc = malloc (sizeof (RGB_GC));
323 values.foreground = xcolor->pixel;
324 rgb_gc->gc = XCreateGC (device->display_info->display,
325 device->drawable, valuemask, &values);
326 mplist_push (plist, Mt, rgb_gc);
331 get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret)
333 MWDevice *device = FRAME_DEVICE (frame);
341 color = for_foreground ? frame->foreground : frame->background;
343 if (! XParseColor (FRAME_DISPLAY (frame), device->cmap,
344 msymbol_name (color), &xcolor))
346 rgb_gc = get_rgb_gc (device, &xcolor);
350 *rgb_ret = rgb_gc->rgb;
355 GCInfo *info = frame->rface->info;
360 rgb = info->rgb_fore, gc = info->gc[GC_NORMAL];
362 rgb = info->rgb_back, gc = info->gc[GC_INVERSE];
370 get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity)
372 int rgb_fore, rgb_back;
377 if (info->gc[intensity])
378 return info->gc[intensity];
380 rgb_fore = info->rgb_fore, rgb_back = info->rgb_back;
381 xcolor.red = ((((rgb_fore & 0xFF0000) >> 16) * intensity
382 + ((rgb_back & 0xFF0000) >> 16) * (7 - intensity)) / 7) << 8;
383 xcolor.green = ((((rgb_fore & 0xFF00) >> 8) * intensity
384 + ((rgb_back & 0xFF00) >> 8) * (7 - intensity)) / 7) << 8;
385 xcolor.blue = (((rgb_fore & 0xFF) * intensity
386 + (rgb_back & 0xFF) * (7 - intensity)) / 7) << 8;
387 rgb_gc = get_rgb_gc (device, &xcolor);
391 gc =get_gc_for_anti_alias (device, info,
392 intensity < 4 ? intensity - 1 : intensity + 1);
393 return (info->gc[intensity] = gc);
397 set_region (MFrame *frame, GC gc, MDrawRegion region)
399 unsigned long valuemask = GCForeground;
401 XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
402 FRAME_DEVICE (frame)->scratch_gc);
403 XSetRegion (FRAME_DISPLAY (frame), FRAME_DEVICE (frame)->scratch_gc, region);
404 return FRAME_DEVICE (frame)->scratch_gc;
408 /** X font handler */
410 static MFont *xfont_select (MFrame *, MFont *, int);
411 static MRealizedFont *xfont_open (MFrame *, MFont *, MFont *, MRealizedFont *);
412 static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int);
413 static int xfont_has_char (MFrame *, MFont *, MFont *, int, unsigned);
414 static unsigned xfont_encode_char (MFrame *, MFont *, MFont *, unsigned);
415 static void xfont_render (MDrawWindow, int, int, MGlyphString *,
416 MGlyph *, MGlyph *, int, MDrawRegion);
417 static int xfont_list (MFrame *, MPlist *, MFont *, int);
418 static void xfont_list_family_names (MFrame *, MPlist *);
419 static int xfont_check_capability (MRealizedFont *rfont, MSymbol capability);
421 static MFontDriver xfont_driver =
422 { xfont_select, xfont_open,
423 xfont_find_metric, xfont_has_char, xfont_encode_char,
424 xfont_render, xfont_list, xfont_list_family_names, xfont_check_capability
428 font_compare (const void *p1, const void *p2)
430 return strcmp (*(char **) p1, *(char **) p2);
434 xfont_registry_list (MFrame *frame, MSymbol registry)
436 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
437 MPlist *font_list = disp_info->font_list;
440 char **font_names, **names;
446 plist = mplist_get (font_list, registry);
449 p = plist = mplist ();
450 mplist_add (font_list, registry, plist);
451 sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", msymbol_name (registry));
452 font_names = XListFonts (disp_info->display, pattern, 0x8000, &nfonts);
456 char *reg_name = msymbol_name (registry);
458 for_full_width = (strncmp (reg_name, "jis", 3) == 0
459 || strncmp (reg_name, "gb", 2) == 0
460 || strncmp (reg_name, "big5", 4) == 0
461 || strncmp (reg_name, "ksc", 3) == 0);
463 names = alloca (sizeof (char *) * nfonts);
464 memcpy (names, font_names, sizeof (char *) * nfonts);
465 qsort (names, nfonts, sizeof (char *), font_compare);
467 for (i = 0; i < nfonts; i++)
468 if (mfont__parse_name_into_font (names[i], Mx, &font) == 0
469 && (font.size > 0 || font.property[MFONT_RESY] == 0))
471 MSymbol family = FONT_PROPERTY (&font, MFONT_FAMILY);
476 int size, normal_size;
481 /* Calculate how many bytes to compare to detect fonts of the
483 for (base_end = names[i], fields = 0; *base_end; base_end++)
485 && ++fields == 7 /* PIXEL_SIZE */)
487 base_len = base_end - names[i] + 1;
489 size = font.size / 10;
490 sizes[nsizes++] = size;
491 normal_size = (size >= 6 && size <= 29);
492 limit = (i + 256 < nfonts ? i + 256 : nfonts);
493 for (j = i + 1; j < limit && ! memcmp (names[i], names[j], base_len);
495 if (mfont__parse_name_into_font (names[j], Mx, &font) == 0
496 && (font.size > 0 || font.property[MFONT_RESY] == 0))
498 size = font.size / 10;
499 sizes[nsizes++] = size;
500 normal_size |= (size >= 6 && size <= 29);
503 font.for_full_width = for_full_width;
504 font.type = MFONT_TYPE_OBJECT;
505 font.source = MFONT_SOURCE_X;
508 MSTRUCT_CALLOC (fontx, MERROR_WIN);
510 fontx->multiple_sizes = 1;
512 for (j = 0; j < nsizes; j++)
513 if (sizes[j] >= 6 && sizes[j] <= 29)
514 fontx->size |= 1 << (sizes[j] - 6);
515 p = mplist_add (p, family, fontx);
517 for (j = 0; j < nsizes; j++)
518 if (sizes[j] < 6 || sizes[j] > 29)
520 MSTRUCT_CALLOC (fontx, MERROR_WIN);
522 fontx->multiple_sizes = 0;
523 fontx->size = sizes[j] * 10;
525 fontx->property[MFONT_RESY] = 0;
526 p = mplist_add (p, family, fontx);
529 XFreeFontNames (font_names);
534 xfont_list_all (MFrame *frame)
536 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
537 MPlist *font_encoding_list, *p;
539 if (disp_info->all_fonts_scaned)
541 disp_info->all_fonts_scaned = 1;
542 font_encoding_list = mfont__encoding_list ();
543 if (! font_encoding_list)
545 MPLIST_DO (p, font_encoding_list)
546 xfont_registry_list (frame, MPLIST_KEY (p));
556 /* The X font driver function SELECT. */
559 xfont_select (MFrame *frame, MFont *font, int limited_size)
561 MPlist *plist = mplist (), *pl;
562 int num = xfont_list (frame, plist, font, 0);
566 MPLIST_DO (pl, plist)
568 font = MPLIST_VAL (pl);
569 if (limited_size == 0
571 || font->size <= limited_size)
577 M17N_OBJECT_UNREF (plist);
581 /* The X font driver function CLOSE. */
584 close_xfont (void *object)
586 MRealizedFontX *x_rfont = object;
588 XFreeFont (x_rfont->display, x_rfont->xfont);
592 /* The X font driver function OPEN. */
594 static MRealizedFont *
595 xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
598 MRealizedFontX *x_rfont;
600 Display *display = FRAME_DISPLAY (frame);
602 int mdebug_flag = MDEBUG_FONT;
608 int ratio = mfont_resize_ratio (font);
611 size = size * ratio / 100;
618 /* non-scalable font */
619 if (font->multiple_sizes)
627 for (i = size / 10 - 6; i >= 0; i--)
628 if (font->size & (1 << i))
631 for (i = size / 10 - 5; i < 24; i++)
632 if (font->size & (1 << i))
642 for (; rfont; rfont = rfont->next)
643 if (rfont->font == font && rfont->spec.size == size)
648 this.multiple_sizes = 0;
650 /* This never fail to generate a valid fontname. */
651 name = mfont_unparse_name (&this, Mx);
652 xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
655 MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
657 font->type = MFONT_TYPE_FAILURE;
660 MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
662 M17N_OBJECT (x_rfont, close_xfont, MERROR_FONT_X);
663 x_rfont->display = display;
664 x_rfont->xfont = xfont;
665 MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
667 rfont->spec.type = MFONT_TYPE_REALIZED;
668 rfont->spec.source = MFONT_SOURCE_X;
669 rfont->frame = frame;
671 rfont->driver = &xfont_driver;
672 rfont->info = x_rfont;
674 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
677 rfont->baseline_offset
678 = (XGetFontProperty (xfont, disp_info->MULE_BASELINE_OFFSET, &value)
679 ? (int) (value << 6) : 0);
681 = (XGetFontProperty (xfont, disp_info->AVERAGE_WIDTH, &value)
682 ? (int) (value << 6) / 10 : 0);
684 rfont->ascent = (xfont->ascent << 6) + rfont->baseline_offset;
685 rfont->descent = (xfont->descent << 6) - rfont->baseline_offset;
686 rfont->max_advance = xfont->max_bounds.width << 6;
687 rfont->x_ppem = rfont->y_ppem = size / 10;
688 rfont->fontp = xfont;
689 rfont->next = MPLIST_VAL (frame->realized_font_list);
690 MPLIST_VAL (frame->realized_font_list) = rfont;
695 /* The X font driver function FIND_METRIC. */
698 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
701 XFontStruct *xfont = rfont->fontp;
702 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
704 for (; g != gend; g++)
707 if (g->g.code == MCHAR_INVALID_CODE)
709 g->g.lbearing = xfont->max_bounds.lbearing << 6;
710 g->g.rbearing = xfont->max_bounds.rbearing << 6;
711 g->g.xadv = xfont->max_bounds.width << 6;
712 g->g.ascent = xfont->ascent << 6;
713 g->g.descent = xfont->descent << 6;
717 int byte1 = g->g.code >> 8, byte2 = g->g.code & 0xFF;
718 XCharStruct *pcm = NULL;
720 if (xfont->per_char != NULL)
722 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
725 && byte2 >= xfont->min_char_or_byte2
726 && byte2 <= xfont->max_char_or_byte2)
727 pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
731 if (byte1 >= xfont->min_byte1
732 && byte1 <= xfont->max_byte1
733 && byte2 >= xfont->min_char_or_byte2
734 && byte2 <= xfont->max_char_or_byte2)
736 pcm = (xfont->per_char
737 + ((xfont->max_char_or_byte2
738 - xfont->min_char_or_byte2 + 1)
739 * (byte1 - xfont->min_byte1))
740 + (byte2 - xfont->min_char_or_byte2));
747 g->g.lbearing = pcm->lbearing << 6;
748 g->g.rbearing = pcm->rbearing << 6;
749 g->g.xadv = pcm->width << 6;
750 g->g.ascent = pcm->ascent << 6;
751 g->g.descent = pcm->descent << 6;
755 /* If the per_char pointer is null, all glyphs between
756 the first and last character indexes inclusive have
757 the same information, as given by both min_bounds and
760 g->g.rbearing = xfont->max_bounds.width << 6;
761 g->g.xadv = xfont->max_bounds.width << 6;
762 g->g.ascent = xfont->ascent << 6;
763 g->g.descent = xfont->descent << 6;
767 g->g.ascent += rfont->baseline_offset;
768 g->g.descent -= rfont->baseline_offset;
775 xfont_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
777 return (xfont_encode_char (frame, font, spec, code) != MCHAR_INVALID_CODE);
780 /* The X font driver function GET_GLYPH_ID. */
783 xfont_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
785 MRealizedFont *rfont;
787 unsigned min_byte1, max_byte1, min_byte2, max_byte2;
790 if (font->type == MFONT_TYPE_REALIZED)
791 rfont = (MRealizedFont *) font;
792 else if (font->type == MFONT_TYPE_OBJECT)
794 for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
796 if (rfont->font == font)
800 rfont = xfont_open (frame, font, spec, NULL);
802 return MCHAR_INVALID_CODE;
806 MFATAL (MERROR_FONT_X);
807 xfont = rfont->fontp;
808 all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
809 min_byte1 = xfont->min_byte1;
810 max_byte1 = xfont->max_byte1;
811 min_byte2 = xfont->min_char_or_byte2;
812 max_byte2 = xfont->max_char_or_byte2;
814 if (min_byte1 == 0 && max_byte1 == 0)
818 if (code < min_byte2 || code > max_byte2)
819 return MCHAR_INVALID_CODE;
822 pcm = xfont->per_char + (code - min_byte2);
823 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
824 ? code : MCHAR_INVALID_CODE);
828 unsigned byte1 = code >> 8, byte2 = code & 0xFF;
831 if (byte1 < min_byte1 || byte1 > max_byte1
832 || byte2 < min_byte2 || byte2 > max_byte2)
833 return MCHAR_INVALID_CODE;
837 pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
838 + (byte2 - min_byte2));
839 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
840 ? code : MCHAR_INVALID_CODE);
844 /* The X font driver function RENDER. */
847 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
848 MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
850 MRealizedFace *rface = from->rface;
851 Display *display = FRAME_DISPLAY (rface->frame);
853 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
861 baseline_offset = rface->rfont->baseline_offset >> 6;
863 gc = set_region (rface->frame, gc, region);
864 XSetFont (display, gc, ((XFontStruct *) rface->rfont->fontp)->fid);
865 code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
866 for (i = 0, g = from; g < to; i++, g++)
868 code[i].byte1 = g->g.code >> 8;
869 code[i].byte2 = g->g.code & 0xFF;
875 if (g->type == GLYPH_PAD)
877 else if (g->type == GLYPH_SPACE)
878 for (; g < to && g->type == GLYPH_SPACE; g++)
880 else if (! g->rface->rfont)
882 if ((g->g.c >= 0x200B && g->g.c <= 0x200F)
883 || (g->g.c >= 0x202A && g->g.c <= 0x202E))
887 /* As a font is not found for this character, draw an
889 int box_width = g->g.xadv;
890 int box_height = gstring->ascent + gstring->descent;
896 XDrawRectangle (display, (Window) win, gc,
897 x, y - gstring->ascent, box_width, box_height);
901 else if (g->g.xoff != 0 || g->g.yoff != 0 || g->right_padding)
903 XDrawString16 (display, (Window) win, gc,
904 x + g->g.xoff, y + g->g.yoff - baseline_offset,
905 code + (g - from), 1);
912 int code_idx = g - from;
915 g < to && g->type == GLYPH_CHAR && g->g.xoff == 0 && g->g.yoff == 0;
918 XDrawString16 (display, (Window) win, gc,
919 orig_x, y - baseline_offset, code + code_idx, i);
925 xfont_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum)
927 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
928 MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil;
929 MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil;
930 int size = font ? font->size : 0;
933 int mdebug_flag = MDEBUG_FONT;
935 MDEBUG_PRINT2 (" [X-FONT] listing %s-%s...",
936 family ? msymbol_name (family) : "*",
937 registry ? msymbol_name (registry) : "*");
939 if (registry == Mnil)
940 xfont_list_all (frame);
942 xfont_registry_list (frame, registry);
944 MPLIST_DO (pl, disp_info->font_list)
945 if (registry == Mnil || registry == MPLIST_KEY (pl))
947 MPLIST_DO (p, MPLIST_VAL (pl))
948 if (family == Mnil || family == MPLIST_KEY (p))
950 MFont *fontx = MPLIST_VAL (p);
952 if (! font || (mfont__match_p (fontx, font, MFONT_REGISTRY)))
954 if (fontx->size != 0 && size)
956 if (fontx->multiple_sizes)
958 if (size < 60 || size > 290
959 || ! (fontx->size & (1 << (size / 10 - 6))))
962 else if (fontx->size != size)
965 mplist_push (plist, MPLIST_KEY (p), fontx);
967 if (maxnum > 0 && maxnum == num)
974 MDEBUG_PRINT1 (" %d found\n", num);
979 xfont_list_family_names (MFrame *frame, MPlist *plist)
981 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
984 MSymbol last_family = Mnil;
986 font_names = XListFonts (disp_info->display,
987 "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", 0x8000, &nfonts);
988 for (i = 0; i < nfonts; i++)
991 char foundry[256], fam[256];
994 if (sscanf (font_names[i], "-%s-%s-", foundry, fam) < 2)
996 family = msymbol (fam);
997 if (family == last_family)
999 last_family = family;
1001 MPLIST_DO (p, plist)
1003 MSymbol sym = MPLIST_SYMBOL (p);
1007 if (strcmp (MSYMBOL_NAME (sym), fam) > 0)
1009 mplist_push (p, Msymbol, family);
1013 if (MPLIST_TAIL_P (p))
1014 mplist_push (p, Msymbol, family);
1017 XFreeFontNames (font_names);
1021 xfont_check_capability (MRealizedFont *rfont, MSymbol capability)
1023 /* Currently X font driver doesn't support any capability. */
1035 FT_Face ft_face; /* This must be the 2nd member. */
1038 XftFont *font_no_aa;
1039 /* Pointer to MRealizedFontFT */
1043 static MRealizedFont *xft_open (MFrame *frame, MFont *font, MFont *spec,
1045 static int xft_has_char (MFrame *frame, MFont *font, MFont *spec,
1046 int c, unsigned code);
1047 static unsigned xft_encode_char (MFrame *frame, MFont *font, MFont *spec,
1049 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
1050 static void xft_render (MDrawWindow, int, int, MGlyphString *,
1051 MGlyph *, MGlyph *, int, MDrawRegion);
1052 static int xft_check_capability (MRealizedFont *rfont, MSymbol capability);
1053 static int xft_check_otf (MFLTFont *font, MFLTOtfSpec *spec);
1054 static int xft_drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
1055 MFLTGlyphString *in, int from, int to,
1056 MFLTGlyphString *out,
1057 MFLTGlyphAdjustment *adjustment);
1059 static MFontDriver xft_driver =
1061 xft_find_metric, xft_has_char, xft_encode_char, xft_render, NULL, NULL,
1062 xft_check_capability, NULL, NULL, xft_check_otf, xft_drive_otf
1066 close_xft (void *object)
1068 MRealizedFontXft *rfont_xft = object;
1070 if (rfont_xft->font_aa)
1071 XftFontClose (rfont_xft->display, rfont_xft->font_aa);
1072 if (rfont_xft->font_no_aa)
1073 XftFontClose (rfont_xft->display, rfont_xft->font_no_aa);
1074 M17N_OBJECT_UNREF (rfont_xft->info);
1080 xft_open_font (Display *display, MSymbol file, double size,
1086 pattern = FcPatternCreate ();
1087 FcPatternAddString (pattern, FC_FILE, (FcChar8 *) msymbol_name (file));
1088 FcPatternAddDouble (pattern, FC_PIXEL_SIZE, size);
1089 FcPatternAddBool (pattern, FC_ANTIALIAS, anti_alias);
1090 font = XftFontOpenPattern (display, pattern);
1095 static MRealizedFont *
1096 xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
1098 Display *display = FRAME_DISPLAY (frame);
1099 int reg = spec->property[MFONT_REGISTRY];
1101 MRealizedFontXft *rfont_xft;
1102 FcBool anti_alias = FRAME_DEVICE (frame)->depth > 1 ? FcTrue : FcFalse;
1105 int ascent, descent, max_advance, average_width, baseline_offset;
1108 /* non-scalable font */
1110 else if (spec->size)
1112 int ratio = mfont_resize_ratio (font);
1114 size = ratio == 100 ? spec->size : spec->size * ratio / 100;
1121 MRealizedFont *save = NULL;
1123 for (; rfont; rfont = rfont->next)
1124 if (rfont->font == font
1125 && (rfont->font->size ? rfont->font->size == size
1126 : rfont->spec.size == size)
1127 && rfont->spec.property[MFONT_REGISTRY] == reg)
1131 if (rfont->driver == &xft_driver)
1136 rfont = (mfont__ft_driver.open) (frame, font, spec, rfont);
1139 ascent = rfont->ascent;
1140 descent = rfont->descent;
1141 max_advance = rfont->max_advance;
1142 average_width = rfont->average_width;
1143 baseline_offset = rfont->baseline_offset;
1144 spec = &rfont->spec;
1145 ft_face = rfont->fontp;
1146 xft_font = xft_open_font (display, font->file, size / 10, anti_alias);
1149 M17N_OBJECT (rfont_xft, close_xft, MERROR_WIN);
1150 rfont_xft->display = display;
1151 if (anti_alias == FcTrue)
1152 rfont_xft->font_aa = xft_font;
1154 rfont_xft->font_no_aa = xft_font;
1155 rfont_xft->ft_face = ft_face;
1156 rfont_xft->info = rfont->info;
1157 M17N_OBJECT_REF (rfont->info);
1158 MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
1159 rfont->spec = *spec;
1160 rfont->spec.size = size;
1161 rfont->frame = frame;
1163 rfont->driver = &xft_driver;
1164 rfont->info = rfont_xft;
1165 rfont->ascent = ascent;
1166 rfont->descent = descent;
1167 rfont->max_advance = max_advance;
1168 rfont->average_width = average_width;
1169 rfont->baseline_offset = baseline_offset;
1170 rfont->x_ppem = ft_face->size->metrics.x_ppem;
1171 rfont->y_ppem = ft_face->size->metrics.y_ppem;
1172 rfont->fontp = xft_font;
1173 rfont->next = MPLIST_VAL (frame->realized_font_list);
1174 MPLIST_VAL (frame->realized_font_list) = rfont;
1179 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1182 Display *display = FRAME_DISPLAY (rfont->frame);
1183 XftFont *xft_font = rfont->fontp;
1184 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1186 for (; g != gend; g++)
1187 if (! g->g.measured)
1189 if (g->g.code == MCHAR_INVALID_CODE)
1192 g->g.rbearing = xft_font->max_advance_width << 6;
1193 g->g.xadv = g->g.rbearing << 6;
1194 g->g.ascent = xft_font->ascent << 6;
1195 g->g.descent = xft_font->descent << 6;
1201 XftGlyphExtents (display, xft_font, &g->g.code, 1, &extents);
1202 g->g.lbearing = (- extents.x) << 6;
1203 g->g.rbearing = (extents.width - extents.x) << 6;
1204 g->g.xadv = extents.xOff << 6;
1205 g->g.ascent = extents.y << 6;
1206 g->g.descent = (extents.height - extents.y) << 6;
1214 xft_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
1218 if (font->type == MFONT_TYPE_REALIZED)
1220 MRealizedFont *rfont = (MRealizedFont *) font;
1221 MRealizedFontXft *rfont_xft = rfont->info;
1223 rfont->info = rfont_xft->info;
1224 result = mfont__ft_driver.has_char (frame, font, spec, c, code);
1225 rfont->info = rfont_xft;
1228 result = mfont__ft_driver.has_char (frame, font, spec, c, code);
1233 xft_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
1235 if (font->type == MFONT_TYPE_REALIZED)
1237 MRealizedFont *rfont = (MRealizedFont *) font;
1238 MRealizedFontXft *rfont_xft = rfont->info;
1240 rfont->info = rfont_xft->info;
1241 code = mfont__ft_driver.encode_char (frame, font, spec, code);
1242 rfont->info = rfont_xft;
1245 code = mfont__ft_driver.encode_char (frame, font, spec, code);
1250 xft_render (MDrawWindow win, int x, int y,
1251 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1252 int reverse, MDrawRegion region)
1254 MRealizedFace *rface = from->rface;
1255 MFrame *frame = rface->frame;
1256 Display *display = FRAME_DISPLAY (frame);
1257 MRealizedFont *rfont = rface->rfont;
1258 MRealizedFontXft *rfont_xft = rfont->info;
1259 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1260 XftColor *xft_color = (! reverse
1261 ? &((GCInfo *) rface->info)->xft_color_fore
1262 : &((GCInfo *) rface->info)->xft_color_back);
1263 int anti_alias = (gstring->control.anti_alias
1264 && FRAME_DEVICE (frame)->depth > 1);
1276 if (rfont_xft->font_aa)
1277 xft_font = rfont_xft->font_aa;
1280 double size = rfont->spec.size;
1282 xft_font = xft_open_font (display, rfont->spec.file, size / 10,
1285 rfont_xft->font_aa = xft_font;
1287 xft_font = rfont->fontp;
1292 if (rfont_xft->font_no_aa)
1293 xft_font = rfont_xft->font_no_aa;
1296 double size = rfont->spec.size;
1298 xft_font = xft_open_font (display, rfont->spec.file, size / 10,
1301 rfont_xft->font_no_aa = xft_font;
1303 xft_font = rfont->fontp;
1307 XftDrawChange (xft_draw, (Drawable) win);
1308 XftDrawSetClip (xft_draw, (Region) region);
1310 y -= rfont->baseline_offset >> 6;
1311 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1312 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->g.xadv)
1314 if (g->g.xoff == 0 && g->g.yoff == 0 && !g->left_padding && !g->right_padding)
1315 glyphs[nglyphs++] = g->g.code;
1319 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1320 last_x, y, glyphs, nglyphs);
1322 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1323 x + g->g.xoff, y + g->g.yoff, (FT_UInt *) &g->g.code, 1);
1324 last_x = x + g->g.xadv;
1328 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1332 xft_check_capability (MRealizedFont *rfont, MSymbol capability)
1334 MRealizedFontXft *rfont_xft = rfont->info;
1337 rfont->info = rfont_xft->info;
1338 result = mfont__ft_driver.check_capability (rfont, capability);
1339 rfont->info = rfont_xft;
1344 xft_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
1346 MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
1347 MRealizedFontXft *rfont_xft = rfont->info;
1350 rfont->info = rfont_xft->info;
1351 result = mfont__ft_driver.check_otf (font, spec);
1352 rfont->info = rfont_xft;
1357 xft_drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
1358 MFLTGlyphString *in, int from, int to,
1359 MFLTGlyphString *out,
1360 MFLTGlyphAdjustment *adjustment)
1362 MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
1363 MRealizedFontXft *rfont_xft = rfont->info;
1366 rfont->info = rfont_xft->info;
1367 result = mfont__ft_driver.drive_otf (font, spec, in, from, to, out,
1369 rfont->info = rfont_xft;
1373 #endif /* HAVE_XFT2 */
1376 /* Functions for the device driver. */
1379 mwin__close_device (MFrame *frame)
1381 MWDevice *device = FRAME_DEVICE (frame);
1383 M17N_OBJECT_UNREF (device);
1387 mwin__device_get_prop (MFrame *frame, MSymbol key)
1389 MWDevice *device = FRAME_DEVICE (frame);
1391 if (key == Mdisplay)
1392 return (void *) device->display_info->display;
1394 return (void *) ScreenOfDisplay(device->display_info->display,
1395 device->screen_num);
1396 if (key == Mcolormap)
1397 return (void *) device->cmap;
1399 return (void *) device->depth;
1404 mwin__realize_face (MRealizedFace *rface)
1407 MSymbol foreground, background, videomode;
1408 MFaceHLineProp *hline;
1412 if (rface != rface->ascii_rface)
1414 rface->info = rface->ascii_rface->info;
1418 frame = rface->frame;
1419 MSTRUCT_CALLOC (info, MERROR_WIN);
1421 foreground = rface->face.property[MFACE_FOREGROUND];
1422 background = rface->face.property[MFACE_BACKGROUND];
1423 videomode = rface->face.property[MFACE_VIDEOMODE];
1425 videomode = frame->videomode;
1426 if (videomode != Mreverse)
1428 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1429 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1433 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1434 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1437 if (foreground == Mnil)
1438 foreground = frame->foreground;
1439 if (background == Mnil)
1440 background = frame->background;
1441 if (videomode == Mreverse)
1443 MSymbol temp = foreground;
1444 foreground = background;
1447 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1448 FRAME_VISUAL (frame),
1450 MSYMBOL_NAME (foreground),
1451 &info->xft_color_fore))
1453 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1454 FRAME_VISUAL (frame),
1456 MSYMBOL_NAME (background),
1457 &info->xft_color_back))
1459 #endif /* HAVE_XFT2 */
1461 hline = rface->hline;
1465 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1467 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1474 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1476 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1478 if (box->color_left && box->color_left != box->color_top)
1479 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1481 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1483 if (box->color_bottom && box->color_bottom != box->color_top)
1484 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1486 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1488 if (box->color_right && box->color_right != box->color_bottom)
1489 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1491 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1499 mwin__free_realized_face (MRealizedFace *rface)
1501 if (rface == rface->ascii_rface)
1507 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1509 int x, int y, int width, int height, MDrawRegion region)
1511 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1514 gc = set_region (frame, gc, region);
1516 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1517 x, y, width, height);
1522 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1523 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1524 int reverse, MDrawRegion region)
1526 MRealizedFace *rface = from->rface;
1527 Display *display = FRAME_DISPLAY (rface->frame);
1528 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1534 gc = set_region (rface->frame, gc, region);
1535 for (; from < to; from++)
1537 XDrawRectangle (display, (Window) win, gc,
1538 x, y - gstring->ascent + 1, from->g.xadv - 1,
1539 gstring->ascent + gstring->descent - 2);
1546 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1547 MRealizedFace *rface, int reverse,
1548 int x, int y, int width, MDrawRegion region)
1550 enum MFaceHLineType type = rface->hline->type;
1551 GCInfo *info = rface->info;
1552 GC gc = gc = info->gc[GC_HLINE];
1555 y = (type == MFACE_HLINE_BOTTOM
1556 ? y + gstring->text_descent - rface->hline->width
1557 : type == MFACE_HLINE_UNDER
1559 : type == MFACE_HLINE_STRIKE_THROUGH
1560 ? y - ((gstring->ascent + gstring->descent) / 2)
1561 : y - gstring->text_ascent);
1563 gc = set_region (frame, gc, region);
1565 for (i = 0; i < rface->hline->width; i++)
1566 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1567 x, y + i, x + width - 1, y + i);
1572 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1573 MGlyph *g, int x, int y, int width, MDrawRegion region)
1575 Display *display = FRAME_DISPLAY (frame);
1576 MRealizedFace *rface = g->rface;
1577 MFaceBoxProp *box = rface->box;
1578 GCInfo *info = rface->info;
1579 GC gc_top, gc_left, gc_right, gc_btm;
1583 y0 = y - (gstring->text_ascent
1584 + rface->box->inner_vmargin + rface->box->width);
1585 y1 = y + (gstring->text_descent
1586 + rface->box->inner_vmargin + rface->box->width - 1);
1588 gc_top = info->gc[GC_BOX_TOP];
1590 gc_top = set_region (frame, gc_top, region);
1591 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1594 gc_btm = info->gc[GC_BOX_BOTTOM];
1596 if (g->type == GLYPH_BOX)
1600 if (g->left_padding)
1601 x0 = x + box->outer_hmargin, x1 = x + g->g.xadv - 1;
1603 x0 = x, x1 = x + g->g.xadv - box->outer_hmargin - 1;
1605 /* Draw the top side. */
1606 for (i = 0; i < box->width; i++)
1607 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1609 /* Draw the bottom side. */
1610 if (region && gc_btm != gc_top)
1611 gc_btm = set_region (frame, gc_btm, region);
1612 for (i = 0; i < box->width; i++)
1613 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1615 if (g->left_padding > 0)
1617 /* Draw the left side. */
1618 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1622 gc_left = info->gc[GC_BOX_LEFT];
1624 gc_left = set_region (frame, gc_left, region);
1626 for (i = 0; i < rface->box->width; i++)
1627 XDrawLine (display, (Window) win, gc_left,
1628 x0 + i, y0 + i, x0 + i, y1 - i);
1632 /* Draw the right side. */
1633 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1637 gc_right = info->gc[GC_BOX_RIGHT];
1639 gc_right = set_region (frame, gc_right, region);
1641 for (i = 0; i < rface->box->width; i++)
1642 XDrawLine (display, (Window) win, gc_right,
1643 x1 - i, y0 + i, x1 - i, y1 - i);
1648 /* Draw the top side. */
1649 for (i = 0; i < box->width; i++)
1650 XDrawLine (display, (Window) win, gc_top,
1651 x, y0 + i, x + width - 1, y0 + i);
1653 /* Draw the bottom side. */
1654 if (region && gc_btm != gc_top)
1655 gc_btm = set_region (frame, gc_btm, region);
1656 for (i = 0; i < box->width; i++)
1657 XDrawLine (display, (Window) win, gc_btm,
1658 x, y1 - i, x + width - 1, y1 - i);
1665 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1666 int reverse, int x, int y,
1667 int width, int height, int row_bytes, unsigned char *bmp,
1670 Display *display = FRAME_DISPLAY (frame);
1672 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1675 gc = set_region (frame, gc, region);
1677 for (i = 0; i < height; i++, bmp += row_bytes)
1678 for (j = 0; j < width; j++)
1679 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1680 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1685 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1686 int intensity, MDrawPoint *points, int num,
1689 GCInfo *info = rface->info;
1692 if (! (gc = info->gc[intensity]))
1693 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1696 gc = set_region (frame, gc, region);
1698 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1699 (XPoint *) points, num, CoordModeOrigin);
1704 mwin__region_from_rect (MDrawMetric *rect)
1706 MDrawRegion region1 = XCreateRegion ();
1707 MDrawRegion region2 = XCreateRegion ();
1712 xrect.width = rect->width;
1713 xrect.height = rect->height;
1714 XUnionRectWithRegion (&xrect, region1, region2);
1715 XDestroyRegion (region1);
1720 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1722 MDrawRegion region1 = XCreateRegion ();
1727 xrect.width = rect->width;
1728 xrect.height = rect->height;
1730 XUnionRegion (region, region, region1);
1731 XUnionRectWithRegion (&xrect, region1, region);
1732 XDestroyRegion (region1);
1736 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1738 MDrawRegion region = XCreateRegion ();
1740 XUnionRegion (region1, region1, region);
1741 XIntersectRegion (region, region2, region1);
1742 XDestroyRegion (region);
1746 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1748 MDrawRegion region1 = XCreateRegion ();
1753 xrect.width = rect->width;
1754 xrect.height = rect->height;
1755 XUnionRectWithRegion (&xrect, region1, region);
1756 XDestroyRegion (region1);
1760 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1764 XClipBox (region, &xrect);
1767 rect->width = xrect.width;
1768 rect->height = xrect.height;
1772 mwin__free_region (MDrawRegion region)
1774 XDestroyRegion (region);
1778 mwin__dump_region (MDrawRegion region)
1781 XClipBox (region, &rect);
1782 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1787 mwin__create_window (MFrame *frame, MDrawWindow parent)
1789 Display *display = FRAME_DISPLAY (frame);
1791 XWMHints wm_hints = { InputHint, False };
1792 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1793 XSetWindowAttributes set_attrs;
1796 GCInfo *info = frame->rface->info;
1799 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1800 mask = GCForeground;
1801 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1802 set_attrs.background_pixel = values.foreground;
1803 set_attrs.backing_store = Always;
1804 set_attrs.override_redirect = True;
1805 set_attrs.save_under = True;
1806 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1807 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1808 CopyFromParent, InputOutput, CopyFromParent,
1810 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1811 NULL, &wm_hints, &class_hints);
1812 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1813 return (MDrawWindow) win;
1817 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1820 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1822 if (XftDrawDrawable (xft_draw) == (Drawable) win)
1823 XftDrawChange (xft_draw, FRAME_DEVICE (frame)->drawable);
1824 #endif /* HAVE_XFT2 */
1825 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1830 mwin__event_window (void *event)
1832 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1836 mwin__print_event (void *arg, char *win_name)
1839 XEvent *event = (XEvent *) arg;
1841 switch (event->xany.type)
1843 case 2: event_name = "KeyPress"; break;
1844 case 3: event_name = "KeyRelease"; break;
1845 case 4: event_name = "ButtonPress"; break;
1846 case 5: event_name = "ButtonRelease"; break;
1847 case 6: event_name = "MotionNotify"; break;
1848 case 7: event_name = "EnterNotify"; break;
1849 case 8: event_name = "LeaveNotify"; break;
1850 case 9: event_name = "FocusIn"; break;
1851 case 10: event_name = "FocusOut"; break;
1852 case 11: event_name = "KeymapNotify"; break;
1853 case 12: event_name = "Expose"; break;
1854 case 13: event_name = "GraphicsExpose"; break;
1855 case 14: event_name = "NoExpose"; break;
1856 case 15: event_name = "VisibilityNotify"; break;
1857 case 16: event_name = "CreateNotify"; break;
1858 case 17: event_name = "DestroyNotify"; break;
1859 case 18: event_name = "UnmapNotify"; break;
1860 case 19: event_name = "MapNotify"; break;
1861 case 20: event_name = "MapRequest"; break;
1862 case 21: event_name = "ReparentNotify"; break;
1863 case 22: event_name = "ConfigureNotify"; break;
1864 case 23: event_name = "ConfigureRequest"; break;
1865 case 24: event_name = "GravityNotify"; break;
1866 case 25: event_name = "ResizeRequest"; break;
1867 case 26: event_name = "CirculateNotify"; break;
1868 case 27: event_name = "CirculateRequest"; break;
1869 case 28: event_name = "PropertyNotify"; break;
1870 case 29: event_name = "SelectionClear"; break;
1871 case 30: event_name = "SelectionRequest"; break;
1872 case 31: event_name = "SelectionNotify"; break;
1873 case 32: event_name = "ColormapNotify"; break;
1874 case 33: event_name = "ClientMessage"; break;
1875 case 34: event_name = "MappingNotify"; break;
1876 default: event_name = "unknown";
1879 fprintf (stderr, "%s: %s\n", win_name, event_name);
1884 mwin__map_window (MFrame *frame, MDrawWindow win)
1886 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1890 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1892 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1896 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1897 MDrawMetric *geometry)
1899 Display *display = FRAME_DISPLAY (frame);
1900 XWindowAttributes attr;
1901 Window parent = (Window) parent_win, root;
1903 XGetWindowAttributes (display, (Window) win, &attr);
1904 geometry->x = attr.x + attr.border_width;
1905 geometry->y = attr.y + attr.border_width;
1906 geometry->width = attr.width;
1907 geometry->height = attr.height;
1910 parent = RootWindow (display, FRAME_SCREEN (frame));
1913 Window this_parent, *children;
1916 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1919 if (this_parent == parent || this_parent == root)
1921 win = (MDrawWindow) this_parent;
1922 XGetWindowAttributes (display, (Window) win, &attr);
1923 geometry->x += attr.x + attr.border_width;
1924 geometry->y += attr.y + attr.border_width;
1929 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1930 MDrawMetric *current, MDrawMetric *new)
1932 Display *display = FRAME_DISPLAY (frame);
1933 unsigned int mask = 0;
1934 XWindowChanges values;
1936 if (current->width != new->width)
1939 if (new->width <= 0)
1941 values.width = current->width = new->width;
1943 if (current->height != new->height)
1946 if (new->height <= 0)
1948 values.height = current->height = new->height;
1950 if (current->x != new->x)
1953 values.x = current->x = new->x;
1955 if (current->y != new->y)
1958 current->y = new->y;
1959 values.y = current->y = new->y;
1962 XConfigureWindow (display, (Window) win, mask, &values);
1963 XClearWindow (display, (Window) win);
1967 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1969 XEvent *event = (XEvent *) arg;
1970 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1977 if (event->xany.type != KeyPress
1978 /* && event->xany.type != KeyRelease */
1981 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1984 if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1986 if (len == 1 && keysym >= XK_space && keysym <= XK_asciitilde)
1990 key = minput__char_to_key (c);
1991 if (c == ' ' && ((XKeyEvent *) event)->state & ShiftMask)
1992 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1996 char *str = XKeysymToString (keysym);
2000 key = msymbol (str);
2001 if (((XKeyEvent *) event)->state & ShiftMask)
2002 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
2004 if (((XKeyEvent *) event)->state & ControlMask)
2005 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
2006 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
2007 *modifiers |= MINPUT_KEY_META_MODIFIER;
2008 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
2009 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
2010 if (((XKeyEvent *) event)->state & disp_info->super_mask)
2011 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
2012 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
2013 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
2020 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
2022 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
2024 Display *display = FRAME_DISPLAY (frame);
2025 GCInfo *info = rface->info;
2028 for (i = 0; i <= GC_INVERSE; i++)
2030 XGetGCValues (display, info->gc[i], valuemask, &values);
2031 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
2032 values.foreground, values.background);
2033 fprintf (stderr, "\n");
2037 static MDeviceDriver x_driver =
2040 mwin__device_get_prop,
2042 mwin__free_realized_face,
2044 mwin__draw_empty_boxes,
2048 mwin__region_from_rect,
2049 mwin__union_rect_with_region,
2050 mwin__intersect_region,
2051 mwin__region_add_rect,
2052 mwin__region_to_rect,
2055 mwin__create_window,
2056 mwin__destroy_window,
2059 mwin__window_geometry,
2060 mwin__adjust_window,
2064 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
2069 M_iso8859_1 = msymbol ("iso8859-1");
2070 M_iso10646_1 = msymbol ("iso10646-1");
2072 display_info_list = mplist ();
2073 device_list = mplist ();
2076 xft_driver.select = mfont__ft_driver.select;
2077 xft_driver.list = mfont__ft_driver.list;
2078 xft_driver.list_family_names = mfont__ft_driver.list_family_names;
2081 Mxim = msymbol ("xim");
2082 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
2090 M17N_OBJECT_UNREF (display_info_list);
2091 M17N_OBJECT_UNREF (device_list);
2096 #ifdef X_SET_ERROR_HANDLER
2098 x_error_handler (Display *display, XErrorEvent *error)
2105 x_io_error_handler (Display *display)
2112 /** Return an MWDevice object corresponding to a display specified in
2115 It searches device_list for a device matching the display. If
2116 found, return the found object. Otherwise, return a newly created
2120 device_open (MFrame *frame, MPlist *param)
2122 Display *display = NULL;
2123 Screen *screen = NULL;
2125 Drawable drawable = 0;
2126 Widget widget = NULL;
2128 int auto_display = 0;
2129 MDisplayInfo *disp_info = NULL;
2130 MWDevice *device = NULL;
2132 XWindowAttributes attr;
2138 int use_xfont = 0, use_freetype = 0, use_xft = 0;
2140 for (plist = param; (key = mplist_key (plist)) != Mnil;
2141 plist = mplist_next (plist))
2143 if (key == Mdisplay)
2144 display = (Display *) mplist_value (plist);
2145 else if (key == Mscreen)
2146 screen = mplist_value (plist);
2147 else if (key == Mdrawable)
2148 drawable = (Drawable) mplist_value (plist);
2149 else if (key == Mdepth)
2150 depth = (unsigned) mplist_value (plist);
2151 else if (key == Mwidget)
2152 widget = (Widget) mplist_value (plist);
2153 else if (key == Mcolormap)
2154 cmap = (Colormap) mplist_value (plist);
2155 else if (key == Mfont)
2157 MSymbol val = MPLIST_SYMBOL (plist);
2161 #ifdef HAVE_FREETYPE
2162 else if (val == Mfreetype)
2165 else if (val == Mxft)
2172 /* If none of them is specified, use all of them. */
2173 if (! use_xfont && ! use_freetype && ! use_xft)
2174 use_xfont = use_freetype = use_xft = 1;
2178 display = XtDisplay (widget);
2179 screen_num = XScreenNumberOfScreen (XtScreen (widget));
2180 depth = DefaultDepth (display, screen_num);
2186 unsigned width, height, border_width;
2189 MERROR (MERROR_WIN, -1);
2190 XGetGeometry (display, drawable, &root_window,
2191 &x, &y, &width, &height, &border_width, &depth);
2192 XGetWindowAttributes (display, root_window, &attr);
2193 screen_num = XScreenNumberOfScreen (attr.screen);
2198 display = DisplayOfScreen (screen);
2203 display = XOpenDisplay (NULL);
2205 MERROR (MERROR_WIN, -1);
2208 screen = DefaultScreenOfDisplay (display);
2210 screen_num = XScreenNumberOfScreen (screen);
2212 depth = DefaultDepth (display, screen_num);
2216 cmap = DefaultColormap (display, screen_num);
2218 for (plist = display_info_list; mplist_key (plist) != Mnil;
2219 plist = mplist_next (plist))
2221 disp_info = (MDisplayInfo *) mplist_value (plist);
2222 if (disp_info->display == display)
2226 if (mplist_key (plist) != Mnil)
2227 M17N_OBJECT_REF (disp_info);
2230 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
2231 disp_info->display = display;
2232 disp_info->auto_display = auto_display;
2233 disp_info->font_list = mplist ();
2234 find_modifier_bits (disp_info);
2235 disp_info->MULE_BASELINE_OFFSET
2236 = XInternAtom (display, "_MULE_BASELINE_OFFSET", False);
2237 disp_info->AVERAGE_WIDTH
2238 = XInternAtom (display, "AVERAGE_WIDTH", False);
2239 mplist_add (display_info_list, Mt, disp_info);
2242 for (plist = device_list; mplist_key (plist) != Mnil;
2243 plist = mplist_next (plist))
2245 device = (MWDevice *) mplist_value (plist);
2246 if (device->display_info == disp_info
2247 && device->depth == depth
2248 && device->cmap == cmap
2249 && device->screen_num == screen_num)
2253 if (mplist_key (plist) != Mnil)
2254 M17N_OBJECT_REF (device);
2257 unsigned long valuemask = GCForeground;
2261 M17N_OBJECT (device, free_device, MERROR_WIN);
2262 device->display_info = disp_info;
2263 device->screen_num = screen_num;
2264 /* A drawable on which to create GCs. */
2265 device->drawable = XCreatePixmap (display,
2266 RootWindow (display, screen_num),
2268 device->depth = depth;
2269 device->cmap = cmap;
2270 pixels = DisplayHeight (display, screen_num);
2271 mm = DisplayHeightMM (display, screen_num);
2272 device->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
2273 device->realized_face_list = mplist ();
2274 device->realized_font_list = mplist ();
2275 mplist_add (device->realized_font_list, Mt, NULL);
2276 device->realized_fontset_list = mplist ();
2277 device->gc_list = mplist ();
2278 values.foreground = BlackPixel (display, screen_num);
2279 device->scratch_gc = XCreateGC (display, device->drawable,
2280 valuemask, &values);
2282 device->xft_draw = XftDrawCreate (display, device->drawable,
2283 DefaultVisual (display, screen_num),
2288 frame->device = device;
2289 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2290 frame->dpi = device->resy;
2291 frame->driver = &x_driver;
2292 frame->font_driver_list = mplist ();
2296 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2299 #endif /* HAVE_XFT2 */
2300 #ifdef HAVE_FREETYPE
2302 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2303 #endif /* HAVE_FREETYPE */
2304 if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list))
2305 mplist_add (frame->font_driver_list, Mx, &xfont_driver);
2307 frame->realized_font_list = device->realized_font_list;
2308 frame->realized_face_list = device->realized_face_list;
2309 frame->realized_fontset_list = device->realized_fontset_list;
2313 XtResource resources[] = {
2314 { XtNfont, XtCFont, XtRString, sizeof (String),
2315 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2316 { XtNforeground, XtCForeground, XtRString, sizeof (String),
2317 XtOffset (AppDataPtr, foreground), XtRString, "black" },
2318 { XtNbackground, XtCBackground, XtRString, sizeof (String),
2319 XtOffset (AppDataPtr, background), XtRString, "white" },
2320 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2321 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2324 XtGetApplicationResources (widget, &app_data,
2325 resources, XtNumber (resources), NULL, 0);
2326 frame->foreground = msymbol (app_data.foreground);
2327 frame->background = msymbol (app_data.background);
2328 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2332 app_data.font = DEFAULT_FONT;
2333 frame->foreground = msymbol ("black");
2334 frame->background = msymbol ("white");
2335 frame->videomode = Mnormal;
2338 if (strcmp (app_data.font, DEFAULT_FONT) != 0)
2340 XFontStruct *xfont = XLoadQueryFont (display, app_data.font);
2341 unsigned long value;
2346 font = mfont_parse_name (app_data.font, Mx);
2348 && XGetFontProperty (xfont, XA_FONT, &value)
2349 && (name = ((char *) XGetAtomName (display, (Atom) value))))
2350 font = mfont_parse_name (name, Mx);
2351 XFreeFont (display, xfont);
2355 font = mfont_parse_name (DEFAULT_FONT, Mx);
2356 else if (! font->size)
2358 face = mface_from_font (font);
2360 face->property[MFACE_FONTSET] = mfontset (NULL);
2361 face->property[MFACE_FOREGROUND] = frame->foreground;
2362 face->property[MFACE_BACKGROUND] = frame->background;
2363 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2364 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2365 face->property[MFACE_VIDEOMODE] = frame->videomode;
2366 mface_put_prop (face, Mhook_func,
2367 mface_get_prop (mface__default, Mhook_func));
2368 face->property[MFACE_RATIO] = (void *) 100;
2369 mplist_push (param, Mface, face);
2370 M17N_OBJECT_UNREF (face);
2372 #ifdef X_SET_ERROR_HANDLER
2373 XSetErrorHandler (x_error_handler);
2374 XSetIOErrorHandler (x_io_error_handler);
2381 /* XIM (X Input Method) handler */
2383 typedef struct MInputXIMMethodInfo
2389 } MInputXIMMethodInfo;
2391 typedef struct MInputXIMContextInfo
2395 MConverter *converter;
2396 } MInputXIMContextInfo;
2399 xim_open_im (MInputMethod *im)
2401 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2402 MLocale *saved, *this;
2403 char *save_modifier_list;
2405 MInputXIMMethodInfo *im_info;
2407 saved = mlocale_set (LC_CTYPE, NULL);
2408 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2410 /* The specified locale is not supported. */
2411 MERROR (MERROR_LOCALE, -1);
2412 if (mlocale_get_prop (this, Mcoding) == Mnil)
2414 /* Unable to decode the output of XIM. */
2415 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2416 MERROR (MERROR_LOCALE, -1);
2419 if (arg->modifier_list)
2420 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2422 save_modifier_list = XSetLocaleModifiers ("");
2423 if (! save_modifier_list)
2425 /* The specified locale is not supported by X. */
2426 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2427 MERROR (MERROR_LOCALE, -1);
2430 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2433 /* No input method is available in the current locale. */
2434 XSetLocaleModifiers (save_modifier_list);
2435 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2436 MERROR (MERROR_WIN, -1);
2439 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2440 im_info->display = arg->display;
2442 im_info->language = mlocale_get_prop (this, Mlanguage);
2443 im_info->coding = mlocale_get_prop (this, Mcoding);
2446 XSetLocaleModifiers (save_modifier_list);
2447 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2453 xim_close_im (MInputMethod *im)
2455 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2457 XCloseIM (im_info->xim);
2462 xim_create_ic (MInputContext *ic)
2464 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2465 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2466 MInputXIMContextInfo *ic_info;
2469 if (! arg->input_style)
2471 /* By default, use Root style. */
2472 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2473 arg->preedit_attrs = NULL;
2474 arg->status_attrs = NULL;
2477 if (! arg->preedit_attrs && ! arg->status_attrs)
2478 xic = XCreateIC (im_info->xim,
2479 XNInputStyle, arg->input_style,
2480 XNClientWindow, arg->client_win,
2481 XNFocusWindow, arg->focus_win,
2483 else if (arg->preedit_attrs && ! arg->status_attrs)
2484 xic = XCreateIC (im_info->xim,
2485 XNInputStyle, arg->input_style,
2486 XNClientWindow, arg->client_win,
2487 XNFocusWindow, arg->focus_win,
2488 XNPreeditAttributes, arg->preedit_attrs,
2490 else if (! arg->preedit_attrs && arg->status_attrs)
2491 xic = XCreateIC (im_info->xim,
2492 XNInputStyle, arg->input_style,
2493 XNClientWindow, arg->client_win,
2494 XNFocusWindow, arg->focus_win,
2495 XNStatusAttributes, arg->status_attrs,
2498 xic = XCreateIC (im_info->xim,
2499 XNInputStyle, arg->input_style,
2500 XNClientWindow, arg->client_win,
2501 XNFocusWindow, arg->focus_win,
2502 XNPreeditAttributes, arg->preedit_attrs,
2503 XNStatusAttributes, arg->status_attrs,
2506 MERROR (MERROR_WIN, -1);
2508 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2510 ic_info->win = arg->focus_win;
2511 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2517 xim_destroy_ic (MInputContext *ic)
2519 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2521 XDestroyIC (ic_info->xic);
2522 mconv_free_converter (ic_info->converter);
2528 xim_filter (MInputContext *ic, MSymbol key, void *event)
2530 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2532 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2537 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2539 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2540 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2541 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2547 buf = (char *) alloca (512);
2548 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2549 if (status == XBufferOverflow)
2551 buf = (char *) alloca (len);
2552 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2555 mtext_reset (ic->produced);
2559 mconv_reset_converter (ic_info->converter);
2560 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2561 mconv_decode (ic_info->converter, ic->produced);
2562 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2563 Mlanguage, (void *) im_info->language);
2564 mtext_cpy (mt, ic->produced);
2565 mtext_reset (ic->produced);
2573 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2577 /*** @addtogroup m17nInputMethodWin */
2582 @brief Input method driver for XIM.
2584 The driver #minput_xim_driver is for the foreign input method of
2585 name #Mxim. It uses XIM (X Input Methods) as a background input
2588 As the symbol #Mxim has property #Minput_driver whose value is
2589 a pointer to this driver, the input method of language #Mnil
2590 and name #Mxim uses this driver.
2592 Therefore, for such input methods, the driver dependent arguments
2593 to the functions whose name begin with minput_ must be as follows.
2595 The argument $ARG of the function minput_open_im () must be a
2596 pointer to the structure #MInputXIMArgIM. See the documentation
2597 of #MInputXIMArgIM for more details.
2599 The argument $ARG of the function minput_create_ic () must be a
2600 pointer to the structure #MInputXIMArgIC. See the documentation
2601 of #MInputXIMArgIC for more details.
2603 The argument $ARG of the function minput_filter () must be a
2604 pointer to the structure @c XEvent. The argument $KEY is ignored.
2606 The argument $ARG of the function minput_lookup () must be the
2607 same one as that of the function minput_filter (). The argument
2611 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2613 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ê¡¢
2614 XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
2616 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2617 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim
2618 ¤Ç¤¢¤ëÆþÎϥ᥽¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2620 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_
2621 ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2623 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM
2624 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò»²¾È¡£
2626 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC
2627 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ¤ò»²¾È¡£
2629 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent
2630 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2632 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2633 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì¤ë¡£ */
2635 MInputDriver minput_xim_driver =
2636 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2637 xim_filter, xim_lookup, NULL };
2641 #else /* not HAVE_X11 */
2643 int device_open () { return -1; }
2645 #endif /* not HAVE_X11 */