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 unsigned int sizes[2];
64 #define SET_SIZE(xfont, s) ((xfont)->sizes[(s) / 32] |= (1 << ((s) & 0x1F)))
65 #define HAVE_SIZE(xfont, s) ((xfont)->sizes[(s) / 32] & (1 << ((s) & 0x1F)))
74 /* Common header for the m17n object. */
79 /* If nonzero, <display> is opened by this library. Thus it should
80 be closed on freeing this structure. */
83 /** List of available X-core fonts on the display. Keys are
84 registries and values are plists whose keys are families and
85 values are pointers to MXFontList. */
88 /** List of available X-core fonts on the display. Keys are
89 families and values are pointers to MFont. For each MFont, only
90 these properties are important; FOUNDRY, FAMILY, REGISTRY. */
91 MPlist *base_font_list;
93 /** Nonzero means that <font_list> already contains all available
94 fonts on the display. */
97 /** Modifier bit masks of the display. */
104 /* Anchor of the chain of MDisplayInfo objects. */
105 static MPlist *display_info_list;
108 /* Color value and the corresponding GC. */
111 unsigned int rgb; /* (red << 16) | (green << 8) | blue */
118 GC_NORMAL = GC_INVERSE + 7,
131 /* The first 8 elements are indexed by an intensity for
132 anti-aliasing. The 2nd to 7th are created on demand. */
135 XftColor xft_color_fore, xft_color_back;
141 /* Common header for the m17n object. */
144 MDisplayInfo *display_info;
160 /** List of pointers to realized faces on the frame. */
161 MPlist *realized_face_list;
163 /* List of information about each font. Keys are font registries,
164 values are (MFontInfo *). */
165 MPlist *realized_font_list;
167 /** List of pointers to realized fontsets on the frame. */
168 MPlist *realized_fontset_list;
170 /** List of XColors vs GCs on the frame. */
174 static MPlist *device_list;
176 static MSymbol M_iso8859_1, M_iso10646_1;
178 #define FRAME_DEVICE(frame) ((MWDevice *) (frame)->device)
179 #define FRAME_DISPLAY(frame) (FRAME_DEVICE (frame)->display_info->display)
180 #define FRAME_SCREEN(frame) (FRAME_DEVICE (frame)->screen_num)
181 #define FRAME_CMAP(frame) (FRAME_DEVICE (frame)->cmap)
182 #define FRAME_VISUAL(frame) DefaultVisual (FRAME_DISPLAY (frame), \
183 FRAME_SCREEN (frame))
185 #define DEFAULT_FONT "-misc-fixed-medium-r-normal--*-120-*-*-*-*-iso8859-1"
186 #define FALLBACK_FONT "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1"
193 Boolean reverse_video;
194 } AppData, *AppDataPtr;
197 free_display_info (void *object)
199 MDisplayInfo *disp_info = (MDisplayInfo *) object;
202 MPLIST_DO (plist, disp_info->font_list)
204 MPLIST_DO (p, MPLIST_VAL (plist))
205 free (MPLIST_VAL (p));
206 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
208 M17N_OBJECT_UNREF (disp_info->font_list);
209 MPLIST_DO (plist, disp_info->base_font_list)
210 free (MPLIST_VAL (plist));
211 M17N_OBJECT_UNREF (disp_info->base_font_list);
213 if (disp_info->auto_display)
214 XCloseDisplay (disp_info->display);
220 free_device (void *object)
222 MWDevice *device = object;
225 for (plist = device->realized_fontset_list;
226 mplist_key (plist) != Mnil; plist = mplist_next (plist))
227 mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist));
228 M17N_OBJECT_UNREF (device->realized_fontset_list);
230 MPLIST_DO (plist, device->realized_font_list)
231 mfont__free_realized ((MRealizedFont *) MPLIST_VAL (plist));
232 M17N_OBJECT_UNREF (device->realized_font_list);
234 MPLIST_DO (plist, device->realized_face_list)
236 MRealizedFace *rface = MPLIST_VAL (plist);
239 mface__free_realized (rface);
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 (frame);
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 set_region (MFrame *frame, GC gc, MDrawRegion region)
413 unsigned long valuemask = GCForeground;
415 XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
416 FRAME_DEVICE (frame)->scratch_gc);
417 XSetRegion (FRAME_DISPLAY (frame), FRAME_DEVICE (frame)->scratch_gc, region);
418 return FRAME_DEVICE (frame)->scratch_gc;
422 /** X font handler */
424 static MRealizedFont *xfont_select (MFrame *, MFont *, MFont *, int);
425 static int xfont_open (MRealizedFont *);
426 static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int);
427 static unsigned xfont_encode_char (MRealizedFont *, unsigned);
428 static void xfont_render (MDrawWindow, int, int, MGlyphString *,
429 MGlyph *, MGlyph *, int, MDrawRegion);
430 static int xfont_list (MFrame *frame, MPlist *plist,
431 MFont *font, MSymbol language, int maxnum);
434 static MFontDriver xfont_driver =
435 { xfont_select, xfont_open,
436 xfont_find_metric, xfont_encode_char, xfont_render, xfont_list };
439 font_compare (const void *p1, const void *p2)
441 return strcmp (*(char **) p1, *(char **) p2);
445 xfont_registry_list (MFrame *frame, MSymbol registry)
447 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
448 MPlist *font_list = disp_info->font_list;
449 MPlist *base_font_list = disp_info->base_font_list;
452 char **font_names, **names;
456 MXFontList *xfont_table;
459 plist = mplist_get (font_list, registry);
463 mplist_add (font_list, registry, plist);
464 sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", msymbol_name (registry));
465 font_names = XListFonts (disp_info->display, pattern, 0x8000, &nfonts);
468 names = alloca (sizeof (char *) * nfonts);
469 memcpy (names, font_names, sizeof (char *) * nfonts);
470 qsort (names, nfonts, sizeof (char *), font_compare);
471 for (i = 0, p = NULL; i < nfonts; i++)
472 if (mfont__parse_name_into_font (names[i], Mx, (MFont *) &font) == 0
473 && (font.core.property[MFONT_SIZE] > 0
474 || font.core.property[MFONT_RESY] == 0))
476 MSymbol family = FONT_PROPERTY ((MFont *) &font, MFONT_FAMILY);
477 int size = font.core.property[MFONT_SIZE] / 10;
482 font.sizes[0] = font.sizes[1] = 0;
483 SET_SIZE (&font, size);
485 /* Handle fonts of the same base. */
486 for (base_end = names[i], fields = 0; *base_end; base_end++)
488 && ++fields == 7 /* PIXEL_SIZE */)
490 base_len = base_end - names[i] + 1;
491 for (j = i + 1; j < nfonts && ! strncmp (names[i], names[j], base_len);
493 if (mfont__parse_name_into_font (names[j], Mx, (MFont *) &font) == 0
494 && (font.core.property[MFONT_SIZE] > 0
495 || font.core.property[MFONT_RESY] == 0))
497 size = font.core.property[MFONT_SIZE] / 10;
498 SET_SIZE (&font, size);
501 if (p && MPLIST_KEY (p) != family)
502 p = mplist_find_by_key (plist, family);
504 xfont_table = MPLIST_VAL (p);
508 MSTRUCT_MALLOC (xfont_table, MERROR_WIN);
509 MLIST_INIT1 (xfont_table, fonts, 4);
510 mplist_push (p, family, xfont_table);
512 MLIST_APPEND1 (xfont_table, fonts, font, MERROR_WIN);
514 || (font.core.property[MFONT_FOUNDRY]
515 != bfont->property[MFONT_FOUNDRY])
516 || (font.core.property[MFONT_FAMILY]
517 != bfont->property[MFONT_FAMILY]))
519 MSTRUCT_MALLOC (bfont, MERROR_WIN);
521 for (j = MFONT_WEIGHT; j <= MFONT_ADSTYLE; j++)
522 bfont->property[j] = 0;
523 bfont->property[MFONT_SIZE] = bfont->property[MFONT_RESY] = 0;
524 mplist_push (base_font_list, family, bfont);
527 XFreeFontNames (font_names);
532 xfont_list_all (MFrame *frame)
534 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
535 MPlist *font_encoding_list, *p;
537 if (disp_info->all_fonts_scaned)
539 disp_info->all_fonts_scaned = 1;
540 font_encoding_list = mfont__encoding_list ();
541 if (! font_encoding_list)
543 MPLIST_DO (p, font_encoding_list)
544 xfont_registry_list (frame, MPLIST_KEY (p));
555 /* The X font driver function SELECT. */
557 static MRealizedFont *
558 xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
560 MSymbol family = FONT_PROPERTY (spec, MFONT_FAMILY);
561 MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
562 int requested_size = request->property[MFONT_SIZE];
563 MRealizedFont *rfont;
567 int best_score, score;
570 || ! strchr (MSYMBOL_NAME (registry), '-'))
573 plist = xfont_registry_list (frame, registry);
574 if (MPLIST_TAIL_P (plist))
576 best_score = -1, best_font = NULL;
577 MPLIST_DO (plist, plist)
579 if (family == Mnil || family == MPLIST_KEY (plist))
581 MXFontList *xfont_table = MPLIST_VAL (plist);
583 for (i = 0; i < xfont_table->used; i++)
585 MXFont *xfont = xfont_table->fonts + i;
586 MFont *font = (MFont *) xfont;
587 int size = requested_size / 10, s0, s1;
589 for (s0 = size; s0 > 0 && ! HAVE_SIZE (xfont, s0); s0--);
590 if (s0 * 10 == requested_size)
591 /* Exact size match. */
593 else if (xfont->sizes[0] & 1)
598 /* No smaller size font. Try a larger font. */
600 /* We can't use a larger font. */
602 for (s0 = size + 1; s0 < 64 && ! HAVE_SIZE (xfont, s0); s0++);
609 /* Check if there's a better larger size font. */
610 int size_limit = size + (size - s0);
612 s1 < size_limit && ! HAVE_SIZE (xfont, s1);
614 size = (s1 < size_limit ? s1 : s0);
616 font->property[MFONT_SIZE] = size * 10;
618 if ((score = mfont__score (font, spec, request,
620 && (best_score < 0 || score < best_score))
623 best_font = (MFont *) (xfont_table->fonts + i);
635 MSTRUCT_CALLOC (rfont, MERROR_WIN);
636 rfont->frame = frame;
638 rfont->request = *request;
639 rfont->font = *best_font;
640 if (best_font->property[MFONT_SIZE] == 0)
641 rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE];
642 rfont->score = best_score;
647 /* The X font driver function CLOSE. */
650 close_xfont (void *object)
652 MXFontInfo *xfont_info = object;
654 XFreeFont (xfont_info->display, xfont_info->xfont);
659 /* The X font driver function OPEN. */
662 xfont_open (MRealizedFont *rfont)
665 MXFontInfo *xfont_info;
666 MFrame *frame = rfont->frame;
667 int mdebug_mask = MDEBUG_FONT;
669 /* This never fail to generate a valid fontname because open_spec
670 should correspond to a font available on the system. */
671 name = mfont_unparse_name (&rfont->font, Mx);
672 M17N_OBJECT (xfont_info, close_xfont, MERROR_WIN);
673 xfont_info->display = FRAME_DISPLAY (frame);
674 xfont_info->xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
675 if (! xfont_info->xfont)
679 MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
683 rfont->info = xfont_info;
684 MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
687 rfont->ascent = xfont_info->xfont->ascent;
688 rfont->descent = xfont_info->xfont->descent;
690 rfont->fontp = xfont_info->xfont;
695 /* The X font driver function FIND_METRIC. */
698 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
701 MXFontInfo *xfont_info = rfont->info;
702 XFontStruct *xfont = xfont_info->xfont;
703 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
705 for (; g != gend; g++)
707 if (g->code == MCHAR_INVALID_CODE)
709 g->lbearing = xfont->max_bounds.lbearing;
710 g->rbearing = xfont->max_bounds.rbearing;
711 g->width = xfont->max_bounds.width;
712 g->ascent = xfont->ascent;
713 g->descent = xfont->descent;
717 int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
718 XCharStruct *pcm = NULL;
720 if (xfont->per_char != NULL)
722 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
725 && byte2 >= xfont->min_char_or_byte2
726 && byte2 <= xfont->max_char_or_byte2)
727 pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
731 if (byte1 >= xfont->min_byte1
732 && byte1 <= xfont->max_byte1
733 && byte2 >= xfont->min_char_or_byte2
734 && byte2 <= xfont->max_char_or_byte2)
736 pcm = (xfont->per_char
737 + ((xfont->max_char_or_byte2
738 - xfont->min_char_or_byte2 + 1)
739 * (byte1 - xfont->min_byte1))
740 + (byte2 - xfont->min_char_or_byte2));
747 g->lbearing = pcm->lbearing;
748 g->rbearing = pcm->rbearing;
749 g->width = pcm->width;
750 g->ascent = pcm->ascent;
751 g->descent = pcm->descent;
755 /* If the per_char pointer is null, all glyphs between
756 the first and last character indexes inclusive have
757 the same information, as given by both min_bounds and
760 g->rbearing = xfont->max_bounds.width;
761 g->width = xfont->max_bounds.width;
762 g->ascent = xfont->ascent;
763 g->descent = xfont->descent;
770 /* The X font driver function GET_GLYPH_ID. */
773 xfont_encode_char (MRealizedFont *rfont, unsigned code)
775 MXFontInfo *xfont_info;
777 unsigned min_byte1, max_byte1, min_byte2, max_byte2;
780 if (rfont->status < 0 || code >= 0x10000)
781 return MCHAR_INVALID_CODE;
782 if (rfont->status == 0)
784 if (xfont_open (rfont) < 0)
785 return MCHAR_INVALID_CODE;
787 xfont_info = rfont->info;
788 xfont = xfont_info->xfont;
789 all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
790 min_byte1 = xfont->min_byte1;
791 max_byte1 = xfont->max_byte1;
792 min_byte2 = xfont->min_char_or_byte2;
793 max_byte2 = xfont->max_char_or_byte2;
795 if (min_byte1 == 0 && max_byte1 == 0)
799 if (code < min_byte2 || code > max_byte2)
800 return MCHAR_INVALID_CODE;
803 pcm = xfont->per_char + (code - min_byte2);
804 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
805 ? code : MCHAR_INVALID_CODE);
809 unsigned byte1 = code >> 8, byte2 = code & 0xFF;
812 if (byte1 < min_byte1 || byte1 > max_byte1
813 || byte2 < min_byte2 || byte2 > max_byte2)
814 return MCHAR_INVALID_CODE;
818 pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
819 + (byte2 - min_byte2));
820 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
821 ? code : MCHAR_INVALID_CODE);
825 /* The X font driver function RENDER. */
828 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
829 MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
831 MRealizedFace *rface = from->rface;
832 MXFontInfo *xfont_info = rface->rfont->info;
835 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
842 /* It is assured that the all glyphs in the current range use the
843 same realized face. */
844 display = FRAME_DISPLAY (rface->frame);
847 gc = set_region (rface->frame, gc, region);
848 XSetFont (display, gc, xfont_info->xfont->fid);
849 code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
850 for (i = 0, g = from; g < to; i++, g++)
852 code[i].byte1 = g->code >> 8;
853 code[i].byte2 = g->code & 0xFF;
859 if (g->type == GLYPH_PAD)
861 else if (g->type == GLYPH_SPACE)
862 for (; g < to && g->type == GLYPH_SPACE; g++)
864 else if (! g->rface->rfont)
866 if ((g->c >= 0x200B && g->c <= 0x200F)
867 || (g->c >= 0x202A && g->c <= 0x202E))
871 /* As a font is not found for this character, draw an
873 int box_width = g->width;
874 int box_height = gstring->ascent + gstring->descent;
880 XDrawRectangle (display, (Window) win, gc,
881 x, y - gstring->ascent, box_width, box_height);
885 else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
887 XDrawString16 (display, (Window) win, gc,
888 x + g->xoff, y + g->yoff, code + (g - from), 1);
895 int code_idx = g - from;
898 g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
901 XDrawString16 (display, (Window) win, gc, orig_x, y,
908 xfont_list (MFrame *frame, MPlist *plist, MFont *font, MSymbol language,
911 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
912 MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil;
913 MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil;
917 if (registry != Mnil)
918 xfont_registry_list (frame, registry);
920 xfont_list_all (frame);
922 /* As we have not yet implemented the language check, return all
925 MPLIST_DO (p, disp_info->base_font_list)
927 mplist_add (plist, MPLIST_KEY (p), MPLIST_VAL (p));
934 MXFontList *xfontlist;
938 pl = disp_info->font_list;
939 if (registry != Mnil)
941 pl = mplist_find_by_key (pl, registry);
951 p = mplist_find_by_key (p, family);
957 xfontlist = MPLIST_VAL (p);
958 for (i = 0; i < xfontlist->used; i++)
960 xfont = xfontlist->fonts + i;
961 if (mfont__match_p (&xfont->core, font, MFONT_REGISTRY))
963 mplist_add (plist, MPLIST_KEY (p), &xfont->core);
972 if (registry != Mnil)
992 static int xft_open (MRealizedFont *);
993 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
994 static void xft_render (MDrawWindow, int, int, MGlyphString *,
995 MGlyph *, MGlyph *, int, MDrawRegion);
997 MFontDriver xft_driver =
998 { NULL, /* Set to ft_select in device_init (). */
999 xft_open, xft_find_metric,
1000 NULL, /* Set to ft_encode_char in device_init (). */
1002 NULL /* Set to ft_list in device_init (). */
1007 close_xft (void *object)
1009 MXftFontInfo *font_info = object;
1011 XftFontClose (font_info->display, font_info->font_aa);
1012 XftFontClose (font_info->display, font_info->font_no_aa);
1018 xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
1020 XftPattern *pattern;
1021 XftFontInfo *xft_font_info;
1024 pattern = XftPatternCreate ();
1025 XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
1026 XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
1027 XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
1028 xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
1029 if (! xft_font_info)
1031 font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
1032 XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
1038 xft_open (MRealizedFont *rfont)
1042 MXftFontInfo *font_info;
1045 if ((mfont__ft_driver.open) (rfont) < 0)
1048 size = rfont->font.property[MFONT_SIZE] / 10;
1049 frame = rfont->frame;
1051 ft_info = rfont->info;
1052 M17N_OBJECT (font_info, close_xft, MERROR_WIN);
1053 ft_info->extra_info = font_info;
1054 font_info->display = FRAME_DISPLAY (frame);
1055 font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
1056 if (font_info->font_aa)
1058 font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
1059 if (font_info->font_no_aa)
1062 rfont->fontp = font_info->font_no_aa;
1065 XftFontClose (FRAME_DISPLAY (rfont->frame), font_info->font_aa);
1068 ft_info->extra_info = NULL;
1075 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1078 MFTInfo *ft_info = rfont->info;
1079 MXftFontInfo *font_info = ft_info->extra_info;
1080 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1082 for (; g != gend; g++)
1084 if (g->code == MCHAR_INVALID_CODE)
1086 MGlyph *start = g++;
1088 while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
1089 (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
1097 XftGlyphExtents (FRAME_DISPLAY (gstring->frame),
1098 font_info->font_aa, &g->code, 1, &extents);
1099 g->lbearing = - extents.x;
1100 g->rbearing = extents.width - extents.x;
1101 g->width = extents.xOff;
1102 g->ascent = extents.y;
1103 g->descent = extents.height - extents.y;
1110 xft_render (MDrawWindow win, int x, int y,
1111 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1112 int reverse, MDrawRegion region)
1114 MRealizedFace *rface = from->rface;
1115 MFrame *frame = rface->frame;
1116 MFTInfo *ft_info = rface->rfont->info;
1117 MXftFontInfo *font_info = ft_info->extra_info;
1118 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1119 XftColor *xft_color = (! reverse
1120 ? &((GCInfo *) rface->info)->xft_color_fore
1121 : &((GCInfo *) rface->info)->xft_color_back);
1122 XftFont *xft_font = (gstring->control.anti_alias
1123 && FRAME_DEVICE (frame)->depth > 1
1124 ? font_info->font_aa : font_info->font_no_aa);
1133 XftDrawChange (xft_draw, (Drawable) win);
1134 XftDrawSetClip (xft_draw, (Region) region);
1136 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1137 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1139 if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1140 glyphs[nglyphs++] = g->code;
1144 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1145 last_x, y, glyphs, nglyphs);
1147 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1148 x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1149 last_x = x + g->width;
1153 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1159 /* Functions for the device driver. */
1162 mwin__close_device (MFrame *frame)
1164 M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
1168 mwin__device_get_prop (MFrame *frame, MSymbol key)
1170 MWDevice *device = FRAME_DEVICE (frame);
1172 if (key == Mdisplay)
1173 return (void *) device->display_info->display;
1175 return (void *) ScreenOfDisplay(device->display_info->display,
1176 device->screen_num);
1177 if (key == Mcolormap)
1178 return (void *) device->cmap;
1180 return (void *) device->depth;
1185 mwin__realize_face (MRealizedFace *rface)
1188 MSymbol foreground, background, videomode;
1189 MFaceHLineProp *hline;
1193 if (rface != rface->ascii_rface)
1195 rface->info = rface->ascii_rface->info;
1199 frame = rface->frame;
1200 MSTRUCT_CALLOC (info, MERROR_WIN);
1202 foreground = rface->face.property[MFACE_FOREGROUND];
1203 background = rface->face.property[MFACE_BACKGROUND];
1204 videomode = rface->face.property[MFACE_VIDEOMODE];
1206 videomode = frame->videomode;
1207 if (videomode != Mreverse)
1209 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1210 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1214 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1215 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1218 if (foreground == Mnil)
1219 foreground = frame->foreground;
1220 if (background == Mnil)
1221 background = frame->background;
1222 if (videomode == Mreverse)
1224 MSymbol temp = foreground;
1225 foreground = background;
1228 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1229 FRAME_VISUAL (frame),
1231 MSYMBOL_NAME (foreground),
1232 &info->xft_color_fore))
1234 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1235 FRAME_VISUAL (frame),
1237 MSYMBOL_NAME (background),
1238 &info->xft_color_back))
1242 hline = rface->hline;
1246 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1248 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1255 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1257 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1259 if (box->color_left && box->color_left != box->color_top)
1260 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1262 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1264 if (box->color_bottom && box->color_bottom != box->color_top)
1265 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1267 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1269 if (box->color_right && box->color_right != box->color_bottom)
1270 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1272 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1280 mwin__free_realized_face (MRealizedFace *rface)
1282 if (rface == rface->ascii_rface)
1288 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1290 int x, int y, int width, int height, MDrawRegion region)
1292 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1295 gc = set_region (frame, gc, region);
1297 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1298 x, y, width, height);
1303 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1304 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1305 int reverse, MDrawRegion region)
1307 MRealizedFace *rface = from->rface;
1308 Display *display = FRAME_DISPLAY (rface->frame);
1309 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1315 gc = set_region (rface->frame, gc, region);
1316 for (; from < to; from++)
1318 XDrawRectangle (display, (Window) win, gc,
1319 x, y - gstring->ascent + 1, from->width - 1,
1320 gstring->ascent + gstring->descent - 2);
1327 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1328 MRealizedFace *rface, int reverse,
1329 int x, int y, int width, MDrawRegion region)
1331 enum MFaceHLineType type = rface->hline->type;
1332 GCInfo *info = rface->info;
1333 GC gc = gc = info->gc[GC_HLINE];
1336 y = (type == MFACE_HLINE_BOTTOM
1337 ? y + gstring->text_descent - rface->hline->width
1338 : type == MFACE_HLINE_UNDER
1340 : type == MFACE_HLINE_STRIKE_THROUGH
1341 ? y - ((gstring->ascent + gstring->descent) / 2)
1342 : y - gstring->text_ascent);
1344 gc = set_region (frame, gc, region);
1346 for (i = 0; i < rface->hline->width; i++)
1347 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1348 x, y + i, x + width - 1, y + i);
1353 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1354 MGlyph *g, int x, int y, int width, MDrawRegion region)
1356 Display *display = FRAME_DISPLAY (frame);
1357 MRealizedFace *rface = g->rface;
1358 MFaceBoxProp *box = rface->box;
1359 GCInfo *info = rface->info;
1360 GC gc_top, gc_left, gc_right, gc_btm;
1364 y0 = y - (gstring->text_ascent
1365 + rface->box->inner_vmargin + rface->box->width);
1366 y1 = y + (gstring->text_descent
1367 + rface->box->inner_vmargin + rface->box->width - 1);
1369 gc_top = info->gc[GC_BOX_TOP];
1371 gc_top = set_region (frame, gc_top, region);
1372 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1375 gc_btm = info->gc[GC_BOX_BOTTOM];
1377 if (g->type == GLYPH_BOX)
1381 if (g->left_padding)
1382 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1384 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1386 /* Draw the top side. */
1387 for (i = 0; i < box->width; i++)
1388 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1390 /* Draw the bottom side. */
1391 if (region && gc_btm != gc_top)
1392 gc_btm = set_region (frame, gc_btm, region);
1393 for (i = 0; i < box->width; i++)
1394 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1396 if (g->left_padding > 0)
1398 /* Draw the left side. */
1399 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1403 gc_left = info->gc[GC_BOX_LEFT];
1405 gc_left = set_region (frame, gc_left, region);
1407 for (i = 0; i < rface->box->width; i++)
1408 XDrawLine (display, (Window) win, gc_left,
1409 x0 + i, y0 + i, x0 + i, y1 - i);
1413 /* Draw the right side. */
1414 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1418 gc_right = info->gc[GC_BOX_RIGHT];
1420 gc_right = set_region (frame, gc_right, region);
1422 for (i = 0; i < rface->box->width; i++)
1423 XDrawLine (display, (Window) win, gc_right,
1424 x1 - i, y0 + i, x1 - i, y1 - i);
1429 /* Draw the top side. */
1430 for (i = 0; i < box->width; i++)
1431 XDrawLine (display, (Window) win, gc_top,
1432 x, y0 + i, x + width - 1, y0 + i);
1434 /* Draw the bottom side. */
1435 if (region && gc_btm != gc_top)
1436 gc_btm = set_region (frame, gc_btm, region);
1437 for (i = 0; i < box->width; i++)
1438 XDrawLine (display, (Window) win, gc_btm,
1439 x, y1 - i, x + width - 1, y1 - i);
1446 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1447 int reverse, int x, int y,
1448 int width, int height, int row_bytes, unsigned char *bmp,
1451 Display *display = FRAME_DISPLAY (frame);
1453 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1456 gc = set_region (frame, gc, region);
1458 for (i = 0; i < height; i++, bmp += row_bytes)
1459 for (j = 0; j < width; j++)
1460 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1461 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1466 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1467 int intensity, MDrawPoint *points, int num,
1470 GCInfo *info = rface->info;
1473 if (! (gc = info->gc[intensity]))
1474 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1477 gc = set_region (frame, gc, region);
1479 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1480 (XPoint *) points, num, CoordModeOrigin);
1485 mwin__region_from_rect (MDrawMetric *rect)
1487 MDrawRegion region1 = XCreateRegion ();
1488 MDrawRegion region2 = XCreateRegion ();
1493 xrect.width = rect->width;
1494 xrect.height = rect->height;
1495 XUnionRectWithRegion (&xrect, region1, region2);
1496 XDestroyRegion (region1);
1501 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1503 MDrawRegion region1 = XCreateRegion ();
1508 xrect.width = rect->width;
1509 xrect.height = rect->height;
1511 XUnionRegion (region, region, region1);
1512 XUnionRectWithRegion (&xrect, region1, region);
1513 XDestroyRegion (region1);
1517 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1519 MDrawRegion region = XCreateRegion ();
1521 XUnionRegion (region1, region1, region);
1522 XIntersectRegion (region, region2, region1);
1523 XDestroyRegion (region);
1527 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1529 MDrawRegion region1 = XCreateRegion ();
1534 xrect.width = rect->width;
1535 xrect.height = rect->height;
1536 XUnionRectWithRegion (&xrect, region1, region);
1537 XDestroyRegion (region1);
1541 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1545 XClipBox (region, &xrect);
1548 rect->width = xrect.width;
1549 rect->height = xrect.height;
1553 mwin__free_region (MDrawRegion region)
1555 XDestroyRegion (region);
1559 mwin__dump_region (MDrawRegion region)
1562 XClipBox (region, &rect);
1563 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1568 mwin__create_window (MFrame *frame, MDrawWindow parent)
1570 Display *display = FRAME_DISPLAY (frame);
1572 XWMHints wm_hints = { InputHint, False };
1573 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1574 XSetWindowAttributes set_attrs;
1577 GCInfo *info = frame->rface->info;
1580 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1581 mask = GCForeground;
1582 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1583 set_attrs.background_pixel = values.foreground;
1584 set_attrs.backing_store = Always;
1585 set_attrs.override_redirect = True;
1586 set_attrs.save_under = True;
1587 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1588 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1589 CopyFromParent, InputOutput, CopyFromParent,
1591 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1592 NULL, &wm_hints, &class_hints);
1593 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1594 return (MDrawWindow) win;
1598 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1600 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1605 mwin__event_window (void *event)
1607 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1611 mwin__print_event (void *arg, char *win_name)
1614 XEvent *event = (XEvent *) arg;
1616 switch (event->xany.type)
1618 case 2: event_name = "KeyPress"; break;
1619 case 3: event_name = "KeyRelease"; break;
1620 case 4: event_name = "ButtonPress"; break;
1621 case 5: event_name = "ButtonRelease"; break;
1622 case 6: event_name = "MotionNotify"; break;
1623 case 7: event_name = "EnterNotify"; break;
1624 case 8: event_name = "LeaveNotify"; break;
1625 case 9: event_name = "FocusIn"; break;
1626 case 10: event_name = "FocusOut"; break;
1627 case 11: event_name = "KeymapNotify"; break;
1628 case 12: event_name = "Expose"; break;
1629 case 13: event_name = "GraphicsExpose"; break;
1630 case 14: event_name = "NoExpose"; break;
1631 case 15: event_name = "VisibilityNotify"; break;
1632 case 16: event_name = "CreateNotify"; break;
1633 case 17: event_name = "DestroyNotify"; break;
1634 case 18: event_name = "UnmapNotify"; break;
1635 case 19: event_name = "MapNotify"; break;
1636 case 20: event_name = "MapRequest"; break;
1637 case 21: event_name = "ReparentNotify"; break;
1638 case 22: event_name = "ConfigureNotify"; break;
1639 case 23: event_name = "ConfigureRequest"; break;
1640 case 24: event_name = "GravityNotify"; break;
1641 case 25: event_name = "ResizeRequest"; break;
1642 case 26: event_name = "CirculateNotify"; break;
1643 case 27: event_name = "CirculateRequest"; break;
1644 case 28: event_name = "PropertyNotify"; break;
1645 case 29: event_name = "SelectionClear"; break;
1646 case 30: event_name = "SelectionRequest"; break;
1647 case 31: event_name = "SelectionNotify"; break;
1648 case 32: event_name = "ColormapNotify"; break;
1649 case 33: event_name = "ClientMessage"; break;
1650 case 34: event_name = "MappingNotify"; break;
1651 default: event_name = "unknown";
1654 fprintf (stderr, "%s: %s\n", win_name, event_name);
1659 mwin__map_window (MFrame *frame, MDrawWindow win)
1661 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1665 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1667 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1671 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1672 MDrawMetric *geometry)
1674 Display *display = FRAME_DISPLAY (frame);
1675 XWindowAttributes attr;
1676 Window parent = (Window) parent_win, root;
1678 XGetWindowAttributes (display, (Window) win, &attr);
1679 geometry->x = attr.x + attr.border_width;
1680 geometry->y = attr.y + attr.border_width;
1681 geometry->width = attr.width;
1682 geometry->height = attr.height;
1685 parent = RootWindow (display, FRAME_SCREEN (frame));
1688 Window this_parent, *children;
1691 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1694 if (this_parent == parent || this_parent == root)
1696 win = (MDrawWindow) this_parent;
1697 XGetWindowAttributes (display, (Window) win, &attr);
1698 geometry->x += attr.x + attr.border_width;
1699 geometry->y += attr.y + attr.border_width;
1704 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1705 MDrawMetric *current, MDrawMetric *new)
1707 Display *display = FRAME_DISPLAY (frame);
1708 unsigned int mask = 0;
1709 XWindowChanges values;
1711 if (current->width != new->width)
1714 if (new->width <= 0)
1716 values.width = current->width = new->width;
1718 if (current->height != new->height)
1721 if (new->height <= 0)
1723 values.height = current->height = new->height;
1725 if (current->x != new->x)
1728 values.x = current->x = new->x;
1730 if (current->y != new->y)
1733 current->y = new->y;
1734 values.y = current->y = new->y;
1737 XConfigureWindow (display, (Window) win, mask, &values);
1738 XClearWindow (display, (Window) win);
1742 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1744 XEvent *event = (XEvent *) arg;
1745 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1752 if (event->xany.type != KeyPress
1753 /* && event->xany.type != KeyRelease */
1756 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1763 if (c < XK_space || c > XK_asciitilde)
1765 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1766 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1767 if (((XKeyEvent *) event)->state & ControlMask)
1769 if (c >= 'a' && c <= 'z')
1771 if (c >= ' ' && c < 127)
1772 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1774 key = minput__char_to_key (c);
1776 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1780 char *str = XKeysymToString (keysym);
1784 key = msymbol (str);
1785 if (((XKeyEvent *) event)->state & ShiftMask)
1786 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1787 if (((XKeyEvent *) event)->state & ControlMask)
1788 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1790 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1791 *modifiers |= MINPUT_KEY_META_MODIFIER;
1792 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1793 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1794 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1795 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1796 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1797 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1804 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1806 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1808 Display *display = FRAME_DISPLAY (frame);
1809 GCInfo *info = rface->info;
1812 for (i = 0; i <= GC_INVERSE; i++)
1814 XGetGCValues (display, info->gc[i], valuemask, &values);
1815 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1816 values.foreground, values.background);
1817 fprintf (stderr, "\n");
1821 static MDeviceDriver x_driver =
1824 mwin__device_get_prop,
1826 mwin__free_realized_face,
1828 mwin__draw_empty_boxes,
1832 mwin__region_from_rect,
1833 mwin__union_rect_with_region,
1834 mwin__intersect_region,
1835 mwin__region_add_rect,
1836 mwin__region_to_rect,
1839 mwin__create_window,
1840 mwin__destroy_window,
1843 mwin__window_geometry,
1844 mwin__adjust_window,
1848 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1853 M_iso8859_1 = msymbol ("iso8859-1");
1854 M_iso10646_1 = msymbol ("iso10646-1");
1856 display_info_list = mplist ();
1857 device_list = mplist ();
1860 xft_driver.select = mfont__ft_driver.select;
1861 xft_driver.encode_char = mfont__ft_driver.encode_char;
1862 xft_driver.list = mfont__ft_driver.list;
1865 Mxim = msymbol ("xim");
1866 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1874 M17N_OBJECT_UNREF (display_info_list);
1875 M17N_OBJECT_UNREF (device_list);
1879 /** Return an MWDevice object corresponding to a display specified in
1882 It searches device_list for a device matching the display. If
1883 found, return the found object. Otherwise, return a newly created
1887 device_open (MFrame *frame, MPlist *param)
1889 Display *display = NULL;
1890 Screen *screen = NULL;
1892 Drawable drawable = 0;
1893 Widget widget = NULL;
1895 int auto_display = 0;
1896 MDisplayInfo *disp_info = NULL;
1897 MWDevice *device = NULL;
1899 XWindowAttributes attr;
1904 int use_xfont = 0, use_freetype = 0, use_xft = 0;
1906 for (plist = param; (key = mplist_key (plist)) != Mnil;
1907 plist = mplist_next (plist))
1909 if (key == Mdisplay)
1910 display = (Display *) mplist_value (plist);
1911 else if (key == Mscreen)
1912 screen = mplist_value (plist);
1913 else if (key == Mdrawable)
1914 drawable = (Drawable) mplist_value (plist);
1915 else if (key == Mdepth)
1916 depth = (unsigned) mplist_value (plist);
1917 else if (key == Mwidget)
1918 widget = (Widget) mplist_value (plist);
1919 else if (key == Mcolormap)
1920 cmap = (Colormap) mplist_value (plist);
1921 else if (key == Mfont)
1923 MSymbol val = MPLIST_SYMBOL (plist);
1927 #ifdef HAVE_FREETYPE
1928 else if (val == Mfreetype)
1931 else if (val == Mxft)
1938 /* If none of them is specified, use all of them. */
1939 if (! use_xfont && ! use_freetype && ! use_xft)
1940 use_xfont = use_freetype = use_xft = 1;
1944 display = XtDisplay (widget);
1945 screen_num = XScreenNumberOfScreen (XtScreen (widget));
1946 depth = DefaultDepth (display, screen_num);
1952 unsigned width, height, border_width;
1955 MERROR (MERROR_WIN, -1);
1956 XGetGeometry (display, drawable, &root_window,
1957 &x, &y, &width, &height, &border_width, &depth);
1958 XGetWindowAttributes (display, root_window, &attr);
1959 screen_num = XScreenNumberOfScreen (attr.screen);
1964 display = DisplayOfScreen (screen);
1969 display = XOpenDisplay (NULL);
1971 MERROR (MERROR_WIN, -1);
1974 screen = DefaultScreenOfDisplay (display);
1976 screen_num = XScreenNumberOfScreen (screen);
1978 depth = DefaultDepth (display, screen_num);
1982 cmap = DefaultColormap (display, screen_num);
1984 for (plist = display_info_list; mplist_key (plist) != Mnil;
1985 plist = mplist_next (plist))
1987 disp_info = (MDisplayInfo *) mplist_value (plist);
1988 if (disp_info->display == display)
1992 if (mplist_key (plist) != Mnil)
1993 M17N_OBJECT_REF (disp_info);
1996 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
1997 disp_info->display = display;
1998 disp_info->auto_display = auto_display;
1999 disp_info->font_list = mplist ();
2000 disp_info->base_font_list = mplist ();
2001 find_modifier_bits (disp_info);
2002 mplist_add (display_info_list, Mt, disp_info);
2005 for (plist = device_list; mplist_key (plist) != Mnil;
2006 plist = mplist_next (plist))
2008 device = (MWDevice *) mplist_value (plist);
2009 if (device->display_info == disp_info
2010 && device->depth == depth
2011 && device->cmap == cmap)
2015 if (mplist_key (plist) != Mnil)
2016 M17N_OBJECT_REF (device);
2019 unsigned long valuemask = GCForeground;
2022 M17N_OBJECT (device, free_device, MERROR_WIN);
2023 device->display_info = disp_info;
2024 device->screen_num = screen_num;
2025 /* A drawable on which to create GCs. */
2026 device->drawable = XCreatePixmap (display,
2027 RootWindow (display, screen_num),
2029 device->depth = depth;
2030 device->cmap = cmap;
2031 device->realized_face_list = mplist ();
2032 device->realized_font_list = mplist ();
2033 device->realized_fontset_list = mplist ();
2034 device->gc_list = mplist ();
2035 values.foreground = BlackPixel (display, screen_num);
2036 device->scratch_gc = XCreateGC (display, device->drawable,
2037 valuemask, &values);
2039 device->xft_draw = XftDrawCreate (display, device->drawable,
2040 DefaultVisual (display, screen_num),
2045 frame->device = device;
2046 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2047 frame->driver = &x_driver;
2048 frame->font_driver_list = mplist ();
2052 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2055 #endif /* HAVE_XFT2 */
2056 #ifdef HAVE_FREETYPE
2058 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2059 #endif /* HAVE_FREETYPE */
2060 if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list))
2061 mplist_push (frame->font_driver_list, Mx, &xfont_driver);
2063 frame->realized_font_list = device->realized_font_list;
2064 frame->realized_face_list = device->realized_face_list;
2065 frame->realized_fontset_list = device->realized_fontset_list;
2069 XtResource resources[] = {
2070 { XtNfont, XtCFont, XtRString, sizeof (String),
2071 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2072 { XtNforeground, XtCForeground, XtRString, sizeof (String),
2073 XtOffset (AppDataPtr, foreground), XtRString, "black" },
2074 { XtNbackground, XtCBackground, XtRString, sizeof (String),
2075 XtOffset (AppDataPtr, background), XtRString, "white" },
2076 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2077 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2080 XtGetApplicationResources (widget, &app_data,
2081 resources, XtNumber (resources), NULL, 0);
2082 frame->foreground = msymbol (app_data.foreground);
2083 frame->background = msymbol (app_data.background);
2084 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2088 app_data.font = DEFAULT_FONT;
2089 frame->foreground = msymbol ("black");
2090 frame->background = msymbol ("white");
2091 frame->videomode = Mnormal;
2096 char **names = XListFonts (display, app_data.font, 1, &nfonts);
2100 if (! (frame->font = mfont_parse_name (names[0], Mx)))
2102 /* The font name does not conform to XLFD. Try to open the
2103 font and get XA_FONT property. */
2104 XFontStruct *xfont = XLoadQueryFont (display, names[0]);
2109 unsigned long value;
2112 if (XGetFontProperty (xfont, XA_FONT, &value)
2113 && (name = ((char *)
2114 XGetAtomName (display, (Atom) value))))
2116 if ((frame->font = mfont_parse_name (name, Mx)))
2119 XFreeFont (display, xfont);
2122 XFreeFontNames (names);
2125 frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
2128 face = mface_from_font (frame->font);
2129 face->property[MFACE_FONTSET] = mfontset (NULL);
2130 face->property[MFACE_FOREGROUND] = frame->foreground;
2131 face->property[MFACE_BACKGROUND] = frame->background;
2132 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2133 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2134 face->property[MFACE_VIDEOMODE] = frame->videomode;
2135 mface_put_prop (face, Mhook_func,
2136 mface_get_prop (mface__default, Mhook_func));
2137 face->property[MFACE_RATIO] = (void *) 100;
2138 mplist_push (param, Mface, face);
2139 M17N_OBJECT_UNREF (face);
2141 #ifdef X_SET_ERROR_HANDLER
2142 XSetErrorHandler (x_error_handler);
2143 XSetIOErrorHandler (x_io_error_handler);
2151 /* XIM (X Input Method) handler */
2153 typedef struct MInputXIMMethodInfo
2159 } MInputXIMMethodInfo;
2161 typedef struct MInputXIMContextInfo
2165 MConverter *converter;
2166 } MInputXIMContextInfo;
2169 xim_open_im (MInputMethod *im)
2171 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2172 MLocale *saved, *this;
2173 char *save_modifier_list;
2175 MInputXIMMethodInfo *im_info;
2177 saved = mlocale_set (LC_CTYPE, NULL);
2178 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2180 /* The specified locale is not supported. */
2181 MERROR (MERROR_LOCALE, -1);
2182 if (mlocale_get_prop (this, Mcoding) == Mnil)
2184 /* Unable to decode the output of XIM. */
2185 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2186 MERROR (MERROR_LOCALE, -1);
2189 if (arg->modifier_list)
2190 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2192 save_modifier_list = XSetLocaleModifiers ("");
2193 if (! save_modifier_list)
2195 /* The specified locale is not supported by X. */
2196 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2197 MERROR (MERROR_LOCALE, -1);
2200 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2203 /* No input method is available in the current locale. */
2204 XSetLocaleModifiers (save_modifier_list);
2205 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2206 MERROR (MERROR_WIN, -1);
2209 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2210 im_info->display = arg->display;
2212 im_info->language = mlocale_get_prop (this, Mlanguage);
2213 im_info->coding = mlocale_get_prop (this, Mcoding);
2216 XSetLocaleModifiers (save_modifier_list);
2217 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2223 xim_close_im (MInputMethod *im)
2225 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2227 XCloseIM (im_info->xim);
2232 xim_create_ic (MInputContext *ic)
2234 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2235 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2236 MInputXIMContextInfo *ic_info;
2239 if (! arg->input_style)
2241 /* By default, use Root style. */
2242 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2243 arg->preedit_attrs = NULL;
2244 arg->status_attrs = NULL;
2247 if (! arg->preedit_attrs && ! arg->status_attrs)
2248 xic = XCreateIC (im_info->xim,
2249 XNInputStyle, arg->input_style,
2250 XNClientWindow, arg->client_win,
2251 XNFocusWindow, arg->focus_win,
2253 else if (arg->preedit_attrs && ! arg->status_attrs)
2254 xic = XCreateIC (im_info->xim,
2255 XNInputStyle, arg->input_style,
2256 XNClientWindow, arg->client_win,
2257 XNFocusWindow, arg->focus_win,
2258 XNPreeditAttributes, arg->preedit_attrs,
2260 else if (! arg->preedit_attrs && arg->status_attrs)
2261 xic = XCreateIC (im_info->xim,
2262 XNInputStyle, arg->input_style,
2263 XNClientWindow, arg->client_win,
2264 XNFocusWindow, arg->focus_win,
2265 XNStatusAttributes, arg->status_attrs,
2268 xic = XCreateIC (im_info->xim,
2269 XNInputStyle, arg->input_style,
2270 XNClientWindow, arg->client_win,
2271 XNFocusWindow, arg->focus_win,
2272 XNPreeditAttributes, arg->preedit_attrs,
2273 XNStatusAttributes, arg->status_attrs,
2276 MERROR (MERROR_WIN, -1);
2278 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2280 ic_info->win = arg->focus_win;
2281 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2287 xim_destroy_ic (MInputContext *ic)
2289 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2291 XDestroyIC (ic_info->xic);
2292 mconv_free_converter (ic_info->converter);
2298 xim_filter (MInputContext *ic, MSymbol key, void *event)
2300 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2302 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2307 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2309 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2310 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2311 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2317 buf = (char *) alloca (512);
2318 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2319 if (status == XBufferOverflow)
2321 buf = (char *) alloca (len);
2322 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2325 mtext_reset (ic->produced);
2329 mconv_reset_converter (ic_info->converter);
2330 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2331 mconv_decode (ic_info->converter, ic->produced);
2332 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2333 Mlanguage, (void *) im_info->language);
2334 mtext_cpy (mt, ic->produced);
2335 mtext_reset (ic->produced);
2341 #ifdef X_SET_ERROR_HANDLER
2343 x_error_handler (Display *display, XErrorEvent *error)
2350 x_io_error_handler (Display *display)
2360 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2364 /*** @addtogroup m17nInputMethodWin */
2369 @brief Input method driver for XIM.
2371 The driver #minput_xim_driver is for the foreign input method of
2372 name #Mxim. It uses XIM (X Input Methods) as a background input
2375 As the symbol #Mxim has property #Minput_driver whose value is
2376 a pointer to this driver, the input method of language #Mnil
2377 and name #Mxim uses this driver.
2379 Therefore, for such input methods, the driver dependent arguments
2380 to the functions whose name begin with minput_ must be as follows.
2382 The argument $ARG of the function minput_open_im () must be a
2383 pointer to the structure #MInputXIMArgIM. See the documentation
2384 of #MInputXIMArgIM for more details.
2386 The argument $ARG of the function minput_create_ic () must be a
2387 pointer to the structure #MInputXIMArgIC. See the documentation
2388 of #MInputXIMArgIC for more details.
2390 The argument $ARG of the function minput_filter () must be a
2391 pointer to the structure @c XEvent. The argument $KEY is ignored.
2393 The argument $ARG of the function minput_lookup () must be the
2394 same one as that of the function minput_filter (). The argument
2398 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2400 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
2401 ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
2404 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2405 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
2406 ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2408 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
2409 ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2411 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM ¤Ø¤Î¥Ý
2412 ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
2415 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC ¤Ø¤Î
2416 ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
2419 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2420 ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2422 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2423 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2426 MInputDriver minput_xim_driver =
2427 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2428 xim_filter, xim_lookup, NULL };