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];
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)
596 else if (limited_size)
597 /* We can't use a larger font. */
601 for (s0 = size + 1; s0 < 64 && ! HAVE_SIZE (xfont, s0); s0++);
608 for (s1 = size + (size - s0) - 1;
609 s1 > size && HAVE_SIZE (xfont, s1); s1++);
610 size = (s1 > size ? s1 : s0);
612 font->property[MFONT_SIZE] = size * 10;
614 if ((score = mfont__score (font, spec, request,
616 && (best_score < 0 || score < best_score))
619 best_font = (MFont *) (xfont_table->fonts + i);
631 MSTRUCT_CALLOC (rfont, MERROR_WIN);
632 rfont->frame = frame;
634 rfont->request = *request;
635 rfont->font = *best_font;
636 if (best_font->property[MFONT_SIZE] == 0)
637 rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE];
638 rfont->score = best_score;
643 /* The X font driver function CLOSE. */
646 close_xfont (void *object)
648 MXFontInfo *xfont_info = object;
650 XFreeFont (xfont_info->display, xfont_info->xfont);
655 /* The X font driver function OPEN. */
658 xfont_open (MRealizedFont *rfont)
661 MXFontInfo *xfont_info;
662 MFrame *frame = rfont->frame;
663 int mdebug_mask = MDEBUG_FONT;
665 /* This never fail to generate a valid fontname because open_spec
666 should correspond to a font available on the system. */
667 name = mfont_unparse_name (&rfont->font, Mx);
668 M17N_OBJECT (xfont_info, close_xfont, MERROR_WIN);
669 xfont_info->display = FRAME_DISPLAY (frame);
670 xfont_info->xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
671 if (! xfont_info->xfont)
675 MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
679 rfont->info = xfont_info;
680 MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
683 rfont->ascent = xfont_info->xfont->ascent;
684 rfont->descent = xfont_info->xfont->descent;
686 rfont->fontp = xfont_info->xfont;
691 /* The X font driver function FIND_METRIC. */
694 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
697 MXFontInfo *xfont_info = rfont->info;
698 XFontStruct *xfont = xfont_info->xfont;
699 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
701 for (; g != gend; g++)
703 if (g->code == MCHAR_INVALID_CODE)
705 g->lbearing = xfont->max_bounds.lbearing;
706 g->rbearing = xfont->max_bounds.rbearing;
707 g->width = xfont->max_bounds.width;
708 g->ascent = xfont->ascent;
709 g->descent = xfont->descent;
713 int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
714 XCharStruct *pcm = NULL;
716 if (xfont->per_char != NULL)
718 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
721 && byte2 >= xfont->min_char_or_byte2
722 && byte2 <= xfont->max_char_or_byte2)
723 pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
727 if (byte1 >= xfont->min_byte1
728 && byte1 <= xfont->max_byte1
729 && byte2 >= xfont->min_char_or_byte2
730 && byte2 <= xfont->max_char_or_byte2)
732 pcm = (xfont->per_char
733 + ((xfont->max_char_or_byte2
734 - xfont->min_char_or_byte2 + 1)
735 * (byte1 - xfont->min_byte1))
736 + (byte2 - xfont->min_char_or_byte2));
743 g->lbearing = pcm->lbearing;
744 g->rbearing = pcm->rbearing;
745 g->width = pcm->width;
746 g->ascent = pcm->ascent;
747 g->descent = pcm->descent;
751 /* If the per_char pointer is null, all glyphs between
752 the first and last character indexes inclusive have
753 the same information, as given by both min_bounds and
756 g->rbearing = xfont->max_bounds.width;
757 g->width = xfont->max_bounds.width;
758 g->ascent = xfont->ascent;
759 g->descent = xfont->descent;
766 /* The X font driver function GET_GLYPH_ID. */
769 xfont_encode_char (MRealizedFont *rfont, unsigned code)
771 MXFontInfo *xfont_info;
773 unsigned min_byte1, max_byte1, min_byte2, max_byte2;
776 if (rfont->status < 0 || code >= 0x10000)
777 return MCHAR_INVALID_CODE;
778 if (rfont->status == 0)
780 if (xfont_open (rfont) < 0)
781 return MCHAR_INVALID_CODE;
783 xfont_info = rfont->info;
784 xfont = xfont_info->xfont;
785 all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
786 min_byte1 = xfont->min_byte1;
787 max_byte1 = xfont->max_byte1;
788 min_byte2 = xfont->min_char_or_byte2;
789 max_byte2 = xfont->max_char_or_byte2;
791 if (min_byte1 == 0 && max_byte1 == 0)
795 if (code < min_byte2 || code > max_byte2)
796 return MCHAR_INVALID_CODE;
799 pcm = xfont->per_char + (code - min_byte2);
800 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
801 ? code : MCHAR_INVALID_CODE);
805 unsigned byte1 = code >> 8, byte2 = code & 0xFF;
808 if (byte1 < min_byte1 || byte1 > max_byte1
809 || byte2 < min_byte2 || byte2 > max_byte2)
810 return MCHAR_INVALID_CODE;
814 pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
815 + (byte2 - min_byte2));
816 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
817 ? code : MCHAR_INVALID_CODE);
821 /* The X font driver function RENDER. */
824 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
825 MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
827 MRealizedFace *rface = from->rface;
828 MXFontInfo *xfont_info = rface->rfont->info;
831 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
838 /* It is assured that the all glyphs in the current range use the
839 same realized face. */
840 display = FRAME_DISPLAY (rface->frame);
843 gc = set_region (rface->frame, gc, region);
844 XSetFont (display, gc, xfont_info->xfont->fid);
845 code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
846 for (i = 0, g = from; g < to; i++, g++)
848 code[i].byte1 = g->code >> 8;
849 code[i].byte2 = g->code & 0xFF;
855 if (g->type == GLYPH_PAD)
857 else if (g->type == GLYPH_SPACE)
858 for (; g < to && g->type == GLYPH_SPACE; g++)
860 else if (! g->rface->rfont)
862 if ((g->c >= 0x200B && g->c <= 0x200F)
863 || (g->c >= 0x202A && g->c <= 0x202E))
867 /* As a font is not found for this character, draw an
869 int box_width = g->width;
870 int box_height = gstring->ascent + gstring->descent;
876 XDrawRectangle (display, (Window) win, gc,
877 x, y - gstring->ascent, box_width, box_height);
881 else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
883 XDrawString16 (display, (Window) win, gc,
884 x + g->xoff, y + g->yoff, code + (g - from), 1);
891 int code_idx = g - from;
894 g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
897 XDrawString16 (display, (Window) win, gc, orig_x, y,
904 xfont_list (MFrame *frame, MPlist *plist, MFont *font, MSymbol language,
907 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
908 MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil;
909 MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil;
913 if (registry != Mnil)
914 xfont_registry_list (frame, registry);
916 xfont_list_all (frame);
918 /* As we have not yet implemented the language check, return all
921 MPLIST_DO (p, disp_info->base_font_list)
923 mplist_add (plist, MPLIST_KEY (p), MPLIST_VAL (p));
930 MXFontList *xfontlist;
934 pl = disp_info->font_list;
935 if (registry != Mnil)
937 pl = mplist_find_by_key (pl, registry);
947 p = mplist_find_by_key (p, family);
953 xfontlist = MPLIST_VAL (p);
954 for (i = 0; i < xfontlist->used; i++)
956 xfont = xfontlist->fonts + i;
957 if (mfont__match_p (&xfont->core, font, MFONT_REGISTRY))
959 mplist_add (plist, MPLIST_KEY (p), &xfont->core);
968 if (registry != Mnil)
988 static int xft_open (MRealizedFont *);
989 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
990 static void xft_render (MDrawWindow, int, int, MGlyphString *,
991 MGlyph *, MGlyph *, int, MDrawRegion);
993 MFontDriver xft_driver =
994 { NULL, /* Set to ft_select in device_init (). */
995 xft_open, xft_find_metric,
996 NULL, /* Set to ft_encode_char in device_init (). */
998 NULL /* Set to ft_list in device_init (). */
1003 close_xft (void *object)
1005 MXftFontInfo *font_info = object;
1007 XftFontClose (font_info->display, font_info->font_aa);
1008 XftFontClose (font_info->display, font_info->font_no_aa);
1014 xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
1016 XftPattern *pattern;
1017 XftFontInfo *xft_font_info;
1020 pattern = XftPatternCreate ();
1021 XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
1022 XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
1023 XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
1024 xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
1025 if (! xft_font_info)
1027 font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
1028 XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
1034 xft_open (MRealizedFont *rfont)
1038 MXftFontInfo *font_info;
1041 if ((mfont__ft_driver.open) (rfont) < 0)
1044 size = rfont->font.property[MFONT_SIZE] / 10;
1045 frame = rfont->frame;
1047 ft_info = rfont->info;
1048 M17N_OBJECT (font_info, close_xft, MERROR_WIN);
1049 ft_info->extra_info = font_info;
1050 font_info->display = FRAME_DISPLAY (frame);
1051 font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
1052 if (font_info->font_aa)
1054 font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
1055 if (font_info->font_no_aa)
1058 rfont->fontp = font_info->font_no_aa;
1061 XftFontClose (FRAME_DISPLAY (rfont->frame), font_info->font_aa);
1064 ft_info->extra_info = NULL;
1071 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1074 MFTInfo *ft_info = rfont->info;
1075 MXftFontInfo *font_info = ft_info->extra_info;
1076 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1078 for (; g != gend; g++)
1080 if (g->code == MCHAR_INVALID_CODE)
1082 MGlyph *start = g++;
1084 while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
1085 (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
1093 XftGlyphExtents (FRAME_DISPLAY (gstring->frame),
1094 font_info->font_aa, &g->code, 1, &extents);
1095 g->lbearing = - extents.x;
1096 g->rbearing = extents.width - extents.x;
1097 g->width = extents.xOff;
1098 g->ascent = extents.y;
1099 g->descent = extents.height - extents.y;
1106 xft_render (MDrawWindow win, int x, int y,
1107 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1108 int reverse, MDrawRegion region)
1110 MRealizedFace *rface = from->rface;
1111 MFrame *frame = rface->frame;
1112 MFTInfo *ft_info = rface->rfont->info;
1113 MXftFontInfo *font_info = ft_info->extra_info;
1114 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1115 XftColor *xft_color = (! reverse
1116 ? &((GCInfo *) rface->info)->xft_color_fore
1117 : &((GCInfo *) rface->info)->xft_color_back);
1118 XftFont *xft_font = (gstring->control.anti_alias
1119 && FRAME_DEVICE (frame)->depth > 1
1120 ? font_info->font_aa : font_info->font_no_aa);
1129 XftDrawChange (xft_draw, (Drawable) win);
1130 XftDrawSetClip (xft_draw, (Region) region);
1132 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1133 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1135 if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1136 glyphs[nglyphs++] = g->code;
1140 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1141 last_x, y, glyphs, nglyphs);
1143 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1144 x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1145 last_x = x + g->width;
1149 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1155 /* Functions for the device driver. */
1158 mwin__close_device (MFrame *frame)
1160 M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
1164 mwin__device_get_prop (MFrame *frame, MSymbol key)
1166 MWDevice *device = FRAME_DEVICE (frame);
1168 if (key == Mdisplay)
1169 return (void *) device->display_info->display;
1171 return (void *) ScreenOfDisplay(device->display_info->display,
1172 device->screen_num);
1173 if (key == Mcolormap)
1174 return (void *) device->cmap;
1176 return (void *) device->depth;
1181 mwin__realize_face (MRealizedFace *rface)
1184 MSymbol foreground, background, videomode;
1185 MFaceHLineProp *hline;
1189 if (rface != rface->ascii_rface)
1191 rface->info = rface->ascii_rface->info;
1195 frame = rface->frame;
1196 MSTRUCT_CALLOC (info, MERROR_WIN);
1198 foreground = rface->face.property[MFACE_FOREGROUND];
1199 background = rface->face.property[MFACE_BACKGROUND];
1200 videomode = rface->face.property[MFACE_VIDEOMODE];
1202 videomode = frame->videomode;
1203 if (videomode != Mreverse)
1205 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1206 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1210 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1211 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1214 if (foreground == Mnil)
1215 foreground = frame->foreground;
1216 if (background == Mnil)
1217 background = frame->background;
1218 if (videomode == Mreverse)
1220 MSymbol temp = foreground;
1221 foreground = background;
1224 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1225 FRAME_VISUAL (frame),
1227 MSYMBOL_NAME (foreground),
1228 &info->xft_color_fore))
1230 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1231 FRAME_VISUAL (frame),
1233 MSYMBOL_NAME (background),
1234 &info->xft_color_back))
1238 hline = rface->hline;
1242 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1244 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1251 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1253 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1255 if (box->color_left && box->color_left != box->color_top)
1256 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1258 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1260 if (box->color_bottom && box->color_bottom != box->color_top)
1261 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1263 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1265 if (box->color_right && box->color_right != box->color_bottom)
1266 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1268 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1276 mwin__free_realized_face (MRealizedFace *rface)
1278 if (rface == rface->ascii_rface)
1284 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1286 int x, int y, int width, int height, MDrawRegion region)
1288 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1291 gc = set_region (frame, gc, region);
1293 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1294 x, y, width, height);
1299 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1300 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1301 int reverse, MDrawRegion region)
1303 MRealizedFace *rface = from->rface;
1304 Display *display = FRAME_DISPLAY (rface->frame);
1305 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1311 gc = set_region (rface->frame, gc, region);
1312 for (; from < to; from++)
1314 XDrawRectangle (display, (Window) win, gc,
1315 x, y - gstring->ascent + 1, from->width - 1,
1316 gstring->ascent + gstring->descent - 2);
1323 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1324 MRealizedFace *rface, int reverse,
1325 int x, int y, int width, MDrawRegion region)
1327 enum MFaceHLineType type = rface->hline->type;
1328 GCInfo *info = rface->info;
1329 GC gc = gc = info->gc[GC_HLINE];
1332 y = (type == MFACE_HLINE_BOTTOM
1333 ? y + gstring->text_descent - rface->hline->width
1334 : type == MFACE_HLINE_UNDER
1336 : type == MFACE_HLINE_STRIKE_THROUGH
1337 ? y - ((gstring->ascent + gstring->descent) / 2)
1338 : y - gstring->text_ascent);
1340 gc = set_region (frame, gc, region);
1342 for (i = 0; i < rface->hline->width; i++)
1343 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1344 x, y + i, x + width - 1, y + i);
1349 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1350 MGlyph *g, int x, int y, int width, MDrawRegion region)
1352 Display *display = FRAME_DISPLAY (frame);
1353 MRealizedFace *rface = g->rface;
1354 MFaceBoxProp *box = rface->box;
1355 GCInfo *info = rface->info;
1356 GC gc_top, gc_left, gc_right, gc_btm;
1360 y0 = y - (gstring->text_ascent
1361 + rface->box->inner_vmargin + rface->box->width);
1362 y1 = y + (gstring->text_descent
1363 + rface->box->inner_vmargin + rface->box->width - 1);
1365 gc_top = info->gc[GC_BOX_TOP];
1367 gc_top = set_region (frame, gc_top, region);
1368 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1371 gc_btm = info->gc[GC_BOX_BOTTOM];
1373 if (g->type == GLYPH_BOX)
1377 if (g->left_padding)
1378 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1380 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1382 /* Draw the top side. */
1383 for (i = 0; i < box->width; i++)
1384 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1386 /* Draw the bottom side. */
1387 if (region && gc_btm != gc_top)
1388 gc_btm = set_region (frame, gc_btm, region);
1389 for (i = 0; i < box->width; i++)
1390 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1392 if (g->left_padding > 0)
1394 /* Draw the left side. */
1395 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1399 gc_left = info->gc[GC_BOX_LEFT];
1401 gc_left = set_region (frame, gc_left, region);
1403 for (i = 0; i < rface->box->width; i++)
1404 XDrawLine (display, (Window) win, gc_left,
1405 x0 + i, y0 + i, x0 + i, y1 - i);
1409 /* Draw the right side. */
1410 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1414 gc_right = info->gc[GC_BOX_RIGHT];
1416 gc_right = set_region (frame, gc_right, region);
1418 for (i = 0; i < rface->box->width; i++)
1419 XDrawLine (display, (Window) win, gc_right,
1420 x1 - i, y0 + i, x1 - i, y1 - i);
1425 /* Draw the top side. */
1426 for (i = 0; i < box->width; i++)
1427 XDrawLine (display, (Window) win, gc_top,
1428 x, y0 + i, x + width - 1, y0 + i);
1430 /* Draw the bottom side. */
1431 if (region && gc_btm != gc_top)
1432 gc_btm = set_region (frame, gc_btm, region);
1433 for (i = 0; i < box->width; i++)
1434 XDrawLine (display, (Window) win, gc_btm,
1435 x, y1 - i, x + width - 1, y1 - i);
1442 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1443 int reverse, int x, int y,
1444 int width, int height, int row_bytes, unsigned char *bmp,
1447 Display *display = FRAME_DISPLAY (frame);
1449 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1452 gc = set_region (frame, gc, region);
1454 for (i = 0; i < height; i++, bmp += row_bytes)
1455 for (j = 0; j < width; j++)
1456 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1457 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1462 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1463 int intensity, MDrawPoint *points, int num,
1466 GCInfo *info = rface->info;
1469 if (! (gc = info->gc[intensity]))
1470 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1473 gc = set_region (frame, gc, region);
1475 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1476 (XPoint *) points, num, CoordModeOrigin);
1481 mwin__region_from_rect (MDrawMetric *rect)
1483 MDrawRegion region1 = XCreateRegion ();
1484 MDrawRegion region2 = XCreateRegion ();
1489 xrect.width = rect->width;
1490 xrect.height = rect->height;
1491 XUnionRectWithRegion (&xrect, region1, region2);
1492 XDestroyRegion (region1);
1497 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1499 MDrawRegion region1 = XCreateRegion ();
1504 xrect.width = rect->width;
1505 xrect.height = rect->height;
1507 XUnionRegion (region, region, region1);
1508 XUnionRectWithRegion (&xrect, region1, region);
1509 XDestroyRegion (region1);
1513 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1515 MDrawRegion region = XCreateRegion ();
1517 XUnionRegion (region1, region1, region);
1518 XIntersectRegion (region, region2, region1);
1519 XDestroyRegion (region);
1523 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1525 MDrawRegion region1 = XCreateRegion ();
1530 xrect.width = rect->width;
1531 xrect.height = rect->height;
1532 XUnionRectWithRegion (&xrect, region1, region);
1533 XDestroyRegion (region1);
1537 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1541 XClipBox (region, &xrect);
1544 rect->width = xrect.width;
1545 rect->height = xrect.height;
1549 mwin__free_region (MDrawRegion region)
1551 XDestroyRegion (region);
1555 mwin__dump_region (MDrawRegion region)
1558 XClipBox (region, &rect);
1559 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1564 mwin__create_window (MFrame *frame, MDrawWindow parent)
1566 Display *display = FRAME_DISPLAY (frame);
1568 XWMHints wm_hints = { InputHint, False };
1569 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1570 XSetWindowAttributes set_attrs;
1573 GCInfo *info = frame->rface->info;
1576 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1577 mask = GCForeground;
1578 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1579 set_attrs.background_pixel = values.foreground;
1580 set_attrs.backing_store = Always;
1581 set_attrs.override_redirect = True;
1582 set_attrs.save_under = True;
1583 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1584 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1585 CopyFromParent, InputOutput, CopyFromParent,
1587 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1588 NULL, &wm_hints, &class_hints);
1589 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1590 return (MDrawWindow) win;
1594 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1596 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1601 mwin__event_window (void *event)
1603 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1607 mwin__print_event (void *arg, char *win_name)
1610 XEvent *event = (XEvent *) arg;
1612 switch (event->xany.type)
1614 case 2: event_name = "KeyPress"; break;
1615 case 3: event_name = "KeyRelease"; break;
1616 case 4: event_name = "ButtonPress"; break;
1617 case 5: event_name = "ButtonRelease"; break;
1618 case 6: event_name = "MotionNotify"; break;
1619 case 7: event_name = "EnterNotify"; break;
1620 case 8: event_name = "LeaveNotify"; break;
1621 case 9: event_name = "FocusIn"; break;
1622 case 10: event_name = "FocusOut"; break;
1623 case 11: event_name = "KeymapNotify"; break;
1624 case 12: event_name = "Expose"; break;
1625 case 13: event_name = "GraphicsExpose"; break;
1626 case 14: event_name = "NoExpose"; break;
1627 case 15: event_name = "VisibilityNotify"; break;
1628 case 16: event_name = "CreateNotify"; break;
1629 case 17: event_name = "DestroyNotify"; break;
1630 case 18: event_name = "UnmapNotify"; break;
1631 case 19: event_name = "MapNotify"; break;
1632 case 20: event_name = "MapRequest"; break;
1633 case 21: event_name = "ReparentNotify"; break;
1634 case 22: event_name = "ConfigureNotify"; break;
1635 case 23: event_name = "ConfigureRequest"; break;
1636 case 24: event_name = "GravityNotify"; break;
1637 case 25: event_name = "ResizeRequest"; break;
1638 case 26: event_name = "CirculateNotify"; break;
1639 case 27: event_name = "CirculateRequest"; break;
1640 case 28: event_name = "PropertyNotify"; break;
1641 case 29: event_name = "SelectionClear"; break;
1642 case 30: event_name = "SelectionRequest"; break;
1643 case 31: event_name = "SelectionNotify"; break;
1644 case 32: event_name = "ColormapNotify"; break;
1645 case 33: event_name = "ClientMessage"; break;
1646 case 34: event_name = "MappingNotify"; break;
1647 default: event_name = "unknown";
1650 fprintf (stderr, "%s: %s\n", win_name, event_name);
1655 mwin__map_window (MFrame *frame, MDrawWindow win)
1657 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1661 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1663 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1667 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1668 MDrawMetric *geometry)
1670 Display *display = FRAME_DISPLAY (frame);
1671 XWindowAttributes attr;
1672 Window parent = (Window) parent_win, root;
1674 XGetWindowAttributes (display, (Window) win, &attr);
1675 geometry->x = attr.x + attr.border_width;
1676 geometry->y = attr.y + attr.border_width;
1677 geometry->width = attr.width;
1678 geometry->height = attr.height;
1681 parent = RootWindow (display, FRAME_SCREEN (frame));
1684 Window this_parent, *children;
1687 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1690 if (this_parent == parent || this_parent == root)
1692 win = (MDrawWindow) this_parent;
1693 XGetWindowAttributes (display, (Window) win, &attr);
1694 geometry->x += attr.x + attr.border_width;
1695 geometry->y += attr.y + attr.border_width;
1700 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1701 MDrawMetric *current, MDrawMetric *new)
1703 Display *display = FRAME_DISPLAY (frame);
1704 unsigned int mask = 0;
1705 XWindowChanges values;
1707 if (current->width != new->width)
1710 if (new->width <= 0)
1712 values.width = current->width = new->width;
1714 if (current->height != new->height)
1717 if (new->height <= 0)
1719 values.height = current->height = new->height;
1721 if (current->x != new->x)
1724 values.x = current->x = new->x;
1726 if (current->y != new->y)
1729 current->y = new->y;
1730 values.y = current->y = new->y;
1733 XConfigureWindow (display, (Window) win, mask, &values);
1734 XClearWindow (display, (Window) win);
1738 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1740 XEvent *event = (XEvent *) arg;
1741 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1748 if (event->xany.type != KeyPress
1749 /* && event->xany.type != KeyRelease */
1752 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1759 if (c < XK_space || c > XK_asciitilde)
1761 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1762 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1763 if (((XKeyEvent *) event)->state & ControlMask)
1765 if (c >= 'a' && c <= 'z')
1767 if (c >= ' ' && c < 127)
1768 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1770 key = minput__char_to_key (c);
1772 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1776 char *str = XKeysymToString (keysym);
1780 key = msymbol (str);
1781 if (((XKeyEvent *) event)->state & ShiftMask)
1782 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1783 if (((XKeyEvent *) event)->state & ControlMask)
1784 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1786 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1787 *modifiers |= MINPUT_KEY_META_MODIFIER;
1788 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1789 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1790 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1791 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1792 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1793 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1800 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1802 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1804 Display *display = FRAME_DISPLAY (frame);
1805 GCInfo *info = rface->info;
1808 for (i = 0; i <= GC_INVERSE; i++)
1810 XGetGCValues (display, info->gc[i], valuemask, &values);
1811 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1812 values.foreground, values.background);
1813 fprintf (stderr, "\n");
1817 static MDeviceDriver x_driver =
1820 mwin__device_get_prop,
1822 mwin__free_realized_face,
1824 mwin__draw_empty_boxes,
1828 mwin__region_from_rect,
1829 mwin__union_rect_with_region,
1830 mwin__intersect_region,
1831 mwin__region_add_rect,
1832 mwin__region_to_rect,
1835 mwin__create_window,
1836 mwin__destroy_window,
1839 mwin__window_geometry,
1840 mwin__adjust_window,
1844 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1849 M_iso8859_1 = msymbol ("iso8859-1");
1850 M_iso10646_1 = msymbol ("iso10646-1");
1852 display_info_list = mplist ();
1853 device_list = mplist ();
1856 xft_driver.select = mfont__ft_driver.select;
1857 xft_driver.encode_char = mfont__ft_driver.encode_char;
1858 xft_driver.list = mfont__ft_driver.list;
1861 Mxim = msymbol ("xim");
1862 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1870 M17N_OBJECT_UNREF (display_info_list);
1871 M17N_OBJECT_UNREF (device_list);
1875 /** Return an MWDevice object corresponding to a display specified in
1878 It searches device_list for a device matching the display. If
1879 found, return the found object. Otherwise, return a newly created
1883 device_open (MFrame *frame, MPlist *param)
1885 Display *display = NULL;
1886 Screen *screen = NULL;
1888 Drawable drawable = 0;
1889 Widget widget = NULL;
1891 int auto_display = 0;
1892 MDisplayInfo *disp_info = NULL;
1893 MWDevice *device = NULL;
1895 XWindowAttributes attr;
1900 int use_xfont = 0, use_freetype = 0, use_xft = 0;
1902 for (plist = param; (key = mplist_key (plist)) != Mnil;
1903 plist = mplist_next (plist))
1905 if (key == Mdisplay)
1906 display = (Display *) mplist_value (plist);
1907 else if (key == Mscreen)
1908 screen = mplist_value (plist);
1909 else if (key == Mdrawable)
1910 drawable = (Drawable) mplist_value (plist);
1911 else if (key == Mdepth)
1912 depth = (unsigned) mplist_value (plist);
1913 else if (key == Mwidget)
1914 widget = (Widget) mplist_value (plist);
1915 else if (key == Mcolormap)
1916 cmap = (Colormap) mplist_value (plist);
1917 else if (key == Mfont)
1919 MSymbol val = MPLIST_SYMBOL (plist);
1923 #ifdef HAVE_FREETYPE
1924 else if (val == Mfreetype)
1927 else if (val == Mxft)
1936 display = XtDisplay (widget);
1937 screen_num = XScreenNumberOfScreen (XtScreen (widget));
1938 depth = DefaultDepth (display, screen_num);
1944 unsigned width, height, border_width;
1947 MERROR (MERROR_WIN, -1);
1948 XGetGeometry (display, drawable, &root_window,
1949 &x, &y, &width, &height, &border_width, &depth);
1950 XGetWindowAttributes (display, root_window, &attr);
1951 screen_num = XScreenNumberOfScreen (attr.screen);
1956 display = DisplayOfScreen (screen);
1961 display = XOpenDisplay (NULL);
1963 MERROR (MERROR_WIN, -1);
1966 screen = DefaultScreenOfDisplay (display);
1968 screen_num = XScreenNumberOfScreen (screen);
1970 depth = DefaultDepth (display, screen_num);
1974 cmap = DefaultColormap (display, screen_num);
1976 for (plist = display_info_list; mplist_key (plist) != Mnil;
1977 plist = mplist_next (plist))
1979 disp_info = (MDisplayInfo *) mplist_value (plist);
1980 if (disp_info->display == display)
1984 if (mplist_key (plist) != Mnil)
1985 M17N_OBJECT_REF (disp_info);
1988 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
1989 disp_info->display = display;
1990 disp_info->auto_display = auto_display;
1991 disp_info->font_list = mplist ();
1992 disp_info->base_font_list = mplist ();
1993 find_modifier_bits (disp_info);
1994 mplist_add (display_info_list, Mt, disp_info);
1997 for (plist = device_list; mplist_key (plist) != Mnil;
1998 plist = mplist_next (plist))
2000 device = (MWDevice *) mplist_value (plist);
2001 if (device->display_info == disp_info
2002 && device->depth == depth
2003 && device->cmap == cmap)
2007 if (mplist_key (plist) != Mnil)
2008 M17N_OBJECT_REF (device);
2011 unsigned long valuemask = GCForeground;
2014 M17N_OBJECT (device, free_device, MERROR_WIN);
2015 device->display_info = disp_info;
2016 device->screen_num = screen_num;
2017 /* A drawable on which to create GCs. */
2018 device->drawable = XCreatePixmap (display,
2019 RootWindow (display, screen_num),
2021 device->depth = depth;
2022 device->cmap = cmap;
2023 device->realized_face_list = mplist ();
2024 device->realized_font_list = mplist ();
2025 device->realized_fontset_list = mplist ();
2026 device->gc_list = mplist ();
2027 values.foreground = BlackPixel (display, screen_num);
2028 device->scratch_gc = XCreateGC (display, device->drawable,
2029 valuemask, &values);
2031 device->xft_draw = XftDrawCreate (display, device->drawable,
2032 DefaultVisual (display, screen_num),
2037 frame->device = device;
2038 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2039 frame->driver = &x_driver;
2040 frame->font_driver_list = mplist ();
2044 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2047 #endif /* HAVE_XFT2 */
2048 #ifdef HAVE_FREETYPE
2050 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2051 #endif /* HAVE_FREETYPE */
2052 if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list))
2053 mplist_push (frame->font_driver_list, Mx, &xfont_driver);
2055 frame->realized_font_list = device->realized_font_list;
2056 frame->realized_face_list = device->realized_face_list;
2057 frame->realized_fontset_list = device->realized_fontset_list;
2061 XtResource resources[] = {
2062 { XtNfont, XtCFont, XtRString, sizeof (String),
2063 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2064 { XtNforeground, XtCForeground, XtRString, sizeof (String),
2065 XtOffset (AppDataPtr, foreground), XtRString, "black" },
2066 { XtNbackground, XtCBackground, XtRString, sizeof (String),
2067 XtOffset (AppDataPtr, background), XtRString, "white" },
2068 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2069 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2072 XtGetApplicationResources (widget, &app_data,
2073 resources, XtNumber (resources), NULL, 0);
2074 frame->foreground = msymbol (app_data.foreground);
2075 frame->background = msymbol (app_data.background);
2076 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2080 app_data.font = DEFAULT_FONT;
2081 frame->foreground = msymbol ("black");
2082 frame->background = msymbol ("white");
2083 frame->videomode = Mnormal;
2088 char **names = XListFonts (display, app_data.font, 1, &nfonts);
2092 if (! (frame->font = mfont_parse_name (names[0], Mx)))
2094 /* The font name does not conform to XLFD. Try to open the
2095 font and get XA_FONT property. */
2096 XFontStruct *xfont = XLoadQueryFont (display, names[0]);
2101 unsigned long value;
2104 if (XGetFontProperty (xfont, XA_FONT, &value)
2105 && (name = ((char *)
2106 XGetAtomName (display, (Atom) value))))
2108 if ((frame->font = mfont_parse_name (name, Mx)))
2111 XFreeFont (display, xfont);
2114 XFreeFontNames (names);
2117 frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
2120 face = mface_from_font (frame->font);
2121 face->property[MFACE_FONTSET] = mfontset (NULL);
2122 face->property[MFACE_FOREGROUND] = frame->foreground;
2123 face->property[MFACE_BACKGROUND] = frame->background;
2124 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2125 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2126 face->property[MFACE_VIDEOMODE] = frame->videomode;
2127 mface_put_prop (face, Mhook_func,
2128 mface_get_prop (mface__default, Mhook_func));
2129 face->property[MFACE_RATIO] = (void *) 100;
2130 mplist_push (param, Mface, face);
2131 M17N_OBJECT_UNREF (face);
2133 #ifdef X_SET_ERROR_HANDLER
2134 XSetErrorHandler (x_error_handler);
2135 XSetIOErrorHandler (x_io_error_handler);
2143 /* XIM (X Input Method) handler */
2145 typedef struct MInputXIMMethodInfo
2151 } MInputXIMMethodInfo;
2153 typedef struct MInputXIMContextInfo
2157 MConverter *converter;
2158 } MInputXIMContextInfo;
2161 xim_open_im (MInputMethod *im)
2163 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2164 MLocale *saved, *this;
2165 char *save_modifier_list;
2167 MInputXIMMethodInfo *im_info;
2169 saved = mlocale_set (LC_CTYPE, NULL);
2170 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2172 /* The specified locale is not supported. */
2173 MERROR (MERROR_LOCALE, -1);
2174 if (mlocale_get_prop (this, Mcoding) == Mnil)
2176 /* Unable to decode the output of XIM. */
2177 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2178 MERROR (MERROR_LOCALE, -1);
2181 if (arg->modifier_list)
2182 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2184 save_modifier_list = XSetLocaleModifiers ("");
2185 if (! save_modifier_list)
2187 /* The specified locale is not supported by X. */
2188 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2189 MERROR (MERROR_LOCALE, -1);
2192 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2195 /* No input method is available in the current locale. */
2196 XSetLocaleModifiers (save_modifier_list);
2197 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2198 MERROR (MERROR_WIN, -1);
2201 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2202 im_info->display = arg->display;
2204 im_info->language = mlocale_get_prop (this, Mlanguage);
2205 im_info->coding = mlocale_get_prop (this, Mcoding);
2208 XSetLocaleModifiers (save_modifier_list);
2209 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2215 xim_close_im (MInputMethod *im)
2217 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2219 XCloseIM (im_info->xim);
2224 xim_create_ic (MInputContext *ic)
2226 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2227 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2228 MInputXIMContextInfo *ic_info;
2231 if (! arg->input_style)
2233 /* By default, use Root style. */
2234 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2235 arg->preedit_attrs = NULL;
2236 arg->status_attrs = NULL;
2239 if (! arg->preedit_attrs && ! arg->status_attrs)
2240 xic = XCreateIC (im_info->xim,
2241 XNInputStyle, arg->input_style,
2242 XNClientWindow, arg->client_win,
2243 XNFocusWindow, arg->focus_win,
2245 else if (arg->preedit_attrs && ! arg->status_attrs)
2246 xic = XCreateIC (im_info->xim,
2247 XNInputStyle, arg->input_style,
2248 XNClientWindow, arg->client_win,
2249 XNFocusWindow, arg->focus_win,
2250 XNPreeditAttributes, arg->preedit_attrs,
2252 else if (! arg->preedit_attrs && arg->status_attrs)
2253 xic = XCreateIC (im_info->xim,
2254 XNInputStyle, arg->input_style,
2255 XNClientWindow, arg->client_win,
2256 XNFocusWindow, arg->focus_win,
2257 XNStatusAttributes, arg->status_attrs,
2260 xic = XCreateIC (im_info->xim,
2261 XNInputStyle, arg->input_style,
2262 XNClientWindow, arg->client_win,
2263 XNFocusWindow, arg->focus_win,
2264 XNPreeditAttributes, arg->preedit_attrs,
2265 XNStatusAttributes, arg->status_attrs,
2268 MERROR (MERROR_WIN, -1);
2270 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2272 ic_info->win = arg->focus_win;
2273 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2279 xim_destroy_ic (MInputContext *ic)
2281 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2283 XDestroyIC (ic_info->xic);
2284 mconv_free_converter (ic_info->converter);
2290 xim_filter (MInputContext *ic, MSymbol key, void *event)
2292 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2294 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2299 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2301 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2302 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2303 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2309 buf = (char *) alloca (512);
2310 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2311 if (status == XBufferOverflow)
2313 buf = (char *) alloca (len);
2314 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2317 mtext_reset (ic->produced);
2321 mconv_reset_converter (ic_info->converter);
2322 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2323 mconv_decode (ic_info->converter, ic->produced);
2324 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2325 Mlanguage, (void *) im_info->language);
2326 mtext_cpy (mt, ic->produced);
2327 mtext_reset (ic->produced);
2333 #ifdef X_SET_ERROR_HANDLER
2335 x_error_handler (Display *display, XErrorEvent *error)
2342 x_io_error_handler (Display *display)
2352 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2356 /*** @addtogroup m17nInputMethodWin */
2361 @brief Input method driver for XIM.
2363 The driver #minput_xim_driver is for the foreign input method of
2364 name #Mxim. It uses XIM (X Input Methods) as a background input
2367 As the symbol #Mxim has property #Minput_driver whose value is
2368 a pointer to this driver, the input method of language #Mnil
2369 and name #Mxim uses this driver.
2371 Therefore, for such input methods, the driver dependent arguments
2372 to the functions whose name begin with minput_ must be as follows.
2374 The argument $ARG of the function minput_open_im () must be a
2375 pointer to the structure #MInputXIMArgIM. See the documentation
2376 of #MInputXIMArgIM for more details.
2378 The argument $ARG of the function minput_create_ic () must be a
2379 pointer to the structure #MInputXIMArgIC. See the documentation
2380 of #MInputXIMArgIC for more details.
2382 The argument $ARG of the function minput_filter () must be a
2383 pointer to the structure @c XEvent. The argument $KEY is ignored.
2385 The argument $ARG of the function minput_lookup () must be the
2386 same one as that of the function minput_filter (). The argument
2390 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2392 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
2393 ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
2396 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2397 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
2398 ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2400 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
2401 ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2403 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM ¤Ø¤Î¥Ý
2404 ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
2407 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC ¤Ø¤Î
2408 ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
2411 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2412 ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2414 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2415 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2418 MInputDriver minput_xim_driver =
2419 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2420 xim_filter, xim_lookup, NULL };