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 void xfont_list (MFrame *frame, MPlist *plist,
431 MFont *font, MSymbol language);
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)
908 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
909 MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil;
910 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)
922 mplist_push (plist, MPLIST_KEY (p), MPLIST_VAL (p));
925 MXFontList *xfontlist;
929 pl = disp_info->font_list;
930 if (registry != Mnil)
932 pl = mplist_find_by_key (pl, registry);
942 p = mplist_find_by_key (p, family);
948 xfontlist = MPLIST_VAL (p);
949 for (i = 0; i < xfontlist->used; i++)
951 xfont = xfontlist->fonts + i;
952 if (mfont__match_p (&xfont->core, font, MFONT_REGISTRY))
953 mplist_push (plist, MPLIST_KEY (p), &xfont->core);
958 if (registry != Mnil)
977 static int xft_open (MRealizedFont *);
978 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
979 static void xft_render (MDrawWindow, int, int, MGlyphString *,
980 MGlyph *, MGlyph *, int, MDrawRegion);
982 MFontDriver xft_driver =
983 { NULL, /* Set to ft_select in device_init (). */
984 xft_open, xft_find_metric,
985 NULL, /* Set to ft_encode_char in device_init (). */
987 NULL /* Set to ft_list in device_init (). */
992 close_xft (void *object)
994 MXftFontInfo *font_info = object;
996 XftFontClose (font_info->display, font_info->font_aa);
997 XftFontClose (font_info->display, font_info->font_no_aa);
1003 xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
1005 XftPattern *pattern;
1006 XftFontInfo *xft_font_info;
1009 pattern = XftPatternCreate ();
1010 XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
1011 XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
1012 XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
1013 xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
1014 if (! xft_font_info)
1016 font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
1017 XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
1023 xft_open (MRealizedFont *rfont)
1027 MXftFontInfo *font_info;
1030 if ((mfont__ft_driver.open) (rfont) < 0)
1033 size = rfont->font.property[MFONT_SIZE] / 10;
1034 frame = rfont->frame;
1036 ft_info = rfont->info;
1037 M17N_OBJECT (font_info, close_xft, MERROR_WIN);
1038 ft_info->extra_info = font_info;
1039 font_info->display = FRAME_DISPLAY (frame);
1040 font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
1041 if (font_info->font_aa)
1043 font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
1044 if (font_info->font_no_aa)
1047 rfont->fontp = font_info->font_no_aa;
1050 XftFontClose (FRAME_DISPLAY (rfont->frame), font_info->font_aa);
1053 ft_info->extra_info = NULL;
1060 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1063 MFTInfo *ft_info = rfont->info;
1064 MXftFontInfo *font_info = ft_info->extra_info;
1065 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1067 for (; g != gend; g++)
1069 if (g->code == MCHAR_INVALID_CODE)
1071 MGlyph *start = g++;
1073 while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
1074 (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
1082 XftGlyphExtents (FRAME_DISPLAY (gstring->frame),
1083 font_info->font_aa, &g->code, 1, &extents);
1084 g->lbearing = - extents.x;
1085 g->rbearing = extents.width - extents.x;
1086 g->width = extents.xOff;
1087 g->ascent = extents.y;
1088 g->descent = extents.height - extents.y;
1095 xft_render (MDrawWindow win, int x, int y,
1096 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1097 int reverse, MDrawRegion region)
1099 MRealizedFace *rface = from->rface;
1100 MFrame *frame = rface->frame;
1101 MFTInfo *ft_info = rface->rfont->info;
1102 MXftFontInfo *font_info = ft_info->extra_info;
1103 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1104 XftColor *xft_color = (! reverse
1105 ? &((GCInfo *) rface->info)->xft_color_fore
1106 : &((GCInfo *) rface->info)->xft_color_back);
1107 XftFont *xft_font = (gstring->control.anti_alias
1108 && FRAME_DEVICE (frame)->depth > 1
1109 ? font_info->font_aa : font_info->font_no_aa);
1118 XftDrawChange (xft_draw, (Drawable) win);
1119 XftDrawSetClip (xft_draw, (Region) region);
1121 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1122 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1124 if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1125 glyphs[nglyphs++] = g->code;
1129 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1130 last_x, y, glyphs, nglyphs);
1132 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1133 x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1134 last_x = x + g->width;
1138 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1144 /* Functions for the device driver. */
1147 mwin__close_device (MFrame *frame)
1149 M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
1153 mwin__device_get_prop (MFrame *frame, MSymbol key)
1155 MWDevice *device = FRAME_DEVICE (frame);
1157 if (key == Mdisplay)
1158 return (void *) device->display_info->display;
1160 return (void *) ScreenOfDisplay(device->display_info->display,
1161 device->screen_num);
1162 if (key == Mcolormap)
1163 return (void *) device->cmap;
1165 return (void *) device->depth;
1170 mwin__realize_face (MRealizedFace *rface)
1173 MSymbol foreground, background, videomode;
1174 MFaceHLineProp *hline;
1178 if (rface != rface->ascii_rface)
1180 rface->info = rface->ascii_rface->info;
1184 frame = rface->frame;
1185 MSTRUCT_CALLOC (info, MERROR_WIN);
1187 foreground = rface->face.property[MFACE_FOREGROUND];
1188 background = rface->face.property[MFACE_BACKGROUND];
1189 videomode = rface->face.property[MFACE_VIDEOMODE];
1191 videomode = frame->videomode;
1192 if (videomode != Mreverse)
1194 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1195 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1199 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1200 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1203 if (foreground == Mnil)
1204 foreground = frame->foreground;
1205 if (background == Mnil)
1206 background = frame->background;
1207 if (videomode == Mreverse)
1209 MSymbol temp = foreground;
1210 foreground = background;
1213 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1214 FRAME_VISUAL (frame),
1216 MSYMBOL_NAME (foreground),
1217 &info->xft_color_fore))
1219 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1220 FRAME_VISUAL (frame),
1222 MSYMBOL_NAME (background),
1223 &info->xft_color_back))
1227 hline = rface->hline;
1231 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1233 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1240 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1242 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1244 if (box->color_left && box->color_left != box->color_top)
1245 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1247 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1249 if (box->color_bottom && box->color_bottom != box->color_top)
1250 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1252 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1254 if (box->color_right && box->color_right != box->color_bottom)
1255 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1257 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1265 mwin__free_realized_face (MRealizedFace *rface)
1267 if (rface == rface->ascii_rface)
1273 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1275 int x, int y, int width, int height, MDrawRegion region)
1277 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1280 gc = set_region (frame, gc, region);
1282 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1283 x, y, width, height);
1288 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1289 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1290 int reverse, MDrawRegion region)
1292 MRealizedFace *rface = from->rface;
1293 Display *display = FRAME_DISPLAY (rface->frame);
1294 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1300 gc = set_region (rface->frame, gc, region);
1301 for (; from < to; from++)
1303 XDrawRectangle (display, (Window) win, gc,
1304 x, y - gstring->ascent + 1, from->width - 1,
1305 gstring->ascent + gstring->descent - 2);
1312 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1313 MRealizedFace *rface, int reverse,
1314 int x, int y, int width, MDrawRegion region)
1316 enum MFaceHLineType type = rface->hline->type;
1317 GCInfo *info = rface->info;
1318 GC gc = gc = info->gc[GC_HLINE];
1321 y = (type == MFACE_HLINE_BOTTOM
1322 ? y + gstring->text_descent - rface->hline->width
1323 : type == MFACE_HLINE_UNDER
1325 : type == MFACE_HLINE_STRIKE_THROUGH
1326 ? y - ((gstring->ascent + gstring->descent) / 2)
1327 : y - gstring->text_ascent);
1329 gc = set_region (frame, gc, region);
1331 for (i = 0; i < rface->hline->width; i++)
1332 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1333 x, y + i, x + width - 1, y + i);
1338 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1339 MGlyph *g, int x, int y, int width, MDrawRegion region)
1341 Display *display = FRAME_DISPLAY (frame);
1342 MRealizedFace *rface = g->rface;
1343 MFaceBoxProp *box = rface->box;
1344 GCInfo *info = rface->info;
1345 GC gc_top, gc_left, gc_right, gc_btm;
1349 y0 = y - (gstring->text_ascent
1350 + rface->box->inner_vmargin + rface->box->width);
1351 y1 = y + (gstring->text_descent
1352 + rface->box->inner_vmargin + rface->box->width - 1);
1354 gc_top = info->gc[GC_BOX_TOP];
1356 gc_top = set_region (frame, gc_top, region);
1357 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1360 gc_btm = info->gc[GC_BOX_BOTTOM];
1362 if (g->type == GLYPH_BOX)
1366 if (g->left_padding)
1367 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1369 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1371 /* Draw the top side. */
1372 for (i = 0; i < box->width; i++)
1373 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1375 /* Draw the bottom side. */
1376 if (region && gc_btm != gc_top)
1377 gc_btm = set_region (frame, gc_btm, region);
1378 for (i = 0; i < box->width; i++)
1379 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1381 if (g->left_padding > 0)
1383 /* Draw the left side. */
1384 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1388 gc_left = info->gc[GC_BOX_LEFT];
1390 gc_left = set_region (frame, gc_left, region);
1392 for (i = 0; i < rface->box->width; i++)
1393 XDrawLine (display, (Window) win, gc_left,
1394 x0 + i, y0 + i, x0 + i, y1 - i);
1398 /* Draw the right side. */
1399 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1403 gc_right = info->gc[GC_BOX_RIGHT];
1405 gc_right = set_region (frame, gc_right, region);
1407 for (i = 0; i < rface->box->width; i++)
1408 XDrawLine (display, (Window) win, gc_right,
1409 x1 - i, y0 + i, x1 - i, y1 - i);
1414 /* Draw the top side. */
1415 for (i = 0; i < box->width; i++)
1416 XDrawLine (display, (Window) win, gc_top,
1417 x, y0 + i, x + width - 1, y0 + i);
1419 /* Draw the bottom side. */
1420 if (region && gc_btm != gc_top)
1421 gc_btm = set_region (frame, gc_btm, region);
1422 for (i = 0; i < box->width; i++)
1423 XDrawLine (display, (Window) win, gc_btm,
1424 x, y1 - i, x + width - 1, y1 - i);
1431 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1432 int reverse, int x, int y,
1433 int width, int height, int row_bytes, unsigned char *bmp,
1436 Display *display = FRAME_DISPLAY (frame);
1438 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1441 gc = set_region (frame, gc, region);
1443 for (i = 0; i < height; i++, bmp += row_bytes)
1444 for (j = 0; j < width; j++)
1445 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1446 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1451 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1452 int intensity, MDrawPoint *points, int num,
1455 GCInfo *info = rface->info;
1458 if (! (gc = info->gc[intensity]))
1459 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1462 gc = set_region (frame, gc, region);
1464 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1465 (XPoint *) points, num, CoordModeOrigin);
1470 mwin__region_from_rect (MDrawMetric *rect)
1472 MDrawRegion region1 = XCreateRegion ();
1473 MDrawRegion region2 = XCreateRegion ();
1478 xrect.width = rect->width;
1479 xrect.height = rect->height;
1480 XUnionRectWithRegion (&xrect, region1, region2);
1481 XDestroyRegion (region1);
1486 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1488 MDrawRegion region1 = XCreateRegion ();
1493 xrect.width = rect->width;
1494 xrect.height = rect->height;
1496 XUnionRegion (region, region, region1);
1497 XUnionRectWithRegion (&xrect, region1, region);
1498 XDestroyRegion (region1);
1502 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1504 MDrawRegion region = XCreateRegion ();
1506 XUnionRegion (region1, region1, region);
1507 XIntersectRegion (region, region2, region1);
1508 XDestroyRegion (region);
1512 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1514 MDrawRegion region1 = XCreateRegion ();
1519 xrect.width = rect->width;
1520 xrect.height = rect->height;
1521 XUnionRectWithRegion (&xrect, region1, region);
1522 XDestroyRegion (region1);
1526 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1530 XClipBox (region, &xrect);
1533 rect->width = xrect.width;
1534 rect->height = xrect.height;
1538 mwin__free_region (MDrawRegion region)
1540 XDestroyRegion (region);
1544 mwin__dump_region (MDrawRegion region)
1547 XClipBox (region, &rect);
1548 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1553 mwin__create_window (MFrame *frame, MDrawWindow parent)
1555 Display *display = FRAME_DISPLAY (frame);
1557 XWMHints wm_hints = { InputHint, False };
1558 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1559 XSetWindowAttributes set_attrs;
1562 GCInfo *info = frame->rface->info;
1565 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1566 mask = GCForeground;
1567 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1568 set_attrs.background_pixel = values.foreground;
1569 set_attrs.backing_store = Always;
1570 set_attrs.override_redirect = True;
1571 set_attrs.save_under = True;
1572 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1573 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1574 CopyFromParent, InputOutput, CopyFromParent,
1576 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1577 NULL, &wm_hints, &class_hints);
1578 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1579 return (MDrawWindow) win;
1583 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1585 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1590 mwin__event_window (void *event)
1592 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1596 mwin__print_event (void *arg, char *win_name)
1599 XEvent *event = (XEvent *) arg;
1601 switch (event->xany.type)
1603 case 2: event_name = "KeyPress"; break;
1604 case 3: event_name = "KeyRelease"; break;
1605 case 4: event_name = "ButtonPress"; break;
1606 case 5: event_name = "ButtonRelease"; break;
1607 case 6: event_name = "MotionNotify"; break;
1608 case 7: event_name = "EnterNotify"; break;
1609 case 8: event_name = "LeaveNotify"; break;
1610 case 9: event_name = "FocusIn"; break;
1611 case 10: event_name = "FocusOut"; break;
1612 case 11: event_name = "KeymapNotify"; break;
1613 case 12: event_name = "Expose"; break;
1614 case 13: event_name = "GraphicsExpose"; break;
1615 case 14: event_name = "NoExpose"; break;
1616 case 15: event_name = "VisibilityNotify"; break;
1617 case 16: event_name = "CreateNotify"; break;
1618 case 17: event_name = "DestroyNotify"; break;
1619 case 18: event_name = "UnmapNotify"; break;
1620 case 19: event_name = "MapNotify"; break;
1621 case 20: event_name = "MapRequest"; break;
1622 case 21: event_name = "ReparentNotify"; break;
1623 case 22: event_name = "ConfigureNotify"; break;
1624 case 23: event_name = "ConfigureRequest"; break;
1625 case 24: event_name = "GravityNotify"; break;
1626 case 25: event_name = "ResizeRequest"; break;
1627 case 26: event_name = "CirculateNotify"; break;
1628 case 27: event_name = "CirculateRequest"; break;
1629 case 28: event_name = "PropertyNotify"; break;
1630 case 29: event_name = "SelectionClear"; break;
1631 case 30: event_name = "SelectionRequest"; break;
1632 case 31: event_name = "SelectionNotify"; break;
1633 case 32: event_name = "ColormapNotify"; break;
1634 case 33: event_name = "ClientMessage"; break;
1635 case 34: event_name = "MappingNotify"; break;
1636 default: event_name = "unknown";
1639 fprintf (stderr, "%s: %s\n", win_name, event_name);
1644 mwin__map_window (MFrame *frame, MDrawWindow win)
1646 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1650 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1652 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1656 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1657 MDrawMetric *geometry)
1659 Display *display = FRAME_DISPLAY (frame);
1660 XWindowAttributes attr;
1661 Window parent = (Window) parent_win, root;
1663 XGetWindowAttributes (display, (Window) win, &attr);
1664 geometry->x = attr.x + attr.border_width;
1665 geometry->y = attr.y + attr.border_width;
1666 geometry->width = attr.width;
1667 geometry->height = attr.height;
1670 parent = RootWindow (display, FRAME_SCREEN (frame));
1673 Window this_parent, *children;
1676 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1679 if (this_parent == parent || this_parent == root)
1681 win = (MDrawWindow) this_parent;
1682 XGetWindowAttributes (display, (Window) win, &attr);
1683 geometry->x += attr.x + attr.border_width;
1684 geometry->y += attr.y + attr.border_width;
1689 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1690 MDrawMetric *current, MDrawMetric *new)
1692 Display *display = FRAME_DISPLAY (frame);
1693 unsigned int mask = 0;
1694 XWindowChanges values;
1696 if (current->width != new->width)
1699 if (new->width <= 0)
1701 values.width = current->width = new->width;
1703 if (current->height != new->height)
1706 if (new->height <= 0)
1708 values.height = current->height = new->height;
1710 if (current->x != new->x)
1713 values.x = current->x = new->x;
1715 if (current->y != new->y)
1718 current->y = new->y;
1719 values.y = current->y = new->y;
1722 XConfigureWindow (display, (Window) win, mask, &values);
1723 XClearWindow (display, (Window) win);
1727 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1729 XEvent *event = (XEvent *) arg;
1730 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1737 if (event->xany.type != KeyPress
1738 /* && event->xany.type != KeyRelease */
1741 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1748 if (c < XK_space || c > XK_asciitilde)
1750 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1751 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1752 if (((XKeyEvent *) event)->state & ControlMask)
1754 if (c >= 'a' && c <= 'z')
1756 if (c >= ' ' && c < 127)
1757 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1759 key = minput__char_to_key (c);
1761 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1765 char *str = XKeysymToString (keysym);
1769 key = msymbol (str);
1770 if (((XKeyEvent *) event)->state & ShiftMask)
1771 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1772 if (((XKeyEvent *) event)->state & ControlMask)
1773 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1775 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1776 *modifiers |= MINPUT_KEY_META_MODIFIER;
1777 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1778 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1779 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1780 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1781 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1782 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1789 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1791 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1793 Display *display = FRAME_DISPLAY (frame);
1794 GCInfo *info = rface->info;
1797 for (i = 0; i <= GC_INVERSE; i++)
1799 XGetGCValues (display, info->gc[i], valuemask, &values);
1800 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1801 values.foreground, values.background);
1802 fprintf (stderr, "\n");
1806 static MDeviceDriver x_driver =
1809 mwin__device_get_prop,
1811 mwin__free_realized_face,
1813 mwin__draw_empty_boxes,
1817 mwin__region_from_rect,
1818 mwin__union_rect_with_region,
1819 mwin__intersect_region,
1820 mwin__region_add_rect,
1821 mwin__region_to_rect,
1824 mwin__create_window,
1825 mwin__destroy_window,
1828 mwin__window_geometry,
1829 mwin__adjust_window,
1833 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1838 M_iso8859_1 = msymbol ("iso8859-1");
1839 M_iso10646_1 = msymbol ("iso10646-1");
1841 display_info_list = mplist ();
1842 device_list = mplist ();
1845 xft_driver.select = mfont__ft_driver.select;
1846 xft_driver.encode_char = mfont__ft_driver.encode_char;
1847 xft_driver.list = mfont__ft_driver.list;
1850 Mxim = msymbol ("xim");
1851 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1859 M17N_OBJECT_UNREF (display_info_list);
1860 M17N_OBJECT_UNREF (device_list);
1864 /** Return an MWDevice object corresponding to a display specified in
1867 It searches device_list for a device matching the display. If
1868 found, return the found object. Otherwise, return a newly created
1872 device_open (MFrame *frame, MPlist *param)
1874 Display *display = NULL;
1875 Screen *screen = NULL;
1877 Drawable drawable = 0;
1878 Widget widget = NULL;
1880 int auto_display = 0;
1881 MDisplayInfo *disp_info = NULL;
1882 MWDevice *device = NULL;
1884 XWindowAttributes attr;
1889 int use_xfont = 1, use_freetype = 1;
1891 for (plist = param; (key = mplist_key (plist)) != Mnil;
1892 plist = mplist_next (plist))
1894 if (key == Mdisplay)
1895 display = (Display *) mplist_value (plist);
1896 else if (key == Mscreen)
1897 screen = mplist_value (plist);
1898 else if (key == Mdrawable)
1899 drawable = (Drawable) mplist_value (plist);
1900 else if (key == Mdepth)
1901 depth = (unsigned) mplist_value (plist);
1902 else if (key == Mwidget)
1903 widget = (Widget) mplist_value (plist);
1904 else if (key == Mcolormap)
1905 cmap = (Colormap) mplist_value (plist);
1906 else if (key == Mfont)
1908 MSymbol val = MPLIST_SYMBOL (plist);
1912 #ifdef HAVE_FREETYPE
1913 else if (val == Mfreetype)
1921 display = XtDisplay (widget);
1922 screen_num = XScreenNumberOfScreen (XtScreen (widget));
1923 depth = DefaultDepth (display, screen_num);
1929 unsigned width, height, border_width;
1932 MERROR (MERROR_WIN, -1);
1933 XGetGeometry (display, drawable, &root_window,
1934 &x, &y, &width, &height, &border_width, &depth);
1935 XGetWindowAttributes (display, root_window, &attr);
1936 screen_num = XScreenNumberOfScreen (attr.screen);
1941 display = DisplayOfScreen (screen);
1946 display = XOpenDisplay (NULL);
1948 MERROR (MERROR_WIN, -1);
1951 screen = DefaultScreenOfDisplay (display);
1953 screen_num = XScreenNumberOfScreen (screen);
1955 depth = DefaultDepth (display, screen_num);
1959 cmap = DefaultColormap (display, screen_num);
1961 for (plist = display_info_list; mplist_key (plist) != Mnil;
1962 plist = mplist_next (plist))
1964 disp_info = (MDisplayInfo *) mplist_value (plist);
1965 if (disp_info->display == display)
1969 if (mplist_key (plist) != Mnil)
1970 M17N_OBJECT_REF (disp_info);
1973 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
1974 disp_info->display = display;
1975 disp_info->auto_display = auto_display;
1976 disp_info->font_list = mplist ();
1977 disp_info->base_font_list = mplist ();
1978 find_modifier_bits (disp_info);
1979 mplist_add (display_info_list, Mt, disp_info);
1982 for (plist = device_list; mplist_key (plist) != Mnil;
1983 plist = mplist_next (plist))
1985 device = (MWDevice *) mplist_value (plist);
1986 if (device->display_info == disp_info
1987 && device->depth == depth
1988 && device->cmap == cmap)
1992 if (mplist_key (plist) != Mnil)
1993 M17N_OBJECT_REF (device);
1996 unsigned long valuemask = GCForeground;
1999 M17N_OBJECT (device, free_device, MERROR_WIN);
2000 device->display_info = disp_info;
2001 device->screen_num = screen_num;
2002 /* A drawable on which to create GCs. */
2003 device->drawable = XCreatePixmap (display,
2004 RootWindow (display, screen_num),
2006 device->depth = depth;
2007 device->cmap = cmap;
2008 device->realized_face_list = mplist ();
2009 device->realized_font_list = mplist ();
2010 device->realized_fontset_list = mplist ();
2011 device->gc_list = mplist ();
2012 values.foreground = BlackPixel (display, screen_num);
2013 device->scratch_gc = XCreateGC (display, device->drawable,
2014 valuemask, &values);
2016 device->xft_draw = XftDrawCreate (display, device->drawable,
2017 DefaultVisual (display, screen_num),
2022 frame->device = device;
2023 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2024 frame->driver = &x_driver;
2025 frame->font_driver_list = mplist ();
2027 mplist_add (frame->font_driver_list, Mx, &xfont_driver);
2030 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2033 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2035 frame->realized_font_list = device->realized_font_list;
2036 frame->realized_face_list = device->realized_face_list;
2037 frame->realized_fontset_list = device->realized_fontset_list;
2041 XtResource resources[] = {
2042 { XtNfont, XtCFont, XtRString, sizeof (String),
2043 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2044 { XtNforeground, XtCForeground, XtRString, sizeof (String),
2045 XtOffset (AppDataPtr, foreground), XtRString, "black" },
2046 { XtNbackground, XtCBackground, XtRString, sizeof (String),
2047 XtOffset (AppDataPtr, background), XtRString, "white" },
2048 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2049 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2052 XtGetApplicationResources (widget, &app_data,
2053 resources, XtNumber (resources), NULL, 0);
2054 frame->foreground = msymbol (app_data.foreground);
2055 frame->background = msymbol (app_data.background);
2056 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2060 app_data.font = DEFAULT_FONT;
2061 frame->foreground = msymbol ("black");
2062 frame->background = msymbol ("white");
2063 frame->videomode = Mnormal;
2068 char **names = XListFonts (display, app_data.font, 1, &nfonts);
2072 if (! (frame->font = mfont_parse_name (names[0], Mx)))
2074 /* The font name does not conform to XLFD. Try to open the
2075 font and get XA_FONT property. */
2076 XFontStruct *xfont = XLoadQueryFont (display, names[0]);
2081 unsigned long value;
2084 if (XGetFontProperty (xfont, XA_FONT, &value)
2085 && (name = ((char *)
2086 XGetAtomName (display, (Atom) value))))
2088 if ((frame->font = mfont_parse_name (name, Mx)))
2091 XFreeFont (display, xfont);
2094 XFreeFontNames (names);
2097 frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
2100 face = mface_from_font (frame->font);
2101 face->property[MFACE_FONTSET] = mfontset (NULL);
2102 face->property[MFACE_FOREGROUND] = frame->foreground;
2103 face->property[MFACE_BACKGROUND] = frame->background;
2104 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2105 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2106 face->property[MFACE_VIDEOMODE] = frame->videomode;
2107 mface_put_prop (face, Mhook_func,
2108 mface_get_prop (mface__default, Mhook_func));
2109 face->property[MFACE_RATIO] = (void *) 100;
2110 mplist_push (param, Mface, face);
2111 M17N_OBJECT_UNREF (face);
2113 #ifdef X_SET_ERROR_HANDLER
2114 XSetErrorHandler (x_error_handler);
2115 XSetIOErrorHandler (x_io_error_handler);
2123 /* XIM (X Input Method) handler */
2125 typedef struct MInputXIMMethodInfo
2131 } MInputXIMMethodInfo;
2133 typedef struct MInputXIMContextInfo
2137 MConverter *converter;
2138 } MInputXIMContextInfo;
2141 xim_open_im (MInputMethod *im)
2143 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2144 MLocale *saved, *this;
2145 char *save_modifier_list;
2147 MInputXIMMethodInfo *im_info;
2149 saved = mlocale_set (LC_CTYPE, NULL);
2150 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2152 /* The specified locale is not supported. */
2153 MERROR (MERROR_LOCALE, -1);
2154 if (mlocale_get_prop (this, Mcoding) == Mnil)
2156 /* Unable to decode the output of XIM. */
2157 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2158 MERROR (MERROR_LOCALE, -1);
2161 if (arg->modifier_list)
2162 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2164 save_modifier_list = XSetLocaleModifiers ("");
2165 if (! save_modifier_list)
2167 /* The specified locale is not supported by X. */
2168 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2169 MERROR (MERROR_LOCALE, -1);
2172 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2175 /* No input method is available in the current locale. */
2176 XSetLocaleModifiers (save_modifier_list);
2177 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2178 MERROR (MERROR_WIN, -1);
2181 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2182 im_info->display = arg->display;
2184 im_info->language = mlocale_get_prop (this, Mlanguage);
2185 im_info->coding = mlocale_get_prop (this, Mcoding);
2188 XSetLocaleModifiers (save_modifier_list);
2189 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2195 xim_close_im (MInputMethod *im)
2197 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2199 XCloseIM (im_info->xim);
2204 xim_create_ic (MInputContext *ic)
2206 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2207 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2208 MInputXIMContextInfo *ic_info;
2211 if (! arg->input_style)
2213 /* By default, use Root style. */
2214 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2215 arg->preedit_attrs = NULL;
2216 arg->status_attrs = NULL;
2219 if (! arg->preedit_attrs && ! arg->status_attrs)
2220 xic = XCreateIC (im_info->xim,
2221 XNInputStyle, arg->input_style,
2222 XNClientWindow, arg->client_win,
2223 XNFocusWindow, arg->focus_win,
2225 else if (arg->preedit_attrs && ! arg->status_attrs)
2226 xic = XCreateIC (im_info->xim,
2227 XNInputStyle, arg->input_style,
2228 XNClientWindow, arg->client_win,
2229 XNFocusWindow, arg->focus_win,
2230 XNPreeditAttributes, arg->preedit_attrs,
2232 else 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,
2237 XNStatusAttributes, arg->status_attrs,
2240 xic = XCreateIC (im_info->xim,
2241 XNInputStyle, arg->input_style,
2242 XNClientWindow, arg->client_win,
2243 XNFocusWindow, arg->focus_win,
2244 XNPreeditAttributes, arg->preedit_attrs,
2245 XNStatusAttributes, arg->status_attrs,
2248 MERROR (MERROR_WIN, -1);
2250 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2252 ic_info->win = arg->focus_win;
2253 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2259 xim_destroy_ic (MInputContext *ic)
2261 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2263 XDestroyIC (ic_info->xic);
2264 mconv_free_converter (ic_info->converter);
2270 xim_filter (MInputContext *ic, MSymbol key, void *event)
2272 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2274 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2279 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2281 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2282 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2283 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2289 buf = (char *) alloca (512);
2290 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2291 if (status == XBufferOverflow)
2293 buf = (char *) alloca (len);
2294 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2297 mtext_reset (ic->produced);
2301 mconv_reset_converter (ic_info->converter);
2302 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2303 mconv_decode (ic_info->converter, ic->produced);
2304 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2305 Mlanguage, (void *) im_info->language);
2306 mtext_cpy (mt, ic->produced);
2307 mtext_reset (ic->produced);
2313 #ifdef X_SET_ERROR_HANDLER
2315 x_error_handler (Display *display, XErrorEvent *error)
2322 x_io_error_handler (Display *display)
2332 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2336 /*** @addtogroup m17nInputMethodWin */
2341 @brief Input method driver for XIM.
2343 The driver #minput_xim_driver is for the foreign input method of
2344 name #Mxim. It uses XIM (X Input Methods) as a background input
2347 As the symbol #Mxim has property #Minput_driver whose value is
2348 a pointer to this driver, the input method of language #Mnil
2349 and name #Mxim uses this driver.
2351 Therefore, for such input methods, the driver dependent arguments
2352 to the functions whose name begin with minput_ must be as follows.
2354 The argument $ARG of the function minput_open_im () must be a
2355 pointer to the structure #MInputXIMArgIM. See the documentation
2356 of #MInputXIMArgIM for more details.
2358 The argument $ARG of the function minput_create_ic () must be a
2359 pointer to the structure #MInputXIMArgIC. See the documentation
2360 of #MInputXIMArgIC for more details.
2362 The argument $ARG of the function minput_filter () must be a
2363 pointer to the structure @c XEvent. The argument $KEY is ignored.
2365 The argument $ARG of the function minput_lookup () must be the
2366 same one as that of the function minput_filter (). The argument
2370 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2372 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
2373 ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
2376 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2377 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
2378 ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2380 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
2381 ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2383 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM ¤Ø¤Î¥Ý
2384 ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
2387 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC ¤Ø¤Î
2388 ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
2391 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2392 ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2394 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2395 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2398 MInputDriver minput_xim_driver =
2399 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2400 xim_filter, xim_lookup, NULL };