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 /** Modifier bit masks of the display. */
100 /* Anchor of the chain of MDisplayInfo objects. */
101 static MPlist *display_info_list;
104 /* Color value and the corresponding GC. */
107 unsigned int rgb; /* (red << 16) | (green << 8) | blue */
114 GC_NORMAL = GC_INVERSE + 7,
127 /* The first 8 elements are indexed by an intensity for
128 anti-aliasing. The 2nd to 7th are created on demand. */
131 XftColor xft_color_fore, xft_color_back;
137 /* Common header for the m17n object. */
140 MDisplayInfo *display_info;
156 /** List of pointers to realized faces on the frame. */
157 MPlist *realized_face_list;
159 /* List of information about each font. Keys are font registries,
160 values are (MFontInfo *). */
161 MPlist *realized_font_list;
163 /** List of pointers to realized fontsets on the frame. */
164 MPlist *realized_fontset_list;
166 /** List of XColors vs GCs on the frame. */
170 static MPlist *device_list;
172 static MSymbol M_iso8859_1, M_iso10646_1;
174 #define FRAME_DEVICE(frame) ((MWDevice *) (frame)->device)
175 #define FRAME_DISPLAY(frame) (FRAME_DEVICE (frame)->display_info->display)
176 #define FRAME_SCREEN(frame) (FRAME_DEVICE (frame)->screen_num)
177 #define FRAME_CMAP(frame) (FRAME_DEVICE (frame)->cmap)
178 #define FRAME_VISUAL(frame) DefaultVisual (FRAME_DISPLAY (frame), \
179 FRAME_SCREEN (frame))
181 #define DEFAULT_FONT "-misc-fixed-medium-r-normal--*-120-*-*-*-*-iso8859-1"
182 #define FALLBACK_FONT "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1"
189 Boolean reverse_video;
190 } AppData, *AppDataPtr;
193 free_display_info (void *object)
195 MDisplayInfo *disp_info = (MDisplayInfo *) object;
198 MPLIST_DO (plist, disp_info->font_list)
200 MPLIST_DO (p, MPLIST_VAL (plist))
201 free (MPLIST_VAL (p));
202 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
204 M17N_OBJECT_UNREF (disp_info->font_list);
205 MPLIST_DO (plist, disp_info->base_font_list)
206 free (MPLIST_VAL (plist));
207 M17N_OBJECT_UNREF (disp_info->base_font_list);
209 if (disp_info->auto_display)
210 XCloseDisplay (disp_info->display);
216 free_device (void *object)
218 MWDevice *device = object;
221 for (plist = device->realized_fontset_list;
222 mplist_key (plist) != Mnil; plist = mplist_next (plist))
223 mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist));
224 M17N_OBJECT_UNREF (device->realized_fontset_list);
226 MPLIST_DO (plist, device->realized_font_list)
227 mfont__free_realized ((MRealizedFont *) MPLIST_VAL (plist));
228 M17N_OBJECT_UNREF (device->realized_font_list);
230 MPLIST_DO (plist, device->realized_face_list)
232 MRealizedFace *rface = MPLIST_VAL (plist);
235 mface__free_realized (rface);
237 M17N_OBJECT_UNREF (device->realized_face_list);
239 MPLIST_DO (plist, device->gc_list)
241 XFreeGC (device->display_info->display,
242 ((RGB_GC *) MPLIST_VAL (plist))->gc);
243 free (MPLIST_VAL (plist));
245 M17N_OBJECT_UNREF (device->gc_list);
246 XFreeGC (device->display_info->display, device->scratch_gc);
249 XftDrawDestroy (device->xft_draw);
252 XFreePixmap (device->display_info->display, device->drawable);
253 M17N_OBJECT_UNREF (device->display_info);
259 find_modifier_bits (MDisplayInfo *disp_info)
261 Display *display = disp_info->display;
262 XModifierKeymap *mods;
263 KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L);
264 KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R);
265 KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L);
266 KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R);
267 KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
268 KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
269 KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
270 KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
273 mods = XGetModifierMapping (display);
274 /* We skip the first three sets for Shift, Lock, and Control. The
275 remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
276 for (i = 3; i < 8; i++)
277 for (j = 0; j < mods->max_keypermod; j++)
279 KeyCode code = mods->modifiermap[i * mods->max_keypermod + j];
283 if (code == meta_l || code == meta_r)
284 disp_info->meta_mask |= (1 << i);
285 else if (code == alt_l || code == alt_r)
286 disp_info->alt_mask |= (1 << i);
287 else if (code == super_l || code == super_r)
288 disp_info->super_mask |= (1 << i);
289 else if (code == hyper_l || code == hyper_r)
290 disp_info->hyper_mask |= (1 << i);
293 /* If meta keys are not in any modifier, use alt keys as meta
295 if (! disp_info->meta_mask)
297 disp_info->meta_mask = disp_info->alt_mask;
298 disp_info->alt_mask = 0;
300 /* If both meta and alt are assigned to the same modifier, give meta
302 if (disp_info->meta_mask & disp_info->alt_mask)
303 disp_info->alt_mask &= ~disp_info->meta_mask;
305 XFreeModifiermap (mods);
309 get_rgb_gc (MWDevice *device, XColor *xcolor)
311 int rgb = (((xcolor->red >> 8) << 16) | ((xcolor->green >> 8) << 8)
312 | (xcolor->blue >> 8));
315 unsigned long valuemask = GCForeground;
318 MPLIST_DO (plist, device->gc_list)
320 rgb_gc = MPLIST_VAL (plist);
322 if (rgb_gc->rgb == rgb)
324 if (rgb_gc->rgb > rgb)
328 if (! XAllocColor (device->display_info->display, device->cmap, xcolor))
331 rgb_gc = malloc (sizeof (RGB_GC));
333 values.foreground = xcolor->pixel;
334 rgb_gc->gc = XCreateGC (device->display_info->display,
335 device->drawable, valuemask, &values);
336 mplist_push (plist, Mt, rgb_gc);
341 get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret)
343 MWDevice *device = FRAME_DEVICE (frame);
351 color = for_foreground ? frame->foreground : frame->background;
353 if (! XParseColor (FRAME_DISPLAY (frame), device->cmap,
354 msymbol_name (color), &xcolor))
356 rgb_gc = get_rgb_gc (device, &xcolor);
360 *rgb_ret = rgb_gc->rgb;
365 GCInfo *info = frame->rface->info;
370 rgb = info->rgb_fore, gc = info->gc[GC_NORMAL];
372 rgb = info->rgb_back, gc = info->gc[GC_INVERSE];
380 get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity)
382 int rgb_fore, rgb_back;
387 if (info->gc[intensity])
388 return info->gc[intensity];
390 rgb_fore = info->rgb_fore, rgb_back = info->rgb_back;
391 xcolor.red = ((((rgb_fore & 0xFF0000) >> 16) * intensity
392 + ((rgb_back & 0xFF0000) >> 16) * (7 - intensity)) / 7) << 8;
393 xcolor.green = ((((rgb_fore & 0xFF00) >> 8) * intensity
394 + ((rgb_back & 0xFF00) >> 8) * (7 - intensity)) / 7) << 8;
395 xcolor.blue = (((rgb_fore & 0xFF) * intensity
396 + (rgb_back & 0xFF) * (7 - intensity)) / 7) << 8;
397 rgb_gc = get_rgb_gc (device, &xcolor);
401 gc =get_gc_for_anti_alias (device, info,
402 intensity < 4 ? intensity - 1 : intensity + 1);
403 return (info->gc[intensity] = gc);
407 set_region (MFrame *frame, GC gc, MDrawRegion region)
409 unsigned long valuemask = GCForeground;
411 XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
412 FRAME_DEVICE (frame)->scratch_gc);
413 XSetRegion (FRAME_DISPLAY (frame), FRAME_DEVICE (frame)->scratch_gc, region);
414 return FRAME_DEVICE (frame)->scratch_gc;
418 /** X font handler */
420 static MRealizedFont *xfont_select (MFrame *, MFont *, MFont *, int);
421 static int xfont_open (MRealizedFont *);
422 static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int);
423 static unsigned xfont_encode_char (MRealizedFont *, unsigned);
424 static void xfont_render (MDrawWindow, int, int, MGlyphString *,
425 MGlyph *, MGlyph *, int, MDrawRegion);
426 static void xfont_list (MFrame *frame, MPlist *plist,
427 MFont *font, MSymbol language);
430 static MFontDriver xfont_driver =
431 { xfont_select, xfont_open,
432 xfont_find_metric, xfont_encode_char, xfont_render, xfont_list };
435 font_compare (const void *p1, const void *p2)
437 return strcmp (*(char **) p1, *(char **) p2);
441 xfont_registry_list (MDisplayInfo *disp_info, MSymbol registry)
443 MPlist *font_list = disp_info->font_list;
444 MPlist *base_font_list = disp_info->base_font_list;
445 MPlist *plist = mplist (), *p;
447 char **font_names, **names;
451 MXFontList *xfont_table;
454 mplist_add (font_list, registry, plist);
455 sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", msymbol_name (registry));
456 font_names = XListFonts (disp_info->display, pattern, 0x8000, &nfonts);
459 names = alloca (sizeof (char *) * nfonts);
460 memcpy (names, font_names, sizeof (char *) * nfonts);
461 qsort (names, nfonts, sizeof (char *), font_compare);
462 for (i = 0, p = NULL; i < nfonts; i++)
463 if (mfont__parse_name_into_font (names[i], Mx, (MFont *) &font) == 0
464 && (font.core.property[MFONT_SIZE] > 0
465 || font.core.property[MFONT_RESY] == 0))
467 MSymbol family = FONT_PROPERTY ((MFont *) &font, MFONT_FAMILY);
468 int size = font.core.property[MFONT_SIZE] / 10;
473 font.sizes[0] = font.sizes[1] = 0;
474 SET_SIZE (&font, size);
476 /* Handle fonts of the same base. */
477 for (base_end = names[i], fields = 0; *base_end; base_end++)
479 && ++fields == 7 /* PIXEL_SIZE */)
481 base_len = base_end - names[i];
482 for (j = i + 1; j < nfonts && ! strncmp (names[i], names[j], base_len);
484 if (mfont__parse_name_into_font (names[j], Mx, (MFont *) &font) == 0
485 && (font.core.property[MFONT_SIZE] > 0
486 || font.core.property[MFONT_RESY] == 0))
488 size = font.core.property[MFONT_SIZE] / 10;
489 SET_SIZE (&font, size);
492 if (p && MPLIST_KEY (p) != family)
493 p = mplist_find_by_key (plist, family);
495 xfont_table = MPLIST_VAL (p);
499 MSTRUCT_MALLOC (xfont_table, MERROR_WIN);
500 MLIST_INIT1 (xfont_table, fonts, 4);
501 mplist_push (p, family, xfont_table);
503 MLIST_APPEND1 (xfont_table, fonts, font, MERROR_WIN);
505 || (font.core.property[MFONT_FOUNDRY]
506 != bfont->property[MFONT_FOUNDRY])
507 || (font.core.property[MFONT_FAMILY]
508 != bfont->property[MFONT_FAMILY]))
510 MSTRUCT_MALLOC (bfont, MERROR_WIN);
512 for (j = MFONT_WEIGHT; j <= MFONT_ADSTYLE; j++)
513 bfont->property[j] = 0;
514 bfont->property[MFONT_SIZE] = bfont->property[MFONT_RESY] = 0;
515 mplist_push (base_font_list, family, bfont);
518 XFreeFontNames (font_names);
529 /* The X font driver function SELECT. */
531 static MRealizedFont *
532 xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size){
534 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
535 MSymbol family = FONT_PROPERTY (spec, MFONT_FAMILY);
536 MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
537 int requested_size = request->property[MFONT_SIZE];
538 MRealizedFont *rfont;
542 int best_score, score;
545 || ! strchr (MSYMBOL_NAME (registry), '-'))
548 plist = mplist_get (disp_info->font_list, registry);
550 && ! (plist = xfont_registry_list (disp_info, registry)))
552 best_score = -1, best_font = NULL;
554 family = FONT_PROPERTY (request, MFONT_FAMILY);
555 MPLIST_DO (plist, plist)
557 if (family == Mnil || family == MPLIST_KEY (plist))
559 MXFontList *xfont_table = MPLIST_VAL (plist);
561 for (i = 0; i < xfont_table->used; i++)
563 MXFont *xfont = xfont_table->fonts + i;
564 MFont *font = (MFont *) xfont;
565 int size = requested_size / 10, s0, s1;
567 for (s0 = size; s0 > 0 && ! HAVE_SIZE (xfont, s0); s0--);
568 if (s0 * 10 == requested_size)
569 /* Exact size match. */
571 else if (xfont->sizes[0] & 1)
574 else if (limited_size)
575 /* We can't use a larger font. */
579 for (s0 = size + 1; s0 < 64 && ! HAVE_SIZE (xfont, s0); s0++);
586 for (s1 = size + (size - s0) - 1;
587 s1 > size && HAVE_SIZE (xfont, s1); s1++);
588 size = (s1 > size ? s1 : s0);
590 font->property[MFONT_SIZE] = size * 10;
592 if ((score = mfont__score (font, spec, request,
594 && (best_score < 0 || score < best_score))
597 best_font = (MFont *) (xfont_table->fonts + i);
609 MSTRUCT_CALLOC (rfont, MERROR_WIN);
610 rfont->frame = frame;
612 rfont->request = *request;
613 rfont->font = *best_font;
614 if (best_font->property[MFONT_SIZE] == 0)
615 rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE];
616 rfont->score = best_score;
621 /* The X font driver function CLOSE. */
624 close_xfont (void *object)
626 MXFontInfo *xfont_info = object;
628 XFreeFont (xfont_info->display, xfont_info->xfont);
633 /* The X font driver function OPEN. */
636 xfont_open (MRealizedFont *rfont)
639 MXFontInfo *xfont_info;
640 MFrame *frame = rfont->frame;
641 int mdebug_mask = MDEBUG_FONT;
643 /* This never fail to generate a valid fontname because open_spec
644 should correspond to a font available on the system. */
645 name = mfont_unparse_name (&rfont->font, Mx);
646 M17N_OBJECT (xfont_info, close_xfont, MERROR_WIN);
647 xfont_info->display = FRAME_DISPLAY (frame);
648 xfont_info->xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
649 if (! xfont_info->xfont)
653 MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
657 rfont->info = xfont_info;
658 MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
661 rfont->ascent = xfont_info->xfont->ascent;
662 rfont->descent = xfont_info->xfont->descent;
664 rfont->fontp = xfont_info->xfont;
669 /* The X font driver function FIND_METRIC. */
672 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
675 MXFontInfo *xfont_info = rfont->info;
676 XFontStruct *xfont = xfont_info->xfont;
677 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
679 for (; g != gend; g++)
681 if (g->code == MCHAR_INVALID_CODE)
683 g->lbearing = xfont->max_bounds.lbearing;
684 g->rbearing = xfont->max_bounds.rbearing;
685 g->width = xfont->max_bounds.width;
686 g->ascent = xfont->ascent;
687 g->descent = xfont->descent;
691 int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
692 XCharStruct *pcm = NULL;
694 if (xfont->per_char != NULL)
696 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
699 && byte2 >= xfont->min_char_or_byte2
700 && byte2 <= xfont->max_char_or_byte2)
701 pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
705 if (byte1 >= xfont->min_byte1
706 && byte1 <= xfont->max_byte1
707 && byte2 >= xfont->min_char_or_byte2
708 && byte2 <= xfont->max_char_or_byte2)
710 pcm = (xfont->per_char
711 + ((xfont->max_char_or_byte2
712 - xfont->min_char_or_byte2 + 1)
713 * (byte1 - xfont->min_byte1))
714 + (byte2 - xfont->min_char_or_byte2));
721 g->lbearing = pcm->lbearing;
722 g->rbearing = pcm->rbearing;
723 g->width = pcm->width;
724 g->ascent = pcm->ascent;
725 g->descent = pcm->descent;
729 /* If the per_char pointer is null, all glyphs between
730 the first and last character indexes inclusive have
731 the same information, as given by both min_bounds and
734 g->rbearing = xfont->max_bounds.width;
735 g->width = xfont->max_bounds.width;
736 g->ascent = xfont->ascent;
737 g->descent = xfont->descent;
744 /* The X font driver function GET_GLYPH_ID. */
747 xfont_encode_char (MRealizedFont *rfont, unsigned code)
749 MXFontInfo *xfont_info;
751 unsigned min_byte1, max_byte1, min_byte2, max_byte2;
754 if (rfont->status < 0 || code >= 0x10000)
755 return MCHAR_INVALID_CODE;
756 if (rfont->status == 0)
758 if (xfont_open (rfont) < 0)
759 return MCHAR_INVALID_CODE;
761 xfont_info = rfont->info;
762 xfont = xfont_info->xfont;
763 all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
764 min_byte1 = xfont->min_byte1;
765 max_byte1 = xfont->max_byte1;
766 min_byte2 = xfont->min_char_or_byte2;
767 max_byte2 = xfont->max_char_or_byte2;
769 if (min_byte1 == 0 && max_byte1 == 0)
773 if (code < min_byte2 || code > max_byte2)
774 return MCHAR_INVALID_CODE;
777 pcm = xfont->per_char + (code - min_byte2);
778 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
779 ? code : MCHAR_INVALID_CODE);
783 unsigned byte1 = code >> 8, byte2 = code & 0xFF;
786 if (byte1 < min_byte1 || byte1 > max_byte1
787 || byte2 < min_byte2 || byte2 > max_byte2)
788 return MCHAR_INVALID_CODE;
792 pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
793 + (byte2 - min_byte2));
794 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
795 ? code : MCHAR_INVALID_CODE);
799 /* The X font driver function RENDER. */
802 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
803 MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
805 MRealizedFace *rface = from->rface;
806 MXFontInfo *xfont_info = rface->rfont->info;
809 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
816 /* It is assured that the all glyphs in the current range use the
817 same realized face. */
818 display = FRAME_DISPLAY (rface->frame);
821 gc = set_region (rface->frame, gc, region);
822 XSetFont (display, gc, xfont_info->xfont->fid);
823 code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
824 for (i = 0, g = from; g < to; i++, g++)
826 code[i].byte1 = g->code >> 8;
827 code[i].byte2 = g->code & 0xFF;
833 if (g->type == GLYPH_PAD)
835 else if (g->type == GLYPH_SPACE)
836 for (; g < to && g->type == GLYPH_SPACE; g++)
838 else if (! g->rface->rfont)
840 if ((g->c >= 0x200B && g->c <= 0x200F)
841 || (g->c >= 0x202A && g->c <= 0x202E))
845 /* As a font is not found for this character, draw an
847 int box_width = g->width;
848 int box_height = gstring->ascent + gstring->descent;
854 XDrawRectangle (display, (Window) win, gc,
855 x, y - gstring->ascent, box_width, box_height);
859 else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
861 XDrawString16 (display, (Window) win, gc,
862 x + g->xoff, y + g->yoff, code + (g - from), 1);
869 int code_idx = g - from;
872 g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
875 XDrawString16 (display, (Window) win, gc, orig_x, y,
882 xfont_list (MFrame *frame, MPlist *plist, MFont *font, MSymbol language)
884 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
887 /* We have not yet implemented the language check. */
888 MPLIST_DO (p, disp_info->base_font_list)
890 || mfont__match_p ((MFont *) MPLIST_VAL (p), font, MFONT_REGISTRY))
891 mplist_push (plist, MPLIST_KEY (p), MPLIST_VAL (p));
907 static int xft_open (MRealizedFont *);
908 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
909 static void xft_render (MDrawWindow, int, int, MGlyphString *,
910 MGlyph *, MGlyph *, int, MDrawRegion);
912 MFontDriver xft_driver =
913 { NULL, /* Set to ft_select in device_init (). */
914 xft_open, xft_find_metric,
915 NULL, /* Set to ft_encode_char in device_init (). */
917 NULL /* Set to ft_list in device_init (). */
922 close_xft (void *object)
924 MXftFontInfo *font_info = object;
926 XftFontClose (font_info->display, font_info->font_aa);
927 XftFontClose (font_info->display, font_info->font_no_aa);
933 xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
936 XftFontInfo *xft_font_info;
939 pattern = XftPatternCreate ();
940 XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
941 XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
942 XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
943 xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
946 font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
947 XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
953 xft_open (MRealizedFont *rfont)
957 MXftFontInfo *font_info;
960 if ((mfont__ft_driver.open) (rfont) < 0)
963 size = rfont->font.property[MFONT_SIZE] / 10;
964 frame = rfont->frame;
966 ft_info = rfont->info;
967 M17N_OBJECT (font_info, close_xft, MERROR_WIN);
968 ft_info->extra_info = font_info;
969 font_info->display = FRAME_DISPLAY (frame);
970 font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
971 if (font_info->font_aa)
973 font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
974 if (font_info->font_no_aa)
977 rfont->fontp = font_info->font_no_aa;
980 XftFontClose (FRAME_DISPLAY (rfont->frame), font_info->font_aa);
983 ft_info->extra_info = NULL;
990 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
993 MFTInfo *ft_info = rfont->info;
994 MXftFontInfo *font_info = ft_info->extra_info;
995 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
997 for (; g != gend; g++)
999 if (g->code == MCHAR_INVALID_CODE)
1001 MGlyph *start = g++;
1003 while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
1004 (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
1012 XftGlyphExtents (FRAME_DISPLAY (gstring->frame),
1013 font_info->font_aa, &g->code, 1, &extents);
1014 g->lbearing = - extents.x;
1015 g->rbearing = extents.width - extents.x;
1016 g->width = extents.xOff;
1017 g->ascent = extents.y;
1018 g->descent = extents.height - extents.y;
1025 xft_render (MDrawWindow win, int x, int y,
1026 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1027 int reverse, MDrawRegion region)
1029 MRealizedFace *rface = from->rface;
1030 MFrame *frame = rface->frame;
1031 MFTInfo *ft_info = rface->rfont->info;
1032 MXftFontInfo *font_info = ft_info->extra_info;
1033 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1034 XftColor *xft_color = (! reverse
1035 ? &((GCInfo *) rface->info)->xft_color_fore
1036 : &((GCInfo *) rface->info)->xft_color_back);
1037 XftFont *xft_font = (gstring->control.anti_alias
1038 && FRAME_DEVICE (frame)->depth > 1
1039 ? font_info->font_aa : font_info->font_no_aa);
1048 XftDrawChange (xft_draw, (Drawable) win);
1049 XftDrawSetClip (xft_draw, (Region) region);
1051 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1052 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1054 if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1055 glyphs[nglyphs++] = g->code;
1059 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1060 last_x, y, glyphs, nglyphs);
1062 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1063 x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1064 last_x = x + g->width;
1068 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1074 /* Functions for the device driver. */
1077 mwin__close_device (MFrame *frame)
1079 M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
1083 mwin__device_get_prop (MFrame *frame, MSymbol key)
1085 MWDevice *device = FRAME_DEVICE (frame);
1087 if (key == Mdisplay)
1088 return (void *) device->display_info->display;
1090 return (void *) ScreenOfDisplay(device->display_info->display,
1091 device->screen_num);
1092 if (key == Mcolormap)
1093 return (void *) device->cmap;
1095 return (void *) device->depth;
1100 mwin__realize_face (MRealizedFace *rface)
1103 MSymbol foreground, background, videomode;
1104 MFaceHLineProp *hline;
1108 if (rface != rface->ascii_rface)
1110 rface->info = rface->ascii_rface->info;
1114 frame = rface->frame;
1115 MSTRUCT_CALLOC (info, MERROR_WIN);
1117 foreground = rface->face.property[MFACE_FOREGROUND];
1118 background = rface->face.property[MFACE_BACKGROUND];
1119 videomode = rface->face.property[MFACE_VIDEOMODE];
1121 videomode = frame->videomode;
1122 if (videomode != Mreverse)
1124 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1125 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1129 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1130 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1133 if (foreground == Mnil)
1134 foreground = frame->foreground;
1135 if (background == Mnil)
1136 background = frame->background;
1137 if (videomode == Mreverse)
1139 MSymbol temp = foreground;
1140 foreground = background;
1143 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1144 FRAME_VISUAL (frame),
1146 MSYMBOL_NAME (foreground),
1147 &info->xft_color_fore))
1149 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1150 FRAME_VISUAL (frame),
1152 MSYMBOL_NAME (background),
1153 &info->xft_color_back))
1157 hline = rface->hline;
1161 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1163 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1170 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1172 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1174 if (box->color_left && box->color_left != box->color_top)
1175 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1177 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1179 if (box->color_bottom && box->color_bottom != box->color_top)
1180 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1182 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1184 if (box->color_right && box->color_right != box->color_bottom)
1185 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1187 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1195 mwin__free_realized_face (MRealizedFace *rface)
1197 if (rface == rface->ascii_rface)
1203 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1205 int x, int y, int width, int height, MDrawRegion region)
1207 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1210 gc = set_region (frame, gc, region);
1212 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1213 x, y, width, height);
1218 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1219 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1220 int reverse, MDrawRegion region)
1222 MRealizedFace *rface = from->rface;
1223 Display *display = FRAME_DISPLAY (rface->frame);
1224 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1230 gc = set_region (rface->frame, gc, region);
1231 for (; from < to; from++)
1233 XDrawRectangle (display, (Window) win, gc,
1234 x, y - gstring->ascent + 1, from->width - 1,
1235 gstring->ascent + gstring->descent - 2);
1242 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1243 MRealizedFace *rface, int reverse,
1244 int x, int y, int width, MDrawRegion region)
1246 enum MFaceHLineType type = rface->hline->type;
1247 GCInfo *info = rface->info;
1248 GC gc = gc = info->gc[GC_HLINE];
1251 y = (type == MFACE_HLINE_BOTTOM
1252 ? y + gstring->text_descent - rface->hline->width
1253 : type == MFACE_HLINE_UNDER
1255 : type == MFACE_HLINE_STRIKE_THROUGH
1256 ? y - ((gstring->ascent + gstring->descent) / 2)
1257 : y - gstring->text_ascent);
1259 gc = set_region (frame, gc, region);
1261 for (i = 0; i < rface->hline->width; i++)
1262 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1263 x, y + i, x + width - 1, y + i);
1268 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1269 MGlyph *g, int x, int y, int width, MDrawRegion region)
1271 Display *display = FRAME_DISPLAY (frame);
1272 MRealizedFace *rface = g->rface;
1273 MFaceBoxProp *box = rface->box;
1274 GCInfo *info = rface->info;
1275 GC gc_top, gc_left, gc_right, gc_btm;
1279 y0 = y - (gstring->text_ascent
1280 + rface->box->inner_vmargin + rface->box->width);
1281 y1 = y + (gstring->text_descent
1282 + rface->box->inner_vmargin + rface->box->width - 1);
1284 gc_top = info->gc[GC_BOX_TOP];
1286 gc_top = set_region (frame, gc_top, region);
1287 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1290 gc_btm = info->gc[GC_BOX_BOTTOM];
1292 if (g->type == GLYPH_BOX)
1296 if (g->left_padding)
1297 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1299 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1301 /* Draw the top side. */
1302 for (i = 0; i < box->width; i++)
1303 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1305 /* Draw the bottom side. */
1306 if (region && gc_btm != gc_top)
1307 gc_btm = set_region (frame, gc_btm, region);
1308 for (i = 0; i < box->width; i++)
1309 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1311 if (g->left_padding > 0)
1313 /* Draw the left side. */
1314 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1318 gc_left = info->gc[GC_BOX_LEFT];
1320 gc_left = set_region (frame, gc_left, region);
1322 for (i = 0; i < rface->box->width; i++)
1323 XDrawLine (display, (Window) win, gc_left,
1324 x0 + i, y0 + i, x0 + i, y1 - i);
1328 /* Draw the right side. */
1329 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1333 gc_right = info->gc[GC_BOX_RIGHT];
1335 gc_right = set_region (frame, gc_right, region);
1337 for (i = 0; i < rface->box->width; i++)
1338 XDrawLine (display, (Window) win, gc_right,
1339 x1 - i, y0 + i, x1 - i, y1 - i);
1344 /* Draw the top side. */
1345 for (i = 0; i < box->width; i++)
1346 XDrawLine (display, (Window) win, gc_top,
1347 x, y0 + i, x + width - 1, y0 + i);
1349 /* Draw the bottom side. */
1350 if (region && gc_btm != gc_top)
1351 gc_btm = set_region (frame, gc_btm, region);
1352 for (i = 0; i < box->width; i++)
1353 XDrawLine (display, (Window) win, gc_btm,
1354 x, y1 - i, x + width - 1, y1 - i);
1361 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1362 int reverse, int x, int y,
1363 int width, int height, int row_bytes, unsigned char *bmp,
1366 Display *display = FRAME_DISPLAY (frame);
1368 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1371 gc = set_region (frame, gc, region);
1373 for (i = 0; i < height; i++, bmp += row_bytes)
1374 for (j = 0; j < width; j++)
1375 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1376 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1381 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1382 int intensity, MDrawPoint *points, int num,
1385 GCInfo *info = rface->info;
1388 if (! (gc = info->gc[intensity]))
1389 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1392 gc = set_region (frame, gc, region);
1394 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1395 (XPoint *) points, num, CoordModeOrigin);
1400 mwin__region_from_rect (MDrawMetric *rect)
1402 MDrawRegion region1 = XCreateRegion ();
1403 MDrawRegion region2 = XCreateRegion ();
1408 xrect.width = rect->width;
1409 xrect.height = rect->height;
1410 XUnionRectWithRegion (&xrect, region1, region2);
1411 XDestroyRegion (region1);
1416 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1418 MDrawRegion region1 = XCreateRegion ();
1423 xrect.width = rect->width;
1424 xrect.height = rect->height;
1426 XUnionRegion (region, region, region1);
1427 XUnionRectWithRegion (&xrect, region1, region);
1428 XDestroyRegion (region1);
1432 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1434 MDrawRegion region = XCreateRegion ();
1436 XUnionRegion (region1, region1, region);
1437 XIntersectRegion (region, region2, region1);
1438 XDestroyRegion (region);
1442 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1444 MDrawRegion region1 = XCreateRegion ();
1449 xrect.width = rect->width;
1450 xrect.height = rect->height;
1451 XUnionRectWithRegion (&xrect, region1, region);
1452 XDestroyRegion (region1);
1456 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1460 XClipBox (region, &xrect);
1463 rect->width = xrect.width;
1464 rect->height = xrect.height;
1468 mwin__free_region (MDrawRegion region)
1470 XDestroyRegion (region);
1474 mwin__dump_region (MDrawRegion region)
1477 XClipBox (region, &rect);
1478 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1483 mwin__create_window (MFrame *frame, MDrawWindow parent)
1485 Display *display = FRAME_DISPLAY (frame);
1487 XWMHints wm_hints = { InputHint, False };
1488 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1489 XSetWindowAttributes set_attrs;
1492 GCInfo *info = frame->rface->info;
1495 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1496 mask = GCForeground;
1497 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1498 set_attrs.background_pixel = values.foreground;
1499 set_attrs.backing_store = Always;
1500 set_attrs.override_redirect = True;
1501 set_attrs.save_under = True;
1502 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1503 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1504 CopyFromParent, InputOutput, CopyFromParent,
1506 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1507 NULL, &wm_hints, &class_hints);
1508 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1509 return (MDrawWindow) win;
1513 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1515 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1520 mwin__event_window (void *event)
1522 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1526 mwin__print_event (void *arg, char *win_name)
1529 XEvent *event = (XEvent *) arg;
1531 switch (event->xany.type)
1533 case 2: event_name = "KeyPress"; break;
1534 case 3: event_name = "KeyRelease"; break;
1535 case 4: event_name = "ButtonPress"; break;
1536 case 5: event_name = "ButtonRelease"; break;
1537 case 6: event_name = "MotionNotify"; break;
1538 case 7: event_name = "EnterNotify"; break;
1539 case 8: event_name = "LeaveNotify"; break;
1540 case 9: event_name = "FocusIn"; break;
1541 case 10: event_name = "FocusOut"; break;
1542 case 11: event_name = "KeymapNotify"; break;
1543 case 12: event_name = "Expose"; break;
1544 case 13: event_name = "GraphicsExpose"; break;
1545 case 14: event_name = "NoExpose"; break;
1546 case 15: event_name = "VisibilityNotify"; break;
1547 case 16: event_name = "CreateNotify"; break;
1548 case 17: event_name = "DestroyNotify"; break;
1549 case 18: event_name = "UnmapNotify"; break;
1550 case 19: event_name = "MapNotify"; break;
1551 case 20: event_name = "MapRequest"; break;
1552 case 21: event_name = "ReparentNotify"; break;
1553 case 22: event_name = "ConfigureNotify"; break;
1554 case 23: event_name = "ConfigureRequest"; break;
1555 case 24: event_name = "GravityNotify"; break;
1556 case 25: event_name = "ResizeRequest"; break;
1557 case 26: event_name = "CirculateNotify"; break;
1558 case 27: event_name = "CirculateRequest"; break;
1559 case 28: event_name = "PropertyNotify"; break;
1560 case 29: event_name = "SelectionClear"; break;
1561 case 30: event_name = "SelectionRequest"; break;
1562 case 31: event_name = "SelectionNotify"; break;
1563 case 32: event_name = "ColormapNotify"; break;
1564 case 33: event_name = "ClientMessage"; break;
1565 case 34: event_name = "MappingNotify"; break;
1566 default: event_name = "unknown";
1569 fprintf (stderr, "%s: %s\n", win_name, event_name);
1574 mwin__map_window (MFrame *frame, MDrawWindow win)
1576 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1580 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1582 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1586 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1587 MDrawMetric *geometry)
1589 Display *display = FRAME_DISPLAY (frame);
1590 XWindowAttributes attr;
1591 Window parent = (Window) parent_win, root;
1593 XGetWindowAttributes (display, (Window) win, &attr);
1594 geometry->x = attr.x + attr.border_width;
1595 geometry->y = attr.y + attr.border_width;
1596 geometry->width = attr.width;
1597 geometry->height = attr.height;
1600 parent = RootWindow (display, FRAME_SCREEN (frame));
1603 Window this_parent, *children;
1606 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1609 if (this_parent == parent || this_parent == root)
1611 win = (MDrawWindow) this_parent;
1612 XGetWindowAttributes (display, (Window) win, &attr);
1613 geometry->x += attr.x + attr.border_width;
1614 geometry->y += attr.y + attr.border_width;
1619 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1620 MDrawMetric *current, MDrawMetric *new)
1622 Display *display = FRAME_DISPLAY (frame);
1623 unsigned int mask = 0;
1624 XWindowChanges values;
1626 if (current->width != new->width)
1629 if (new->width <= 0)
1631 values.width = current->width = new->width;
1633 if (current->height != new->height)
1636 if (new->height <= 0)
1638 values.height = current->height = new->height;
1640 if (current->x != new->x)
1643 values.x = current->x = new->x;
1645 if (current->y != new->y)
1648 current->y = new->y;
1649 values.y = current->y = new->y;
1652 XConfigureWindow (display, (Window) win, mask, &values);
1653 XClearWindow (display, (Window) win);
1657 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1659 XEvent *event = (XEvent *) arg;
1660 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1667 if (event->xany.type != KeyPress
1668 /* && event->xany.type != KeyRelease */
1671 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1678 if (c < XK_space || c > XK_asciitilde)
1680 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1681 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1682 if (((XKeyEvent *) event)->state & ControlMask)
1684 if (c >= 'a' && c <= 'z')
1686 if (c >= ' ' && c < 127)
1687 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1689 key = minput__char_to_key (c);
1691 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1695 char *str = XKeysymToString (keysym);
1699 key = msymbol (str);
1700 if (((XKeyEvent *) event)->state & ShiftMask)
1701 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1702 if (((XKeyEvent *) event)->state & ControlMask)
1703 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1705 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1706 *modifiers |= MINPUT_KEY_META_MODIFIER;
1707 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1708 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1709 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1710 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1711 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1712 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1719 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1721 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1723 Display *display = FRAME_DISPLAY (frame);
1724 GCInfo *info = rface->info;
1727 for (i = 0; i <= GC_INVERSE; i++)
1729 XGetGCValues (display, info->gc[i], valuemask, &values);
1730 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1731 values.foreground, values.background);
1732 fprintf (stderr, "\n");
1736 static MDeviceDriver x_driver =
1739 mwin__device_get_prop,
1741 mwin__free_realized_face,
1743 mwin__draw_empty_boxes,
1747 mwin__region_from_rect,
1748 mwin__union_rect_with_region,
1749 mwin__intersect_region,
1750 mwin__region_add_rect,
1751 mwin__region_to_rect,
1754 mwin__create_window,
1755 mwin__destroy_window,
1758 mwin__window_geometry,
1759 mwin__adjust_window,
1763 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1768 M_iso8859_1 = msymbol ("iso8859-1");
1769 M_iso10646_1 = msymbol ("iso10646-1");
1771 display_info_list = mplist ();
1772 device_list = mplist ();
1775 xft_driver.select = mfont__ft_driver.select;
1776 xft_driver.encode_char = mfont__ft_driver.encode_char;
1777 xft_driver.list = mfont__ft_driver.list;
1780 Mxim = msymbol ("xim");
1781 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1789 M17N_OBJECT_UNREF (display_info_list);
1790 M17N_OBJECT_UNREF (device_list);
1794 /** Return an MWDevice object corresponding to a display specified in
1797 It searches device_list for a device matching the display. If
1798 found, return the found object. Otherwise, return a newly created
1802 device_open (MFrame *frame, MPlist *param)
1804 Display *display = NULL;
1805 Screen *screen = NULL;
1807 Drawable drawable = 0;
1808 Widget widget = NULL;
1810 int auto_display = 0;
1811 MDisplayInfo *disp_info = NULL;
1812 MWDevice *device = NULL;
1814 XWindowAttributes attr;
1820 for (plist = param; (key = mplist_key (plist)) != Mnil;
1821 plist = mplist_next (plist))
1823 if (key == Mdisplay)
1824 display = (Display *) mplist_value (plist);
1825 else if (key == Mscreen)
1826 screen = mplist_value (plist);
1827 else if (key == Mdrawable)
1828 drawable = (Drawable) mplist_value (plist);
1829 else if (key == Mdepth)
1830 depth = (unsigned) mplist_value (plist);
1831 else if (key == Mwidget)
1832 widget = (Widget) mplist_value (plist);
1833 else if (key == Mcolormap)
1834 cmap = (Colormap) mplist_value (plist);
1839 display = XtDisplay (widget);
1840 screen_num = XScreenNumberOfScreen (XtScreen (widget));
1841 depth = DefaultDepth (display, screen_num);
1847 unsigned width, height, border_width;
1850 MERROR (MERROR_WIN, -1);
1851 XGetGeometry (display, drawable, &root_window,
1852 &x, &y, &width, &height, &border_width, &depth);
1853 XGetWindowAttributes (display, root_window, &attr);
1854 screen_num = XScreenNumberOfScreen (attr.screen);
1859 display = DisplayOfScreen (screen);
1864 display = XOpenDisplay (NULL);
1866 MERROR (MERROR_WIN, -1);
1869 screen = DefaultScreenOfDisplay (display);
1871 screen_num = XScreenNumberOfScreen (screen);
1873 depth = DefaultDepth (display, screen_num);
1877 cmap = DefaultColormap (display, screen_num);
1879 for (plist = display_info_list; mplist_key (plist) != Mnil;
1880 plist = mplist_next (plist))
1882 disp_info = (MDisplayInfo *) mplist_value (plist);
1883 if (disp_info->display == display)
1887 if (mplist_key (plist) != Mnil)
1888 M17N_OBJECT_REF (disp_info);
1891 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
1892 disp_info->display = display;
1893 disp_info->auto_display = auto_display;
1894 disp_info->font_list = mplist ();
1895 disp_info->base_font_list = mplist ();
1896 find_modifier_bits (disp_info);
1897 mplist_add (display_info_list, Mt, disp_info);
1900 for (plist = device_list; mplist_key (plist) != Mnil;
1901 plist = mplist_next (plist))
1903 device = (MWDevice *) mplist_value (plist);
1904 if (device->display_info == disp_info
1905 && device->depth == depth
1906 && device->cmap == cmap)
1910 if (mplist_key (plist) != Mnil)
1911 M17N_OBJECT_REF (device);
1914 unsigned long valuemask = GCForeground;
1917 M17N_OBJECT (device, free_device, MERROR_WIN);
1918 device->display_info = disp_info;
1919 device->screen_num = screen_num;
1920 /* A drawable on which to create GCs. */
1921 device->drawable = XCreatePixmap (display,
1922 RootWindow (display, screen_num),
1924 device->depth = depth;
1925 device->cmap = cmap;
1926 device->realized_face_list = mplist ();
1927 device->realized_font_list = mplist ();
1928 device->realized_fontset_list = mplist ();
1929 device->gc_list = mplist ();
1930 values.foreground = BlackPixel (display, screen_num);
1931 device->scratch_gc = XCreateGC (display, device->drawable,
1932 valuemask, &values);
1934 device->xft_draw = XftDrawCreate (display, device->drawable,
1935 DefaultVisual (display, screen_num),
1940 frame->device = device;
1941 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
1942 frame->driver = &x_driver;
1943 frame->font_driver_list = mplist ();
1944 mplist_add (frame->font_driver_list, Mx, &xfont_driver);
1946 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
1948 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
1950 frame->realized_font_list = device->realized_font_list;
1951 frame->realized_face_list = device->realized_face_list;
1952 frame->realized_fontset_list = device->realized_fontset_list;
1956 XtResource resources[] = {
1957 { XtNfont, XtCFont, XtRString, sizeof (String),
1958 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
1959 { XtNforeground, XtCForeground, XtRString, sizeof (String),
1960 XtOffset (AppDataPtr, foreground), XtRString, "black" },
1961 { XtNbackground, XtCBackground, XtRString, sizeof (String),
1962 XtOffset (AppDataPtr, background), XtRString, "white" },
1963 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
1964 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
1967 XtGetApplicationResources (widget, &app_data,
1968 resources, XtNumber (resources), NULL, 0);
1969 frame->foreground = msymbol (app_data.foreground);
1970 frame->background = msymbol (app_data.background);
1971 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
1975 app_data.font = DEFAULT_FONT;
1976 frame->foreground = msymbol ("black");
1977 frame->background = msymbol ("white");
1978 frame->videomode = Mnormal;
1983 char **names = XListFonts (display, app_data.font, 1, &nfonts);
1987 if (! (frame->font = mfont_parse_name (names[0], Mx)))
1989 /* The font name does not conform to XLFD. Try to open the
1990 font and get XA_FONT property. */
1991 XFontStruct *xfont = XLoadQueryFont (display, names[0]);
1996 unsigned long value;
1999 if (XGetFontProperty (xfont, XA_FONT, &value)
2000 && (name = ((char *)
2001 XGetAtomName (display, (Atom) value))))
2003 if ((frame->font = mfont_parse_name (name, Mx)))
2006 XFreeFont (display, xfont);
2009 XFreeFontNames (names);
2012 frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
2015 face = mface_from_font (frame->font);
2016 face->property[MFACE_FONTSET] = mfontset (NULL);
2017 face->property[MFACE_FOREGROUND] = frame->foreground;
2018 face->property[MFACE_BACKGROUND] = frame->background;
2019 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2020 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2021 face->property[MFACE_VIDEOMODE] = frame->videomode;
2022 mface_put_prop (face, Mhook_func,
2023 mface_get_prop (mface__default, Mhook_func));
2024 face->property[MFACE_RATIO] = (void *) 100;
2025 mplist_push (param, Mface, face);
2026 M17N_OBJECT_UNREF (face);
2028 #ifdef X_SET_ERROR_HANDLER
2029 XSetErrorHandler (x_error_handler);
2030 XSetIOErrorHandler (x_io_error_handler);
2038 /* XIM (X Input Method) handler */
2040 typedef struct MInputXIMMethodInfo
2046 } MInputXIMMethodInfo;
2048 typedef struct MInputXIMContextInfo
2052 MConverter *converter;
2053 } MInputXIMContextInfo;
2056 xim_open_im (MInputMethod *im)
2058 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2059 MLocale *saved, *this;
2060 char *save_modifier_list;
2062 MInputXIMMethodInfo *im_info;
2064 saved = mlocale_set (LC_CTYPE, NULL);
2065 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2067 /* The specified locale is not supported. */
2068 MERROR (MERROR_LOCALE, -1);
2069 if (mlocale_get_prop (this, Mcoding) == Mnil)
2071 /* Unable to decode the output of XIM. */
2072 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2073 MERROR (MERROR_LOCALE, -1);
2076 if (arg->modifier_list)
2077 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2079 save_modifier_list = XSetLocaleModifiers ("");
2080 if (! save_modifier_list)
2082 /* The specified locale is not supported by X. */
2083 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2084 MERROR (MERROR_LOCALE, -1);
2087 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2090 /* No input method is available in the current locale. */
2091 XSetLocaleModifiers (save_modifier_list);
2092 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2093 MERROR (MERROR_WIN, -1);
2096 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2097 im_info->display = arg->display;
2099 im_info->language = mlocale_get_prop (this, Mlanguage);
2100 im_info->coding = mlocale_get_prop (this, Mcoding);
2103 XSetLocaleModifiers (save_modifier_list);
2104 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2110 xim_close_im (MInputMethod *im)
2112 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2114 XCloseIM (im_info->xim);
2119 xim_create_ic (MInputContext *ic)
2121 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2122 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2123 MInputXIMContextInfo *ic_info;
2126 if (! arg->input_style)
2128 /* By default, use Root style. */
2129 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2130 arg->preedit_attrs = NULL;
2131 arg->status_attrs = NULL;
2134 if (! arg->preedit_attrs && ! arg->status_attrs)
2135 xic = XCreateIC (im_info->xim,
2136 XNInputStyle, arg->input_style,
2137 XNClientWindow, arg->client_win,
2138 XNFocusWindow, arg->focus_win,
2140 else if (arg->preedit_attrs && ! arg->status_attrs)
2141 xic = XCreateIC (im_info->xim,
2142 XNInputStyle, arg->input_style,
2143 XNClientWindow, arg->client_win,
2144 XNFocusWindow, arg->focus_win,
2145 XNPreeditAttributes, arg->preedit_attrs,
2147 else if (! arg->preedit_attrs && arg->status_attrs)
2148 xic = XCreateIC (im_info->xim,
2149 XNInputStyle, arg->input_style,
2150 XNClientWindow, arg->client_win,
2151 XNFocusWindow, arg->focus_win,
2152 XNStatusAttributes, arg->status_attrs,
2155 xic = XCreateIC (im_info->xim,
2156 XNInputStyle, arg->input_style,
2157 XNClientWindow, arg->client_win,
2158 XNFocusWindow, arg->focus_win,
2159 XNPreeditAttributes, arg->preedit_attrs,
2160 XNStatusAttributes, arg->status_attrs,
2163 MERROR (MERROR_WIN, -1);
2165 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2167 ic_info->win = arg->focus_win;
2168 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2174 xim_destroy_ic (MInputContext *ic)
2176 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2178 XDestroyIC (ic_info->xic);
2179 mconv_free_converter (ic_info->converter);
2185 xim_filter (MInputContext *ic, MSymbol key, void *event)
2187 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2189 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2194 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2196 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2197 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2198 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2204 buf = (char *) alloca (512);
2205 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2206 if (status == XBufferOverflow)
2208 buf = (char *) alloca (len);
2209 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2212 mtext_reset (ic->produced);
2216 mconv_reset_converter (ic_info->converter);
2217 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2218 mconv_decode (ic_info->converter, ic->produced);
2219 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2220 Mlanguage, (void *) im_info->language);
2221 mtext_cpy (mt, ic->produced);
2222 mtext_reset (ic->produced);
2228 #ifdef X_SET_ERROR_HANDLER
2230 x_error_handler (Display *display, XErrorEvent *error)
2237 x_io_error_handler (Display *display)
2247 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2251 /*** @addtogroup m17nInputMethodWin */
2256 @brief Input method driver for XIM.
2258 The driver #minput_xim_driver is for the foreign input method of
2259 name #Mxim. It uses XIM (X Input Methods) as a background input
2262 As the symbol #Mxim has property #Minput_driver whose value is
2263 a pointer to this driver, the input method of language #Mnil
2264 and name #Mxim uses this driver.
2266 Therefore, for such input methods, the driver dependent arguments
2267 to the functions whose name begin with minput_ must be as follows.
2269 The argument $ARG of the function minput_open_im () must be a
2270 pointer to the structure #MInputXIMArgIM. See the documentation
2271 of #MInputXIMArgIM for more details.
2273 The argument $ARG of the function minput_create_ic () must be a
2274 pointer to the structure #MInputXIMArgIC. See the documentation
2275 of #MInputXIMArgIC for more details.
2277 The argument $ARG of the function minput_filter () must be a
2278 pointer to the structure @c XEvent. The argument $KEY is ignored.
2280 The argument $ARG of the function minput_lookup () must be the
2281 same one as that of the function minput_filter (). The argument
2285 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2287 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
2288 ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
2291 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2292 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
2293 ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2295 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
2296 ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2298 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM ¤Ø¤Î¥Ý
2299 ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
2302 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC ¤Ø¤Î
2303 ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
2306 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2307 ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2309 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2310 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2313 MInputDriver minput_xim_driver =
2314 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2315 xim_filter, xim_lookup, NULL };