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 MPlist *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));
908 static int xft_open (MRealizedFont *);
909 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
910 static void xft_render (MDrawWindow, int, int, MGlyphString *,
911 MGlyph *, MGlyph *, int, MDrawRegion);
913 MFontDriver xft_driver =
914 { NULL, /* Set to ft_select in device_init (). */
915 xft_open, xft_find_metric,
916 NULL, /* Set to ft_encode_char in device_init (). */
921 close_xft (void *object)
923 MXftFontInfo *font_info = object;
925 XftFontClose (font_info->display, font_info->font_aa);
926 XftFontClose (font_info->display, font_info->font_no_aa);
932 xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
935 XftFontInfo *xft_font_info;
938 pattern = XftPatternCreate ();
939 XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
940 XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
941 XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
942 xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
945 font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
946 XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
952 xft_open (MRealizedFont *rfont)
956 MXftFontInfo *font_info;
959 if ((mfont__ft_driver.open) (rfont) < 0)
962 size = rfont->font.property[MFONT_SIZE] / 10;
963 frame = rfont->frame;
965 ft_info = rfont->info;
966 M17N_OBJECT (font_info, close_xft, MERROR_WIN);
967 ft_info->extra_info = font_info;
968 font_info->display = FRAME_DISPLAY (frame);
969 font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
970 if (font_info->font_aa)
972 font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
973 if (font_info->font_no_aa)
976 rfont->fontp = font_info->font_no_aa;
979 XftFontClose (FRAME_DISPLAY (rfont->frame), font_info->font_aa);
982 ft_info->extra_info = NULL;
989 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
992 MFTInfo *ft_info = rfont->info;
993 MXftFontInfo *font_info = ft_info->extra_info;
994 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
996 for (; g != gend; g++)
998 if (g->code == MCHAR_INVALID_CODE)
1000 MGlyph *start = g++;
1002 while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
1003 (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
1011 XftGlyphExtents (FRAME_DISPLAY (gstring->frame),
1012 font_info->font_aa, &g->code, 1, &extents);
1013 g->lbearing = - extents.x;
1014 g->rbearing = extents.width - extents.x;
1015 g->width = extents.xOff;
1016 g->ascent = extents.y;
1017 g->descent = extents.height - extents.y;
1024 xft_render (MDrawWindow win, int x, int y,
1025 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1026 int reverse, MDrawRegion region)
1028 MRealizedFace *rface = from->rface;
1029 MFrame *frame = rface->frame;
1030 MFTInfo *ft_info = rface->rfont->info;
1031 MXftFontInfo *font_info = ft_info->extra_info;
1032 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1033 XftColor *xft_color = (! reverse
1034 ? &((GCInfo *) rface->info)->xft_color_fore
1035 : &((GCInfo *) rface->info)->xft_color_back);
1036 XftFont *xft_font = (gstring->control.anti_alias
1037 && FRAME_DEVICE (frame)->depth > 1
1038 ? font_info->font_aa : font_info->font_no_aa);
1047 XftDrawChange (xft_draw, (Drawable) win);
1048 XftDrawSetClip (xft_draw, (Region) region);
1050 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1051 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1053 if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1054 glyphs[nglyphs++] = g->code;
1058 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1059 last_x, y, glyphs, nglyphs);
1061 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1062 x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1063 last_x = x + g->width;
1067 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1073 /* Functions for the device driver. */
1076 mwin__close_device (MFrame *frame)
1078 M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
1082 mwin__device_get_prop (MFrame *frame, MSymbol key)
1084 MWDevice *device = FRAME_DEVICE (frame);
1086 if (key == Mdisplay)
1087 return (void *) device->display_info->display;
1089 return (void *) ScreenOfDisplay(device->display_info->display,
1090 device->screen_num);
1091 if (key == Mcolormap)
1092 return (void *) device->cmap;
1094 return (void *) device->depth;
1099 mwin__realize_face (MRealizedFace *rface)
1102 MSymbol foreground, background, videomode;
1103 MFaceHLineProp *hline;
1107 if (rface != rface->ascii_rface)
1109 rface->info = rface->ascii_rface->info;
1113 frame = rface->frame;
1114 MSTRUCT_CALLOC (info, MERROR_WIN);
1116 foreground = rface->face.property[MFACE_FOREGROUND];
1117 background = rface->face.property[MFACE_BACKGROUND];
1118 videomode = rface->face.property[MFACE_VIDEOMODE];
1120 videomode = frame->videomode;
1121 if (videomode != Mreverse)
1123 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1124 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1128 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1129 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1132 if (foreground == Mnil)
1133 foreground = frame->foreground;
1134 if (background == Mnil)
1135 background = frame->background;
1136 if (videomode == Mreverse)
1138 MSymbol temp = foreground;
1139 foreground = background;
1142 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1143 FRAME_VISUAL (frame),
1145 MSYMBOL_NAME (foreground),
1146 &info->xft_color_fore))
1148 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1149 FRAME_VISUAL (frame),
1151 MSYMBOL_NAME (background),
1152 &info->xft_color_back))
1156 hline = rface->hline;
1160 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1162 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1169 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1171 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1173 if (box->color_left && box->color_left != box->color_top)
1174 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1176 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1178 if (box->color_bottom && box->color_bottom != box->color_top)
1179 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1181 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1183 if (box->color_right && box->color_right != box->color_bottom)
1184 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1186 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1194 mwin__free_realized_face (MRealizedFace *rface)
1196 if (rface == rface->ascii_rface)
1202 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1204 int x, int y, int width, int height, MDrawRegion region)
1206 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1209 gc = set_region (frame, gc, region);
1211 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1212 x, y, width, height);
1217 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1218 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1219 int reverse, MDrawRegion region)
1221 MRealizedFace *rface = from->rface;
1222 Display *display = FRAME_DISPLAY (rface->frame);
1223 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1229 gc = set_region (rface->frame, gc, region);
1230 for (; from < to; from++)
1232 XDrawRectangle (display, (Window) win, gc,
1233 x, y - gstring->ascent + 1, from->width - 1,
1234 gstring->ascent + gstring->descent - 2);
1241 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1242 MRealizedFace *rface, int reverse,
1243 int x, int y, int width, MDrawRegion region)
1245 enum MFaceHLineType type = rface->hline->type;
1246 GCInfo *info = rface->info;
1247 GC gc = gc = info->gc[GC_HLINE];
1250 y = (type == MFACE_HLINE_BOTTOM
1251 ? y + gstring->text_descent - rface->hline->width
1252 : type == MFACE_HLINE_UNDER
1254 : type == MFACE_HLINE_STRIKE_THROUGH
1255 ? y - ((gstring->ascent + gstring->descent) / 2)
1256 : y - gstring->text_ascent);
1258 gc = set_region (frame, gc, region);
1260 for (i = 0; i < rface->hline->width; i++)
1261 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1262 x, y + i, x + width - 1, y + i);
1267 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1268 MGlyph *g, int x, int y, int width, MDrawRegion region)
1270 Display *display = FRAME_DISPLAY (frame);
1271 MRealizedFace *rface = g->rface;
1272 MFaceBoxProp *box = rface->box;
1273 GCInfo *info = rface->info;
1274 GC gc_top, gc_left, gc_right, gc_btm;
1278 y0 = y - (gstring->text_ascent
1279 + rface->box->inner_vmargin + rface->box->width);
1280 y1 = y + (gstring->text_descent
1281 + rface->box->inner_vmargin + rface->box->width - 1);
1283 gc_top = info->gc[GC_BOX_TOP];
1285 gc_top = set_region (frame, gc_top, region);
1286 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1289 gc_btm = info->gc[GC_BOX_BOTTOM];
1291 if (g->type == GLYPH_BOX)
1295 if (g->left_padding)
1296 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1298 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1300 /* Draw the top side. */
1301 for (i = 0; i < box->width; i++)
1302 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1304 /* Draw the bottom side. */
1305 if (region && gc_btm != gc_top)
1306 gc_btm = set_region (frame, gc_btm, region);
1307 for (i = 0; i < box->width; i++)
1308 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1310 if (g->left_padding > 0)
1312 /* Draw the left side. */
1313 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1317 gc_left = info->gc[GC_BOX_LEFT];
1319 gc_left = set_region (frame, gc_left, region);
1321 for (i = 0; i < rface->box->width; i++)
1322 XDrawLine (display, (Window) win, gc_left,
1323 x0 + i, y0 + i, x0 + i, y1 - i);
1327 /* Draw the right side. */
1328 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1332 gc_right = info->gc[GC_BOX_RIGHT];
1334 gc_right = set_region (frame, gc_right, region);
1336 for (i = 0; i < rface->box->width; i++)
1337 XDrawLine (display, (Window) win, gc_right,
1338 x1 - i, y0 + i, x1 - i, y1 - i);
1343 /* Draw the top side. */
1344 for (i = 0; i < box->width; i++)
1345 XDrawLine (display, (Window) win, gc_top,
1346 x, y0 + i, x + width - 1, y0 + i);
1348 /* Draw the bottom side. */
1349 if (region && gc_btm != gc_top)
1350 gc_btm = set_region (frame, gc_btm, region);
1351 for (i = 0; i < box->width; i++)
1352 XDrawLine (display, (Window) win, gc_btm,
1353 x, y1 - i, x + width - 1, y1 - i);
1360 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1361 int reverse, int x, int y,
1362 int width, int height, int row_bytes, unsigned char *bmp,
1365 Display *display = FRAME_DISPLAY (frame);
1367 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1370 gc = set_region (frame, gc, region);
1372 for (i = 0; i < height; i++, bmp += row_bytes)
1373 for (j = 0; j < width; j++)
1374 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1375 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1380 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1381 int intensity, MDrawPoint *points, int num,
1384 GCInfo *info = rface->info;
1387 if (! (gc = info->gc[intensity]))
1388 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1391 gc = set_region (frame, gc, region);
1393 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1394 (XPoint *) points, num, CoordModeOrigin);
1399 mwin__region_from_rect (MDrawMetric *rect)
1401 MDrawRegion region1 = XCreateRegion ();
1402 MDrawRegion region2 = XCreateRegion ();
1407 xrect.width = rect->width;
1408 xrect.height = rect->height;
1409 XUnionRectWithRegion (&xrect, region1, region2);
1410 XDestroyRegion (region1);
1415 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1417 MDrawRegion region1 = XCreateRegion ();
1422 xrect.width = rect->width;
1423 xrect.height = rect->height;
1425 XUnionRegion (region, region, region1);
1426 XUnionRectWithRegion (&xrect, region1, region);
1427 XDestroyRegion (region1);
1431 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1433 MDrawRegion region = XCreateRegion ();
1435 XUnionRegion (region1, region1, region);
1436 XIntersectRegion (region, region2, region1);
1437 XDestroyRegion (region);
1441 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1443 MDrawRegion region1 = XCreateRegion ();
1448 xrect.width = rect->width;
1449 xrect.height = rect->height;
1450 XUnionRectWithRegion (&xrect, region1, region);
1451 XDestroyRegion (region1);
1455 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1459 XClipBox (region, &xrect);
1462 rect->width = xrect.width;
1463 rect->height = xrect.height;
1467 mwin__free_region (MDrawRegion region)
1469 XDestroyRegion (region);
1473 mwin__dump_region (MDrawRegion region)
1476 XClipBox (region, &rect);
1477 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1482 mwin__create_window (MFrame *frame, MDrawWindow parent)
1484 Display *display = FRAME_DISPLAY (frame);
1486 XWMHints wm_hints = { InputHint, False };
1487 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1488 XSetWindowAttributes set_attrs;
1491 GCInfo *info = frame->rface->info;
1494 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1495 mask = GCForeground;
1496 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1497 set_attrs.background_pixel = values.foreground;
1498 set_attrs.backing_store = Always;
1499 set_attrs.override_redirect = True;
1500 set_attrs.save_under = True;
1501 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1502 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1503 CopyFromParent, InputOutput, CopyFromParent,
1505 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1506 NULL, &wm_hints, &class_hints);
1507 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1508 return (MDrawWindow) win;
1512 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1514 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1519 mwin__event_window (void *event)
1521 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1525 mwin__print_event (void *arg, char *win_name)
1528 XEvent *event = (XEvent *) arg;
1530 switch (event->xany.type)
1532 case 2: event_name = "KeyPress"; break;
1533 case 3: event_name = "KeyRelease"; break;
1534 case 4: event_name = "ButtonPress"; break;
1535 case 5: event_name = "ButtonRelease"; break;
1536 case 6: event_name = "MotionNotify"; break;
1537 case 7: event_name = "EnterNotify"; break;
1538 case 8: event_name = "LeaveNotify"; break;
1539 case 9: event_name = "FocusIn"; break;
1540 case 10: event_name = "FocusOut"; break;
1541 case 11: event_name = "KeymapNotify"; break;
1542 case 12: event_name = "Expose"; break;
1543 case 13: event_name = "GraphicsExpose"; break;
1544 case 14: event_name = "NoExpose"; break;
1545 case 15: event_name = "VisibilityNotify"; break;
1546 case 16: event_name = "CreateNotify"; break;
1547 case 17: event_name = "DestroyNotify"; break;
1548 case 18: event_name = "UnmapNotify"; break;
1549 case 19: event_name = "MapNotify"; break;
1550 case 20: event_name = "MapRequest"; break;
1551 case 21: event_name = "ReparentNotify"; break;
1552 case 22: event_name = "ConfigureNotify"; break;
1553 case 23: event_name = "ConfigureRequest"; break;
1554 case 24: event_name = "GravityNotify"; break;
1555 case 25: event_name = "ResizeRequest"; break;
1556 case 26: event_name = "CirculateNotify"; break;
1557 case 27: event_name = "CirculateRequest"; break;
1558 case 28: event_name = "PropertyNotify"; break;
1559 case 29: event_name = "SelectionClear"; break;
1560 case 30: event_name = "SelectionRequest"; break;
1561 case 31: event_name = "SelectionNotify"; break;
1562 case 32: event_name = "ColormapNotify"; break;
1563 case 33: event_name = "ClientMessage"; break;
1564 case 34: event_name = "MappingNotify"; break;
1565 default: event_name = "unknown";
1568 fprintf (stderr, "%s: %s\n", win_name, event_name);
1573 mwin__map_window (MFrame *frame, MDrawWindow win)
1575 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1579 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1581 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1585 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1586 MDrawMetric *geometry)
1588 Display *display = FRAME_DISPLAY (frame);
1589 XWindowAttributes attr;
1590 Window parent = (Window) parent_win, root;
1592 XGetWindowAttributes (display, (Window) win, &attr);
1593 geometry->x = attr.x + attr.border_width;
1594 geometry->y = attr.y + attr.border_width;
1595 geometry->width = attr.width;
1596 geometry->height = attr.height;
1599 parent = RootWindow (display, FRAME_SCREEN (frame));
1602 Window this_parent, *children;
1605 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1608 if (this_parent == parent || this_parent == root)
1610 win = (MDrawWindow) this_parent;
1611 XGetWindowAttributes (display, (Window) win, &attr);
1612 geometry->x += attr.x + attr.border_width;
1613 geometry->y += attr.y + attr.border_width;
1618 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1619 MDrawMetric *current, MDrawMetric *new)
1621 Display *display = FRAME_DISPLAY (frame);
1622 unsigned int mask = 0;
1623 XWindowChanges values;
1625 if (current->width != new->width)
1628 if (new->width <= 0)
1630 values.width = current->width = new->width;
1632 if (current->height != new->height)
1635 if (new->height <= 0)
1637 values.height = current->height = new->height;
1639 if (current->x != new->x)
1642 values.x = current->x = new->x;
1644 if (current->y != new->y)
1647 current->y = new->y;
1648 values.y = current->y = new->y;
1651 XConfigureWindow (display, (Window) win, mask, &values);
1652 XClearWindow (display, (Window) win);
1656 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1658 XEvent *event = (XEvent *) arg;
1659 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1666 if (event->xany.type != KeyPress
1667 /* && event->xany.type != KeyRelease */
1670 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1677 if (c < XK_space || c > XK_asciitilde)
1679 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1680 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1681 if (((XKeyEvent *) event)->state & ControlMask)
1683 if (c >= 'a' && c <= 'z')
1685 if (c >= ' ' && c < 127)
1686 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1688 key = minput__char_to_key (c);
1690 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1694 char *str = XKeysymToString (keysym);
1698 key = msymbol (str);
1699 if (((XKeyEvent *) event)->state & ShiftMask)
1700 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1701 if (((XKeyEvent *) event)->state & ControlMask)
1702 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1704 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1705 *modifiers |= MINPUT_KEY_META_MODIFIER;
1706 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1707 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1708 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1709 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1710 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1711 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1718 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1720 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1722 Display *display = FRAME_DISPLAY (frame);
1723 GCInfo *info = rface->info;
1726 for (i = 0; i <= GC_INVERSE; i++)
1728 XGetGCValues (display, info->gc[i], valuemask, &values);
1729 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1730 values.foreground, values.background);
1731 fprintf (stderr, "\n");
1735 static MDeviceDriver x_driver =
1738 mwin__device_get_prop,
1740 mwin__free_realized_face,
1742 mwin__draw_empty_boxes,
1746 mwin__region_from_rect,
1747 mwin__union_rect_with_region,
1748 mwin__intersect_region,
1749 mwin__region_add_rect,
1750 mwin__region_to_rect,
1753 mwin__create_window,
1754 mwin__destroy_window,
1757 mwin__window_geometry,
1758 mwin__adjust_window,
1762 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1767 M_iso8859_1 = msymbol ("iso8859-1");
1768 M_iso10646_1 = msymbol ("iso10646-1");
1770 display_info_list = mplist ();
1771 device_list = mplist ();
1774 xft_driver.select = mfont__ft_driver.select;
1775 xft_driver.encode_char = mfont__ft_driver.encode_char;
1778 Mxim = msymbol ("xim");
1779 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1787 M17N_OBJECT_UNREF (display_info_list);
1788 M17N_OBJECT_UNREF (device_list);
1792 /** Return an MWDevice object corresponding to a display specified in
1795 It searches device_list for a device matching the display. If
1796 found, return the found object. Otherwise, return a newly created
1800 device_open (MFrame *frame, MPlist *param)
1802 Display *display = NULL;
1803 Screen *screen = NULL;
1805 Drawable drawable = 0;
1806 Widget widget = NULL;
1808 int auto_display = 0;
1809 MDisplayInfo *disp_info = NULL;
1810 MWDevice *device = NULL;
1812 XWindowAttributes attr;
1818 for (plist = param; (key = mplist_key (plist)) != Mnil;
1819 plist = mplist_next (plist))
1821 if (key == Mdisplay)
1822 display = (Display *) mplist_value (plist);
1823 else if (key == Mscreen)
1824 screen = mplist_value (plist);
1825 else if (key == Mdrawable)
1826 drawable = (Drawable) mplist_value (plist);
1827 else if (key == Mdepth)
1828 depth = (unsigned) mplist_value (plist);
1829 else if (key == Mwidget)
1830 widget = (Widget) mplist_value (plist);
1831 else if (key == Mcolormap)
1832 cmap = (Colormap) mplist_value (plist);
1837 display = XtDisplay (widget);
1838 screen_num = XScreenNumberOfScreen (XtScreen (widget));
1839 depth = DefaultDepth (display, screen_num);
1845 unsigned width, height, border_width;
1848 MERROR (MERROR_WIN, -1);
1849 XGetGeometry (display, drawable, &root_window,
1850 &x, &y, &width, &height, &border_width, &depth);
1851 XGetWindowAttributes (display, root_window, &attr);
1852 screen_num = XScreenNumberOfScreen (attr.screen);
1857 display = DisplayOfScreen (screen);
1862 display = XOpenDisplay (NULL);
1864 MERROR (MERROR_WIN, -1);
1867 screen = DefaultScreenOfDisplay (display);
1869 screen_num = XScreenNumberOfScreen (screen);
1871 depth = DefaultDepth (display, screen_num);
1875 cmap = DefaultColormap (display, screen_num);
1877 for (plist = display_info_list; mplist_key (plist) != Mnil;
1878 plist = mplist_next (plist))
1880 disp_info = (MDisplayInfo *) mplist_value (plist);
1881 if (disp_info->display == display)
1885 if (mplist_key (plist) != Mnil)
1886 M17N_OBJECT_REF (disp_info);
1889 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
1890 disp_info->display = display;
1891 disp_info->auto_display = auto_display;
1892 disp_info->font_list = mplist ();
1893 disp_info->base_font_list = mplist ();
1894 find_modifier_bits (disp_info);
1895 mplist_add (display_info_list, Mt, disp_info);
1898 for (plist = device_list; mplist_key (plist) != Mnil;
1899 plist = mplist_next (plist))
1901 device = (MWDevice *) mplist_value (plist);
1902 if (device->display_info == disp_info
1903 && device->depth == depth
1904 && device->cmap == cmap)
1908 if (mplist_key (plist) != Mnil)
1909 M17N_OBJECT_REF (device);
1912 unsigned long valuemask = GCForeground;
1915 M17N_OBJECT (device, free_device, MERROR_WIN);
1916 device->display_info = disp_info;
1917 device->screen_num = screen_num;
1918 /* A drawable on which to create GCs. */
1919 device->drawable = XCreatePixmap (display,
1920 RootWindow (display, screen_num),
1922 device->depth = depth;
1923 device->cmap = cmap;
1924 device->realized_face_list = mplist ();
1925 device->realized_font_list = mplist ();
1926 device->realized_fontset_list = mplist ();
1927 device->gc_list = mplist ();
1928 values.foreground = BlackPixel (display, screen_num);
1929 device->scratch_gc = XCreateGC (display, device->drawable,
1930 valuemask, &values);
1932 device->xft_draw = XftDrawCreate (display, device->drawable,
1933 DefaultVisual (display, screen_num),
1938 frame->device = device;
1939 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
1940 frame->driver = &x_driver;
1941 frame->font_driver_list = mplist ();
1942 mplist_add (frame->font_driver_list, Mx, &xfont_driver);
1944 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
1946 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
1948 frame->realized_font_list = device->realized_font_list;
1949 frame->realized_face_list = device->realized_face_list;
1950 frame->realized_fontset_list = device->realized_fontset_list;
1954 XtResource resources[] = {
1955 { XtNfont, XtCFont, XtRString, sizeof (String),
1956 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
1957 { XtNforeground, XtCForeground, XtRString, sizeof (String),
1958 XtOffset (AppDataPtr, foreground), XtRString, "black" },
1959 { XtNbackground, XtCBackground, XtRString, sizeof (String),
1960 XtOffset (AppDataPtr, background), XtRString, "white" },
1961 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
1962 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
1965 XtGetApplicationResources (widget, &app_data,
1966 resources, XtNumber (resources), NULL, 0);
1967 frame->foreground = msymbol (app_data.foreground);
1968 frame->background = msymbol (app_data.background);
1969 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
1973 app_data.font = DEFAULT_FONT;
1974 frame->foreground = msymbol ("black");
1975 frame->background = msymbol ("white");
1976 frame->videomode = Mnormal;
1981 char **names = XListFonts (display, app_data.font, 1, &nfonts);
1985 if (! (frame->font = mfont_parse_name (names[0], Mx)))
1987 /* The font name does not conform to XLFD. Try to open the
1988 font and get XA_FONT property. */
1989 XFontStruct *xfont = XLoadQueryFont (display, names[0]);
1994 unsigned long value;
1997 if (XGetFontProperty (xfont, XA_FONT, &value)
1998 && (name = ((char *)
1999 XGetAtomName (display, (Atom) value))))
2001 if ((frame->font = mfont_parse_name (name, Mx)))
2004 XFreeFont (display, xfont);
2007 XFreeFontNames (names);
2010 frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
2013 face = mface_from_font (frame->font);
2014 face->property[MFACE_FONTSET] = mfontset (NULL);
2015 face->property[MFACE_FOREGROUND] = frame->foreground;
2016 face->property[MFACE_BACKGROUND] = frame->background;
2017 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2018 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2019 face->property[MFACE_VIDEOMODE] = frame->videomode;
2020 mface_put_prop (face, Mhook_func,
2021 mface_get_prop (mface__default, Mhook_func));
2022 face->property[MFACE_RATIO] = (void *) 100;
2023 mplist_push (param, Mface, face);
2024 M17N_OBJECT_UNREF (face);
2026 #ifdef X_SET_ERROR_HANDLER
2027 XSetErrorHandler (x_error_handler);
2028 XSetIOErrorHandler (x_io_error_handler);
2036 /* XIM (X Input Method) handler */
2038 typedef struct MInputXIMMethodInfo
2044 } MInputXIMMethodInfo;
2046 typedef struct MInputXIMContextInfo
2050 MConverter *converter;
2051 } MInputXIMContextInfo;
2054 xim_open_im (MInputMethod *im)
2056 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2057 MLocale *saved, *this;
2058 char *save_modifier_list;
2060 MInputXIMMethodInfo *im_info;
2062 saved = mlocale_set (LC_CTYPE, NULL);
2063 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2065 /* The specified locale is not supported. */
2066 MERROR (MERROR_LOCALE, -1);
2067 if (mlocale_get_prop (this, Mcoding) == Mnil)
2069 /* Unable to decode the output of XIM. */
2070 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2071 MERROR (MERROR_LOCALE, -1);
2074 if (arg->modifier_list)
2075 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2077 save_modifier_list = XSetLocaleModifiers ("");
2078 if (! save_modifier_list)
2080 /* The specified locale is not supported by X. */
2081 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2082 MERROR (MERROR_LOCALE, -1);
2085 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2088 /* No input method is available in the current locale. */
2089 XSetLocaleModifiers (save_modifier_list);
2090 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2091 MERROR (MERROR_WIN, -1);
2094 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2095 im_info->display = arg->display;
2097 im_info->language = mlocale_get_prop (this, Mlanguage);
2098 im_info->coding = mlocale_get_prop (this, Mcoding);
2101 XSetLocaleModifiers (save_modifier_list);
2102 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2108 xim_close_im (MInputMethod *im)
2110 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2112 XCloseIM (im_info->xim);
2117 xim_create_ic (MInputContext *ic)
2119 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2120 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2121 MInputXIMContextInfo *ic_info;
2124 if (! arg->input_style)
2126 /* By default, use Root style. */
2127 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2128 arg->preedit_attrs = NULL;
2129 arg->status_attrs = NULL;
2132 if (! arg->preedit_attrs && ! arg->status_attrs)
2133 xic = XCreateIC (im_info->xim,
2134 XNInputStyle, arg->input_style,
2135 XNClientWindow, arg->client_win,
2136 XNFocusWindow, arg->focus_win,
2138 else if (arg->preedit_attrs && ! arg->status_attrs)
2139 xic = XCreateIC (im_info->xim,
2140 XNInputStyle, arg->input_style,
2141 XNClientWindow, arg->client_win,
2142 XNFocusWindow, arg->focus_win,
2143 XNPreeditAttributes, arg->preedit_attrs,
2145 else if (! arg->preedit_attrs && arg->status_attrs)
2146 xic = XCreateIC (im_info->xim,
2147 XNInputStyle, arg->input_style,
2148 XNClientWindow, arg->client_win,
2149 XNFocusWindow, arg->focus_win,
2150 XNStatusAttributes, arg->status_attrs,
2153 xic = XCreateIC (im_info->xim,
2154 XNInputStyle, arg->input_style,
2155 XNClientWindow, arg->client_win,
2156 XNFocusWindow, arg->focus_win,
2157 XNPreeditAttributes, arg->preedit_attrs,
2158 XNStatusAttributes, arg->status_attrs,
2161 MERROR (MERROR_WIN, -1);
2163 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2165 ic_info->win = arg->focus_win;
2166 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2172 xim_destroy_ic (MInputContext *ic)
2174 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2176 XDestroyIC (ic_info->xic);
2177 mconv_free_converter (ic_info->converter);
2183 xim_filter (MInputContext *ic, MSymbol key, void *event)
2185 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2187 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2192 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2194 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2195 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2196 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2202 buf = (char *) alloca (512);
2203 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2204 if (status == XBufferOverflow)
2206 buf = (char *) alloca (len);
2207 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2210 mtext_reset (ic->produced);
2214 mconv_reset_converter (ic_info->converter);
2215 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2216 mconv_decode (ic_info->converter, ic->produced);
2217 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2218 Mlanguage, (void *) im_info->language);
2219 mtext_cpy (mt, ic->produced);
2220 mtext_reset (ic->produced);
2226 #ifdef X_SET_ERROR_HANDLER
2228 x_error_handler (Display *display, XErrorEvent *error)
2235 x_io_error_handler (Display *display)
2245 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2249 /*** @addtogroup m17nInputMethodWin */
2254 @brief Input method driver for XIM.
2256 The driver #minput_xim_driver is for the foreign input method of
2257 name #Mxim. It uses XIM (X Input Methods) as a background input
2260 As the symbol #Mxim has property #Minput_driver whose value is
2261 a pointer to this driver, the input method of language #Mnil
2262 and name #Mxim uses this driver.
2264 Therefore, for such input methods, the driver dependent arguments
2265 to the functions whose name begin with minput_ must be as follows.
2267 The argument $ARG of the function minput_open_im () must be a
2268 pointer to the structure #MInputXIMArgIM. See the documentation
2269 of #MInputXIMArgIM for more details.
2271 The argument $ARG of the function minput_create_ic () must be a
2272 pointer to the structure #MInputXIMArgIC. See the documentation
2273 of #MInputXIMArgIC for more details.
2275 The argument $ARG of the function minput_filter () must be a
2276 pointer to the structure @c XEvent. The argument $KEY is ignored.
2278 The argument $ARG of the function minput_lookup () must be the
2279 same one as that of the function minput_filter (). The argument
2283 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2285 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
2286 ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
2289 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2290 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
2291 ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2293 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
2294 ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2296 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM ¤Ø¤Î¥Ý
2297 ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
2300 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC ¤Ø¤Î
2301 ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
2304 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2305 ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2307 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2308 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2311 MInputDriver minput_xim_driver =
2312 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2313 xim_filter, xim_lookup, NULL };