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 /* Nth bit tells the existence of a font of size (N+1).
62 core.property[MFONT_SIZE] holds the smallest size. */
66 /* S must satisfy the condition (S > 0 && S <= 32). */
67 #define SET_SIZE(sizes, s) ((sizes) |= (1 << ((s) - 1)))
68 #define HAVE_SIZE(sizes, s) ((sizes) & (1 << ((s) - 1)))
77 /* Common header for the m17n object. */
82 /* If nonzero, <display> is opened by this library. Thus it should
83 be closed on freeing this structure. */
86 /** List of available X-core fonts on the display. Keys are
87 registries and values are plists whose keys are families and
88 values are pointers to MXFontList. */
91 /** List of available X-core fonts on the display. Keys are
92 families and values are pointers to MFont. For each MFont, only
93 these properties are important; FOUNDRY, FAMILY, REGISTRY. */
94 MPlist *base_font_list;
96 /** Nonzero means that <font_list> already contains all available
97 fonts on the display. */
100 /** Modifier bit masks of the display. */
107 /* Anchor of the chain of MDisplayInfo objects. */
108 static MPlist *display_info_list;
111 /* Color value and the corresponding GC. */
114 unsigned int rgb; /* (red << 16) | (green << 8) | blue */
121 GC_NORMAL = GC_INVERSE + 7,
134 /* The first 8 elements are indexed by an intensity for
135 anti-aliasing. The 2nd to 7th are created on demand. */
138 XftColor xft_color_fore, xft_color_back;
144 /* Common header for the m17n object. */
147 MDisplayInfo *display_info;
163 /** List of pointers to realized faces on the frame. */
164 MPlist *realized_face_list;
166 /* List of information about each font. Keys are font registries,
167 values are (MFontInfo *). */
168 MPlist *realized_font_list;
170 /** List of pointers to realized fontsets on the frame. */
171 MPlist *realized_fontset_list;
173 /** List of XColors vs GCs on the frame. */
177 static MPlist *device_list;
179 static MSymbol M_iso8859_1, M_iso10646_1;
181 #define FRAME_DEVICE(frame) ((MWDevice *) (frame)->device)
182 #define FRAME_DISPLAY(frame) (FRAME_DEVICE (frame)->display_info->display)
183 #define FRAME_SCREEN(frame) (FRAME_DEVICE (frame)->screen_num)
184 #define FRAME_CMAP(frame) (FRAME_DEVICE (frame)->cmap)
185 #define FRAME_VISUAL(frame) DefaultVisual (FRAME_DISPLAY (frame), \
186 FRAME_SCREEN (frame))
188 #define DEFAULT_FONT "-misc-fixed-medium-r-normal--*-120-*-*-*-*-iso8859-1"
189 #define FALLBACK_FONT "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1"
196 Boolean reverse_video;
197 } AppData, *AppDataPtr;
200 free_display_info (void *object)
202 MDisplayInfo *disp_info = (MDisplayInfo *) object;
205 MPLIST_DO (plist, disp_info->font_list)
207 MPLIST_DO (p, MPLIST_VAL (plist))
208 free (MPLIST_VAL (p));
209 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
211 M17N_OBJECT_UNREF (disp_info->font_list);
212 MPLIST_DO (plist, disp_info->base_font_list)
213 free (MPLIST_VAL (plist));
214 M17N_OBJECT_UNREF (disp_info->base_font_list);
216 if (disp_info->auto_display)
217 XCloseDisplay (disp_info->display);
223 free_device (void *object)
225 MWDevice *device = object;
228 for (plist = device->realized_fontset_list;
229 mplist_key (plist) != Mnil; plist = mplist_next (plist))
230 mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist));
231 M17N_OBJECT_UNREF (device->realized_fontset_list);
233 MPLIST_DO (plist, device->realized_font_list)
234 mfont__free_realized ((MRealizedFont *) MPLIST_VAL (plist));
235 M17N_OBJECT_UNREF (device->realized_font_list);
237 MPLIST_DO (plist, device->realized_face_list)
239 MRealizedFace *rface = MPLIST_VAL (plist);
242 mface__free_realized (rface);
244 M17N_OBJECT_UNREF (device->realized_face_list);
246 MPLIST_DO (plist, device->gc_list)
248 XFreeGC (device->display_info->display,
249 ((RGB_GC *) MPLIST_VAL (plist))->gc);
250 free (MPLIST_VAL (plist));
252 M17N_OBJECT_UNREF (device->gc_list);
253 XFreeGC (device->display_info->display, device->scratch_gc);
256 XftDrawDestroy (device->xft_draw);
259 XFreePixmap (device->display_info->display, device->drawable);
260 M17N_OBJECT_UNREF (device->display_info);
266 find_modifier_bits (MDisplayInfo *disp_info)
268 Display *display = disp_info->display;
269 XModifierKeymap *mods;
270 KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L);
271 KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R);
272 KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L);
273 KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R);
274 KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
275 KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
276 KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
277 KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
280 mods = XGetModifierMapping (display);
281 /* We skip the first three sets for Shift, Lock, and Control. The
282 remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
283 for (i = 3; i < 8; i++)
284 for (j = 0; j < mods->max_keypermod; j++)
286 KeyCode code = mods->modifiermap[i * mods->max_keypermod + j];
290 if (code == meta_l || code == meta_r)
291 disp_info->meta_mask |= (1 << i);
292 else if (code == alt_l || code == alt_r)
293 disp_info->alt_mask |= (1 << i);
294 else if (code == super_l || code == super_r)
295 disp_info->super_mask |= (1 << i);
296 else if (code == hyper_l || code == hyper_r)
297 disp_info->hyper_mask |= (1 << i);
300 /* If meta keys are not in any modifier, use alt keys as meta
302 if (! disp_info->meta_mask)
304 disp_info->meta_mask = disp_info->alt_mask;
305 disp_info->alt_mask = 0;
307 /* If both meta and alt are assigned to the same modifier, give meta
309 if (disp_info->meta_mask & disp_info->alt_mask)
310 disp_info->alt_mask &= ~disp_info->meta_mask;
312 XFreeModifiermap (mods);
316 get_rgb_gc (MWDevice *device, XColor *xcolor)
318 int rgb = (((xcolor->red >> 8) << 16) | ((xcolor->green >> 8) << 8)
319 | (xcolor->blue >> 8));
322 unsigned long valuemask = GCForeground;
325 MPLIST_DO (plist, device->gc_list)
327 rgb_gc = MPLIST_VAL (plist);
329 if (rgb_gc->rgb == rgb)
331 if (rgb_gc->rgb > rgb)
335 if (! XAllocColor (device->display_info->display, device->cmap, xcolor))
338 rgb_gc = malloc (sizeof (RGB_GC));
340 values.foreground = xcolor->pixel;
341 rgb_gc->gc = XCreateGC (device->display_info->display,
342 device->drawable, valuemask, &values);
343 mplist_push (plist, Mt, rgb_gc);
348 get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret)
350 MWDevice *device = FRAME_DEVICE (frame);
358 color = for_foreground ? frame->foreground : frame->background;
360 if (! XParseColor (FRAME_DISPLAY (frame), device->cmap,
361 msymbol_name (color), &xcolor))
363 rgb_gc = get_rgb_gc (device, &xcolor);
367 *rgb_ret = rgb_gc->rgb;
372 GCInfo *info = frame->rface->info;
377 rgb = info->rgb_fore, gc = info->gc[GC_NORMAL];
379 rgb = info->rgb_back, gc = info->gc[GC_INVERSE];
387 get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity)
389 int rgb_fore, rgb_back;
394 if (info->gc[intensity])
395 return info->gc[intensity];
397 rgb_fore = info->rgb_fore, rgb_back = info->rgb_back;
398 xcolor.red = ((((rgb_fore & 0xFF0000) >> 16) * intensity
399 + ((rgb_back & 0xFF0000) >> 16) * (7 - intensity)) / 7) << 8;
400 xcolor.green = ((((rgb_fore & 0xFF00) >> 8) * intensity
401 + ((rgb_back & 0xFF00) >> 8) * (7 - intensity)) / 7) << 8;
402 xcolor.blue = (((rgb_fore & 0xFF) * intensity
403 + (rgb_back & 0xFF) * (7 - intensity)) / 7) << 8;
404 rgb_gc = get_rgb_gc (device, &xcolor);
408 gc =get_gc_for_anti_alias (device, info,
409 intensity < 4 ? intensity - 1 : intensity + 1);
410 return (info->gc[intensity] = gc);
414 set_region (MFrame *frame, GC gc, MDrawRegion region)
416 unsigned long valuemask = GCForeground;
418 XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
419 FRAME_DEVICE (frame)->scratch_gc);
420 XSetRegion (FRAME_DISPLAY (frame), FRAME_DEVICE (frame)->scratch_gc, region);
421 return FRAME_DEVICE (frame)->scratch_gc;
425 /** X font handler */
427 static MRealizedFont *xfont_select (MFrame *, MFont *, MFont *, int);
428 static int xfont_open (MRealizedFont *);
429 static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int);
430 static unsigned xfont_encode_char (MRealizedFont *, unsigned);
431 static void xfont_render (MDrawWindow, int, int, MGlyphString *,
432 MGlyph *, MGlyph *, int, MDrawRegion);
433 static int xfont_list (MFrame *frame, MPlist *plist,
434 MFont *font, MSymbol language, int maxnum);
437 static MFontDriver xfont_driver =
438 { xfont_select, xfont_open,
439 xfont_find_metric, xfont_encode_char, xfont_render, xfont_list };
442 font_compare (const void *p1, const void *p2)
444 return strcmp (*(char **) p1, *(char **) p2);
448 xfont_registry_list (MFrame *frame, MSymbol registry)
450 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
451 MPlist *font_list = disp_info->font_list;
452 MPlist *base_font_list = disp_info->base_font_list;
455 char **font_names, **names;
459 MXFontList *xfont_table;
462 plist = mplist_get (font_list, registry);
466 mplist_add (font_list, registry, plist);
467 sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", msymbol_name (registry));
468 font_names = XListFonts (disp_info->display, pattern, 0x8000, &nfonts);
471 names = alloca (sizeof (char *) * nfonts);
472 memcpy (names, font_names, sizeof (char *) * nfonts);
473 qsort (names, nfonts, sizeof (char *), font_compare);
474 for (i = 0, p = NULL; i < nfonts; i++)
475 if (mfont__parse_name_into_font (names[i], Mx, (MFont *) &font) == 0
476 && (font.core.property[MFONT_SIZE] > 0
477 || font.core.property[MFONT_RESY] == 0))
479 MSymbol family = FONT_PROPERTY ((MFont *) &font, MFONT_FAMILY);
480 int size = font.core.property[MFONT_SIZE] / 10;
484 unsigned int size_bits = 0;
489 sizes[sizes_idx++] = smallest = size;
490 /* Handle fonts of the same base name. */
491 for (base_end = names[i], fields = 0; *base_end; base_end++)
493 && ++fields == 7 /* PIXEL_SIZE */)
495 base_len = base_end - names[i] + 1;
496 for (j = i + 1; j < nfonts && ! strncmp (names[i], names[j], base_len);
498 if (mfont__parse_name_into_font (names[j], Mx, (MFont *) &font) == 0
499 && (font.core.property[MFONT_SIZE] > 0
500 || font.core.property[MFONT_RESY] == 0))
502 int this_size = font.core.property[MFONT_SIZE] / 10;
505 for (k = 0; k < sizes_idx && sizes[k] != this_size; k++);
506 if (k == sizes_idx && sizes_idx < 256)
508 sizes[sizes_idx++] = this_size;
509 if (this_size < smallest)
510 smallest = this_size;
514 if (p && MPLIST_KEY (p) != family)
515 p = mplist_find_by_key (plist, family);
517 xfont_table = MPLIST_VAL (p);
521 MSTRUCT_MALLOC (xfont_table, MERROR_WIN);
522 MLIST_INIT1 (xfont_table, fonts, 4);
523 mplist_push (p, family, xfont_table);
526 for (j = 0; j < sizes_idx; j++)
531 SET_SIZE (size_bits, sizes[j]);
535 font.core.property[MFONT_SIZE] = sizes[j] * 10;
537 MLIST_APPEND1 (xfont_table, fonts, font, MERROR_WIN);
541 if (size_bits || smallest == 0)
543 font.sizes = size_bits;
544 font.core.property[MFONT_SIZE] = smallest * 10;
545 MLIST_APPEND1 (xfont_table, fonts, font, MERROR_WIN);
548 || (font.core.property[MFONT_FOUNDRY]
549 != bfont->property[MFONT_FOUNDRY])
550 || (font.core.property[MFONT_FAMILY]
551 != bfont->property[MFONT_FAMILY]))
553 MSTRUCT_MALLOC (bfont, MERROR_WIN);
555 for (j = MFONT_WEIGHT; j <= MFONT_ADSTYLE; j++)
556 bfont->property[j] = 0;
557 bfont->property[MFONT_SIZE] = bfont->property[MFONT_RESY] = 0;
558 mplist_push (base_font_list, family, bfont);
561 XFreeFontNames (font_names);
566 xfont_list_all (MFrame *frame)
568 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
569 MPlist *font_encoding_list, *p;
571 if (disp_info->all_fonts_scaned)
573 disp_info->all_fonts_scaned = 1;
574 font_encoding_list = mfont__encoding_list ();
575 if (! font_encoding_list)
577 MPLIST_DO (p, font_encoding_list)
578 xfont_registry_list (frame, MPLIST_KEY (p));
589 /* The X font driver function SELECT. */
591 static MRealizedFont *
592 xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
594 MSymbol family = FONT_PROPERTY (spec, MFONT_FAMILY);
595 MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
596 int requested_size = request->property[MFONT_SIZE];
597 MRealizedFont *rfont;
601 int best_size, best_score, score;
604 || ! strchr (MSYMBOL_NAME (registry), '-'))
607 plist = xfont_registry_list (frame, registry);
608 if (MPLIST_TAIL_P (plist))
610 best_score = -1, best_font = NULL;
611 MPLIST_DO (plist, plist)
613 if (family == Mnil || family == MPLIST_KEY (plist))
615 MXFontList *xfont_table = MPLIST_VAL (plist);
617 for (i = 0; i < xfont_table->used; i++)
619 MXFont *xfont = xfont_table->fonts + i;
620 MFont *font = (MFont *) xfont;
621 unsigned int sizes = xfont->sizes;
626 size = font->property[MFONT_SIZE];
627 score = mfont__score (font, spec, request, limited_size);
631 unsigned short orig_size = font->property[MFONT_SIZE];
632 int smallest = orig_size / 10;
635 size = requested_size / 10;
638 /* Find an exact or smaller size. */
643 s0 > smallest && s0 > 0 && ! HAVE_SIZE (sizes, s0);
646 /* Exact size match. */
648 else if (smallest == 0)
649 /* Scalable font exists. */
651 else if (size < smallest)
653 /* No smaller size font. Select the smallest one. */
655 /* Can't use a larger font. */
661 /* Check if there's a better larger size font. */
662 int largest = size + (size - s0);
668 s1 < largest && ! HAVE_SIZE (sizes, s1);
670 size = (s1 < largest ? s1 : s0);
673 font->property[MFONT_SIZE] = size;
674 score = mfont__score (font, spec, request, limited_size);
675 font->property[MFONT_SIZE] = orig_size;
678 if (score >= 0 && (best_score < 0 || score < best_score))
682 best_font = (MFont *) (xfont_table->fonts + i);
694 MSTRUCT_CALLOC (rfont, MERROR_WIN);
695 rfont->frame = frame;
697 rfont->request = *request;
698 rfont->font = *best_font;
700 rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE];
702 rfont->font.property[MFONT_SIZE] = best_size;
703 rfont->score = best_score;
708 /* The X font driver function CLOSE. */
711 close_xfont (void *object)
713 MXFontInfo *xfont_info = object;
715 XFreeFont (xfont_info->display, xfont_info->xfont);
720 /* The X font driver function OPEN. */
723 xfont_open (MRealizedFont *rfont)
726 MXFontInfo *xfont_info;
727 MFrame *frame = rfont->frame;
728 int mdebug_mask = MDEBUG_FONT;
730 /* This never fail to generate a valid fontname because open_spec
731 should correspond to a font available on the system. */
732 name = mfont_unparse_name (&rfont->font, Mx);
733 M17N_OBJECT (xfont_info, close_xfont, MERROR_WIN);
734 xfont_info->display = FRAME_DISPLAY (frame);
735 xfont_info->xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
736 if (! xfont_info->xfont)
740 MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
744 rfont->info = xfont_info;
745 MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
748 rfont->ascent = xfont_info->xfont->ascent;
749 rfont->descent = xfont_info->xfont->descent;
751 rfont->fontp = xfont_info->xfont;
756 /* The X font driver function FIND_METRIC. */
759 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
762 MXFontInfo *xfont_info = rfont->info;
763 XFontStruct *xfont = xfont_info->xfont;
764 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
766 for (; g != gend; g++)
768 if (g->code == MCHAR_INVALID_CODE)
770 g->lbearing = xfont->max_bounds.lbearing;
771 g->rbearing = xfont->max_bounds.rbearing;
772 g->width = xfont->max_bounds.width;
773 g->ascent = xfont->ascent;
774 g->descent = xfont->descent;
778 int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
779 XCharStruct *pcm = NULL;
781 if (xfont->per_char != NULL)
783 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
786 && byte2 >= xfont->min_char_or_byte2
787 && byte2 <= xfont->max_char_or_byte2)
788 pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
792 if (byte1 >= xfont->min_byte1
793 && byte1 <= xfont->max_byte1
794 && byte2 >= xfont->min_char_or_byte2
795 && byte2 <= xfont->max_char_or_byte2)
797 pcm = (xfont->per_char
798 + ((xfont->max_char_or_byte2
799 - xfont->min_char_or_byte2 + 1)
800 * (byte1 - xfont->min_byte1))
801 + (byte2 - xfont->min_char_or_byte2));
808 g->lbearing = pcm->lbearing;
809 g->rbearing = pcm->rbearing;
810 g->width = pcm->width;
811 g->ascent = pcm->ascent;
812 g->descent = pcm->descent;
816 /* If the per_char pointer is null, all glyphs between
817 the first and last character indexes inclusive have
818 the same information, as given by both min_bounds and
821 g->rbearing = xfont->max_bounds.width;
822 g->width = xfont->max_bounds.width;
823 g->ascent = xfont->ascent;
824 g->descent = xfont->descent;
831 /* The X font driver function GET_GLYPH_ID. */
834 xfont_encode_char (MRealizedFont *rfont, unsigned code)
836 MXFontInfo *xfont_info;
838 unsigned min_byte1, max_byte1, min_byte2, max_byte2;
841 if (rfont->status < 0 || code >= 0x10000)
842 return MCHAR_INVALID_CODE;
843 if (rfont->status == 0)
845 if (xfont_open (rfont) < 0)
846 return MCHAR_INVALID_CODE;
848 xfont_info = rfont->info;
849 xfont = xfont_info->xfont;
850 all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
851 min_byte1 = xfont->min_byte1;
852 max_byte1 = xfont->max_byte1;
853 min_byte2 = xfont->min_char_or_byte2;
854 max_byte2 = xfont->max_char_or_byte2;
856 if (min_byte1 == 0 && max_byte1 == 0)
860 if (code < min_byte2 || code > max_byte2)
861 return MCHAR_INVALID_CODE;
864 pcm = xfont->per_char + (code - min_byte2);
865 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
866 ? code : MCHAR_INVALID_CODE);
870 unsigned byte1 = code >> 8, byte2 = code & 0xFF;
873 if (byte1 < min_byte1 || byte1 > max_byte1
874 || byte2 < min_byte2 || byte2 > max_byte2)
875 return MCHAR_INVALID_CODE;
879 pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
880 + (byte2 - min_byte2));
881 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
882 ? code : MCHAR_INVALID_CODE);
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;
893 MXFontInfo *xfont_info = rface->rfont->info;
896 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
903 /* It is assured that the all glyphs in the current range use the
904 same realized face. */
905 display = FRAME_DISPLAY (rface->frame);
908 gc = set_region (rface->frame, gc, region);
909 XSetFont (display, gc, xfont_info->xfont->fid);
910 code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
911 for (i = 0, g = from; g < to; i++, g++)
913 code[i].byte1 = g->code >> 8;
914 code[i].byte2 = g->code & 0xFF;
920 if (g->type == GLYPH_PAD)
922 else if (g->type == GLYPH_SPACE)
923 for (; g < to && g->type == GLYPH_SPACE; g++)
925 else if (! g->rface->rfont)
927 if ((g->c >= 0x200B && g->c <= 0x200F)
928 || (g->c >= 0x202A && g->c <= 0x202E))
932 /* As a font is not found for this character, draw an
934 int box_width = g->width;
935 int box_height = gstring->ascent + gstring->descent;
941 XDrawRectangle (display, (Window) win, gc,
942 x, y - gstring->ascent, box_width, box_height);
946 else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
948 XDrawString16 (display, (Window) win, gc,
949 x + g->xoff, y + g->yoff, code + (g - from), 1);
956 int code_idx = g - from;
959 g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
962 XDrawString16 (display, (Window) win, gc, orig_x, y,
969 xfont_list (MFrame *frame, MPlist *plist, MFont *font, MSymbol language,
972 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
973 MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil;
974 MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil;
978 if (registry != Mnil)
979 xfont_registry_list (frame, registry);
981 xfont_list_all (frame);
983 /* As we have not yet implemented the language check, return all
986 MPLIST_DO (p, disp_info->base_font_list)
988 mplist_add (plist, MPLIST_KEY (p), MPLIST_VAL (p));
995 MXFontList *xfontlist;
999 pl = disp_info->font_list;
1000 if (registry != Mnil)
1002 pl = mplist_find_by_key (pl, registry);
1009 p = MPLIST_VAL (pl);
1012 p = mplist_find_by_key (p, family);
1018 xfontlist = MPLIST_VAL (p);
1019 for (i = 0; i < xfontlist->used; i++)
1021 xfont = xfontlist->fonts + i;
1022 if (mfont__match_p (&xfont->core, font, MFONT_REGISTRY))
1024 mplist_add (plist, MPLIST_KEY (p), &xfont->core);
1033 if (registry != Mnil)
1050 XftFont *font_no_aa;
1053 static int xft_open (MRealizedFont *);
1054 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
1055 static void xft_render (MDrawWindow, int, int, MGlyphString *,
1056 MGlyph *, MGlyph *, int, MDrawRegion);
1058 MFontDriver xft_driver =
1059 { NULL, /* Set to ft_select in device_init (). */
1060 xft_open, xft_find_metric,
1061 NULL, /* Set to ft_encode_char in device_init (). */
1063 NULL /* Set to ft_list in device_init (). */
1068 close_xft (void *object)
1070 MXftFontInfo *font_info = object;
1072 XftFontClose (font_info->display, font_info->font_aa);
1073 XftFontClose (font_info->display, font_info->font_no_aa);
1079 xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
1081 XftPattern *pattern;
1082 XftFontInfo *xft_font_info;
1085 pattern = XftPatternCreate ();
1086 XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
1087 XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
1088 XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
1089 xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
1090 if (! xft_font_info)
1092 font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
1093 XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
1099 xft_open (MRealizedFont *rfont)
1103 MXftFontInfo *font_info;
1106 if ((mfont__ft_driver.open) (rfont) < 0)
1109 size = rfont->font.property[MFONT_SIZE] / 10;
1110 frame = rfont->frame;
1112 ft_info = rfont->info;
1113 M17N_OBJECT (font_info, close_xft, MERROR_WIN);
1114 ft_info->extra_info = font_info;
1115 font_info->display = FRAME_DISPLAY (frame);
1116 font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
1117 if (font_info->font_aa)
1119 font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
1120 if (font_info->font_no_aa)
1123 rfont->fontp = font_info->font_no_aa;
1126 XftFontClose (FRAME_DISPLAY (rfont->frame), font_info->font_aa);
1129 ft_info->extra_info = NULL;
1136 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1139 MFTInfo *ft_info = rfont->info;
1140 MXftFontInfo *font_info = ft_info->extra_info;
1141 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1143 for (; g != gend; g++)
1145 if (g->code == MCHAR_INVALID_CODE)
1147 MGlyph *start = g++;
1149 while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
1150 (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
1158 XftGlyphExtents (FRAME_DISPLAY (gstring->frame),
1159 font_info->font_aa, &g->code, 1, &extents);
1160 g->lbearing = - extents.x;
1161 g->rbearing = extents.width - extents.x;
1162 g->width = extents.xOff;
1163 g->ascent = extents.y;
1164 g->descent = extents.height - extents.y;
1171 xft_render (MDrawWindow win, int x, int y,
1172 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1173 int reverse, MDrawRegion region)
1175 MRealizedFace *rface = from->rface;
1176 MFrame *frame = rface->frame;
1177 MFTInfo *ft_info = rface->rfont->info;
1178 MXftFontInfo *font_info = ft_info->extra_info;
1179 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1180 XftColor *xft_color = (! reverse
1181 ? &((GCInfo *) rface->info)->xft_color_fore
1182 : &((GCInfo *) rface->info)->xft_color_back);
1183 XftFont *xft_font = (gstring->control.anti_alias
1184 && FRAME_DEVICE (frame)->depth > 1
1185 ? font_info->font_aa : font_info->font_no_aa);
1194 XftDrawChange (xft_draw, (Drawable) win);
1195 XftDrawSetClip (xft_draw, (Region) region);
1197 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1198 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1200 if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1201 glyphs[nglyphs++] = g->code;
1205 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1206 last_x, y, glyphs, nglyphs);
1208 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1209 x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1210 last_x = x + g->width;
1214 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1220 /* Functions for the device driver. */
1223 mwin__close_device (MFrame *frame)
1225 M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
1229 mwin__device_get_prop (MFrame *frame, MSymbol key)
1231 MWDevice *device = FRAME_DEVICE (frame);
1233 if (key == Mdisplay)
1234 return (void *) device->display_info->display;
1236 return (void *) ScreenOfDisplay(device->display_info->display,
1237 device->screen_num);
1238 if (key == Mcolormap)
1239 return (void *) device->cmap;
1241 return (void *) device->depth;
1246 mwin__realize_face (MRealizedFace *rface)
1249 MSymbol foreground, background, videomode;
1250 MFaceHLineProp *hline;
1254 if (rface != rface->ascii_rface)
1256 rface->info = rface->ascii_rface->info;
1260 frame = rface->frame;
1261 MSTRUCT_CALLOC (info, MERROR_WIN);
1263 foreground = rface->face.property[MFACE_FOREGROUND];
1264 background = rface->face.property[MFACE_BACKGROUND];
1265 videomode = rface->face.property[MFACE_VIDEOMODE];
1267 videomode = frame->videomode;
1268 if (videomode != Mreverse)
1270 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1271 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1275 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1276 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1279 if (foreground == Mnil)
1280 foreground = frame->foreground;
1281 if (background == Mnil)
1282 background = frame->background;
1283 if (videomode == Mreverse)
1285 MSymbol temp = foreground;
1286 foreground = background;
1289 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1290 FRAME_VISUAL (frame),
1292 MSYMBOL_NAME (foreground),
1293 &info->xft_color_fore))
1295 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1296 FRAME_VISUAL (frame),
1298 MSYMBOL_NAME (background),
1299 &info->xft_color_back))
1303 hline = rface->hline;
1307 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1309 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1316 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1318 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1320 if (box->color_left && box->color_left != box->color_top)
1321 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1323 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1325 if (box->color_bottom && box->color_bottom != box->color_top)
1326 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1328 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1330 if (box->color_right && box->color_right != box->color_bottom)
1331 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1333 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1341 mwin__free_realized_face (MRealizedFace *rface)
1343 if (rface == rface->ascii_rface)
1349 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1351 int x, int y, int width, int height, MDrawRegion region)
1353 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1356 gc = set_region (frame, gc, region);
1358 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1359 x, y, width, height);
1364 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1365 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1366 int reverse, MDrawRegion region)
1368 MRealizedFace *rface = from->rface;
1369 Display *display = FRAME_DISPLAY (rface->frame);
1370 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1376 gc = set_region (rface->frame, gc, region);
1377 for (; from < to; from++)
1379 XDrawRectangle (display, (Window) win, gc,
1380 x, y - gstring->ascent + 1, from->width - 1,
1381 gstring->ascent + gstring->descent - 2);
1388 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1389 MRealizedFace *rface, int reverse,
1390 int x, int y, int width, MDrawRegion region)
1392 enum MFaceHLineType type = rface->hline->type;
1393 GCInfo *info = rface->info;
1394 GC gc = gc = info->gc[GC_HLINE];
1397 y = (type == MFACE_HLINE_BOTTOM
1398 ? y + gstring->text_descent - rface->hline->width
1399 : type == MFACE_HLINE_UNDER
1401 : type == MFACE_HLINE_STRIKE_THROUGH
1402 ? y - ((gstring->ascent + gstring->descent) / 2)
1403 : y - gstring->text_ascent);
1405 gc = set_region (frame, gc, region);
1407 for (i = 0; i < rface->hline->width; i++)
1408 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1409 x, y + i, x + width - 1, y + i);
1414 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1415 MGlyph *g, int x, int y, int width, MDrawRegion region)
1417 Display *display = FRAME_DISPLAY (frame);
1418 MRealizedFace *rface = g->rface;
1419 MFaceBoxProp *box = rface->box;
1420 GCInfo *info = rface->info;
1421 GC gc_top, gc_left, gc_right, gc_btm;
1425 y0 = y - (gstring->text_ascent
1426 + rface->box->inner_vmargin + rface->box->width);
1427 y1 = y + (gstring->text_descent
1428 + rface->box->inner_vmargin + rface->box->width - 1);
1430 gc_top = info->gc[GC_BOX_TOP];
1432 gc_top = set_region (frame, gc_top, region);
1433 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1436 gc_btm = info->gc[GC_BOX_BOTTOM];
1438 if (g->type == GLYPH_BOX)
1442 if (g->left_padding)
1443 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1445 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1447 /* Draw the top side. */
1448 for (i = 0; i < box->width; i++)
1449 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1451 /* Draw the bottom side. */
1452 if (region && gc_btm != gc_top)
1453 gc_btm = set_region (frame, gc_btm, region);
1454 for (i = 0; i < box->width; i++)
1455 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1457 if (g->left_padding > 0)
1459 /* Draw the left side. */
1460 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1464 gc_left = info->gc[GC_BOX_LEFT];
1466 gc_left = set_region (frame, gc_left, region);
1468 for (i = 0; i < rface->box->width; i++)
1469 XDrawLine (display, (Window) win, gc_left,
1470 x0 + i, y0 + i, x0 + i, y1 - i);
1474 /* Draw the right side. */
1475 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1479 gc_right = info->gc[GC_BOX_RIGHT];
1481 gc_right = set_region (frame, gc_right, region);
1483 for (i = 0; i < rface->box->width; i++)
1484 XDrawLine (display, (Window) win, gc_right,
1485 x1 - i, y0 + i, x1 - i, y1 - i);
1490 /* Draw the top side. */
1491 for (i = 0; i < box->width; i++)
1492 XDrawLine (display, (Window) win, gc_top,
1493 x, y0 + i, x + width - 1, y0 + i);
1495 /* Draw the bottom side. */
1496 if (region && gc_btm != gc_top)
1497 gc_btm = set_region (frame, gc_btm, region);
1498 for (i = 0; i < box->width; i++)
1499 XDrawLine (display, (Window) win, gc_btm,
1500 x, y1 - i, x + width - 1, y1 - i);
1507 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1508 int reverse, int x, int y,
1509 int width, int height, int row_bytes, unsigned char *bmp,
1512 Display *display = FRAME_DISPLAY (frame);
1514 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1517 gc = set_region (frame, gc, region);
1519 for (i = 0; i < height; i++, bmp += row_bytes)
1520 for (j = 0; j < width; j++)
1521 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1522 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1527 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1528 int intensity, MDrawPoint *points, int num,
1531 GCInfo *info = rface->info;
1534 if (! (gc = info->gc[intensity]))
1535 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1538 gc = set_region (frame, gc, region);
1540 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1541 (XPoint *) points, num, CoordModeOrigin);
1546 mwin__region_from_rect (MDrawMetric *rect)
1548 MDrawRegion region1 = XCreateRegion ();
1549 MDrawRegion region2 = XCreateRegion ();
1554 xrect.width = rect->width;
1555 xrect.height = rect->height;
1556 XUnionRectWithRegion (&xrect, region1, region2);
1557 XDestroyRegion (region1);
1562 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1564 MDrawRegion region1 = XCreateRegion ();
1569 xrect.width = rect->width;
1570 xrect.height = rect->height;
1572 XUnionRegion (region, region, region1);
1573 XUnionRectWithRegion (&xrect, region1, region);
1574 XDestroyRegion (region1);
1578 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1580 MDrawRegion region = XCreateRegion ();
1582 XUnionRegion (region1, region1, region);
1583 XIntersectRegion (region, region2, region1);
1584 XDestroyRegion (region);
1588 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1590 MDrawRegion region1 = XCreateRegion ();
1595 xrect.width = rect->width;
1596 xrect.height = rect->height;
1597 XUnionRectWithRegion (&xrect, region1, region);
1598 XDestroyRegion (region1);
1602 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1606 XClipBox (region, &xrect);
1609 rect->width = xrect.width;
1610 rect->height = xrect.height;
1614 mwin__free_region (MDrawRegion region)
1616 XDestroyRegion (region);
1620 mwin__dump_region (MDrawRegion region)
1623 XClipBox (region, &rect);
1624 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1629 mwin__create_window (MFrame *frame, MDrawWindow parent)
1631 Display *display = FRAME_DISPLAY (frame);
1633 XWMHints wm_hints = { InputHint, False };
1634 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1635 XSetWindowAttributes set_attrs;
1638 GCInfo *info = frame->rface->info;
1641 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1642 mask = GCForeground;
1643 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1644 set_attrs.background_pixel = values.foreground;
1645 set_attrs.backing_store = Always;
1646 set_attrs.override_redirect = True;
1647 set_attrs.save_under = True;
1648 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1649 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1650 CopyFromParent, InputOutput, CopyFromParent,
1652 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1653 NULL, &wm_hints, &class_hints);
1654 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1655 return (MDrawWindow) win;
1659 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1661 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1666 mwin__event_window (void *event)
1668 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1672 mwin__print_event (void *arg, char *win_name)
1675 XEvent *event = (XEvent *) arg;
1677 switch (event->xany.type)
1679 case 2: event_name = "KeyPress"; break;
1680 case 3: event_name = "KeyRelease"; break;
1681 case 4: event_name = "ButtonPress"; break;
1682 case 5: event_name = "ButtonRelease"; break;
1683 case 6: event_name = "MotionNotify"; break;
1684 case 7: event_name = "EnterNotify"; break;
1685 case 8: event_name = "LeaveNotify"; break;
1686 case 9: event_name = "FocusIn"; break;
1687 case 10: event_name = "FocusOut"; break;
1688 case 11: event_name = "KeymapNotify"; break;
1689 case 12: event_name = "Expose"; break;
1690 case 13: event_name = "GraphicsExpose"; break;
1691 case 14: event_name = "NoExpose"; break;
1692 case 15: event_name = "VisibilityNotify"; break;
1693 case 16: event_name = "CreateNotify"; break;
1694 case 17: event_name = "DestroyNotify"; break;
1695 case 18: event_name = "UnmapNotify"; break;
1696 case 19: event_name = "MapNotify"; break;
1697 case 20: event_name = "MapRequest"; break;
1698 case 21: event_name = "ReparentNotify"; break;
1699 case 22: event_name = "ConfigureNotify"; break;
1700 case 23: event_name = "ConfigureRequest"; break;
1701 case 24: event_name = "GravityNotify"; break;
1702 case 25: event_name = "ResizeRequest"; break;
1703 case 26: event_name = "CirculateNotify"; break;
1704 case 27: event_name = "CirculateRequest"; break;
1705 case 28: event_name = "PropertyNotify"; break;
1706 case 29: event_name = "SelectionClear"; break;
1707 case 30: event_name = "SelectionRequest"; break;
1708 case 31: event_name = "SelectionNotify"; break;
1709 case 32: event_name = "ColormapNotify"; break;
1710 case 33: event_name = "ClientMessage"; break;
1711 case 34: event_name = "MappingNotify"; break;
1712 default: event_name = "unknown";
1715 fprintf (stderr, "%s: %s\n", win_name, event_name);
1720 mwin__map_window (MFrame *frame, MDrawWindow win)
1722 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1726 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1728 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1732 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1733 MDrawMetric *geometry)
1735 Display *display = FRAME_DISPLAY (frame);
1736 XWindowAttributes attr;
1737 Window parent = (Window) parent_win, root;
1739 XGetWindowAttributes (display, (Window) win, &attr);
1740 geometry->x = attr.x + attr.border_width;
1741 geometry->y = attr.y + attr.border_width;
1742 geometry->width = attr.width;
1743 geometry->height = attr.height;
1746 parent = RootWindow (display, FRAME_SCREEN (frame));
1749 Window this_parent, *children;
1752 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1755 if (this_parent == parent || this_parent == root)
1757 win = (MDrawWindow) this_parent;
1758 XGetWindowAttributes (display, (Window) win, &attr);
1759 geometry->x += attr.x + attr.border_width;
1760 geometry->y += attr.y + attr.border_width;
1765 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1766 MDrawMetric *current, MDrawMetric *new)
1768 Display *display = FRAME_DISPLAY (frame);
1769 unsigned int mask = 0;
1770 XWindowChanges values;
1772 if (current->width != new->width)
1775 if (new->width <= 0)
1777 values.width = current->width = new->width;
1779 if (current->height != new->height)
1782 if (new->height <= 0)
1784 values.height = current->height = new->height;
1786 if (current->x != new->x)
1789 values.x = current->x = new->x;
1791 if (current->y != new->y)
1794 current->y = new->y;
1795 values.y = current->y = new->y;
1798 XConfigureWindow (display, (Window) win, mask, &values);
1799 XClearWindow (display, (Window) win);
1803 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1805 XEvent *event = (XEvent *) arg;
1806 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1813 if (event->xany.type != KeyPress
1814 /* && event->xany.type != KeyRelease */
1817 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1824 if (c < XK_space || c > XK_asciitilde)
1826 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1827 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1828 if (((XKeyEvent *) event)->state & ControlMask)
1830 if (c >= 'a' && c <= 'z')
1832 if (c >= ' ' && c < 127)
1833 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1835 key = minput__char_to_key (c);
1837 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1841 char *str = XKeysymToString (keysym);
1845 key = msymbol (str);
1846 if (((XKeyEvent *) event)->state & ShiftMask)
1847 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1848 if (((XKeyEvent *) event)->state & ControlMask)
1849 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1851 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1852 *modifiers |= MINPUT_KEY_META_MODIFIER;
1853 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1854 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1855 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1856 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1857 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1858 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1865 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1867 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1869 Display *display = FRAME_DISPLAY (frame);
1870 GCInfo *info = rface->info;
1873 for (i = 0; i <= GC_INVERSE; i++)
1875 XGetGCValues (display, info->gc[i], valuemask, &values);
1876 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1877 values.foreground, values.background);
1878 fprintf (stderr, "\n");
1882 static MDeviceDriver x_driver =
1885 mwin__device_get_prop,
1887 mwin__free_realized_face,
1889 mwin__draw_empty_boxes,
1893 mwin__region_from_rect,
1894 mwin__union_rect_with_region,
1895 mwin__intersect_region,
1896 mwin__region_add_rect,
1897 mwin__region_to_rect,
1900 mwin__create_window,
1901 mwin__destroy_window,
1904 mwin__window_geometry,
1905 mwin__adjust_window,
1909 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1914 M_iso8859_1 = msymbol ("iso8859-1");
1915 M_iso10646_1 = msymbol ("iso10646-1");
1917 display_info_list = mplist ();
1918 device_list = mplist ();
1921 xft_driver.select = mfont__ft_driver.select;
1922 xft_driver.encode_char = mfont__ft_driver.encode_char;
1923 xft_driver.list = mfont__ft_driver.list;
1926 Mxim = msymbol ("xim");
1927 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1935 M17N_OBJECT_UNREF (display_info_list);
1936 M17N_OBJECT_UNREF (device_list);
1940 /** Return an MWDevice object corresponding to a display specified in
1943 It searches device_list for a device matching the display. If
1944 found, return the found object. Otherwise, return a newly created
1948 device_open (MFrame *frame, MPlist *param)
1950 Display *display = NULL;
1951 Screen *screen = NULL;
1953 Drawable drawable = 0;
1954 Widget widget = NULL;
1956 int auto_display = 0;
1957 MDisplayInfo *disp_info = NULL;
1958 MWDevice *device = NULL;
1960 XWindowAttributes attr;
1965 int use_xfont = 0, use_freetype = 0, use_xft = 0;
1967 for (plist = param; (key = mplist_key (plist)) != Mnil;
1968 plist = mplist_next (plist))
1970 if (key == Mdisplay)
1971 display = (Display *) mplist_value (plist);
1972 else if (key == Mscreen)
1973 screen = mplist_value (plist);
1974 else if (key == Mdrawable)
1975 drawable = (Drawable) mplist_value (plist);
1976 else if (key == Mdepth)
1977 depth = (unsigned) mplist_value (plist);
1978 else if (key == Mwidget)
1979 widget = (Widget) mplist_value (plist);
1980 else if (key == Mcolormap)
1981 cmap = (Colormap) mplist_value (plist);
1982 else if (key == Mfont)
1984 MSymbol val = MPLIST_SYMBOL (plist);
1988 #ifdef HAVE_FREETYPE
1989 else if (val == Mfreetype)
1992 else if (val == Mxft)
1999 /* If none of them is specified, use all of them. */
2000 if (! use_xfont && ! use_freetype && ! use_xft)
2001 use_xfont = use_freetype = use_xft = 1;
2005 display = XtDisplay (widget);
2006 screen_num = XScreenNumberOfScreen (XtScreen (widget));
2007 depth = DefaultDepth (display, screen_num);
2013 unsigned width, height, border_width;
2016 MERROR (MERROR_WIN, -1);
2017 XGetGeometry (display, drawable, &root_window,
2018 &x, &y, &width, &height, &border_width, &depth);
2019 XGetWindowAttributes (display, root_window, &attr);
2020 screen_num = XScreenNumberOfScreen (attr.screen);
2025 display = DisplayOfScreen (screen);
2030 display = XOpenDisplay (NULL);
2032 MERROR (MERROR_WIN, -1);
2035 screen = DefaultScreenOfDisplay (display);
2037 screen_num = XScreenNumberOfScreen (screen);
2039 depth = DefaultDepth (display, screen_num);
2043 cmap = DefaultColormap (display, screen_num);
2045 for (plist = display_info_list; mplist_key (plist) != Mnil;
2046 plist = mplist_next (plist))
2048 disp_info = (MDisplayInfo *) mplist_value (plist);
2049 if (disp_info->display == display)
2053 if (mplist_key (plist) != Mnil)
2054 M17N_OBJECT_REF (disp_info);
2057 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
2058 disp_info->display = display;
2059 disp_info->auto_display = auto_display;
2060 disp_info->font_list = mplist ();
2061 disp_info->base_font_list = mplist ();
2062 find_modifier_bits (disp_info);
2063 mplist_add (display_info_list, Mt, disp_info);
2066 for (plist = device_list; mplist_key (plist) != Mnil;
2067 plist = mplist_next (plist))
2069 device = (MWDevice *) mplist_value (plist);
2070 if (device->display_info == disp_info
2071 && device->depth == depth
2072 && device->cmap == cmap)
2076 if (mplist_key (plist) != Mnil)
2077 M17N_OBJECT_REF (device);
2080 unsigned long valuemask = GCForeground;
2083 M17N_OBJECT (device, free_device, MERROR_WIN);
2084 device->display_info = disp_info;
2085 device->screen_num = screen_num;
2086 /* A drawable on which to create GCs. */
2087 device->drawable = XCreatePixmap (display,
2088 RootWindow (display, screen_num),
2090 device->depth = depth;
2091 device->cmap = cmap;
2092 device->realized_face_list = mplist ();
2093 device->realized_font_list = mplist ();
2094 device->realized_fontset_list = mplist ();
2095 device->gc_list = mplist ();
2096 values.foreground = BlackPixel (display, screen_num);
2097 device->scratch_gc = XCreateGC (display, device->drawable,
2098 valuemask, &values);
2100 device->xft_draw = XftDrawCreate (display, device->drawable,
2101 DefaultVisual (display, screen_num),
2106 frame->device = device;
2107 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2108 frame->driver = &x_driver;
2109 frame->font_driver_list = mplist ();
2113 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2116 #endif /* HAVE_XFT2 */
2117 #ifdef HAVE_FREETYPE
2119 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2120 #endif /* HAVE_FREETYPE */
2121 if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list))
2122 mplist_push (frame->font_driver_list, Mx, &xfont_driver);
2124 frame->realized_font_list = device->realized_font_list;
2125 frame->realized_face_list = device->realized_face_list;
2126 frame->realized_fontset_list = device->realized_fontset_list;
2130 XtResource resources[] = {
2131 { XtNfont, XtCFont, XtRString, sizeof (String),
2132 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2133 { XtNforeground, XtCForeground, XtRString, sizeof (String),
2134 XtOffset (AppDataPtr, foreground), XtRString, "black" },
2135 { XtNbackground, XtCBackground, XtRString, sizeof (String),
2136 XtOffset (AppDataPtr, background), XtRString, "white" },
2137 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2138 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2141 XtGetApplicationResources (widget, &app_data,
2142 resources, XtNumber (resources), NULL, 0);
2143 frame->foreground = msymbol (app_data.foreground);
2144 frame->background = msymbol (app_data.background);
2145 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2149 app_data.font = DEFAULT_FONT;
2150 frame->foreground = msymbol ("black");
2151 frame->background = msymbol ("white");
2152 frame->videomode = Mnormal;
2157 char **names = XListFonts (display, app_data.font, 1, &nfonts);
2161 if (! (frame->font = mfont_parse_name (names[0], Mx)))
2163 /* The font name does not conform to XLFD. Try to open the
2164 font and get XA_FONT property. */
2165 XFontStruct *xfont = XLoadQueryFont (display, names[0]);
2170 unsigned long value;
2173 if (XGetFontProperty (xfont, XA_FONT, &value)
2174 && (name = ((char *)
2175 XGetAtomName (display, (Atom) value))))
2177 if ((frame->font = mfont_parse_name (name, Mx)))
2180 XFreeFont (display, xfont);
2183 XFreeFontNames (names);
2186 frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
2189 face = mface_from_font (frame->font);
2190 face->property[MFACE_FONTSET] = mfontset (NULL);
2191 face->property[MFACE_FOREGROUND] = frame->foreground;
2192 face->property[MFACE_BACKGROUND] = frame->background;
2193 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2194 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2195 face->property[MFACE_VIDEOMODE] = frame->videomode;
2196 mface_put_prop (face, Mhook_func,
2197 mface_get_prop (mface__default, Mhook_func));
2198 face->property[MFACE_RATIO] = (void *) 100;
2199 mplist_push (param, Mface, face);
2200 M17N_OBJECT_UNREF (face);
2202 #ifdef X_SET_ERROR_HANDLER
2203 XSetErrorHandler (x_error_handler);
2204 XSetIOErrorHandler (x_io_error_handler);
2212 /* XIM (X Input Method) handler */
2214 typedef struct MInputXIMMethodInfo
2220 } MInputXIMMethodInfo;
2222 typedef struct MInputXIMContextInfo
2226 MConverter *converter;
2227 } MInputXIMContextInfo;
2230 xim_open_im (MInputMethod *im)
2232 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2233 MLocale *saved, *this;
2234 char *save_modifier_list;
2236 MInputXIMMethodInfo *im_info;
2238 saved = mlocale_set (LC_CTYPE, NULL);
2239 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2241 /* The specified locale is not supported. */
2242 MERROR (MERROR_LOCALE, -1);
2243 if (mlocale_get_prop (this, Mcoding) == Mnil)
2245 /* Unable to decode the output of XIM. */
2246 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2247 MERROR (MERROR_LOCALE, -1);
2250 if (arg->modifier_list)
2251 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2253 save_modifier_list = XSetLocaleModifiers ("");
2254 if (! save_modifier_list)
2256 /* The specified locale is not supported by X. */
2257 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2258 MERROR (MERROR_LOCALE, -1);
2261 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2264 /* No input method is available in the current locale. */
2265 XSetLocaleModifiers (save_modifier_list);
2266 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2267 MERROR (MERROR_WIN, -1);
2270 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2271 im_info->display = arg->display;
2273 im_info->language = mlocale_get_prop (this, Mlanguage);
2274 im_info->coding = mlocale_get_prop (this, Mcoding);
2277 XSetLocaleModifiers (save_modifier_list);
2278 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2284 xim_close_im (MInputMethod *im)
2286 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2288 XCloseIM (im_info->xim);
2293 xim_create_ic (MInputContext *ic)
2295 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2296 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2297 MInputXIMContextInfo *ic_info;
2300 if (! arg->input_style)
2302 /* By default, use Root style. */
2303 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2304 arg->preedit_attrs = NULL;
2305 arg->status_attrs = NULL;
2308 if (! arg->preedit_attrs && ! arg->status_attrs)
2309 xic = XCreateIC (im_info->xim,
2310 XNInputStyle, arg->input_style,
2311 XNClientWindow, arg->client_win,
2312 XNFocusWindow, arg->focus_win,
2314 else if (arg->preedit_attrs && ! arg->status_attrs)
2315 xic = XCreateIC (im_info->xim,
2316 XNInputStyle, arg->input_style,
2317 XNClientWindow, arg->client_win,
2318 XNFocusWindow, arg->focus_win,
2319 XNPreeditAttributes, arg->preedit_attrs,
2321 else if (! arg->preedit_attrs && arg->status_attrs)
2322 xic = XCreateIC (im_info->xim,
2323 XNInputStyle, arg->input_style,
2324 XNClientWindow, arg->client_win,
2325 XNFocusWindow, arg->focus_win,
2326 XNStatusAttributes, arg->status_attrs,
2329 xic = XCreateIC (im_info->xim,
2330 XNInputStyle, arg->input_style,
2331 XNClientWindow, arg->client_win,
2332 XNFocusWindow, arg->focus_win,
2333 XNPreeditAttributes, arg->preedit_attrs,
2334 XNStatusAttributes, arg->status_attrs,
2337 MERROR (MERROR_WIN, -1);
2339 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2341 ic_info->win = arg->focus_win;
2342 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2348 xim_destroy_ic (MInputContext *ic)
2350 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2352 XDestroyIC (ic_info->xic);
2353 mconv_free_converter (ic_info->converter);
2359 xim_filter (MInputContext *ic, MSymbol key, void *event)
2361 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2363 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2368 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2370 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2371 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2372 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2378 buf = (char *) alloca (512);
2379 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2380 if (status == XBufferOverflow)
2382 buf = (char *) alloca (len);
2383 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2386 mtext_reset (ic->produced);
2390 mconv_reset_converter (ic_info->converter);
2391 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2392 mconv_decode (ic_info->converter, ic->produced);
2393 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2394 Mlanguage, (void *) im_info->language);
2395 mtext_cpy (mt, ic->produced);
2396 mtext_reset (ic->produced);
2402 #ifdef X_SET_ERROR_HANDLER
2404 x_error_handler (Display *display, XErrorEvent *error)
2411 x_io_error_handler (Display *display)
2421 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
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 details.
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 details.
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 };