1 /* m17n-X.c -- implementation of the GUI API on X Windows.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
24 /*** @addtogroup m17nInternal
36 #include <X11/keysym.h>
37 #include <X11/Xlocale.h>
38 #include <X11/Xutil.h>
39 #include <X11/Xresource.h>
40 #include <X11/Xatom.h>
41 #include <X11/StringDefs.h>
42 #include <X11/Intrinsic.h>
45 #include <X11/Xft/Xft.h>
46 #endif /* HAVE_XFT2 */
50 #include "m17n-misc.h"
52 #include "internal-gui.h"
61 unsigned int sizes[2];
64 #define SET_SIZE(xfont, s) ((xfont)->sizes[(s) / 32] |= (1 << ((s) & 0x1F)))
65 #define HAVE_SIZE(xfont, s) ((xfont)->sizes[(s) / 32] & (1 << ((s) & 0x1F)))
74 /* Common header for the m17n object. */
79 /* If nonzero, <display> is opened by this library. Thus it should
80 be closed on freeing this structure. */
83 /** List of available X-core fonts on the display. Keys are
84 registries and values are plists whose keys are families and
85 values are pointers to MXFontList. */
88 /** List of available X-core fonts on the display. Keys are
89 families and values are pointers to MFont. For each MFont, only
90 these properties are important; FOUNDRY, FAMILY, REGISTRY. */
91 MPlist *base_font_list;
93 /** Nonzero means that <font_list> already contains all available
94 fonts on the display. */
97 /** Modifier bit masks of the display. */
104 /* Anchor of the chain of MDisplayInfo objects. */
105 static MPlist *display_info_list;
108 /* Color value and the corresponding GC. */
111 unsigned int rgb; /* (red << 16) | (green << 8) | blue */
118 GC_NORMAL = GC_INVERSE + 7,
131 /* The first 8 elements are indexed by an intensity for
132 anti-aliasing. The 2nd to 7th are created on demand. */
135 XftColor xft_color_fore, xft_color_back;
141 /* Common header for the m17n object. */
144 MDisplayInfo *display_info;
160 /** List of pointers to realized faces on the frame. */
161 MPlist *realized_face_list;
163 /* List of information about each font. Keys are font registries,
164 values are (MFontInfo *). */
165 MPlist *realized_font_list;
167 /** List of pointers to realized fontsets on the frame. */
168 MPlist *realized_fontset_list;
170 /** List of XColors vs GCs on the frame. */
174 static MPlist *device_list;
176 static MSymbol M_iso8859_1, M_iso10646_1;
178 #define FRAME_DEVICE(frame) ((MWDevice *) (frame)->device)
179 #define FRAME_DISPLAY(frame) (FRAME_DEVICE (frame)->display_info->display)
180 #define FRAME_SCREEN(frame) (FRAME_DEVICE (frame)->screen_num)
181 #define FRAME_CMAP(frame) (FRAME_DEVICE (frame)->cmap)
182 #define FRAME_VISUAL(frame) DefaultVisual (FRAME_DISPLAY (frame), \
183 FRAME_SCREEN (frame))
185 #define DEFAULT_FONT "-misc-fixed-medium-r-normal--*-120-*-*-*-*-iso8859-1"
186 #define FALLBACK_FONT "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1"
193 Boolean reverse_video;
194 } AppData, *AppDataPtr;
197 free_display_info (void *object)
199 MDisplayInfo *disp_info = (MDisplayInfo *) object;
202 MPLIST_DO (plist, disp_info->font_list)
204 MPLIST_DO (p, MPLIST_VAL (plist))
205 free (MPLIST_VAL (p));
206 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
208 M17N_OBJECT_UNREF (disp_info->font_list);
209 MPLIST_DO (plist, disp_info->base_font_list)
210 free (MPLIST_VAL (plist));
211 M17N_OBJECT_UNREF (disp_info->base_font_list);
213 if (disp_info->auto_display)
214 XCloseDisplay (disp_info->display);
220 free_device (void *object)
222 MWDevice *device = object;
225 for (plist = device->realized_fontset_list;
226 mplist_key (plist) != Mnil; plist = mplist_next (plist))
227 mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist));
228 M17N_OBJECT_UNREF (device->realized_fontset_list);
230 MPLIST_DO (plist, device->realized_font_list)
231 mfont__free_realized ((MRealizedFont *) MPLIST_VAL (plist));
232 M17N_OBJECT_UNREF (device->realized_font_list);
234 MPLIST_DO (plist, device->realized_face_list)
236 MRealizedFace *rface = MPLIST_VAL (plist);
239 mface__free_realized (rface);
241 M17N_OBJECT_UNREF (device->realized_face_list);
243 MPLIST_DO (plist, device->gc_list)
245 XFreeGC (device->display_info->display,
246 ((RGB_GC *) MPLIST_VAL (plist))->gc);
247 free (MPLIST_VAL (plist));
249 M17N_OBJECT_UNREF (device->gc_list);
250 XFreeGC (device->display_info->display, device->scratch_gc);
253 XftDrawDestroy (device->xft_draw);
256 XFreePixmap (device->display_info->display, device->drawable);
257 M17N_OBJECT_UNREF (device->display_info);
263 find_modifier_bits (MDisplayInfo *disp_info)
265 Display *display = disp_info->display;
266 XModifierKeymap *mods;
267 KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L);
268 KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R);
269 KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L);
270 KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R);
271 KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
272 KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
273 KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
274 KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
277 mods = XGetModifierMapping (display);
278 /* We skip the first three sets for Shift, Lock, and Control. The
279 remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
280 for (i = 3; i < 8; i++)
281 for (j = 0; j < mods->max_keypermod; j++)
283 KeyCode code = mods->modifiermap[i * mods->max_keypermod + j];
287 if (code == meta_l || code == meta_r)
288 disp_info->meta_mask |= (1 << i);
289 else if (code == alt_l || code == alt_r)
290 disp_info->alt_mask |= (1 << i);
291 else if (code == super_l || code == super_r)
292 disp_info->super_mask |= (1 << i);
293 else if (code == hyper_l || code == hyper_r)
294 disp_info->hyper_mask |= (1 << i);
297 /* If meta keys are not in any modifier, use alt keys as meta
299 if (! disp_info->meta_mask)
301 disp_info->meta_mask = disp_info->alt_mask;
302 disp_info->alt_mask = 0;
304 /* If both meta and alt are assigned to the same modifier, give meta
306 if (disp_info->meta_mask & disp_info->alt_mask)
307 disp_info->alt_mask &= ~disp_info->meta_mask;
309 XFreeModifiermap (mods);
313 get_rgb_gc (MWDevice *device, XColor *xcolor)
315 int rgb = (((xcolor->red >> 8) << 16) | ((xcolor->green >> 8) << 8)
316 | (xcolor->blue >> 8));
319 unsigned long valuemask = GCForeground;
322 MPLIST_DO (plist, device->gc_list)
324 rgb_gc = MPLIST_VAL (plist);
326 if (rgb_gc->rgb == rgb)
328 if (rgb_gc->rgb > rgb)
332 if (! XAllocColor (device->display_info->display, device->cmap, xcolor))
335 rgb_gc = malloc (sizeof (RGB_GC));
337 values.foreground = xcolor->pixel;
338 rgb_gc->gc = XCreateGC (device->display_info->display,
339 device->drawable, valuemask, &values);
340 mplist_push (plist, Mt, rgb_gc);
345 get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret)
347 MWDevice *device = FRAME_DEVICE (frame);
355 color = for_foreground ? frame->foreground : frame->background;
357 if (! XParseColor (FRAME_DISPLAY (frame), device->cmap,
358 msymbol_name (color), &xcolor))
360 rgb_gc = get_rgb_gc (device, &xcolor);
364 *rgb_ret = rgb_gc->rgb;
369 GCInfo *info = frame->rface->info;
374 rgb = info->rgb_fore, gc = info->gc[GC_NORMAL];
376 rgb = info->rgb_back, gc = info->gc[GC_INVERSE];
384 get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity)
386 int rgb_fore, rgb_back;
391 if (info->gc[intensity])
392 return info->gc[intensity];
394 rgb_fore = info->rgb_fore, rgb_back = info->rgb_back;
395 xcolor.red = ((((rgb_fore & 0xFF0000) >> 16) * intensity
396 + ((rgb_back & 0xFF0000) >> 16) * (7 - intensity)) / 7) << 8;
397 xcolor.green = ((((rgb_fore & 0xFF00) >> 8) * intensity
398 + ((rgb_back & 0xFF00) >> 8) * (7 - intensity)) / 7) << 8;
399 xcolor.blue = (((rgb_fore & 0xFF) * intensity
400 + (rgb_back & 0xFF) * (7 - intensity)) / 7) << 8;
401 rgb_gc = get_rgb_gc (device, &xcolor);
405 gc =get_gc_for_anti_alias (device, info,
406 intensity < 4 ? intensity - 1 : intensity + 1);
407 return (info->gc[intensity] = gc);
411 set_region (MFrame *frame, GC gc, MDrawRegion region)
413 unsigned long valuemask = GCForeground;
415 XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
416 FRAME_DEVICE (frame)->scratch_gc);
417 XSetRegion (FRAME_DISPLAY (frame), FRAME_DEVICE (frame)->scratch_gc, region);
418 return FRAME_DEVICE (frame)->scratch_gc;
422 /** X font handler */
424 static MRealizedFont *xfont_select (MFrame *, MFont *, MFont *, int);
425 static int xfont_open (MRealizedFont *);
426 static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int);
427 static unsigned xfont_encode_char (MRealizedFont *, unsigned);
428 static void xfont_render (MDrawWindow, int, int, MGlyphString *,
429 MGlyph *, MGlyph *, int, MDrawRegion);
430 static int xfont_list (MFrame *frame, MPlist *plist,
431 MFont *font, MSymbol language, int maxnum);
434 static MFontDriver xfont_driver =
435 { xfont_select, xfont_open,
436 xfont_find_metric, xfont_encode_char, xfont_render, xfont_list };
439 font_compare (const void *p1, const void *p2)
441 return strcmp (*(char **) p1, *(char **) p2);
445 xfont_registry_list (MFrame *frame, MSymbol registry)
447 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
448 MPlist *font_list = disp_info->font_list;
449 MPlist *base_font_list = disp_info->base_font_list;
452 char **font_names, **names;
456 MXFontList *xfont_table;
459 plist = mplist_get (font_list, registry);
463 mplist_add (font_list, registry, plist);
464 sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", msymbol_name (registry));
465 font_names = XListFonts (disp_info->display, pattern, 0x8000, &nfonts);
468 names = alloca (sizeof (char *) * nfonts);
469 memcpy (names, font_names, sizeof (char *) * nfonts);
470 qsort (names, nfonts, sizeof (char *), font_compare);
471 for (i = 0, p = NULL; i < nfonts; i++)
472 if (mfont__parse_name_into_font (names[i], Mx, (MFont *) &font) == 0
473 && (font.core.property[MFONT_SIZE] > 0
474 || font.core.property[MFONT_RESY] == 0))
476 MSymbol family = FONT_PROPERTY ((MFont *) &font, MFONT_FAMILY);
477 int size = font.core.property[MFONT_SIZE] / 10;
482 font.sizes[0] = font.sizes[1] = 0;
483 SET_SIZE (&font, size);
485 /* Handle fonts of the same base. */
486 for (base_end = names[i], fields = 0; *base_end; base_end++)
488 && ++fields == 7 /* PIXEL_SIZE */)
490 base_len = base_end - names[i];
491 for (j = i + 1; j < nfonts && ! strncmp (names[i], names[j], base_len);
493 if (mfont__parse_name_into_font (names[j], Mx, (MFont *) &font) == 0
494 && (font.core.property[MFONT_SIZE] > 0
495 || font.core.property[MFONT_RESY] == 0))
497 size = font.core.property[MFONT_SIZE] / 10;
498 SET_SIZE (&font, size);
501 if (p && MPLIST_KEY (p) != family)
502 p = mplist_find_by_key (plist, family);
504 xfont_table = MPLIST_VAL (p);
508 MSTRUCT_MALLOC (xfont_table, MERROR_WIN);
509 MLIST_INIT1 (xfont_table, fonts, 4);
510 mplist_push (p, family, xfont_table);
512 MLIST_APPEND1 (xfont_table, fonts, font, MERROR_WIN);
514 || (font.core.property[MFONT_FOUNDRY]
515 != bfont->property[MFONT_FOUNDRY])
516 || (font.core.property[MFONT_FAMILY]
517 != bfont->property[MFONT_FAMILY]))
519 MSTRUCT_MALLOC (bfont, MERROR_WIN);
521 for (j = MFONT_WEIGHT; j <= MFONT_ADSTYLE; j++)
522 bfont->property[j] = 0;
523 bfont->property[MFONT_SIZE] = bfont->property[MFONT_RESY] = 0;
524 mplist_push (base_font_list, family, bfont);
527 XFreeFontNames (font_names);
532 xfont_list_all (MFrame *frame)
534 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
535 MPlist *font_encoding_list, *p;
537 if (disp_info->all_fonts_scaned)
539 disp_info->all_fonts_scaned = 1;
540 font_encoding_list = mfont__encoding_list ();
541 if (! font_encoding_list)
543 MPLIST_DO (p, font_encoding_list)
544 xfont_registry_list (frame, MPLIST_KEY (p));
555 /* The X font driver function SELECT. */
557 static MRealizedFont *
558 xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size){
560 MSymbol family = FONT_PROPERTY (spec, MFONT_FAMILY);
561 MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
562 int requested_size = request->property[MFONT_SIZE];
563 MRealizedFont *rfont;
567 int best_score, score;
570 || ! strchr (MSYMBOL_NAME (registry), '-'))
573 plist = xfont_registry_list (frame, registry);
574 if (MPLIST_TAIL_P (plist))
576 best_score = -1, best_font = NULL;
577 MPLIST_DO (plist, plist)
579 if (family == Mnil || family == MPLIST_KEY (plist))
581 MXFontList *xfont_table = MPLIST_VAL (plist);
583 for (i = 0; i < xfont_table->used; i++)
585 MXFont *xfont = xfont_table->fonts + i;
586 MFont *font = (MFont *) xfont;
587 int size = requested_size / 10, s0, s1;
589 for (s0 = size; s0 > 0 && ! HAVE_SIZE (xfont, s0); s0--);
590 if (s0 * 10 == requested_size)
591 /* Exact size match. */
593 else if (xfont->sizes[0] & 1)
596 else if (limited_size)
597 /* We can't use a larger font. */
601 for (s0 = size + 1; s0 < 64 && ! HAVE_SIZE (xfont, s0); s0++);
608 for (s1 = size + (size - s0) - 1;
609 s1 > size && HAVE_SIZE (xfont, s1); s1++);
610 size = (s1 > size ? s1 : s0);
612 font->property[MFONT_SIZE] = size * 10;
614 if ((score = mfont__score (font, spec, request,
616 && (best_score < 0 || score < best_score))
619 best_font = (MFont *) (xfont_table->fonts + i);
631 MSTRUCT_CALLOC (rfont, MERROR_WIN);
632 rfont->frame = frame;
634 rfont->request = *request;
635 rfont->font = *best_font;
636 if (best_font->property[MFONT_SIZE] == 0)
637 rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE];
638 rfont->score = best_score;
643 /* The X font driver function CLOSE. */
646 close_xfont (void *object)
648 MXFontInfo *xfont_info = object;
650 XFreeFont (xfont_info->display, xfont_info->xfont);
655 /* The X font driver function OPEN. */
658 xfont_open (MRealizedFont *rfont)
661 MXFontInfo *xfont_info;
662 MFrame *frame = rfont->frame;
663 int mdebug_mask = MDEBUG_FONT;
665 /* This never fail to generate a valid fontname because open_spec
666 should correspond to a font available on the system. */
667 name = mfont_unparse_name (&rfont->font, Mx);
668 M17N_OBJECT (xfont_info, close_xfont, MERROR_WIN);
669 xfont_info->display = FRAME_DISPLAY (frame);
670 xfont_info->xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
671 if (! xfont_info->xfont)
675 MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
679 rfont->info = xfont_info;
680 MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
683 rfont->ascent = xfont_info->xfont->ascent;
684 rfont->descent = xfont_info->xfont->descent;
686 rfont->fontp = xfont_info->xfont;
691 /* The X font driver function FIND_METRIC. */
694 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
697 MXFontInfo *xfont_info = rfont->info;
698 XFontStruct *xfont = xfont_info->xfont;
699 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
701 for (; g != gend; g++)
703 if (g->code == MCHAR_INVALID_CODE)
705 g->lbearing = xfont->max_bounds.lbearing;
706 g->rbearing = xfont->max_bounds.rbearing;
707 g->width = xfont->max_bounds.width;
708 g->ascent = xfont->ascent;
709 g->descent = xfont->descent;
713 int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
714 XCharStruct *pcm = NULL;
716 if (xfont->per_char != NULL)
718 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
721 && byte2 >= xfont->min_char_or_byte2
722 && byte2 <= xfont->max_char_or_byte2)
723 pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
727 if (byte1 >= xfont->min_byte1
728 && byte1 <= xfont->max_byte1
729 && byte2 >= xfont->min_char_or_byte2
730 && byte2 <= xfont->max_char_or_byte2)
732 pcm = (xfont->per_char
733 + ((xfont->max_char_or_byte2
734 - xfont->min_char_or_byte2 + 1)
735 * (byte1 - xfont->min_byte1))
736 + (byte2 - xfont->min_char_or_byte2));
743 g->lbearing = pcm->lbearing;
744 g->rbearing = pcm->rbearing;
745 g->width = pcm->width;
746 g->ascent = pcm->ascent;
747 g->descent = pcm->descent;
751 /* If the per_char pointer is null, all glyphs between
752 the first and last character indexes inclusive have
753 the same information, as given by both min_bounds and
756 g->rbearing = xfont->max_bounds.width;
757 g->width = xfont->max_bounds.width;
758 g->ascent = xfont->ascent;
759 g->descent = xfont->descent;
766 /* The X font driver function GET_GLYPH_ID. */
769 xfont_encode_char (MRealizedFont *rfont, unsigned code)
771 MXFontInfo *xfont_info;
773 unsigned min_byte1, max_byte1, min_byte2, max_byte2;
776 if (rfont->status < 0 || code >= 0x10000)
777 return MCHAR_INVALID_CODE;
778 if (rfont->status == 0)
780 if (xfont_open (rfont) < 0)
781 return MCHAR_INVALID_CODE;
783 xfont_info = rfont->info;
784 xfont = xfont_info->xfont;
785 all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
786 min_byte1 = xfont->min_byte1;
787 max_byte1 = xfont->max_byte1;
788 min_byte2 = xfont->min_char_or_byte2;
789 max_byte2 = xfont->max_char_or_byte2;
791 if (min_byte1 == 0 && max_byte1 == 0)
795 if (code < min_byte2 || code > max_byte2)
796 return MCHAR_INVALID_CODE;
799 pcm = xfont->per_char + (code - min_byte2);
800 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
801 ? code : MCHAR_INVALID_CODE);
805 unsigned byte1 = code >> 8, byte2 = code & 0xFF;
808 if (byte1 < min_byte1 || byte1 > max_byte1
809 || byte2 < min_byte2 || byte2 > max_byte2)
810 return MCHAR_INVALID_CODE;
814 pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
815 + (byte2 - min_byte2));
816 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
817 ? code : MCHAR_INVALID_CODE);
821 /* The X font driver function RENDER. */
824 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
825 MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
827 MRealizedFace *rface = from->rface;
828 MXFontInfo *xfont_info = rface->rfont->info;
831 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
838 /* It is assured that the all glyphs in the current range use the
839 same realized face. */
840 display = FRAME_DISPLAY (rface->frame);
843 gc = set_region (rface->frame, gc, region);
844 XSetFont (display, gc, xfont_info->xfont->fid);
845 code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
846 for (i = 0, g = from; g < to; i++, g++)
848 code[i].byte1 = g->code >> 8;
849 code[i].byte2 = g->code & 0xFF;
855 if (g->type == GLYPH_PAD)
857 else if (g->type == GLYPH_SPACE)
858 for (; g < to && g->type == GLYPH_SPACE; g++)
860 else if (! g->rface->rfont)
862 if ((g->c >= 0x200B && g->c <= 0x200F)
863 || (g->c >= 0x202A && g->c <= 0x202E))
867 /* As a font is not found for this character, draw an
869 int box_width = g->width;
870 int box_height = gstring->ascent + gstring->descent;
876 XDrawRectangle (display, (Window) win, gc,
877 x, y - gstring->ascent, box_width, box_height);
881 else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
883 XDrawString16 (display, (Window) win, gc,
884 x + g->xoff, y + g->yoff, code + (g - from), 1);
891 int code_idx = g - from;
894 g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
897 XDrawString16 (display, (Window) win, gc, orig_x, y,
904 xfont_list (MFrame *frame, MPlist *plist, MFont *font, MSymbol language,
907 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
908 MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil;
909 MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil;
913 if (registry != Mnil)
914 xfont_registry_list (frame, registry);
916 xfont_list_all (frame);
918 /* As we have not yet implemented the language check, return all
921 MPLIST_DO (p, disp_info->base_font_list)
923 mplist_add (plist, MPLIST_KEY (p), MPLIST_VAL (p));
930 MXFontList *xfontlist;
934 pl = disp_info->font_list;
935 if (registry != Mnil)
937 pl = mplist_find_by_key (pl, registry);
947 p = mplist_find_by_key (p, family);
953 xfontlist = MPLIST_VAL (p);
954 for (i = 0; i < xfontlist->used; i++)
956 xfont = xfontlist->fonts + i;
957 if (mfont__match_p (&xfont->core, font, MFONT_REGISTRY))
959 mplist_add (plist, MPLIST_KEY (p), &xfont->core);
968 if (registry != Mnil)
988 static int xft_open (MRealizedFont *);
989 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
990 static void xft_render (MDrawWindow, int, int, MGlyphString *,
991 MGlyph *, MGlyph *, int, MDrawRegion);
993 MFontDriver xft_driver =
994 { NULL, /* Set to ft_select in device_init (). */
995 xft_open, xft_find_metric,
996 NULL, /* Set to ft_encode_char in device_init (). */
998 NULL /* Set to ft_list in device_init (). */
1003 close_xft (void *object)
1005 MXftFontInfo *font_info = object;
1007 XftFontClose (font_info->display, font_info->font_aa);
1008 XftFontClose (font_info->display, font_info->font_no_aa);
1014 xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
1016 XftPattern *pattern;
1017 XftFontInfo *xft_font_info;
1020 pattern = XftPatternCreate ();
1021 XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
1022 XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
1023 XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
1024 xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
1025 if (! xft_font_info)
1027 font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
1028 XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
1034 xft_open (MRealizedFont *rfont)
1038 MXftFontInfo *font_info;
1041 if ((mfont__ft_driver.open) (rfont) < 0)
1044 size = rfont->font.property[MFONT_SIZE] / 10;
1045 frame = rfont->frame;
1047 ft_info = rfont->info;
1048 M17N_OBJECT (font_info, close_xft, MERROR_WIN);
1049 ft_info->extra_info = font_info;
1050 font_info->display = FRAME_DISPLAY (frame);
1051 font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
1052 if (font_info->font_aa)
1054 font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
1055 if (font_info->font_no_aa)
1058 rfont->fontp = font_info->font_no_aa;
1061 XftFontClose (FRAME_DISPLAY (rfont->frame), font_info->font_aa);
1064 ft_info->extra_info = NULL;
1071 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1074 MFTInfo *ft_info = rfont->info;
1075 MXftFontInfo *font_info = ft_info->extra_info;
1076 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1078 for (; g != gend; g++)
1080 if (g->code == MCHAR_INVALID_CODE)
1082 MGlyph *start = g++;
1084 while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
1085 (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
1093 XftGlyphExtents (FRAME_DISPLAY (gstring->frame),
1094 font_info->font_aa, &g->code, 1, &extents);
1095 g->lbearing = - extents.x;
1096 g->rbearing = extents.width - extents.x;
1097 g->width = extents.xOff;
1098 g->ascent = extents.y;
1099 g->descent = extents.height - extents.y;
1106 xft_render (MDrawWindow win, int x, int y,
1107 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1108 int reverse, MDrawRegion region)
1110 MRealizedFace *rface = from->rface;
1111 MFrame *frame = rface->frame;
1112 MFTInfo *ft_info = rface->rfont->info;
1113 MXftFontInfo *font_info = ft_info->extra_info;
1114 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1115 XftColor *xft_color = (! reverse
1116 ? &((GCInfo *) rface->info)->xft_color_fore
1117 : &((GCInfo *) rface->info)->xft_color_back);
1118 XftFont *xft_font = (gstring->control.anti_alias
1119 && FRAME_DEVICE (frame)->depth > 1
1120 ? font_info->font_aa : font_info->font_no_aa);
1129 XftDrawChange (xft_draw, (Drawable) win);
1130 XftDrawSetClip (xft_draw, (Region) region);
1132 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1133 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1135 if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1136 glyphs[nglyphs++] = g->code;
1140 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1141 last_x, y, glyphs, nglyphs);
1143 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1144 x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1145 last_x = x + g->width;
1149 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1155 /* Functions for the device driver. */
1158 mwin__close_device (MFrame *frame)
1160 M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
1164 mwin__device_get_prop (MFrame *frame, MSymbol key)
1166 MWDevice *device = FRAME_DEVICE (frame);
1168 if (key == Mdisplay)
1169 return (void *) device->display_info->display;
1171 return (void *) ScreenOfDisplay(device->display_info->display,
1172 device->screen_num);
1173 if (key == Mcolormap)
1174 return (void *) device->cmap;
1176 return (void *) device->depth;
1181 mwin__realize_face (MRealizedFace *rface)
1184 MSymbol foreground, background, videomode;
1185 MFaceHLineProp *hline;
1189 if (rface != rface->ascii_rface)
1191 rface->info = rface->ascii_rface->info;
1195 frame = rface->frame;
1196 MSTRUCT_CALLOC (info, MERROR_WIN);
1198 foreground = rface->face.property[MFACE_FOREGROUND];
1199 background = rface->face.property[MFACE_BACKGROUND];
1200 videomode = rface->face.property[MFACE_VIDEOMODE];
1202 videomode = frame->videomode;
1203 if (videomode != Mreverse)
1205 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1206 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1210 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1211 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1214 if (foreground == Mnil)
1215 foreground = frame->foreground;
1216 if (background == Mnil)
1217 background = frame->background;
1218 if (videomode == Mreverse)
1220 MSymbol temp = foreground;
1221 foreground = background;
1224 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1225 FRAME_VISUAL (frame),
1227 MSYMBOL_NAME (foreground),
1228 &info->xft_color_fore))
1230 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1231 FRAME_VISUAL (frame),
1233 MSYMBOL_NAME (background),
1234 &info->xft_color_back))
1238 hline = rface->hline;
1242 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1244 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1251 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1253 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1255 if (box->color_left && box->color_left != box->color_top)
1256 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1258 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1260 if (box->color_bottom && box->color_bottom != box->color_top)
1261 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1263 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1265 if (box->color_right && box->color_right != box->color_bottom)
1266 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1268 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1276 mwin__free_realized_face (MRealizedFace *rface)
1278 if (rface == rface->ascii_rface)
1284 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1286 int x, int y, int width, int height, MDrawRegion region)
1288 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1291 gc = set_region (frame, gc, region);
1293 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1294 x, y, width, height);
1299 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1300 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1301 int reverse, MDrawRegion region)
1303 MRealizedFace *rface = from->rface;
1304 Display *display = FRAME_DISPLAY (rface->frame);
1305 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1311 gc = set_region (rface->frame, gc, region);
1312 for (; from < to; from++)
1314 XDrawRectangle (display, (Window) win, gc,
1315 x, y - gstring->ascent + 1, from->width - 1,
1316 gstring->ascent + gstring->descent - 2);
1323 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1324 MRealizedFace *rface, int reverse,
1325 int x, int y, int width, MDrawRegion region)
1327 enum MFaceHLineType type = rface->hline->type;
1328 GCInfo *info = rface->info;
1329 GC gc = gc = info->gc[GC_HLINE];
1332 y = (type == MFACE_HLINE_BOTTOM
1333 ? y + gstring->text_descent - rface->hline->width
1334 : type == MFACE_HLINE_UNDER
1336 : type == MFACE_HLINE_STRIKE_THROUGH
1337 ? y - ((gstring->ascent + gstring->descent) / 2)
1338 : y - gstring->text_ascent);
1340 gc = set_region (frame, gc, region);
1342 for (i = 0; i < rface->hline->width; i++)
1343 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1344 x, y + i, x + width - 1, y + i);
1349 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1350 MGlyph *g, int x, int y, int width, MDrawRegion region)
1352 Display *display = FRAME_DISPLAY (frame);
1353 MRealizedFace *rface = g->rface;
1354 MFaceBoxProp *box = rface->box;
1355 GCInfo *info = rface->info;
1356 GC gc_top, gc_left, gc_right, gc_btm;
1360 y0 = y - (gstring->text_ascent
1361 + rface->box->inner_vmargin + rface->box->width);
1362 y1 = y + (gstring->text_descent
1363 + rface->box->inner_vmargin + rface->box->width - 1);
1365 gc_top = info->gc[GC_BOX_TOP];
1367 gc_top = set_region (frame, gc_top, region);
1368 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1371 gc_btm = info->gc[GC_BOX_BOTTOM];
1373 if (g->type == GLYPH_BOX)
1377 if (g->left_padding)
1378 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1380 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1382 /* Draw the top side. */
1383 for (i = 0; i < box->width; i++)
1384 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1386 /* Draw the bottom side. */
1387 if (region && gc_btm != gc_top)
1388 gc_btm = set_region (frame, gc_btm, region);
1389 for (i = 0; i < box->width; i++)
1390 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1392 if (g->left_padding > 0)
1394 /* Draw the left side. */
1395 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1399 gc_left = info->gc[GC_BOX_LEFT];
1401 gc_left = set_region (frame, gc_left, region);
1403 for (i = 0; i < rface->box->width; i++)
1404 XDrawLine (display, (Window) win, gc_left,
1405 x0 + i, y0 + i, x0 + i, y1 - i);
1409 /* Draw the right side. */
1410 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1414 gc_right = info->gc[GC_BOX_RIGHT];
1416 gc_right = set_region (frame, gc_right, region);
1418 for (i = 0; i < rface->box->width; i++)
1419 XDrawLine (display, (Window) win, gc_right,
1420 x1 - i, y0 + i, x1 - i, y1 - i);
1425 /* Draw the top side. */
1426 for (i = 0; i < box->width; i++)
1427 XDrawLine (display, (Window) win, gc_top,
1428 x, y0 + i, x + width - 1, y0 + i);
1430 /* Draw the bottom side. */
1431 if (region && gc_btm != gc_top)
1432 gc_btm = set_region (frame, gc_btm, region);
1433 for (i = 0; i < box->width; i++)
1434 XDrawLine (display, (Window) win, gc_btm,
1435 x, y1 - i, x + width - 1, y1 - i);
1442 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1443 int reverse, int x, int y,
1444 int width, int height, int row_bytes, unsigned char *bmp,
1447 Display *display = FRAME_DISPLAY (frame);
1449 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1452 gc = set_region (frame, gc, region);
1454 for (i = 0; i < height; i++, bmp += row_bytes)
1455 for (j = 0; j < width; j++)
1456 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1457 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1462 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1463 int intensity, MDrawPoint *points, int num,
1466 GCInfo *info = rface->info;
1469 if (! (gc = info->gc[intensity]))
1470 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1473 gc = set_region (frame, gc, region);
1475 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1476 (XPoint *) points, num, CoordModeOrigin);
1481 mwin__region_from_rect (MDrawMetric *rect)
1483 MDrawRegion region1 = XCreateRegion ();
1484 MDrawRegion region2 = XCreateRegion ();
1489 xrect.width = rect->width;
1490 xrect.height = rect->height;
1491 XUnionRectWithRegion (&xrect, region1, region2);
1492 XDestroyRegion (region1);
1497 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1499 MDrawRegion region1 = XCreateRegion ();
1504 xrect.width = rect->width;
1505 xrect.height = rect->height;
1507 XUnionRegion (region, region, region1);
1508 XUnionRectWithRegion (&xrect, region1, region);
1509 XDestroyRegion (region1);
1513 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1515 MDrawRegion region = XCreateRegion ();
1517 XUnionRegion (region1, region1, region);
1518 XIntersectRegion (region, region2, region1);
1519 XDestroyRegion (region);
1523 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1525 MDrawRegion region1 = XCreateRegion ();
1530 xrect.width = rect->width;
1531 xrect.height = rect->height;
1532 XUnionRectWithRegion (&xrect, region1, region);
1533 XDestroyRegion (region1);
1537 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1541 XClipBox (region, &xrect);
1544 rect->width = xrect.width;
1545 rect->height = xrect.height;
1549 mwin__free_region (MDrawRegion region)
1551 XDestroyRegion (region);
1555 mwin__dump_region (MDrawRegion region)
1558 XClipBox (region, &rect);
1559 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1564 mwin__create_window (MFrame *frame, MDrawWindow parent)
1566 Display *display = FRAME_DISPLAY (frame);
1568 XWMHints wm_hints = { InputHint, False };
1569 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1570 XSetWindowAttributes set_attrs;
1573 GCInfo *info = frame->rface->info;
1576 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1577 mask = GCForeground;
1578 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1579 set_attrs.background_pixel = values.foreground;
1580 set_attrs.backing_store = Always;
1581 set_attrs.override_redirect = True;
1582 set_attrs.save_under = True;
1583 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1584 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1585 CopyFromParent, InputOutput, CopyFromParent,
1587 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1588 NULL, &wm_hints, &class_hints);
1589 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1590 return (MDrawWindow) win;
1594 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1596 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1601 mwin__event_window (void *event)
1603 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1607 mwin__print_event (void *arg, char *win_name)
1610 XEvent *event = (XEvent *) arg;
1612 switch (event->xany.type)
1614 case 2: event_name = "KeyPress"; break;
1615 case 3: event_name = "KeyRelease"; break;
1616 case 4: event_name = "ButtonPress"; break;
1617 case 5: event_name = "ButtonRelease"; break;
1618 case 6: event_name = "MotionNotify"; break;
1619 case 7: event_name = "EnterNotify"; break;
1620 case 8: event_name = "LeaveNotify"; break;
1621 case 9: event_name = "FocusIn"; break;
1622 case 10: event_name = "FocusOut"; break;
1623 case 11: event_name = "KeymapNotify"; break;
1624 case 12: event_name = "Expose"; break;
1625 case 13: event_name = "GraphicsExpose"; break;
1626 case 14: event_name = "NoExpose"; break;
1627 case 15: event_name = "VisibilityNotify"; break;
1628 case 16: event_name = "CreateNotify"; break;
1629 case 17: event_name = "DestroyNotify"; break;
1630 case 18: event_name = "UnmapNotify"; break;
1631 case 19: event_name = "MapNotify"; break;
1632 case 20: event_name = "MapRequest"; break;
1633 case 21: event_name = "ReparentNotify"; break;
1634 case 22: event_name = "ConfigureNotify"; break;
1635 case 23: event_name = "ConfigureRequest"; break;
1636 case 24: event_name = "GravityNotify"; break;
1637 case 25: event_name = "ResizeRequest"; break;
1638 case 26: event_name = "CirculateNotify"; break;
1639 case 27: event_name = "CirculateRequest"; break;
1640 case 28: event_name = "PropertyNotify"; break;
1641 case 29: event_name = "SelectionClear"; break;
1642 case 30: event_name = "SelectionRequest"; break;
1643 case 31: event_name = "SelectionNotify"; break;
1644 case 32: event_name = "ColormapNotify"; break;
1645 case 33: event_name = "ClientMessage"; break;
1646 case 34: event_name = "MappingNotify"; break;
1647 default: event_name = "unknown";
1650 fprintf (stderr, "%s: %s\n", win_name, event_name);
1655 mwin__map_window (MFrame *frame, MDrawWindow win)
1657 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1661 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1663 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1667 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1668 MDrawMetric *geometry)
1670 Display *display = FRAME_DISPLAY (frame);
1671 XWindowAttributes attr;
1672 Window parent = (Window) parent_win, root;
1674 XGetWindowAttributes (display, (Window) win, &attr);
1675 geometry->x = attr.x + attr.border_width;
1676 geometry->y = attr.y + attr.border_width;
1677 geometry->width = attr.width;
1678 geometry->height = attr.height;
1681 parent = RootWindow (display, FRAME_SCREEN (frame));
1684 Window this_parent, *children;
1687 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1690 if (this_parent == parent || this_parent == root)
1692 win = (MDrawWindow) this_parent;
1693 XGetWindowAttributes (display, (Window) win, &attr);
1694 geometry->x += attr.x + attr.border_width;
1695 geometry->y += attr.y + attr.border_width;
1700 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1701 MDrawMetric *current, MDrawMetric *new)
1703 Display *display = FRAME_DISPLAY (frame);
1704 unsigned int mask = 0;
1705 XWindowChanges values;
1707 if (current->width != new->width)
1710 if (new->width <= 0)
1712 values.width = current->width = new->width;
1714 if (current->height != new->height)
1717 if (new->height <= 0)
1719 values.height = current->height = new->height;
1721 if (current->x != new->x)
1724 values.x = current->x = new->x;
1726 if (current->y != new->y)
1729 current->y = new->y;
1730 values.y = current->y = new->y;
1733 XConfigureWindow (display, (Window) win, mask, &values);
1734 XClearWindow (display, (Window) win);
1738 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1740 XEvent *event = (XEvent *) arg;
1741 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1748 if (event->xany.type != KeyPress
1749 /* && event->xany.type != KeyRelease */
1752 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1759 if (c < XK_space || c > XK_asciitilde)
1761 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1762 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1763 if (((XKeyEvent *) event)->state & ControlMask)
1765 if (c >= 'a' && c <= 'z')
1767 if (c >= ' ' && c < 127)
1768 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1770 key = minput__char_to_key (c);
1772 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1776 char *str = XKeysymToString (keysym);
1780 key = msymbol (str);
1781 if (((XKeyEvent *) event)->state & ShiftMask)
1782 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1783 if (((XKeyEvent *) event)->state & ControlMask)
1784 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1786 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1787 *modifiers |= MINPUT_KEY_META_MODIFIER;
1788 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1789 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1790 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1791 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1792 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1793 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1800 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1802 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1804 Display *display = FRAME_DISPLAY (frame);
1805 GCInfo *info = rface->info;
1808 for (i = 0; i <= GC_INVERSE; i++)
1810 XGetGCValues (display, info->gc[i], valuemask, &values);
1811 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1812 values.foreground, values.background);
1813 fprintf (stderr, "\n");
1817 static MDeviceDriver x_driver =
1820 mwin__device_get_prop,
1822 mwin__free_realized_face,
1824 mwin__draw_empty_boxes,
1828 mwin__region_from_rect,
1829 mwin__union_rect_with_region,
1830 mwin__intersect_region,
1831 mwin__region_add_rect,
1832 mwin__region_to_rect,
1835 mwin__create_window,
1836 mwin__destroy_window,
1839 mwin__window_geometry,
1840 mwin__adjust_window,
1844 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1849 M_iso8859_1 = msymbol ("iso8859-1");
1850 M_iso10646_1 = msymbol ("iso10646-1");
1852 display_info_list = mplist ();
1853 device_list = mplist ();
1856 xft_driver.select = mfont__ft_driver.select;
1857 xft_driver.encode_char = mfont__ft_driver.encode_char;
1858 xft_driver.list = mfont__ft_driver.list;
1861 Mxim = msymbol ("xim");
1862 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1870 M17N_OBJECT_UNREF (display_info_list);
1871 M17N_OBJECT_UNREF (device_list);
1875 /** Return an MWDevice object corresponding to a display specified in
1878 It searches device_list for a device matching the display. If
1879 found, return the found object. Otherwise, return a newly created
1883 device_open (MFrame *frame, MPlist *param)
1885 Display *display = NULL;
1886 Screen *screen = NULL;
1888 Drawable drawable = 0;
1889 Widget widget = NULL;
1891 int auto_display = 0;
1892 MDisplayInfo *disp_info = NULL;
1893 MWDevice *device = NULL;
1895 XWindowAttributes attr;
1900 int use_xfont = 1, use_freetype = 1;
1902 for (plist = param; (key = mplist_key (plist)) != Mnil;
1903 plist = mplist_next (plist))
1905 if (key == Mdisplay)
1906 display = (Display *) mplist_value (plist);
1907 else if (key == Mscreen)
1908 screen = mplist_value (plist);
1909 else if (key == Mdrawable)
1910 drawable = (Drawable) mplist_value (plist);
1911 else if (key == Mdepth)
1912 depth = (unsigned) mplist_value (plist);
1913 else if (key == Mwidget)
1914 widget = (Widget) mplist_value (plist);
1915 else if (key == Mcolormap)
1916 cmap = (Colormap) mplist_value (plist);
1917 else if (key == Mfont)
1919 MSymbol val = MPLIST_SYMBOL (plist);
1923 #ifdef HAVE_FREETYPE
1924 else if (val == Mfreetype)
1932 display = XtDisplay (widget);
1933 screen_num = XScreenNumberOfScreen (XtScreen (widget));
1934 depth = DefaultDepth (display, screen_num);
1940 unsigned width, height, border_width;
1943 MERROR (MERROR_WIN, -1);
1944 XGetGeometry (display, drawable, &root_window,
1945 &x, &y, &width, &height, &border_width, &depth);
1946 XGetWindowAttributes (display, root_window, &attr);
1947 screen_num = XScreenNumberOfScreen (attr.screen);
1952 display = DisplayOfScreen (screen);
1957 display = XOpenDisplay (NULL);
1959 MERROR (MERROR_WIN, -1);
1962 screen = DefaultScreenOfDisplay (display);
1964 screen_num = XScreenNumberOfScreen (screen);
1966 depth = DefaultDepth (display, screen_num);
1970 cmap = DefaultColormap (display, screen_num);
1972 for (plist = display_info_list; mplist_key (plist) != Mnil;
1973 plist = mplist_next (plist))
1975 disp_info = (MDisplayInfo *) mplist_value (plist);
1976 if (disp_info->display == display)
1980 if (mplist_key (plist) != Mnil)
1981 M17N_OBJECT_REF (disp_info);
1984 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
1985 disp_info->display = display;
1986 disp_info->auto_display = auto_display;
1987 disp_info->font_list = mplist ();
1988 disp_info->base_font_list = mplist ();
1989 find_modifier_bits (disp_info);
1990 mplist_add (display_info_list, Mt, disp_info);
1993 for (plist = device_list; mplist_key (plist) != Mnil;
1994 plist = mplist_next (plist))
1996 device = (MWDevice *) mplist_value (plist);
1997 if (device->display_info == disp_info
1998 && device->depth == depth
1999 && device->cmap == cmap)
2003 if (mplist_key (plist) != Mnil)
2004 M17N_OBJECT_REF (device);
2007 unsigned long valuemask = GCForeground;
2010 M17N_OBJECT (device, free_device, MERROR_WIN);
2011 device->display_info = disp_info;
2012 device->screen_num = screen_num;
2013 /* A drawable on which to create GCs. */
2014 device->drawable = XCreatePixmap (display,
2015 RootWindow (display, screen_num),
2017 device->depth = depth;
2018 device->cmap = cmap;
2019 device->realized_face_list = mplist ();
2020 device->realized_font_list = mplist ();
2021 device->realized_fontset_list = mplist ();
2022 device->gc_list = mplist ();
2023 values.foreground = BlackPixel (display, screen_num);
2024 device->scratch_gc = XCreateGC (display, device->drawable,
2025 valuemask, &values);
2027 device->xft_draw = XftDrawCreate (display, device->drawable,
2028 DefaultVisual (display, screen_num),
2033 frame->device = device;
2034 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2035 frame->driver = &x_driver;
2036 frame->font_driver_list = mplist ();
2038 mplist_add (frame->font_driver_list, Mx, &xfont_driver);
2041 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2044 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2047 mplist_add (frame->font_driver_list, Mx, &xfont_driver);
2049 frame->realized_font_list = device->realized_font_list;
2050 frame->realized_face_list = device->realized_face_list;
2051 frame->realized_fontset_list = device->realized_fontset_list;
2055 XtResource resources[] = {
2056 { XtNfont, XtCFont, XtRString, sizeof (String),
2057 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2058 { XtNforeground, XtCForeground, XtRString, sizeof (String),
2059 XtOffset (AppDataPtr, foreground), XtRString, "black" },
2060 { XtNbackground, XtCBackground, XtRString, sizeof (String),
2061 XtOffset (AppDataPtr, background), XtRString, "white" },
2062 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2063 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2066 XtGetApplicationResources (widget, &app_data,
2067 resources, XtNumber (resources), NULL, 0);
2068 frame->foreground = msymbol (app_data.foreground);
2069 frame->background = msymbol (app_data.background);
2070 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2074 app_data.font = DEFAULT_FONT;
2075 frame->foreground = msymbol ("black");
2076 frame->background = msymbol ("white");
2077 frame->videomode = Mnormal;
2082 char **names = XListFonts (display, app_data.font, 1, &nfonts);
2086 if (! (frame->font = mfont_parse_name (names[0], Mx)))
2088 /* The font name does not conform to XLFD. Try to open the
2089 font and get XA_FONT property. */
2090 XFontStruct *xfont = XLoadQueryFont (display, names[0]);
2095 unsigned long value;
2098 if (XGetFontProperty (xfont, XA_FONT, &value)
2099 && (name = ((char *)
2100 XGetAtomName (display, (Atom) value))))
2102 if ((frame->font = mfont_parse_name (name, Mx)))
2105 XFreeFont (display, xfont);
2108 XFreeFontNames (names);
2111 frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
2114 face = mface_from_font (frame->font);
2115 face->property[MFACE_FONTSET] = mfontset (NULL);
2116 face->property[MFACE_FOREGROUND] = frame->foreground;
2117 face->property[MFACE_BACKGROUND] = frame->background;
2118 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2119 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2120 face->property[MFACE_VIDEOMODE] = frame->videomode;
2121 mface_put_prop (face, Mhook_func,
2122 mface_get_prop (mface__default, Mhook_func));
2123 face->property[MFACE_RATIO] = (void *) 100;
2124 mplist_push (param, Mface, face);
2125 M17N_OBJECT_UNREF (face);
2127 #ifdef X_SET_ERROR_HANDLER
2128 XSetErrorHandler (x_error_handler);
2129 XSetIOErrorHandler (x_io_error_handler);
2137 /* XIM (X Input Method) handler */
2139 typedef struct MInputXIMMethodInfo
2145 } MInputXIMMethodInfo;
2147 typedef struct MInputXIMContextInfo
2151 MConverter *converter;
2152 } MInputXIMContextInfo;
2155 xim_open_im (MInputMethod *im)
2157 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2158 MLocale *saved, *this;
2159 char *save_modifier_list;
2161 MInputXIMMethodInfo *im_info;
2163 saved = mlocale_set (LC_CTYPE, NULL);
2164 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2166 /* The specified locale is not supported. */
2167 MERROR (MERROR_LOCALE, -1);
2168 if (mlocale_get_prop (this, Mcoding) == Mnil)
2170 /* Unable to decode the output of XIM. */
2171 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2172 MERROR (MERROR_LOCALE, -1);
2175 if (arg->modifier_list)
2176 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2178 save_modifier_list = XSetLocaleModifiers ("");
2179 if (! save_modifier_list)
2181 /* The specified locale is not supported by X. */
2182 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2183 MERROR (MERROR_LOCALE, -1);
2186 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2189 /* No input method is available in the current locale. */
2190 XSetLocaleModifiers (save_modifier_list);
2191 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2192 MERROR (MERROR_WIN, -1);
2195 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2196 im_info->display = arg->display;
2198 im_info->language = mlocale_get_prop (this, Mlanguage);
2199 im_info->coding = mlocale_get_prop (this, Mcoding);
2202 XSetLocaleModifiers (save_modifier_list);
2203 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2209 xim_close_im (MInputMethod *im)
2211 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2213 XCloseIM (im_info->xim);
2218 xim_create_ic (MInputContext *ic)
2220 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2221 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2222 MInputXIMContextInfo *ic_info;
2225 if (! arg->input_style)
2227 /* By default, use Root style. */
2228 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2229 arg->preedit_attrs = NULL;
2230 arg->status_attrs = NULL;
2233 if (! arg->preedit_attrs && ! arg->status_attrs)
2234 xic = XCreateIC (im_info->xim,
2235 XNInputStyle, arg->input_style,
2236 XNClientWindow, arg->client_win,
2237 XNFocusWindow, arg->focus_win,
2239 else if (arg->preedit_attrs && ! arg->status_attrs)
2240 xic = XCreateIC (im_info->xim,
2241 XNInputStyle, arg->input_style,
2242 XNClientWindow, arg->client_win,
2243 XNFocusWindow, arg->focus_win,
2244 XNPreeditAttributes, arg->preedit_attrs,
2246 else if (! arg->preedit_attrs && arg->status_attrs)
2247 xic = XCreateIC (im_info->xim,
2248 XNInputStyle, arg->input_style,
2249 XNClientWindow, arg->client_win,
2250 XNFocusWindow, arg->focus_win,
2251 XNStatusAttributes, arg->status_attrs,
2254 xic = XCreateIC (im_info->xim,
2255 XNInputStyle, arg->input_style,
2256 XNClientWindow, arg->client_win,
2257 XNFocusWindow, arg->focus_win,
2258 XNPreeditAttributes, arg->preedit_attrs,
2259 XNStatusAttributes, arg->status_attrs,
2262 MERROR (MERROR_WIN, -1);
2264 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2266 ic_info->win = arg->focus_win;
2267 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2273 xim_destroy_ic (MInputContext *ic)
2275 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2277 XDestroyIC (ic_info->xic);
2278 mconv_free_converter (ic_info->converter);
2284 xim_filter (MInputContext *ic, MSymbol key, void *event)
2286 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2288 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2293 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2295 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2296 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2297 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2303 buf = (char *) alloca (512);
2304 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2305 if (status == XBufferOverflow)
2307 buf = (char *) alloca (len);
2308 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2311 mtext_reset (ic->produced);
2315 mconv_reset_converter (ic_info->converter);
2316 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2317 mconv_decode (ic_info->converter, ic->produced);
2318 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2319 Mlanguage, (void *) im_info->language);
2320 mtext_cpy (mt, ic->produced);
2321 mtext_reset (ic->produced);
2327 #ifdef X_SET_ERROR_HANDLER
2329 x_error_handler (Display *display, XErrorEvent *error)
2336 x_io_error_handler (Display *display)
2346 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2350 /*** @addtogroup m17nInputMethodWin */
2355 @brief Input method driver for XIM.
2357 The driver #minput_xim_driver is for the foreign input method of
2358 name #Mxim. It uses XIM (X Input Methods) as a background input
2361 As the symbol #Mxim has property #Minput_driver whose value is
2362 a pointer to this driver, the input method of language #Mnil
2363 and name #Mxim uses this driver.
2365 Therefore, for such input methods, the driver dependent arguments
2366 to the functions whose name begin with minput_ must be as follows.
2368 The argument $ARG of the function minput_open_im () must be a
2369 pointer to the structure #MInputXIMArgIM. See the documentation
2370 of #MInputXIMArgIM for more details.
2372 The argument $ARG of the function minput_create_ic () must be a
2373 pointer to the structure #MInputXIMArgIC. See the documentation
2374 of #MInputXIMArgIC for more details.
2376 The argument $ARG of the function minput_filter () must be a
2377 pointer to the structure @c XEvent. The argument $KEY is ignored.
2379 The argument $ARG of the function minput_lookup () must be the
2380 same one as that of the function minput_filter (). The argument
2384 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2386 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
2387 ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
2390 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2391 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
2392 ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2394 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
2395 ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2397 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM ¤Ø¤Î¥Ý
2398 ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
2401 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC ¤Ø¤Î
2402 ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
2405 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2406 ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2408 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2409 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2412 MInputDriver minput_xim_driver =
2413 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2414 xim_filter, xim_lookup, NULL };