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 #endif /* HAVE_XFT2 */
50 #include "m17n-misc.h"
52 #include "internal-gui.h"
61 /* Common header for the m17n object. */
66 /* If nonzero, <display> is opened by this library. Thus it should
67 be closed on freeing this structure. */
70 /** List of available fonts on the display (except for iso8859-1 and
71 iso10646-1 fonts). Keys are font registries, values are
73 MPlist *font_registry_list;
75 MPlist *iso8859_1_family_list;
77 MPlist *iso10646_1_family_list;
79 /* List of information about each font. Keys are font registries,
80 values are (MFontInfo *). */
81 MPlist *realized_font_list;
83 /** Modifier bit masks of the display. */
90 /* Anchor of the chain of MDisplayInfo objects. */
91 static MPlist *display_info_list;
94 /* Color value and the corresponding GC. */
97 unsigned int rgb; /* (red << 16) | (green << 8) | blue */
104 GC_NORMAL = GC_INVERSE + 7,
117 /* The first 8 elements are indexed by an intensity for
118 anti-aliasing. The 2nd to 7th are created on demand. */
121 XftColor xft_color_fore, xft_color_back;
127 /* Common header for the m17n object. */
130 MDisplayInfo *display_info;
146 /** List of pointers to realized faces on the frame. */
147 MPlist *realized_face_list;
149 /** List of pointers to realized fontsets on the frame. */
150 MPlist *realized_fontset_list;
152 /** List of XColors vs GCs on the frame. */
156 static MPlist *device_list;
158 static MSymbol M_iso8859_1, M_iso10646_1;
160 #define FRAME_DEVICE(frame) ((MWDevice *) (frame)->device)
161 #define FRAME_DISPLAY(frame) (FRAME_DEVICE (frame)->display_info->display)
162 #define FRAME_SCREEN(frame) (FRAME_DEVICE (frame)->screen_num)
163 #define FRAME_CMAP(frame) (FRAME_DEVICE (frame)->cmap)
164 #define FRAME_VISUAL(frame) DefaultVisual (FRAME_DISPLAY (frame), \
165 FRAME_SCREEN (frame))
167 #define DEFAULT_FONT "-misc-fixed-medium-r-normal--*-120-*-*-*-*-iso8859-1"
168 #define FALLBACK_FONT "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1"
175 Boolean reverse_video;
176 } AppData, *AppDataPtr;
179 free_display_info (void *object)
181 MDisplayInfo *disp_info = (MDisplayInfo *) object;
184 MPLIST_DO (plist, disp_info->font_registry_list)
186 MFontList *registry_list = MPLIST_VAL (plist);
188 if (registry_list->fonts)
189 free (registry_list->fonts);
190 free (registry_list);
192 M17N_OBJECT_UNREF (disp_info->font_registry_list);
194 MPLIST_DO (plist, disp_info->iso8859_1_family_list)
196 MFontList *family_list = MPLIST_VAL (plist);
198 if (family_list->fonts)
199 free (family_list->fonts);
202 M17N_OBJECT_UNREF (disp_info->iso8859_1_family_list);
204 MPLIST_DO (plist, disp_info->iso10646_1_family_list)
206 MFontList *family_list = MPLIST_VAL (plist);
208 if (family_list->fonts)
209 free (family_list->fonts);
212 M17N_OBJECT_UNREF (disp_info->iso10646_1_family_list);
214 MPLIST_DO (plist, disp_info->realized_font_list)
215 mfont__free_realized ((MRealizedFont *) MPLIST_VAL (plist));
216 M17N_OBJECT_UNREF (disp_info->realized_font_list);
218 if (disp_info->auto_display)
219 XCloseDisplay (disp_info->display);
225 free_device (void *object)
227 MWDevice *device = object;
230 for (plist = device->realized_fontset_list;
231 mplist_key (plist) != Mnil; plist = mplist_next (plist))
232 mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist));
233 M17N_OBJECT_UNREF (device->realized_fontset_list);
235 MPLIST_DO (plist, device->realized_face_list)
237 MRealizedFace *rface = MPLIST_VAL (plist);
240 mface__free_realized (rface);
242 M17N_OBJECT_UNREF (device->realized_face_list);
244 MPLIST_DO (plist, device->gc_list)
246 XFreeGC (device->display_info->display,
247 ((RGB_GC *) MPLIST_VAL (plist))->gc);
248 free (MPLIST_VAL (plist));
250 M17N_OBJECT_UNREF (device->gc_list);
251 XFreeGC (device->display_info->display, device->scratch_gc);
254 XftDrawDestroy (device->xft_draw);
257 XFreePixmap (device->display_info->display, device->drawable);
258 M17N_OBJECT_UNREF (device->display_info);
264 find_modifier_bits (MDisplayInfo *disp_info)
266 Display *display = disp_info->display;
267 XModifierKeymap *mods;
268 KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L);
269 KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R);
270 KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L);
271 KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R);
272 KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
273 KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
274 KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
275 KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
278 mods = XGetModifierMapping (display);
279 /* We skip the first three sets for Shift, Lock, and Control. The
280 remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
281 for (i = 3; i < 8; i++)
282 for (j = 0; j < mods->max_keypermod; j++)
284 KeyCode code = mods->modifiermap[i * mods->max_keypermod + j];
288 if (code == meta_l || code == meta_r)
289 disp_info->meta_mask |= (1 << i);
290 else if (code == alt_l || code == alt_r)
291 disp_info->alt_mask |= (1 << i);
292 else if (code == super_l || code == super_r)
293 disp_info->super_mask |= (1 << i);
294 else if (code == hyper_l || code == hyper_r)
295 disp_info->hyper_mask |= (1 << i);
298 /* If meta keys are not in any modifier, use alt keys as meta
300 if (! disp_info->meta_mask)
302 disp_info->meta_mask = disp_info->alt_mask;
303 disp_info->alt_mask = 0;
305 /* If both meta and alt are assigned to the same modifier, give meta
307 if (disp_info->meta_mask & disp_info->alt_mask)
308 disp_info->alt_mask &= ~disp_info->meta_mask;
310 XFreeModifiermap (mods);
314 get_rgb_gc (MWDevice *device, XColor *xcolor)
316 int rgb = (((xcolor->red >> 8) << 16) | ((xcolor->green >> 8) << 8)
317 | (xcolor->blue >> 8));
320 unsigned long valuemask = GCForeground;
323 MPLIST_DO (plist, device->gc_list)
325 rgb_gc = MPLIST_VAL (plist);
327 if (rgb_gc->rgb == rgb)
329 if (rgb_gc->rgb > rgb)
333 if (! XAllocColor (device->display_info->display, device->cmap, xcolor))
336 rgb_gc = malloc (sizeof (RGB_GC));
338 values.foreground = xcolor->pixel;
339 rgb_gc->gc = XCreateGC (device->display_info->display,
340 device->drawable, valuemask, &values);
341 mplist_push (plist, Mt, rgb_gc);
346 get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret)
348 MWDevice *device = FRAME_DEVICE (frame);
356 color = for_foreground ? frame->foreground : frame->background;
358 if (! XParseColor (FRAME_DISPLAY (frame), device->cmap,
359 msymbol_name (color), &xcolor))
361 rgb_gc = get_rgb_gc (device, &xcolor);
365 *rgb_ret = rgb_gc->rgb;
370 GCInfo *info = frame->rface->info;
375 rgb = info->rgb_fore, gc = info->gc[GC_NORMAL];
377 rgb = info->rgb_back, gc = info->gc[GC_INVERSE];
385 get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity)
387 int rgb_fore, rgb_back;
392 if (info->gc[intensity])
393 return info->gc[intensity];
395 rgb_fore = info->rgb_fore, rgb_back = info->rgb_back;
396 xcolor.red = ((((rgb_fore & 0xFF0000) >> 16) * intensity
397 + ((rgb_back & 0xFF0000) >> 16) * (7 - intensity)) / 7) << 8;
398 xcolor.green = ((((rgb_fore & 0xFF00) >> 8) * intensity
399 + ((rgb_back & 0xFF00) >> 8) * (7 - intensity)) / 7) << 8;
400 xcolor.blue = (((rgb_fore & 0xFF) * intensity
401 + (rgb_back & 0xFF) * (7 - intensity)) / 7) << 8;
402 rgb_gc = get_rgb_gc (device, &xcolor);
406 gc =get_gc_for_anti_alias (device, info,
407 intensity < 4 ? intensity - 1 : intensity + 1);
408 return (info->gc[intensity] = gc);
412 set_region (MFrame *frame, GC gc, MDrawRegion region)
414 unsigned long valuemask = GCForeground;
416 XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
417 FRAME_DEVICE (frame)->scratch_gc);
418 XSetRegion (FRAME_DISPLAY (frame), FRAME_DEVICE (frame)->scratch_gc, region);
419 return FRAME_DEVICE (frame)->scratch_gc;
423 /** X font handler */
425 static MRealizedFont *xfont_select (MFrame *, MFont *, MFont *, int);
426 static int xfont_open (MRealizedFont *);
427 static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int);
428 static unsigned xfont_encode_char (MRealizedFont *, unsigned);
429 static void xfont_render (MDrawWindow, int, int, MGlyphString *,
430 MGlyph *, MGlyph *, int, MDrawRegion);
432 static MFontDriver xfont_driver =
433 { xfont_select, xfont_open,
434 xfont_find_metric, xfont_encode_char, xfont_render };
444 build_font_list (MFrame *frame, MSymbol family, MSymbol registry,
448 MFontList *font_list;
453 MSTRUCT_CALLOC (font_list, MERROR_WIN);
457 sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s",
458 msymbol_name (registry));
459 font_list->tag = registry;
463 sprintf (pattern, "-*-%s-*-*-*-*-*-*-*-*-*-*-%s",
464 msymbol_name (family), msymbol_name (registry));
465 font_list->tag = family;
468 fontnames = XListFonts (FRAME_DISPLAY (frame), pattern, 0x8000, &nfonts);
471 MTABLE_MALLOC (font_list->fonts, nfonts, MERROR_WIN);
472 for (i = j = 0; i < nfonts; i++)
473 if ((mfont__parse_name_into_font (fontnames[i], Mx,
474 font_list->fonts + j)
476 && (font_list->fonts[j].property[MFONT_SIZE] != 0
477 || font_list->fonts[j].property[MFONT_RESY] == 0))
479 XFreeFontNames (fontnames);
480 font_list->nfonts = j;
482 mplist_add (plist, font_list->tag, font_list);
483 return (nfonts > 0 ? font_list : NULL);
486 /* The X font driver function SELECT. */
488 static MRealizedFont *
489 xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
491 MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
492 MRealizedFont *rfont;
493 MFontList *font_list = NULL;
496 int best_score, score;
499 || ! strchr (MSYMBOL_NAME (registry), '-'))
502 /* We handles iso8859-1 and iso10646-1 fonts specially because there
503 exists so many such fonts. */
504 if (registry == M_iso8859_1 || registry == M_iso10646_1)
507 = (registry == M_iso8859_1
508 ? FRAME_DEVICE (frame)->display_info->iso8859_1_family_list
509 : FRAME_DEVICE (frame)->display_info->iso10646_1_family_list);
510 MSymbol family = FONT_PROPERTY (spec, MFONT_FAMILY);
514 font_list = (MFontList *) mplist_get (family_list, family);
516 font_list = build_font_list (frame, family, registry, family_list);
520 family = FONT_PROPERTY (request, MFONT_FAMILY);
521 font_list = (MFontList *) mplist_get (family_list, family);
523 font_list = build_font_list (frame, family, registry, family_list);
528 MPlist *registry_list
529 = FRAME_DEVICE (frame)->display_info->font_registry_list;
531 font_list = (MFontList *) mplist_get (registry_list, registry);
533 font_list = build_font_list (frame, Mnil, registry, registry_list);
538 for (i = 0, best_score = -1, best_font = NULL; i < font_list->nfonts; i++)
539 if ((best_score = mfont__score (font_list->fonts + i, spec, request,
544 best_font = font_list->fonts + i;
545 for (; best_score > 0 && i < font_list->nfonts ; i++)
547 score = mfont__score (font_list->fonts + i, spec, request,
549 if (score >= 0 && score < best_score)
551 best_font = font_list->fonts + i;
556 MSTRUCT_CALLOC (rfont, MERROR_WIN);
557 rfont->frame = frame;
559 rfont->request = *request;
560 rfont->font = *best_font;
561 if (best_font->property[MFONT_SIZE] == 0)
562 rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE];
563 rfont->score = best_score;
568 /* The X font driver function CLOSE. */
571 close_xfont (void *object)
573 MXFontInfo *xfont_info = object;
575 XFreeFont (xfont_info->display, xfont_info->xfont);
580 /* The X font driver function OPEN. */
583 xfont_open (MRealizedFont *rfont)
586 MXFontInfo *xfont_info;
587 MFrame *frame = rfont->frame;
588 int mdebug_mask = MDEBUG_FONT;
590 /* This never fail to generate a valid fontname because open_spec
591 should correspond to a font available on the system. */
592 name = mfont_unparse_name (&rfont->font, Mx);
593 M17N_OBJECT (xfont_info, close_xfont, MERROR_WIN);
594 xfont_info->display = FRAME_DISPLAY (frame);
595 xfont_info->xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
596 if (! xfont_info->xfont)
600 MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
604 rfont->info = xfont_info;
605 MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
608 rfont->ascent = xfont_info->xfont->ascent;
609 rfont->descent = xfont_info->xfont->descent;
614 /* The X font driver function FIND_METRIC. */
617 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
620 MXFontInfo *xfont_info = rfont->info;
621 XFontStruct *xfont = xfont_info->xfont;
622 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
624 for (; g != gend; g++)
626 if (g->code == MCHAR_INVALID_CODE)
628 g->lbearing = xfont->max_bounds.lbearing;
629 g->rbearing = xfont->max_bounds.rbearing;
630 g->width = xfont->max_bounds.width;
631 g->ascent = xfont->ascent;
632 g->descent = xfont->descent;
636 int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
637 XCharStruct *pcm = NULL;
639 if (xfont->per_char != NULL)
641 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
644 && byte2 >= xfont->min_char_or_byte2
645 && byte2 <= xfont->max_char_or_byte2)
646 pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
650 if (byte1 >= xfont->min_byte1
651 && byte1 <= xfont->max_byte1
652 && byte2 >= xfont->min_char_or_byte2
653 && byte2 <= xfont->max_char_or_byte2)
655 pcm = (xfont->per_char
656 + ((xfont->max_char_or_byte2
657 - xfont->min_char_or_byte2 + 1)
658 * (byte1 - xfont->min_byte1))
659 + (byte2 - xfont->min_char_or_byte2));
666 g->lbearing = pcm->lbearing;
667 g->rbearing = pcm->rbearing;
668 g->width = pcm->width;
669 g->ascent = pcm->ascent;
670 g->descent = pcm->descent;
674 /* If the per_char pointer is null, all glyphs between
675 the first and last character indexes inclusive have
676 the same information, as given by both min_bounds and
679 g->rbearing = xfont->max_bounds.width;
680 g->width = xfont->max_bounds.width;
681 g->ascent = xfont->ascent;
682 g->descent = xfont->descent;
689 /* The X font driver function GET_GLYPH_ID. */
692 xfont_encode_char (MRealizedFont *rfont, unsigned code)
694 MXFontInfo *xfont_info;
696 unsigned min_byte1, max_byte1, min_byte2, max_byte2;
699 if (rfont->status < 0 || code >= 0x10000)
700 return MCHAR_INVALID_CODE;
701 if (rfont->status == 0)
703 if (xfont_open (rfont) < 0)
704 return MCHAR_INVALID_CODE;
706 xfont_info = rfont->info;
707 xfont = xfont_info->xfont;
708 all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
709 min_byte1 = xfont->min_byte1;
710 max_byte1 = xfont->max_byte1;
711 min_byte2 = xfont->min_char_or_byte2;
712 max_byte2 = xfont->max_char_or_byte2;
714 if (min_byte1 == 0 && max_byte1 == 0)
718 if (code < min_byte2 || code > max_byte2)
719 return MCHAR_INVALID_CODE;
722 pcm = xfont->per_char + (code - min_byte2);
723 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
724 ? code : MCHAR_INVALID_CODE);
728 unsigned byte1 = code >> 8, byte2 = code & 0xFF;
731 if (byte1 < min_byte1 || byte1 > max_byte1
732 || byte2 < min_byte2 || byte2 > max_byte2)
733 return MCHAR_INVALID_CODE;
737 pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
738 + (byte2 - min_byte2));
739 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
740 ? code : MCHAR_INVALID_CODE);
744 /* The X font driver function RENDER. */
747 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
748 MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
750 MRealizedFace *rface = from->rface;
751 MXFontInfo *xfont_info = rface->rfont->info;
754 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
761 /* It is assured that the all glyphs in the current range use the
762 same realized face. */
763 display = FRAME_DISPLAY (rface->frame);
766 gc = set_region (rface->frame, gc, region);
767 XSetFont (display, gc, xfont_info->xfont->fid);
768 code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
769 for (i = 0, g = from; g < to; i++, g++)
771 code[i].byte1 = g->code >> 8;
772 code[i].byte2 = g->code & 0xFF;
778 if (g->type == GLYPH_PAD)
780 else if (g->type == GLYPH_SPACE)
781 for (; g < to && g->type == GLYPH_SPACE; g++)
783 else if (! g->rface->rfont)
785 if ((g->c >= 0x200B && g->c <= 0x200F)
786 || (g->c >= 0x202A && g->c <= 0x202E))
790 /* As a font is not found for this character, draw an
792 int box_width = g->width;
793 int box_height = gstring->ascent + gstring->descent;
799 XDrawRectangle (display, (Window) win, gc,
800 x, y - gstring->ascent, box_width, box_height);
804 else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
806 XDrawString16 (display, (Window) win, gc,
807 x + g->xoff, y + g->yoff, code + (g - from), 1);
814 int code_idx = g - from;
817 g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
820 XDrawString16 (display, (Window) win, gc, orig_x, y,
839 static int xft_open (MRealizedFont *);
840 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
841 static void xft_render (MDrawWindow, int, int, MGlyphString *,
842 MGlyph *, MGlyph *, int, MDrawRegion);
844 MFontDriver xft_driver =
845 { NULL, /* Set to ft_select in mwin__init (). */
846 xft_open, xft_find_metric,
847 NULL, /* Set to ft_encode_char in mwin__init (). */
852 close_xft (void *object)
854 MXftFontInfo *font_info = object;
856 XftFontClose (font_info->display, font_info->font_aa);
857 XftFontClose (font_info->display, font_info->font_no_aa);
863 xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
866 XftFontInfo *xft_font_info;
869 pattern = XftPatternCreate ();
870 XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
871 XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
872 XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
873 xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
876 font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
877 XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
883 xft_open (MRealizedFont *rfont)
887 MXftFontInfo *font_info;
890 if ((mfont__ft_driver.open) (rfont) < 0)
893 size = rfont->font.property[MFONT_SIZE] / 10;
894 frame = rfont->frame;
896 ft_info = rfont->info;
897 M17N_OBJECT (font_info, close_xft, MERROR_WIN);
898 ft_info->extra_info = font_info;
899 font_info->display = FRAME_DISPLAY (frame);
900 font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
901 if (font_info->font_aa)
903 font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
904 if (font_info->font_no_aa)
906 XftFontClose (FRAME_DISPLAY (rfont->frame), font_info->font_aa);
909 ft_info->extra_info = NULL;
916 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
919 MFTInfo *ft_info = rfont->info;
920 MXftFontInfo *font_info = ft_info->extra_info;
921 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
923 for (; g != gend; g++)
925 if (g->code == MCHAR_INVALID_CODE)
929 while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
930 (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
938 XftGlyphExtents (FRAME_DISPLAY (rfont->frame),
939 font_info->font_aa, &g->code, 1, &extents);
940 g->lbearing = - extents.x;
941 g->rbearing = extents.width - extents.x;
942 g->width = extents.xOff;
943 g->ascent = extents.y;
944 g->descent = extents.height - extents.y;
951 xft_render (MDrawWindow win, int x, int y,
952 MGlyphString *gstring, MGlyph *from, MGlyph *to,
953 int reverse, MDrawRegion region)
955 MRealizedFace *rface = from->rface;
956 MFrame *frame = rface->frame;
957 MFTInfo *ft_info = rface->rfont->info;
958 MXftFontInfo *font_info = ft_info->extra_info;
959 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
960 XftColor *xft_color = (! reverse
961 ? &((GCInfo *) rface->info)->xft_color_fore
962 : &((GCInfo *) rface->info)->xft_color_back);
963 XftFont *xft_font = (gstring->control.anti_alias
964 && FRAME_DEVICE (frame)->depth > 1
965 ? font_info->font_aa : font_info->font_no_aa);
974 XftDrawChange (xft_draw, (Drawable) win);
975 XftDrawSetClip (xft_draw, (Region) region);
977 glyphs = alloca (sizeof (FT_UInt) * (to - from));
978 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
980 if (g->xoff == 0 && g->yoff == 0)
981 glyphs[nglyphs++] = g->code;
985 XftDrawGlyphs (xft_draw, xft_color, xft_font,
986 last_x, y, glyphs, nglyphs);
988 XftDrawGlyphs (xft_draw, xft_color, xft_font,
989 x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
990 last_x = x + g->width;
994 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1000 /* Functions for the device driver. */
1003 mwin__device_init ()
1005 M_iso8859_1 = msymbol ("iso8859-1");
1006 M_iso10646_1 = msymbol ("iso10646-1");
1008 display_info_list = mplist ();
1009 device_list = mplist ();
1011 Mxim = msymbol ("xim");
1012 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1018 mwin__device_fini ()
1020 M17N_OBJECT_UNREF (display_info_list);
1021 M17N_OBJECT_UNREF (device_list);
1025 /** Return an MWDevice object corresponding to a display specified in
1028 It searches device_list for a device matching the display. If
1029 found, return the found object. Otherwise, return a newly created
1033 mwin__open_device (MFrame *frame, MPlist *param)
1035 Display *display = NULL;
1036 Screen *screen = NULL;
1038 Drawable drawable = 0;
1039 Widget widget = NULL;
1041 int auto_display = 0;
1042 MDisplayInfo *disp_info = NULL;
1043 MWDevice *device = NULL;
1045 XWindowAttributes attr;
1051 for (plist = param; (key = mplist_key (plist)) != Mnil;
1052 plist = mplist_next (plist))
1054 if (key == Mdisplay)
1055 display = (Display *) mplist_value (plist);
1056 else if (key == Mscreen)
1057 screen = mplist_value (plist);
1058 else if (key == Mdrawable)
1059 drawable = (Drawable) mplist_value (plist);
1060 else if (key == Mdepth)
1061 depth = (unsigned) mplist_value (plist);
1062 else if (key == Mwidget)
1063 widget = (Widget) mplist_value (plist);
1064 else if (key == Mcolormap)
1065 cmap = (Colormap) mplist_value (plist);
1070 display = XtDisplay (widget);
1071 screen_num = XScreenNumberOfScreen (XtScreen (widget));
1072 depth = DefaultDepth (display, screen_num);
1078 unsigned width, height, border_width;
1081 MERROR (MERROR_WIN, -1);
1082 XGetGeometry (display, drawable, &root_window,
1083 &x, &y, &width, &height, &border_width, &depth);
1084 XGetWindowAttributes (display, root_window, &attr);
1085 screen_num = XScreenNumberOfScreen (attr.screen);
1090 display = DisplayOfScreen (screen);
1095 display = XOpenDisplay (NULL);
1097 MERROR (MERROR_WIN, -1);
1100 screen = DefaultScreenOfDisplay (display);
1102 screen_num = XScreenNumberOfScreen (screen);
1104 depth = DefaultDepth (display, screen_num);
1108 cmap = DefaultColormap (display, screen_num);
1110 for (plist = display_info_list; mplist_key (plist) != Mnil;
1111 plist = mplist_next (plist))
1113 disp_info = (MDisplayInfo *) mplist_value (plist);
1114 if (disp_info->display == display)
1118 if (mplist_key (plist) != Mnil)
1119 M17N_OBJECT_REF (disp_info);
1122 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
1123 disp_info->display = display;
1124 disp_info->auto_display = auto_display;
1125 disp_info->font_registry_list = mplist ();
1126 disp_info->iso8859_1_family_list = mplist ();
1127 disp_info->iso10646_1_family_list = mplist ();
1128 disp_info->realized_font_list = mplist ();
1129 find_modifier_bits (disp_info);
1130 mplist_add (display_info_list, Mt, disp_info);
1133 for (plist = device_list; mplist_key (plist) != Mnil;
1134 plist = mplist_next (plist))
1136 device = (MWDevice *) mplist_value (plist);
1137 if (device->display_info == disp_info
1138 && device->depth == depth
1139 && device->cmap == cmap)
1143 if (mplist_key (plist) != Mnil)
1144 M17N_OBJECT_REF (device);
1147 unsigned long valuemask = GCForeground;
1150 M17N_OBJECT (device, free_device, MERROR_WIN);
1151 device->display_info = disp_info;
1152 device->screen_num = screen_num;
1153 /* A drawable on which to create GCs. */
1154 device->drawable = XCreatePixmap (display,
1155 RootWindow (display, screen_num),
1157 device->depth = depth;
1158 device->cmap = cmap;
1159 device->realized_face_list = mplist ();
1160 device->realized_fontset_list = mplist ();
1161 device->gc_list = mplist ();
1162 values.foreground = BlackPixel (display, screen_num);
1163 device->scratch_gc = XCreateGC (display, device->drawable,
1164 valuemask, &values);
1166 device->xft_draw = XftDrawCreate (display, device->drawable,
1167 DefaultVisual (display, screen_num),
1172 frame->device = device;
1173 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
1174 frame->font_driver_list = mplist ();
1175 mplist_add (frame->font_driver_list, Mx, &xfont_driver);
1177 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
1179 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
1181 frame->realized_font_list = disp_info->realized_font_list;
1182 frame->realized_face_list = device->realized_face_list;
1183 frame->realized_fontset_list = device->realized_fontset_list;
1187 XtResource resources[] = {
1188 { XtNfont, XtCFont, XtRString, sizeof (String),
1189 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
1190 { XtNforeground, XtCForeground, XtRString, sizeof (String),
1191 XtOffset (AppDataPtr, foreground), XtRString, "black" },
1192 { XtNbackground, XtCBackground, XtRString, sizeof (String),
1193 XtOffset (AppDataPtr, background), XtRString, "white" },
1194 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
1195 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
1198 XtGetApplicationResources (widget, &app_data,
1199 resources, XtNumber (resources), NULL, 0);
1200 frame->foreground = msymbol (app_data.foreground);
1201 frame->background = msymbol (app_data.background);
1202 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
1206 app_data.font = DEFAULT_FONT;
1207 frame->foreground = msymbol ("black");
1208 frame->background = msymbol ("white");
1209 frame->videomode = Mnormal;
1214 char **names = XListFonts (display, app_data.font, 1, &nfonts);
1218 if (! (frame->font = mfont_parse_name (names[0], Mx)))
1220 /* The font name does not conform to XLFD. Try to open the
1221 font and get XA_FONT property. */
1222 XFontStruct *xfont = XLoadQueryFont (display, names[0]);
1227 unsigned long value;
1230 if (XGetFontProperty (xfont, XA_FONT, &value)
1231 && (name = ((char *)
1232 XGetAtomName (display, (Atom) value))))
1234 if ((frame->font = mfont_parse_name (name, Mx)))
1237 XFreeFont (display, xfont);
1240 XFreeFontNames (names);
1243 frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
1246 face = mface_from_font (frame->font);
1247 face->property[MFACE_FONTSET] = mfontset (NULL);
1248 face->property[MFACE_FOREGROUND] = frame->foreground;
1249 face->property[MFACE_BACKGROUND] = frame->background;
1250 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
1251 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
1252 face->property[MFACE_VIDEOMODE] = frame->videomode;
1253 mface_put_prop (face, Mhook_func,
1254 mface_get_prop (mface__default, Mhook_func));
1255 face->property[MFACE_RATIO] = (void *) 100;
1256 mplist_push (param, Mface, face);
1257 M17N_OBJECT_UNREF (face);
1259 #ifdef X_SET_ERROR_HANDLER
1260 XSetErrorHandler (x_error_handler);
1261 XSetIOErrorHandler (x_io_error_handler);
1269 mwin__close_device (MFrame *frame)
1271 M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
1275 mwin__device_get_prop (MFrame *frame, MSymbol key)
1277 MWDevice *device = FRAME_DEVICE (frame);
1279 if (key == Mdisplay)
1280 return (void *) device->display_info->display;
1282 return (void *) ScreenOfDisplay(device->display_info->display,
1283 device->screen_num);
1284 if (key == Mcolormap)
1285 return (void *) device->cmap;
1287 return (void *) device->depth;
1292 mwin__realize_face (MRealizedFace *rface)
1295 MSymbol foreground, background, videomode;
1296 MFaceHLineProp *hline;
1300 if (rface != rface->ascii_rface)
1302 rface->info = rface->ascii_rface->info;
1306 frame = rface->frame;
1307 MSTRUCT_CALLOC (info, MERROR_WIN);
1309 foreground = rface->face.property[MFACE_FOREGROUND];
1310 background = rface->face.property[MFACE_BACKGROUND];
1311 videomode = rface->face.property[MFACE_VIDEOMODE];
1313 videomode = frame->videomode;
1314 if (videomode != Mreverse)
1316 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1317 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1321 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1322 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1325 if (foreground == Mnil)
1326 foreground = frame->foreground;
1327 if (background == Mnil)
1328 background = frame->background;
1329 if (videomode == Mreverse)
1331 MSymbol temp = foreground;
1332 foreground = background;
1335 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1336 FRAME_VISUAL (frame),
1338 MSYMBOL_NAME (foreground),
1339 &info->xft_color_fore))
1341 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1342 FRAME_VISUAL (frame),
1344 MSYMBOL_NAME (background),
1345 &info->xft_color_back))
1349 hline = rface->hline;
1353 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1355 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1362 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1364 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1366 if (box->color_left && box->color_left != box->color_top)
1367 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1369 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1371 if (box->color_bottom && box->color_bottom != box->color_top)
1372 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1374 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1376 if (box->color_right && box->color_right != box->color_bottom)
1377 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1379 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1387 mwin__free_realized_face (MRealizedFace *rface)
1389 if (rface == rface->ascii_rface)
1395 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1397 int x, int y, int width, int height, MDrawRegion region)
1399 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1402 gc = set_region (frame, gc, region);
1404 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1405 x, y, width, height);
1410 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1411 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1412 int reverse, MDrawRegion region)
1414 MRealizedFace *rface = from->rface;
1415 Display *display = FRAME_DISPLAY (rface->frame);
1416 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1422 gc = set_region (rface->frame, gc, region);
1423 for (; from < to; from++)
1425 XDrawRectangle (display, (Window) win, gc,
1426 x, y - gstring->ascent + 1, from->width - 1,
1427 gstring->ascent + gstring->descent - 2);
1434 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1435 MRealizedFace *rface, int reverse,
1436 int x, int y, int width, MDrawRegion region)
1438 enum MFaceHLineType type = rface->hline->type;
1439 GCInfo *info = rface->info;
1440 GC gc = gc = info->gc[GC_HLINE];
1443 y = (type == MFACE_HLINE_BOTTOM
1444 ? y + gstring->text_descent - rface->hline->width
1445 : type == MFACE_HLINE_UNDER
1447 : type == MFACE_HLINE_STRIKE_THROUGH
1448 ? y - ((gstring->ascent + gstring->descent) / 2)
1449 : y - gstring->text_ascent);
1451 gc = set_region (frame, gc, region);
1453 for (i = 0; i < rface->hline->width; i++)
1454 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1455 x, y + i, x + width - 1, y + i);
1460 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1461 MGlyph *g, int x, int y, int width, MDrawRegion region)
1463 Display *display = FRAME_DISPLAY (frame);
1464 MRealizedFace *rface = g->rface;
1465 MFaceBoxProp *box = rface->box;
1466 GCInfo *info = rface->info;
1467 GC gc_top, gc_left, gc_right, gc_btm;
1471 y0 = y - (gstring->text_ascent
1472 + rface->box->inner_vmargin + rface->box->width);
1473 y1 = y + (gstring->text_descent
1474 + rface->box->inner_vmargin + rface->box->width - 1);
1476 gc_top = info->gc[GC_BOX_TOP];
1478 gc_top = set_region (frame, gc_top, region);
1479 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1482 gc_btm = info->gc[GC_BOX_BOTTOM];
1484 if (g->type == GLYPH_BOX)
1488 if (g->left_padding)
1489 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1491 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1493 /* Draw the top side. */
1494 for (i = 0; i < box->width; i++)
1495 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1497 /* Draw the bottom side. */
1498 if (region && gc_btm != gc_top)
1499 gc_btm = set_region (frame, gc_btm, region);
1500 for (i = 0; i < box->width; i++)
1501 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1503 if (g->left_padding > 0)
1505 /* Draw the left side. */
1506 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1510 gc_left = info->gc[GC_BOX_LEFT];
1512 gc_left = set_region (frame, gc_left, region);
1514 for (i = 0; i < rface->box->width; i++)
1515 XDrawLine (display, (Window) win, gc_left,
1516 x0 + i, y0 + i, x0 + i, y1 - i);
1520 /* Draw the right side. */
1521 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1525 gc_right = info->gc[GC_BOX_RIGHT];
1527 gc_right = set_region (frame, gc_right, region);
1529 for (i = 0; i < rface->box->width; i++)
1530 XDrawLine (display, (Window) win, gc_right,
1531 x1 - i, y0 + i, x1 - i, y1 - i);
1536 /* Draw the top side. */
1537 for (i = 0; i < box->width; i++)
1538 XDrawLine (display, (Window) win, gc_top,
1539 x, y0 + i, x + width - 1, y0 + i);
1541 /* Draw the bottom side. */
1542 if (region && gc_btm != gc_top)
1543 gc_btm = set_region (frame, gc_btm, region);
1544 for (i = 0; i < box->width; i++)
1545 XDrawLine (display, (Window) win, gc_btm,
1546 x, y1 - i, x + width - 1, y1 - i);
1553 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1554 int reverse, int x, int y,
1555 int width, int height, int row_bytes, unsigned char *bmp,
1558 Display *display = FRAME_DISPLAY (frame);
1560 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1563 gc = set_region (frame, gc, region);
1565 for (i = 0; i < height; i++, bmp += row_bytes)
1566 for (j = 0; j < width; j++)
1567 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1568 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1573 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1574 int intensity, MDrawPoint *points, int num,
1577 GCInfo *info = rface->info;
1580 if (! (gc = info->gc[intensity]))
1581 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1584 gc = set_region (frame, gc, region);
1586 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1587 (XPoint *) points, num, CoordModeOrigin);
1592 mwin__region_from_rect (MDrawMetric *rect)
1594 MDrawRegion region1 = XCreateRegion ();
1595 MDrawRegion region2 = XCreateRegion ();
1600 xrect.width = rect->width;
1601 xrect.height = rect->height;
1602 XUnionRectWithRegion (&xrect, region1, region2);
1603 XDestroyRegion (region1);
1608 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1610 MDrawRegion region1 = XCreateRegion ();
1615 xrect.width = rect->width;
1616 xrect.height = rect->height;
1618 XUnionRegion (region, region, region1);
1619 XUnionRectWithRegion (&xrect, region1, region);
1620 XDestroyRegion (region1);
1624 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1626 MDrawRegion region = XCreateRegion ();
1628 XUnionRegion (region1, region1, region);
1629 XIntersectRegion (region, region2, region1);
1630 XDestroyRegion (region);
1634 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1636 MDrawRegion region1 = XCreateRegion ();
1641 xrect.width = rect->width;
1642 xrect.height = rect->height;
1643 XUnionRectWithRegion (&xrect, region1, region);
1644 XDestroyRegion (region1);
1648 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1652 XClipBox (region, &xrect);
1655 rect->width = xrect.width;
1656 rect->height = xrect.height;
1660 mwin__free_region (MDrawRegion region)
1662 XDestroyRegion (region);
1666 mwin__dump_region (MDrawRegion region)
1669 XClipBox (region, &rect);
1670 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1675 mwin__create_window (MFrame *frame, MDrawWindow parent)
1677 Display *display = FRAME_DISPLAY (frame);
1679 XWMHints wm_hints = { InputHint, False };
1680 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1681 XSetWindowAttributes set_attrs;
1684 GCInfo *info = frame->rface->info;
1687 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1688 mask = GCForeground;
1689 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1690 set_attrs.background_pixel = values.foreground;
1691 set_attrs.backing_store = Always;
1692 set_attrs.override_redirect = True;
1693 set_attrs.save_under = True;
1694 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1695 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1696 CopyFromParent, InputOutput, CopyFromParent,
1698 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1699 NULL, &wm_hints, &class_hints);
1700 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1701 return (MDrawWindow) win;
1705 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1707 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1712 mwin__event_window (void *event)
1714 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1718 mwin__print_event (void *arg, char *win_name)
1721 XEvent *event = (XEvent *) arg;
1723 switch (event->xany.type)
1725 case 2: event_name = "KeyPress"; break;
1726 case 3: event_name = "KeyRelease"; break;
1727 case 4: event_name = "ButtonPress"; break;
1728 case 5: event_name = "ButtonRelease"; break;
1729 case 6: event_name = "MotionNotify"; break;
1730 case 7: event_name = "EnterNotify"; break;
1731 case 8: event_name = "LeaveNotify"; break;
1732 case 9: event_name = "FocusIn"; break;
1733 case 10: event_name = "FocusOut"; break;
1734 case 11: event_name = "KeymapNotify"; break;
1735 case 12: event_name = "Expose"; break;
1736 case 13: event_name = "GraphicsExpose"; break;
1737 case 14: event_name = "NoExpose"; break;
1738 case 15: event_name = "VisibilityNotify"; break;
1739 case 16: event_name = "CreateNotify"; break;
1740 case 17: event_name = "DestroyNotify"; break;
1741 case 18: event_name = "UnmapNotify"; break;
1742 case 19: event_name = "MapNotify"; break;
1743 case 20: event_name = "MapRequest"; break;
1744 case 21: event_name = "ReparentNotify"; break;
1745 case 22: event_name = "ConfigureNotify"; break;
1746 case 23: event_name = "ConfigureRequest"; break;
1747 case 24: event_name = "GravityNotify"; break;
1748 case 25: event_name = "ResizeRequest"; break;
1749 case 26: event_name = "CirculateNotify"; break;
1750 case 27: event_name = "CirculateRequest"; break;
1751 case 28: event_name = "PropertyNotify"; break;
1752 case 29: event_name = "SelectionClear"; break;
1753 case 30: event_name = "SelectionRequest"; break;
1754 case 31: event_name = "SelectionNotify"; break;
1755 case 32: event_name = "ColormapNotify"; break;
1756 case 33: event_name = "ClientMessage"; break;
1757 case 34: event_name = "MappingNotify"; break;
1758 default: event_name = "unknown";
1761 fprintf (stderr, "%s: %s\n", win_name, event_name);
1766 mwin__map_window (MFrame *frame, MDrawWindow win)
1768 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1772 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1774 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1778 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1779 MDrawMetric *geometry)
1781 Display *display = FRAME_DISPLAY (frame);
1782 XWindowAttributes attr;
1783 Window parent = (Window) parent_win, root;
1785 XGetWindowAttributes (display, (Window) win, &attr);
1786 geometry->x = attr.x + attr.border_width;
1787 geometry->y = attr.y + attr.border_width;
1788 geometry->width = attr.width;
1789 geometry->height = attr.height;
1792 parent = RootWindow (display, FRAME_SCREEN (frame));
1795 Window this_parent, *children;
1798 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1801 if (this_parent == parent || this_parent == root)
1803 win = (MDrawWindow) this_parent;
1804 XGetWindowAttributes (display, (Window) win, &attr);
1805 geometry->x += attr.x + attr.border_width;
1806 geometry->y += attr.y + attr.border_width;
1811 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1812 MDrawMetric *current, MDrawMetric *new)
1814 Display *display = FRAME_DISPLAY (frame);
1815 unsigned int mask = 0;
1816 XWindowChanges values;
1818 if (current->width != new->width)
1821 if (new->width <= 0)
1823 values.width = current->width = new->width;
1825 if (current->height != new->height)
1828 if (new->height <= 0)
1830 values.height = current->height = new->height;
1832 if (current->x != new->x)
1835 values.x = current->x = new->x;
1837 if (current->y != new->y)
1840 current->y = new->y;
1841 values.y = current->y = new->y;
1844 XConfigureWindow (display, (Window) win, mask, &values);
1845 XClearWindow (display, (Window) win);
1849 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1851 XEvent *event = (XEvent *) arg;
1852 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1859 if (event->xany.type != KeyPress
1860 /* && event->xany.type != KeyRelease */
1863 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1870 if (c < XK_space || c > XK_asciitilde)
1872 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1873 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1874 if (((XKeyEvent *) event)->state & ControlMask)
1876 if (c >= 'a' && c <= 'z')
1878 if (c >= ' ' && c < 127)
1879 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1881 key = minput__char_to_key (c);
1883 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1887 char *str = XKeysymToString (keysym);
1891 key = msymbol (str);
1892 if (((XKeyEvent *) event)->state & ShiftMask)
1893 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1894 if (((XKeyEvent *) event)->state & ControlMask)
1895 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1897 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1898 *modifiers |= MINPUT_KEY_META_MODIFIER;
1899 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1900 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1901 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1902 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1903 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1904 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1911 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1913 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1915 Display *display = FRAME_DISPLAY (frame);
1916 GCInfo *info = rface->info;
1919 for (i = 0; i <= GC_INVERSE; i++)
1921 XGetGCValues (display, info->gc[i], valuemask, &values);
1922 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1923 values.foreground, values.background);
1924 fprintf (stderr, "\n");
1928 static MDeviceDriver x_driver =
1935 mwin__device_get_prop,
1937 mwin__free_realized_face,
1939 mwin__draw_empty_boxes,
1943 mwin__region_from_rect,
1944 mwin__union_rect_with_region,
1945 mwin__intersect_region,
1946 mwin__region_add_rect,
1947 mwin__region_to_rect,
1950 mwin__create_window,
1951 mwin__destroy_window,
1954 mwin__window_geometry,
1955 mwin__adjust_window,
1961 /* XIM (X Input Method) handler */
1963 typedef struct MInputXIMMethodInfo
1969 } MInputXIMMethodInfo;
1971 typedef struct MInputXIMContextInfo
1975 MConverter *converter;
1976 } MInputXIMContextInfo;
1979 xim_open_im (MInputMethod *im)
1981 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
1982 MLocale *saved, *this;
1983 char *save_modifier_list;
1985 MInputXIMMethodInfo *im_info;
1987 saved = mlocale_set (LC_CTYPE, NULL);
1988 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
1990 /* The specified locale is not supported. */
1991 MERROR (MERROR_LOCALE, -1);
1992 if (mlocale_get_prop (this, Mcoding) == Mnil)
1994 /* Unable to decode the output of XIM. */
1995 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
1996 MERROR (MERROR_LOCALE, -1);
1999 if (arg->modifier_list)
2000 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2002 save_modifier_list = XSetLocaleModifiers ("");
2003 if (! save_modifier_list)
2005 /* The specified locale is not supported by X. */
2006 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2007 MERROR (MERROR_LOCALE, -1);
2010 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2013 /* No input method is available in the current locale. */
2014 XSetLocaleModifiers (save_modifier_list);
2015 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2016 MERROR (MERROR_WIN, -1);
2019 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2020 im_info->display = arg->display;
2022 im_info->language = mlocale_get_prop (this, Mlanguage);
2023 im_info->coding = mlocale_get_prop (this, Mcoding);
2026 XSetLocaleModifiers (save_modifier_list);
2027 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2033 xim_close_im (MInputMethod *im)
2035 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2037 XCloseIM (im_info->xim);
2042 xim_create_ic (MInputContext *ic)
2044 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2045 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2046 MInputXIMContextInfo *ic_info;
2049 if (! arg->input_style)
2051 /* By default, use Root style. */
2052 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2053 arg->preedit_attrs = NULL;
2054 arg->status_attrs = NULL;
2057 if (! arg->preedit_attrs && ! arg->status_attrs)
2058 xic = XCreateIC (im_info->xim,
2059 XNInputStyle, arg->input_style,
2060 XNClientWindow, arg->client_win,
2061 XNFocusWindow, arg->focus_win,
2063 else if (arg->preedit_attrs && ! arg->status_attrs)
2064 xic = XCreateIC (im_info->xim,
2065 XNInputStyle, arg->input_style,
2066 XNClientWindow, arg->client_win,
2067 XNFocusWindow, arg->focus_win,
2068 XNPreeditAttributes, arg->preedit_attrs,
2070 else if (! arg->preedit_attrs && arg->status_attrs)
2071 xic = XCreateIC (im_info->xim,
2072 XNInputStyle, arg->input_style,
2073 XNClientWindow, arg->client_win,
2074 XNFocusWindow, arg->focus_win,
2075 XNStatusAttributes, arg->status_attrs,
2078 xic = XCreateIC (im_info->xim,
2079 XNInputStyle, arg->input_style,
2080 XNClientWindow, arg->client_win,
2081 XNFocusWindow, arg->focus_win,
2082 XNPreeditAttributes, arg->preedit_attrs,
2083 XNStatusAttributes, arg->status_attrs,
2086 MERROR (MERROR_WIN, -1);
2088 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2090 ic_info->win = arg->focus_win;
2091 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2097 xim_destroy_ic (MInputContext *ic)
2099 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2101 XDestroyIC (ic_info->xic);
2102 mconv_free_converter (ic_info->converter);
2108 xim_filter (MInputContext *ic, MSymbol key, void *event)
2110 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2112 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2117 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2119 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2120 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2121 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2127 buf = (char *) alloca (512);
2128 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2129 if (status == XBufferOverflow)
2131 buf = (char *) alloca (len);
2132 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2135 mtext_reset (ic->produced);
2139 mconv_reset_converter (ic_info->converter);
2140 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2141 mconv_decode (ic_info->converter, ic->produced);
2142 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2143 Mlanguage, (void *) im_info->language);
2144 mtext_cpy (mt, ic->produced);
2145 mtext_reset (ic->produced);
2151 #ifdef X_SET_ERROR_HANDLER
2153 x_error_handler (Display *display, XErrorEvent *error)
2160 x_io_error_handler (Display *display)
2168 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2175 x_driver.initialized = 0;
2176 mplist_put (m17n__device_library_list, Mx, &x_driver);
2179 xft_driver.select = mfont__ft_driver.select;
2180 xft_driver.encode_char = mfont__ft_driver.encode_char;
2187 /*** @addtogroup m17nInputMethodWin */
2192 @brief Input method driver for XIM.
2194 The driver #minput_xim_driver is for the foreign input method of
2195 name #Mxim. It uses XIM (X Input Methods) as a background input
2198 As the symbol #Mxim has property #Minput_driver whose value is
2199 a pointer to this driver, the input method of language #Mnil
2200 and name #Mxim uses this driver.
2202 Therefore, for such input methods, the driver dependent arguments
2203 to the functions whose name begin with minput_ must be as follows.
2205 The argument $ARG of the function minput_open_im () must be a
2206 pointer to the structure #MInputXIMArgIM. See the documentation
2207 of #MInputXIMArgIM for more details.
2209 The argument $ARG of the function minput_create_ic () must be a
2210 pointer to the structure #MInputXIMArgIC. See the documentation
2211 of #MInputXIMArgIC for more details.
2213 The argument $ARG of the function minput_filter () must be a
2214 pointer to the structure @c XEvent. The argument $KEY is ignored.
2216 The argument $ARG of the function minput_lookup () must be the
2217 same one as that of the function minput_filter (). The argument
2221 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2223 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
2224 ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
2227 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2228 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
2229 ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2231 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
2232 ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2234 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM ¤Ø¤Î¥Ý
2235 ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
2238 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC ¤Ø¤Î
2239 ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
2242 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2243 ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2245 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2246 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2249 MInputDriver minput_xim_driver =
2250 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2251 xim_filter, xim_lookup, NULL };