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;
578 family = FONT_PROPERTY (request, MFONT_FAMILY);
579 MPLIST_DO (plist, plist)
581 if (family == Mnil || family == MPLIST_KEY (plist))
583 MXFontList *xfont_table = MPLIST_VAL (plist);
585 for (i = 0; i < xfont_table->used; i++)
587 MXFont *xfont = xfont_table->fonts + i;
588 MFont *font = (MFont *) xfont;
589 int size = requested_size / 10, s0, s1;
591 for (s0 = size; s0 > 0 && ! HAVE_SIZE (xfont, s0); s0--);
592 if (s0 * 10 == requested_size)
593 /* Exact size match. */
595 else if (xfont->sizes[0] & 1)
598 else if (limited_size)
599 /* We can't use a larger font. */
603 for (s0 = size + 1; s0 < 64 && ! HAVE_SIZE (xfont, s0); s0++);
610 for (s1 = size + (size - s0) - 1;
611 s1 > size && HAVE_SIZE (xfont, s1); s1++);
612 size = (s1 > size ? s1 : s0);
614 font->property[MFONT_SIZE] = size * 10;
616 if ((score = mfont__score (font, spec, request,
618 && (best_score < 0 || score < best_score))
621 best_font = (MFont *) (xfont_table->fonts + i);
633 MSTRUCT_CALLOC (rfont, MERROR_WIN);
634 rfont->frame = frame;
636 rfont->request = *request;
637 rfont->font = *best_font;
638 if (best_font->property[MFONT_SIZE] == 0)
639 rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE];
640 rfont->score = best_score;
645 /* The X font driver function CLOSE. */
648 close_xfont (void *object)
650 MXFontInfo *xfont_info = object;
652 XFreeFont (xfont_info->display, xfont_info->xfont);
657 /* The X font driver function OPEN. */
660 xfont_open (MRealizedFont *rfont)
663 MXFontInfo *xfont_info;
664 MFrame *frame = rfont->frame;
665 int mdebug_mask = MDEBUG_FONT;
667 /* This never fail to generate a valid fontname because open_spec
668 should correspond to a font available on the system. */
669 name = mfont_unparse_name (&rfont->font, Mx);
670 M17N_OBJECT (xfont_info, close_xfont, MERROR_WIN);
671 xfont_info->display = FRAME_DISPLAY (frame);
672 xfont_info->xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
673 if (! xfont_info->xfont)
677 MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
681 rfont->info = xfont_info;
682 MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
685 rfont->ascent = xfont_info->xfont->ascent;
686 rfont->descent = xfont_info->xfont->descent;
688 rfont->fontp = xfont_info->xfont;
693 /* The X font driver function FIND_METRIC. */
696 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
699 MXFontInfo *xfont_info = rfont->info;
700 XFontStruct *xfont = xfont_info->xfont;
701 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
703 for (; g != gend; g++)
705 if (g->code == MCHAR_INVALID_CODE)
707 g->lbearing = xfont->max_bounds.lbearing;
708 g->rbearing = xfont->max_bounds.rbearing;
709 g->width = xfont->max_bounds.width;
710 g->ascent = xfont->ascent;
711 g->descent = xfont->descent;
715 int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
716 XCharStruct *pcm = NULL;
718 if (xfont->per_char != NULL)
720 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
723 && byte2 >= xfont->min_char_or_byte2
724 && byte2 <= xfont->max_char_or_byte2)
725 pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
729 if (byte1 >= xfont->min_byte1
730 && byte1 <= xfont->max_byte1
731 && byte2 >= xfont->min_char_or_byte2
732 && byte2 <= xfont->max_char_or_byte2)
734 pcm = (xfont->per_char
735 + ((xfont->max_char_or_byte2
736 - xfont->min_char_or_byte2 + 1)
737 * (byte1 - xfont->min_byte1))
738 + (byte2 - xfont->min_char_or_byte2));
745 g->lbearing = pcm->lbearing;
746 g->rbearing = pcm->rbearing;
747 g->width = pcm->width;
748 g->ascent = pcm->ascent;
749 g->descent = pcm->descent;
753 /* If the per_char pointer is null, all glyphs between
754 the first and last character indexes inclusive have
755 the same information, as given by both min_bounds and
758 g->rbearing = xfont->max_bounds.width;
759 g->width = xfont->max_bounds.width;
760 g->ascent = xfont->ascent;
761 g->descent = xfont->descent;
768 /* The X font driver function GET_GLYPH_ID. */
771 xfont_encode_char (MRealizedFont *rfont, unsigned code)
773 MXFontInfo *xfont_info;
775 unsigned min_byte1, max_byte1, min_byte2, max_byte2;
778 if (rfont->status < 0 || code >= 0x10000)
779 return MCHAR_INVALID_CODE;
780 if (rfont->status == 0)
782 if (xfont_open (rfont) < 0)
783 return MCHAR_INVALID_CODE;
785 xfont_info = rfont->info;
786 xfont = xfont_info->xfont;
787 all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
788 min_byte1 = xfont->min_byte1;
789 max_byte1 = xfont->max_byte1;
790 min_byte2 = xfont->min_char_or_byte2;
791 max_byte2 = xfont->max_char_or_byte2;
793 if (min_byte1 == 0 && max_byte1 == 0)
797 if (code < min_byte2 || code > max_byte2)
798 return MCHAR_INVALID_CODE;
801 pcm = xfont->per_char + (code - min_byte2);
802 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
803 ? code : MCHAR_INVALID_CODE);
807 unsigned byte1 = code >> 8, byte2 = code & 0xFF;
810 if (byte1 < min_byte1 || byte1 > max_byte1
811 || byte2 < min_byte2 || byte2 > max_byte2)
812 return MCHAR_INVALID_CODE;
816 pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
817 + (byte2 - min_byte2));
818 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
819 ? code : MCHAR_INVALID_CODE);
823 /* The X font driver function RENDER. */
826 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
827 MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
829 MRealizedFace *rface = from->rface;
830 MXFontInfo *xfont_info = rface->rfont->info;
833 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
840 /* It is assured that the all glyphs in the current range use the
841 same realized face. */
842 display = FRAME_DISPLAY (rface->frame);
845 gc = set_region (rface->frame, gc, region);
846 XSetFont (display, gc, xfont_info->xfont->fid);
847 code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
848 for (i = 0, g = from; g < to; i++, g++)
850 code[i].byte1 = g->code >> 8;
851 code[i].byte2 = g->code & 0xFF;
857 if (g->type == GLYPH_PAD)
859 else if (g->type == GLYPH_SPACE)
860 for (; g < to && g->type == GLYPH_SPACE; g++)
862 else if (! g->rface->rfont)
864 if ((g->c >= 0x200B && g->c <= 0x200F)
865 || (g->c >= 0x202A && g->c <= 0x202E))
869 /* As a font is not found for this character, draw an
871 int box_width = g->width;
872 int box_height = gstring->ascent + gstring->descent;
878 XDrawRectangle (display, (Window) win, gc,
879 x, y - gstring->ascent, box_width, box_height);
883 else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
885 XDrawString16 (display, (Window) win, gc,
886 x + g->xoff, y + g->yoff, code + (g - from), 1);
893 int code_idx = g - from;
896 g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
899 XDrawString16 (display, (Window) win, gc, orig_x, y,
906 xfont_list (MFrame *frame, MPlist *plist, MFont *font, MSymbol language,
909 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
910 MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil;
911 MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil;
915 if (registry != Mnil)
916 xfont_registry_list (frame, registry);
918 xfont_list_all (frame);
920 /* As we have not yet implemented the language check, return all
923 MPLIST_DO (p, disp_info->base_font_list)
925 mplist_add (plist, MPLIST_KEY (p), MPLIST_VAL (p));
932 MXFontList *xfontlist;
936 pl = disp_info->font_list;
937 if (registry != Mnil)
939 pl = mplist_find_by_key (pl, registry);
949 p = mplist_find_by_key (p, family);
955 xfontlist = MPLIST_VAL (p);
956 for (i = 0; i < xfontlist->used; i++)
958 xfont = xfontlist->fonts + i;
959 if (mfont__match_p (&xfont->core, font, MFONT_REGISTRY))
961 mplist_add (plist, MPLIST_KEY (p), &xfont->core);
970 if (registry != Mnil)
990 static int xft_open (MRealizedFont *);
991 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
992 static void xft_render (MDrawWindow, int, int, MGlyphString *,
993 MGlyph *, MGlyph *, int, MDrawRegion);
995 MFontDriver xft_driver =
996 { NULL, /* Set to ft_select in device_init (). */
997 xft_open, xft_find_metric,
998 NULL, /* Set to ft_encode_char in device_init (). */
1000 NULL /* Set to ft_list in device_init (). */
1005 close_xft (void *object)
1007 MXftFontInfo *font_info = object;
1009 XftFontClose (font_info->display, font_info->font_aa);
1010 XftFontClose (font_info->display, font_info->font_no_aa);
1016 xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
1018 XftPattern *pattern;
1019 XftFontInfo *xft_font_info;
1022 pattern = XftPatternCreate ();
1023 XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
1024 XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
1025 XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
1026 xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
1027 if (! xft_font_info)
1029 font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
1030 XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
1036 xft_open (MRealizedFont *rfont)
1040 MXftFontInfo *font_info;
1043 if ((mfont__ft_driver.open) (rfont) < 0)
1046 size = rfont->font.property[MFONT_SIZE] / 10;
1047 frame = rfont->frame;
1049 ft_info = rfont->info;
1050 M17N_OBJECT (font_info, close_xft, MERROR_WIN);
1051 ft_info->extra_info = font_info;
1052 font_info->display = FRAME_DISPLAY (frame);
1053 font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
1054 if (font_info->font_aa)
1056 font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
1057 if (font_info->font_no_aa)
1060 rfont->fontp = font_info->font_no_aa;
1063 XftFontClose (FRAME_DISPLAY (rfont->frame), font_info->font_aa);
1066 ft_info->extra_info = NULL;
1073 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1076 MFTInfo *ft_info = rfont->info;
1077 MXftFontInfo *font_info = ft_info->extra_info;
1078 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1080 for (; g != gend; g++)
1082 if (g->code == MCHAR_INVALID_CODE)
1084 MGlyph *start = g++;
1086 while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
1087 (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
1095 XftGlyphExtents (FRAME_DISPLAY (gstring->frame),
1096 font_info->font_aa, &g->code, 1, &extents);
1097 g->lbearing = - extents.x;
1098 g->rbearing = extents.width - extents.x;
1099 g->width = extents.xOff;
1100 g->ascent = extents.y;
1101 g->descent = extents.height - extents.y;
1108 xft_render (MDrawWindow win, int x, int y,
1109 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1110 int reverse, MDrawRegion region)
1112 MRealizedFace *rface = from->rface;
1113 MFrame *frame = rface->frame;
1114 MFTInfo *ft_info = rface->rfont->info;
1115 MXftFontInfo *font_info = ft_info->extra_info;
1116 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1117 XftColor *xft_color = (! reverse
1118 ? &((GCInfo *) rface->info)->xft_color_fore
1119 : &((GCInfo *) rface->info)->xft_color_back);
1120 XftFont *xft_font = (gstring->control.anti_alias
1121 && FRAME_DEVICE (frame)->depth > 1
1122 ? font_info->font_aa : font_info->font_no_aa);
1131 XftDrawChange (xft_draw, (Drawable) win);
1132 XftDrawSetClip (xft_draw, (Region) region);
1134 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1135 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1137 if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1138 glyphs[nglyphs++] = g->code;
1142 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1143 last_x, y, glyphs, nglyphs);
1145 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1146 x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1147 last_x = x + g->width;
1151 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1157 /* Functions for the device driver. */
1160 mwin__close_device (MFrame *frame)
1162 M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
1166 mwin__device_get_prop (MFrame *frame, MSymbol key)
1168 MWDevice *device = FRAME_DEVICE (frame);
1170 if (key == Mdisplay)
1171 return (void *) device->display_info->display;
1173 return (void *) ScreenOfDisplay(device->display_info->display,
1174 device->screen_num);
1175 if (key == Mcolormap)
1176 return (void *) device->cmap;
1178 return (void *) device->depth;
1183 mwin__realize_face (MRealizedFace *rface)
1186 MSymbol foreground, background, videomode;
1187 MFaceHLineProp *hline;
1191 if (rface != rface->ascii_rface)
1193 rface->info = rface->ascii_rface->info;
1197 frame = rface->frame;
1198 MSTRUCT_CALLOC (info, MERROR_WIN);
1200 foreground = rface->face.property[MFACE_FOREGROUND];
1201 background = rface->face.property[MFACE_BACKGROUND];
1202 videomode = rface->face.property[MFACE_VIDEOMODE];
1204 videomode = frame->videomode;
1205 if (videomode != Mreverse)
1207 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1208 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1212 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1213 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1216 if (foreground == Mnil)
1217 foreground = frame->foreground;
1218 if (background == Mnil)
1219 background = frame->background;
1220 if (videomode == Mreverse)
1222 MSymbol temp = foreground;
1223 foreground = background;
1226 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1227 FRAME_VISUAL (frame),
1229 MSYMBOL_NAME (foreground),
1230 &info->xft_color_fore))
1232 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1233 FRAME_VISUAL (frame),
1235 MSYMBOL_NAME (background),
1236 &info->xft_color_back))
1240 hline = rface->hline;
1244 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1246 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1253 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1255 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1257 if (box->color_left && box->color_left != box->color_top)
1258 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1260 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1262 if (box->color_bottom && box->color_bottom != box->color_top)
1263 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1265 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1267 if (box->color_right && box->color_right != box->color_bottom)
1268 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1270 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1278 mwin__free_realized_face (MRealizedFace *rface)
1280 if (rface == rface->ascii_rface)
1286 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1288 int x, int y, int width, int height, MDrawRegion region)
1290 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1293 gc = set_region (frame, gc, region);
1295 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1296 x, y, width, height);
1301 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1302 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1303 int reverse, MDrawRegion region)
1305 MRealizedFace *rface = from->rface;
1306 Display *display = FRAME_DISPLAY (rface->frame);
1307 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1313 gc = set_region (rface->frame, gc, region);
1314 for (; from < to; from++)
1316 XDrawRectangle (display, (Window) win, gc,
1317 x, y - gstring->ascent + 1, from->width - 1,
1318 gstring->ascent + gstring->descent - 2);
1325 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1326 MRealizedFace *rface, int reverse,
1327 int x, int y, int width, MDrawRegion region)
1329 enum MFaceHLineType type = rface->hline->type;
1330 GCInfo *info = rface->info;
1331 GC gc = gc = info->gc[GC_HLINE];
1334 y = (type == MFACE_HLINE_BOTTOM
1335 ? y + gstring->text_descent - rface->hline->width
1336 : type == MFACE_HLINE_UNDER
1338 : type == MFACE_HLINE_STRIKE_THROUGH
1339 ? y - ((gstring->ascent + gstring->descent) / 2)
1340 : y - gstring->text_ascent);
1342 gc = set_region (frame, gc, region);
1344 for (i = 0; i < rface->hline->width; i++)
1345 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1346 x, y + i, x + width - 1, y + i);
1351 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1352 MGlyph *g, int x, int y, int width, MDrawRegion region)
1354 Display *display = FRAME_DISPLAY (frame);
1355 MRealizedFace *rface = g->rface;
1356 MFaceBoxProp *box = rface->box;
1357 GCInfo *info = rface->info;
1358 GC gc_top, gc_left, gc_right, gc_btm;
1362 y0 = y - (gstring->text_ascent
1363 + rface->box->inner_vmargin + rface->box->width);
1364 y1 = y + (gstring->text_descent
1365 + rface->box->inner_vmargin + rface->box->width - 1);
1367 gc_top = info->gc[GC_BOX_TOP];
1369 gc_top = set_region (frame, gc_top, region);
1370 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1373 gc_btm = info->gc[GC_BOX_BOTTOM];
1375 if (g->type == GLYPH_BOX)
1379 if (g->left_padding)
1380 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1382 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1384 /* Draw the top side. */
1385 for (i = 0; i < box->width; i++)
1386 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1388 /* Draw the bottom side. */
1389 if (region && gc_btm != gc_top)
1390 gc_btm = set_region (frame, gc_btm, region);
1391 for (i = 0; i < box->width; i++)
1392 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1394 if (g->left_padding > 0)
1396 /* Draw the left side. */
1397 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1401 gc_left = info->gc[GC_BOX_LEFT];
1403 gc_left = set_region (frame, gc_left, region);
1405 for (i = 0; i < rface->box->width; i++)
1406 XDrawLine (display, (Window) win, gc_left,
1407 x0 + i, y0 + i, x0 + i, y1 - i);
1411 /* Draw the right side. */
1412 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1416 gc_right = info->gc[GC_BOX_RIGHT];
1418 gc_right = set_region (frame, gc_right, region);
1420 for (i = 0; i < rface->box->width; i++)
1421 XDrawLine (display, (Window) win, gc_right,
1422 x1 - i, y0 + i, x1 - i, y1 - i);
1427 /* Draw the top side. */
1428 for (i = 0; i < box->width; i++)
1429 XDrawLine (display, (Window) win, gc_top,
1430 x, y0 + i, x + width - 1, y0 + i);
1432 /* Draw the bottom side. */
1433 if (region && gc_btm != gc_top)
1434 gc_btm = set_region (frame, gc_btm, region);
1435 for (i = 0; i < box->width; i++)
1436 XDrawLine (display, (Window) win, gc_btm,
1437 x, y1 - i, x + width - 1, y1 - i);
1444 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1445 int reverse, int x, int y,
1446 int width, int height, int row_bytes, unsigned char *bmp,
1449 Display *display = FRAME_DISPLAY (frame);
1451 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1454 gc = set_region (frame, gc, region);
1456 for (i = 0; i < height; i++, bmp += row_bytes)
1457 for (j = 0; j < width; j++)
1458 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1459 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1464 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1465 int intensity, MDrawPoint *points, int num,
1468 GCInfo *info = rface->info;
1471 if (! (gc = info->gc[intensity]))
1472 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1475 gc = set_region (frame, gc, region);
1477 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1478 (XPoint *) points, num, CoordModeOrigin);
1483 mwin__region_from_rect (MDrawMetric *rect)
1485 MDrawRegion region1 = XCreateRegion ();
1486 MDrawRegion region2 = XCreateRegion ();
1491 xrect.width = rect->width;
1492 xrect.height = rect->height;
1493 XUnionRectWithRegion (&xrect, region1, region2);
1494 XDestroyRegion (region1);
1499 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1501 MDrawRegion region1 = XCreateRegion ();
1506 xrect.width = rect->width;
1507 xrect.height = rect->height;
1509 XUnionRegion (region, region, region1);
1510 XUnionRectWithRegion (&xrect, region1, region);
1511 XDestroyRegion (region1);
1515 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1517 MDrawRegion region = XCreateRegion ();
1519 XUnionRegion (region1, region1, region);
1520 XIntersectRegion (region, region2, region1);
1521 XDestroyRegion (region);
1525 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1527 MDrawRegion region1 = XCreateRegion ();
1532 xrect.width = rect->width;
1533 xrect.height = rect->height;
1534 XUnionRectWithRegion (&xrect, region1, region);
1535 XDestroyRegion (region1);
1539 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1543 XClipBox (region, &xrect);
1546 rect->width = xrect.width;
1547 rect->height = xrect.height;
1551 mwin__free_region (MDrawRegion region)
1553 XDestroyRegion (region);
1557 mwin__dump_region (MDrawRegion region)
1560 XClipBox (region, &rect);
1561 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1566 mwin__create_window (MFrame *frame, MDrawWindow parent)
1568 Display *display = FRAME_DISPLAY (frame);
1570 XWMHints wm_hints = { InputHint, False };
1571 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1572 XSetWindowAttributes set_attrs;
1575 GCInfo *info = frame->rface->info;
1578 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1579 mask = GCForeground;
1580 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1581 set_attrs.background_pixel = values.foreground;
1582 set_attrs.backing_store = Always;
1583 set_attrs.override_redirect = True;
1584 set_attrs.save_under = True;
1585 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1586 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1587 CopyFromParent, InputOutput, CopyFromParent,
1589 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1590 NULL, &wm_hints, &class_hints);
1591 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1592 return (MDrawWindow) win;
1596 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1598 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1603 mwin__event_window (void *event)
1605 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1609 mwin__print_event (void *arg, char *win_name)
1612 XEvent *event = (XEvent *) arg;
1614 switch (event->xany.type)
1616 case 2: event_name = "KeyPress"; break;
1617 case 3: event_name = "KeyRelease"; break;
1618 case 4: event_name = "ButtonPress"; break;
1619 case 5: event_name = "ButtonRelease"; break;
1620 case 6: event_name = "MotionNotify"; break;
1621 case 7: event_name = "EnterNotify"; break;
1622 case 8: event_name = "LeaveNotify"; break;
1623 case 9: event_name = "FocusIn"; break;
1624 case 10: event_name = "FocusOut"; break;
1625 case 11: event_name = "KeymapNotify"; break;
1626 case 12: event_name = "Expose"; break;
1627 case 13: event_name = "GraphicsExpose"; break;
1628 case 14: event_name = "NoExpose"; break;
1629 case 15: event_name = "VisibilityNotify"; break;
1630 case 16: event_name = "CreateNotify"; break;
1631 case 17: event_name = "DestroyNotify"; break;
1632 case 18: event_name = "UnmapNotify"; break;
1633 case 19: event_name = "MapNotify"; break;
1634 case 20: event_name = "MapRequest"; break;
1635 case 21: event_name = "ReparentNotify"; break;
1636 case 22: event_name = "ConfigureNotify"; break;
1637 case 23: event_name = "ConfigureRequest"; break;
1638 case 24: event_name = "GravityNotify"; break;
1639 case 25: event_name = "ResizeRequest"; break;
1640 case 26: event_name = "CirculateNotify"; break;
1641 case 27: event_name = "CirculateRequest"; break;
1642 case 28: event_name = "PropertyNotify"; break;
1643 case 29: event_name = "SelectionClear"; break;
1644 case 30: event_name = "SelectionRequest"; break;
1645 case 31: event_name = "SelectionNotify"; break;
1646 case 32: event_name = "ColormapNotify"; break;
1647 case 33: event_name = "ClientMessage"; break;
1648 case 34: event_name = "MappingNotify"; break;
1649 default: event_name = "unknown";
1652 fprintf (stderr, "%s: %s\n", win_name, event_name);
1657 mwin__map_window (MFrame *frame, MDrawWindow win)
1659 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1663 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1665 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1669 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1670 MDrawMetric *geometry)
1672 Display *display = FRAME_DISPLAY (frame);
1673 XWindowAttributes attr;
1674 Window parent = (Window) parent_win, root;
1676 XGetWindowAttributes (display, (Window) win, &attr);
1677 geometry->x = attr.x + attr.border_width;
1678 geometry->y = attr.y + attr.border_width;
1679 geometry->width = attr.width;
1680 geometry->height = attr.height;
1683 parent = RootWindow (display, FRAME_SCREEN (frame));
1686 Window this_parent, *children;
1689 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1692 if (this_parent == parent || this_parent == root)
1694 win = (MDrawWindow) this_parent;
1695 XGetWindowAttributes (display, (Window) win, &attr);
1696 geometry->x += attr.x + attr.border_width;
1697 geometry->y += attr.y + attr.border_width;
1702 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1703 MDrawMetric *current, MDrawMetric *new)
1705 Display *display = FRAME_DISPLAY (frame);
1706 unsigned int mask = 0;
1707 XWindowChanges values;
1709 if (current->width != new->width)
1712 if (new->width <= 0)
1714 values.width = current->width = new->width;
1716 if (current->height != new->height)
1719 if (new->height <= 0)
1721 values.height = current->height = new->height;
1723 if (current->x != new->x)
1726 values.x = current->x = new->x;
1728 if (current->y != new->y)
1731 current->y = new->y;
1732 values.y = current->y = new->y;
1735 XConfigureWindow (display, (Window) win, mask, &values);
1736 XClearWindow (display, (Window) win);
1740 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1742 XEvent *event = (XEvent *) arg;
1743 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1750 if (event->xany.type != KeyPress
1751 /* && event->xany.type != KeyRelease */
1754 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1761 if (c < XK_space || c > XK_asciitilde)
1763 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1764 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1765 if (((XKeyEvent *) event)->state & ControlMask)
1767 if (c >= 'a' && c <= 'z')
1769 if (c >= ' ' && c < 127)
1770 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1772 key = minput__char_to_key (c);
1774 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1778 char *str = XKeysymToString (keysym);
1782 key = msymbol (str);
1783 if (((XKeyEvent *) event)->state & ShiftMask)
1784 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1785 if (((XKeyEvent *) event)->state & ControlMask)
1786 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1788 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1789 *modifiers |= MINPUT_KEY_META_MODIFIER;
1790 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1791 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1792 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1793 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1794 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1795 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1802 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1804 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1806 Display *display = FRAME_DISPLAY (frame);
1807 GCInfo *info = rface->info;
1810 for (i = 0; i <= GC_INVERSE; i++)
1812 XGetGCValues (display, info->gc[i], valuemask, &values);
1813 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1814 values.foreground, values.background);
1815 fprintf (stderr, "\n");
1819 static MDeviceDriver x_driver =
1822 mwin__device_get_prop,
1824 mwin__free_realized_face,
1826 mwin__draw_empty_boxes,
1830 mwin__region_from_rect,
1831 mwin__union_rect_with_region,
1832 mwin__intersect_region,
1833 mwin__region_add_rect,
1834 mwin__region_to_rect,
1837 mwin__create_window,
1838 mwin__destroy_window,
1841 mwin__window_geometry,
1842 mwin__adjust_window,
1846 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1851 M_iso8859_1 = msymbol ("iso8859-1");
1852 M_iso10646_1 = msymbol ("iso10646-1");
1854 display_info_list = mplist ();
1855 device_list = mplist ();
1858 xft_driver.select = mfont__ft_driver.select;
1859 xft_driver.encode_char = mfont__ft_driver.encode_char;
1860 xft_driver.list = mfont__ft_driver.list;
1863 Mxim = msymbol ("xim");
1864 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1872 M17N_OBJECT_UNREF (display_info_list);
1873 M17N_OBJECT_UNREF (device_list);
1877 /** Return an MWDevice object corresponding to a display specified in
1880 It searches device_list for a device matching the display. If
1881 found, return the found object. Otherwise, return a newly created
1885 device_open (MFrame *frame, MPlist *param)
1887 Display *display = NULL;
1888 Screen *screen = NULL;
1890 Drawable drawable = 0;
1891 Widget widget = NULL;
1893 int auto_display = 0;
1894 MDisplayInfo *disp_info = NULL;
1895 MWDevice *device = NULL;
1897 XWindowAttributes attr;
1902 int use_xfont = 1, use_freetype = 1;
1904 for (plist = param; (key = mplist_key (plist)) != Mnil;
1905 plist = mplist_next (plist))
1907 if (key == Mdisplay)
1908 display = (Display *) mplist_value (plist);
1909 else if (key == Mscreen)
1910 screen = mplist_value (plist);
1911 else if (key == Mdrawable)
1912 drawable = (Drawable) mplist_value (plist);
1913 else if (key == Mdepth)
1914 depth = (unsigned) mplist_value (plist);
1915 else if (key == Mwidget)
1916 widget = (Widget) mplist_value (plist);
1917 else if (key == Mcolormap)
1918 cmap = (Colormap) mplist_value (plist);
1919 else if (key == Mfont)
1921 MSymbol val = MPLIST_SYMBOL (plist);
1925 #ifdef HAVE_FREETYPE
1926 else if (val == Mfreetype)
1934 display = XtDisplay (widget);
1935 screen_num = XScreenNumberOfScreen (XtScreen (widget));
1936 depth = DefaultDepth (display, screen_num);
1942 unsigned width, height, border_width;
1945 MERROR (MERROR_WIN, -1);
1946 XGetGeometry (display, drawable, &root_window,
1947 &x, &y, &width, &height, &border_width, &depth);
1948 XGetWindowAttributes (display, root_window, &attr);
1949 screen_num = XScreenNumberOfScreen (attr.screen);
1954 display = DisplayOfScreen (screen);
1959 display = XOpenDisplay (NULL);
1961 MERROR (MERROR_WIN, -1);
1964 screen = DefaultScreenOfDisplay (display);
1966 screen_num = XScreenNumberOfScreen (screen);
1968 depth = DefaultDepth (display, screen_num);
1972 cmap = DefaultColormap (display, screen_num);
1974 for (plist = display_info_list; mplist_key (plist) != Mnil;
1975 plist = mplist_next (plist))
1977 disp_info = (MDisplayInfo *) mplist_value (plist);
1978 if (disp_info->display == display)
1982 if (mplist_key (plist) != Mnil)
1983 M17N_OBJECT_REF (disp_info);
1986 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
1987 disp_info->display = display;
1988 disp_info->auto_display = auto_display;
1989 disp_info->font_list = mplist ();
1990 disp_info->base_font_list = mplist ();
1991 find_modifier_bits (disp_info);
1992 mplist_add (display_info_list, Mt, disp_info);
1995 for (plist = device_list; mplist_key (plist) != Mnil;
1996 plist = mplist_next (plist))
1998 device = (MWDevice *) mplist_value (plist);
1999 if (device->display_info == disp_info
2000 && device->depth == depth
2001 && device->cmap == cmap)
2005 if (mplist_key (plist) != Mnil)
2006 M17N_OBJECT_REF (device);
2009 unsigned long valuemask = GCForeground;
2012 M17N_OBJECT (device, free_device, MERROR_WIN);
2013 device->display_info = disp_info;
2014 device->screen_num = screen_num;
2015 /* A drawable on which to create GCs. */
2016 device->drawable = XCreatePixmap (display,
2017 RootWindow (display, screen_num),
2019 device->depth = depth;
2020 device->cmap = cmap;
2021 device->realized_face_list = mplist ();
2022 device->realized_font_list = mplist ();
2023 device->realized_fontset_list = mplist ();
2024 device->gc_list = mplist ();
2025 values.foreground = BlackPixel (display, screen_num);
2026 device->scratch_gc = XCreateGC (display, device->drawable,
2027 valuemask, &values);
2029 device->xft_draw = XftDrawCreate (display, device->drawable,
2030 DefaultVisual (display, screen_num),
2035 frame->device = device;
2036 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2037 frame->driver = &x_driver;
2038 frame->font_driver_list = mplist ();
2040 mplist_add (frame->font_driver_list, Mx, &xfont_driver);
2043 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2046 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2048 frame->realized_font_list = device->realized_font_list;
2049 frame->realized_face_list = device->realized_face_list;
2050 frame->realized_fontset_list = device->realized_fontset_list;
2054 XtResource resources[] = {
2055 { XtNfont, XtCFont, XtRString, sizeof (String),
2056 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2057 { XtNforeground, XtCForeground, XtRString, sizeof (String),
2058 XtOffset (AppDataPtr, foreground), XtRString, "black" },
2059 { XtNbackground, XtCBackground, XtRString, sizeof (String),
2060 XtOffset (AppDataPtr, background), XtRString, "white" },
2061 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2062 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2065 XtGetApplicationResources (widget, &app_data,
2066 resources, XtNumber (resources), NULL, 0);
2067 frame->foreground = msymbol (app_data.foreground);
2068 frame->background = msymbol (app_data.background);
2069 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2073 app_data.font = DEFAULT_FONT;
2074 frame->foreground = msymbol ("black");
2075 frame->background = msymbol ("white");
2076 frame->videomode = Mnormal;
2081 char **names = XListFonts (display, app_data.font, 1, &nfonts);
2085 if (! (frame->font = mfont_parse_name (names[0], Mx)))
2087 /* The font name does not conform to XLFD. Try to open the
2088 font and get XA_FONT property. */
2089 XFontStruct *xfont = XLoadQueryFont (display, names[0]);
2094 unsigned long value;
2097 if (XGetFontProperty (xfont, XA_FONT, &value)
2098 && (name = ((char *)
2099 XGetAtomName (display, (Atom) value))))
2101 if ((frame->font = mfont_parse_name (name, Mx)))
2104 XFreeFont (display, xfont);
2107 XFreeFontNames (names);
2110 frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
2113 face = mface_from_font (frame->font);
2114 face->property[MFACE_FONTSET] = mfontset (NULL);
2115 face->property[MFACE_FOREGROUND] = frame->foreground;
2116 face->property[MFACE_BACKGROUND] = frame->background;
2117 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2118 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2119 face->property[MFACE_VIDEOMODE] = frame->videomode;
2120 mface_put_prop (face, Mhook_func,
2121 mface_get_prop (mface__default, Mhook_func));
2122 face->property[MFACE_RATIO] = (void *) 100;
2123 mplist_push (param, Mface, face);
2124 M17N_OBJECT_UNREF (face);
2126 #ifdef X_SET_ERROR_HANDLER
2127 XSetErrorHandler (x_error_handler);
2128 XSetIOErrorHandler (x_io_error_handler);
2136 /* XIM (X Input Method) handler */
2138 typedef struct MInputXIMMethodInfo
2144 } MInputXIMMethodInfo;
2146 typedef struct MInputXIMContextInfo
2150 MConverter *converter;
2151 } MInputXIMContextInfo;
2154 xim_open_im (MInputMethod *im)
2156 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2157 MLocale *saved, *this;
2158 char *save_modifier_list;
2160 MInputXIMMethodInfo *im_info;
2162 saved = mlocale_set (LC_CTYPE, NULL);
2163 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2165 /* The specified locale is not supported. */
2166 MERROR (MERROR_LOCALE, -1);
2167 if (mlocale_get_prop (this, Mcoding) == Mnil)
2169 /* Unable to decode the output of XIM. */
2170 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2171 MERROR (MERROR_LOCALE, -1);
2174 if (arg->modifier_list)
2175 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2177 save_modifier_list = XSetLocaleModifiers ("");
2178 if (! save_modifier_list)
2180 /* The specified locale is not supported by X. */
2181 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2182 MERROR (MERROR_LOCALE, -1);
2185 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2188 /* No input method is available in the current locale. */
2189 XSetLocaleModifiers (save_modifier_list);
2190 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2191 MERROR (MERROR_WIN, -1);
2194 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2195 im_info->display = arg->display;
2197 im_info->language = mlocale_get_prop (this, Mlanguage);
2198 im_info->coding = mlocale_get_prop (this, Mcoding);
2201 XSetLocaleModifiers (save_modifier_list);
2202 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2208 xim_close_im (MInputMethod *im)
2210 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2212 XCloseIM (im_info->xim);
2217 xim_create_ic (MInputContext *ic)
2219 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2220 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2221 MInputXIMContextInfo *ic_info;
2224 if (! arg->input_style)
2226 /* By default, use Root style. */
2227 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2228 arg->preedit_attrs = NULL;
2229 arg->status_attrs = NULL;
2232 if (! arg->preedit_attrs && ! arg->status_attrs)
2233 xic = XCreateIC (im_info->xim,
2234 XNInputStyle, arg->input_style,
2235 XNClientWindow, arg->client_win,
2236 XNFocusWindow, arg->focus_win,
2238 else if (arg->preedit_attrs && ! arg->status_attrs)
2239 xic = XCreateIC (im_info->xim,
2240 XNInputStyle, arg->input_style,
2241 XNClientWindow, arg->client_win,
2242 XNFocusWindow, arg->focus_win,
2243 XNPreeditAttributes, arg->preedit_attrs,
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 XNStatusAttributes, 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 XNPreeditAttributes, arg->preedit_attrs,
2258 XNStatusAttributes, arg->status_attrs,
2261 MERROR (MERROR_WIN, -1);
2263 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2265 ic_info->win = arg->focus_win;
2266 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2272 xim_destroy_ic (MInputContext *ic)
2274 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2276 XDestroyIC (ic_info->xic);
2277 mconv_free_converter (ic_info->converter);
2283 xim_filter (MInputContext *ic, MSymbol key, void *event)
2285 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2287 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2292 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2294 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2295 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2296 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2302 buf = (char *) alloca (512);
2303 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2304 if (status == XBufferOverflow)
2306 buf = (char *) alloca (len);
2307 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2310 mtext_reset (ic->produced);
2314 mconv_reset_converter (ic_info->converter);
2315 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2316 mconv_decode (ic_info->converter, ic->produced);
2317 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2318 Mlanguage, (void *) im_info->language);
2319 mtext_cpy (mt, ic->produced);
2320 mtext_reset (ic->produced);
2326 #ifdef X_SET_ERROR_HANDLER
2328 x_error_handler (Display *display, XErrorEvent *error)
2335 x_io_error_handler (Display *display)
2345 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2349 /*** @addtogroup m17nInputMethodWin */
2354 @brief Input method driver for XIM.
2356 The driver #minput_xim_driver is for the foreign input method of
2357 name #Mxim. It uses XIM (X Input Methods) as a background input
2360 As the symbol #Mxim has property #Minput_driver whose value is
2361 a pointer to this driver, the input method of language #Mnil
2362 and name #Mxim uses this driver.
2364 Therefore, for such input methods, the driver dependent arguments
2365 to the functions whose name begin with minput_ must be as follows.
2367 The argument $ARG of the function minput_open_im () must be a
2368 pointer to the structure #MInputXIMArgIM. See the documentation
2369 of #MInputXIMArgIM for more details.
2371 The argument $ARG of the function minput_create_ic () must be a
2372 pointer to the structure #MInputXIMArgIC. See the documentation
2373 of #MInputXIMArgIC for more details.
2375 The argument $ARG of the function minput_filter () must be a
2376 pointer to the structure @c XEvent. The argument $KEY is ignored.
2378 The argument $ARG of the function minput_lookup () must be the
2379 same one as that of the function minput_filter (). The argument
2383 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2385 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
2386 ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
2389 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2390 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
2391 ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2393 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
2394 ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2396 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM ¤Ø¤Î¥Ý
2397 ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
2400 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC ¤Ø¤Î
2401 ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
2404 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2405 ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2407 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2408 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2411 MInputDriver minput_xim_driver =
2412 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2413 xim_filter, xim_lookup, NULL };