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 M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
1219 mwin__device_get_prop (MFrame *frame, MSymbol key)
1221 MWDevice *device = FRAME_DEVICE (frame);
1223 if (key == Mdisplay)
1224 return (void *) device->display_info->display;
1226 return (void *) ScreenOfDisplay(device->display_info->display,
1227 device->screen_num);
1228 if (key == Mcolormap)
1229 return (void *) device->cmap;
1231 return (void *) device->depth;
1236 mwin__realize_face (MRealizedFace *rface)
1239 MSymbol foreground, background, videomode;
1240 MFaceHLineProp *hline;
1244 if (rface != rface->ascii_rface)
1246 rface->info = rface->ascii_rface->info;
1250 frame = rface->frame;
1251 MSTRUCT_CALLOC (info, MERROR_WIN);
1253 foreground = rface->face.property[MFACE_FOREGROUND];
1254 background = rface->face.property[MFACE_BACKGROUND];
1255 videomode = rface->face.property[MFACE_VIDEOMODE];
1257 videomode = frame->videomode;
1258 if (videomode != Mreverse)
1260 info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1261 info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1265 info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1266 info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1269 if (foreground == Mnil)
1270 foreground = frame->foreground;
1271 if (background == Mnil)
1272 background = frame->background;
1273 if (videomode == Mreverse)
1275 MSymbol temp = foreground;
1276 foreground = background;
1279 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1280 FRAME_VISUAL (frame),
1282 MSYMBOL_NAME (foreground),
1283 &info->xft_color_fore))
1285 if (! XftColorAllocName (FRAME_DISPLAY (frame),
1286 FRAME_VISUAL (frame),
1288 MSYMBOL_NAME (background),
1289 &info->xft_color_back))
1293 hline = rface->hline;
1297 info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1299 info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1306 info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1308 info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1310 if (box->color_left && box->color_left != box->color_top)
1311 info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1313 info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1315 if (box->color_bottom && box->color_bottom != box->color_top)
1316 info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1318 info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1320 if (box->color_right && box->color_right != box->color_bottom)
1321 info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1323 info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1331 mwin__free_realized_face (MRealizedFace *rface)
1333 if (rface == rface->ascii_rface)
1339 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1341 int x, int y, int width, int height, MDrawRegion region)
1343 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1346 gc = set_region (frame, gc, region);
1348 XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1349 x, y, width, height);
1354 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1355 MGlyphString *gstring, MGlyph *from, MGlyph *to,
1356 int reverse, MDrawRegion region)
1358 MRealizedFace *rface = from->rface;
1359 Display *display = FRAME_DISPLAY (rface->frame);
1360 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1366 gc = set_region (rface->frame, gc, region);
1367 for (; from < to; from++)
1369 XDrawRectangle (display, (Window) win, gc,
1370 x, y - gstring->ascent + 1, from->width - 1,
1371 gstring->ascent + gstring->descent - 2);
1378 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1379 MRealizedFace *rface, int reverse,
1380 int x, int y, int width, MDrawRegion region)
1382 enum MFaceHLineType type = rface->hline->type;
1383 GCInfo *info = rface->info;
1384 GC gc = gc = info->gc[GC_HLINE];
1387 y = (type == MFACE_HLINE_BOTTOM
1388 ? y + gstring->text_descent - rface->hline->width
1389 : type == MFACE_HLINE_UNDER
1391 : type == MFACE_HLINE_STRIKE_THROUGH
1392 ? y - ((gstring->ascent + gstring->descent) / 2)
1393 : y - gstring->text_ascent);
1395 gc = set_region (frame, gc, region);
1397 for (i = 0; i < rface->hline->width; i++)
1398 XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1399 x, y + i, x + width - 1, y + i);
1404 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1405 MGlyph *g, int x, int y, int width, MDrawRegion region)
1407 Display *display = FRAME_DISPLAY (frame);
1408 MRealizedFace *rface = g->rface;
1409 MFaceBoxProp *box = rface->box;
1410 GCInfo *info = rface->info;
1411 GC gc_top, gc_left, gc_right, gc_btm;
1415 y0 = y - (gstring->text_ascent
1416 + rface->box->inner_vmargin + rface->box->width);
1417 y1 = y + (gstring->text_descent
1418 + rface->box->inner_vmargin + rface->box->width - 1);
1420 gc_top = info->gc[GC_BOX_TOP];
1422 gc_top = set_region (frame, gc_top, region);
1423 if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1426 gc_btm = info->gc[GC_BOX_BOTTOM];
1428 if (g->type == GLYPH_BOX)
1432 if (g->left_padding)
1433 x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1435 x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1437 /* Draw the top side. */
1438 for (i = 0; i < box->width; i++)
1439 XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1441 /* Draw the bottom side. */
1442 if (region && gc_btm != gc_top)
1443 gc_btm = set_region (frame, gc_btm, region);
1444 for (i = 0; i < box->width; i++)
1445 XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1447 if (g->left_padding > 0)
1449 /* Draw the left side. */
1450 if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1454 gc_left = info->gc[GC_BOX_LEFT];
1456 gc_left = set_region (frame, gc_left, region);
1458 for (i = 0; i < rface->box->width; i++)
1459 XDrawLine (display, (Window) win, gc_left,
1460 x0 + i, y0 + i, x0 + i, y1 - i);
1464 /* Draw the right side. */
1465 if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1469 gc_right = info->gc[GC_BOX_RIGHT];
1471 gc_right = set_region (frame, gc_right, region);
1473 for (i = 0; i < rface->box->width; i++)
1474 XDrawLine (display, (Window) win, gc_right,
1475 x1 - i, y0 + i, x1 - i, y1 - i);
1480 /* Draw the top side. */
1481 for (i = 0; i < box->width; i++)
1482 XDrawLine (display, (Window) win, gc_top,
1483 x, y0 + i, x + width - 1, y0 + i);
1485 /* Draw the bottom side. */
1486 if (region && gc_btm != gc_top)
1487 gc_btm = set_region (frame, gc_btm, region);
1488 for (i = 0; i < box->width; i++)
1489 XDrawLine (display, (Window) win, gc_btm,
1490 x, y1 - i, x + width - 1, y1 - i);
1497 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1498 int reverse, int x, int y,
1499 int width, int height, int row_bytes, unsigned char *bmp,
1502 Display *display = FRAME_DISPLAY (frame);
1504 GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1507 gc = set_region (frame, gc, region);
1509 for (i = 0; i < height; i++, bmp += row_bytes)
1510 for (j = 0; j < width; j++)
1511 if (bmp[j / 8] & (1 << (7 - (j % 8))))
1512 XDrawPoint (display, (Window) win, gc, x + j, y + i);
1517 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1518 int intensity, MDrawPoint *points, int num,
1521 GCInfo *info = rface->info;
1524 if (! (gc = info->gc[intensity]))
1525 gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1528 gc = set_region (frame, gc, region);
1530 XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1531 (XPoint *) points, num, CoordModeOrigin);
1536 mwin__region_from_rect (MDrawMetric *rect)
1538 MDrawRegion region1 = XCreateRegion ();
1539 MDrawRegion region2 = XCreateRegion ();
1544 xrect.width = rect->width;
1545 xrect.height = rect->height;
1546 XUnionRectWithRegion (&xrect, region1, region2);
1547 XDestroyRegion (region1);
1552 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1554 MDrawRegion region1 = XCreateRegion ();
1559 xrect.width = rect->width;
1560 xrect.height = rect->height;
1562 XUnionRegion (region, region, region1);
1563 XUnionRectWithRegion (&xrect, region1, region);
1564 XDestroyRegion (region1);
1568 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1570 MDrawRegion region = XCreateRegion ();
1572 XUnionRegion (region1, region1, region);
1573 XIntersectRegion (region, region2, region1);
1574 XDestroyRegion (region);
1578 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1580 MDrawRegion region1 = XCreateRegion ();
1585 xrect.width = rect->width;
1586 xrect.height = rect->height;
1587 XUnionRectWithRegion (&xrect, region1, region);
1588 XDestroyRegion (region1);
1592 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1596 XClipBox (region, &xrect);
1599 rect->width = xrect.width;
1600 rect->height = xrect.height;
1604 mwin__free_region (MDrawRegion region)
1606 XDestroyRegion (region);
1610 mwin__dump_region (MDrawRegion region)
1613 XClipBox (region, &rect);
1614 fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1619 mwin__create_window (MFrame *frame, MDrawWindow parent)
1621 Display *display = FRAME_DISPLAY (frame);
1623 XWMHints wm_hints = { InputHint, False };
1624 XClassHint class_hints = { "M17N-IM", "m17n-im" };
1625 XSetWindowAttributes set_attrs;
1628 GCInfo *info = frame->rface->info;
1631 parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1632 mask = GCForeground;
1633 XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1634 set_attrs.background_pixel = values.foreground;
1635 set_attrs.backing_store = Always;
1636 set_attrs.override_redirect = True;
1637 set_attrs.save_under = True;
1638 mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1639 win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1640 CopyFromParent, InputOutput, CopyFromParent,
1642 XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1643 NULL, &wm_hints, &class_hints);
1644 XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1645 return (MDrawWindow) win;
1649 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1651 XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1656 mwin__event_window (void *event)
1658 return ((MDrawWindow) ((XEvent *) event)->xany.window);
1662 mwin__print_event (void *arg, char *win_name)
1665 XEvent *event = (XEvent *) arg;
1667 switch (event->xany.type)
1669 case 2: event_name = "KeyPress"; break;
1670 case 3: event_name = "KeyRelease"; break;
1671 case 4: event_name = "ButtonPress"; break;
1672 case 5: event_name = "ButtonRelease"; break;
1673 case 6: event_name = "MotionNotify"; break;
1674 case 7: event_name = "EnterNotify"; break;
1675 case 8: event_name = "LeaveNotify"; break;
1676 case 9: event_name = "FocusIn"; break;
1677 case 10: event_name = "FocusOut"; break;
1678 case 11: event_name = "KeymapNotify"; break;
1679 case 12: event_name = "Expose"; break;
1680 case 13: event_name = "GraphicsExpose"; break;
1681 case 14: event_name = "NoExpose"; break;
1682 case 15: event_name = "VisibilityNotify"; break;
1683 case 16: event_name = "CreateNotify"; break;
1684 case 17: event_name = "DestroyNotify"; break;
1685 case 18: event_name = "UnmapNotify"; break;
1686 case 19: event_name = "MapNotify"; break;
1687 case 20: event_name = "MapRequest"; break;
1688 case 21: event_name = "ReparentNotify"; break;
1689 case 22: event_name = "ConfigureNotify"; break;
1690 case 23: event_name = "ConfigureRequest"; break;
1691 case 24: event_name = "GravityNotify"; break;
1692 case 25: event_name = "ResizeRequest"; break;
1693 case 26: event_name = "CirculateNotify"; break;
1694 case 27: event_name = "CirculateRequest"; break;
1695 case 28: event_name = "PropertyNotify"; break;
1696 case 29: event_name = "SelectionClear"; break;
1697 case 30: event_name = "SelectionRequest"; break;
1698 case 31: event_name = "SelectionNotify"; break;
1699 case 32: event_name = "ColormapNotify"; break;
1700 case 33: event_name = "ClientMessage"; break;
1701 case 34: event_name = "MappingNotify"; break;
1702 default: event_name = "unknown";
1705 fprintf (stderr, "%s: %s\n", win_name, event_name);
1710 mwin__map_window (MFrame *frame, MDrawWindow win)
1712 XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1716 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1718 XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1722 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1723 MDrawMetric *geometry)
1725 Display *display = FRAME_DISPLAY (frame);
1726 XWindowAttributes attr;
1727 Window parent = (Window) parent_win, root;
1729 XGetWindowAttributes (display, (Window) win, &attr);
1730 geometry->x = attr.x + attr.border_width;
1731 geometry->y = attr.y + attr.border_width;
1732 geometry->width = attr.width;
1733 geometry->height = attr.height;
1736 parent = RootWindow (display, FRAME_SCREEN (frame));
1739 Window this_parent, *children;
1742 XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1745 if (this_parent == parent || this_parent == root)
1747 win = (MDrawWindow) this_parent;
1748 XGetWindowAttributes (display, (Window) win, &attr);
1749 geometry->x += attr.x + attr.border_width;
1750 geometry->y += attr.y + attr.border_width;
1755 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1756 MDrawMetric *current, MDrawMetric *new)
1758 Display *display = FRAME_DISPLAY (frame);
1759 unsigned int mask = 0;
1760 XWindowChanges values;
1762 if (current->width != new->width)
1765 if (new->width <= 0)
1767 values.width = current->width = new->width;
1769 if (current->height != new->height)
1772 if (new->height <= 0)
1774 values.height = current->height = new->height;
1776 if (current->x != new->x)
1779 values.x = current->x = new->x;
1781 if (current->y != new->y)
1784 current->y = new->y;
1785 values.y = current->y = new->y;
1788 XConfigureWindow (display, (Window) win, mask, &values);
1789 XClearWindow (display, (Window) win);
1793 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1795 XEvent *event = (XEvent *) arg;
1796 MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1803 if (event->xany.type != KeyPress
1804 /* && event->xany.type != KeyRelease */
1807 len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1814 if (c < XK_space || c > XK_asciitilde)
1816 if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1817 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1818 if (((XKeyEvent *) event)->state & ControlMask)
1820 if (c >= 'a' && c <= 'z')
1822 if (c >= ' ' && c < 127)
1823 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1825 key = minput__char_to_key (c);
1827 else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1831 char *str = XKeysymToString (keysym);
1835 key = msymbol (str);
1836 if (((XKeyEvent *) event)->state & ShiftMask)
1837 *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1838 if (((XKeyEvent *) event)->state & ControlMask)
1839 *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1841 if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1842 *modifiers |= MINPUT_KEY_META_MODIFIER;
1843 if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1844 *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1845 if (((XKeyEvent *) event)->state & disp_info->super_mask)
1846 *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1847 if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1848 *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1855 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1857 unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1859 Display *display = FRAME_DISPLAY (frame);
1860 GCInfo *info = rface->info;
1863 for (i = 0; i <= GC_INVERSE; i++)
1865 XGetGCValues (display, info->gc[i], valuemask, &values);
1866 fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1867 values.foreground, values.background);
1868 fprintf (stderr, "\n");
1872 static MDeviceDriver x_driver =
1875 mwin__device_get_prop,
1877 mwin__free_realized_face,
1879 mwin__draw_empty_boxes,
1883 mwin__region_from_rect,
1884 mwin__union_rect_with_region,
1885 mwin__intersect_region,
1886 mwin__region_add_rect,
1887 mwin__region_to_rect,
1890 mwin__create_window,
1891 mwin__destroy_window,
1894 mwin__window_geometry,
1895 mwin__adjust_window,
1899 /* Functions to be stored in MDeviceLibraryInterface by dlsym (). */
1904 M_iso8859_1 = msymbol ("iso8859-1");
1905 M_iso10646_1 = msymbol ("iso10646-1");
1907 display_info_list = mplist ();
1908 device_list = mplist ();
1911 xft_driver.select = mfont__ft_driver.select;
1912 xft_driver.encode_char = mfont__ft_driver.encode_char;
1913 xft_driver.list = mfont__ft_driver.list;
1916 Mxim = msymbol ("xim");
1917 msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1925 M17N_OBJECT_UNREF (display_info_list);
1926 M17N_OBJECT_UNREF (device_list);
1930 /** Return an MWDevice object corresponding to a display specified in
1933 It searches device_list for a device matching the display. If
1934 found, return the found object. Otherwise, return a newly created
1938 device_open (MFrame *frame, MPlist *param)
1940 Display *display = NULL;
1941 Screen *screen = NULL;
1943 Drawable drawable = 0;
1944 Widget widget = NULL;
1946 int auto_display = 0;
1947 MDisplayInfo *disp_info = NULL;
1948 MWDevice *device = NULL;
1950 XWindowAttributes attr;
1955 int use_xfont = 0, use_freetype = 0, use_xft = 0;
1957 for (plist = param; (key = mplist_key (plist)) != Mnil;
1958 plist = mplist_next (plist))
1960 if (key == Mdisplay)
1961 display = (Display *) mplist_value (plist);
1962 else if (key == Mscreen)
1963 screen = mplist_value (plist);
1964 else if (key == Mdrawable)
1965 drawable = (Drawable) mplist_value (plist);
1966 else if (key == Mdepth)
1967 depth = (unsigned) mplist_value (plist);
1968 else if (key == Mwidget)
1969 widget = (Widget) mplist_value (plist);
1970 else if (key == Mcolormap)
1971 cmap = (Colormap) mplist_value (plist);
1972 else if (key == Mfont)
1974 MSymbol val = MPLIST_SYMBOL (plist);
1978 #ifdef HAVE_FREETYPE
1979 else if (val == Mfreetype)
1982 else if (val == Mxft)
1989 /* If none of them is specified, use all of them. */
1990 if (! use_xfont && ! use_freetype && ! use_xft)
1991 use_xfont = use_freetype = use_xft = 1;
1995 display = XtDisplay (widget);
1996 screen_num = XScreenNumberOfScreen (XtScreen (widget));
1997 depth = DefaultDepth (display, screen_num);
2003 unsigned width, height, border_width;
2006 MERROR (MERROR_WIN, -1);
2007 XGetGeometry (display, drawable, &root_window,
2008 &x, &y, &width, &height, &border_width, &depth);
2009 XGetWindowAttributes (display, root_window, &attr);
2010 screen_num = XScreenNumberOfScreen (attr.screen);
2015 display = DisplayOfScreen (screen);
2020 display = XOpenDisplay (NULL);
2022 MERROR (MERROR_WIN, -1);
2025 screen = DefaultScreenOfDisplay (display);
2027 screen_num = XScreenNumberOfScreen (screen);
2029 depth = DefaultDepth (display, screen_num);
2033 cmap = DefaultColormap (display, screen_num);
2035 for (plist = display_info_list; mplist_key (plist) != Mnil;
2036 plist = mplist_next (plist))
2038 disp_info = (MDisplayInfo *) mplist_value (plist);
2039 if (disp_info->display == display)
2043 if (mplist_key (plist) != Mnil)
2044 M17N_OBJECT_REF (disp_info);
2047 M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
2048 disp_info->display = display;
2049 disp_info->auto_display = auto_display;
2050 disp_info->font_list = mplist ();
2051 disp_info->base_font_list = mplist ();
2052 find_modifier_bits (disp_info);
2053 mplist_add (display_info_list, Mt, disp_info);
2056 for (plist = device_list; mplist_key (plist) != Mnil;
2057 plist = mplist_next (plist))
2059 device = (MWDevice *) mplist_value (plist);
2060 if (device->display_info == disp_info
2061 && device->depth == depth
2062 && device->cmap == cmap)
2066 if (mplist_key (plist) != Mnil)
2067 M17N_OBJECT_REF (device);
2070 unsigned long valuemask = GCForeground;
2073 M17N_OBJECT (device, free_device, MERROR_WIN);
2074 device->display_info = disp_info;
2075 device->screen_num = screen_num;
2076 /* A drawable on which to create GCs. */
2077 device->drawable = XCreatePixmap (display,
2078 RootWindow (display, screen_num),
2080 device->depth = depth;
2081 device->cmap = cmap;
2082 device->realized_face_list = mplist ();
2083 device->realized_font_list = mplist ();
2084 device->realized_fontset_list = mplist ();
2085 device->gc_list = mplist ();
2086 values.foreground = BlackPixel (display, screen_num);
2087 device->scratch_gc = XCreateGC (display, device->drawable,
2088 valuemask, &values);
2090 device->xft_draw = XftDrawCreate (display, device->drawable,
2091 DefaultVisual (display, screen_num),
2096 frame->device = device;
2097 frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2098 frame->driver = &x_driver;
2099 frame->font_driver_list = mplist ();
2103 mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2106 #endif /* HAVE_XFT2 */
2107 #ifdef HAVE_FREETYPE
2109 mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2110 #endif /* HAVE_FREETYPE */
2111 if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list))
2112 mplist_push (frame->font_driver_list, Mx, &xfont_driver);
2114 frame->realized_font_list = device->realized_font_list;
2115 frame->realized_face_list = device->realized_face_list;
2116 frame->realized_fontset_list = device->realized_fontset_list;
2120 XtResource resources[] = {
2121 { XtNfont, XtCFont, XtRString, sizeof (String),
2122 XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2123 { XtNforeground, XtCForeground, XtRString, sizeof (String),
2124 XtOffset (AppDataPtr, foreground), XtRString, "black" },
2125 { XtNbackground, XtCBackground, XtRString, sizeof (String),
2126 XtOffset (AppDataPtr, background), XtRString, "white" },
2127 { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2128 XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2131 XtGetApplicationResources (widget, &app_data,
2132 resources, XtNumber (resources), NULL, 0);
2133 frame->foreground = msymbol (app_data.foreground);
2134 frame->background = msymbol (app_data.background);
2135 frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2139 app_data.font = DEFAULT_FONT;
2140 frame->foreground = msymbol ("black");
2141 frame->background = msymbol ("white");
2142 frame->videomode = Mnormal;
2147 /* Try at least 32 fonts to obtain a non-autoscaled font. */
2148 char **names = XListFonts (display, app_data.font, 32, &nfonts);
2151 for (i = 0; ! font && i < nfonts; i++)
2153 font = mfont_parse_name (names[i], Mx);
2156 /* The font name does not conform to XLFD. Try to open the
2157 font and get XA_FONT property. */
2158 XFontStruct *xfont = XLoadQueryFont (display, names[i]);
2162 unsigned long value;
2165 if (XGetFontProperty (xfont, XA_FONT, &value)
2166 && (name = ((char *)
2167 XGetAtomName (display, (Atom) value))))
2168 font = mfont_parse_name (name, Mx);
2169 XFreeFont (display, xfont);
2173 font->property[MFONT_SIZE] == 0 && font->property[MFONT_RESY] > 0)
2180 XFreeFontNames (names);
2181 frame->font = font ? font : mfont_parse_name (FALLBACK_FONT, Mx);
2184 face = mface_from_font (frame->font);
2185 face->property[MFACE_FONTSET] = mfontset (NULL);
2186 face->property[MFACE_FOREGROUND] = frame->foreground;
2187 face->property[MFACE_BACKGROUND] = frame->background;
2188 mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2189 mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2190 face->property[MFACE_VIDEOMODE] = frame->videomode;
2191 mface_put_prop (face, Mhook_func,
2192 mface_get_prop (mface__default, Mhook_func));
2193 face->property[MFACE_RATIO] = (void *) 100;
2194 mplist_push (param, Mface, face);
2195 M17N_OBJECT_UNREF (face);
2197 #ifdef X_SET_ERROR_HANDLER
2198 XSetErrorHandler (x_error_handler);
2199 XSetIOErrorHandler (x_io_error_handler);
2207 /* XIM (X Input Method) handler */
2209 typedef struct MInputXIMMethodInfo
2215 } MInputXIMMethodInfo;
2217 typedef struct MInputXIMContextInfo
2221 MConverter *converter;
2222 } MInputXIMContextInfo;
2225 xim_open_im (MInputMethod *im)
2227 MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2228 MLocale *saved, *this;
2229 char *save_modifier_list;
2231 MInputXIMMethodInfo *im_info;
2233 saved = mlocale_set (LC_CTYPE, NULL);
2234 this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2236 /* The specified locale is not supported. */
2237 MERROR (MERROR_LOCALE, -1);
2238 if (mlocale_get_prop (this, Mcoding) == Mnil)
2240 /* Unable to decode the output of XIM. */
2241 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2242 MERROR (MERROR_LOCALE, -1);
2245 if (arg->modifier_list)
2246 save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2248 save_modifier_list = XSetLocaleModifiers ("");
2249 if (! save_modifier_list)
2251 /* The specified locale is not supported by X. */
2252 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2253 MERROR (MERROR_LOCALE, -1);
2256 xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2259 /* No input method is available in the current locale. */
2260 XSetLocaleModifiers (save_modifier_list);
2261 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2262 MERROR (MERROR_WIN, -1);
2265 MSTRUCT_MALLOC (im_info, MERROR_WIN);
2266 im_info->display = arg->display;
2268 im_info->language = mlocale_get_prop (this, Mlanguage);
2269 im_info->coding = mlocale_get_prop (this, Mcoding);
2272 XSetLocaleModifiers (save_modifier_list);
2273 mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2279 xim_close_im (MInputMethod *im)
2281 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2283 XCloseIM (im_info->xim);
2288 xim_create_ic (MInputContext *ic)
2290 MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2291 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2292 MInputXIMContextInfo *ic_info;
2295 if (! arg->input_style)
2297 /* By default, use Root style. */
2298 arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2299 arg->preedit_attrs = NULL;
2300 arg->status_attrs = NULL;
2303 if (! arg->preedit_attrs && ! arg->status_attrs)
2304 xic = XCreateIC (im_info->xim,
2305 XNInputStyle, arg->input_style,
2306 XNClientWindow, arg->client_win,
2307 XNFocusWindow, arg->focus_win,
2309 else if (arg->preedit_attrs && ! arg->status_attrs)
2310 xic = XCreateIC (im_info->xim,
2311 XNInputStyle, arg->input_style,
2312 XNClientWindow, arg->client_win,
2313 XNFocusWindow, arg->focus_win,
2314 XNPreeditAttributes, arg->preedit_attrs,
2316 else if (! arg->preedit_attrs && arg->status_attrs)
2317 xic = XCreateIC (im_info->xim,
2318 XNInputStyle, arg->input_style,
2319 XNClientWindow, arg->client_win,
2320 XNFocusWindow, arg->focus_win,
2321 XNStatusAttributes, arg->status_attrs,
2324 xic = XCreateIC (im_info->xim,
2325 XNInputStyle, arg->input_style,
2326 XNClientWindow, arg->client_win,
2327 XNFocusWindow, arg->focus_win,
2328 XNPreeditAttributes, arg->preedit_attrs,
2329 XNStatusAttributes, arg->status_attrs,
2332 MERROR (MERROR_WIN, -1);
2334 MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2336 ic_info->win = arg->focus_win;
2337 ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2343 xim_destroy_ic (MInputContext *ic)
2345 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2347 XDestroyIC (ic_info->xic);
2348 mconv_free_converter (ic_info->converter);
2354 xim_filter (MInputContext *ic, MSymbol key, void *event)
2356 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2358 return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2363 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2365 MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2366 MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2367 XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2373 buf = (char *) alloca (512);
2374 len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2375 if (status == XBufferOverflow)
2377 buf = (char *) alloca (len);
2378 len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2381 mtext_reset (ic->produced);
2385 mconv_reset_converter (ic_info->converter);
2386 mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2387 mconv_decode (ic_info->converter, ic->produced);
2388 mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2389 Mlanguage, (void *) im_info->language);
2390 mtext_cpy (mt, ic->produced);
2391 mtext_reset (ic->produced);
2397 #ifdef X_SET_ERROR_HANDLER
2399 x_error_handler (Display *display, XErrorEvent *error)
2406 x_io_error_handler (Display *display)
2416 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2420 /*** @addtogroup m17nInputMethodWin */
2425 @brief Input method driver for XIM.
2427 The driver #minput_xim_driver is for the foreign input method of
2428 name #Mxim. It uses XIM (X Input Methods) as a background input
2431 As the symbol #Mxim has property #Minput_driver whose value is
2432 a pointer to this driver, the input method of language #Mnil
2433 and name #Mxim uses this driver.
2435 Therefore, for such input methods, the driver dependent arguments
2436 to the functions whose name begin with minput_ must be as follows.
2438 The argument $ARG of the function minput_open_im () must be a
2439 pointer to the structure #MInputXIMArgIM. See the documentation
2440 of #MInputXIMArgIM for more details.
2442 The argument $ARG of the function minput_create_ic () must be a
2443 pointer to the structure #MInputXIMArgIC. See the documentation
2444 of #MInputXIMArgIC for more details.
2446 The argument $ARG of the function minput_filter () must be a
2447 pointer to the structure @c XEvent. The argument $KEY is ignored.
2449 The argument $ARG of the function minput_lookup () must be the
2450 same one as that of the function minput_filter (). The argument
2454 @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2456 ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
2457 ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
2460 ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2461 #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
2462 ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2464 ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
2465 ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2467 ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM ¤Ø¤Î¥Ý
2468 ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
2471 ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC ¤Ø¤Î
2472 ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
2475 ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2476 ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2478 ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter ()
2479 ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2482 MInputDriver minput_xim_driver =
2483 { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2484 xim_filter, xim_lookup, NULL };