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 /** Modifier bit masks of the display. */
86 /* Anchor of the chain of MDisplayInfo objects. */
87 static MPlist *display_info_list;
90 /* Color value and the corresponding GC. */
93 unsigned int rgb; /* (red << 16) | (green << 8) | blue */
100 GC_NORMAL = GC_INVERSE + 7,
113 /* The first 8 elements are indexed by an intensity for
114 anti-aliasing. The 2nd to 7th are created on demand. */
117 XftColor xft_color_fore, xft_color_back;
123 /* Common header for the m17n object. */
126 MDisplayInfo *display_info;
142 /** List of pointers to realized faces on the frame. */
143 MPlist *realized_face_list;
145 /* List of information about each font. Keys are font registries,
146 values are (MFontInfo *). */
147 MPlist *realized_font_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 if (disp_info->auto_display)
215 XCloseDisplay (disp_info->display);
221 free_device (void *object)
223 MWDevice *device = object;
226 for (plist = device->realized_fontset_list;
227 mplist_key (plist) != Mnil; plist = mplist_next (plist))
228 mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist));
229 M17N_OBJECT_UNREF (device->realized_fontset_list);
231 MPLIST_DO (plist, device->realized_font_list)
232 mfont__free_realized ((MRealizedFont *) MPLIST_VAL (plist));
233 M17N_OBJECT_UNREF (device->realized_font_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;
611 rfont->fontp = xfont_info->xfont;
616 /* The X font driver function FIND_METRIC. */
619 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
622 MXFontInfo *xfont_info = rfont->info;
623 XFontStruct *xfont = xfont_info->xfont;
624 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
626 for (; g != gend; g++)
628 if (g->code == MCHAR_INVALID_CODE)
630 g->lbearing = xfont->max_bounds.lbearing;
631 g->rbearing = xfont->max_bounds.rbearing;
632 g->width = xfont->max_bounds.width;
633 g->ascent = xfont->ascent;
634 g->descent = xfont->descent;
638 int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
639 XCharStruct *pcm = NULL;
641 if (xfont->per_char != NULL)
643 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
646 && byte2 >= xfont->min_char_or_byte2
647 && byte2 <= xfont->max_char_or_byte2)
648 pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
652 if (byte1 >= xfont->min_byte1
653 && byte1 <= xfont->max_byte1
654 && byte2 >= xfont->min_char_or_byte2
655 && byte2 <= xfont->max_char_or_byte2)
657 pcm = (xfont->per_char
658 + ((xfont->max_char_or_byte2
659 - xfont->min_char_or_byte2 + 1)
660 * (byte1 - xfont->min_byte1))
661 + (byte2 - xfont->min_char_or_byte2));
668 g->lbearing = pcm->lbearing;
669 g->rbearing = pcm->rbearing;
670 g->width = pcm->width;
671 g->ascent = pcm->ascent;
672 g->descent = pcm->descent;
676 /* If the per_char pointer is null, all glyphs between
677 the first and last character indexes inclusive have
678 the same information, as given by both min_bounds and
681 g->rbearing = xfont->max_bounds.width;
682 g->width = xfont->max_bounds.width;
683 g->ascent = xfont->ascent;
684 g->descent = xfont->descent;
691 /* The X font driver function GET_GLYPH_ID. */
694 xfont_encode_char (MRealizedFont *rfont, unsigned code)
696 MXFontInfo *xfont_info;
698 unsigned min_byte1, max_byte1, min_byte2, max_byte2;
701 if (rfont->status < 0 || code >= 0x10000)
702 return MCHAR_INVALID_CODE;
703 if (rfont->status == 0)
705 if (xfont_open (rfont) < 0)
706 return MCHAR_INVALID_CODE;
708 xfont_info = rfont->info;
709 xfont = xfont_info->xfont;
710 all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
711 min_byte1 = xfont->min_byte1;
712 max_byte1 = xfont->max_byte1;
713 min_byte2 = xfont->min_char_or_byte2;
714 max_byte2 = xfont->max_char_or_byte2;
716 if (min_byte1 == 0 && max_byte1 == 0)
720 if (code < min_byte2 || code > max_byte2)
721 return MCHAR_INVALID_CODE;
724 pcm = xfont->per_char + (code - min_byte2);
725 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
726 ? code : MCHAR_INVALID_CODE);
730 unsigned byte1 = code >> 8, byte2 = code & 0xFF;
733 if (byte1 < min_byte1 || byte1 > max_byte1
734 || byte2 < min_byte2 || byte2 > max_byte2)
735 return MCHAR_INVALID_CODE;
739 pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
740 + (byte2 - min_byte2));
741 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
742 ? code : MCHAR_INVALID_CODE);
746 /* The X font driver function RENDER. */
749 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
750 MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
752 MRealizedFace *rface = from->rface;
753 MXFontInfo *xfont_info = rface->rfont->info;
756 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
763 /* It is assured that the all glyphs in the current range use the
764 same realized face. */
765 display = FRAME_DISPLAY (rface->frame);
768 gc = set_region (rface->frame, gc, region);
769 XSetFont (display, gc, xfont_info->xfont->fid);
770 code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
771 for (i = 0, g = from; g < to; i++, g++)
773 code[i].byte1 = g->code >> 8;
774 code[i].byte2 = g->code & 0xFF;
780 if (g->type == GLYPH_PAD)
782 else if (g->type == GLYPH_SPACE)
783 for (; g < to && g->type == GLYPH_SPACE; g++)
785 else if (! g->rface->rfont)
787 if ((g->c >= 0x200B && g->c <= 0x200F)
788 || (g->c >= 0x202A && g->c <= 0x202E))
792 /* As a font is not found for this character, draw an
794 int box_width = g->width;
795 int box_height = gstring->ascent + gstring->descent;
801 XDrawRectangle (display, (Window) win, gc,
802 x, y - gstring->ascent, box_width, box_height);
806 else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
808 XDrawString16 (display, (Window) win, gc,
809 x + g->xoff, y + g->yoff, code + (g - from), 1);
816 int code_idx = g - from;
819 g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
822 XDrawString16 (display, (Window) win, gc, orig_x, y,
841 static int xft_open (MRealizedFont *);
842 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
843 static void xft_render (MDrawWindow, int, int, MGlyphString *,
844 MGlyph *, MGlyph *, int, MDrawRegion);
846 MFontDriver xft_driver =
847 { NULL, /* Set to ft_select in device_init (). */
848 xft_open, xft_find_metric,
849 NULL, /* Set to ft_encode_char in device_init (). */
854 close_xft (void *object)
856 MXftFontInfo *font_info = object;
858 XftFontClose (font_info->display, font_info->font_aa);
859 XftFontClose (font_info->display, font_info->font_no_aa);
865 xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
868 XftFontInfo *xft_font_info;
871 pattern = XftPatternCreate ();
872 XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
873 XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
874 XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
875 xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
878 font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
879 XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
885 xft_open (MRealizedFont *rfont)
889 MXftFontInfo *font_info;
892 if ((mfont__ft_driver.open) (rfont) < 0)
895 size = rfont->font.property[MFONT_SIZE] / 10;
896 frame = rfont->frame;
898 ft_info = rfont->info;
899 M17N_OBJECT (font_info, close_xft, MERROR_WIN);
900 ft_info->extra_info = font_info;
901 font_info->display = FRAME_DISPLAY (frame);
902 font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
903 if (font_info->font_aa)
905 font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
906 if (font_info->font_no_aa)
909 rfont->fontp = font_info->font_no_aa;
912 XftFontClose (FRAME_DISPLAY (rfont->frame), font_info->font_aa);
915 ft_info->extra_info = NULL;
922 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
925 MFTInfo *ft_info = rfont->info;
926 MXftFontInfo *font_info = ft_info->extra_info;
927 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
929 for (; g != gend; g++)
931 if (g->code == MCHAR_INVALID_CODE)
935 while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
936 (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
944 XftGlyphExtents (FRAME_DISPLAY (gstring->frame),
945 font_info->font_aa, &g->code, 1, &extents);
946 g->lbearing = - extents.x;
947 g->rbearing = extents.width - extents.x;
948 g->width = extents.xOff;
949 g->ascent = extents.y;
950 g->descent = extents.height - extents.y;
957 xft_render (MDrawWindow win, int x, int y,
958 MGlyphString *gstring, MGlyph *from, MGlyph *to,
959 int reverse, MDrawRegion region)
961 MRealizedFace *rface = from->rface;
962 MFrame *frame = rface->frame;
963 MFTInfo *ft_info = rface->rfont->info;
964 MXftFontInfo *font_info = ft_info->extra_info;
965 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
966 XftColor *xft_color = (! reverse
967 ? &((GCInfo *) rface->info)->xft_color_fore
968 : &((GCInfo *) rface->info)->xft_color_back);
969 XftFont *xft_font = (gstring->control.anti_alias
970 && FRAME_DEVICE (frame)->depth > 1
971 ? font_info->font_aa : font_info->font_no_aa);
980 XftDrawChange (xft_draw, (Drawable) win);
981 XftDrawSetClip (xft_draw, (Region) region);
983 glyphs = alloca (sizeof (FT_UInt) * (to - from));
984 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
986 if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
987 glyphs[nglyphs++] = g->code;
991 XftDrawGlyphs (xft_draw, xft_color, xft_font,
992 last_x, y, glyphs, nglyphs);
994 XftDrawGlyphs (xft_draw, xft_color, xft_font,
995 x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
996 last_x = x + g->width;
1000 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1006 /* Functions for the device driver. */
1009 mwin__close_device (MFrame *frame)
1011 M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
1015 mwin__device_get_prop (MFrame *frame, MSymbol key)
1017 MWDevice *device = FRAME_DEVICE (frame);
1019 if (key == Mdisplay)
1020 return (void *) device->display_info->display;
1022 return (void *) ScreenOfDisplay(device->display_info->display,
1023 device->screen_num);
1024 if (key == Mcolormap)
1025 return (void *) device->cmap;
1027 return (void *) device->depth;
1032 mwin__realize_face (MRealizedFace *rface)
1035 MSymbol foreground, background, videomode;
1036 MFaceHLineProp *hline;
1040 if (rface != rface->ascii_rface)
1042 rface->info = rface->ascii_rface->info;
1046 frame = rface->frame;
1047 MSTRUCT_CALLOC (info, MERROR_WIN);
1049 foreground = rface->face.property[MFACE_FOREGROUND];
1050 background = rface->face.property[MFACE_BACKGROUND];
1051 videomode = rface->face.property[MFACE_VIDEOMODE];
1053 videomode = frame->videomode;
1054 if (videomode != Mreverse)
1056 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1057 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1061 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1062 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1065 if (foreground == Mnil)
1066 foreground = frame->foreground;
1067 if (background == Mnil)
1068 background = frame->background;
1069 if (videomode == Mreverse)
1071 MSymbol temp = foreground;
1072 foreground = background;
1075 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1076 FRAME_VISUAL (frame),
1078 MSYMBOL_NAME (foreground),
1079 &info->xft_color_fore))
1081 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1082 FRAME_VISUAL (frame),
1084 MSYMBOL_NAME (background),
1085 &info->xft_color_back))
1089 hline = rface->hline;
1093 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1095 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1102 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1104 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1106 if (box->color_left && box->color_left != box->color_top)
1107 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1109 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1111 if (box->color_bottom && box->color_bottom != box->color_top)
1112 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1114 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1116 if (box->color_right && box->color_right != box->color_bottom)
1117 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1119 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1127 mwin__free_realized_face (MRealizedFace *rface)
1129 if (rface == rface->ascii_rface)
1135 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1137 int x, int y, int width, int height, MDrawRegion region)
1139 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1142 gc = set_region (frame, gc, region);
1144 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1145 x, y, width, height);
1150 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1151 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1152 int reverse, MDrawRegion region)
1154 MRealizedFace *rface = from->rface;
1155 Display *display = FRAME_DISPLAY (rface->frame);
1156 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1162 gc = set_region (rface->frame, gc, region);
1163 for (; from < to; from++)
1165 XDrawRectangle (display, (Window) win, gc,
1166 x, y - gstring->ascent + 1, from->width - 1,
1167 gstring->ascent + gstring->descent - 2);
1174 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1175 MRealizedFace *rface, int reverse,
1176 int x, int y, int width, MDrawRegion region)
1178 enum MFaceHLineType type = rface->hline->type;
1179 GCInfo *info = rface->info;
1180 GC gc = gc = info->gc[GC_HLINE];
1183 y = (type == MFACE_HLINE_BOTTOM
1184 ? y + gstring->text_descent - rface->hline->width
1185 : type == MFACE_HLINE_UNDER
1187 : type == MFACE_HLINE_STRIKE_THROUGH
1188 ? y - ((gstring->ascent + gstring->descent) / 2)
1189 : y - gstring->text_ascent);
1191 gc = set_region (frame, gc, region);
1193 for (i = 0; i < rface->hline->width; i++)
1194 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1195 x, y + i, x + width - 1, y + i);
1200 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1201 MGlyph *g, int x, int y, int width, MDrawRegion region)
1203 Display *display = FRAME_DISPLAY (frame);
1204 MRealizedFace *rface = g->rface;
1205 MFaceBoxProp *box = rface->box;
1206 GCInfo *info = rface->info;
1207 GC gc_top, gc_left, gc_right, gc_btm;
1211 y0 = y - (gstring->text_ascent
1212 + rface->box->inner_vmargin + rface->box->width);
1213 y1 = y + (gstring->text_descent
1214 + rface->box->inner_vmargin + rface->box->width - 1);
1216 gc_top = info->gc[GC_BOX_TOP];
1218 gc_top = set_region (frame, gc_top, region);
1219 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1222 gc_btm = info->gc[GC_BOX_BOTTOM];
1224 if (g->type == GLYPH_BOX)
1228 if (g->left_padding)
1229 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1231 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1233 /* Draw the top side. */
1234 for (i = 0; i < box->width; i++)
1235 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1237 /* Draw the bottom side. */
1238 if (region && gc_btm != gc_top)
1239 gc_btm = set_region (frame, gc_btm, region);
1240 for (i = 0; i < box->width; i++)
1241 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1243 if (g->left_padding > 0)
1245 /* Draw the left side. */
1246 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1250 gc_left = info->gc[GC_BOX_LEFT];
1252 gc_left = set_region (frame, gc_left, region);
1254 for (i = 0; i < rface->box->width; i++)
1255 XDrawLine (display, (Window) win, gc_left,
1256 x0 + i, y0 + i, x0 + i, y1 - i);
1260 /* Draw the right side. */
1261 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1265 gc_right = info->gc[GC_BOX_RIGHT];
1267 gc_right = set_region (frame, gc_right, region);
1269 for (i = 0; i < rface->box->width; i++)
1270 XDrawLine (display, (Window) win, gc_right,
1271 x1 - i, y0 + i, x1 - i, y1 - i);
1276 /* Draw the top side. */
1277 for (i = 0; i < box->width; i++)
1278 XDrawLine (display, (Window) win, gc_top,
1279 x, y0 + i, x + width - 1, y0 + i);
1281 /* Draw the bottom side. */
1282 if (region && gc_btm != gc_top)
1283 gc_btm = set_region (frame, gc_btm, region);
1284 for (i = 0; i < box->width; i++)
1285 XDrawLine (display, (Window) win, gc_btm,
1286 x, y1 - i, x + width - 1, y1 - i);
1293 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1294 int reverse, int x, int y,
1295 int width, int height, int row_bytes, unsigned char *bmp,
1298 Display *display = FRAME_DISPLAY (frame);
1300 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1303 gc = set_region (frame, gc, region);
1305 for (i = 0; i < height; i++, bmp += row_bytes)
1306 for (j = 0; j < width; j++)
1307 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1308 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1313 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1314 int intensity, MDrawPoint *points, int num,
1317 GCInfo *info = rface->info;
1320 if (! (gc = info->gc[intensity]))
1321 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1324 gc = set_region (frame, gc, region);
1326 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1327 (XPoint *) points, num, CoordModeOrigin);
1332 mwin__region_from_rect (MDrawMetric *rect)
1334 MDrawRegion region1 = XCreateRegion ();
1335 MDrawRegion region2 = XCreateRegion ();
1340 xrect.width = rect->width;
1341 xrect.height = rect->height;
1342 XUnionRectWithRegion (&xrect, region1, region2);
1343 XDestroyRegion (region1);
1348 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1350 MDrawRegion region1 = XCreateRegion ();
1355 xrect.width = rect->width;
1356 xrect.height = rect->height;
1358 XUnionRegion (region, region, region1);
1359 XUnionRectWithRegion (&xrect, region1, region);
1360 XDestroyRegion (region1);
1364 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1366 MDrawRegion region = XCreateRegion ();
1368 XUnionRegion (region1, region1, region);
1369 XIntersectRegion (region, region2, region1);
1370 XDestroyRegion (region);
1374 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1376 MDrawRegion region1 = XCreateRegion ();
1381 xrect.width = rect->width;
1382 xrect.height = rect->height;
1383 XUnionRectWithRegion (&xrect, region1, region);
1384 XDestroyRegion (region1);
1388 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1392 XClipBox (region, &xrect);
1395 rect->width = xrect.width;
1396 rect->height = xrect.height;
1400 mwin__free_region (MDrawRegion region)
1402 XDestroyRegion (region);
1406 mwin__dump_region (MDrawRegion region)
1409 XClipBox (region, &rect);
1410 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1415 mwin__create_window (MFrame *frame, MDrawWindow parent)
1417 Display *display = FRAME_DISPLAY (frame);
1419 XWMHints wm_hints = { InputHint, False };
1420 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1421 XSetWindowAttributes set_attrs;
1424 GCInfo *info = frame->rface->info;
1427 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1428 mask = GCForeground;
1429 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1430 set_attrs.background_pixel = values.foreground;
1431 set_attrs.backing_store = Always;
1432 set_attrs.override_redirect = True;
1433 set_attrs.save_under = True;
1434 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1435 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1436 CopyFromParent, InputOutput, CopyFromParent,
1438 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1439 NULL, &wm_hints, &class_hints);
1440 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1441 return (MDrawWindow) win;
1445 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1447 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1452 mwin__event_window (void *event)
1454 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1458 mwin__print_event (void *arg, char *win_name)
1461 XEvent *event = (XEvent *) arg;
1463 switch (event->xany.type)
1465 case 2: event_name = "KeyPress"; break;
1466 case 3: event_name = "KeyRelease"; break;
1467 case 4: event_name = "ButtonPress"; break;
1468 case 5: event_name = "ButtonRelease"; break;
1469 case 6: event_name = "MotionNotify"; break;
1470 case 7: event_name = "EnterNotify"; break;
1471 case 8: event_name = "LeaveNotify"; break;
1472 case 9: event_name = "FocusIn"; break;
1473 case 10: event_name = "FocusOut"; break;
1474 case 11: event_name = "KeymapNotify"; break;
1475 case 12: event_name = "Expose"; break;
1476 case 13: event_name = "GraphicsExpose"; break;
1477 case 14: event_name = "NoExpose"; break;
1478 case 15: event_name = "VisibilityNotify"; break;
1479 case 16: event_name = "CreateNotify"; break;
1480 case 17: event_name = "DestroyNotify"; break;
1481 case 18: event_name = "UnmapNotify"; break;
1482 case 19: event_name = "MapNotify"; break;
1483 case 20: event_name = "MapRequest"; break;
1484 case 21: event_name = "ReparentNotify"; break;
1485 case 22: event_name = "ConfigureNotify"; break;
1486 case 23: event_name = "ConfigureRequest"; break;
1487 case 24: event_name = "GravityNotify"; break;
1488 case 25: event_name = "ResizeRequest"; break;
1489 case 26: event_name = "CirculateNotify"; break;
1490 case 27: event_name = "CirculateRequest"; break;
1491 case 28: event_name = "PropertyNotify"; break;
1492 case 29: event_name = "SelectionClear"; break;
1493 case 30: event_name = "SelectionRequest"; break;
1494 case 31: event_name = "SelectionNotify"; break;
1495 case 32: event_name = "ColormapNotify"; break;
1496 case 33: event_name = "ClientMessage"; break;
1497 case 34: event_name = "MappingNotify"; break;
1498 default: event_name = "unknown";
1501 fprintf (stderr, "%s: %s\n", win_name, event_name);
1506 mwin__map_window (MFrame *frame, MDrawWindow win)
1508 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1512 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1514 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1518 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1519 MDrawMetric *geometry)
1521 Display *display = FRAME_DISPLAY (frame);
1522 XWindowAttributes attr;
1523 Window parent = (Window) parent_win, root;
1525 XGetWindowAttributes (display, (Window) win, &attr);
1526 geometry->x = attr.x + attr.border_width;
1527 geometry->y = attr.y + attr.border_width;
1528 geometry->width = attr.width;
1529 geometry->height = attr.height;
1532 parent = RootWindow (display, FRAME_SCREEN (frame));
1535 Window this_parent, *children;
1538 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1541 if (this_parent == parent || this_parent == root)
1543 win = (MDrawWindow) this_parent;
1544 XGetWindowAttributes (display, (Window) win, &attr);
1545 geometry->x += attr.x + attr.border_width;
1546 geometry->y += attr.y + attr.border_width;
1551 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1552 MDrawMetric *current, MDrawMetric *new)
1554 Display *display = FRAME_DISPLAY (frame);
1555 unsigned int mask = 0;
1556 XWindowChanges values;
1558 if (current->width != new->width)
1561 if (new->width <= 0)
1563 values.width = current->width = new->width;
1565 if (current->height != new->height)
1568 if (new->height <= 0)
1570 values.height = current->height = new->height;
1572 if (current->x != new->x)
1575 values.x = current->x = new->x;
1577 if (current->y != new->y)
1580 current->y = new->y;
1581 values.y = current->y = new->y;
1584 XConfigureWindow (display, (Window) win, mask, &values);
1585 XClearWindow (display, (Window) win);
1589 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1591 XEvent *event = (XEvent *) arg;
1592 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1599 if (event->xany.type != KeyPress
1600 /* && event->xany.type != KeyRelease */
1603 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1610 if (c < XK_space || c > XK_asciitilde)
1612 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1613 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1614 if (((XKeyEvent *) event)->state & ControlMask)
1616 if (c >= 'a' && c <= 'z')
1618 if (c >= ' ' && c < 127)
1619 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1621 key = minput__char_to_key (c);
1623 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1627 char *str = XKeysymToString (keysym);
1631 key = msymbol (str);
1632 if (((XKeyEvent *) event)->state & ShiftMask)
1633 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1634 if (((XKeyEvent *) event)->state & ControlMask)
1635 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1637 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1638 *modifiers |= MINPUT_KEY_META_MODIFIER;
1639 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1640 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1641 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1642 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1643 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1644 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1651 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1653 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1655 Display *display = FRAME_DISPLAY (frame);
1656 GCInfo *info = rface->info;
1659 for (i = 0; i <= GC_INVERSE; i++)
1661 XGetGCValues (display, info->gc[i], valuemask, &values);
1662 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1663 values.foreground, values.background);
1664 fprintf (stderr, "\n");
1668 static MDeviceDriver x_driver =
1671 mwin__device_get_prop,
1673 mwin__free_realized_face,
1675 mwin__draw_empty_boxes,
1679 mwin__region_from_rect,
1680 mwin__union_rect_with_region,
1681 mwin__intersect_region,
1682 mwin__region_add_rect,
1683 mwin__region_to_rect,
1686 mwin__create_window,
1687 mwin__destroy_window,
1690 mwin__window_geometry,
1691 mwin__adjust_window,
1695 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1700 M_iso8859_1 = msymbol ("iso8859-1");
1701 M_iso10646_1 = msymbol ("iso10646-1");
1703 display_info_list = mplist ();
1704 device_list = mplist ();
1707 xft_driver.select = mfont__ft_driver.select;
1708 xft_driver.encode_char = mfont__ft_driver.encode_char;
1711 Mxim = msymbol ("xim");
1712 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1720 M17N_OBJECT_UNREF (display_info_list);
1721 M17N_OBJECT_UNREF (device_list);
1725 /** Return an MWDevice object corresponding to a display specified in
1728 It searches device_list for a device matching the display. If
1729 found, return the found object. Otherwise, return a newly created
1733 device_open (MFrame *frame, MPlist *param)
1735 Display *display = NULL;
1736 Screen *screen = NULL;
1738 Drawable drawable = 0;
1739 Widget widget = NULL;
1741 int auto_display = 0;
1742 MDisplayInfo *disp_info = NULL;
1743 MWDevice *device = NULL;
1745 XWindowAttributes attr;
1751 for (plist = param; (key = mplist_key (plist)) != Mnil;
1752 plist = mplist_next (plist))
1754 if (key == Mdisplay)
1755 display = (Display *) mplist_value (plist);
1756 else if (key == Mscreen)
1757 screen = mplist_value (plist);
1758 else if (key == Mdrawable)
1759 drawable = (Drawable) mplist_value (plist);
1760 else if (key == Mdepth)
1761 depth = (unsigned) mplist_value (plist);
1762 else if (key == Mwidget)
1763 widget = (Widget) mplist_value (plist);
1764 else if (key == Mcolormap)
1765 cmap = (Colormap) mplist_value (plist);
1770 display = XtDisplay (widget);
1771 screen_num = XScreenNumberOfScreen (XtScreen (widget));
1772 depth = DefaultDepth (display, screen_num);
1778 unsigned width, height, border_width;
1781 MERROR (MERROR_WIN, -1);
1782 XGetGeometry (display, drawable, &root_window,
1783 &x, &y, &width, &height, &border_width, &depth);
1784 XGetWindowAttributes (display, root_window, &attr);
1785 screen_num = XScreenNumberOfScreen (attr.screen);
1790 display = DisplayOfScreen (screen);
1795 display = XOpenDisplay (NULL);
1797 MERROR (MERROR_WIN, -1);
1800 screen = DefaultScreenOfDisplay (display);
1802 screen_num = XScreenNumberOfScreen (screen);
1804 depth = DefaultDepth (display, screen_num);
1808 cmap = DefaultColormap (display, screen_num);
1810 for (plist = display_info_list; mplist_key (plist) != Mnil;
1811 plist = mplist_next (plist))
1813 disp_info = (MDisplayInfo *) mplist_value (plist);
1814 if (disp_info->display == display)
1818 if (mplist_key (plist) != Mnil)
1819 M17N_OBJECT_REF (disp_info);
1822 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
1823 disp_info->display = display;
1824 disp_info->auto_display = auto_display;
1825 disp_info->font_registry_list = mplist ();
1826 disp_info->iso8859_1_family_list = mplist ();
1827 disp_info->iso10646_1_family_list = mplist ();
1828 find_modifier_bits (disp_info);
1829 mplist_add (display_info_list, Mt, disp_info);
1832 for (plist = device_list; mplist_key (plist) != Mnil;
1833 plist = mplist_next (plist))
1835 device = (MWDevice *) mplist_value (plist);
1836 if (device->display_info == disp_info
1837 && device->depth == depth
1838 && device->cmap == cmap)
1842 if (mplist_key (plist) != Mnil)
1843 M17N_OBJECT_REF (device);
1846 unsigned long valuemask = GCForeground;
1849 M17N_OBJECT (device, free_device, MERROR_WIN);
1850 device->display_info = disp_info;
1851 device->screen_num = screen_num;
1852 /* A drawable on which to create GCs. */
1853 device->drawable = XCreatePixmap (display,
1854 RootWindow (display, screen_num),
1856 device->depth = depth;
1857 device->cmap = cmap;
1858 device->realized_face_list = mplist ();
1859 device->realized_font_list = mplist ();
1860 device->realized_fontset_list = mplist ();
1861 device->gc_list = mplist ();
1862 values.foreground = BlackPixel (display, screen_num);
1863 device->scratch_gc = XCreateGC (display, device->drawable,
1864 valuemask, &values);
1866 device->xft_draw = XftDrawCreate (display, device->drawable,
1867 DefaultVisual (display, screen_num),
1872 frame->device = device;
1873 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
1874 frame->driver = &x_driver;
1875 frame->font_driver_list = mplist ();
1876 mplist_add (frame->font_driver_list, Mx, &xfont_driver);
1878 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
1880 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
1882 frame->realized_font_list = device->realized_font_list;
1883 frame->realized_face_list = device->realized_face_list;
1884 frame->realized_fontset_list = device->realized_fontset_list;
1888 XtResource resources[] = {
1889 { XtNfont, XtCFont, XtRString, sizeof (String),
1890 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
1891 { XtNforeground, XtCForeground, XtRString, sizeof (String),
1892 XtOffset (AppDataPtr, foreground), XtRString, "black" },
1893 { XtNbackground, XtCBackground, XtRString, sizeof (String),
1894 XtOffset (AppDataPtr, background), XtRString, "white" },
1895 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
1896 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
1899 XtGetApplicationResources (widget, &app_data,
1900 resources, XtNumber (resources), NULL, 0);
1901 frame->foreground = msymbol (app_data.foreground);
1902 frame->background = msymbol (app_data.background);
1903 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
1907 app_data.font = DEFAULT_FONT;
1908 frame->foreground = msymbol ("black");
1909 frame->background = msymbol ("white");
1910 frame->videomode = Mnormal;
1915 char **names = XListFonts (display, app_data.font, 1, &nfonts);
1919 if (! (frame->font = mfont_parse_name (names[0], Mx)))
1921 /* The font name does not conform to XLFD. Try to open the
1922 font and get XA_FONT property. */
1923 XFontStruct *xfont = XLoadQueryFont (display, names[0]);
1928 unsigned long value;
1931 if (XGetFontProperty (xfont, XA_FONT, &value)
1932 && (name = ((char *)
1933 XGetAtomName (display, (Atom) value))))
1935 if ((frame->font = mfont_parse_name (name, Mx)))
1938 XFreeFont (display, xfont);
1941 XFreeFontNames (names);
1944 frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
1947 face = mface_from_font (frame->font);
1948 face->property[MFACE_FONTSET] = mfontset (NULL);
1949 face->property[MFACE_FOREGROUND] = frame->foreground;
1950 face->property[MFACE_BACKGROUND] = frame->background;
1951 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
1952 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
1953 face->property[MFACE_VIDEOMODE] = frame->videomode;
1954 mface_put_prop (face, Mhook_func,
1955 mface_get_prop (mface__default, Mhook_func));
1956 face->property[MFACE_RATIO] = (void *) 100;
1957 mplist_push (param, Mface, face);
1958 M17N_OBJECT_UNREF (face);
1960 #ifdef X_SET_ERROR_HANDLER
1961 XSetErrorHandler (x_error_handler);
1962 XSetIOErrorHandler (x_io_error_handler);
1970 /* XIM (X Input Method) handler */
1972 typedef struct MInputXIMMethodInfo
1978 } MInputXIMMethodInfo;
1980 typedef struct MInputXIMContextInfo
1984 MConverter *converter;
1985 } MInputXIMContextInfo;
1988 xim_open_im (MInputMethod *im)
1990 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
1991 MLocale *saved, *this;
1992 char *save_modifier_list;
1994 MInputXIMMethodInfo *im_info;
1996 saved = mlocale_set (LC_CTYPE, NULL);
1997 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
1999 /* The specified locale is not supported. */
2000 MERROR (MERROR_LOCALE, -1);
2001 if (mlocale_get_prop (this, Mcoding) == Mnil)
2003 /* Unable to decode the output of XIM. */
2004 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2005 MERROR (MERROR_LOCALE, -1);
2008 if (arg->modifier_list)
2009 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2011 save_modifier_list = XSetLocaleModifiers ("");
2012 if (! save_modifier_list)
2014 /* The specified locale is not supported by X. */
2015 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2016 MERROR (MERROR_LOCALE, -1);
2019 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2022 /* No input method is available in the current locale. */
2023 XSetLocaleModifiers (save_modifier_list);
2024 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2025 MERROR (MERROR_WIN, -1);
2028 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2029 im_info->display = arg->display;
2031 im_info->language = mlocale_get_prop (this, Mlanguage);
2032 im_info->coding = mlocale_get_prop (this, Mcoding);
2035 XSetLocaleModifiers (save_modifier_list);
2036 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2042 xim_close_im (MInputMethod *im)
2044 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2046 XCloseIM (im_info->xim);
2051 xim_create_ic (MInputContext *ic)
2053 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2054 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2055 MInputXIMContextInfo *ic_info;
2058 if (! arg->input_style)
2060 /* By default, use Root style. */
2061 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2062 arg->preedit_attrs = NULL;
2063 arg->status_attrs = NULL;
2066 if (! arg->preedit_attrs && ! arg->status_attrs)
2067 xic = XCreateIC (im_info->xim,
2068 XNInputStyle, arg->input_style,
2069 XNClientWindow, arg->client_win,
2070 XNFocusWindow, arg->focus_win,
2072 else if (arg->preedit_attrs && ! arg->status_attrs)
2073 xic = XCreateIC (im_info->xim,
2074 XNInputStyle, arg->input_style,
2075 XNClientWindow, arg->client_win,
2076 XNFocusWindow, arg->focus_win,
2077 XNPreeditAttributes, arg->preedit_attrs,
2079 else if (! arg->preedit_attrs && arg->status_attrs)
2080 xic = XCreateIC (im_info->xim,
2081 XNInputStyle, arg->input_style,
2082 XNClientWindow, arg->client_win,
2083 XNFocusWindow, arg->focus_win,
2084 XNStatusAttributes, arg->status_attrs,
2087 xic = XCreateIC (im_info->xim,
2088 XNInputStyle, arg->input_style,
2089 XNClientWindow, arg->client_win,
2090 XNFocusWindow, arg->focus_win,
2091 XNPreeditAttributes, arg->preedit_attrs,
2092 XNStatusAttributes, arg->status_attrs,
2095 MERROR (MERROR_WIN, -1);
2097 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2099 ic_info->win = arg->focus_win;
2100 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2106 xim_destroy_ic (MInputContext *ic)
2108 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2110 XDestroyIC (ic_info->xic);
2111 mconv_free_converter (ic_info->converter);
2117 xim_filter (MInputContext *ic, MSymbol key, void *event)
2119 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2121 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2126 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2128 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2129 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2130 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2136 buf = (char *) alloca (512);
2137 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2138 if (status == XBufferOverflow)
2140 buf = (char *) alloca (len);
2141 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2144 mtext_reset (ic->produced);
2148 mconv_reset_converter (ic_info->converter);
2149 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2150 mconv_decode (ic_info->converter, ic->produced);
2151 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2152 Mlanguage, (void *) im_info->language);
2153 mtext_cpy (mt, ic->produced);
2154 mtext_reset (ic->produced);
2160 #ifdef X_SET_ERROR_HANDLER
2162 x_error_handler (Display *display, XErrorEvent *error)
2169 x_io_error_handler (Display *display)
2179 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2183 /*** @addtogroup m17nInputMethodWin */
2188 @brief Input method driver for XIM.
2190 The driver #minput_xim_driver is for the foreign input method of
2191 name #Mxim. It uses XIM (X Input Methods) as a background input
2194 As the symbol #Mxim has property #Minput_driver whose value is
2195 a pointer to this driver, the input method of language #Mnil
2196 and name #Mxim uses this driver.
2198 Therefore, for such input methods, the driver dependent arguments
2199 to the functions whose name begin with minput_ must be as follows.
2201 The argument $ARG of the function minput_open_im () must be a
2202 pointer to the structure #MInputXIMArgIM. See the documentation
2203 of #MInputXIMArgIM for more details.
2205 The argument $ARG of the function minput_create_ic () must be a
2206 pointer to the structure #MInputXIMArgIC. See the documentation
2207 of #MInputXIMArgIC for more details.
2209 The argument $ARG of the function minput_filter () must be a
2210 pointer to the structure @c XEvent. The argument $KEY is ignored.
2212 The argument $ARG of the function minput_lookup () must be the
2213 same one as that of the function minput_filter (). The argument
2217 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2219 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
2220 ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
2223 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2224 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
2225 ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2227 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
2228 ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2230 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM ¤Ø¤Î¥Ý
2231 ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
2234 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC ¤Ø¤Î
2235 ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
2238 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2239 ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2241 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2242 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2245 MInputDriver minput_xim_driver =
2246 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2247 xim_filter, xim_lookup, NULL };