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 /* Nth bit tells the existence of a font of size (N+1).
62 core.property[MFONT_SIZE] holds the smallest size. */
64 /* If sizes is not 0, smallest and largest sizes. */
65 unsigned short smallest, largest;
68 /* S must satisfy the condition (S > 0 && S <= 32). */
69 #define SET_SIZE(sizes, s) ((sizes) |= (1 << ((s) - 1)))
70 #define HAVE_SIZE(sizes, s) ((sizes) & (1 << ((s) - 1)))
79 /* Common header for the m17n object. */
84 /* If nonzero, <display> is opened by this library. Thus it should
85 be closed on freeing this structure. */
88 /** List of available X-core fonts on the display. Keys are
89 registries and values are plists whose keys are families and
90 values are pointers to MXFontList. */
93 /** List of available X-core fonts on the display. Keys are
94 families and values are pointers to MFont. For each MFont, only
95 these properties are important; FOUNDRY, FAMILY, REGISTRY. */
96 MPlist *base_font_list;
98 /** Nonzero means that <font_list> already contains all available
99 fonts on the display. */
100 int all_fonts_scaned;
102 /** Modifier bit masks of the display. */
109 /* Anchor of the chain of MDisplayInfo objects. */
110 static MPlist *display_info_list;
113 /* Color value and the corresponding GC. */
116 unsigned int rgb; /* (red << 16) | (green << 8) | blue */
123 GC_NORMAL = GC_INVERSE + 7,
136 /* The first 8 elements are indexed by an intensity for
137 anti-aliasing. The 2nd to 7th are created on demand. */
140 XftColor xft_color_fore, xft_color_back;
146 /* Common header for the m17n object. */
149 MDisplayInfo *display_info;
165 /** List of pointers to realized faces on the frame. */
166 MPlist *realized_face_list;
168 /* List of information about each font. Keys are font registries,
169 values are (MFontInfo *). */
170 MPlist *realized_font_list;
172 /** List of pointers to realized fontsets on the frame. */
173 MPlist *realized_fontset_list;
175 /** List of XColors vs GCs on the frame. */
179 static MPlist *device_list;
181 static MSymbol M_iso8859_1, M_iso10646_1;
183 #define FRAME_DEVICE(frame) ((MWDevice *) (frame)->device)
184 #define FRAME_DISPLAY(frame) (FRAME_DEVICE (frame)->display_info->display)
185 #define FRAME_SCREEN(frame) (FRAME_DEVICE (frame)->screen_num)
186 #define FRAME_CMAP(frame) (FRAME_DEVICE (frame)->cmap)
187 #define FRAME_VISUAL(frame) DefaultVisual (FRAME_DISPLAY (frame), \
188 FRAME_SCREEN (frame))
190 #define DEFAULT_FONT "-misc-fixed-medium-r-normal--*-120-*-*-*-*-iso8859-1"
191 #define FALLBACK_FONT "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1"
198 Boolean reverse_video;
199 } AppData, *AppDataPtr;
202 free_display_info (void *object)
204 MDisplayInfo *disp_info = (MDisplayInfo *) object;
207 MPLIST_DO (plist, disp_info->font_list)
209 MPLIST_DO (p, MPLIST_VAL (plist))
210 free (MPLIST_VAL (p));
211 M17N_OBJECT_UNREF (MPLIST_VAL (plist));
213 M17N_OBJECT_UNREF (disp_info->font_list);
214 MPLIST_DO (plist, disp_info->base_font_list)
215 free (MPLIST_VAL (plist));
216 M17N_OBJECT_UNREF (disp_info->base_font_list);
218 if (disp_info->auto_display)
219 XCloseDisplay (disp_info->display);
225 free_device (void *object)
227 MWDevice *device = object;
230 for (plist = device->realized_fontset_list;
231 mplist_key (plist) != Mnil; plist = mplist_next (plist))
232 mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist));
233 M17N_OBJECT_UNREF (device->realized_fontset_list);
235 MPLIST_DO (plist, device->realized_font_list)
236 mfont__free_realized ((MRealizedFont *) MPLIST_VAL (plist));
237 M17N_OBJECT_UNREF (device->realized_font_list);
239 MPLIST_DO (plist, device->realized_face_list)
241 MRealizedFace *rface = MPLIST_VAL (plist);
244 mface__free_realized (rface);
246 M17N_OBJECT_UNREF (device->realized_face_list);
248 MPLIST_DO (plist, device->gc_list)
250 XFreeGC (device->display_info->display,
251 ((RGB_GC *) MPLIST_VAL (plist))->gc);
252 free (MPLIST_VAL (plist));
254 M17N_OBJECT_UNREF (device->gc_list);
255 XFreeGC (device->display_info->display, device->scratch_gc);
258 XftDrawDestroy (device->xft_draw);
261 XFreePixmap (device->display_info->display, device->drawable);
262 M17N_OBJECT_UNREF (device->display_info);
268 find_modifier_bits (MDisplayInfo *disp_info)
270 Display *display = disp_info->display;
271 XModifierKeymap *mods;
272 KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L);
273 KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R);
274 KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L);
275 KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R);
276 KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
277 KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
278 KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
279 KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
282 mods = XGetModifierMapping (display);
283 /* We skip the first three sets for Shift, Lock, and Control. The
284 remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
285 for (i = 3; i < 8; i++)
286 for (j = 0; j < mods->max_keypermod; j++)
288 KeyCode code = mods->modifiermap[i * mods->max_keypermod + j];
292 if (code == meta_l || code == meta_r)
293 disp_info->meta_mask |= (1 << i);
294 else if (code == alt_l || code == alt_r)
295 disp_info->alt_mask |= (1 << i);
296 else if (code == super_l || code == super_r)
297 disp_info->super_mask |= (1 << i);
298 else if (code == hyper_l || code == hyper_r)
299 disp_info->hyper_mask |= (1 << i);
302 /* If meta keys are not in any modifier, use alt keys as meta
304 if (! disp_info->meta_mask)
306 disp_info->meta_mask = disp_info->alt_mask;
307 disp_info->alt_mask = 0;
309 /* If both meta and alt are assigned to the same modifier, give meta
311 if (disp_info->meta_mask & disp_info->alt_mask)
312 disp_info->alt_mask &= ~disp_info->meta_mask;
314 XFreeModifiermap (mods);
318 get_rgb_gc (MWDevice *device, XColor *xcolor)
320 int rgb = (((xcolor->red >> 8) << 16) | ((xcolor->green >> 8) << 8)
321 | (xcolor->blue >> 8));
324 unsigned long valuemask = GCForeground;
327 MPLIST_DO (plist, device->gc_list)
329 rgb_gc = MPLIST_VAL (plist);
331 if (rgb_gc->rgb == rgb)
333 if (rgb_gc->rgb > rgb)
337 if (! XAllocColor (device->display_info->display, device->cmap, xcolor))
340 rgb_gc = malloc (sizeof (RGB_GC));
342 values.foreground = xcolor->pixel;
343 rgb_gc->gc = XCreateGC (device->display_info->display,
344 device->drawable, valuemask, &values);
345 mplist_push (plist, Mt, rgb_gc);
350 get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret)
352 MWDevice *device = FRAME_DEVICE (frame);
360 color = for_foreground ? frame->foreground : frame->background;
362 if (! XParseColor (FRAME_DISPLAY (frame), device->cmap,
363 msymbol_name (color), &xcolor))
365 rgb_gc = get_rgb_gc (device, &xcolor);
369 *rgb_ret = rgb_gc->rgb;
374 GCInfo *info = frame->rface->info;
379 rgb = info->rgb_fore, gc = info->gc[GC_NORMAL];
381 rgb = info->rgb_back, gc = info->gc[GC_INVERSE];
389 get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity)
391 int rgb_fore, rgb_back;
396 if (info->gc[intensity])
397 return info->gc[intensity];
399 rgb_fore = info->rgb_fore, rgb_back = info->rgb_back;
400 xcolor.red = ((((rgb_fore & 0xFF0000) >> 16) * intensity
401 + ((rgb_back & 0xFF0000) >> 16) * (7 - intensity)) / 7) << 8;
402 xcolor.green = ((((rgb_fore & 0xFF00) >> 8) * intensity
403 + ((rgb_back & 0xFF00) >> 8) * (7 - intensity)) / 7) << 8;
404 xcolor.blue = (((rgb_fore & 0xFF) * intensity
405 + (rgb_back & 0xFF) * (7 - intensity)) / 7) << 8;
406 rgb_gc = get_rgb_gc (device, &xcolor);
410 gc =get_gc_for_anti_alias (device, info,
411 intensity < 4 ? intensity - 1 : intensity + 1);
412 return (info->gc[intensity] = gc);
416 set_region (MFrame *frame, GC gc, MDrawRegion region)
418 unsigned long valuemask = GCForeground;
420 XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
421 FRAME_DEVICE (frame)->scratch_gc);
422 XSetRegion (FRAME_DISPLAY (frame), FRAME_DEVICE (frame)->scratch_gc, region);
423 return FRAME_DEVICE (frame)->scratch_gc;
427 /** X font handler */
429 static MRealizedFont *xfont_select (MFrame *, MFont *, MFont *, int);
430 static int xfont_open (MRealizedFont *);
431 static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int);
432 static unsigned xfont_encode_char (MRealizedFont *, unsigned);
433 static void xfont_render (MDrawWindow, int, int, MGlyphString *,
434 MGlyph *, MGlyph *, int, MDrawRegion);
435 static int xfont_list (MFrame *frame, MPlist *plist,
436 MFont *font, MSymbol language, int maxnum);
439 static MFontDriver xfont_driver =
440 { xfont_select, xfont_open,
441 xfont_find_metric, xfont_encode_char, xfont_render, xfont_list };
444 font_compare (const void *p1, const void *p2)
446 return strcmp (*(char **) p1, *(char **) p2);
450 xfont_registry_list (MFrame *frame, MSymbol registry)
452 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
453 MPlist *font_list = disp_info->font_list;
454 MPlist *base_font_list = disp_info->base_font_list;
457 char **font_names, **names;
463 plist = mplist_get (font_list, registry);
467 mplist_add (font_list, registry, plist);
468 sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", msymbol_name (registry));
469 font_names = XListFonts (disp_info->display, pattern, 0x8000, &nfonts);
472 names = alloca (sizeof (char *) * nfonts);
473 memcpy (names, font_names, sizeof (char *) * nfonts);
474 qsort (names, nfonts, sizeof (char *), font_compare);
475 for (i = 0, p = NULL; i < nfonts; i++)
476 if (mfont__parse_name_into_font (names[i], Mx, (MFont *) &font) == 0
477 && (font.core.property[MFONT_SIZE] > 0
478 || font.core.property[MFONT_RESY] == 0))
480 MSymbol family = FONT_PROPERTY ((MFont *) &font, MFONT_FAMILY);
481 MXFontList *xfont_table;
484 int size, smallest, largest;
486 unsigned int size_bits = 0;
491 if (p && MPLIST_KEY (p) != family)
492 p = mplist_find_by_key (plist, family);
494 xfont_table = MPLIST_VAL (p);
498 MSTRUCT_MALLOC (xfont_table, MERROR_WIN);
499 MLIST_INIT1 (xfont_table, fonts, 4);
500 mplist_push (p, family, xfont_table);
503 /* Calculate how many bytes to compare to detect fonts of the
505 for (base_end = names[i], fields = 0; *base_end; base_end++)
507 && ++fields == 7 /* PIXEL_SIZE */)
509 base_len = base_end - names[i] + 1;
511 size = font.core.property[MFONT_SIZE] / 10;
512 have_scalable = size == 0;
513 sizes[sizes_idx++] = size;
514 for (j = i + 1; j < nfonts && ! strncmp (names[i], names[j], base_len);
516 if (mfont__parse_name_into_font (names[j], Mx, (MFont *) &font) == 0
517 && (font.core.property[MFONT_SIZE] > 0
518 || font.core.property[MFONT_RESY] == 0))
522 size = font.core.property[MFONT_SIZE] / 10;
524 have_scalable = size == 0;
525 for (k = 0; k < sizes_idx && sizes[k] != size; k++);
526 if (k == sizes_idx && sizes_idx < 256)
527 sizes[sizes_idx++] = size;
530 for (j = 0, smallest = 0; j < sizes_idx; j++)
538 smallest = largest = size;
539 else if (size < smallest)
541 else if (size > largest)
543 SET_SIZE (size_bits, size);
548 font.core.property[MFONT_SIZE] = size * 10;
550 MLIST_APPEND1 (xfont_table, fonts, font, MERROR_WIN);
554 if (size_bits || have_scalable == 1)
556 font.sizes = size_bits;
557 font.smallest = smallest;
558 font.largest = largest;
559 font.core.property[MFONT_SIZE] = have_scalable ? 0 : smallest * 10;
560 MLIST_APPEND1 (xfont_table, fonts, font, MERROR_WIN);
563 || (font.core.property[MFONT_FOUNDRY]
564 != bfont->property[MFONT_FOUNDRY])
565 || (font.core.property[MFONT_FAMILY]
566 != bfont->property[MFONT_FAMILY]))
568 MSTRUCT_MALLOC (bfont, MERROR_WIN);
570 for (j = MFONT_WEIGHT; j <= MFONT_ADSTYLE; j++)
571 bfont->property[j] = 0;
572 bfont->property[MFONT_SIZE] = bfont->property[MFONT_RESY] = 0;
573 mplist_push (base_font_list, family, bfont);
576 XFreeFontNames (font_names);
581 xfont_list_all (MFrame *frame)
583 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
584 MPlist *font_encoding_list, *p;
586 if (disp_info->all_fonts_scaned)
588 disp_info->all_fonts_scaned = 1;
589 font_encoding_list = mfont__encoding_list ();
590 if (! font_encoding_list)
592 MPLIST_DO (p, font_encoding_list)
593 xfont_registry_list (frame, MPLIST_KEY (p));
604 /* The X font driver function SELECT. */
606 static MRealizedFont *
607 xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
609 MSymbol family = FONT_PROPERTY (spec, MFONT_FAMILY);
610 MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
611 int requested_size = request->property[MFONT_SIZE] / 10;
612 MRealizedFont *rfont;
616 int best_size, best_score, score;
619 || ! strchr (MSYMBOL_NAME (registry), '-'))
622 plist = xfont_registry_list (frame, registry);
623 if (MPLIST_TAIL_P (plist))
625 best_score = -1, best_font = NULL;
626 MPLIST_DO (plist, plist)
628 if (family == Mnil || family == MPLIST_KEY (plist))
630 MXFontList *xfont_table = MPLIST_VAL (plist);
632 for (i = 0; i < xfont_table->used; i++)
634 MXFont *xfont = xfont_table->fonts + i;
635 MFont *font = (MFont *) xfont;
636 unsigned int sizes = xfont->sizes;
637 int orig_size = font->property[MFONT_SIZE];
641 size = orig_size / 10;
642 else if (requested_size < xfont->smallest)
643 size = orig_size == 0 ? 0 : xfont->smallest;
644 else if (requested_size > xfont->largest)
645 size = orig_size == 0 ? 0 : xfont->largest;
646 else if (HAVE_SIZE (sizes, requested_size))
647 size = requested_size;
648 else if (orig_size == 0)
652 for (size = requested_size - 1;
653 size > xfont->smallest && ! HAVE_SIZE (sizes, size);
658 for (s = requested_size;
659 s < xfont->largest && ! HAVE_SIZE (sizes, s);
661 if (s - requested_size < requested_size - size)
665 font->property[MFONT_SIZE] = size * 10;
666 score = mfont__score (font, spec, request, limited_size);
667 font->property[MFONT_SIZE] = orig_size;
668 if (score >= 0 && (best_score < 0 || score < best_score))
670 best_size = size * 10;
672 best_font = (MFont *) (xfont_table->fonts + i);
684 MSTRUCT_CALLOC (rfont, MERROR_WIN);
685 rfont->frame = frame;
687 rfont->request = *request;
688 rfont->font = *best_font;
690 rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE];
692 rfont->font.property[MFONT_SIZE] = best_size;
693 rfont->score = best_score;
698 /* The X font driver function CLOSE. */
701 close_xfont (void *object)
703 MXFontInfo *xfont_info = object;
705 XFreeFont (xfont_info->display, xfont_info->xfont);
710 /* The X font driver function OPEN. */
713 xfont_open (MRealizedFont *rfont)
716 MXFontInfo *xfont_info;
717 MFrame *frame = rfont->frame;
718 int mdebug_mask = MDEBUG_FONT;
720 /* This never fail to generate a valid fontname because open_spec
721 should correspond to a font available on the system. */
722 name = mfont_unparse_name (&rfont->font, Mx);
723 M17N_OBJECT (xfont_info, close_xfont, MERROR_WIN);
724 xfont_info->display = FRAME_DISPLAY (frame);
725 xfont_info->xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
726 if (! xfont_info->xfont)
730 MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
734 rfont->info = xfont_info;
735 MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
738 rfont->ascent = xfont_info->xfont->ascent;
739 rfont->descent = xfont_info->xfont->descent;
741 rfont->fontp = xfont_info->xfont;
746 /* The X font driver function FIND_METRIC. */
749 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
752 MXFontInfo *xfont_info = rfont->info;
753 XFontStruct *xfont = xfont_info->xfont;
754 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
756 for (; g != gend; g++)
758 if (g->code == MCHAR_INVALID_CODE)
760 g->lbearing = xfont->max_bounds.lbearing;
761 g->rbearing = xfont->max_bounds.rbearing;
762 g->width = xfont->max_bounds.width;
763 g->ascent = xfont->ascent;
764 g->descent = xfont->descent;
768 int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
769 XCharStruct *pcm = NULL;
771 if (xfont->per_char != NULL)
773 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
776 && byte2 >= xfont->min_char_or_byte2
777 && byte2 <= xfont->max_char_or_byte2)
778 pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
782 if (byte1 >= xfont->min_byte1
783 && byte1 <= xfont->max_byte1
784 && byte2 >= xfont->min_char_or_byte2
785 && byte2 <= xfont->max_char_or_byte2)
787 pcm = (xfont->per_char
788 + ((xfont->max_char_or_byte2
789 - xfont->min_char_or_byte2 + 1)
790 * (byte1 - xfont->min_byte1))
791 + (byte2 - xfont->min_char_or_byte2));
798 g->lbearing = pcm->lbearing;
799 g->rbearing = pcm->rbearing;
800 g->width = pcm->width;
801 g->ascent = pcm->ascent;
802 g->descent = pcm->descent;
806 /* If the per_char pointer is null, all glyphs between
807 the first and last character indexes inclusive have
808 the same information, as given by both min_bounds and
811 g->rbearing = xfont->max_bounds.width;
812 g->width = xfont->max_bounds.width;
813 g->ascent = xfont->ascent;
814 g->descent = xfont->descent;
821 /* The X font driver function GET_GLYPH_ID. */
824 xfont_encode_char (MRealizedFont *rfont, unsigned code)
826 MXFontInfo *xfont_info;
828 unsigned min_byte1, max_byte1, min_byte2, max_byte2;
831 if (rfont->status < 0 || code >= 0x10000)
832 return MCHAR_INVALID_CODE;
833 if (rfont->status == 0)
835 if (xfont_open (rfont) < 0)
836 return MCHAR_INVALID_CODE;
838 xfont_info = rfont->info;
839 xfont = xfont_info->xfont;
840 all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
841 min_byte1 = xfont->min_byte1;
842 max_byte1 = xfont->max_byte1;
843 min_byte2 = xfont->min_char_or_byte2;
844 max_byte2 = xfont->max_char_or_byte2;
846 if (min_byte1 == 0 && max_byte1 == 0)
850 if (code < min_byte2 || code > max_byte2)
851 return MCHAR_INVALID_CODE;
854 pcm = xfont->per_char + (code - min_byte2);
855 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
856 ? code : MCHAR_INVALID_CODE);
860 unsigned byte1 = code >> 8, byte2 = code & 0xFF;
863 if (byte1 < min_byte1 || byte1 > max_byte1
864 || byte2 < min_byte2 || byte2 > max_byte2)
865 return MCHAR_INVALID_CODE;
869 pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
870 + (byte2 - min_byte2));
871 return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
872 ? code : MCHAR_INVALID_CODE);
876 /* The X font driver function RENDER. */
879 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
880 MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
882 MRealizedFace *rface = from->rface;
883 MXFontInfo *xfont_info = rface->rfont->info;
886 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
893 /* It is assured that the all glyphs in the current range use the
894 same realized face. */
895 display = FRAME_DISPLAY (rface->frame);
898 gc = set_region (rface->frame, gc, region);
899 XSetFont (display, gc, xfont_info->xfont->fid);
900 code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
901 for (i = 0, g = from; g < to; i++, g++)
903 code[i].byte1 = g->code >> 8;
904 code[i].byte2 = g->code & 0xFF;
910 if (g->type == GLYPH_PAD)
912 else if (g->type == GLYPH_SPACE)
913 for (; g < to && g->type == GLYPH_SPACE; g++)
915 else if (! g->rface->rfont)
917 if ((g->c >= 0x200B && g->c <= 0x200F)
918 || (g->c >= 0x202A && g->c <= 0x202E))
922 /* As a font is not found for this character, draw an
924 int box_width = g->width;
925 int box_height = gstring->ascent + gstring->descent;
931 XDrawRectangle (display, (Window) win, gc,
932 x, y - gstring->ascent, box_width, box_height);
936 else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
938 XDrawString16 (display, (Window) win, gc,
939 x + g->xoff, y + g->yoff, code + (g - from), 1);
946 int code_idx = g - from;
949 g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
952 XDrawString16 (display, (Window) win, gc, orig_x, y,
959 xfont_list (MFrame *frame, MPlist *plist, MFont *font, MSymbol language,
962 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
963 MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil;
964 MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil;
968 if (registry != Mnil)
969 xfont_registry_list (frame, registry);
971 xfont_list_all (frame);
973 /* As we have not yet implemented the language check, return all
976 MPLIST_DO (p, disp_info->base_font_list)
978 mplist_add (plist, MPLIST_KEY (p), MPLIST_VAL (p));
985 MXFontList *xfontlist;
989 pl = disp_info->font_list;
990 if (registry != Mnil)
992 pl = mplist_find_by_key (pl, registry);
1002 p = mplist_find_by_key (p, family);
1008 xfontlist = MPLIST_VAL (p);
1009 for (i = 0; i < xfontlist->used; i++)
1011 xfont = xfontlist->fonts + i;
1012 if (mfont__match_p (&xfont->core, font, MFONT_REGISTRY))
1014 mplist_add (plist, MPLIST_KEY (p), &xfont->core);
1023 if (registry != Mnil)
1040 XftFont *font_no_aa;
1043 static int xft_open (MRealizedFont *);
1044 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
1045 static void xft_render (MDrawWindow, int, int, MGlyphString *,
1046 MGlyph *, MGlyph *, int, MDrawRegion);
1048 MFontDriver xft_driver =
1049 { NULL, /* Set to ft_select in device_init (). */
1050 xft_open, xft_find_metric,
1051 NULL, /* Set to ft_encode_char in device_init (). */
1053 NULL /* Set to ft_list in device_init (). */
1058 close_xft (void *object)
1060 MXftFontInfo *font_info = object;
1062 XftFontClose (font_info->display, font_info->font_aa);
1063 XftFontClose (font_info->display, font_info->font_no_aa);
1069 xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
1071 XftPattern *pattern;
1072 XftFontInfo *xft_font_info;
1075 pattern = XftPatternCreate ();
1076 XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
1077 XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
1078 XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
1079 xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
1080 if (! xft_font_info)
1082 font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
1083 XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
1089 xft_open (MRealizedFont *rfont)
1093 MXftFontInfo *font_info;
1096 if ((mfont__ft_driver.open) (rfont) < 0)
1099 size = rfont->font.property[MFONT_SIZE] / 10;
1100 frame = rfont->frame;
1102 ft_info = rfont->info;
1103 M17N_OBJECT (font_info, close_xft, MERROR_WIN);
1104 ft_info->extra_info = font_info;
1105 font_info->display = FRAME_DISPLAY (frame);
1106 font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
1107 if (font_info->font_aa)
1109 font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
1110 if (font_info->font_no_aa)
1113 rfont->fontp = font_info->font_no_aa;
1116 XftFontClose (FRAME_DISPLAY (rfont->frame), font_info->font_aa);
1119 ft_info->extra_info = NULL;
1126 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1129 MFTInfo *ft_info = rfont->info;
1130 MXftFontInfo *font_info = ft_info->extra_info;
1131 MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1133 for (; g != gend; g++)
1135 if (g->code == MCHAR_INVALID_CODE)
1137 MGlyph *start = g++;
1139 while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
1140 (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
1148 XftGlyphExtents (FRAME_DISPLAY (gstring->frame),
1149 font_info->font_aa, &g->code, 1, &extents);
1150 g->lbearing = - extents.x;
1151 g->rbearing = extents.width - extents.x;
1152 g->width = extents.xOff;
1153 g->ascent = extents.y;
1154 g->descent = extents.height - extents.y;
1161 xft_render (MDrawWindow win, int x, int y,
1162 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1163 int reverse, MDrawRegion region)
1165 MRealizedFace *rface = from->rface;
1166 MFrame *frame = rface->frame;
1167 MFTInfo *ft_info = rface->rfont->info;
1168 MXftFontInfo *font_info = ft_info->extra_info;
1169 XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1170 XftColor *xft_color = (! reverse
1171 ? &((GCInfo *) rface->info)->xft_color_fore
1172 : &((GCInfo *) rface->info)->xft_color_back);
1173 XftFont *xft_font = (gstring->control.anti_alias
1174 && FRAME_DEVICE (frame)->depth > 1
1175 ? font_info->font_aa : font_info->font_no_aa);
1184 XftDrawChange (xft_draw, (Drawable) win);
1185 XftDrawSetClip (xft_draw, (Region) region);
1187 glyphs = alloca (sizeof (FT_UInt) * (to - from));
1188 for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1190 if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1191 glyphs[nglyphs++] = g->code;
1195 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1196 last_x, y, glyphs, nglyphs);
1198 XftDrawGlyphs (xft_draw, xft_color, xft_font,
1199 x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1200 last_x = x + g->width;
1204 XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1210 /* Functions for the device driver. */
1213 mwin__close_device (MFrame *frame)
1215 MWDevice *device = FRAME_DEVICE (frame);
1217 M17N_OBJECT_UNREF (device);
1221 mwin__device_get_prop (MFrame *frame, MSymbol key)
1223 MWDevice *device = FRAME_DEVICE (frame);
1225 if (key == Mdisplay)
1226 return (void *) device->display_info->display;
1228 return (void *) ScreenOfDisplay(device->display_info->display,
1229 device->screen_num);
1230 if (key == Mcolormap)
1231 return (void *) device->cmap;
1233 return (void *) device->depth;
1238 mwin__realize_face (MRealizedFace *rface)
1241 MSymbol foreground, background, videomode;
1242 MFaceHLineProp *hline;
1246 if (rface != rface->ascii_rface)
1248 rface->info = rface->ascii_rface->info;
1252 frame = rface->frame;
1253 MSTRUCT_CALLOC (info, MERROR_WIN);
1255 foreground = rface->face.property[MFACE_FOREGROUND];
1256 background = rface->face.property[MFACE_BACKGROUND];
1257 videomode = rface->face.property[MFACE_VIDEOMODE];
1259 videomode = frame->videomode;
1260 if (videomode != Mreverse)
1262 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1263 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1267 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1268 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1271 if (foreground == Mnil)
1272 foreground = frame->foreground;
1273 if (background == Mnil)
1274 background = frame->background;
1275 if (videomode == Mreverse)
1277 MSymbol temp = foreground;
1278 foreground = background;
1281 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1282 FRAME_VISUAL (frame),
1284 MSYMBOL_NAME (foreground),
1285 &info->xft_color_fore))
1287 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1288 FRAME_VISUAL (frame),
1290 MSYMBOL_NAME (background),
1291 &info->xft_color_back))
1295 hline = rface->hline;
1299 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1301 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1308 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1310 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1312 if (box->color_left && box->color_left != box->color_top)
1313 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1315 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1317 if (box->color_bottom && box->color_bottom != box->color_top)
1318 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1320 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1322 if (box->color_right && box->color_right != box->color_bottom)
1323 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1325 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1333 mwin__free_realized_face (MRealizedFace *rface)
1335 if (rface == rface->ascii_rface)
1341 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1343 int x, int y, int width, int height, MDrawRegion region)
1345 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1348 gc = set_region (frame, gc, region);
1350 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1351 x, y, width, height);
1356 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1357 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1358 int reverse, MDrawRegion region)
1360 MRealizedFace *rface = from->rface;
1361 Display *display = FRAME_DISPLAY (rface->frame);
1362 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1368 gc = set_region (rface->frame, gc, region);
1369 for (; from < to; from++)
1371 XDrawRectangle (display, (Window) win, gc,
1372 x, y - gstring->ascent + 1, from->width - 1,
1373 gstring->ascent + gstring->descent - 2);
1380 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1381 MRealizedFace *rface, int reverse,
1382 int x, int y, int width, MDrawRegion region)
1384 enum MFaceHLineType type = rface->hline->type;
1385 GCInfo *info = rface->info;
1386 GC gc = gc = info->gc[GC_HLINE];
1389 y = (type == MFACE_HLINE_BOTTOM
1390 ? y + gstring->text_descent - rface->hline->width
1391 : type == MFACE_HLINE_UNDER
1393 : type == MFACE_HLINE_STRIKE_THROUGH
1394 ? y - ((gstring->ascent + gstring->descent) / 2)
1395 : y - gstring->text_ascent);
1397 gc = set_region (frame, gc, region);
1399 for (i = 0; i < rface->hline->width; i++)
1400 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1401 x, y + i, x + width - 1, y + i);
1406 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1407 MGlyph *g, int x, int y, int width, MDrawRegion region)
1409 Display *display = FRAME_DISPLAY (frame);
1410 MRealizedFace *rface = g->rface;
1411 MFaceBoxProp *box = rface->box;
1412 GCInfo *info = rface->info;
1413 GC gc_top, gc_left, gc_right, gc_btm;
1417 y0 = y - (gstring->text_ascent
1418 + rface->box->inner_vmargin + rface->box->width);
1419 y1 = y + (gstring->text_descent
1420 + rface->box->inner_vmargin + rface->box->width - 1);
1422 gc_top = info->gc[GC_BOX_TOP];
1424 gc_top = set_region (frame, gc_top, region);
1425 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1428 gc_btm = info->gc[GC_BOX_BOTTOM];
1430 if (g->type == GLYPH_BOX)
1434 if (g->left_padding)
1435 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1437 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1439 /* Draw the top side. */
1440 for (i = 0; i < box->width; i++)
1441 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1443 /* Draw the bottom side. */
1444 if (region && gc_btm != gc_top)
1445 gc_btm = set_region (frame, gc_btm, region);
1446 for (i = 0; i < box->width; i++)
1447 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1449 if (g->left_padding > 0)
1451 /* Draw the left side. */
1452 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1456 gc_left = info->gc[GC_BOX_LEFT];
1458 gc_left = set_region (frame, gc_left, region);
1460 for (i = 0; i < rface->box->width; i++)
1461 XDrawLine (display, (Window) win, gc_left,
1462 x0 + i, y0 + i, x0 + i, y1 - i);
1466 /* Draw the right side. */
1467 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1471 gc_right = info->gc[GC_BOX_RIGHT];
1473 gc_right = set_region (frame, gc_right, region);
1475 for (i = 0; i < rface->box->width; i++)
1476 XDrawLine (display, (Window) win, gc_right,
1477 x1 - i, y0 + i, x1 - i, y1 - i);
1482 /* Draw the top side. */
1483 for (i = 0; i < box->width; i++)
1484 XDrawLine (display, (Window) win, gc_top,
1485 x, y0 + i, x + width - 1, y0 + i);
1487 /* Draw the bottom side. */
1488 if (region && gc_btm != gc_top)
1489 gc_btm = set_region (frame, gc_btm, region);
1490 for (i = 0; i < box->width; i++)
1491 XDrawLine (display, (Window) win, gc_btm,
1492 x, y1 - i, x + width - 1, y1 - i);
1499 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1500 int reverse, int x, int y,
1501 int width, int height, int row_bytes, unsigned char *bmp,
1504 Display *display = FRAME_DISPLAY (frame);
1506 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1509 gc = set_region (frame, gc, region);
1511 for (i = 0; i < height; i++, bmp += row_bytes)
1512 for (j = 0; j < width; j++)
1513 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1514 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1519 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1520 int intensity, MDrawPoint *points, int num,
1523 GCInfo *info = rface->info;
1526 if (! (gc = info->gc[intensity]))
1527 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1530 gc = set_region (frame, gc, region);
1532 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1533 (XPoint *) points, num, CoordModeOrigin);
1538 mwin__region_from_rect (MDrawMetric *rect)
1540 MDrawRegion region1 = XCreateRegion ();
1541 MDrawRegion region2 = XCreateRegion ();
1546 xrect.width = rect->width;
1547 xrect.height = rect->height;
1548 XUnionRectWithRegion (&xrect, region1, region2);
1549 XDestroyRegion (region1);
1554 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1556 MDrawRegion region1 = XCreateRegion ();
1561 xrect.width = rect->width;
1562 xrect.height = rect->height;
1564 XUnionRegion (region, region, region1);
1565 XUnionRectWithRegion (&xrect, region1, region);
1566 XDestroyRegion (region1);
1570 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1572 MDrawRegion region = XCreateRegion ();
1574 XUnionRegion (region1, region1, region);
1575 XIntersectRegion (region, region2, region1);
1576 XDestroyRegion (region);
1580 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1582 MDrawRegion region1 = XCreateRegion ();
1587 xrect.width = rect->width;
1588 xrect.height = rect->height;
1589 XUnionRectWithRegion (&xrect, region1, region);
1590 XDestroyRegion (region1);
1594 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1598 XClipBox (region, &xrect);
1601 rect->width = xrect.width;
1602 rect->height = xrect.height;
1606 mwin__free_region (MDrawRegion region)
1608 XDestroyRegion (region);
1612 mwin__dump_region (MDrawRegion region)
1615 XClipBox (region, &rect);
1616 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1621 mwin__create_window (MFrame *frame, MDrawWindow parent)
1623 Display *display = FRAME_DISPLAY (frame);
1625 XWMHints wm_hints = { InputHint, False };
1626 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1627 XSetWindowAttributes set_attrs;
1630 GCInfo *info = frame->rface->info;
1633 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1634 mask = GCForeground;
1635 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1636 set_attrs.background_pixel = values.foreground;
1637 set_attrs.backing_store = Always;
1638 set_attrs.override_redirect = True;
1639 set_attrs.save_under = True;
1640 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1641 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1642 CopyFromParent, InputOutput, CopyFromParent,
1644 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1645 NULL, &wm_hints, &class_hints);
1646 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1647 return (MDrawWindow) win;
1651 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1653 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1658 mwin__event_window (void *event)
1660 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1664 mwin__print_event (void *arg, char *win_name)
1667 XEvent *event = (XEvent *) arg;
1669 switch (event->xany.type)
1671 case 2: event_name = "KeyPress"; break;
1672 case 3: event_name = "KeyRelease"; break;
1673 case 4: event_name = "ButtonPress"; break;
1674 case 5: event_name = "ButtonRelease"; break;
1675 case 6: event_name = "MotionNotify"; break;
1676 case 7: event_name = "EnterNotify"; break;
1677 case 8: event_name = "LeaveNotify"; break;
1678 case 9: event_name = "FocusIn"; break;
1679 case 10: event_name = "FocusOut"; break;
1680 case 11: event_name = "KeymapNotify"; break;
1681 case 12: event_name = "Expose"; break;
1682 case 13: event_name = "GraphicsExpose"; break;
1683 case 14: event_name = "NoExpose"; break;
1684 case 15: event_name = "VisibilityNotify"; break;
1685 case 16: event_name = "CreateNotify"; break;
1686 case 17: event_name = "DestroyNotify"; break;
1687 case 18: event_name = "UnmapNotify"; break;
1688 case 19: event_name = "MapNotify"; break;
1689 case 20: event_name = "MapRequest"; break;
1690 case 21: event_name = "ReparentNotify"; break;
1691 case 22: event_name = "ConfigureNotify"; break;
1692 case 23: event_name = "ConfigureRequest"; break;
1693 case 24: event_name = "GravityNotify"; break;
1694 case 25: event_name = "ResizeRequest"; break;
1695 case 26: event_name = "CirculateNotify"; break;
1696 case 27: event_name = "CirculateRequest"; break;
1697 case 28: event_name = "PropertyNotify"; break;
1698 case 29: event_name = "SelectionClear"; break;
1699 case 30: event_name = "SelectionRequest"; break;
1700 case 31: event_name = "SelectionNotify"; break;
1701 case 32: event_name = "ColormapNotify"; break;
1702 case 33: event_name = "ClientMessage"; break;
1703 case 34: event_name = "MappingNotify"; break;
1704 default: event_name = "unknown";
1707 fprintf (stderr, "%s: %s\n", win_name, event_name);
1712 mwin__map_window (MFrame *frame, MDrawWindow win)
1714 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1718 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1720 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1724 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1725 MDrawMetric *geometry)
1727 Display *display = FRAME_DISPLAY (frame);
1728 XWindowAttributes attr;
1729 Window parent = (Window) parent_win, root;
1731 XGetWindowAttributes (display, (Window) win, &attr);
1732 geometry->x = attr.x + attr.border_width;
1733 geometry->y = attr.y + attr.border_width;
1734 geometry->width = attr.width;
1735 geometry->height = attr.height;
1738 parent = RootWindow (display, FRAME_SCREEN (frame));
1741 Window this_parent, *children;
1744 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1747 if (this_parent == parent || this_parent == root)
1749 win = (MDrawWindow) this_parent;
1750 XGetWindowAttributes (display, (Window) win, &attr);
1751 geometry->x += attr.x + attr.border_width;
1752 geometry->y += attr.y + attr.border_width;
1757 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1758 MDrawMetric *current, MDrawMetric *new)
1760 Display *display = FRAME_DISPLAY (frame);
1761 unsigned int mask = 0;
1762 XWindowChanges values;
1764 if (current->width != new->width)
1767 if (new->width <= 0)
1769 values.width = current->width = new->width;
1771 if (current->height != new->height)
1774 if (new->height <= 0)
1776 values.height = current->height = new->height;
1778 if (current->x != new->x)
1781 values.x = current->x = new->x;
1783 if (current->y != new->y)
1786 current->y = new->y;
1787 values.y = current->y = new->y;
1790 XConfigureWindow (display, (Window) win, mask, &values);
1791 XClearWindow (display, (Window) win);
1795 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1797 XEvent *event = (XEvent *) arg;
1798 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1805 if (event->xany.type != KeyPress
1806 /* && event->xany.type != KeyRelease */
1809 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1816 if (c < XK_space || c > XK_asciitilde)
1818 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1819 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1820 if (((XKeyEvent *) event)->state & ControlMask)
1822 if (c >= 'a' && c <= 'z')
1824 if (c >= ' ' && c < 127)
1825 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1827 key = minput__char_to_key (c);
1829 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1833 char *str = XKeysymToString (keysym);
1837 key = msymbol (str);
1838 if (((XKeyEvent *) event)->state & ShiftMask)
1839 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1840 if (((XKeyEvent *) event)->state & ControlMask)
1841 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1843 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1844 *modifiers |= MINPUT_KEY_META_MODIFIER;
1845 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1846 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1847 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1848 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1849 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1850 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1857 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1859 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1861 Display *display = FRAME_DISPLAY (frame);
1862 GCInfo *info = rface->info;
1865 for (i = 0; i <= GC_INVERSE; i++)
1867 XGetGCValues (display, info->gc[i], valuemask, &values);
1868 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1869 values.foreground, values.background);
1870 fprintf (stderr, "\n");
1874 static MDeviceDriver x_driver =
1877 mwin__device_get_prop,
1879 mwin__free_realized_face,
1881 mwin__draw_empty_boxes,
1885 mwin__region_from_rect,
1886 mwin__union_rect_with_region,
1887 mwin__intersect_region,
1888 mwin__region_add_rect,
1889 mwin__region_to_rect,
1892 mwin__create_window,
1893 mwin__destroy_window,
1896 mwin__window_geometry,
1897 mwin__adjust_window,
1901 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1906 M_iso8859_1 = msymbol ("iso8859-1");
1907 M_iso10646_1 = msymbol ("iso10646-1");
1909 display_info_list = mplist ();
1910 device_list = mplist ();
1913 xft_driver.select = mfont__ft_driver.select;
1914 xft_driver.encode_char = mfont__ft_driver.encode_char;
1915 xft_driver.list = mfont__ft_driver.list;
1918 Mxim = msymbol ("xim");
1919 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1927 M17N_OBJECT_UNREF (display_info_list);
1928 M17N_OBJECT_UNREF (device_list);
1932 /** Return an MWDevice object corresponding to a display specified in
1935 It searches device_list for a device matching the display. If
1936 found, return the found object. Otherwise, return a newly created
1940 device_open (MFrame *frame, MPlist *param)
1942 Display *display = NULL;
1943 Screen *screen = NULL;
1945 Drawable drawable = 0;
1946 Widget widget = NULL;
1948 int auto_display = 0;
1949 MDisplayInfo *disp_info = NULL;
1950 MWDevice *device = NULL;
1952 XWindowAttributes attr;
1957 int use_xfont = 0, use_freetype = 0, use_xft = 0;
1959 for (plist = param; (key = mplist_key (plist)) != Mnil;
1960 plist = mplist_next (plist))
1962 if (key == Mdisplay)
1963 display = (Display *) mplist_value (plist);
1964 else if (key == Mscreen)
1965 screen = mplist_value (plist);
1966 else if (key == Mdrawable)
1967 drawable = (Drawable) mplist_value (plist);
1968 else if (key == Mdepth)
1969 depth = (unsigned) mplist_value (plist);
1970 else if (key == Mwidget)
1971 widget = (Widget) mplist_value (plist);
1972 else if (key == Mcolormap)
1973 cmap = (Colormap) mplist_value (plist);
1974 else if (key == Mfont)
1976 MSymbol val = MPLIST_SYMBOL (plist);
1980 #ifdef HAVE_FREETYPE
1981 else if (val == Mfreetype)
1984 else if (val == Mxft)
1991 /* If none of them is specified, use all of them. */
1992 if (! use_xfont && ! use_freetype && ! use_xft)
1993 use_xfont = use_freetype = use_xft = 1;
1997 display = XtDisplay (widget);
1998 screen_num = XScreenNumberOfScreen (XtScreen (widget));
1999 depth = DefaultDepth (display, screen_num);
2005 unsigned width, height, border_width;
2008 MERROR (MERROR_WIN, -1);
2009 XGetGeometry (display, drawable, &root_window,
2010 &x, &y, &width, &height, &border_width, &depth);
2011 XGetWindowAttributes (display, root_window, &attr);
2012 screen_num = XScreenNumberOfScreen (attr.screen);
2017 display = DisplayOfScreen (screen);
2022 display = XOpenDisplay (NULL);
2024 MERROR (MERROR_WIN, -1);
2027 screen = DefaultScreenOfDisplay (display);
2029 screen_num = XScreenNumberOfScreen (screen);
2031 depth = DefaultDepth (display, screen_num);
2035 cmap = DefaultColormap (display, screen_num);
2037 for (plist = display_info_list; mplist_key (plist) != Mnil;
2038 plist = mplist_next (plist))
2040 disp_info = (MDisplayInfo *) mplist_value (plist);
2041 if (disp_info->display == display)
2045 if (mplist_key (plist) != Mnil)
2046 M17N_OBJECT_REF (disp_info);
2049 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
2050 disp_info->display = display;
2051 disp_info->auto_display = auto_display;
2052 disp_info->font_list = mplist ();
2053 disp_info->base_font_list = mplist ();
2054 find_modifier_bits (disp_info);
2055 mplist_add (display_info_list, Mt, disp_info);
2058 for (plist = device_list; mplist_key (plist) != Mnil;
2059 plist = mplist_next (plist))
2061 device = (MWDevice *) mplist_value (plist);
2062 if (device->display_info == disp_info
2063 && device->depth == depth
2064 && device->cmap == cmap)
2068 if (mplist_key (plist) != Mnil)
2069 M17N_OBJECT_REF (device);
2072 unsigned long valuemask = GCForeground;
2075 M17N_OBJECT (device, free_device, MERROR_WIN);
2076 device->display_info = disp_info;
2077 device->screen_num = screen_num;
2078 /* A drawable on which to create GCs. */
2079 device->drawable = XCreatePixmap (display,
2080 RootWindow (display, screen_num),
2082 device->depth = depth;
2083 device->cmap = cmap;
2084 device->realized_face_list = mplist ();
2085 device->realized_font_list = mplist ();
2086 device->realized_fontset_list = mplist ();
2087 device->gc_list = mplist ();
2088 values.foreground = BlackPixel (display, screen_num);
2089 device->scratch_gc = XCreateGC (display, device->drawable,
2090 valuemask, &values);
2092 device->xft_draw = XftDrawCreate (display, device->drawable,
2093 DefaultVisual (display, screen_num),
2098 frame->device = device;
2099 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2100 frame->driver = &x_driver;
2101 frame->font_driver_list = mplist ();
2105 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2108 #endif /* HAVE_XFT2 */
2109 #ifdef HAVE_FREETYPE
2111 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2112 #endif /* HAVE_FREETYPE */
2113 if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list))
2114 mplist_push (frame->font_driver_list, Mx, &xfont_driver);
2116 frame->realized_font_list = device->realized_font_list;
2117 frame->realized_face_list = device->realized_face_list;
2118 frame->realized_fontset_list = device->realized_fontset_list;
2122 XtResource resources[] = {
2123 { XtNfont, XtCFont, XtRString, sizeof (String),
2124 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2125 { XtNforeground, XtCForeground, XtRString, sizeof (String),
2126 XtOffset (AppDataPtr, foreground), XtRString, "black" },
2127 { XtNbackground, XtCBackground, XtRString, sizeof (String),
2128 XtOffset (AppDataPtr, background), XtRString, "white" },
2129 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2130 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2133 XtGetApplicationResources (widget, &app_data,
2134 resources, XtNumber (resources), NULL, 0);
2135 frame->foreground = msymbol (app_data.foreground);
2136 frame->background = msymbol (app_data.background);
2137 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2141 app_data.font = DEFAULT_FONT;
2142 frame->foreground = msymbol ("black");
2143 frame->background = msymbol ("white");
2144 frame->videomode = Mnormal;
2149 /* Try at least 32 fonts to obtain a non-autoscaled font. */
2150 char **names = XListFonts (display, app_data.font, 32, &nfonts);
2153 for (i = 0; ! font && i < nfonts; i++)
2155 font = mfont_parse_name (names[i], Mx);
2158 /* The font name does not conform to XLFD. Try to open the
2159 font and get XA_FONT property. */
2160 XFontStruct *xfont = XLoadQueryFont (display, names[i]);
2164 unsigned long value;
2167 if (XGetFontProperty (xfont, XA_FONT, &value)
2168 && (name = ((char *)
2169 XGetAtomName (display, (Atom) value))))
2170 font = mfont_parse_name (name, Mx);
2171 XFreeFont (display, xfont);
2175 font->property[MFONT_SIZE] == 0 && font->property[MFONT_RESY] > 0)
2182 XFreeFontNames (names);
2183 frame->font = font ? font : mfont_parse_name (FALLBACK_FONT, Mx);
2186 face = mface_from_font (frame->font);
2187 face->property[MFACE_FONTSET] = mfontset (NULL);
2188 face->property[MFACE_FOREGROUND] = frame->foreground;
2189 face->property[MFACE_BACKGROUND] = frame->background;
2190 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2191 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2192 face->property[MFACE_VIDEOMODE] = frame->videomode;
2193 mface_put_prop (face, Mhook_func,
2194 mface_get_prop (mface__default, Mhook_func));
2195 face->property[MFACE_RATIO] = (void *) 100;
2196 mplist_push (param, Mface, face);
2197 M17N_OBJECT_UNREF (face);
2199 #ifdef X_SET_ERROR_HANDLER
2200 XSetErrorHandler (x_error_handler);
2201 XSetIOErrorHandler (x_io_error_handler);
2209 /* XIM (X Input Method) handler */
2211 typedef struct MInputXIMMethodInfo
2217 } MInputXIMMethodInfo;
2219 typedef struct MInputXIMContextInfo
2223 MConverter *converter;
2224 } MInputXIMContextInfo;
2227 xim_open_im (MInputMethod *im)
2229 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2230 MLocale *saved, *this;
2231 char *save_modifier_list;
2233 MInputXIMMethodInfo *im_info;
2235 saved = mlocale_set (LC_CTYPE, NULL);
2236 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2238 /* The specified locale is not supported. */
2239 MERROR (MERROR_LOCALE, -1);
2240 if (mlocale_get_prop (this, Mcoding) == Mnil)
2242 /* Unable to decode the output of XIM. */
2243 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2244 MERROR (MERROR_LOCALE, -1);
2247 if (arg->modifier_list)
2248 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2250 save_modifier_list = XSetLocaleModifiers ("");
2251 if (! save_modifier_list)
2253 /* The specified locale is not supported by X. */
2254 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2255 MERROR (MERROR_LOCALE, -1);
2258 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2261 /* No input method is available in the current locale. */
2262 XSetLocaleModifiers (save_modifier_list);
2263 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2264 MERROR (MERROR_WIN, -1);
2267 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2268 im_info->display = arg->display;
2270 im_info->language = mlocale_get_prop (this, Mlanguage);
2271 im_info->coding = mlocale_get_prop (this, Mcoding);
2274 XSetLocaleModifiers (save_modifier_list);
2275 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2281 xim_close_im (MInputMethod *im)
2283 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2285 XCloseIM (im_info->xim);
2290 xim_create_ic (MInputContext *ic)
2292 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2293 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2294 MInputXIMContextInfo *ic_info;
2297 if (! arg->input_style)
2299 /* By default, use Root style. */
2300 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2301 arg->preedit_attrs = NULL;
2302 arg->status_attrs = NULL;
2305 if (! arg->preedit_attrs && ! arg->status_attrs)
2306 xic = XCreateIC (im_info->xim,
2307 XNInputStyle, arg->input_style,
2308 XNClientWindow, arg->client_win,
2309 XNFocusWindow, arg->focus_win,
2311 else if (arg->preedit_attrs && ! arg->status_attrs)
2312 xic = XCreateIC (im_info->xim,
2313 XNInputStyle, arg->input_style,
2314 XNClientWindow, arg->client_win,
2315 XNFocusWindow, arg->focus_win,
2316 XNPreeditAttributes, arg->preedit_attrs,
2318 else if (! arg->preedit_attrs && arg->status_attrs)
2319 xic = XCreateIC (im_info->xim,
2320 XNInputStyle, arg->input_style,
2321 XNClientWindow, arg->client_win,
2322 XNFocusWindow, arg->focus_win,
2323 XNStatusAttributes, arg->status_attrs,
2326 xic = XCreateIC (im_info->xim,
2327 XNInputStyle, arg->input_style,
2328 XNClientWindow, arg->client_win,
2329 XNFocusWindow, arg->focus_win,
2330 XNPreeditAttributes, arg->preedit_attrs,
2331 XNStatusAttributes, arg->status_attrs,
2334 MERROR (MERROR_WIN, -1);
2336 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2338 ic_info->win = arg->focus_win;
2339 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2345 xim_destroy_ic (MInputContext *ic)
2347 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2349 XDestroyIC (ic_info->xic);
2350 mconv_free_converter (ic_info->converter);
2356 xim_filter (MInputContext *ic, MSymbol key, void *event)
2358 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2360 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2365 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2367 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2368 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2369 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2375 buf = (char *) alloca (512);
2376 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2377 if (status == XBufferOverflow)
2379 buf = (char *) alloca (len);
2380 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2383 mtext_reset (ic->produced);
2387 mconv_reset_converter (ic_info->converter);
2388 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2389 mconv_decode (ic_info->converter, ic->produced);
2390 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2391 Mlanguage, (void *) im_info->language);
2392 mtext_cpy (mt, ic->produced);
2393 mtext_reset (ic->produced);
2399 #ifdef X_SET_ERROR_HANDLER
2401 x_error_handler (Display *display, XErrorEvent *error)
2408 x_io_error_handler (Display *display)
2418 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2422 /*** @addtogroup m17nInputMethodWin */
2427 @brief Input method driver for XIM.
2429 The driver #minput_xim_driver is for the foreign input method of
2430 name #Mxim. It uses XIM (X Input Methods) as a background input
2433 As the symbol #Mxim has property #Minput_driver whose value is
2434 a pointer to this driver, the input method of language #Mnil
2435 and name #Mxim uses this driver.
2437 Therefore, for such input methods, the driver dependent arguments
2438 to the functions whose name begin with minput_ must be as follows.
2440 The argument $ARG of the function minput_open_im () must be a
2441 pointer to the structure #MInputXIMArgIM. See the documentation
2442 of #MInputXIMArgIM for more details.
2444 The argument $ARG of the function minput_create_ic () must be a
2445 pointer to the structure #MInputXIMArgIC. See the documentation
2446 of #MInputXIMArgIC for more details.
2448 The argument $ARG of the function minput_filter () must be a
2449 pointer to the structure @c XEvent. The argument $KEY is ignored.
2451 The argument $ARG of the function minput_lookup () must be the
2452 same one as that of the function minput_filter (). The argument
2456 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2458 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ê¡¢
2459 XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
2461 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2462 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim
2463 ¤Ç¤¢¤ëÆþÎϥ᥽¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2465 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_
2466 ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2468 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM
2469 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò»²¾È¡£
2471 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC
2472 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ¤ò»²¾È¡£
2474 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent
2475 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2477 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2478 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì¤ë¡£ */
2480 MInputDriver minput_xim_driver =
2481 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2482 xim_filter, xim_lookup, NULL };