1 /* m17n-X.c -- implementation of the GUI API on X Windows.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
24 /*** @addtogroup m17nInternal
36 #include <X11/keysym.h>
37 #include <X11/Xlocale.h>
38 #include <X11/Xutil.h>
39 #include <X11/Xresource.h>
40 #include <X11/Xatom.h>
41 #include <X11/StringDefs.h>
42 #include <X11/Intrinsic.h>
45 #include <X11/Xft/Xft.h>
46 #include <fontconfig/fcfreetype.h>
47 #endif /* HAVE_XFT2 */
51 #include "m17n-misc.h"
53 #include "internal-gui.h"
60 typedef struct _MFontX MFontX;
64 /* Record a font of the smallest pixel size. */
66 /* Nth bit tells the existence of a font of size N + 5. So this is
67 for 5..36 pixel size fonts. Usually this covers all sizes. */
68 unsigned int size5_36;
69 /* Fonts of (size < 5 || size > 36) are listed here (except for a
70 scalable whose size is 0). */
74 /* S must satisfy the condition (S >= 5 && S < 36). */
76 #define SET_SIZE(FONTX, S) ((FONTX)->size5_36 |= (1 << ((S) - 5)))
78 #define HAVE_SIZE(FONTX, S) ((FONTX)->size5_36 & (1 << ((S) - 5)))
82 /* Common header for the m17n object. */
87 /* If nonzero, <display> is opened by this library. Thus it should
88 be closed on freeing this structure. */
91 /** List of available X-core fonts on the display. Keys are
92 registries and values are plists whose keys are families and
93 values are pointers to MFontX. */
96 /** Nonzero means that <font_list> already contains all available
97 fonts on the display. */
100 /** Modifier bit masks of the display. */
107 /* Anchor of the chain of MDisplayInfo objects. */
108 static MPlist *display_info_list;
111 /* Color value and the corresponding GC. */
114 unsigned int rgb; /* (red << 16) | (green << 8) | blue */
121 GC_NORMAL = GC_INVERSE + 7,
134 /* The first 8 elements are indexed by an intensity for
135 anti-aliasing. The 2nd to 7th are created on demand. */
138 XftColor xft_color_fore, xft_color_back;
144 /* Common header for the m17n object. */
147 MDisplayInfo *display_info;
163 /** List of pointers to realized faces on the frame. */
164 MPlist *realized_face_list;
166 /* List of single element whose value is a root of chain of realized
168 MPlist *realized_font_list;
170 /** List of pointers to realized fontsets on the frame. */
171 MPlist *realized_fontset_list;
173 /** List of XColors vs GCs on the frame. */
177 static MPlist *device_list;
179 static MSymbol M_iso8859_1, M_iso10646_1;
181 #define FRAME_DEVICE(frame) ((MWDevice *) (frame)->device)
182 #define FRAME_DISPLAY(frame) (FRAME_DEVICE (frame)->display_info->display)
183 #define FRAME_SCREEN(frame) (FRAME_DEVICE (frame)->screen_num)
184 #define FRAME_CMAP(frame) (FRAME_DEVICE (frame)->cmap)
185 #define FRAME_VISUAL(frame) DefaultVisual (FRAME_DISPLAY (frame), \
186 FRAME_SCREEN (frame))
188 #define DEFAULT_FONT "-*-*-medium-r-normal--13-*-*-*-c-*-iso8859-1"
195 Boolean reverse_video;
196 } AppData, *AppDataPtr;
199 free_display_info (void *object)
201 MDisplayInfo *disp_info = (MDisplayInfo *) object;
204 MPLIST_DO (plist, disp_info->font_list)
206 MPLIST_DO (pl, MPLIST_VAL (plist))
208 MFontX *fontx, *next;
210 for (fontx = MPLIST_VAL (pl); fontx; fontx = next)
216 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
218 M17N_OBJECT_UNREF (disp_info->font_list);
220 if (disp_info->auto_display)
221 XCloseDisplay (disp_info->display);
227 free_device (void *object)
229 MWDevice *device = object;
232 for (plist = device->realized_fontset_list;
233 mplist_key (plist) != Mnil; plist = mplist_next (plist))
234 mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist));
235 M17N_OBJECT_UNREF (device->realized_fontset_list);
237 if (MPLIST_VAL (device->realized_font_list))
238 mfont__free_realized (MPLIST_VAL (device->realized_font_list));
239 M17N_OBJECT_UNREF (device->realized_font_list);
241 MPLIST_DO (plist, device->realized_face_list)
243 MRealizedFace *rface = MPLIST_VAL (plist);
246 mface__free_realized (rface);
248 M17N_OBJECT_UNREF (device->realized_face_list);
250 MPLIST_DO (plist, device->gc_list)
252 XFreeGC (device->display_info->display,
253 ((RGB_GC *) MPLIST_VAL (plist))->gc);
254 free (MPLIST_VAL (plist));
256 M17N_OBJECT_UNREF (device->gc_list);
257 XFreeGC (device->display_info->display, device->scratch_gc);
260 XftDrawDestroy (device->xft_draw);
263 XFreePixmap (device->display_info->display, device->drawable);
264 M17N_OBJECT_UNREF (device->display_info);
270 find_modifier_bits (MDisplayInfo *disp_info)
272 Display *display = disp_info->display;
273 XModifierKeymap *mods;
274 KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L);
275 KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R);
276 KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L);
277 KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R);
278 KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
279 KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
280 KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
281 KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
284 mods = XGetModifierMapping (display);
285 /* We skip the first three sets for Shift, Lock, and Control. The
286 remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
287 for (i = 3; i < 8; i++)
288 for (j = 0; j < mods->max_keypermod; j++)
290 KeyCode code = mods->modifiermap[i * mods->max_keypermod + j];
294 if (code == meta_l || code == meta_r)
295 disp_info->meta_mask |= (1 << i);
296 else if (code == alt_l || code == alt_r)
297 disp_info->alt_mask |= (1 << i);
298 else if (code == super_l || code == super_r)
299 disp_info->super_mask |= (1 << i);
300 else if (code == hyper_l || code == hyper_r)
301 disp_info->hyper_mask |= (1 << i);
304 /* If meta keys are not in any modifier, use alt keys as meta
306 if (! disp_info->meta_mask)
308 disp_info->meta_mask = disp_info->alt_mask;
309 disp_info->alt_mask = 0;
311 /* If both meta and alt are assigned to the same modifier, give meta
313 if (disp_info->meta_mask & disp_info->alt_mask)
314 disp_info->alt_mask &= ~disp_info->meta_mask;
316 XFreeModifiermap (mods);
320 get_rgb_gc (MWDevice *device, XColor *xcolor)
322 int rgb = (((xcolor->red >> 8) << 16) | ((xcolor->green >> 8) << 8)
323 | (xcolor->blue >> 8));
326 unsigned long valuemask = GCForeground;
329 MPLIST_DO (plist, device->gc_list)
331 rgb_gc = MPLIST_VAL (plist);
333 if (rgb_gc->rgb == rgb)
335 if (rgb_gc->rgb > rgb)
339 if (! XAllocColor (device->display_info->display, device->cmap, xcolor))
342 rgb_gc = malloc (sizeof (RGB_GC));
344 values.foreground = xcolor->pixel;
345 rgb_gc->gc = XCreateGC (device->display_info->display,
346 device->drawable, valuemask, &values);
347 mplist_push (plist, Mt, rgb_gc);
352 get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret)
354 MWDevice *device = FRAME_DEVICE (frame);
362 color = for_foreground ? frame->foreground : frame->background;
364 if (! XParseColor (FRAME_DISPLAY (frame), device->cmap,
365 msymbol_name (color), &xcolor))
367 rgb_gc = get_rgb_gc (device, &xcolor);
371 *rgb_ret = rgb_gc->rgb;
376 GCInfo *info = frame->rface->info;
381 rgb = info->rgb_fore, gc = info->gc[GC_NORMAL];
383 rgb = info->rgb_back, gc = info->gc[GC_INVERSE];
391 get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity)
393 int rgb_fore, rgb_back;
398 if (info->gc[intensity])
399 return info->gc[intensity];
401 rgb_fore = info->rgb_fore, rgb_back = info->rgb_back;
402 xcolor.red = ((((rgb_fore & 0xFF0000) >> 16) * intensity
403 + ((rgb_back & 0xFF0000) >> 16) * (7 - intensity)) / 7) << 8;
404 xcolor.green = ((((rgb_fore & 0xFF00) >> 8) * intensity
405 + ((rgb_back & 0xFF00) >> 8) * (7 - intensity)) / 7) << 8;
406 xcolor.blue = (((rgb_fore & 0xFF) * intensity
407 + (rgb_back & 0xFF) * (7 - intensity)) / 7) << 8;
408 rgb_gc = get_rgb_gc (device, &xcolor);
412 gc =get_gc_for_anti_alias (device, info,
413 intensity < 4 ? intensity - 1 : intensity + 1);
414 return (info->gc[intensity] = gc);
418 set_region (MFrame *frame, GC gc, MDrawRegion region)
420 unsigned long valuemask = GCForeground;
422 XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
423 FRAME_DEVICE (frame)->scratch_gc);
424 XSetRegion (FRAME_DISPLAY (frame), FRAME_DEVICE (frame)->scratch_gc, region);
425 return FRAME_DEVICE (frame)->scratch_gc;
429 /** X font handler */
431 static MFont *xfont_select (MFrame *, MFont *, int);
432 static MRealizedFont *xfont_open (MFrame *, MFont *, MFont *, MRealizedFont *);
433 static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int);
434 static int xfont_has_char (MFrame *, MFont *, MFont *, int, unsigned);
435 static unsigned xfont_encode_char (MFrame *, MFont *, MFont *, unsigned);
436 static void xfont_render (MDrawWindow, int, int, MGlyphString *,
437 MGlyph *, MGlyph *, int, MDrawRegion);
438 static int xfont_list (MFrame *, MPlist *, MFont *, int);
441 static MFontDriver xfont_driver =
442 { xfont_select, xfont_open,
443 xfont_find_metric, xfont_has_char, xfont_encode_char,
444 xfont_render, xfont_list };
447 font_compare (const void *p1, const void *p2)
449 return strcmp (*(char **) p1, *(char **) p2);
453 xfont_registry_list (MFrame *frame, MSymbol registry)
455 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
456 MPlist *font_list = disp_info->font_list;
459 char **font_names, **names;
464 plist = mplist_get (font_list, registry);
468 mplist_add (font_list, registry, plist);
469 sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", msymbol_name (registry));
470 font_names = XListFonts (disp_info->display, pattern, 0x8000, &nfonts);
473 names = alloca (sizeof (char *) * nfonts);
474 memcpy (names, font_names, sizeof (char *) * nfonts);
475 qsort (names, nfonts, sizeof (char *), font_compare);
477 for (i = 0, p = NULL; i < nfonts; i++)
478 if (mfont__parse_name_into_font (names[i], Mx, &font) == 0
479 && (font.size >= 50 || font.property[MFONT_RESY] == 0))
481 MSymbol family = FONT_PROPERTY (&font, MFONT_FAMILY);
482 MFontX *fontx, *fontx2;
490 if (p && MPLIST_KEY (p) != family)
491 p = mplist_find_by_key (plist, family);
493 p = mplist_push (plist, family, NULL);
495 /* Calculate how many bytes to compare to detect fonts of the
497 for (base_end = names[i], fields = 0; *base_end; base_end++)
499 && ++fields == 7 /* PIXEL_SIZE */)
501 base_len = base_end - names[i] + 1;
503 size = smallest = font.size / 10;
504 sizes[nsizes++] = size;
505 for (j = i + 1; j < nfonts && ! strncmp (names[i], names[j], base_len);
507 if (mfont__parse_name_into_font (names[j], Mx, &font) == 0
508 && (font.size >= 50 || font.property[MFONT_RESY] == 0))
510 size = font.size / 10;
514 sizes[nsizes++] = size;
517 font.type = MFONT_TYPE_OBJECT;
518 font.source = MFONT_SOURCE_X;
519 MSTRUCT_CALLOC (fontx, MERROR_WIN);
521 fontx->core.size = smallest * 10;
522 fontx->next = MPLIST_VAL (p);
523 MPLIST_VAL (p) = fontx;
525 for (j = 0; j < nsizes; j++)
529 if (sizes[j] != smallest)
530 SET_SIZE (fontx, sizes[j]);
534 MSTRUCT_CALLOC (fontx2, MERROR_WIN);
536 fontx2->core.size = sizes[j] * 10;
537 fontx2->next = MPLIST_VAL (p);
538 MPLIST_VAL (p) = fontx2;
542 XFreeFontNames (font_names);
547 xfont_list_all (MFrame *frame)
549 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
550 MPlist *font_encoding_list, *p;
552 if (disp_info->all_fonts_scaned)
554 disp_info->all_fonts_scaned = 1;
555 font_encoding_list = mfont__encoding_list ();
556 if (! font_encoding_list)
558 MPLIST_DO (p, font_encoding_list)
559 xfont_registry_list (frame, MPLIST_KEY (p));
569 /* The X font driver function SELECT. */
572 xfont_select (MFrame *frame, MFont *font, int limited_size)
574 MPlist *plist = mplist (), *pl;
575 int num = xfont_list (frame, plist, font, 0);
579 MPLIST_DO (pl, plist)
581 font = MPLIST_VAL (pl);
582 if (limited_size == 0
584 || font->size <= limited_size)
590 M17N_OBJECT_UNREF (plist);
594 /* The X font driver function CLOSE. */
597 close_xfont (void *object)
599 MRealizedFontX *x_rfont = object;
601 XFreeFont (x_rfont->display, x_rfont->xfont);
605 /* The X font driver function OPEN. */
607 static MRealizedFont *
608 xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
610 int size = spec->size;
611 MRealizedFontX *x_rfont;
613 Display *display = FRAME_DISPLAY (frame);
615 int mdebug_mask = MDEBUG_FONT;
620 for (; rfont; rfont = rfont->next)
621 if (rfont->font == font && rfont->spec.size == size)
628 /* This never fail to generate a valid fontname. */
629 name = mfont_unparse_name (&this, Mx);
630 xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
633 MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
635 font->type = MFONT_TYPE_FAILURE;
638 MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
640 M17N_OBJECT (x_rfont, close_xfont, MERROR_FONT_X);
641 x_rfont->display = display;
642 x_rfont->xfont = xfont;
643 MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
645 rfont->spec.type = MFONT_TYPE_REALIZED;
646 rfont->spec.source = MFONT_SOURCE_X;
647 rfont->frame = frame;
649 rfont->driver = &xfont_driver;
650 rfont->info = x_rfont;
651 rfont->fontp = xfont;
652 rfont->next = MPLIST_VAL (frame->realized_font_list);
653 MPLIST_VAL (frame->realized_font_list) = rfont;
658 /* The X font driver function FIND_METRIC. */
661 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
664 XFontStruct *xfont = rfont->fontp;
665 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
667 for (; g != gend; g++)
669 if (g->code == MCHAR_INVALID_CODE)
671 g->lbearing = xfont->max_bounds.lbearing;
672 g->rbearing = xfont->max_bounds.rbearing;
673 g->width = xfont->max_bounds.width;
674 g->ascent = xfont->ascent;
675 g->descent = xfont->descent;
679 int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
680 XCharStruct *pcm = NULL;
682 if (xfont->per_char != NULL)
684 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
687 && byte2 >= xfont->min_char_or_byte2
688 && byte2 <= xfont->max_char_or_byte2)
689 pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
693 if (byte1 >= xfont->min_byte1
694 && byte1 <= xfont->max_byte1
695 && byte2 >= xfont->min_char_or_byte2
696 && byte2 <= xfont->max_char_or_byte2)
698 pcm = (xfont->per_char
699 + ((xfont->max_char_or_byte2
700 - xfont->min_char_or_byte2 + 1)
701 * (byte1 - xfont->min_byte1))
702 + (byte2 - xfont->min_char_or_byte2));
709 g->lbearing = pcm->lbearing;
710 g->rbearing = pcm->rbearing;
711 g->width = pcm->width;
712 g->ascent = pcm->ascent;
713 g->descent = pcm->descent;
717 /* If the per_char pointer is null, all glyphs between
718 the first and last character indexes inclusive have
719 the same information, as given by both min_bounds and
722 g->rbearing = xfont->max_bounds.width;
723 g->width = xfont->max_bounds.width;
724 g->ascent = xfont->ascent;
725 g->descent = xfont->descent;
733 xfont_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
735 return (xfont_encode_char (frame, font, spec, code) != MCHAR_INVALID_CODE);
738 /* The X font driver function GET_GLYPH_ID. */
741 xfont_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
743 MRealizedFont *rfont;
745 unsigned min_byte1, max_byte1, min_byte2, max_byte2;
748 if (font->type == MFONT_TYPE_REALIZED)
749 rfont = (MRealizedFont *) font;
750 else if (font->type == MFONT_TYPE_OBJECT)
752 int size = spec->size;
754 for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
756 if (rfont->font == font && rfont->spec.size == size)
760 rfont = xfont_open (frame, font, spec, NULL);
762 return MCHAR_INVALID_CODE;
766 MFATAL (MERROR_FONT_X);
767 xfont = rfont->fontp;
768 all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
769 min_byte1 = xfont->min_byte1;
770 max_byte1 = xfont->max_byte1;
771 min_byte2 = xfont->min_char_or_byte2;
772 max_byte2 = xfont->max_char_or_byte2;
774 if (min_byte1 == 0 && max_byte1 == 0)
778 if (code < min_byte2 || code > max_byte2)
779 return MCHAR_INVALID_CODE;
782 pcm = xfont->per_char + (code - min_byte2);
783 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
784 ? code : MCHAR_INVALID_CODE);
788 unsigned byte1 = code >> 8, byte2 = code & 0xFF;
791 if (byte1 < min_byte1 || byte1 > max_byte1
792 || byte2 < min_byte2 || byte2 > max_byte2)
793 return MCHAR_INVALID_CODE;
797 pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
798 + (byte2 - min_byte2));
799 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
800 ? code : MCHAR_INVALID_CODE);
804 /* The X font driver function RENDER. */
807 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
808 MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
810 MRealizedFace *rface = from->rface;
811 Display *display = FRAME_DISPLAY (rface->frame);
813 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
821 gc = set_region (rface->frame, gc, region);
822 XSetFont (display, gc, ((XFontStruct *) rface->rfont->fontp)->fid);
823 code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
824 for (i = 0, g = from; g < to; i++, g++)
826 code[i].byte1 = g->code >> 8;
827 code[i].byte2 = g->code & 0xFF;
833 if (g->type == GLYPH_PAD)
835 else if (g->type == GLYPH_SPACE)
836 for (; g < to && g->type == GLYPH_SPACE; g++)
838 else if (! g->rface->rfont)
840 if ((g->c >= 0x200B && g->c <= 0x200F)
841 || (g->c >= 0x202A && g->c <= 0x202E))
845 /* As a font is not found for this character, draw an
847 int box_width = g->width;
848 int box_height = gstring->ascent + gstring->descent;
854 XDrawRectangle (display, (Window) win, gc,
855 x, y - gstring->ascent, box_width, box_height);
859 else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
861 XDrawString16 (display, (Window) win, gc,
862 x + g->xoff, y + g->yoff, code + (g - from), 1);
869 int code_idx = g - from;
872 g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
875 XDrawString16 (display, (Window) win, gc, orig_x, y,
882 xfont_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum)
884 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
885 MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil;
886 MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil;
887 int size = font ? font->size : 0;
890 int mdebug_mask = MDEBUG_FONT;
892 MDEBUG_PRINT2 (" [X-FONT] listing %s-%s...",
893 family ? msymbol_name (family) : "*",
894 registry ? msymbol_name (registry) : "*");
896 if (registry == Mnil)
897 xfont_list_all (frame);
899 xfont_registry_list (frame, registry);
901 MPLIST_DO (pl, disp_info->font_list)
903 if (registry != Mnil && registry != MPLIST_KEY (pl))
905 MPLIST_DO (p, MPLIST_VAL (pl))
909 if (family != Mnil && family != MPLIST_KEY (p))
911 for (fontx = MPLIST_VAL (p); fontx; fontx = fontx->next)
913 || (mfont__match_p (&fontx->core, font, MFONT_REGISTRY)))
915 if (fontx->core.size == size
916 || fontx->core.size == 0)
918 mplist_push (plist, MPLIST_KEY (p), fontx);
922 || (size <= 360 && HAVE_SIZE (fontx, (size / 10))))
924 unsigned size5_36 = fontx->size5_36;
929 for (i = fontx->core.size / 10; i <= 36; i++)
930 if (size5_36 & (1 << (i - 5)))
932 MSTRUCT_CALLOC (fontx2, MERROR_WIN);
933 fontx2->core = fontx->core;
934 fontx2->core.size = i * 10;
935 fontx2->next = fontx->next;
936 fontx->next = fontx2;
938 if ((size == 0 || size == fontx->core.size)
939 && (maxnum == 0 || num < maxnum))
941 mplist_push (plist, MPLIST_KEY (p), fontx);
946 if (maxnum > 0 && maxnum == num)
949 if (maxnum > 0 && maxnum == num)
952 if (maxnum > 0 && maxnum == num)
956 MDEBUG_PRINT1 (" %d found\n", num);
972 /* Pointer to MRealizedFontFT */
976 static MRealizedFont *xft_open (MFrame *frame, MFont *font, MFont *spec,
978 static int xft_has_char (MFrame *frame, MFont *font, MFont *spec,
979 int c, unsigned code);
980 static unsigned xft_encode_char (MFrame *frame, MFont *font, MFont *spec,
982 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
983 static void xft_render (MDrawWindow, int, int, MGlyphString *,
984 MGlyph *, MGlyph *, int, MDrawRegion);
986 MFontDriver xft_driver =
988 xft_find_metric, xft_has_char, xft_encode_char, xft_render, NULL };
991 close_xft (void *object)
993 MRealizedFontXft *rfont_xft = object;
995 if (rfont_xft->font_aa)
996 XftFontClose (rfont_xft->display, rfont_xft->font_aa);
997 if (rfont_xft->font_no_aa)
998 XftFontClose (rfont_xft->display, rfont_xft->font_no_aa);
999 M17N_OBJECT_UNREF (rfont_xft->info);
1005 xft_open_font (Display *display, MSymbol file, double size,
1011 pattern = FcPatternCreate ();
1012 FcPatternAddString (pattern, FC_FILE, (FcChar8 *) msymbol_name (file));
1013 FcPatternAddDouble (pattern, FC_PIXEL_SIZE, size);
1014 FcPatternAddBool (pattern, FC_ANTIALIAS, anti_alias);
1015 font = XftFontOpenPattern (display, pattern);
1020 static MRealizedFont *
1021 xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
1023 Display *display = FRAME_DISPLAY (frame);
1024 int reg = spec->property[MFONT_REGISTRY];
1026 MRealizedFontXft *rfont_xft;
1027 FcBool anti_alias = FRAME_DEVICE (frame)->depth > 1 ? FcTrue : FcFalse;
1028 double size = font->size ? font->size : spec->size;
1033 MRealizedFont *save = NULL;
1035 for (; rfont; rfont = rfont->next)
1036 if (rfont->font == font
1037 && (rfont->font->size ? rfont->font->size == size
1038 : rfont->spec.size == size)
1039 && rfont->spec.property[MFONT_REGISTRY] == reg)
1043 if (rfont->driver == &xft_driver)
1048 rfont = (mfont__ft_driver.open) (frame, font, spec, rfont);
1051 spec = &rfont->spec;
1052 ft_face = rfont->fontp;
1053 xft_font = xft_open_font (display, font->file, size / 10, anti_alias);
1056 M17N_OBJECT (rfont_xft, close_xft, MERROR_WIN);
1057 rfont_xft->display = display;
1058 if (anti_alias == FcTrue)
1059 rfont_xft->font_aa = xft_font;
1061 rfont_xft->font_no_aa = xft_font;
1062 rfont_xft->ft_face = ft_face;
1063 rfont_xft->info = rfont->info;
1064 M17N_OBJECT_REF (rfont->info);
1065 MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
1066 rfont->spec = *spec;
1067 rfont->frame = frame;
1069 rfont->driver = &xft_driver;
1070 rfont->info = rfont_xft;
1071 rfont->fontp = xft_font;
1072 rfont->next = MPLIST_VAL (frame->realized_font_list);
1073 MPLIST_VAL (frame->realized_font_list) = rfont;
1078 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1081 Display *display = FRAME_DISPLAY (rfont->frame);
1082 XftFont *xft_font = rfont->fontp;
1083 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1085 for (; g != gend; g++)
1087 if (g->code == MCHAR_INVALID_CODE)
1090 g->rbearing = xft_font->max_advance_width;
1091 g->width = g->rbearing;
1092 g->ascent = xft_font->ascent;
1093 g->descent = xft_font->descent;
1099 XftGlyphExtents (display, xft_font, &g->code, 1, &extents);
1100 g->lbearing = - extents.x;
1101 g->rbearing = extents.width - extents.x;
1102 g->width = extents.xOff;
1103 g->ascent = extents.y;
1104 g->descent = extents.height - extents.y;
1110 xft_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
1114 if (font->type == MFONT_TYPE_REALIZED)
1116 MRealizedFont *rfont = (MRealizedFont *) font;
1117 MRealizedFontXft *rfont_xft = rfont->info;
1119 rfont->info = rfont_xft->info;
1120 result = mfont__ft_driver.has_char (frame, font, spec, c, code);
1121 rfont->info = rfont_xft;
1124 result = mfont__ft_driver.has_char (frame, font, spec, c, code);
1129 xft_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
1131 if (font->type == MFONT_TYPE_REALIZED)
1133 MRealizedFont *rfont = (MRealizedFont *) font;
1134 MRealizedFontXft *rfont_xft = rfont->info;
1136 rfont->info = rfont_xft->info;
1137 code = mfont__ft_driver.encode_char (frame, font, spec, code);
1138 rfont->info = rfont_xft;
1141 code = mfont__ft_driver.encode_char (frame, font, spec, code);
1146 xft_render (MDrawWindow win, int x, int y,
1147 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1148 int reverse, MDrawRegion region)
1150 MRealizedFace *rface = from->rface;
1151 MFrame *frame = rface->frame;
1152 Display *display = FRAME_DISPLAY (frame);
1153 MRealizedFont *rfont = rface->rfont;
1154 MRealizedFontXft *rfont_xft = rfont->info;
1155 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1156 XftColor *xft_color = (! reverse
1157 ? &((GCInfo *) rface->info)->xft_color_fore
1158 : &((GCInfo *) rface->info)->xft_color_back);
1159 int anti_alias = (gstring->control.anti_alias
1160 && FRAME_DEVICE (frame)->depth > 1);
1172 if (rfont_xft->font_aa)
1173 xft_font = rfont_xft->font_aa;
1176 double size = rfont->spec.size;
1178 xft_font = xft_open_font (display, rfont->spec.file, size / 10,
1181 rfont_xft->font_aa = xft_font;
1183 xft_font = rfont->fontp;
1188 if (rfont_xft->font_no_aa)
1189 xft_font = rfont_xft->font_no_aa;
1192 double size = rfont->spec.size;
1194 xft_font = xft_open_font (display, rfont->spec.file, size / 10,
1197 rfont_xft->font_no_aa = xft_font;
1199 xft_font = rfont->fontp;
1203 XftDrawChange (xft_draw, (Drawable) win);
1204 XftDrawSetClip (xft_draw, (Region) region);
1206 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1207 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1209 if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1210 glyphs[nglyphs++] = g->code;
1214 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1215 last_x, y, glyphs, nglyphs);
1217 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1218 x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1219 last_x = x + g->width;
1223 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1226 #endif /* HAVE_XFT2 */
1229 /* Functions for the device driver. */
1232 mwin__close_device (MFrame *frame)
1234 MWDevice *device = FRAME_DEVICE (frame);
1236 M17N_OBJECT_UNREF (device);
1240 mwin__device_get_prop (MFrame *frame, MSymbol key)
1242 MWDevice *device = FRAME_DEVICE (frame);
1244 if (key == Mdisplay)
1245 return (void *) device->display_info->display;
1247 return (void *) ScreenOfDisplay(device->display_info->display,
1248 device->screen_num);
1249 if (key == Mcolormap)
1250 return (void *) device->cmap;
1252 return (void *) device->depth;
1257 mwin__realize_face (MRealizedFace *rface)
1260 MSymbol foreground, background, videomode;
1261 MFaceHLineProp *hline;
1265 if (rface != rface->ascii_rface)
1267 rface->info = rface->ascii_rface->info;
1271 frame = rface->frame;
1272 MSTRUCT_CALLOC (info, MERROR_WIN);
1274 foreground = rface->face.property[MFACE_FOREGROUND];
1275 background = rface->face.property[MFACE_BACKGROUND];
1276 videomode = rface->face.property[MFACE_VIDEOMODE];
1278 videomode = frame->videomode;
1279 if (videomode != Mreverse)
1281 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1282 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1286 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1287 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1290 if (foreground == Mnil)
1291 foreground = frame->foreground;
1292 if (background == Mnil)
1293 background = frame->background;
1294 if (videomode == Mreverse)
1296 MSymbol temp = foreground;
1297 foreground = background;
1300 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1301 FRAME_VISUAL (frame),
1303 MSYMBOL_NAME (foreground),
1304 &info->xft_color_fore))
1306 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1307 FRAME_VISUAL (frame),
1309 MSYMBOL_NAME (background),
1310 &info->xft_color_back))
1312 #endif /* HAVE_XFT2 */
1314 hline = rface->hline;
1318 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1320 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1327 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1329 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1331 if (box->color_left && box->color_left != box->color_top)
1332 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1334 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1336 if (box->color_bottom && box->color_bottom != box->color_top)
1337 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1339 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1341 if (box->color_right && box->color_right != box->color_bottom)
1342 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1344 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1352 mwin__free_realized_face (MRealizedFace *rface)
1354 if (rface == rface->ascii_rface)
1360 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1362 int x, int y, int width, int height, MDrawRegion region)
1364 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1367 gc = set_region (frame, gc, region);
1369 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1370 x, y, width, height);
1375 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1376 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1377 int reverse, MDrawRegion region)
1379 MRealizedFace *rface = from->rface;
1380 Display *display = FRAME_DISPLAY (rface->frame);
1381 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1387 gc = set_region (rface->frame, gc, region);
1388 for (; from < to; from++)
1390 XDrawRectangle (display, (Window) win, gc,
1391 x, y - gstring->ascent + 1, from->width - 1,
1392 gstring->ascent + gstring->descent - 2);
1399 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1400 MRealizedFace *rface, int reverse,
1401 int x, int y, int width, MDrawRegion region)
1403 enum MFaceHLineType type = rface->hline->type;
1404 GCInfo *info = rface->info;
1405 GC gc = gc = info->gc[GC_HLINE];
1408 y = (type == MFACE_HLINE_BOTTOM
1409 ? y + gstring->text_descent - rface->hline->width
1410 : type == MFACE_HLINE_UNDER
1412 : type == MFACE_HLINE_STRIKE_THROUGH
1413 ? y - ((gstring->ascent + gstring->descent) / 2)
1414 : y - gstring->text_ascent);
1416 gc = set_region (frame, gc, region);
1418 for (i = 0; i < rface->hline->width; i++)
1419 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1420 x, y + i, x + width - 1, y + i);
1425 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1426 MGlyph *g, int x, int y, int width, MDrawRegion region)
1428 Display *display = FRAME_DISPLAY (frame);
1429 MRealizedFace *rface = g->rface;
1430 MFaceBoxProp *box = rface->box;
1431 GCInfo *info = rface->info;
1432 GC gc_top, gc_left, gc_right, gc_btm;
1436 y0 = y - (gstring->text_ascent
1437 + rface->box->inner_vmargin + rface->box->width);
1438 y1 = y + (gstring->text_descent
1439 + rface->box->inner_vmargin + rface->box->width - 1);
1441 gc_top = info->gc[GC_BOX_TOP];
1443 gc_top = set_region (frame, gc_top, region);
1444 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1447 gc_btm = info->gc[GC_BOX_BOTTOM];
1449 if (g->type == GLYPH_BOX)
1453 if (g->left_padding)
1454 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1456 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1458 /* Draw the top side. */
1459 for (i = 0; i < box->width; i++)
1460 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1462 /* Draw the bottom side. */
1463 if (region && gc_btm != gc_top)
1464 gc_btm = set_region (frame, gc_btm, region);
1465 for (i = 0; i < box->width; i++)
1466 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1468 if (g->left_padding > 0)
1470 /* Draw the left side. */
1471 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1475 gc_left = info->gc[GC_BOX_LEFT];
1477 gc_left = set_region (frame, gc_left, region);
1479 for (i = 0; i < rface->box->width; i++)
1480 XDrawLine (display, (Window) win, gc_left,
1481 x0 + i, y0 + i, x0 + i, y1 - i);
1485 /* Draw the right side. */
1486 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1490 gc_right = info->gc[GC_BOX_RIGHT];
1492 gc_right = set_region (frame, gc_right, region);
1494 for (i = 0; i < rface->box->width; i++)
1495 XDrawLine (display, (Window) win, gc_right,
1496 x1 - i, y0 + i, x1 - i, y1 - i);
1501 /* Draw the top side. */
1502 for (i = 0; i < box->width; i++)
1503 XDrawLine (display, (Window) win, gc_top,
1504 x, y0 + i, x + width - 1, y0 + i);
1506 /* Draw the bottom side. */
1507 if (region && gc_btm != gc_top)
1508 gc_btm = set_region (frame, gc_btm, region);
1509 for (i = 0; i < box->width; i++)
1510 XDrawLine (display, (Window) win, gc_btm,
1511 x, y1 - i, x + width - 1, y1 - i);
1518 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1519 int reverse, int x, int y,
1520 int width, int height, int row_bytes, unsigned char *bmp,
1523 Display *display = FRAME_DISPLAY (frame);
1525 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1528 gc = set_region (frame, gc, region);
1530 for (i = 0; i < height; i++, bmp += row_bytes)
1531 for (j = 0; j < width; j++)
1532 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1533 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1538 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1539 int intensity, MDrawPoint *points, int num,
1542 GCInfo *info = rface->info;
1545 if (! (gc = info->gc[intensity]))
1546 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1549 gc = set_region (frame, gc, region);
1551 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1552 (XPoint *) points, num, CoordModeOrigin);
1557 mwin__region_from_rect (MDrawMetric *rect)
1559 MDrawRegion region1 = XCreateRegion ();
1560 MDrawRegion region2 = XCreateRegion ();
1565 xrect.width = rect->width;
1566 xrect.height = rect->height;
1567 XUnionRectWithRegion (&xrect, region1, region2);
1568 XDestroyRegion (region1);
1573 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1575 MDrawRegion region1 = XCreateRegion ();
1580 xrect.width = rect->width;
1581 xrect.height = rect->height;
1583 XUnionRegion (region, region, region1);
1584 XUnionRectWithRegion (&xrect, region1, region);
1585 XDestroyRegion (region1);
1589 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1591 MDrawRegion region = XCreateRegion ();
1593 XUnionRegion (region1, region1, region);
1594 XIntersectRegion (region, region2, region1);
1595 XDestroyRegion (region);
1599 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1601 MDrawRegion region1 = XCreateRegion ();
1606 xrect.width = rect->width;
1607 xrect.height = rect->height;
1608 XUnionRectWithRegion (&xrect, region1, region);
1609 XDestroyRegion (region1);
1613 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1617 XClipBox (region, &xrect);
1620 rect->width = xrect.width;
1621 rect->height = xrect.height;
1625 mwin__free_region (MDrawRegion region)
1627 XDestroyRegion (region);
1631 mwin__dump_region (MDrawRegion region)
1634 XClipBox (region, &rect);
1635 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1640 mwin__create_window (MFrame *frame, MDrawWindow parent)
1642 Display *display = FRAME_DISPLAY (frame);
1644 XWMHints wm_hints = { InputHint, False };
1645 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1646 XSetWindowAttributes set_attrs;
1649 GCInfo *info = frame->rface->info;
1652 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1653 mask = GCForeground;
1654 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1655 set_attrs.background_pixel = values.foreground;
1656 set_attrs.backing_store = Always;
1657 set_attrs.override_redirect = True;
1658 set_attrs.save_under = True;
1659 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1660 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1661 CopyFromParent, InputOutput, CopyFromParent,
1663 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1664 NULL, &wm_hints, &class_hints);
1665 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1666 return (MDrawWindow) win;
1670 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1672 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1677 mwin__event_window (void *event)
1679 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1683 mwin__print_event (void *arg, char *win_name)
1686 XEvent *event = (XEvent *) arg;
1688 switch (event->xany.type)
1690 case 2: event_name = "KeyPress"; break;
1691 case 3: event_name = "KeyRelease"; break;
1692 case 4: event_name = "ButtonPress"; break;
1693 case 5: event_name = "ButtonRelease"; break;
1694 case 6: event_name = "MotionNotify"; break;
1695 case 7: event_name = "EnterNotify"; break;
1696 case 8: event_name = "LeaveNotify"; break;
1697 case 9: event_name = "FocusIn"; break;
1698 case 10: event_name = "FocusOut"; break;
1699 case 11: event_name = "KeymapNotify"; break;
1700 case 12: event_name = "Expose"; break;
1701 case 13: event_name = "GraphicsExpose"; break;
1702 case 14: event_name = "NoExpose"; break;
1703 case 15: event_name = "VisibilityNotify"; break;
1704 case 16: event_name = "CreateNotify"; break;
1705 case 17: event_name = "DestroyNotify"; break;
1706 case 18: event_name = "UnmapNotify"; break;
1707 case 19: event_name = "MapNotify"; break;
1708 case 20: event_name = "MapRequest"; break;
1709 case 21: event_name = "ReparentNotify"; break;
1710 case 22: event_name = "ConfigureNotify"; break;
1711 case 23: event_name = "ConfigureRequest"; break;
1712 case 24: event_name = "GravityNotify"; break;
1713 case 25: event_name = "ResizeRequest"; break;
1714 case 26: event_name = "CirculateNotify"; break;
1715 case 27: event_name = "CirculateRequest"; break;
1716 case 28: event_name = "PropertyNotify"; break;
1717 case 29: event_name = "SelectionClear"; break;
1718 case 30: event_name = "SelectionRequest"; break;
1719 case 31: event_name = "SelectionNotify"; break;
1720 case 32: event_name = "ColormapNotify"; break;
1721 case 33: event_name = "ClientMessage"; break;
1722 case 34: event_name = "MappingNotify"; break;
1723 default: event_name = "unknown";
1726 fprintf (stderr, "%s: %s\n", win_name, event_name);
1731 mwin__map_window (MFrame *frame, MDrawWindow win)
1733 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1737 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1739 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1743 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1744 MDrawMetric *geometry)
1746 Display *display = FRAME_DISPLAY (frame);
1747 XWindowAttributes attr;
1748 Window parent = (Window) parent_win, root;
1750 XGetWindowAttributes (display, (Window) win, &attr);
1751 geometry->x = attr.x + attr.border_width;
1752 geometry->y = attr.y + attr.border_width;
1753 geometry->width = attr.width;
1754 geometry->height = attr.height;
1757 parent = RootWindow (display, FRAME_SCREEN (frame));
1760 Window this_parent, *children;
1763 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1766 if (this_parent == parent || this_parent == root)
1768 win = (MDrawWindow) this_parent;
1769 XGetWindowAttributes (display, (Window) win, &attr);
1770 geometry->x += attr.x + attr.border_width;
1771 geometry->y += attr.y + attr.border_width;
1776 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1777 MDrawMetric *current, MDrawMetric *new)
1779 Display *display = FRAME_DISPLAY (frame);
1780 unsigned int mask = 0;
1781 XWindowChanges values;
1783 if (current->width != new->width)
1786 if (new->width <= 0)
1788 values.width = current->width = new->width;
1790 if (current->height != new->height)
1793 if (new->height <= 0)
1795 values.height = current->height = new->height;
1797 if (current->x != new->x)
1800 values.x = current->x = new->x;
1802 if (current->y != new->y)
1805 current->y = new->y;
1806 values.y = current->y = new->y;
1809 XConfigureWindow (display, (Window) win, mask, &values);
1810 XClearWindow (display, (Window) win);
1814 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1816 XEvent *event = (XEvent *) arg;
1817 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1824 if (event->xany.type != KeyPress
1825 /* && event->xany.type != KeyRelease */
1828 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1835 if (c < XK_space || c > XK_asciitilde)
1837 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1838 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1839 if (((XKeyEvent *) event)->state & ControlMask)
1841 if (c >= 'a' && c <= 'z')
1843 if (c >= ' ' && c < 127)
1844 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1846 key = minput__char_to_key (c);
1848 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1852 char *str = XKeysymToString (keysym);
1856 key = msymbol (str);
1857 if (((XKeyEvent *) event)->state & ShiftMask)
1858 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1859 if (((XKeyEvent *) event)->state & ControlMask)
1860 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1862 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1863 *modifiers |= MINPUT_KEY_META_MODIFIER;
1864 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1865 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1866 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1867 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1868 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1869 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1876 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1878 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1880 Display *display = FRAME_DISPLAY (frame);
1881 GCInfo *info = rface->info;
1884 for (i = 0; i <= GC_INVERSE; i++)
1886 XGetGCValues (display, info->gc[i], valuemask, &values);
1887 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1888 values.foreground, values.background);
1889 fprintf (stderr, "\n");
1893 static MDeviceDriver x_driver =
1896 mwin__device_get_prop,
1898 mwin__free_realized_face,
1900 mwin__draw_empty_boxes,
1904 mwin__region_from_rect,
1905 mwin__union_rect_with_region,
1906 mwin__intersect_region,
1907 mwin__region_add_rect,
1908 mwin__region_to_rect,
1911 mwin__create_window,
1912 mwin__destroy_window,
1915 mwin__window_geometry,
1916 mwin__adjust_window,
1920 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1925 M_iso8859_1 = msymbol ("iso8859-1");
1926 M_iso10646_1 = msymbol ("iso10646-1");
1928 display_info_list = mplist ();
1929 device_list = mplist ();
1932 xft_driver.select = mfont__ft_driver.select;
1933 xft_driver.list = mfont__ft_driver.list;
1936 Mxim = msymbol ("xim");
1937 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1945 M17N_OBJECT_UNREF (display_info_list);
1946 M17N_OBJECT_UNREF (device_list);
1951 #ifdef X_SET_ERROR_HANDLER
1953 x_error_handler (Display *display, XErrorEvent *error)
1960 x_io_error_handler (Display *display)
1967 /** Return an MWDevice object corresponding to a display specified in
1970 It searches device_list for a device matching the display. If
1971 found, return the found object. Otherwise, return a newly created
1975 device_open (MFrame *frame, MPlist *param)
1977 Display *display = NULL;
1978 Screen *screen = NULL;
1980 Drawable drawable = 0;
1981 Widget widget = NULL;
1983 int auto_display = 0;
1984 MDisplayInfo *disp_info = NULL;
1985 MWDevice *device = NULL;
1987 XWindowAttributes attr;
1993 int use_xfont = 0, use_freetype = 0, use_xft = 0;
1995 for (plist = param; (key = mplist_key (plist)) != Mnil;
1996 plist = mplist_next (plist))
1998 if (key == Mdisplay)
1999 display = (Display *) mplist_value (plist);
2000 else if (key == Mscreen)
2001 screen = mplist_value (plist);
2002 else if (key == Mdrawable)
2003 drawable = (Drawable) mplist_value (plist);
2004 else if (key == Mdepth)
2005 depth = (unsigned) mplist_value (plist);
2006 else if (key == Mwidget)
2007 widget = (Widget) mplist_value (plist);
2008 else if (key == Mcolormap)
2009 cmap = (Colormap) mplist_value (plist);
2010 else if (key == Mfont)
2012 MSymbol val = MPLIST_SYMBOL (plist);
2016 #ifdef HAVE_FREETYPE
2017 else if (val == Mfreetype)
2020 else if (val == Mxft)
2027 /* If none of them is specified, use all of them. */
2028 if (! use_xfont && ! use_freetype && ! use_xft)
2029 use_xfont = use_freetype = use_xft = 1;
2033 display = XtDisplay (widget);
2034 screen_num = XScreenNumberOfScreen (XtScreen (widget));
2035 depth = DefaultDepth (display, screen_num);
2041 unsigned width, height, border_width;
2044 MERROR (MERROR_WIN, -1);
2045 XGetGeometry (display, drawable, &root_window,
2046 &x, &y, &width, &height, &border_width, &depth);
2047 XGetWindowAttributes (display, root_window, &attr);
2048 screen_num = XScreenNumberOfScreen (attr.screen);
2053 display = DisplayOfScreen (screen);
2058 display = XOpenDisplay (NULL);
2060 MERROR (MERROR_WIN, -1);
2063 screen = DefaultScreenOfDisplay (display);
2065 screen_num = XScreenNumberOfScreen (screen);
2067 depth = DefaultDepth (display, screen_num);
2071 cmap = DefaultColormap (display, screen_num);
2073 for (plist = display_info_list; mplist_key (plist) != Mnil;
2074 plist = mplist_next (plist))
2076 disp_info = (MDisplayInfo *) mplist_value (plist);
2077 if (disp_info->display == display)
2081 if (mplist_key (plist) != Mnil)
2082 M17N_OBJECT_REF (disp_info);
2085 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
2086 disp_info->display = display;
2087 disp_info->auto_display = auto_display;
2088 disp_info->font_list = mplist ();
2089 find_modifier_bits (disp_info);
2090 mplist_add (display_info_list, Mt, disp_info);
2093 for (plist = device_list; mplist_key (plist) != Mnil;
2094 plist = mplist_next (plist))
2096 device = (MWDevice *) mplist_value (plist);
2097 if (device->display_info == disp_info
2098 && device->depth == depth
2099 && device->cmap == cmap)
2103 if (mplist_key (plist) != Mnil)
2104 M17N_OBJECT_REF (device);
2107 unsigned long valuemask = GCForeground;
2110 M17N_OBJECT (device, free_device, MERROR_WIN);
2111 device->display_info = disp_info;
2112 device->screen_num = screen_num;
2113 /* A drawable on which to create GCs. */
2114 device->drawable = XCreatePixmap (display,
2115 RootWindow (display, screen_num),
2117 device->depth = depth;
2118 device->cmap = cmap;
2119 device->realized_face_list = mplist ();
2120 device->realized_font_list = mplist ();
2121 mplist_add (device->realized_font_list, Mt, NULL);
2122 device->realized_fontset_list = mplist ();
2123 device->gc_list = mplist ();
2124 values.foreground = BlackPixel (display, screen_num);
2125 device->scratch_gc = XCreateGC (display, device->drawable,
2126 valuemask, &values);
2128 device->xft_draw = XftDrawCreate (display, device->drawable,
2129 DefaultVisual (display, screen_num),
2134 frame->device = device;
2135 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2136 frame->driver = &x_driver;
2137 frame->font_driver_list = mplist ();
2141 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2144 #endif /* HAVE_XFT2 */
2145 #ifdef HAVE_FREETYPE
2147 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2148 #endif /* HAVE_FREETYPE */
2149 if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list))
2150 mplist_push (frame->font_driver_list, Mx, &xfont_driver);
2152 frame->realized_font_list = device->realized_font_list;
2153 frame->realized_face_list = device->realized_face_list;
2154 frame->realized_fontset_list = device->realized_fontset_list;
2158 XtResource resources[] = {
2159 { XtNfont, XtCFont, XtRString, sizeof (String),
2160 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2161 { XtNforeground, XtCForeground, XtRString, sizeof (String),
2162 XtOffset (AppDataPtr, foreground), XtRString, "black" },
2163 { XtNbackground, XtCBackground, XtRString, sizeof (String),
2164 XtOffset (AppDataPtr, background), XtRString, "white" },
2165 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2166 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2169 XtGetApplicationResources (widget, &app_data,
2170 resources, XtNumber (resources), NULL, 0);
2171 frame->foreground = msymbol (app_data.foreground);
2172 frame->background = msymbol (app_data.background);
2173 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2177 app_data.font = DEFAULT_FONT;
2178 frame->foreground = msymbol ("black");
2179 frame->background = msymbol ("white");
2180 frame->videomode = Mnormal;
2183 if (strcmp (app_data.font, DEFAULT_FONT) != 0)
2185 XFontStruct *xfont = XLoadQueryFont (display, app_data.font);
2186 unsigned long value;
2191 font = mfont_parse_name (app_data.font, Mx);
2193 && XGetFontProperty (xfont, XA_FONT, &value)
2194 && (name = ((char *) XGetAtomName (display, (Atom) value))))
2195 font = mfont_parse_name (name, Mx);
2196 XFreeFont (display, xfont);
2200 font = mfont_parse_name (DEFAULT_FONT, Mx);
2201 else if (! font->size)
2203 face = mface_from_font (font);
2205 face->property[MFACE_FONTSET] = mfontset (NULL);
2206 face->property[MFACE_FOREGROUND] = frame->foreground;
2207 face->property[MFACE_BACKGROUND] = frame->background;
2208 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2209 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2210 face->property[MFACE_VIDEOMODE] = frame->videomode;
2211 mface_put_prop (face, Mhook_func,
2212 mface_get_prop (mface__default, Mhook_func));
2213 face->property[MFACE_RATIO] = (void *) 100;
2214 mplist_push (param, Mface, face);
2215 M17N_OBJECT_UNREF (face);
2217 #ifdef X_SET_ERROR_HANDLER
2218 XSetErrorHandler (x_error_handler);
2219 XSetIOErrorHandler (x_io_error_handler);
2226 /* XIM (X Input Method) handler */
2228 typedef struct MInputXIMMethodInfo
2234 } MInputXIMMethodInfo;
2236 typedef struct MInputXIMContextInfo
2240 MConverter *converter;
2241 } MInputXIMContextInfo;
2244 xim_open_im (MInputMethod *im)
2246 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2247 MLocale *saved, *this;
2248 char *save_modifier_list;
2250 MInputXIMMethodInfo *im_info;
2252 saved = mlocale_set (LC_CTYPE, NULL);
2253 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2255 /* The specified locale is not supported. */
2256 MERROR (MERROR_LOCALE, -1);
2257 if (mlocale_get_prop (this, Mcoding) == Mnil)
2259 /* Unable to decode the output of XIM. */
2260 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2261 MERROR (MERROR_LOCALE, -1);
2264 if (arg->modifier_list)
2265 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2267 save_modifier_list = XSetLocaleModifiers ("");
2268 if (! save_modifier_list)
2270 /* The specified locale is not supported by X. */
2271 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2272 MERROR (MERROR_LOCALE, -1);
2275 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2278 /* No input method is available in the current locale. */
2279 XSetLocaleModifiers (save_modifier_list);
2280 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2281 MERROR (MERROR_WIN, -1);
2284 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2285 im_info->display = arg->display;
2287 im_info->language = mlocale_get_prop (this, Mlanguage);
2288 im_info->coding = mlocale_get_prop (this, Mcoding);
2291 XSetLocaleModifiers (save_modifier_list);
2292 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2298 xim_close_im (MInputMethod *im)
2300 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2302 XCloseIM (im_info->xim);
2307 xim_create_ic (MInputContext *ic)
2309 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2310 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2311 MInputXIMContextInfo *ic_info;
2314 if (! arg->input_style)
2316 /* By default, use Root style. */
2317 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2318 arg->preedit_attrs = NULL;
2319 arg->status_attrs = NULL;
2322 if (! arg->preedit_attrs && ! arg->status_attrs)
2323 xic = XCreateIC (im_info->xim,
2324 XNInputStyle, arg->input_style,
2325 XNClientWindow, arg->client_win,
2326 XNFocusWindow, arg->focus_win,
2328 else if (arg->preedit_attrs && ! arg->status_attrs)
2329 xic = XCreateIC (im_info->xim,
2330 XNInputStyle, arg->input_style,
2331 XNClientWindow, arg->client_win,
2332 XNFocusWindow, arg->focus_win,
2333 XNPreeditAttributes, arg->preedit_attrs,
2335 else if (! arg->preedit_attrs && arg->status_attrs)
2336 xic = XCreateIC (im_info->xim,
2337 XNInputStyle, arg->input_style,
2338 XNClientWindow, arg->client_win,
2339 XNFocusWindow, arg->focus_win,
2340 XNStatusAttributes, arg->status_attrs,
2343 xic = XCreateIC (im_info->xim,
2344 XNInputStyle, arg->input_style,
2345 XNClientWindow, arg->client_win,
2346 XNFocusWindow, arg->focus_win,
2347 XNPreeditAttributes, arg->preedit_attrs,
2348 XNStatusAttributes, arg->status_attrs,
2351 MERROR (MERROR_WIN, -1);
2353 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2355 ic_info->win = arg->focus_win;
2356 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2362 xim_destroy_ic (MInputContext *ic)
2364 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2366 XDestroyIC (ic_info->xic);
2367 mconv_free_converter (ic_info->converter);
2373 xim_filter (MInputContext *ic, MSymbol key, void *event)
2375 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2377 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2382 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2384 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2385 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2386 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2392 buf = (char *) alloca (512);
2393 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2394 if (status == XBufferOverflow)
2396 buf = (char *) alloca (len);
2397 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2400 mtext_reset (ic->produced);
2404 mconv_reset_converter (ic_info->converter);
2405 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2406 mconv_decode (ic_info->converter, ic->produced);
2407 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2408 Mlanguage, (void *) im_info->language);
2409 mtext_cpy (mt, ic->produced);
2410 mtext_reset (ic->produced);
2418 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2422 /*** @addtogroup m17nInputMethodWin */
2427 @brief Input method driver for XIM.
2429 The driver #minput_xim_driver is for the foreign input method of
2430 name #Mxim. It uses XIM (X Input Methods) as a background input
2433 As the symbol #Mxim has property #Minput_driver whose value is
2434 a pointer to this driver, the input method of language #Mnil
2435 and name #Mxim uses this driver.
2437 Therefore, for such input methods, the driver dependent arguments
2438 to the functions whose name begin with minput_ must be as follows.
2440 The argument $ARG of the function minput_open_im () must be a
2441 pointer to the structure #MInputXIMArgIM. See the documentation
2442 of #MInputXIMArgIM for more details.
2444 The argument $ARG of the function minput_create_ic () must be a
2445 pointer to the structure #MInputXIMArgIC. See the documentation
2446 of #MInputXIMArgIC for more details.
2448 The argument $ARG of the function minput_filter () must be a
2449 pointer to the structure @c XEvent. The argument $KEY is ignored.
2451 The argument $ARG of the function minput_lookup () must be the
2452 same one as that of the function minput_filter (). The argument
2456 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2458 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ê¡¢
2459 XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
2461 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2462 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim
2463 ¤Ç¤¢¤ëÆþÎϥ᥽¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2465 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_
2466 ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2468 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM
2469 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò»²¾È¡£
2471 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC
2472 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ¤ò»²¾È¡£
2474 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent
2475 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2477 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2478 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì¤ë¡£ */
2480 MInputDriver minput_xim_driver =
2481 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2482 xim_filter, xim_lookup, NULL };