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 (). */
920 close_xft (void *object)
922 MXftFontInfo *font_info = object;
924 XftFontClose (font_info->display, font_info->font_aa);
925 XftFontClose (font_info->display, font_info->font_no_aa);
931 xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
934 XftFontInfo *xft_font_info;
937 pattern = XftPatternCreate ();
938 XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
939 XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
940 XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
941 xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
944 font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
945 XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
951 xft_open (MRealizedFont *rfont)
955 MXftFontInfo *font_info;
958 if ((mfont__ft_driver.open) (rfont) < 0)
961 size = rfont->font.property[MFONT_SIZE] / 10;
962 frame = rfont->frame;
964 ft_info = rfont->info;
965 M17N_OBJECT (font_info, close_xft, MERROR_WIN);
966 ft_info->extra_info = font_info;
967 font_info->display = FRAME_DISPLAY (frame);
968 font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
969 if (font_info->font_aa)
971 font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
972 if (font_info->font_no_aa)
975 rfont->fontp = font_info->font_no_aa;
978 XftFontClose (FRAME_DISPLAY (rfont->frame), font_info->font_aa);
981 ft_info->extra_info = NULL;
988 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
991 MFTInfo *ft_info = rfont->info;
992 MXftFontInfo *font_info = ft_info->extra_info;
993 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
995 for (; g != gend; g++)
997 if (g->code == MCHAR_INVALID_CODE)
1001 while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
1002 (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
1010 XftGlyphExtents (FRAME_DISPLAY (gstring->frame),
1011 font_info->font_aa, &g->code, 1, &extents);
1012 g->lbearing = - extents.x;
1013 g->rbearing = extents.width - extents.x;
1014 g->width = extents.xOff;
1015 g->ascent = extents.y;
1016 g->descent = extents.height - extents.y;
1023 xft_render (MDrawWindow win, int x, int y,
1024 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1025 int reverse, MDrawRegion region)
1027 MRealizedFace *rface = from->rface;
1028 MFrame *frame = rface->frame;
1029 MFTInfo *ft_info = rface->rfont->info;
1030 MXftFontInfo *font_info = ft_info->extra_info;
1031 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1032 XftColor *xft_color = (! reverse
1033 ? &((GCInfo *) rface->info)->xft_color_fore
1034 : &((GCInfo *) rface->info)->xft_color_back);
1035 XftFont *xft_font = (gstring->control.anti_alias
1036 && FRAME_DEVICE (frame)->depth > 1
1037 ? font_info->font_aa : font_info->font_no_aa);
1046 XftDrawChange (xft_draw, (Drawable) win);
1047 XftDrawSetClip (xft_draw, (Region) region);
1049 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1050 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1052 if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1053 glyphs[nglyphs++] = g->code;
1057 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1058 last_x, y, glyphs, nglyphs);
1060 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1061 x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1062 last_x = x + g->width;
1066 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1072 /* Functions for the device driver. */
1075 mwin__close_device (MFrame *frame)
1077 M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
1081 mwin__device_get_prop (MFrame *frame, MSymbol key)
1083 MWDevice *device = FRAME_DEVICE (frame);
1085 if (key == Mdisplay)
1086 return (void *) device->display_info->display;
1088 return (void *) ScreenOfDisplay(device->display_info->display,
1089 device->screen_num);
1090 if (key == Mcolormap)
1091 return (void *) device->cmap;
1093 return (void *) device->depth;
1098 mwin__realize_face (MRealizedFace *rface)
1101 MSymbol foreground, background, videomode;
1102 MFaceHLineProp *hline;
1106 if (rface != rface->ascii_rface)
1108 rface->info = rface->ascii_rface->info;
1112 frame = rface->frame;
1113 MSTRUCT_CALLOC (info, MERROR_WIN);
1115 foreground = rface->face.property[MFACE_FOREGROUND];
1116 background = rface->face.property[MFACE_BACKGROUND];
1117 videomode = rface->face.property[MFACE_VIDEOMODE];
1119 videomode = frame->videomode;
1120 if (videomode != Mreverse)
1122 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1123 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1127 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1128 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1131 if (foreground == Mnil)
1132 foreground = frame->foreground;
1133 if (background == Mnil)
1134 background = frame->background;
1135 if (videomode == Mreverse)
1137 MSymbol temp = foreground;
1138 foreground = background;
1141 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1142 FRAME_VISUAL (frame),
1144 MSYMBOL_NAME (foreground),
1145 &info->xft_color_fore))
1147 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1148 FRAME_VISUAL (frame),
1150 MSYMBOL_NAME (background),
1151 &info->xft_color_back))
1155 hline = rface->hline;
1159 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1161 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1168 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1170 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1172 if (box->color_left && box->color_left != box->color_top)
1173 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1175 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1177 if (box->color_bottom && box->color_bottom != box->color_top)
1178 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1180 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1182 if (box->color_right && box->color_right != box->color_bottom)
1183 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1185 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1193 mwin__free_realized_face (MRealizedFace *rface)
1195 if (rface == rface->ascii_rface)
1201 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1203 int x, int y, int width, int height, MDrawRegion region)
1205 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1208 gc = set_region (frame, gc, region);
1210 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1211 x, y, width, height);
1216 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1217 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1218 int reverse, MDrawRegion region)
1220 MRealizedFace *rface = from->rface;
1221 Display *display = FRAME_DISPLAY (rface->frame);
1222 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1228 gc = set_region (rface->frame, gc, region);
1229 for (; from < to; from++)
1231 XDrawRectangle (display, (Window) win, gc,
1232 x, y - gstring->ascent + 1, from->width - 1,
1233 gstring->ascent + gstring->descent - 2);
1240 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1241 MRealizedFace *rface, int reverse,
1242 int x, int y, int width, MDrawRegion region)
1244 enum MFaceHLineType type = rface->hline->type;
1245 GCInfo *info = rface->info;
1246 GC gc = gc = info->gc[GC_HLINE];
1249 y = (type == MFACE_HLINE_BOTTOM
1250 ? y + gstring->text_descent - rface->hline->width
1251 : type == MFACE_HLINE_UNDER
1253 : type == MFACE_HLINE_STRIKE_THROUGH
1254 ? y - ((gstring->ascent + gstring->descent) / 2)
1255 : y - gstring->text_ascent);
1257 gc = set_region (frame, gc, region);
1259 for (i = 0; i < rface->hline->width; i++)
1260 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1261 x, y + i, x + width - 1, y + i);
1266 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1267 MGlyph *g, int x, int y, int width, MDrawRegion region)
1269 Display *display = FRAME_DISPLAY (frame);
1270 MRealizedFace *rface = g->rface;
1271 MFaceBoxProp *box = rface->box;
1272 GCInfo *info = rface->info;
1273 GC gc_top, gc_left, gc_right, gc_btm;
1277 y0 = y - (gstring->text_ascent
1278 + rface->box->inner_vmargin + rface->box->width);
1279 y1 = y + (gstring->text_descent
1280 + rface->box->inner_vmargin + rface->box->width - 1);
1282 gc_top = info->gc[GC_BOX_TOP];
1284 gc_top = set_region (frame, gc_top, region);
1285 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1288 gc_btm = info->gc[GC_BOX_BOTTOM];
1290 if (g->type == GLYPH_BOX)
1294 if (g->left_padding)
1295 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1297 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1299 /* Draw the top side. */
1300 for (i = 0; i < box->width; i++)
1301 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1303 /* Draw the bottom side. */
1304 if (region && gc_btm != gc_top)
1305 gc_btm = set_region (frame, gc_btm, region);
1306 for (i = 0; i < box->width; i++)
1307 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1309 if (g->left_padding > 0)
1311 /* Draw the left side. */
1312 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1316 gc_left = info->gc[GC_BOX_LEFT];
1318 gc_left = set_region (frame, gc_left, region);
1320 for (i = 0; i < rface->box->width; i++)
1321 XDrawLine (display, (Window) win, gc_left,
1322 x0 + i, y0 + i, x0 + i, y1 - i);
1326 /* Draw the right side. */
1327 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1331 gc_right = info->gc[GC_BOX_RIGHT];
1333 gc_right = set_region (frame, gc_right, region);
1335 for (i = 0; i < rface->box->width; i++)
1336 XDrawLine (display, (Window) win, gc_right,
1337 x1 - i, y0 + i, x1 - i, y1 - i);
1342 /* Draw the top side. */
1343 for (i = 0; i < box->width; i++)
1344 XDrawLine (display, (Window) win, gc_top,
1345 x, y0 + i, x + width - 1, y0 + i);
1347 /* Draw the bottom side. */
1348 if (region && gc_btm != gc_top)
1349 gc_btm = set_region (frame, gc_btm, region);
1350 for (i = 0; i < box->width; i++)
1351 XDrawLine (display, (Window) win, gc_btm,
1352 x, y1 - i, x + width - 1, y1 - i);
1359 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1360 int reverse, int x, int y,
1361 int width, int height, int row_bytes, unsigned char *bmp,
1364 Display *display = FRAME_DISPLAY (frame);
1366 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1369 gc = set_region (frame, gc, region);
1371 for (i = 0; i < height; i++, bmp += row_bytes)
1372 for (j = 0; j < width; j++)
1373 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1374 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1379 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1380 int intensity, MDrawPoint *points, int num,
1383 GCInfo *info = rface->info;
1386 if (! (gc = info->gc[intensity]))
1387 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1390 gc = set_region (frame, gc, region);
1392 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1393 (XPoint *) points, num, CoordModeOrigin);
1398 mwin__region_from_rect (MDrawMetric *rect)
1400 MDrawRegion region1 = XCreateRegion ();
1401 MDrawRegion region2 = XCreateRegion ();
1406 xrect.width = rect->width;
1407 xrect.height = rect->height;
1408 XUnionRectWithRegion (&xrect, region1, region2);
1409 XDestroyRegion (region1);
1414 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1416 MDrawRegion region1 = XCreateRegion ();
1421 xrect.width = rect->width;
1422 xrect.height = rect->height;
1424 XUnionRegion (region, region, region1);
1425 XUnionRectWithRegion (&xrect, region1, region);
1426 XDestroyRegion (region1);
1430 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1432 MDrawRegion region = XCreateRegion ();
1434 XUnionRegion (region1, region1, region);
1435 XIntersectRegion (region, region2, region1);
1436 XDestroyRegion (region);
1440 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1442 MDrawRegion region1 = XCreateRegion ();
1447 xrect.width = rect->width;
1448 xrect.height = rect->height;
1449 XUnionRectWithRegion (&xrect, region1, region);
1450 XDestroyRegion (region1);
1454 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1458 XClipBox (region, &xrect);
1461 rect->width = xrect.width;
1462 rect->height = xrect.height;
1466 mwin__free_region (MDrawRegion region)
1468 XDestroyRegion (region);
1472 mwin__dump_region (MDrawRegion region)
1475 XClipBox (region, &rect);
1476 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1481 mwin__create_window (MFrame *frame, MDrawWindow parent)
1483 Display *display = FRAME_DISPLAY (frame);
1485 XWMHints wm_hints = { InputHint, False };
1486 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1487 XSetWindowAttributes set_attrs;
1490 GCInfo *info = frame->rface->info;
1493 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1494 mask = GCForeground;
1495 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1496 set_attrs.background_pixel = values.foreground;
1497 set_attrs.backing_store = Always;
1498 set_attrs.override_redirect = True;
1499 set_attrs.save_under = True;
1500 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1501 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1502 CopyFromParent, InputOutput, CopyFromParent,
1504 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1505 NULL, &wm_hints, &class_hints);
1506 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1507 return (MDrawWindow) win;
1511 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1513 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1518 mwin__event_window (void *event)
1520 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1524 mwin__print_event (void *arg, char *win_name)
1527 XEvent *event = (XEvent *) arg;
1529 switch (event->xany.type)
1531 case 2: event_name = "KeyPress"; break;
1532 case 3: event_name = "KeyRelease"; break;
1533 case 4: event_name = "ButtonPress"; break;
1534 case 5: event_name = "ButtonRelease"; break;
1535 case 6: event_name = "MotionNotify"; break;
1536 case 7: event_name = "EnterNotify"; break;
1537 case 8: event_name = "LeaveNotify"; break;
1538 case 9: event_name = "FocusIn"; break;
1539 case 10: event_name = "FocusOut"; break;
1540 case 11: event_name = "KeymapNotify"; break;
1541 case 12: event_name = "Expose"; break;
1542 case 13: event_name = "GraphicsExpose"; break;
1543 case 14: event_name = "NoExpose"; break;
1544 case 15: event_name = "VisibilityNotify"; break;
1545 case 16: event_name = "CreateNotify"; break;
1546 case 17: event_name = "DestroyNotify"; break;
1547 case 18: event_name = "UnmapNotify"; break;
1548 case 19: event_name = "MapNotify"; break;
1549 case 20: event_name = "MapRequest"; break;
1550 case 21: event_name = "ReparentNotify"; break;
1551 case 22: event_name = "ConfigureNotify"; break;
1552 case 23: event_name = "ConfigureRequest"; break;
1553 case 24: event_name = "GravityNotify"; break;
1554 case 25: event_name = "ResizeRequest"; break;
1555 case 26: event_name = "CirculateNotify"; break;
1556 case 27: event_name = "CirculateRequest"; break;
1557 case 28: event_name = "PropertyNotify"; break;
1558 case 29: event_name = "SelectionClear"; break;
1559 case 30: event_name = "SelectionRequest"; break;
1560 case 31: event_name = "SelectionNotify"; break;
1561 case 32: event_name = "ColormapNotify"; break;
1562 case 33: event_name = "ClientMessage"; break;
1563 case 34: event_name = "MappingNotify"; break;
1564 default: event_name = "unknown";
1567 fprintf (stderr, "%s: %s\n", win_name, event_name);
1572 mwin__map_window (MFrame *frame, MDrawWindow win)
1574 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1578 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1580 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1584 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1585 MDrawMetric *geometry)
1587 Display *display = FRAME_DISPLAY (frame);
1588 XWindowAttributes attr;
1589 Window parent = (Window) parent_win, root;
1591 XGetWindowAttributes (display, (Window) win, &attr);
1592 geometry->x = attr.x + attr.border_width;
1593 geometry->y = attr.y + attr.border_width;
1594 geometry->width = attr.width;
1595 geometry->height = attr.height;
1598 parent = RootWindow (display, FRAME_SCREEN (frame));
1601 Window this_parent, *children;
1604 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1607 if (this_parent == parent || this_parent == root)
1609 win = (MDrawWindow) this_parent;
1610 XGetWindowAttributes (display, (Window) win, &attr);
1611 geometry->x += attr.x + attr.border_width;
1612 geometry->y += attr.y + attr.border_width;
1617 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1618 MDrawMetric *current, MDrawMetric *new)
1620 Display *display = FRAME_DISPLAY (frame);
1621 unsigned int mask = 0;
1622 XWindowChanges values;
1624 if (current->width != new->width)
1627 if (new->width <= 0)
1629 values.width = current->width = new->width;
1631 if (current->height != new->height)
1634 if (new->height <= 0)
1636 values.height = current->height = new->height;
1638 if (current->x != new->x)
1641 values.x = current->x = new->x;
1643 if (current->y != new->y)
1646 current->y = new->y;
1647 values.y = current->y = new->y;
1650 XConfigureWindow (display, (Window) win, mask, &values);
1651 XClearWindow (display, (Window) win);
1655 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1657 XEvent *event = (XEvent *) arg;
1658 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1665 if (event->xany.type != KeyPress
1666 /* && event->xany.type != KeyRelease */
1669 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1676 if (c < XK_space || c > XK_asciitilde)
1678 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1679 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1680 if (((XKeyEvent *) event)->state & ControlMask)
1682 if (c >= 'a' && c <= 'z')
1684 if (c >= ' ' && c < 127)
1685 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1687 key = minput__char_to_key (c);
1689 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1693 char *str = XKeysymToString (keysym);
1697 key = msymbol (str);
1698 if (((XKeyEvent *) event)->state & ShiftMask)
1699 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1700 if (((XKeyEvent *) event)->state & ControlMask)
1701 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1703 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1704 *modifiers |= MINPUT_KEY_META_MODIFIER;
1705 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1706 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1707 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1708 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1709 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1710 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1717 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1719 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1721 Display *display = FRAME_DISPLAY (frame);
1722 GCInfo *info = rface->info;
1725 for (i = 0; i <= GC_INVERSE; i++)
1727 XGetGCValues (display, info->gc[i], valuemask, &values);
1728 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1729 values.foreground, values.background);
1730 fprintf (stderr, "\n");
1734 static MDeviceDriver x_driver =
1737 mwin__device_get_prop,
1739 mwin__free_realized_face,
1741 mwin__draw_empty_boxes,
1745 mwin__region_from_rect,
1746 mwin__union_rect_with_region,
1747 mwin__intersect_region,
1748 mwin__region_add_rect,
1749 mwin__region_to_rect,
1752 mwin__create_window,
1753 mwin__destroy_window,
1756 mwin__window_geometry,
1757 mwin__adjust_window,
1761 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1766 M_iso8859_1 = msymbol ("iso8859-1");
1767 M_iso10646_1 = msymbol ("iso10646-1");
1769 display_info_list = mplist ();
1770 device_list = mplist ();
1773 xft_driver.select = mfont__ft_driver.select;
1774 xft_driver.encode_char = mfont__ft_driver.encode_char;
1777 Mxim = msymbol ("xim");
1778 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1786 M17N_OBJECT_UNREF (display_info_list);
1787 M17N_OBJECT_UNREF (device_list);
1791 /** Return an MWDevice object corresponding to a display specified in
1794 It searches device_list for a device matching the display. If
1795 found, return the found object. Otherwise, return a newly created
1799 device_open (MFrame *frame, MPlist *param)
1801 Display *display = NULL;
1802 Screen *screen = NULL;
1804 Drawable drawable = 0;
1805 Widget widget = NULL;
1807 int auto_display = 0;
1808 MDisplayInfo *disp_info = NULL;
1809 MWDevice *device = NULL;
1811 XWindowAttributes attr;
1817 for (plist = param; (key = mplist_key (plist)) != Mnil;
1818 plist = mplist_next (plist))
1820 if (key == Mdisplay)
1821 display = (Display *) mplist_value (plist);
1822 else if (key == Mscreen)
1823 screen = mplist_value (plist);
1824 else if (key == Mdrawable)
1825 drawable = (Drawable) mplist_value (plist);
1826 else if (key == Mdepth)
1827 depth = (unsigned) mplist_value (plist);
1828 else if (key == Mwidget)
1829 widget = (Widget) mplist_value (plist);
1830 else if (key == Mcolormap)
1831 cmap = (Colormap) mplist_value (plist);
1836 display = XtDisplay (widget);
1837 screen_num = XScreenNumberOfScreen (XtScreen (widget));
1838 depth = DefaultDepth (display, screen_num);
1844 unsigned width, height, border_width;
1847 MERROR (MERROR_WIN, -1);
1848 XGetGeometry (display, drawable, &root_window,
1849 &x, &y, &width, &height, &border_width, &depth);
1850 XGetWindowAttributes (display, root_window, &attr);
1851 screen_num = XScreenNumberOfScreen (attr.screen);
1856 display = DisplayOfScreen (screen);
1861 display = XOpenDisplay (NULL);
1863 MERROR (MERROR_WIN, -1);
1866 screen = DefaultScreenOfDisplay (display);
1868 screen_num = XScreenNumberOfScreen (screen);
1870 depth = DefaultDepth (display, screen_num);
1874 cmap = DefaultColormap (display, screen_num);
1876 for (plist = display_info_list; mplist_key (plist) != Mnil;
1877 plist = mplist_next (plist))
1879 disp_info = (MDisplayInfo *) mplist_value (plist);
1880 if (disp_info->display == display)
1884 if (mplist_key (plist) != Mnil)
1885 M17N_OBJECT_REF (disp_info);
1888 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
1889 disp_info->display = display;
1890 disp_info->auto_display = auto_display;
1891 disp_info->font_list = mplist ();
1892 disp_info->base_font_list = mplist ();
1893 find_modifier_bits (disp_info);
1894 mplist_add (display_info_list, Mt, disp_info);
1897 for (plist = device_list; mplist_key (plist) != Mnil;
1898 plist = mplist_next (plist))
1900 device = (MWDevice *) mplist_value (plist);
1901 if (device->display_info == disp_info
1902 && device->depth == depth
1903 && device->cmap == cmap)
1907 if (mplist_key (plist) != Mnil)
1908 M17N_OBJECT_REF (device);
1911 unsigned long valuemask = GCForeground;
1914 M17N_OBJECT (device, free_device, MERROR_WIN);
1915 device->display_info = disp_info;
1916 device->screen_num = screen_num;
1917 /* A drawable on which to create GCs. */
1918 device->drawable = XCreatePixmap (display,
1919 RootWindow (display, screen_num),
1921 device->depth = depth;
1922 device->cmap = cmap;
1923 device->realized_face_list = mplist ();
1924 device->realized_font_list = mplist ();
1925 device->realized_fontset_list = mplist ();
1926 device->gc_list = mplist ();
1927 values.foreground = BlackPixel (display, screen_num);
1928 device->scratch_gc = XCreateGC (display, device->drawable,
1929 valuemask, &values);
1931 device->xft_draw = XftDrawCreate (display, device->drawable,
1932 DefaultVisual (display, screen_num),
1937 frame->device = device;
1938 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
1939 frame->driver = &x_driver;
1940 frame->font_driver_list = mplist ();
1941 mplist_add (frame->font_driver_list, Mx, &xfont_driver);
1943 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
1945 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
1947 frame->realized_font_list = device->realized_font_list;
1948 frame->realized_face_list = device->realized_face_list;
1949 frame->realized_fontset_list = device->realized_fontset_list;
1953 XtResource resources[] = {
1954 { XtNfont, XtCFont, XtRString, sizeof (String),
1955 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
1956 { XtNforeground, XtCForeground, XtRString, sizeof (String),
1957 XtOffset (AppDataPtr, foreground), XtRString, "black" },
1958 { XtNbackground, XtCBackground, XtRString, sizeof (String),
1959 XtOffset (AppDataPtr, background), XtRString, "white" },
1960 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
1961 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
1964 XtGetApplicationResources (widget, &app_data,
1965 resources, XtNumber (resources), NULL, 0);
1966 frame->foreground = msymbol (app_data.foreground);
1967 frame->background = msymbol (app_data.background);
1968 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
1972 app_data.font = DEFAULT_FONT;
1973 frame->foreground = msymbol ("black");
1974 frame->background = msymbol ("white");
1975 frame->videomode = Mnormal;
1980 char **names = XListFonts (display, app_data.font, 1, &nfonts);
1984 if (! (frame->font = mfont_parse_name (names[0], Mx)))
1986 /* The font name does not conform to XLFD. Try to open the
1987 font and get XA_FONT property. */
1988 XFontStruct *xfont = XLoadQueryFont (display, names[0]);
1993 unsigned long value;
1996 if (XGetFontProperty (xfont, XA_FONT, &value)
1997 && (name = ((char *)
1998 XGetAtomName (display, (Atom) value))))
2000 if ((frame->font = mfont_parse_name (name, Mx)))
2003 XFreeFont (display, xfont);
2006 XFreeFontNames (names);
2009 frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
2012 face = mface_from_font (frame->font);
2013 face->property[MFACE_FONTSET] = mfontset (NULL);
2014 face->property[MFACE_FOREGROUND] = frame->foreground;
2015 face->property[MFACE_BACKGROUND] = frame->background;
2016 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2017 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2018 face->property[MFACE_VIDEOMODE] = frame->videomode;
2019 mface_put_prop (face, Mhook_func,
2020 mface_get_prop (mface__default, Mhook_func));
2021 face->property[MFACE_RATIO] = (void *) 100;
2022 mplist_push (param, Mface, face);
2023 M17N_OBJECT_UNREF (face);
2025 #ifdef X_SET_ERROR_HANDLER
2026 XSetErrorHandler (x_error_handler);
2027 XSetIOErrorHandler (x_io_error_handler);
2035 /* XIM (X Input Method) handler */
2037 typedef struct MInputXIMMethodInfo
2043 } MInputXIMMethodInfo;
2045 typedef struct MInputXIMContextInfo
2049 MConverter *converter;
2050 } MInputXIMContextInfo;
2053 xim_open_im (MInputMethod *im)
2055 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2056 MLocale *saved, *this;
2057 char *save_modifier_list;
2059 MInputXIMMethodInfo *im_info;
2061 saved = mlocale_set (LC_CTYPE, NULL);
2062 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2064 /* The specified locale is not supported. */
2065 MERROR (MERROR_LOCALE, -1);
2066 if (mlocale_get_prop (this, Mcoding) == Mnil)
2068 /* Unable to decode the output of XIM. */
2069 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2070 MERROR (MERROR_LOCALE, -1);
2073 if (arg->modifier_list)
2074 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2076 save_modifier_list = XSetLocaleModifiers ("");
2077 if (! save_modifier_list)
2079 /* The specified locale is not supported by X. */
2080 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2081 MERROR (MERROR_LOCALE, -1);
2084 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2087 /* No input method is available in the current locale. */
2088 XSetLocaleModifiers (save_modifier_list);
2089 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2090 MERROR (MERROR_WIN, -1);
2093 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2094 im_info->display = arg->display;
2096 im_info->language = mlocale_get_prop (this, Mlanguage);
2097 im_info->coding = mlocale_get_prop (this, Mcoding);
2100 XSetLocaleModifiers (save_modifier_list);
2101 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2107 xim_close_im (MInputMethod *im)
2109 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2111 XCloseIM (im_info->xim);
2116 xim_create_ic (MInputContext *ic)
2118 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2119 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2120 MInputXIMContextInfo *ic_info;
2123 if (! arg->input_style)
2125 /* By default, use Root style. */
2126 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2127 arg->preedit_attrs = NULL;
2128 arg->status_attrs = NULL;
2131 if (! arg->preedit_attrs && ! arg->status_attrs)
2132 xic = XCreateIC (im_info->xim,
2133 XNInputStyle, arg->input_style,
2134 XNClientWindow, arg->client_win,
2135 XNFocusWindow, arg->focus_win,
2137 else if (arg->preedit_attrs && ! arg->status_attrs)
2138 xic = XCreateIC (im_info->xim,
2139 XNInputStyle, arg->input_style,
2140 XNClientWindow, arg->client_win,
2141 XNFocusWindow, arg->focus_win,
2142 XNPreeditAttributes, arg->preedit_attrs,
2144 else if (! arg->preedit_attrs && arg->status_attrs)
2145 xic = XCreateIC (im_info->xim,
2146 XNInputStyle, arg->input_style,
2147 XNClientWindow, arg->client_win,
2148 XNFocusWindow, arg->focus_win,
2149 XNStatusAttributes, arg->status_attrs,
2152 xic = XCreateIC (im_info->xim,
2153 XNInputStyle, arg->input_style,
2154 XNClientWindow, arg->client_win,
2155 XNFocusWindow, arg->focus_win,
2156 XNPreeditAttributes, arg->preedit_attrs,
2157 XNStatusAttributes, arg->status_attrs,
2160 MERROR (MERROR_WIN, -1);
2162 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2164 ic_info->win = arg->focus_win;
2165 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2171 xim_destroy_ic (MInputContext *ic)
2173 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2175 XDestroyIC (ic_info->xic);
2176 mconv_free_converter (ic_info->converter);
2182 xim_filter (MInputContext *ic, MSymbol key, void *event)
2184 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2186 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2191 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2193 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2194 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2195 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2201 buf = (char *) alloca (512);
2202 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2203 if (status == XBufferOverflow)
2205 buf = (char *) alloca (len);
2206 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2209 mtext_reset (ic->produced);
2213 mconv_reset_converter (ic_info->converter);
2214 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2215 mconv_decode (ic_info->converter, ic->produced);
2216 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2217 Mlanguage, (void *) im_info->language);
2218 mtext_cpy (mt, ic->produced);
2219 mtext_reset (ic->produced);
2225 #ifdef X_SET_ERROR_HANDLER
2227 x_error_handler (Display *display, XErrorEvent *error)
2234 x_io_error_handler (Display *display)
2244 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2248 /*** @addtogroup m17nInputMethodWin */
2253 @brief Input method driver for XIM.
2255 The driver #minput_xim_driver is for the foreign input method of
2256 name #Mxim. It uses XIM (X Input Methods) as a background input
2259 As the symbol #Mxim has property #Minput_driver whose value is
2260 a pointer to this driver, the input method of language #Mnil
2261 and name #Mxim uses this driver.
2263 Therefore, for such input methods, the driver dependent arguments
2264 to the functions whose name begin with minput_ must be as follows.
2266 The argument $ARG of the function minput_open_im () must be a
2267 pointer to the structure #MInputXIMArgIM. See the documentation
2268 of #MInputXIMArgIM for more details.
2270 The argument $ARG of the function minput_create_ic () must be a
2271 pointer to the structure #MInputXIMArgIC. See the documentation
2272 of #MInputXIMArgIC for more details.
2274 The argument $ARG of the function minput_filter () must be a
2275 pointer to the structure @c XEvent. The argument $KEY is ignored.
2277 The argument $ARG of the function minput_lookup () must be the
2278 same one as that of the function minput_filter (). The argument
2282 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2284 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
2285 ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
2288 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2289 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
2290 ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2292 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
2293 ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2295 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM ¤Ø¤Î¥Ý
2296 ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
2299 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC ¤Ø¤Î
2300 ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
2303 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2304 ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2306 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2307 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2310 MInputDriver minput_xim_driver =
2311 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2312 xim_filter, xim_lookup, NULL };