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_DISPLAY(frame) ((frame)->device->display_info->display)
161 #define FRAME_SCREEN(frame) ((frame)->device->screen_num)
162 #define FRAME_CMAP(frame) ((frame)->device->cmap)
163 #define FRAME_VISUAL(frame) DefaultVisual (FRAME_DISPLAY (frame), \
164 FRAME_SCREEN (frame))
166 #define DEFAULT_FONT "-misc-fixed-medium-r-normal--*-120-*-*-*-*-iso8859-1"
167 #define FALLBACK_FONT "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1"
174 Boolean reverse_video;
175 } AppData, *AppDataPtr;
178 free_display_info (void *object)
180 MDisplayInfo *disp_info = (MDisplayInfo *) object;
183 for (plist = disp_info->font_registry_list;
184 mplist_key (plist) != Mnil; plist = mplist_next (plist))
186 MFontList *registry_list = mplist_value (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 for (plist = disp_info->iso8859_1_family_list;
195 mplist_key (plist) != Mnil; plist = mplist_next (plist))
197 MFontList *family_list = mplist_value (plist);
199 if (family_list->fonts)
200 free (family_list->fonts);
203 M17N_OBJECT_UNREF (disp_info->iso8859_1_family_list);
205 for (plist = disp_info->iso10646_1_family_list;
206 mplist_key (plist) != Mnil; plist = mplist_next (plist))
208 MFontList *family_list = mplist_value (plist);
210 if (family_list->fonts)
211 free (family_list->fonts);
214 M17N_OBJECT_UNREF (disp_info->iso10646_1_family_list);
216 for (plist = disp_info->realized_font_list;
217 mplist_key (plist) != Mnil; plist = mplist_next (plist))
218 mfont__free_realized ((MRealizedFont *) mplist_value (plist));
219 M17N_OBJECT_UNREF (disp_info->realized_font_list);
221 if (disp_info->auto_display)
222 XCloseDisplay (disp_info->display);
228 free_device (void *object)
230 MWDevice *device = (MWDevice *) object;
233 for (plist = device->realized_fontset_list;
234 mplist_key (plist) != Mnil; plist = mplist_next (plist))
235 mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist));
236 M17N_OBJECT_UNREF (device->realized_fontset_list);
238 for (plist = device->realized_face_list;
239 mplist_key (plist) != Mnil; plist = mplist_next (plist))
240 mface__free_realized ((MRealizedFace *) mplist_value (plist));
241 M17N_OBJECT_UNREF (device->realized_face_list);
243 MPLIST_DO (plist, device->gc_list)
245 XFreeGC (device->display_info->display,
246 ((RGB_GC *) MPLIST_VAL (plist))->gc);
247 free (MPLIST_VAL (plist));
249 M17N_OBJECT_UNREF (device->gc_list);
250 XFreeGC (device->display_info->display, device->scratch_gc);
253 XftDrawDestroy (device->xft_draw);
256 XFreePixmap (device->display_info->display, device->drawable);
257 M17N_OBJECT_UNREF (device->display_info);
263 find_modifier_bits (MDisplayInfo *disp_info)
265 Display *display = disp_info->display;
266 XModifierKeymap *mods;
267 KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L);
268 KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R);
269 KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L);
270 KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R);
271 KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
272 KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
273 KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
274 KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
277 mods = XGetModifierMapping (display);
278 /* We skip the first three sets for Shift, Lock, and Control. The
279 remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
280 for (i = 3; i < 8; i++)
281 for (j = 0; j < mods->max_keypermod; j++)
283 KeyCode code = mods->modifiermap[i * mods->max_keypermod + j];
287 if (code == meta_l || code == meta_r)
288 disp_info->meta_mask |= (1 << i);
289 else if (code == alt_l || code == alt_r)
290 disp_info->alt_mask |= (1 << i);
291 else if (code == super_l || code == super_r)
292 disp_info->super_mask |= (1 << i);
293 else if (code == hyper_l || code == hyper_r)
294 disp_info->hyper_mask |= (1 << i);
297 /* If meta keys are not in any modifier, use alt keys as meta
299 if (! disp_info->meta_mask)
301 disp_info->meta_mask = disp_info->alt_mask;
302 disp_info->alt_mask = 0;
304 /* If both meta and alt are assigned to the same modifier, give meta
306 if (disp_info->meta_mask & disp_info->alt_mask)
307 disp_info->alt_mask &= ~disp_info->meta_mask;
309 XFreeModifiermap (mods);
313 get_rgb_gc (MWDevice *device, XColor *xcolor)
315 int rgb = (((xcolor->red >> 8) << 16) | ((xcolor->green >> 8) << 8)
316 | (xcolor->blue >> 8));
319 unsigned long valuemask = GCForeground;
322 MPLIST_DO (plist, device->gc_list)
324 rgb_gc = MPLIST_VAL (plist);
326 if (rgb_gc->rgb == rgb)
328 if (rgb_gc->rgb > rgb)
332 if (! XAllocColor (device->display_info->display, device->cmap, xcolor))
335 rgb_gc = malloc (sizeof (RGB_GC));
337 values.foreground = xcolor->pixel;
338 rgb_gc->gc = XCreateGC (device->display_info->display,
339 device->drawable, valuemask, &values);
340 mplist_push (plist, Mt, rgb_gc);
345 get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret)
347 MWDevice *device = frame->device;
355 color = for_foreground ? frame->foreground : frame->background;
357 if (! XParseColor (FRAME_DISPLAY (frame), device->cmap,
358 msymbol_name (color), &xcolor))
360 rgb_gc = get_rgb_gc (device, &xcolor);
364 *rgb_ret = rgb_gc->rgb;
369 GCInfo *info = frame->rface->info;
374 rgb = info->rgb_fore, gc = info->gc[GC_NORMAL];
376 rgb = info->rgb_back, gc = info->gc[GC_INVERSE];
384 get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity)
386 int rgb_fore, rgb_back;
391 if (info->gc[intensity])
392 return info->gc[intensity];
394 rgb_fore = info->rgb_fore, rgb_back = info->rgb_back;
395 xcolor.red = ((((rgb_fore & 0xFF0000) >> 16) * intensity
396 + ((rgb_back & 0xFF0000) >> 16) * (7 - intensity)) / 7) << 8;
397 xcolor.green = ((((rgb_fore & 0xFF00) >> 8) * intensity
398 + ((rgb_back & 0xFF00) >> 8) * (7 - intensity)) / 7) << 8;
399 xcolor.blue = (((rgb_fore & 0xFF) * intensity
400 + (rgb_back & 0xFF) * (7 - intensity)) / 7) << 8;
401 rgb_gc = get_rgb_gc (device, &xcolor);
405 gc =get_gc_for_anti_alias (device, info,
406 intensity < 4 ? intensity - 1 : intensity + 1);
407 return (info->gc[intensity] = gc);
411 /** X font handler */
413 /** Indices to each field of split font name. */
435 /** Split the fontname NAME into each XLFD field destructively. Set
436 each element of the table pointed by PROPERTY_IDX to a pointer to
437 the corresponding font property name. Store the point size and
438 the resolution-Y of the font to the place pointed by POINT and
441 If NAME does not contain all XLFD fields, the unspecified fields is
442 treated as wild cards. */
445 split_font_name (char *name, char **field,
446 unsigned short *size, unsigned short *resy)
451 for (i = 0, p = name; *p; p++)
454 if (*p == '-' && i < XLFD_FIELD_MAX)
457 if (i != XLFD_ENCODING)
462 if (i < XLFD_REGISTRY)
464 for (; i < XLFD_FIELD_MAX; i++)
467 if (*(field[XLFD_RESY]) == '*')
470 *resy = atoi (field[XLFD_RESY]);
471 if (*(field[XLFD_PIXEL]) == '*')
473 if (*(field[XLFD_POINT]) != '*')
474 *size = atoi (field[XLFD_POINT]) * *resy / 72;
478 else if (*(field[XLFD_PIXEL]) == '[')
480 /* The pixel size field specifies a transformation matrix of the
481 form "[A B C D]". The XLFD spec says that the scalar value N
482 for the pixel size is equivalent to D. */
483 char *p0 = field[XLFD_PIXEL] + 1, *p1;
486 for (i = 0; i < 4; i++, p0 = p1)
487 d = strtod (p0, &p1);
491 *size = atoi (field[XLFD_PIXEL]) * 10;
492 if (*size == 0 && *(field[XLFD_POINT]) != '*')
494 *size = atoi (field[XLFD_POINT]);
496 *size = *size * *resy / 72;
498 *size = *size * 100 / 72;
505 build_font_name (MFont *font, char *name, int limit)
510 unsigned short size, resy;
512 prop[0] = (MSymbol) mfont_get_prop (font, Mfoundry);
513 prop[1] = (MSymbol) mfont_get_prop (font, Mfamily);
514 prop[2] = (MSymbol) mfont_get_prop (font, Mweight);
515 prop[3] = (MSymbol) mfont_get_prop (font, Mstyle);
516 prop[4] = (MSymbol) mfont_get_prop (font, Mstretch);
517 prop[5] = (MSymbol) mfont_get_prop (font, Madstyle);
518 prop[6] = (MSymbol) mfont_get_prop (font, Mregistry);
519 for (len = 0, i = 0; i < 7; i++)
523 str[i] = msymbol_name (prop[i]);
524 len += strlen (str[i]);
534 + 3 /* 3 asterisks */
535 + 30 /* 3 integers (each 10 digits) */
536 + 1) /* '\0' terminal */
540 size = (int) mfont_get_prop (font, Msize);
544 size = size / 10 + 1;
545 resy = (int) mfont_get_prop (font, Mresolution);
547 sprintf (name, "-%s-%s-%s-%s-%s-%s-%d-*-%d-%d-*-*-%s",
548 str[0], str[1], str[2], str[3], str[4], str[5],
549 size, resy, resy, str[6]);
554 build_font_list (MFrame *frame, MSymbol family, MSymbol registry,
558 MFontList *font_list;
563 MSTRUCT_CALLOC (font_list, MERROR_WIN);
567 sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s",
568 msymbol_name (registry));
569 font_list->tag = registry;
573 sprintf (pattern, "-*-%s-*-*-*-*-*-*-*-*-*-*-%s",
574 msymbol_name (family), msymbol_name (registry));
575 font_list->tag = family;
578 fontnames = XListFonts (FRAME_DISPLAY (frame), pattern, 0x8000, &nfonts);
581 MTABLE_MALLOC (font_list->fonts, nfonts, MERROR_WIN);
582 for (i = j = 0; i < nfonts; i++)
583 if (mwin__parse_font_name (fontnames[i], font_list->fonts + j) >= 0
584 && (font_list->fonts[j].property[MFONT_SIZE] != 0
585 || font_list->fonts[j].property[MFONT_RESY] == 0))
587 XFreeFontNames (fontnames);
588 font_list->nfonts = j;
590 mplist_add (plist, font_list->tag, font_list);
591 return (nfonts > 0 ? font_list : NULL);
595 static MRealizedFont *xfont_select (MFrame *, MFont *, MFont *, int);
596 static int xfont_open (MRealizedFont *);
597 static void xfont_close (MRealizedFont *);
598 static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int);
599 static unsigned xfont_encode_char (MRealizedFont *, int, unsigned);
600 static void xfont_render (MDrawWindow, int, int, MGlyphString *,
601 MGlyph *, MGlyph *, int, MDrawRegion);
603 static MFontDriver xfont_driver =
604 { xfont_select, xfont_open, xfont_close,
605 xfont_find_metric, xfont_encode_char, xfont_render };
607 /* The X font driver function SELECT. */
609 static MRealizedFont *
610 xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
612 MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
613 MRealizedFont *rfont;
614 MFontList *font_list = NULL;
617 int best_score, score;
620 || ! strchr (MSYMBOL_NAME (registry), '-'))
623 /* We handles iso8859-1 and iso10646-1 fonts specially because there
624 exists so many such fonts. */
625 if (registry == M_iso8859_1 || registry == M_iso10646_1)
628 = (registry == M_iso8859_1
629 ? frame->device->display_info->iso8859_1_family_list
630 : frame->device->display_info->iso10646_1_family_list);
631 MSymbol family = FONT_PROPERTY (spec, MFONT_FAMILY);
635 font_list = (MFontList *) mplist_get (family_list, family);
637 font_list = build_font_list (frame, family, registry, family_list);
641 family = FONT_PROPERTY (request, MFONT_FAMILY);
642 font_list = (MFontList *) mplist_get (family_list, family);
644 font_list = build_font_list (frame, family, registry, family_list);
649 MPlist *registry_list
650 = frame->device->display_info->font_registry_list;
652 font_list = (MFontList *) mplist_get (registry_list, registry);
654 font_list = build_font_list (frame, Mnil, registry, registry_list);
659 for (i = 0, best_score = -1, best_font = NULL; i < font_list->nfonts; i++)
660 if ((best_score = mfont__score (font_list->fonts + i, spec, request,
665 best_font = font_list->fonts + i;
666 for (; best_score > 0 && i < font_list->nfonts ; i++)
668 score = mfont__score (font_list->fonts + i, spec, request,
670 if (score >= 0 && score < best_score)
672 best_font = font_list->fonts + i;
677 MSTRUCT_CALLOC (rfont, MERROR_WIN);
678 rfont->frame = frame;
680 rfont->request = *request;
681 rfont->font = *best_font;
682 if (best_font->property[MFONT_SIZE] == 0)
683 rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE];
684 rfont->score = best_score;
685 rfont->driver = &xfont_driver;
697 close_xfont (void *object)
699 MXFontInfo *xfont = (MXFontInfo *) object;
702 XFreeFont (FRAME_DISPLAY (xfont->frame), xfont->f);
707 /* The X font driver function OPEN. */
710 xfont_open (MRealizedFont *rfont)
714 MFrame *frame = rfont->frame;
715 int mdebug_mask = MDEBUG_FONT;
717 /* This never fail to generate a valid fontname because open_spec
718 should correspond to a font available on the system. */
719 build_font_name (&rfont->font, name, 1024);
720 M17N_OBJECT (xfont, close_xfont, MERROR_WIN);
722 xfont->frame = frame;
723 xfont->f = XLoadQueryFont (FRAME_DISPLAY (frame), name);
727 MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
730 MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
732 rfont->ascent = xfont->f->ascent;
733 rfont->descent = xfont->f->descent;
738 /* The X font driver function CLOSE. */
741 xfont_close (MRealizedFont *rfont)
743 M17N_OBJECT_UNREF (rfont->info);
746 /* The X font driver function FIND_METRIC. */
749 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
752 MXFontInfo *xfont = (MXFontInfo *) rfont->info;
753 XFontStruct *f = xfont->f;
754 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
756 for (; g != gend; g++)
758 if (g->code == MCHAR_INVALID_CODE)
760 g->lbearing = f->max_bounds.lbearing;
761 g->rbearing = f->max_bounds.rbearing;
762 g->width = f->max_bounds.width;
763 g->ascent = f->ascent;
764 g->descent = f->descent;
768 int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
769 XCharStruct *pcm = NULL;
771 if (f->per_char != NULL)
773 if (f->min_byte1 == 0 && f->max_byte1 == 0)
776 && byte2 >= f->min_char_or_byte2
777 && byte2 <= f->max_char_or_byte2)
778 pcm = f->per_char + byte2 - f->min_char_or_byte2;
782 if (byte1 >= f->min_byte1
783 && byte1 <= f->max_byte1
784 && byte2 >= f->min_char_or_byte2
785 && byte2 <= f->max_char_or_byte2)
788 + ((f->max_char_or_byte2-f->min_char_or_byte2 + 1)
789 * (byte1 - f->min_byte1))
790 + (byte2 - f->min_char_or_byte2));
797 g->lbearing = pcm->lbearing;
798 g->rbearing = pcm->rbearing;
799 g->width = pcm->width;
800 g->ascent = pcm->ascent;
801 g->descent = pcm->descent;
805 /* If the per_char pointer is null, all glyphs between
806 the first and last character indexes inclusive have
807 the same information, as given by both min_bounds and
810 g->rbearing = f->max_bounds.width;
811 g->width = f->max_bounds.width;
812 g->ascent = f->ascent;
813 g->descent = f->descent;
820 /* The X font driver function ENCODE_CHAR. */
823 xfont_encode_char (MRealizedFont *rfont, int c, unsigned code)
827 unsigned min_byte1, max_byte1, min_byte2, max_byte2;
830 if (rfont->status < 0 || code >= 0x10000)
831 return MCHAR_INVALID_CODE;
832 if (rfont->status == 0)
834 if (xfont_open (rfont) < 0)
835 return MCHAR_INVALID_CODE;
837 xfont = (MXFontInfo *) rfont->info;
839 all_chars_exist = (! f->per_char || f->all_chars_exist == True);
840 min_byte1 = f->min_byte1;
841 max_byte1 = f->max_byte1;
842 min_byte2 = f->min_char_or_byte2;
843 max_byte2 = f->max_char_or_byte2;
845 if (min_byte1 == 0 && max_byte1 == 0)
849 if (code < min_byte2 || code > max_byte2)
850 return MCHAR_INVALID_CODE;
853 pcm = f->per_char + (code - min_byte2);
854 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
855 ? code : MCHAR_INVALID_CODE);
859 unsigned byte1 = code >> 8, byte2 = code & 0xFF;
862 if (byte1 < min_byte1 || byte1 > max_byte1
863 || byte2 < min_byte2 || byte2 > max_byte2)
864 return MCHAR_INVALID_CODE;
868 pcm = f->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
869 + (byte2 - min_byte2));
870 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
871 ? code : MCHAR_INVALID_CODE);
876 set_region (MFrame *frame, GC gc, MDrawRegion region)
878 unsigned long valuemask = GCForeground;
880 XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
881 frame->device->scratch_gc);
882 XSetRegion (FRAME_DISPLAY (frame), frame->device->scratch_gc, region);
883 return frame->device->scratch_gc;
886 /* The X font driver function RENDER. */
889 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
890 MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
892 MRealizedFace *rface = from->rface;
895 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
902 /* It is assured that the all glyphs in the current range use the
903 same realized face. */
904 display = FRAME_DISPLAY (rface->frame);
907 gc = set_region (rface->frame, gc, region);
908 if (! rface->rfont || from->code == MCHAR_INVALID_CODE)
912 for (; from < to; from++)
914 XDrawRectangle (display, (Window) win, gc,
915 x0, y - gstring->ascent + 1, from->width - 1,
916 gstring->ascent + gstring->descent - 2);
922 XSetFont (display, gc, ((MXFontInfo *) (rface->rfont->info))->f->fid);
923 code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
924 for (i = 0, g = from; g < to; i++, g++)
926 code[i].byte1 = g->code >> 8;
927 code[i].byte2 = g->code & 0xFF;
933 if (g->type == GLYPH_PAD)
935 else if (g->type == GLYPH_SPACE)
936 for (; g < to && g->type == GLYPH_SPACE; g++)
938 else if (! g->rface->rfont)
940 if ((g->c >= 0x200B && g->c <= 0x200F)
941 || (g->c >= 0x202A && g->c <= 0x202E))
945 /* As a font is not found for this character, draw an
947 int box_width = g->width;
948 int box_height = gstring->ascent + gstring->descent;
954 XDrawRectangle (display, (Window) win, gc,
955 x, y - gstring->ascent, box_width, box_height);
959 else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
961 XDrawString16 (display, (Window) win, gc,
962 x + g->xoff, y + g->yoff, code + (g - from), 1);
969 int code_idx = g - from;
972 g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
975 XDrawString16 (display, (Window) win, gc, orig_x, y,
993 static MRealizedFont *xft_select (MFrame *, MFont *, MFont *, int);
994 static int xft_open (MRealizedFont *);
995 static void xft_close (MRealizedFont *);
996 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
997 static void xft_render (MDrawWindow, int, int, MGlyphString *,
998 MGlyph *, MGlyph *, int, MDrawRegion);
1000 MFontDriver xft_driver =
1001 { xft_select, xft_open, xft_close,
1003 NULL, /* Set to ft_encode_char in mwin__init (). */
1006 static MRealizedFont *
1007 xft_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
1009 MRealizedFont *rfont;
1011 rfont = (mfont__ft_driver.select) (frame, spec, request, limited_size);
1013 rfont->driver = &xft_driver;
1019 close_xft (void *object)
1021 MXftFontInfo *font_info = object;
1023 if (font_info->font_aa)
1024 XftFontClose (FRAME_DISPLAY (font_info->frame), font_info->font_aa);
1025 if (font_info->font_no_aa)
1026 XftFontClose (FRAME_DISPLAY (font_info->frame), font_info->font_no_aa);
1032 xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
1034 XftPattern *pattern;
1035 XftFontInfo *xft_font_info;
1038 pattern = XftPatternCreate ();
1039 XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
1040 XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
1041 XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
1042 xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
1043 if (! xft_font_info)
1045 font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
1046 XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
1052 xft_open (MRealizedFont *rfont)
1056 MXftFontInfo *font_info;
1059 if ((mfont__ft_driver.open) (rfont) < 0)
1062 size = rfont->font.property[MFONT_SIZE] / 10;
1063 frame = rfont->frame;
1065 ft_info = rfont->info;
1066 M17N_OBJECT (font_info, close_xft, MERROR_WIN);
1067 ft_info->extra_info = font_info;
1068 font_info->frame = frame;
1069 font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
1070 if (font_info->font_aa)
1072 font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
1073 if (font_info->font_no_aa)
1076 M17N_OBJECT_UNREF (font_info);
1077 ft_info->extra_info = NULL;
1084 xft_close (MRealizedFont *rfont)
1086 M17N_OBJECT_UNREF (rfont->info);
1091 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1094 MFTInfo *ft_info = rfont->info;
1095 MXftFontInfo *font_info = ft_info->extra_info;
1096 FT_Face ft_face = ft_info->ft_face;
1097 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1099 for (; g != gend; g++)
1101 if (g->code == MCHAR_INVALID_CODE)
1103 MGlyph *start = g++;
1105 while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
1106 (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
1118 code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
1120 XftGlyphExtents (FRAME_DISPLAY (font_info->frame),
1121 font_info->font_aa, &code, 1, &extents);
1122 g->lbearing = extents.x;
1123 g->rbearing = extents.width - extents.x;
1124 g->width = extents.xOff;
1125 g->ascent = extents.y;
1126 g->descent = extents.height - extents.y;
1133 xft_render (MDrawWindow win, int x, int y,
1134 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1135 int reverse, MDrawRegion region)
1137 MRealizedFace *rface = from->rface;
1138 MFrame *frame = rface->frame;
1139 MFTInfo *ft_info = rface->rfont->info;
1140 MXftFontInfo *font_info = ft_info->extra_info;
1141 FT_Face ft_face = ft_info->ft_face;
1142 XftDraw *xft_draw = frame->device->xft_draw;
1143 XftColor *xft_color = (! reverse
1144 ? &((GCInfo *) rface->info)->xft_color_fore
1145 : &((GCInfo *) rface->info)->xft_color_back);
1146 XftFont *xft_font = (gstring->control.anti_alias && frame->device->depth > 1
1147 ? font_info->font_aa : font_info->font_no_aa);
1156 XftDrawChange (xft_draw, (Drawable) win);
1157 XftDrawSetClip (xft_draw, (Region) region);
1159 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1160 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1167 code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
1168 if (g->xoff == 0 && g->yoff == 0)
1169 glyphs[nglyphs++] = code;
1173 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1174 last_x, y, glyphs, nglyphs);
1176 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1177 x + g->xoff, y + g->yoff, (FT_UInt *) &code, 1);
1178 last_x = x + g->width;
1182 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1189 /* XIM (X Input Method) handler */
1191 typedef struct MInputXIMMethodInfo
1197 } MInputXIMMethodInfo;
1199 typedef struct MInputXIMContextInfo
1203 MConverter *converter;
1204 } MInputXIMContextInfo;
1207 xim_open_im (MInputMethod *im)
1209 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
1210 MLocale *saved, *this;
1211 char *save_modifier_list;
1213 MInputXIMMethodInfo *im_info;
1215 saved = mlocale_set (LC_CTYPE, NULL);
1216 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
1218 /* The specified locale is not supported. */
1219 MERROR (MERROR_LOCALE, -1);
1220 if (mlocale_get_prop (this, Mcoding) == Mnil)
1222 /* Unable to decode the output of XIM. */
1223 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
1224 MERROR (MERROR_LOCALE, -1);
1227 if (arg->modifier_list)
1228 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
1230 save_modifier_list = XSetLocaleModifiers ("");
1231 if (! save_modifier_list)
1233 /* The specified locale is not supported by X. */
1234 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
1235 MERROR (MERROR_LOCALE, -1);
1238 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
1241 /* No input method is available in the current locale. */
1242 XSetLocaleModifiers (save_modifier_list);
1243 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
1244 MERROR (MERROR_WIN, -1);
1247 MSTRUCT_MALLOC (im_info, MERROR_WIN);
1248 im_info->display = arg->display;
1250 im_info->language = mlocale_get_prop (this, Mlanguage);
1251 im_info->coding = mlocale_get_prop (this, Mcoding);
1254 XSetLocaleModifiers (save_modifier_list);
1255 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
1261 xim_close_im (MInputMethod *im)
1263 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
1265 XCloseIM (im_info->xim);
1270 xim_create_ic (MInputContext *ic)
1272 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
1273 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
1274 MInputXIMContextInfo *ic_info;
1277 if (! arg->input_style)
1279 /* By default, use Root style. */
1280 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
1281 arg->preedit_attrs = NULL;
1282 arg->status_attrs = NULL;
1285 if (! arg->preedit_attrs && ! arg->status_attrs)
1286 xic = XCreateIC (im_info->xim,
1287 XNInputStyle, arg->input_style,
1288 XNClientWindow, arg->client_win,
1289 XNFocusWindow, arg->focus_win,
1291 else if (arg->preedit_attrs && ! arg->status_attrs)
1292 xic = XCreateIC (im_info->xim,
1293 XNInputStyle, arg->input_style,
1294 XNClientWindow, arg->client_win,
1295 XNFocusWindow, arg->focus_win,
1296 XNPreeditAttributes, arg->preedit_attrs,
1298 else if (! arg->preedit_attrs && arg->status_attrs)
1299 xic = XCreateIC (im_info->xim,
1300 XNInputStyle, arg->input_style,
1301 XNClientWindow, arg->client_win,
1302 XNFocusWindow, arg->focus_win,
1303 XNStatusAttributes, arg->status_attrs,
1306 xic = XCreateIC (im_info->xim,
1307 XNInputStyle, arg->input_style,
1308 XNClientWindow, arg->client_win,
1309 XNFocusWindow, arg->focus_win,
1310 XNPreeditAttributes, arg->preedit_attrs,
1311 XNStatusAttributes, arg->status_attrs,
1314 MERROR (MERROR_WIN, -1);
1316 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
1318 ic_info->win = arg->focus_win;
1319 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
1325 xim_destroy_ic (MInputContext *ic)
1327 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
1329 XDestroyIC (ic_info->xic);
1330 mconv_free_converter (ic_info->converter);
1336 xim_filter (MInputContext *ic, MSymbol key, void *event)
1338 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
1340 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
1345 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
1347 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
1348 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
1349 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
1355 buf = (char *) alloca (512);
1356 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
1357 if (status == XBufferOverflow)
1359 buf = (char *) alloca (len);
1360 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
1363 mtext_reset (ic->produced);
1367 mconv_reset_converter (ic_info->converter);
1368 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
1369 mconv_decode (ic_info->converter, ic->produced);
1370 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
1371 Mlanguage, (void *) im_info->language);
1372 mtext_cpy (mt, ic->produced);
1373 mtext_reset (ic->produced);
1379 #ifdef X_SET_ERROR_HANDLER
1381 x_error_handler (Display *display, XErrorEvent *error)
1388 x_io_error_handler (Display *display)
1400 Mdisplay = msymbol ("display");
1401 Mscreen = msymbol ("screen");
1402 Mdrawable = msymbol ("drawable");
1403 Mdepth = msymbol ("depth");
1404 Mwidget = msymbol ("widget");
1405 M_iso8859_1 = msymbol ("iso8859-1");
1406 M_iso10646_1 = msymbol ("iso10646-1");
1408 display_info_list = mplist ();
1409 device_list = mplist ();
1411 mplist_add (mfont__driver_list, msymbol ("x"), &xfont_driver);
1413 xft_driver.encode_char = mfont__ft_driver.encode_char;
1414 mplist_put (mfont__driver_list, msymbol ("freetype"), &xft_driver);
1417 Mxim = msymbol ("xim");
1418 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1426 M17N_OBJECT_UNREF (display_info_list);
1427 M17N_OBJECT_UNREF (device_list);
1431 mwin__parse_font_name (char *name, MFont *font)
1433 char *field[XLFD_FIELD_MAX];
1434 unsigned short size, resy;
1435 MSymbol attrs[MFONT_PROPERTY_MAX];
1436 char *copy = (char *) alloca (512);
1438 char *p, *last = NULL;
1440 len = strlen (name) + 1;
1441 for (i = 0, p = name; *p; p++)
1445 else if (p > name && *p == '*' && p[-1] == '-')
1449 memcpy (copy, name, len);
1452 memcpy (copy, name, last - name);
1454 strcat (copy, "-*");
1455 strcat (copy, last);
1458 if (split_font_name (copy, field, &size, &resy) < 0)
1460 attrs[MFONT_FOUNDRY]
1461 = *(field[XLFD_FOUNDRY]) != '*' ? msymbol (field[XLFD_FOUNDRY]) : Mnil;
1463 = *(field[XLFD_FAMILY]) != '*' ? msymbol (field[XLFD_FAMILY]) : Mnil;
1465 = *(field[XLFD_WEIGHT]) != '*' ? msymbol (field[XLFD_WEIGHT]) : Mnil;
1467 = *(field[XLFD_SLANT]) != '*' ? msymbol (field[XLFD_SLANT]) : Mnil;
1468 attrs[MFONT_STRETCH]
1469 = *(field[XLFD_SWIDTH]) != '*' ? msymbol (field[XLFD_SWIDTH]) : Mnil;
1470 attrs[MFONT_ADSTYLE]
1471 = *(field[XLFD_ADSTYLE]) != '*' ? msymbol (field[XLFD_ADSTYLE]) : Mnil;
1472 attrs[MFONT_REGISTRY]
1473 = *(field[XLFD_REGISTRY]) != '*' ? msymbol (field[XLFD_REGISTRY]) : Mnil;
1474 mfont__set_spec (font, attrs, size, resy);
1480 mwin__build_font_name (MFont *font)
1484 if (build_font_name (font, name, 1024) < 0)
1486 return strdup (name);
1489 /** Return an MWDevice object corresponding to a display specified in
1492 It searches device_list for a device matching the display. If
1493 found, return the found object. Otherwise, return a newly created
1497 mwin__open_device (MFrame *frame, MPlist *param)
1499 Display *display = NULL;
1500 Screen *screen = NULL;
1502 Drawable drawable = 0;
1503 Widget widget = NULL;
1505 int auto_display = 0;
1506 MDisplayInfo *disp_info = NULL;
1507 MWDevice *device = NULL;
1509 XWindowAttributes attr;
1515 for (plist = param; (key = mplist_key (plist)) != Mnil;
1516 plist = mplist_next (plist))
1518 if (key == Mdisplay)
1519 display = (Display *) mplist_value (plist);
1520 else if (key == Mscreen)
1521 screen = mplist_value (plist);
1522 else if (key == Mdrawable)
1523 drawable = (Drawable) mplist_value (plist);
1524 else if (key == Mdepth)
1525 depth = (unsigned) mplist_value (plist);
1526 else if (key == Mwidget)
1527 widget = (Widget) mplist_value (plist);
1528 else if (key == Mcolormap)
1529 cmap = (Colormap) mplist_value (plist);
1534 display = XtDisplay (widget);
1535 screen_num = XScreenNumberOfScreen (XtScreen (widget));
1536 depth = DefaultDepth (display, screen_num);
1542 unsigned width, height, border_width;
1545 MERROR (MERROR_WIN, NULL);
1546 XGetGeometry (display, drawable, &root_window,
1547 &x, &y, &width, &height, &border_width, &depth);
1548 XGetWindowAttributes (display, root_window, &attr);
1549 screen_num = XScreenNumberOfScreen (attr.screen);
1554 display = DisplayOfScreen (screen);
1559 display = XOpenDisplay (NULL);
1561 MERROR (MERROR_WIN, NULL);
1564 screen = DefaultScreenOfDisplay (display);
1566 screen_num = XScreenNumberOfScreen (screen);
1568 depth = DefaultDepth (display, screen_num);
1572 cmap = DefaultColormap (display, screen_num);
1574 for (plist = display_info_list; mplist_key (plist) != Mnil;
1575 plist = mplist_next (plist))
1577 disp_info = (MDisplayInfo *) mplist_value (plist);
1578 if (disp_info->display == display)
1582 if (mplist_key (plist) != Mnil)
1583 M17N_OBJECT_REF (disp_info);
1586 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
1587 disp_info->display = display;
1588 disp_info->auto_display = auto_display;
1589 disp_info->font_registry_list = mplist ();
1590 disp_info->iso8859_1_family_list = mplist ();
1591 disp_info->iso10646_1_family_list = mplist ();
1592 disp_info->realized_font_list = mplist ();
1593 find_modifier_bits (disp_info);
1594 mplist_add (display_info_list, Mt, disp_info);
1597 for (plist = device_list; mplist_key (plist) != Mnil;
1598 plist = mplist_next (plist))
1600 device = (MWDevice *) mplist_value (plist);
1601 if (device->display_info == disp_info
1602 && device->depth == depth
1603 && device->cmap == cmap)
1607 if (mplist_key (plist) != Mnil)
1608 M17N_OBJECT_REF (device);
1611 unsigned long valuemask = GCForeground;
1614 M17N_OBJECT (device, free_device, MERROR_WIN);
1615 device->display_info = disp_info;
1616 device->screen_num = screen_num;
1617 /* A drawable on which to create GCs. */
1618 device->drawable = XCreatePixmap (display,
1619 RootWindow (display, screen_num),
1621 device->depth = depth;
1622 device->cmap = cmap;
1623 device->realized_face_list = mplist ();
1624 device->realized_fontset_list = mplist ();
1625 device->gc_list = mplist ();
1626 values.foreground = BlackPixel (display, screen_num);
1627 device->scratch_gc = XCreateGC (display, device->drawable,
1628 valuemask, &values);
1630 device->xft_draw = XftDrawCreate (display, device->drawable,
1631 DefaultVisual (display, screen_num),
1636 frame->realized_font_list = disp_info->realized_font_list;
1637 frame->realized_face_list = device->realized_face_list;
1638 frame->realized_fontset_list = device->realized_fontset_list;
1642 XtResource resources[] = {
1643 { XtNfont, XtCFont, XtRString, sizeof (String),
1644 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
1645 { XtNforeground, XtCForeground, XtRString, sizeof (String),
1646 XtOffset (AppDataPtr, foreground), XtRString, "black" },
1647 { XtNbackground, XtCBackground, XtRString, sizeof (String),
1648 XtOffset (AppDataPtr, background), XtRString, "white" },
1649 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
1650 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
1653 XtGetApplicationResources (widget, &app_data,
1654 resources, XtNumber (resources), NULL, 0);
1655 frame->foreground = msymbol (app_data.foreground);
1656 frame->background = msymbol (app_data.background);
1657 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
1661 app_data.font = DEFAULT_FONT;
1662 frame->foreground = msymbol ("black");
1663 frame->background = msymbol ("white");
1664 frame->videomode = Mnormal;
1667 frame->font = mfont ();
1670 char **names = XListFonts (display, app_data.font, 1, &nfonts);
1674 if (mwin__parse_font_name (names[0], frame->font) < 0)
1676 /* The font name does not conform to XLFD. Try to open the
1677 font and get XA_FONT property. */
1678 XFontStruct *xfont = XLoadQueryFont (display, names[0]);
1683 unsigned long value;
1686 if (XGetFontProperty (xfont, XA_FONT, &value)
1687 && (name = ((char *)
1688 XGetAtomName (display, (Atom) value))))
1690 if (mwin__parse_font_name (name, frame->font) >= 0)
1693 XFreeFont (display, xfont);
1696 XFreeFontNames (names);
1699 mwin__parse_font_name (FALLBACK_FONT, frame->font);
1702 face = mface_from_font (frame->font);
1703 face->property[MFACE_FONTSET] = mfontset (NULL);
1704 face->property[MFACE_FOREGROUND] = frame->foreground;
1705 face->property[MFACE_BACKGROUND] = frame->background;
1706 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
1707 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
1708 face->property[MFACE_VIDEOMODE] = frame->videomode;
1709 mface_put_prop (face, Mhook_func,
1710 mface_get_prop (mface__default, Mhook_func));
1711 face->property[MFACE_RATIO] = (void *) 100;
1712 mplist_push (param, Mface, face);
1713 M17N_OBJECT_UNREF (face);
1715 #ifdef X_SET_ERROR_HANDLER
1716 XSetErrorHandler (x_error_handler);
1717 XSetIOErrorHandler (x_io_error_handler);
1724 mwin__close_device (MFrame *frame)
1726 M17N_OBJECT_UNREF (frame->device);
1730 mwin__device_get_prop (MWDevice *device, MSymbol key)
1732 if (key == Mdisplay)
1733 return (void *) device->display_info->display;
1735 return (void *) ScreenOfDisplay(device->display_info->display,
1736 device->screen_num);
1737 if (key == Mcolormap)
1738 return (void *) device->cmap;
1740 return (void *) device->depth;
1745 mwin__realize_face (MRealizedFace *rface)
1748 MSymbol foreground, background, videomode;
1749 MFaceHLineProp *hline;
1753 if (rface != rface->ascii_rface)
1755 rface->info = rface->ascii_rface->info;
1759 frame = rface->frame;
1760 MSTRUCT_CALLOC (info, MERROR_WIN);
1762 foreground = rface->face.property[MFACE_FOREGROUND];
1763 background = rface->face.property[MFACE_BACKGROUND];
1764 videomode = rface->face.property[MFACE_VIDEOMODE];
1766 videomode = frame->videomode;
1767 if (videomode != Mreverse)
1769 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1770 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1774 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1775 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1778 if (foreground == Mnil)
1779 foreground = frame->foreground;
1780 if (background == Mnil)
1781 background = frame->background;
1782 if (videomode == Mreverse)
1784 MSymbol temp = foreground;
1785 foreground = background;
1788 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1789 FRAME_VISUAL (frame),
1791 MSYMBOL_NAME (foreground),
1792 &info->xft_color_fore))
1794 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1795 FRAME_VISUAL (frame),
1797 MSYMBOL_NAME (background),
1798 &info->xft_color_back))
1802 hline = rface->hline;
1806 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1808 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1815 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1817 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1819 if (box->color_left && box->color_left != box->color_top)
1820 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1822 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1824 if (box->color_bottom && box->color_bottom != box->color_top)
1825 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1827 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1829 if (box->color_right && box->color_right != box->color_bottom)
1830 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1832 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1840 mwin__free_realized_face (MRealizedFace *rface)
1842 if (rface == rface->ascii_rface)
1848 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1850 int x, int y, int width, int height, MDrawRegion region)
1852 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1855 gc = set_region (frame, gc, region);
1857 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1858 x, y, width, height);
1862 void mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1863 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1864 int reverse, MDrawRegion region)
1866 MRealizedFace *rface = from->rface;
1867 Display *display = FRAME_DISPLAY (rface->frame);
1868 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1874 gc = set_region (rface->frame, gc, region);
1875 for (; from < to; from++)
1877 XDrawRectangle (display, (Window) win, gc,
1878 x, y - gstring->ascent + 1, from->width - 1,
1879 gstring->ascent + gstring->descent - 2);
1886 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1887 MRealizedFace *rface, int reverse,
1888 int x, int y, int width, MDrawRegion region)
1890 enum MFaceHLineType type = rface->hline->type;
1891 GCInfo *info = rface->info;
1892 GC gc = gc = info->gc[GC_HLINE];
1895 y = (type == MFACE_HLINE_BOTTOM
1896 ? y + gstring->text_descent - rface->hline->width
1897 : type == MFACE_HLINE_UNDER
1899 : type == MFACE_HLINE_STRIKE_THROUGH
1900 ? y - ((gstring->ascent + gstring->descent) / 2)
1901 : y - gstring->text_ascent);
1903 gc = set_region (frame, gc, region);
1905 for (i = 0; i < rface->hline->width; i++)
1906 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1907 x, y + i, x + width - 1, y + i);
1912 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1913 MGlyph *g, int x, int y, int width, MDrawRegion region)
1915 Display *display = FRAME_DISPLAY (frame);
1916 MRealizedFace *rface = g->rface;
1917 MFaceBoxProp *box = rface->box;
1918 GCInfo *info = rface->info;
1919 GC gc_top, gc_left, gc_right, gc_btm;
1923 y0 = y - (gstring->text_ascent
1924 + rface->box->inner_vmargin + rface->box->width);
1925 y1 = y + (gstring->text_descent
1926 + rface->box->inner_vmargin + rface->box->width - 1);
1928 gc_top = info->gc[GC_BOX_TOP];
1930 gc_top = set_region (frame, gc_top, region);
1931 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1934 gc_btm = info->gc[GC_BOX_BOTTOM];
1936 if (g->type == GLYPH_BOX)
1940 if (g->left_padding)
1941 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1943 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1945 /* Draw the top side. */
1946 for (i = 0; i < box->width; i++)
1947 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1949 /* Draw the bottom side. */
1950 if (region && gc_btm != gc_top)
1951 gc_btm = set_region (frame, gc_btm, region);
1952 for (i = 0; i < box->width; i++)
1953 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1955 if (g->left_padding > 0)
1957 /* Draw the left side. */
1958 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1962 gc_left = info->gc[GC_BOX_LEFT];
1964 gc_left = set_region (frame, gc_left, region);
1966 for (i = 0; i < rface->box->width; i++)
1967 XDrawLine (display, (Window) win, gc_left,
1968 x0 + i, y0 + i, x0 + i, y1 - i);
1972 /* Draw the right side. */
1973 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1977 gc_right = info->gc[GC_BOX_RIGHT];
1979 gc_right = set_region (frame, gc_right, region);
1981 for (i = 0; i < rface->box->width; i++)
1982 XDrawLine (display, (Window) win, gc_right,
1983 x1 - i, y0 + i, x1 - i, y1 - i);
1988 /* Draw the top side. */
1989 for (i = 0; i < box->width; i++)
1990 XDrawLine (display, (Window) win, gc_top,
1991 x, y0 + i, x + width - 1, y0 + i);
1993 /* Draw the bottom side. */
1994 if (region && gc_btm != gc_top)
1995 gc_btm = set_region (frame, gc_btm, region);
1996 for (i = 0; i < box->width; i++)
1997 XDrawLine (display, (Window) win, gc_btm,
1998 x, y1 - i, x + width - 1, y1 - i);
2005 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
2006 int reverse, int x, int y,
2007 int width, int height, int row_bytes, unsigned char *bmp,
2010 Display *display = FRAME_DISPLAY (frame);
2012 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
2015 gc = set_region (frame, gc, region);
2017 for (i = 0; i < height; i++, bmp += row_bytes)
2018 for (j = 0; j < width; j++)
2019 if (bmp[j / 8] & (1 << (7 - (j % 8))))
2020 XDrawPoint (display, (Window) win, gc, x + j, y + i);
2025 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
2026 int intensity, MDrawPoint *points, int num,
2029 GCInfo *info = rface->info;
2032 if (! (gc = info->gc[intensity]))
2033 gc = info->gc[intensity] = get_gc_for_anti_alias (frame->device, info,
2036 gc = set_region (frame, gc, region);
2038 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
2039 (XPoint *) points, num, CoordModeOrigin);
2044 mwin__region_from_rect (MDrawMetric *rect)
2046 MDrawRegion region1 = XCreateRegion ();
2047 MDrawRegion region2 = XCreateRegion ();
2052 xrect.width = rect->width;
2053 xrect.height = rect->height;
2054 XUnionRectWithRegion (&xrect, region1, region2);
2055 XDestroyRegion (region1);
2060 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
2062 MDrawRegion region1 = XCreateRegion ();
2067 xrect.width = rect->width;
2068 xrect.height = rect->height;
2070 XUnionRegion (region, region, region1);
2071 XUnionRectWithRegion (&xrect, region1, region);
2072 XDestroyRegion (region1);
2076 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
2078 MDrawRegion region = XCreateRegion ();
2080 XUnionRegion (region1, region1, region);
2081 XIntersectRegion (region, region2, region1);
2082 XDestroyRegion (region);
2086 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
2088 MDrawRegion region1 = XCreateRegion ();
2093 xrect.width = rect->width;
2094 xrect.height = rect->height;
2095 XUnionRectWithRegion (&xrect, region1, region);
2096 XDestroyRegion (region1);
2100 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
2104 XClipBox (region, &xrect);
2107 rect->width = xrect.width;
2108 rect->height = xrect.height;
2112 mwin__free_region (MDrawRegion region)
2114 XDestroyRegion (region);
2118 mwin__dump_region (MDrawRegion region)
2121 XClipBox (region, &rect);
2122 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
2126 mwin__verify_region (MFrame *frame, MDrawRegion region)
2128 set_region (frame, ((GCInfo *) frame->rface->info)->gc[GC_NORMAL], region);
2132 mwin__create_window (MFrame *frame, MDrawWindow parent)
2134 Display *display = FRAME_DISPLAY (frame);
2136 XWMHints wm_hints = { InputHint, False };
2137 XClassHint class_hints = { "M17N-IM", "m17n-im" };
2138 XSetWindowAttributes set_attrs;
2141 GCInfo *info = frame->rface->info;
2144 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
2145 mask = GCForeground;
2146 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
2147 set_attrs.background_pixel = values.foreground;
2148 set_attrs.backing_store = Always;
2149 set_attrs.override_redirect = True;
2150 set_attrs.save_under = True;
2151 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
2152 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
2153 CopyFromParent, InputOutput, CopyFromParent,
2155 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
2156 NULL, &wm_hints, &class_hints);
2157 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
2158 return (MDrawWindow) win;
2162 mwin__destroy_window (MFrame *frame, MDrawWindow win)
2164 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
2169 mwin__event_window (void *event)
2171 return ((MDrawWindow) ((XEvent *) event)->xany.window);
2175 mwin__print_event (void *arg, char *win_name)
2178 XEvent *event = (XEvent *) arg;
2180 switch (event->xany.type)
2182 case 2: event_name = "KeyPress"; break;
2183 case 3: event_name = "KeyRelease"; break;
2184 case 4: event_name = "ButtonPress"; break;
2185 case 5: event_name = "ButtonRelease"; break;
2186 case 6: event_name = "MotionNotify"; break;
2187 case 7: event_name = "EnterNotify"; break;
2188 case 8: event_name = "LeaveNotify"; break;
2189 case 9: event_name = "FocusIn"; break;
2190 case 10: event_name = "FocusOut"; break;
2191 case 11: event_name = "KeymapNotify"; break;
2192 case 12: event_name = "Expose"; break;
2193 case 13: event_name = "GraphicsExpose"; break;
2194 case 14: event_name = "NoExpose"; break;
2195 case 15: event_name = "VisibilityNotify"; break;
2196 case 16: event_name = "CreateNotify"; break;
2197 case 17: event_name = "DestroyNotify"; break;
2198 case 18: event_name = "UnmapNotify"; break;
2199 case 19: event_name = "MapNotify"; break;
2200 case 20: event_name = "MapRequest"; break;
2201 case 21: event_name = "ReparentNotify"; break;
2202 case 22: event_name = "ConfigureNotify"; break;
2203 case 23: event_name = "ConfigureRequest"; break;
2204 case 24: event_name = "GravityNotify"; break;
2205 case 25: event_name = "ResizeRequest"; break;
2206 case 26: event_name = "CirculateNotify"; break;
2207 case 27: event_name = "CirculateRequest"; break;
2208 case 28: event_name = "PropertyNotify"; break;
2209 case 29: event_name = "SelectionClear"; break;
2210 case 30: event_name = "SelectionRequest"; break;
2211 case 31: event_name = "SelectionNotify"; break;
2212 case 32: event_name = "ColormapNotify"; break;
2213 case 33: event_name = "ClientMessage"; break;
2214 case 34: event_name = "MappingNotify"; break;
2215 default: event_name = "unknown";
2218 fprintf (stderr, "%s: %s\n", win_name, event_name);
2223 mwin__map_window (MFrame *frame, MDrawWindow win)
2225 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
2229 mwin__unmap_window (MFrame *frame, MDrawWindow win)
2231 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
2235 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
2236 MDrawMetric *geometry)
2238 Display *display = FRAME_DISPLAY (frame);
2239 XWindowAttributes attr;
2240 Window parent = (Window) parent_win, root;
2242 XGetWindowAttributes (display, (Window) win, &attr);
2243 geometry->x = attr.x + attr.border_width;
2244 geometry->y = attr.y + attr.border_width;
2245 geometry->width = attr.width;
2246 geometry->height = attr.height;
2249 parent = RootWindow (display, FRAME_SCREEN (frame));
2252 Window this_parent, *children;
2255 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
2258 if (this_parent == parent || this_parent == root)
2260 win = (MDrawWindow) this_parent;
2261 XGetWindowAttributes (display, (Window) win, &attr);
2262 geometry->x += attr.x + attr.border_width;
2263 geometry->y += attr.y + attr.border_width;
2268 mwin__adjust_window (MFrame *frame, MDrawWindow win,
2269 MDrawMetric *current, MDrawMetric *new)
2271 Display *display = FRAME_DISPLAY (frame);
2272 unsigned int mask = 0;
2273 XWindowChanges values;
2275 if (current->width != new->width)
2278 if (new->width <= 0)
2280 values.width = current->width = new->width;
2282 if (current->height != new->height)
2285 if (new->height <= 0)
2287 values.height = current->height = new->height;
2289 if (current->x != new->x)
2292 values.x = current->x = new->x;
2294 if (current->y != new->y)
2297 current->y = new->y;
2298 values.y = current->y = new->y;
2301 XConfigureWindow (display, (Window) win, mask, &values);
2302 XClearWindow (display, (Window) win);
2306 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
2308 XEvent *event = (XEvent *) arg;
2309 MDisplayInfo *disp_info = frame->device->display_info;
2316 if (event->xany.type != KeyPress
2317 /* && event->xany.type != KeyRelease */
2320 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
2327 if (c < XK_space || c > XK_asciitilde)
2329 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
2330 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
2331 if (((XKeyEvent *) event)->state & ControlMask)
2333 if (c >= 'a' && c <= 'z')
2335 if (c >= ' ' && c < 127)
2336 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
2338 key = minput__char_to_key (c);
2340 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
2344 char *str = XKeysymToString (keysym);
2348 key = msymbol (str);
2349 if (((XKeyEvent *) event)->state & ShiftMask)
2350 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
2351 if (((XKeyEvent *) event)->state & ControlMask)
2352 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
2354 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
2355 *modifiers |= MINPUT_KEY_META_MODIFIER;
2356 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
2357 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
2358 if (((XKeyEvent *) event)->state & disp_info->super_mask)
2359 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
2360 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
2361 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
2368 mwin__get_selection_text (MFrame *frame)
2375 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
2377 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
2379 Display *display = FRAME_DISPLAY (frame);
2380 GCInfo *info = rface->info;
2383 for (i = 0; i <= GC_INVERSE; i++)
2385 XGetGCValues (display, info->gc[i], valuemask, &values);
2386 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
2387 values.foreground, values.background);
2388 fprintf (stderr, "\n");
2393 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2398 /*** @addtogroup m17nFrame */
2403 @name Variables: Keys of frame parameter (X specific).
2405 These are the symbols to use as parameter keys for the function
2406 mframe () (which see). They are also keys of a frame property
2407 except for #Mwidget. */
2409 @name ÊÑ¿ô¡§ ¥Õ¥ì¡¼¥à¥Ñ¥é¥á¡¼¥¿ÍÑ¥¡¼ (X ¸ÇÍ).
2411 ´Ø¿ô mframe () ¤Î¥Ñ¥é¥á¡¼¥¿¥¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¥·¥ó¥Ü¥ë¡£( mframe
2412 () ¤ÎÀâÌÀ»²¾È¡£) #Mwidget ¤ò½ü¤¤¤Æ¤Ï¥Õ¥ì¡¼¥à¥×¥í¥Ñ¥Æ¥£¤Î¥¡¼¤Ç¤â¤¢
2418 /* Keywords for mwin__open_device (). */
2419 MSymbol Mdisplay, Mscreen, Mdrawable, Mdepth, Mwidget, Mcolormap;
2425 /*** @addtogroup m17nInputMethodWin */
2430 @brief Input method driver for XIM.
2432 The driver #minput_xim_driver is for the foreign input method of
2433 name #Mxim. It uses XIM (X Input Methods) as a background input
2436 As the symbol #Mxim has property #Minput_driver whose value is
2437 a pointer to this driver, the input method of language #Mnil
2438 and name #Mxim uses this driver.
2440 Therefore, for such input methods, the driver dependent arguments
2441 to the functions whose name begin with minput_ must be as follows.
2443 The argument $ARG of the function minput_open_im () must be a
2444 pointer to the structure #MInputXIMArgIM. See the documentation
2445 of #MInputXIMArgIM for more detail.
2447 The argument $ARG of the function minput_create_ic () must be a
2448 pointer to the structure #MInputXIMArgIC. See the documentation
2449 of #MInputXIMArgIC for more detail.
2451 The argument $ARG of the function minput_filter () must be a
2452 pointer to the structure @c XEvent. The argument $KEY is ignored.
2454 The argument $ARG of the function minput_lookup () must be the
2455 same one as that of the function minput_filter (). The argument
2459 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2461 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
2462 ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
2465 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2466 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
2467 ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2469 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
2470 ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2472 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM ¤Ø¤Î¥Ý
2473 ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
2476 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC ¤Ø¤Î
2477 ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
2480 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2481 ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2483 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2484 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2487 MInputDriver minput_xim_driver =
2488 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2489 xim_filter, xim_lookup, NULL };
2494 @brief Symbol of the name "xim".
2496 The variable Mxim is a symbol of name "xim". It is a name of the
2497 input method driver #minput_xim_driver. */
2499 @brief "xim"¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë .
2501 ÊÑ¿ô Mxim ¤Ï"xim"¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£"xim" ¤ÏÆþÎϥ᥽¥Ã
2502 ¥É¥É¥é¥¤¥Ð #minput_xim_driver ¤Î̾Á°¤Ç¤¢¤ë¡£ */