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)
627 /* This never fail to generate a valid fontname. */
628 name = mfont_unparse_name (&this, Mx);
629 xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
632 MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
634 font->type = MFONT_TYPE_FAILURE;
637 MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
639 M17N_OBJECT (x_rfont, close_xfont, MERROR_FONT_X);
640 x_rfont->display = display;
641 x_rfont->xfont = xfont;
642 MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
644 rfont->spec.type = MFONT_TYPE_REALIZED;
645 rfont->spec.source = MFONT_SOURCE_X;
646 rfont->frame = frame;
648 rfont->driver = &xfont_driver;
649 rfont->info = x_rfont;
650 rfont->ascent = xfont->ascent;
651 rfont->descent = xfont->descent;
652 rfont->max_advance = xfont->max_bounds.width;
653 rfont->fontp = xfont;
654 rfont->next = MPLIST_VAL (frame->realized_font_list);
655 MPLIST_VAL (frame->realized_font_list) = rfont;
660 /* The X font driver function FIND_METRIC. */
663 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
666 XFontStruct *xfont = rfont->fontp;
667 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
669 for (; g != gend; g++)
671 if (g->code == MCHAR_INVALID_CODE)
673 g->lbearing = xfont->max_bounds.lbearing;
674 g->rbearing = xfont->max_bounds.rbearing;
675 g->width = xfont->max_bounds.width;
676 g->ascent = xfont->ascent;
677 g->descent = xfont->descent;
681 int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
682 XCharStruct *pcm = NULL;
684 if (xfont->per_char != NULL)
686 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
689 && byte2 >= xfont->min_char_or_byte2
690 && byte2 <= xfont->max_char_or_byte2)
691 pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
695 if (byte1 >= xfont->min_byte1
696 && byte1 <= xfont->max_byte1
697 && byte2 >= xfont->min_char_or_byte2
698 && byte2 <= xfont->max_char_or_byte2)
700 pcm = (xfont->per_char
701 + ((xfont->max_char_or_byte2
702 - xfont->min_char_or_byte2 + 1)
703 * (byte1 - xfont->min_byte1))
704 + (byte2 - xfont->min_char_or_byte2));
711 g->lbearing = pcm->lbearing;
712 g->rbearing = pcm->rbearing;
713 g->width = pcm->width;
714 g->ascent = pcm->ascent;
715 g->descent = pcm->descent;
719 /* If the per_char pointer is null, all glyphs between
720 the first and last character indexes inclusive have
721 the same information, as given by both min_bounds and
724 g->rbearing = xfont->max_bounds.width;
725 g->width = xfont->max_bounds.width;
726 g->ascent = xfont->ascent;
727 g->descent = xfont->descent;
735 xfont_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
737 return (xfont_encode_char (frame, font, spec, code) != MCHAR_INVALID_CODE);
740 /* The X font driver function GET_GLYPH_ID. */
743 xfont_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
745 MRealizedFont *rfont;
747 unsigned min_byte1, max_byte1, min_byte2, max_byte2;
750 if (font->type == MFONT_TYPE_REALIZED)
751 rfont = (MRealizedFont *) font;
752 else if (font->type == MFONT_TYPE_OBJECT)
754 int size = spec->size;
756 for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
758 if (rfont->font == font && rfont->spec.size == size)
762 rfont = xfont_open (frame, font, spec, NULL);
764 return MCHAR_INVALID_CODE;
768 MFATAL (MERROR_FONT_X);
769 xfont = rfont->fontp;
770 all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
771 min_byte1 = xfont->min_byte1;
772 max_byte1 = xfont->max_byte1;
773 min_byte2 = xfont->min_char_or_byte2;
774 max_byte2 = xfont->max_char_or_byte2;
776 if (min_byte1 == 0 && max_byte1 == 0)
780 if (code < min_byte2 || code > max_byte2)
781 return MCHAR_INVALID_CODE;
784 pcm = xfont->per_char + (code - min_byte2);
785 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
786 ? code : MCHAR_INVALID_CODE);
790 unsigned byte1 = code >> 8, byte2 = code & 0xFF;
793 if (byte1 < min_byte1 || byte1 > max_byte1
794 || byte2 < min_byte2 || byte2 > max_byte2)
795 return MCHAR_INVALID_CODE;
799 pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
800 + (byte2 - min_byte2));
801 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
802 ? code : MCHAR_INVALID_CODE);
806 /* The X font driver function RENDER. */
809 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
810 MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
812 MRealizedFace *rface = from->rface;
813 Display *display = FRAME_DISPLAY (rface->frame);
815 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
823 gc = set_region (rface->frame, gc, region);
824 XSetFont (display, gc, ((XFontStruct *) rface->rfont->fontp)->fid);
825 code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
826 for (i = 0, g = from; g < to; i++, g++)
828 code[i].byte1 = g->code >> 8;
829 code[i].byte2 = g->code & 0xFF;
835 if (g->type == GLYPH_PAD)
837 else if (g->type == GLYPH_SPACE)
838 for (; g < to && g->type == GLYPH_SPACE; g++)
840 else if (! g->rface->rfont)
842 if ((g->c >= 0x200B && g->c <= 0x200F)
843 || (g->c >= 0x202A && g->c <= 0x202E))
847 /* As a font is not found for this character, draw an
849 int box_width = g->width;
850 int box_height = gstring->ascent + gstring->descent;
856 XDrawRectangle (display, (Window) win, gc,
857 x, y - gstring->ascent, box_width, box_height);
861 else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
863 XDrawString16 (display, (Window) win, gc,
864 x + g->xoff, y + g->yoff, code + (g - from), 1);
871 int code_idx = g - from;
874 g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
877 XDrawString16 (display, (Window) win, gc, orig_x, y,
884 xfont_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum)
886 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
887 MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil;
888 MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil;
889 int size = font ? font->size : 0;
892 int mdebug_mask = MDEBUG_FONT;
894 MDEBUG_PRINT2 (" [X-FONT] listing %s-%s...",
895 family ? msymbol_name (family) : "*",
896 registry ? msymbol_name (registry) : "*");
898 if (registry == Mnil)
899 xfont_list_all (frame);
901 xfont_registry_list (frame, registry);
903 MPLIST_DO (pl, disp_info->font_list)
905 if (registry != Mnil && registry != MPLIST_KEY (pl))
907 MPLIST_DO (p, MPLIST_VAL (pl))
911 if (family != Mnil && family != MPLIST_KEY (p))
913 for (fontx = MPLIST_VAL (p); fontx; fontx = fontx->next)
915 || (mfont__match_p (&fontx->core, font, MFONT_REGISTRY)))
917 if (fontx->core.size == size
918 || fontx->core.size == 0)
920 mplist_push (plist, MPLIST_KEY (p), fontx);
924 || (size <= 360 && HAVE_SIZE (fontx, (size / 10))))
926 unsigned size5_36 = fontx->size5_36;
931 for (i = fontx->core.size / 10; i <= 36; i++)
932 if (size5_36 & (1 << (i - 5)))
934 MSTRUCT_CALLOC (fontx2, MERROR_WIN);
935 fontx2->core = fontx->core;
936 fontx2->core.size = i * 10;
937 fontx2->next = fontx->next;
938 fontx->next = fontx2;
940 if ((size == 0 || size == fontx->core.size)
941 && (maxnum == 0 || num < maxnum))
943 mplist_push (plist, MPLIST_KEY (p), fontx);
948 if (maxnum > 0 && maxnum == num)
951 if (maxnum > 0 && maxnum == num)
954 if (maxnum > 0 && maxnum == num)
958 MDEBUG_PRINT1 (" %d found\n", num);
974 /* Pointer to MRealizedFontFT */
978 static MRealizedFont *xft_open (MFrame *frame, MFont *font, MFont *spec,
980 static int xft_has_char (MFrame *frame, MFont *font, MFont *spec,
981 int c, unsigned code);
982 static unsigned xft_encode_char (MFrame *frame, MFont *font, MFont *spec,
984 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
985 static void xft_render (MDrawWindow, int, int, MGlyphString *,
986 MGlyph *, MGlyph *, int, MDrawRegion);
988 MFontDriver xft_driver =
990 xft_find_metric, xft_has_char, xft_encode_char, xft_render, NULL };
993 close_xft (void *object)
995 MRealizedFontXft *rfont_xft = object;
997 if (rfont_xft->font_aa)
998 XftFontClose (rfont_xft->display, rfont_xft->font_aa);
999 if (rfont_xft->font_no_aa)
1000 XftFontClose (rfont_xft->display, rfont_xft->font_no_aa);
1001 M17N_OBJECT_UNREF (rfont_xft->info);
1007 xft_open_font (Display *display, MSymbol file, double size,
1013 pattern = FcPatternCreate ();
1014 FcPatternAddString (pattern, FC_FILE, (FcChar8 *) msymbol_name (file));
1015 FcPatternAddDouble (pattern, FC_PIXEL_SIZE, size);
1016 FcPatternAddBool (pattern, FC_ANTIALIAS, anti_alias);
1017 font = XftFontOpenPattern (display, pattern);
1022 static MRealizedFont *
1023 xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
1025 Display *display = FRAME_DISPLAY (frame);
1026 int reg = spec->property[MFONT_REGISTRY];
1028 MRealizedFontXft *rfont_xft;
1029 FcBool anti_alias = FRAME_DEVICE (frame)->depth > 1 ? FcTrue : FcFalse;
1030 double size = font->size ? font->size : spec->size;
1035 MRealizedFont *save = NULL;
1037 for (; rfont; rfont = rfont->next)
1038 if (rfont->font == font
1039 && (rfont->font->size ? rfont->font->size == size
1040 : rfont->spec.size == size)
1041 && rfont->spec.property[MFONT_REGISTRY] == reg)
1045 if (rfont->driver == &xft_driver)
1050 rfont = (mfont__ft_driver.open) (frame, font, spec, rfont);
1053 spec = &rfont->spec;
1054 ft_face = rfont->fontp;
1055 xft_font = xft_open_font (display, font->file, size / 10, anti_alias);
1058 M17N_OBJECT (rfont_xft, close_xft, MERROR_WIN);
1059 rfont_xft->display = display;
1060 if (anti_alias == FcTrue)
1061 rfont_xft->font_aa = xft_font;
1063 rfont_xft->font_no_aa = xft_font;
1064 rfont_xft->ft_face = ft_face;
1065 rfont_xft->info = rfont->info;
1066 M17N_OBJECT_REF (rfont->info);
1067 MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
1068 rfont->spec = *spec;
1069 rfont->frame = frame;
1071 rfont->driver = &xft_driver;
1072 rfont->info = rfont_xft;
1073 rfont->ascent = ft_face->size->metrics.ascender >> 6;
1074 rfont->descent = - ft_face->size->metrics.descender >> 6;
1075 rfont->max_advance = ft_face->size->metrics.max_advance >> 6;
1076 rfont->fontp = xft_font;
1077 rfont->next = MPLIST_VAL (frame->realized_font_list);
1078 MPLIST_VAL (frame->realized_font_list) = rfont;
1083 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1086 Display *display = FRAME_DISPLAY (rfont->frame);
1087 XftFont *xft_font = rfont->fontp;
1088 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1090 for (; g != gend; g++)
1092 if (g->code == MCHAR_INVALID_CODE)
1095 g->rbearing = xft_font->max_advance_width;
1096 g->width = g->rbearing;
1097 g->ascent = xft_font->ascent;
1098 g->descent = xft_font->descent;
1104 XftGlyphExtents (display, xft_font, &g->code, 1, &extents);
1105 g->lbearing = - extents.x;
1106 g->rbearing = extents.width - extents.x;
1107 g->width = extents.xOff;
1108 g->ascent = extents.y;
1109 g->descent = extents.height - extents.y;
1115 xft_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
1119 if (font->type == MFONT_TYPE_REALIZED)
1121 MRealizedFont *rfont = (MRealizedFont *) font;
1122 MRealizedFontXft *rfont_xft = rfont->info;
1124 rfont->info = rfont_xft->info;
1125 result = mfont__ft_driver.has_char (frame, font, spec, c, code);
1126 rfont->info = rfont_xft;
1129 result = mfont__ft_driver.has_char (frame, font, spec, c, code);
1134 xft_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
1136 if (font->type == MFONT_TYPE_REALIZED)
1138 MRealizedFont *rfont = (MRealizedFont *) font;
1139 MRealizedFontXft *rfont_xft = rfont->info;
1141 rfont->info = rfont_xft->info;
1142 code = mfont__ft_driver.encode_char (frame, font, spec, code);
1143 rfont->info = rfont_xft;
1146 code = mfont__ft_driver.encode_char (frame, font, spec, code);
1151 xft_render (MDrawWindow win, int x, int y,
1152 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1153 int reverse, MDrawRegion region)
1155 MRealizedFace *rface = from->rface;
1156 MFrame *frame = rface->frame;
1157 Display *display = FRAME_DISPLAY (frame);
1158 MRealizedFont *rfont = rface->rfont;
1159 MRealizedFontXft *rfont_xft = rfont->info;
1160 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1161 XftColor *xft_color = (! reverse
1162 ? &((GCInfo *) rface->info)->xft_color_fore
1163 : &((GCInfo *) rface->info)->xft_color_back);
1164 int anti_alias = (gstring->control.anti_alias
1165 && FRAME_DEVICE (frame)->depth > 1);
1177 if (rfont_xft->font_aa)
1178 xft_font = rfont_xft->font_aa;
1181 double size = rfont->spec.size;
1183 xft_font = xft_open_font (display, rfont->spec.file, size / 10,
1186 rfont_xft->font_aa = xft_font;
1188 xft_font = rfont->fontp;
1193 if (rfont_xft->font_no_aa)
1194 xft_font = rfont_xft->font_no_aa;
1197 double size = rfont->spec.size;
1199 xft_font = xft_open_font (display, rfont->spec.file, size / 10,
1202 rfont_xft->font_no_aa = xft_font;
1204 xft_font = rfont->fontp;
1208 XftDrawChange (xft_draw, (Drawable) win);
1209 XftDrawSetClip (xft_draw, (Region) region);
1211 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1212 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1214 if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1215 glyphs[nglyphs++] = g->code;
1219 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1220 last_x, y, glyphs, nglyphs);
1222 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1223 x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1224 last_x = x + g->width;
1228 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1231 #endif /* HAVE_XFT2 */
1234 /* Functions for the device driver. */
1237 mwin__close_device (MFrame *frame)
1239 MWDevice *device = FRAME_DEVICE (frame);
1241 M17N_OBJECT_UNREF (device);
1245 mwin__device_get_prop (MFrame *frame, MSymbol key)
1247 MWDevice *device = FRAME_DEVICE (frame);
1249 if (key == Mdisplay)
1250 return (void *) device->display_info->display;
1252 return (void *) ScreenOfDisplay(device->display_info->display,
1253 device->screen_num);
1254 if (key == Mcolormap)
1255 return (void *) device->cmap;
1257 return (void *) device->depth;
1262 mwin__realize_face (MRealizedFace *rface)
1265 MSymbol foreground, background, videomode;
1266 MFaceHLineProp *hline;
1270 if (rface != rface->ascii_rface)
1272 rface->info = rface->ascii_rface->info;
1276 frame = rface->frame;
1277 MSTRUCT_CALLOC (info, MERROR_WIN);
1279 foreground = rface->face.property[MFACE_FOREGROUND];
1280 background = rface->face.property[MFACE_BACKGROUND];
1281 videomode = rface->face.property[MFACE_VIDEOMODE];
1283 videomode = frame->videomode;
1284 if (videomode != Mreverse)
1286 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1287 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1291 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1292 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1295 if (foreground == Mnil)
1296 foreground = frame->foreground;
1297 if (background == Mnil)
1298 background = frame->background;
1299 if (videomode == Mreverse)
1301 MSymbol temp = foreground;
1302 foreground = background;
1305 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1306 FRAME_VISUAL (frame),
1308 MSYMBOL_NAME (foreground),
1309 &info->xft_color_fore))
1311 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1312 FRAME_VISUAL (frame),
1314 MSYMBOL_NAME (background),
1315 &info->xft_color_back))
1317 #endif /* HAVE_XFT2 */
1319 hline = rface->hline;
1323 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1325 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1332 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1334 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1336 if (box->color_left && box->color_left != box->color_top)
1337 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1339 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1341 if (box->color_bottom && box->color_bottom != box->color_top)
1342 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1344 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1346 if (box->color_right && box->color_right != box->color_bottom)
1347 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1349 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1357 mwin__free_realized_face (MRealizedFace *rface)
1359 if (rface == rface->ascii_rface)
1365 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1367 int x, int y, int width, int height, MDrawRegion region)
1369 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1372 gc = set_region (frame, gc, region);
1374 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1375 x, y, width, height);
1380 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1381 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1382 int reverse, MDrawRegion region)
1384 MRealizedFace *rface = from->rface;
1385 Display *display = FRAME_DISPLAY (rface->frame);
1386 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1392 gc = set_region (rface->frame, gc, region);
1393 for (; from < to; from++)
1395 XDrawRectangle (display, (Window) win, gc,
1396 x, y - gstring->ascent + 1, from->width - 1,
1397 gstring->ascent + gstring->descent - 2);
1404 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1405 MRealizedFace *rface, int reverse,
1406 int x, int y, int width, MDrawRegion region)
1408 enum MFaceHLineType type = rface->hline->type;
1409 GCInfo *info = rface->info;
1410 GC gc = gc = info->gc[GC_HLINE];
1413 y = (type == MFACE_HLINE_BOTTOM
1414 ? y + gstring->text_descent - rface->hline->width
1415 : type == MFACE_HLINE_UNDER
1417 : type == MFACE_HLINE_STRIKE_THROUGH
1418 ? y - ((gstring->ascent + gstring->descent) / 2)
1419 : y - gstring->text_ascent);
1421 gc = set_region (frame, gc, region);
1423 for (i = 0; i < rface->hline->width; i++)
1424 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1425 x, y + i, x + width - 1, y + i);
1430 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1431 MGlyph *g, int x, int y, int width, MDrawRegion region)
1433 Display *display = FRAME_DISPLAY (frame);
1434 MRealizedFace *rface = g->rface;
1435 MFaceBoxProp *box = rface->box;
1436 GCInfo *info = rface->info;
1437 GC gc_top, gc_left, gc_right, gc_btm;
1441 y0 = y - (gstring->text_ascent
1442 + rface->box->inner_vmargin + rface->box->width);
1443 y1 = y + (gstring->text_descent
1444 + rface->box->inner_vmargin + rface->box->width - 1);
1446 gc_top = info->gc[GC_BOX_TOP];
1448 gc_top = set_region (frame, gc_top, region);
1449 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1452 gc_btm = info->gc[GC_BOX_BOTTOM];
1454 if (g->type == GLYPH_BOX)
1458 if (g->left_padding)
1459 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1461 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1463 /* Draw the top side. */
1464 for (i = 0; i < box->width; i++)
1465 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1467 /* Draw the bottom side. */
1468 if (region && gc_btm != gc_top)
1469 gc_btm = set_region (frame, gc_btm, region);
1470 for (i = 0; i < box->width; i++)
1471 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1473 if (g->left_padding > 0)
1475 /* Draw the left side. */
1476 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1480 gc_left = info->gc[GC_BOX_LEFT];
1482 gc_left = set_region (frame, gc_left, region);
1484 for (i = 0; i < rface->box->width; i++)
1485 XDrawLine (display, (Window) win, gc_left,
1486 x0 + i, y0 + i, x0 + i, y1 - i);
1490 /* Draw the right side. */
1491 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1495 gc_right = info->gc[GC_BOX_RIGHT];
1497 gc_right = set_region (frame, gc_right, region);
1499 for (i = 0; i < rface->box->width; i++)
1500 XDrawLine (display, (Window) win, gc_right,
1501 x1 - i, y0 + i, x1 - i, y1 - i);
1506 /* Draw the top side. */
1507 for (i = 0; i < box->width; i++)
1508 XDrawLine (display, (Window) win, gc_top,
1509 x, y0 + i, x + width - 1, y0 + i);
1511 /* Draw the bottom side. */
1512 if (region && gc_btm != gc_top)
1513 gc_btm = set_region (frame, gc_btm, region);
1514 for (i = 0; i < box->width; i++)
1515 XDrawLine (display, (Window) win, gc_btm,
1516 x, y1 - i, x + width - 1, y1 - i);
1523 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1524 int reverse, int x, int y,
1525 int width, int height, int row_bytes, unsigned char *bmp,
1528 Display *display = FRAME_DISPLAY (frame);
1530 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1533 gc = set_region (frame, gc, region);
1535 for (i = 0; i < height; i++, bmp += row_bytes)
1536 for (j = 0; j < width; j++)
1537 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1538 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1543 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1544 int intensity, MDrawPoint *points, int num,
1547 GCInfo *info = rface->info;
1550 if (! (gc = info->gc[intensity]))
1551 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1554 gc = set_region (frame, gc, region);
1556 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1557 (XPoint *) points, num, CoordModeOrigin);
1562 mwin__region_from_rect (MDrawMetric *rect)
1564 MDrawRegion region1 = XCreateRegion ();
1565 MDrawRegion region2 = XCreateRegion ();
1570 xrect.width = rect->width;
1571 xrect.height = rect->height;
1572 XUnionRectWithRegion (&xrect, region1, region2);
1573 XDestroyRegion (region1);
1578 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1580 MDrawRegion region1 = XCreateRegion ();
1585 xrect.width = rect->width;
1586 xrect.height = rect->height;
1588 XUnionRegion (region, region, region1);
1589 XUnionRectWithRegion (&xrect, region1, region);
1590 XDestroyRegion (region1);
1594 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1596 MDrawRegion region = XCreateRegion ();
1598 XUnionRegion (region1, region1, region);
1599 XIntersectRegion (region, region2, region1);
1600 XDestroyRegion (region);
1604 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1606 MDrawRegion region1 = XCreateRegion ();
1611 xrect.width = rect->width;
1612 xrect.height = rect->height;
1613 XUnionRectWithRegion (&xrect, region1, region);
1614 XDestroyRegion (region1);
1618 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1622 XClipBox (region, &xrect);
1625 rect->width = xrect.width;
1626 rect->height = xrect.height;
1630 mwin__free_region (MDrawRegion region)
1632 XDestroyRegion (region);
1636 mwin__dump_region (MDrawRegion region)
1639 XClipBox (region, &rect);
1640 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1645 mwin__create_window (MFrame *frame, MDrawWindow parent)
1647 Display *display = FRAME_DISPLAY (frame);
1649 XWMHints wm_hints = { InputHint, False };
1650 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1651 XSetWindowAttributes set_attrs;
1654 GCInfo *info = frame->rface->info;
1657 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1658 mask = GCForeground;
1659 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1660 set_attrs.background_pixel = values.foreground;
1661 set_attrs.backing_store = Always;
1662 set_attrs.override_redirect = True;
1663 set_attrs.save_under = True;
1664 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1665 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1666 CopyFromParent, InputOutput, CopyFromParent,
1668 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1669 NULL, &wm_hints, &class_hints);
1670 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1671 return (MDrawWindow) win;
1675 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1677 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1682 mwin__event_window (void *event)
1684 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1688 mwin__print_event (void *arg, char *win_name)
1691 XEvent *event = (XEvent *) arg;
1693 switch (event->xany.type)
1695 case 2: event_name = "KeyPress"; break;
1696 case 3: event_name = "KeyRelease"; break;
1697 case 4: event_name = "ButtonPress"; break;
1698 case 5: event_name = "ButtonRelease"; break;
1699 case 6: event_name = "MotionNotify"; break;
1700 case 7: event_name = "EnterNotify"; break;
1701 case 8: event_name = "LeaveNotify"; break;
1702 case 9: event_name = "FocusIn"; break;
1703 case 10: event_name = "FocusOut"; break;
1704 case 11: event_name = "KeymapNotify"; break;
1705 case 12: event_name = "Expose"; break;
1706 case 13: event_name = "GraphicsExpose"; break;
1707 case 14: event_name = "NoExpose"; break;
1708 case 15: event_name = "VisibilityNotify"; break;
1709 case 16: event_name = "CreateNotify"; break;
1710 case 17: event_name = "DestroyNotify"; break;
1711 case 18: event_name = "UnmapNotify"; break;
1712 case 19: event_name = "MapNotify"; break;
1713 case 20: event_name = "MapRequest"; break;
1714 case 21: event_name = "ReparentNotify"; break;
1715 case 22: event_name = "ConfigureNotify"; break;
1716 case 23: event_name = "ConfigureRequest"; break;
1717 case 24: event_name = "GravityNotify"; break;
1718 case 25: event_name = "ResizeRequest"; break;
1719 case 26: event_name = "CirculateNotify"; break;
1720 case 27: event_name = "CirculateRequest"; break;
1721 case 28: event_name = "PropertyNotify"; break;
1722 case 29: event_name = "SelectionClear"; break;
1723 case 30: event_name = "SelectionRequest"; break;
1724 case 31: event_name = "SelectionNotify"; break;
1725 case 32: event_name = "ColormapNotify"; break;
1726 case 33: event_name = "ClientMessage"; break;
1727 case 34: event_name = "MappingNotify"; break;
1728 default: event_name = "unknown";
1731 fprintf (stderr, "%s: %s\n", win_name, event_name);
1736 mwin__map_window (MFrame *frame, MDrawWindow win)
1738 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1742 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1744 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1748 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1749 MDrawMetric *geometry)
1751 Display *display = FRAME_DISPLAY (frame);
1752 XWindowAttributes attr;
1753 Window parent = (Window) parent_win, root;
1755 XGetWindowAttributes (display, (Window) win, &attr);
1756 geometry->x = attr.x + attr.border_width;
1757 geometry->y = attr.y + attr.border_width;
1758 geometry->width = attr.width;
1759 geometry->height = attr.height;
1762 parent = RootWindow (display, FRAME_SCREEN (frame));
1765 Window this_parent, *children;
1768 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1771 if (this_parent == parent || this_parent == root)
1773 win = (MDrawWindow) this_parent;
1774 XGetWindowAttributes (display, (Window) win, &attr);
1775 geometry->x += attr.x + attr.border_width;
1776 geometry->y += attr.y + attr.border_width;
1781 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1782 MDrawMetric *current, MDrawMetric *new)
1784 Display *display = FRAME_DISPLAY (frame);
1785 unsigned int mask = 0;
1786 XWindowChanges values;
1788 if (current->width != new->width)
1791 if (new->width <= 0)
1793 values.width = current->width = new->width;
1795 if (current->height != new->height)
1798 if (new->height <= 0)
1800 values.height = current->height = new->height;
1802 if (current->x != new->x)
1805 values.x = current->x = new->x;
1807 if (current->y != new->y)
1810 current->y = new->y;
1811 values.y = current->y = new->y;
1814 XConfigureWindow (display, (Window) win, mask, &values);
1815 XClearWindow (display, (Window) win);
1819 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1821 XEvent *event = (XEvent *) arg;
1822 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1829 if (event->xany.type != KeyPress
1830 /* && event->xany.type != KeyRelease */
1833 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1840 if (c < XK_space || c > XK_asciitilde)
1842 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1843 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1844 if (((XKeyEvent *) event)->state & ControlMask)
1846 if (c >= 'a' && c <= 'z')
1848 if (c >= ' ' && c < 127)
1849 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1851 key = minput__char_to_key (c);
1853 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1857 char *str = XKeysymToString (keysym);
1861 key = msymbol (str);
1862 if (((XKeyEvent *) event)->state & ShiftMask)
1863 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1864 if (((XKeyEvent *) event)->state & ControlMask)
1865 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1867 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1868 *modifiers |= MINPUT_KEY_META_MODIFIER;
1869 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1870 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1871 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1872 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1873 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1874 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1881 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1883 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1885 Display *display = FRAME_DISPLAY (frame);
1886 GCInfo *info = rface->info;
1889 for (i = 0; i <= GC_INVERSE; i++)
1891 XGetGCValues (display, info->gc[i], valuemask, &values);
1892 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1893 values.foreground, values.background);
1894 fprintf (stderr, "\n");
1898 static MDeviceDriver x_driver =
1901 mwin__device_get_prop,
1903 mwin__free_realized_face,
1905 mwin__draw_empty_boxes,
1909 mwin__region_from_rect,
1910 mwin__union_rect_with_region,
1911 mwin__intersect_region,
1912 mwin__region_add_rect,
1913 mwin__region_to_rect,
1916 mwin__create_window,
1917 mwin__destroy_window,
1920 mwin__window_geometry,
1921 mwin__adjust_window,
1925 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1930 M_iso8859_1 = msymbol ("iso8859-1");
1931 M_iso10646_1 = msymbol ("iso10646-1");
1933 display_info_list = mplist ();
1934 device_list = mplist ();
1937 xft_driver.select = mfont__ft_driver.select;
1938 xft_driver.list = mfont__ft_driver.list;
1941 Mxim = msymbol ("xim");
1942 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1950 M17N_OBJECT_UNREF (display_info_list);
1951 M17N_OBJECT_UNREF (device_list);
1956 #ifdef X_SET_ERROR_HANDLER
1958 x_error_handler (Display *display, XErrorEvent *error)
1965 x_io_error_handler (Display *display)
1972 /** Return an MWDevice object corresponding to a display specified in
1975 It searches device_list for a device matching the display. If
1976 found, return the found object. Otherwise, return a newly created
1980 device_open (MFrame *frame, MPlist *param)
1982 Display *display = NULL;
1983 Screen *screen = NULL;
1985 Drawable drawable = 0;
1986 Widget widget = NULL;
1988 int auto_display = 0;
1989 MDisplayInfo *disp_info = NULL;
1990 MWDevice *device = NULL;
1992 XWindowAttributes attr;
1998 int use_xfont = 0, use_freetype = 0, use_xft = 0;
2000 for (plist = param; (key = mplist_key (plist)) != Mnil;
2001 plist = mplist_next (plist))
2003 if (key == Mdisplay)
2004 display = (Display *) mplist_value (plist);
2005 else if (key == Mscreen)
2006 screen = mplist_value (plist);
2007 else if (key == Mdrawable)
2008 drawable = (Drawable) mplist_value (plist);
2009 else if (key == Mdepth)
2010 depth = (unsigned) mplist_value (plist);
2011 else if (key == Mwidget)
2012 widget = (Widget) mplist_value (plist);
2013 else if (key == Mcolormap)
2014 cmap = (Colormap) mplist_value (plist);
2015 else if (key == Mfont)
2017 MSymbol val = MPLIST_SYMBOL (plist);
2021 #ifdef HAVE_FREETYPE
2022 else if (val == Mfreetype)
2025 else if (val == Mxft)
2032 /* If none of them is specified, use all of them. */
2033 if (! use_xfont && ! use_freetype && ! use_xft)
2034 use_xfont = use_freetype = use_xft = 1;
2038 display = XtDisplay (widget);
2039 screen_num = XScreenNumberOfScreen (XtScreen (widget));
2040 depth = DefaultDepth (display, screen_num);
2046 unsigned width, height, border_width;
2049 MERROR (MERROR_WIN, -1);
2050 XGetGeometry (display, drawable, &root_window,
2051 &x, &y, &width, &height, &border_width, &depth);
2052 XGetWindowAttributes (display, root_window, &attr);
2053 screen_num = XScreenNumberOfScreen (attr.screen);
2058 display = DisplayOfScreen (screen);
2063 display = XOpenDisplay (NULL);
2065 MERROR (MERROR_WIN, -1);
2068 screen = DefaultScreenOfDisplay (display);
2070 screen_num = XScreenNumberOfScreen (screen);
2072 depth = DefaultDepth (display, screen_num);
2076 cmap = DefaultColormap (display, screen_num);
2078 for (plist = display_info_list; mplist_key (plist) != Mnil;
2079 plist = mplist_next (plist))
2081 disp_info = (MDisplayInfo *) mplist_value (plist);
2082 if (disp_info->display == display)
2086 if (mplist_key (plist) != Mnil)
2087 M17N_OBJECT_REF (disp_info);
2090 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
2091 disp_info->display = display;
2092 disp_info->auto_display = auto_display;
2093 disp_info->font_list = mplist ();
2094 find_modifier_bits (disp_info);
2095 mplist_add (display_info_list, Mt, disp_info);
2098 for (plist = device_list; mplist_key (plist) != Mnil;
2099 plist = mplist_next (plist))
2101 device = (MWDevice *) mplist_value (plist);
2102 if (device->display_info == disp_info
2103 && device->depth == depth
2104 && device->cmap == cmap)
2108 if (mplist_key (plist) != Mnil)
2109 M17N_OBJECT_REF (device);
2112 unsigned long valuemask = GCForeground;
2115 M17N_OBJECT (device, free_device, MERROR_WIN);
2116 device->display_info = disp_info;
2117 device->screen_num = screen_num;
2118 /* A drawable on which to create GCs. */
2119 device->drawable = XCreatePixmap (display,
2120 RootWindow (display, screen_num),
2122 device->depth = depth;
2123 device->cmap = cmap;
2124 device->realized_face_list = mplist ();
2125 device->realized_font_list = mplist ();
2126 mplist_add (device->realized_font_list, Mt, NULL);
2127 device->realized_fontset_list = mplist ();
2128 device->gc_list = mplist ();
2129 values.foreground = BlackPixel (display, screen_num);
2130 device->scratch_gc = XCreateGC (display, device->drawable,
2131 valuemask, &values);
2133 device->xft_draw = XftDrawCreate (display, device->drawable,
2134 DefaultVisual (display, screen_num),
2139 frame->device = device;
2140 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2141 frame->driver = &x_driver;
2142 frame->font_driver_list = mplist ();
2146 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2149 #endif /* HAVE_XFT2 */
2150 #ifdef HAVE_FREETYPE
2152 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2153 #endif /* HAVE_FREETYPE */
2154 if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list))
2155 mplist_push (frame->font_driver_list, Mx, &xfont_driver);
2157 frame->realized_font_list = device->realized_font_list;
2158 frame->realized_face_list = device->realized_face_list;
2159 frame->realized_fontset_list = device->realized_fontset_list;
2163 XtResource resources[] = {
2164 { XtNfont, XtCFont, XtRString, sizeof (String),
2165 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2166 { XtNforeground, XtCForeground, XtRString, sizeof (String),
2167 XtOffset (AppDataPtr, foreground), XtRString, "black" },
2168 { XtNbackground, XtCBackground, XtRString, sizeof (String),
2169 XtOffset (AppDataPtr, background), XtRString, "white" },
2170 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2171 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2174 XtGetApplicationResources (widget, &app_data,
2175 resources, XtNumber (resources), NULL, 0);
2176 frame->foreground = msymbol (app_data.foreground);
2177 frame->background = msymbol (app_data.background);
2178 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2182 app_data.font = DEFAULT_FONT;
2183 frame->foreground = msymbol ("black");
2184 frame->background = msymbol ("white");
2185 frame->videomode = Mnormal;
2188 if (strcmp (app_data.font, DEFAULT_FONT) != 0)
2190 XFontStruct *xfont = XLoadQueryFont (display, app_data.font);
2191 unsigned long value;
2196 font = mfont_parse_name (app_data.font, Mx);
2198 && XGetFontProperty (xfont, XA_FONT, &value)
2199 && (name = ((char *) XGetAtomName (display, (Atom) value))))
2200 font = mfont_parse_name (name, Mx);
2201 XFreeFont (display, xfont);
2205 font = mfont_parse_name (DEFAULT_FONT, Mx);
2206 else if (! font->size)
2208 face = mface_from_font (font);
2210 face->property[MFACE_FONTSET] = mfontset (NULL);
2211 face->property[MFACE_FOREGROUND] = frame->foreground;
2212 face->property[MFACE_BACKGROUND] = frame->background;
2213 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2214 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2215 face->property[MFACE_VIDEOMODE] = frame->videomode;
2216 mface_put_prop (face, Mhook_func,
2217 mface_get_prop (mface__default, Mhook_func));
2218 face->property[MFACE_RATIO] = (void *) 100;
2219 mplist_push (param, Mface, face);
2220 M17N_OBJECT_UNREF (face);
2222 #ifdef X_SET_ERROR_HANDLER
2223 XSetErrorHandler (x_error_handler);
2224 XSetIOErrorHandler (x_io_error_handler);
2231 /* XIM (X Input Method) handler */
2233 typedef struct MInputXIMMethodInfo
2239 } MInputXIMMethodInfo;
2241 typedef struct MInputXIMContextInfo
2245 MConverter *converter;
2246 } MInputXIMContextInfo;
2249 xim_open_im (MInputMethod *im)
2251 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2252 MLocale *saved, *this;
2253 char *save_modifier_list;
2255 MInputXIMMethodInfo *im_info;
2257 saved = mlocale_set (LC_CTYPE, NULL);
2258 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2260 /* The specified locale is not supported. */
2261 MERROR (MERROR_LOCALE, -1);
2262 if (mlocale_get_prop (this, Mcoding) == Mnil)
2264 /* Unable to decode the output of XIM. */
2265 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2266 MERROR (MERROR_LOCALE, -1);
2269 if (arg->modifier_list)
2270 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2272 save_modifier_list = XSetLocaleModifiers ("");
2273 if (! save_modifier_list)
2275 /* The specified locale is not supported by X. */
2276 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2277 MERROR (MERROR_LOCALE, -1);
2280 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2283 /* No input method is available in the current locale. */
2284 XSetLocaleModifiers (save_modifier_list);
2285 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2286 MERROR (MERROR_WIN, -1);
2289 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2290 im_info->display = arg->display;
2292 im_info->language = mlocale_get_prop (this, Mlanguage);
2293 im_info->coding = mlocale_get_prop (this, Mcoding);
2296 XSetLocaleModifiers (save_modifier_list);
2297 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2303 xim_close_im (MInputMethod *im)
2305 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2307 XCloseIM (im_info->xim);
2312 xim_create_ic (MInputContext *ic)
2314 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2315 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2316 MInputXIMContextInfo *ic_info;
2319 if (! arg->input_style)
2321 /* By default, use Root style. */
2322 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2323 arg->preedit_attrs = NULL;
2324 arg->status_attrs = NULL;
2327 if (! arg->preedit_attrs && ! arg->status_attrs)
2328 xic = XCreateIC (im_info->xim,
2329 XNInputStyle, arg->input_style,
2330 XNClientWindow, arg->client_win,
2331 XNFocusWindow, arg->focus_win,
2333 else if (arg->preedit_attrs && ! arg->status_attrs)
2334 xic = XCreateIC (im_info->xim,
2335 XNInputStyle, arg->input_style,
2336 XNClientWindow, arg->client_win,
2337 XNFocusWindow, arg->focus_win,
2338 XNPreeditAttributes, arg->preedit_attrs,
2340 else if (! arg->preedit_attrs && arg->status_attrs)
2341 xic = XCreateIC (im_info->xim,
2342 XNInputStyle, arg->input_style,
2343 XNClientWindow, arg->client_win,
2344 XNFocusWindow, arg->focus_win,
2345 XNStatusAttributes, arg->status_attrs,
2348 xic = XCreateIC (im_info->xim,
2349 XNInputStyle, arg->input_style,
2350 XNClientWindow, arg->client_win,
2351 XNFocusWindow, arg->focus_win,
2352 XNPreeditAttributes, arg->preedit_attrs,
2353 XNStatusAttributes, arg->status_attrs,
2356 MERROR (MERROR_WIN, -1);
2358 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2360 ic_info->win = arg->focus_win;
2361 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2367 xim_destroy_ic (MInputContext *ic)
2369 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2371 XDestroyIC (ic_info->xic);
2372 mconv_free_converter (ic_info->converter);
2378 xim_filter (MInputContext *ic, MSymbol key, void *event)
2380 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2382 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2387 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2389 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2390 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2391 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2397 buf = (char *) alloca (512);
2398 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2399 if (status == XBufferOverflow)
2401 buf = (char *) alloca (len);
2402 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2405 mtext_reset (ic->produced);
2409 mconv_reset_converter (ic_info->converter);
2410 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2411 mconv_decode (ic_info->converter, ic->produced);
2412 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2413 Mlanguage, (void *) im_info->language);
2414 mtext_cpy (mt, ic->produced);
2415 mtext_reset (ic->produced);
2423 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2427 /*** @addtogroup m17nInputMethodWin */
2432 @brief Input method driver for XIM.
2434 The driver #minput_xim_driver is for the foreign input method of
2435 name #Mxim. It uses XIM (X Input Methods) as a background input
2438 As the symbol #Mxim has property #Minput_driver whose value is
2439 a pointer to this driver, the input method of language #Mnil
2440 and name #Mxim uses this driver.
2442 Therefore, for such input methods, the driver dependent arguments
2443 to the functions whose name begin with minput_ must be as follows.
2445 The argument $ARG of the function minput_open_im () must be a
2446 pointer to the structure #MInputXIMArgIM. See the documentation
2447 of #MInputXIMArgIM for more details.
2449 The argument $ARG of the function minput_create_ic () must be a
2450 pointer to the structure #MInputXIMArgIC. See the documentation
2451 of #MInputXIMArgIC for more details.
2453 The argument $ARG of the function minput_filter () must be a
2454 pointer to the structure @c XEvent. The argument $KEY is ignored.
2456 The argument $ARG of the function minput_lookup () must be the
2457 same one as that of the function minput_filter (). The argument
2461 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2463 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ê¡¢
2464 XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
2466 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2467 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim
2468 ¤Ç¤¢¤ëÆþÎϥ᥽¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2470 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_
2471 ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2473 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM
2474 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò»²¾È¡£
2476 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC
2477 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ¤ò»²¾È¡£
2479 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent
2480 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2482 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2483 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì¤ë¡£ */
2485 MInputDriver minput_xim_driver =
2486 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2487 xim_filter, xim_lookup, NULL };