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 device_init (). */
846 xft_open, xft_find_metric,
847 NULL, /* Set to ft_encode_char in device_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__close_device (MFrame *frame)
1005 M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
1009 mwin__device_get_prop (MFrame *frame, MSymbol key)
1011 MWDevice *device = FRAME_DEVICE (frame);
1013 if (key == Mdisplay)
1014 return (void *) device->display_info->display;
1016 return (void *) ScreenOfDisplay(device->display_info->display,
1017 device->screen_num);
1018 if (key == Mcolormap)
1019 return (void *) device->cmap;
1021 return (void *) device->depth;
1026 mwin__realize_face (MRealizedFace *rface)
1029 MSymbol foreground, background, videomode;
1030 MFaceHLineProp *hline;
1034 if (rface != rface->ascii_rface)
1036 rface->info = rface->ascii_rface->info;
1040 frame = rface->frame;
1041 MSTRUCT_CALLOC (info, MERROR_WIN);
1043 foreground = rface->face.property[MFACE_FOREGROUND];
1044 background = rface->face.property[MFACE_BACKGROUND];
1045 videomode = rface->face.property[MFACE_VIDEOMODE];
1047 videomode = frame->videomode;
1048 if (videomode != Mreverse)
1050 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1051 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1055 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1056 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1059 if (foreground == Mnil)
1060 foreground = frame->foreground;
1061 if (background == Mnil)
1062 background = frame->background;
1063 if (videomode == Mreverse)
1065 MSymbol temp = foreground;
1066 foreground = background;
1069 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1070 FRAME_VISUAL (frame),
1072 MSYMBOL_NAME (foreground),
1073 &info->xft_color_fore))
1075 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1076 FRAME_VISUAL (frame),
1078 MSYMBOL_NAME (background),
1079 &info->xft_color_back))
1083 hline = rface->hline;
1087 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1089 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1096 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1098 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1100 if (box->color_left && box->color_left != box->color_top)
1101 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1103 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1105 if (box->color_bottom && box->color_bottom != box->color_top)
1106 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1108 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1110 if (box->color_right && box->color_right != box->color_bottom)
1111 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1113 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1121 mwin__free_realized_face (MRealizedFace *rface)
1123 if (rface == rface->ascii_rface)
1129 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1131 int x, int y, int width, int height, MDrawRegion region)
1133 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1136 gc = set_region (frame, gc, region);
1138 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1139 x, y, width, height);
1144 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1145 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1146 int reverse, MDrawRegion region)
1148 MRealizedFace *rface = from->rface;
1149 Display *display = FRAME_DISPLAY (rface->frame);
1150 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1156 gc = set_region (rface->frame, gc, region);
1157 for (; from < to; from++)
1159 XDrawRectangle (display, (Window) win, gc,
1160 x, y - gstring->ascent + 1, from->width - 1,
1161 gstring->ascent + gstring->descent - 2);
1168 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1169 MRealizedFace *rface, int reverse,
1170 int x, int y, int width, MDrawRegion region)
1172 enum MFaceHLineType type = rface->hline->type;
1173 GCInfo *info = rface->info;
1174 GC gc = gc = info->gc[GC_HLINE];
1177 y = (type == MFACE_HLINE_BOTTOM
1178 ? y + gstring->text_descent - rface->hline->width
1179 : type == MFACE_HLINE_UNDER
1181 : type == MFACE_HLINE_STRIKE_THROUGH
1182 ? y - ((gstring->ascent + gstring->descent) / 2)
1183 : y - gstring->text_ascent);
1185 gc = set_region (frame, gc, region);
1187 for (i = 0; i < rface->hline->width; i++)
1188 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1189 x, y + i, x + width - 1, y + i);
1194 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1195 MGlyph *g, int x, int y, int width, MDrawRegion region)
1197 Display *display = FRAME_DISPLAY (frame);
1198 MRealizedFace *rface = g->rface;
1199 MFaceBoxProp *box = rface->box;
1200 GCInfo *info = rface->info;
1201 GC gc_top, gc_left, gc_right, gc_btm;
1205 y0 = y - (gstring->text_ascent
1206 + rface->box->inner_vmargin + rface->box->width);
1207 y1 = y + (gstring->text_descent
1208 + rface->box->inner_vmargin + rface->box->width - 1);
1210 gc_top = info->gc[GC_BOX_TOP];
1212 gc_top = set_region (frame, gc_top, region);
1213 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1216 gc_btm = info->gc[GC_BOX_BOTTOM];
1218 if (g->type == GLYPH_BOX)
1222 if (g->left_padding)
1223 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1225 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1227 /* Draw the top side. */
1228 for (i = 0; i < box->width; i++)
1229 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1231 /* Draw the bottom side. */
1232 if (region && gc_btm != gc_top)
1233 gc_btm = set_region (frame, gc_btm, region);
1234 for (i = 0; i < box->width; i++)
1235 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1237 if (g->left_padding > 0)
1239 /* Draw the left side. */
1240 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1244 gc_left = info->gc[GC_BOX_LEFT];
1246 gc_left = set_region (frame, gc_left, region);
1248 for (i = 0; i < rface->box->width; i++)
1249 XDrawLine (display, (Window) win, gc_left,
1250 x0 + i, y0 + i, x0 + i, y1 - i);
1254 /* Draw the right side. */
1255 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1259 gc_right = info->gc[GC_BOX_RIGHT];
1261 gc_right = set_region (frame, gc_right, region);
1263 for (i = 0; i < rface->box->width; i++)
1264 XDrawLine (display, (Window) win, gc_right,
1265 x1 - i, y0 + i, x1 - i, y1 - i);
1270 /* Draw the top side. */
1271 for (i = 0; i < box->width; i++)
1272 XDrawLine (display, (Window) win, gc_top,
1273 x, y0 + i, x + width - 1, y0 + i);
1275 /* Draw the bottom side. */
1276 if (region && gc_btm != gc_top)
1277 gc_btm = set_region (frame, gc_btm, region);
1278 for (i = 0; i < box->width; i++)
1279 XDrawLine (display, (Window) win, gc_btm,
1280 x, y1 - i, x + width - 1, y1 - i);
1287 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1288 int reverse, int x, int y,
1289 int width, int height, int row_bytes, unsigned char *bmp,
1292 Display *display = FRAME_DISPLAY (frame);
1294 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1297 gc = set_region (frame, gc, region);
1299 for (i = 0; i < height; i++, bmp += row_bytes)
1300 for (j = 0; j < width; j++)
1301 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1302 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1307 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1308 int intensity, MDrawPoint *points, int num,
1311 GCInfo *info = rface->info;
1314 if (! (gc = info->gc[intensity]))
1315 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1318 gc = set_region (frame, gc, region);
1320 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1321 (XPoint *) points, num, CoordModeOrigin);
1326 mwin__region_from_rect (MDrawMetric *rect)
1328 MDrawRegion region1 = XCreateRegion ();
1329 MDrawRegion region2 = XCreateRegion ();
1334 xrect.width = rect->width;
1335 xrect.height = rect->height;
1336 XUnionRectWithRegion (&xrect, region1, region2);
1337 XDestroyRegion (region1);
1342 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1344 MDrawRegion region1 = XCreateRegion ();
1349 xrect.width = rect->width;
1350 xrect.height = rect->height;
1352 XUnionRegion (region, region, region1);
1353 XUnionRectWithRegion (&xrect, region1, region);
1354 XDestroyRegion (region1);
1358 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1360 MDrawRegion region = XCreateRegion ();
1362 XUnionRegion (region1, region1, region);
1363 XIntersectRegion (region, region2, region1);
1364 XDestroyRegion (region);
1368 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1370 MDrawRegion region1 = XCreateRegion ();
1375 xrect.width = rect->width;
1376 xrect.height = rect->height;
1377 XUnionRectWithRegion (&xrect, region1, region);
1378 XDestroyRegion (region1);
1382 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1386 XClipBox (region, &xrect);
1389 rect->width = xrect.width;
1390 rect->height = xrect.height;
1394 mwin__free_region (MDrawRegion region)
1396 XDestroyRegion (region);
1400 mwin__dump_region (MDrawRegion region)
1403 XClipBox (region, &rect);
1404 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1409 mwin__create_window (MFrame *frame, MDrawWindow parent)
1411 Display *display = FRAME_DISPLAY (frame);
1413 XWMHints wm_hints = { InputHint, False };
1414 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1415 XSetWindowAttributes set_attrs;
1418 GCInfo *info = frame->rface->info;
1421 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1422 mask = GCForeground;
1423 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1424 set_attrs.background_pixel = values.foreground;
1425 set_attrs.backing_store = Always;
1426 set_attrs.override_redirect = True;
1427 set_attrs.save_under = True;
1428 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1429 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1430 CopyFromParent, InputOutput, CopyFromParent,
1432 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1433 NULL, &wm_hints, &class_hints);
1434 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1435 return (MDrawWindow) win;
1439 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1441 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1446 mwin__event_window (void *event)
1448 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1452 mwin__print_event (void *arg, char *win_name)
1455 XEvent *event = (XEvent *) arg;
1457 switch (event->xany.type)
1459 case 2: event_name = "KeyPress"; break;
1460 case 3: event_name = "KeyRelease"; break;
1461 case 4: event_name = "ButtonPress"; break;
1462 case 5: event_name = "ButtonRelease"; break;
1463 case 6: event_name = "MotionNotify"; break;
1464 case 7: event_name = "EnterNotify"; break;
1465 case 8: event_name = "LeaveNotify"; break;
1466 case 9: event_name = "FocusIn"; break;
1467 case 10: event_name = "FocusOut"; break;
1468 case 11: event_name = "KeymapNotify"; break;
1469 case 12: event_name = "Expose"; break;
1470 case 13: event_name = "GraphicsExpose"; break;
1471 case 14: event_name = "NoExpose"; break;
1472 case 15: event_name = "VisibilityNotify"; break;
1473 case 16: event_name = "CreateNotify"; break;
1474 case 17: event_name = "DestroyNotify"; break;
1475 case 18: event_name = "UnmapNotify"; break;
1476 case 19: event_name = "MapNotify"; break;
1477 case 20: event_name = "MapRequest"; break;
1478 case 21: event_name = "ReparentNotify"; break;
1479 case 22: event_name = "ConfigureNotify"; break;
1480 case 23: event_name = "ConfigureRequest"; break;
1481 case 24: event_name = "GravityNotify"; break;
1482 case 25: event_name = "ResizeRequest"; break;
1483 case 26: event_name = "CirculateNotify"; break;
1484 case 27: event_name = "CirculateRequest"; break;
1485 case 28: event_name = "PropertyNotify"; break;
1486 case 29: event_name = "SelectionClear"; break;
1487 case 30: event_name = "SelectionRequest"; break;
1488 case 31: event_name = "SelectionNotify"; break;
1489 case 32: event_name = "ColormapNotify"; break;
1490 case 33: event_name = "ClientMessage"; break;
1491 case 34: event_name = "MappingNotify"; break;
1492 default: event_name = "unknown";
1495 fprintf (stderr, "%s: %s\n", win_name, event_name);
1500 mwin__map_window (MFrame *frame, MDrawWindow win)
1502 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1506 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1508 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1512 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1513 MDrawMetric *geometry)
1515 Display *display = FRAME_DISPLAY (frame);
1516 XWindowAttributes attr;
1517 Window parent = (Window) parent_win, root;
1519 XGetWindowAttributes (display, (Window) win, &attr);
1520 geometry->x = attr.x + attr.border_width;
1521 geometry->y = attr.y + attr.border_width;
1522 geometry->width = attr.width;
1523 geometry->height = attr.height;
1526 parent = RootWindow (display, FRAME_SCREEN (frame));
1529 Window this_parent, *children;
1532 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1535 if (this_parent == parent || this_parent == root)
1537 win = (MDrawWindow) this_parent;
1538 XGetWindowAttributes (display, (Window) win, &attr);
1539 geometry->x += attr.x + attr.border_width;
1540 geometry->y += attr.y + attr.border_width;
1545 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1546 MDrawMetric *current, MDrawMetric *new)
1548 Display *display = FRAME_DISPLAY (frame);
1549 unsigned int mask = 0;
1550 XWindowChanges values;
1552 if (current->width != new->width)
1555 if (new->width <= 0)
1557 values.width = current->width = new->width;
1559 if (current->height != new->height)
1562 if (new->height <= 0)
1564 values.height = current->height = new->height;
1566 if (current->x != new->x)
1569 values.x = current->x = new->x;
1571 if (current->y != new->y)
1574 current->y = new->y;
1575 values.y = current->y = new->y;
1578 XConfigureWindow (display, (Window) win, mask, &values);
1579 XClearWindow (display, (Window) win);
1583 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1585 XEvent *event = (XEvent *) arg;
1586 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1593 if (event->xany.type != KeyPress
1594 /* && event->xany.type != KeyRelease */
1597 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1604 if (c < XK_space || c > XK_asciitilde)
1606 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1607 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1608 if (((XKeyEvent *) event)->state & ControlMask)
1610 if (c >= 'a' && c <= 'z')
1612 if (c >= ' ' && c < 127)
1613 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1615 key = minput__char_to_key (c);
1617 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1621 char *str = XKeysymToString (keysym);
1625 key = msymbol (str);
1626 if (((XKeyEvent *) event)->state & ShiftMask)
1627 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1628 if (((XKeyEvent *) event)->state & ControlMask)
1629 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1631 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1632 *modifiers |= MINPUT_KEY_META_MODIFIER;
1633 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1634 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1635 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1636 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1637 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1638 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1645 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1647 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1649 Display *display = FRAME_DISPLAY (frame);
1650 GCInfo *info = rface->info;
1653 for (i = 0; i <= GC_INVERSE; i++)
1655 XGetGCValues (display, info->gc[i], valuemask, &values);
1656 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1657 values.foreground, values.background);
1658 fprintf (stderr, "\n");
1662 static MDeviceDriver x_driver =
1665 mwin__device_get_prop,
1667 mwin__free_realized_face,
1669 mwin__draw_empty_boxes,
1673 mwin__region_from_rect,
1674 mwin__union_rect_with_region,
1675 mwin__intersect_region,
1676 mwin__region_add_rect,
1677 mwin__region_to_rect,
1680 mwin__create_window,
1681 mwin__destroy_window,
1684 mwin__window_geometry,
1685 mwin__adjust_window,
1689 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1694 M_iso8859_1 = msymbol ("iso8859-1");
1695 M_iso10646_1 = msymbol ("iso10646-1");
1697 display_info_list = mplist ();
1698 device_list = mplist ();
1701 xft_driver.select = mfont__ft_driver.select;
1702 xft_driver.encode_char = mfont__ft_driver.encode_char;
1705 Mxim = msymbol ("xim");
1706 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1714 M17N_OBJECT_UNREF (display_info_list);
1715 M17N_OBJECT_UNREF (device_list);
1719 /** Return an MWDevice object corresponding to a display specified in
1722 It searches device_list for a device matching the display. If
1723 found, return the found object. Otherwise, return a newly created
1727 device_open (MFrame *frame, MPlist *param)
1729 Display *display = NULL;
1730 Screen *screen = NULL;
1732 Drawable drawable = 0;
1733 Widget widget = NULL;
1735 int auto_display = 0;
1736 MDisplayInfo *disp_info = NULL;
1737 MWDevice *device = NULL;
1739 XWindowAttributes attr;
1745 for (plist = param; (key = mplist_key (plist)) != Mnil;
1746 plist = mplist_next (plist))
1748 if (key == Mdisplay)
1749 display = (Display *) mplist_value (plist);
1750 else if (key == Mscreen)
1751 screen = mplist_value (plist);
1752 else if (key == Mdrawable)
1753 drawable = (Drawable) mplist_value (plist);
1754 else if (key == Mdepth)
1755 depth = (unsigned) mplist_value (plist);
1756 else if (key == Mwidget)
1757 widget = (Widget) mplist_value (plist);
1758 else if (key == Mcolormap)
1759 cmap = (Colormap) mplist_value (plist);
1764 display = XtDisplay (widget);
1765 screen_num = XScreenNumberOfScreen (XtScreen (widget));
1766 depth = DefaultDepth (display, screen_num);
1772 unsigned width, height, border_width;
1775 MERROR (MERROR_WIN, -1);
1776 XGetGeometry (display, drawable, &root_window,
1777 &x, &y, &width, &height, &border_width, &depth);
1778 XGetWindowAttributes (display, root_window, &attr);
1779 screen_num = XScreenNumberOfScreen (attr.screen);
1784 display = DisplayOfScreen (screen);
1789 display = XOpenDisplay (NULL);
1791 MERROR (MERROR_WIN, -1);
1794 screen = DefaultScreenOfDisplay (display);
1796 screen_num = XScreenNumberOfScreen (screen);
1798 depth = DefaultDepth (display, screen_num);
1802 cmap = DefaultColormap (display, screen_num);
1804 for (plist = display_info_list; mplist_key (plist) != Mnil;
1805 plist = mplist_next (plist))
1807 disp_info = (MDisplayInfo *) mplist_value (plist);
1808 if (disp_info->display == display)
1812 if (mplist_key (plist) != Mnil)
1813 M17N_OBJECT_REF (disp_info);
1816 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
1817 disp_info->display = display;
1818 disp_info->auto_display = auto_display;
1819 disp_info->font_registry_list = mplist ();
1820 disp_info->iso8859_1_family_list = mplist ();
1821 disp_info->iso10646_1_family_list = mplist ();
1822 disp_info->realized_font_list = mplist ();
1823 find_modifier_bits (disp_info);
1824 mplist_add (display_info_list, Mt, disp_info);
1827 for (plist = device_list; mplist_key (plist) != Mnil;
1828 plist = mplist_next (plist))
1830 device = (MWDevice *) mplist_value (plist);
1831 if (device->display_info == disp_info
1832 && device->depth == depth
1833 && device->cmap == cmap)
1837 if (mplist_key (plist) != Mnil)
1838 M17N_OBJECT_REF (device);
1841 unsigned long valuemask = GCForeground;
1844 M17N_OBJECT (device, free_device, MERROR_WIN);
1845 device->display_info = disp_info;
1846 device->screen_num = screen_num;
1847 /* A drawable on which to create GCs. */
1848 device->drawable = XCreatePixmap (display,
1849 RootWindow (display, screen_num),
1851 device->depth = depth;
1852 device->cmap = cmap;
1853 device->realized_face_list = mplist ();
1854 device->realized_fontset_list = mplist ();
1855 device->gc_list = mplist ();
1856 values.foreground = BlackPixel (display, screen_num);
1857 device->scratch_gc = XCreateGC (display, device->drawable,
1858 valuemask, &values);
1860 device->xft_draw = XftDrawCreate (display, device->drawable,
1861 DefaultVisual (display, screen_num),
1866 frame->device = device;
1867 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
1868 frame->driver = &x_driver;
1869 frame->font_driver_list = mplist ();
1870 mplist_add (frame->font_driver_list, Mx, &xfont_driver);
1872 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
1874 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
1876 frame->realized_font_list = disp_info->realized_font_list;
1877 frame->realized_face_list = device->realized_face_list;
1878 frame->realized_fontset_list = device->realized_fontset_list;
1882 XtResource resources[] = {
1883 { XtNfont, XtCFont, XtRString, sizeof (String),
1884 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
1885 { XtNforeground, XtCForeground, XtRString, sizeof (String),
1886 XtOffset (AppDataPtr, foreground), XtRString, "black" },
1887 { XtNbackground, XtCBackground, XtRString, sizeof (String),
1888 XtOffset (AppDataPtr, background), XtRString, "white" },
1889 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
1890 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
1893 XtGetApplicationResources (widget, &app_data,
1894 resources, XtNumber (resources), NULL, 0);
1895 frame->foreground = msymbol (app_data.foreground);
1896 frame->background = msymbol (app_data.background);
1897 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
1901 app_data.font = DEFAULT_FONT;
1902 frame->foreground = msymbol ("black");
1903 frame->background = msymbol ("white");
1904 frame->videomode = Mnormal;
1909 char **names = XListFonts (display, app_data.font, 1, &nfonts);
1913 if (! (frame->font = mfont_parse_name (names[0], Mx)))
1915 /* The font name does not conform to XLFD. Try to open the
1916 font and get XA_FONT property. */
1917 XFontStruct *xfont = XLoadQueryFont (display, names[0]);
1922 unsigned long value;
1925 if (XGetFontProperty (xfont, XA_FONT, &value)
1926 && (name = ((char *)
1927 XGetAtomName (display, (Atom) value))))
1929 if ((frame->font = mfont_parse_name (name, Mx)))
1932 XFreeFont (display, xfont);
1935 XFreeFontNames (names);
1938 frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
1941 face = mface_from_font (frame->font);
1942 face->property[MFACE_FONTSET] = mfontset (NULL);
1943 face->property[MFACE_FOREGROUND] = frame->foreground;
1944 face->property[MFACE_BACKGROUND] = frame->background;
1945 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
1946 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
1947 face->property[MFACE_VIDEOMODE] = frame->videomode;
1948 mface_put_prop (face, Mhook_func,
1949 mface_get_prop (mface__default, Mhook_func));
1950 face->property[MFACE_RATIO] = (void *) 100;
1951 mplist_push (param, Mface, face);
1952 M17N_OBJECT_UNREF (face);
1954 #ifdef X_SET_ERROR_HANDLER
1955 XSetErrorHandler (x_error_handler);
1956 XSetIOErrorHandler (x_io_error_handler);
1964 /* XIM (X Input Method) handler */
1966 typedef struct MInputXIMMethodInfo
1972 } MInputXIMMethodInfo;
1974 typedef struct MInputXIMContextInfo
1978 MConverter *converter;
1979 } MInputXIMContextInfo;
1982 xim_open_im (MInputMethod *im)
1984 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
1985 MLocale *saved, *this;
1986 char *save_modifier_list;
1988 MInputXIMMethodInfo *im_info;
1990 saved = mlocale_set (LC_CTYPE, NULL);
1991 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
1993 /* The specified locale is not supported. */
1994 MERROR (MERROR_LOCALE, -1);
1995 if (mlocale_get_prop (this, Mcoding) == Mnil)
1997 /* Unable to decode the output of XIM. */
1998 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
1999 MERROR (MERROR_LOCALE, -1);
2002 if (arg->modifier_list)
2003 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2005 save_modifier_list = XSetLocaleModifiers ("");
2006 if (! save_modifier_list)
2008 /* The specified locale is not supported by X. */
2009 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2010 MERROR (MERROR_LOCALE, -1);
2013 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2016 /* No input method is available in the current locale. */
2017 XSetLocaleModifiers (save_modifier_list);
2018 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2019 MERROR (MERROR_WIN, -1);
2022 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2023 im_info->display = arg->display;
2025 im_info->language = mlocale_get_prop (this, Mlanguage);
2026 im_info->coding = mlocale_get_prop (this, Mcoding);
2029 XSetLocaleModifiers (save_modifier_list);
2030 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2036 xim_close_im (MInputMethod *im)
2038 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2040 XCloseIM (im_info->xim);
2045 xim_create_ic (MInputContext *ic)
2047 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2048 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2049 MInputXIMContextInfo *ic_info;
2052 if (! arg->input_style)
2054 /* By default, use Root style. */
2055 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2056 arg->preedit_attrs = NULL;
2057 arg->status_attrs = NULL;
2060 if (! arg->preedit_attrs && ! arg->status_attrs)
2061 xic = XCreateIC (im_info->xim,
2062 XNInputStyle, arg->input_style,
2063 XNClientWindow, arg->client_win,
2064 XNFocusWindow, arg->focus_win,
2066 else 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,
2071 XNPreeditAttributes, arg->preedit_attrs,
2073 else if (! arg->preedit_attrs && arg->status_attrs)
2074 xic = XCreateIC (im_info->xim,
2075 XNInputStyle, arg->input_style,
2076 XNClientWindow, arg->client_win,
2077 XNFocusWindow, arg->focus_win,
2078 XNStatusAttributes, arg->status_attrs,
2081 xic = XCreateIC (im_info->xim,
2082 XNInputStyle, arg->input_style,
2083 XNClientWindow, arg->client_win,
2084 XNFocusWindow, arg->focus_win,
2085 XNPreeditAttributes, arg->preedit_attrs,
2086 XNStatusAttributes, arg->status_attrs,
2089 MERROR (MERROR_WIN, -1);
2091 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2093 ic_info->win = arg->focus_win;
2094 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2100 xim_destroy_ic (MInputContext *ic)
2102 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2104 XDestroyIC (ic_info->xic);
2105 mconv_free_converter (ic_info->converter);
2111 xim_filter (MInputContext *ic, MSymbol key, void *event)
2113 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2115 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2120 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2122 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2123 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2124 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2130 buf = (char *) alloca (512);
2131 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2132 if (status == XBufferOverflow)
2134 buf = (char *) alloca (len);
2135 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2138 mtext_reset (ic->produced);
2142 mconv_reset_converter (ic_info->converter);
2143 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2144 mconv_decode (ic_info->converter, ic->produced);
2145 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2146 Mlanguage, (void *) im_info->language);
2147 mtext_cpy (mt, ic->produced);
2148 mtext_reset (ic->produced);
2154 #ifdef X_SET_ERROR_HANDLER
2156 x_error_handler (Display *display, XErrorEvent *error)
2163 x_io_error_handler (Display *display)
2173 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2177 /*** @addtogroup m17nInputMethodWin */
2182 @brief Input method driver for XIM.
2184 The driver #minput_xim_driver is for the foreign input method of
2185 name #Mxim. It uses XIM (X Input Methods) as a background input
2188 As the symbol #Mxim has property #Minput_driver whose value is
2189 a pointer to this driver, the input method of language #Mnil
2190 and name #Mxim uses this driver.
2192 Therefore, for such input methods, the driver dependent arguments
2193 to the functions whose name begin with minput_ must be as follows.
2195 The argument $ARG of the function minput_open_im () must be a
2196 pointer to the structure #MInputXIMArgIM. See the documentation
2197 of #MInputXIMArgIM for more details.
2199 The argument $ARG of the function minput_create_ic () must be a
2200 pointer to the structure #MInputXIMArgIC. See the documentation
2201 of #MInputXIMArgIC for more details.
2203 The argument $ARG of the function minput_filter () must be a
2204 pointer to the structure @c XEvent. The argument $KEY is ignored.
2206 The argument $ARG of the function minput_lookup () must be the
2207 same one as that of the function minput_filter (). The argument
2211 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2213 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
2214 ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
2217 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2218 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
2219 ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2221 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
2222 ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2224 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM ¤Ø¤Î¥Ý
2225 ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
2228 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC ¤Ø¤Î
2229 ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
2232 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2233 ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2235 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2236 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2239 MInputDriver minput_xim_driver =
2240 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2241 xim_filter, xim_lookup, NULL };