(xfont_registry_list): Set font.for_full_width if the
[m17n/m17n-lib.git] / src / m17n-X.c
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
5
6    This file is part of the m17n library.
7
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.
12
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.
17
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
21    02111-1307, USA.  */
22
23 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
24 /*** @addtogroup m17nInternal
25      @{ */
26
27 #include "config.h"
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32 #include <string.h>
33 #include <locale.h>
34
35 #include <X11/Xlib.h>
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>
43
44 #ifdef HAVE_XFT2
45 #include <X11/Xft/Xft.h>
46 #include <fontconfig/fcfreetype.h>
47 #endif  /* HAVE_XFT2 */
48
49 #include "m17n-gui.h"
50 #include "m17n-X.h"
51 #include "m17n-misc.h"
52 #include "internal.h"
53 #include "internal-gui.h"
54 #include "symbol.h"
55 #include "input.h"
56 #include "font.h"
57 #include "fontset.h"
58 #include "face.h"
59
60 typedef struct _MFontX MFontX;
61
62 struct _MFontX 
63 {
64   /* Record a font of the smallest pixel size.  */
65   MFont core;
66   /* Nth bit tells the existence of a font of size N + 5.  So this is
67      for 5..36 pixel size fonts.  Usually this covers all sizes.  */
68   unsigned int size5_36;
69   /* Fonts of (size < 5 || size > 36) are listed here (except for a
70      scalable whose size is 0).  */
71   MFontX *next;
72 };
73
74 /* S must satisfy the condition (S >= 5 && S < 36).  */
75
76 #define SET_SIZE(FONTX, S) ((FONTX)->size5_36 |= (1 << ((S) - 5)))
77
78 #define HAVE_SIZE(FONTX, S) ((FONTX)->size5_36 & (1 << ((S) - 5)))
79
80 typedef struct
81 {
82   /* Common header for the m17n object.  */
83   M17NObject control;
84
85   Display *display;
86
87   /* If nonzero, <display> is opened by this library.  Thus it should
88      be closed on freeing this structure.  */
89   int auto_display;
90
91   /** List of available X-core fonts on the display.  Keys are
92       registries and values are plists whose keys are families and
93       values are pointers to MFontX.  */
94   MPlist *font_list;
95
96   /** Nonzero means that <font_list> already contains all available
97       fonts on the display.  */
98   int all_fonts_scaned;
99
100  /** Modifier bit masks of the display.  */
101   int meta_mask;
102   int alt_mask;
103   int super_mask;
104   int hyper_mask;
105 } MDisplayInfo;
106
107 /* Anchor of the chain of MDisplayInfo objects.  */
108 static MPlist *display_info_list;
109
110
111 /* Color value and the corresponding GC.  */
112 typedef struct
113 {
114   unsigned int rgb;            /* (red << 16) | (green << 8) | blue */
115   GC gc;
116 } RGB_GC;
117
118 enum gc_index
119   {
120     GC_INVERSE,
121     GC_NORMAL = GC_INVERSE + 7,
122     GC_HLINE,
123     GC_BOX_TOP,
124     GC_BOX_BOTTOM,
125     GC_BOX_LEFT,
126     GC_BOX_RIGHT,
127     GC_MAX
128   };
129
130 typedef struct
131 {
132   int rgb_fore;
133   int rgb_back;
134   /* The first 8 elements are indexed by an intensity for
135      anti-aliasing.  The 2nd to 7th are created on demand.  */
136   GC gc[GC_MAX];
137 #ifdef HAVE_XFT2
138   XftColor xft_color_fore, xft_color_back;
139 #endif
140 } GCInfo;
141
142 typedef struct
143 {
144   /* Common header for the m17n object.  */
145   M17NObject control;
146
147   MDisplayInfo *display_info;
148
149   int screen_num;
150
151   Drawable drawable;
152
153   unsigned depth;
154
155   Colormap cmap;
156
157   GC scratch_gc;
158
159   int resy;
160
161 #ifdef HAVE_XFT2
162   XftDraw *xft_draw;
163 #endif
164
165   /** List of pointers to realized faces on the frame.  */
166   MPlist *realized_face_list;
167
168   /* List of single element whose value is a root of chain of realized
169      fonts.  */
170   MPlist *realized_font_list;
171
172   /** List of pointers to realized fontsets on the frame.  */
173   MPlist *realized_fontset_list;
174
175   /** List of XColors vs GCs on the frame.  */
176   MPlist *gc_list;
177 } MWDevice;
178
179 static MPlist *device_list;
180
181 static MSymbol M_iso8859_1, M_iso10646_1;
182
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))
189
190 #define DEFAULT_FONT "-*-*-medium-r-normal--13-*-*-*-c-*-iso8859-1"
191
192 typedef struct
193 {
194   String font;
195   String foreground;
196   String background;
197   Boolean reverse_video;
198 } AppData, *AppDataPtr;
199
200 static void
201 free_display_info (void *object)
202 {
203   MDisplayInfo *disp_info = (MDisplayInfo *) object;
204   MPlist *plist, *pl;
205
206   MPLIST_DO (plist, disp_info->font_list)
207     {
208       MPLIST_DO (pl, MPLIST_VAL (plist))
209         {
210           MFontX *fontx, *next;
211
212           for (fontx = MPLIST_VAL (pl); fontx; fontx = next)
213             {
214               next = fontx->next;
215               free (fontx);
216             }
217         }
218       M17N_OBJECT_UNREF (MPLIST_VAL (plist));
219     }
220   M17N_OBJECT_UNREF (disp_info->font_list);
221
222   if (disp_info->auto_display)
223     XCloseDisplay (disp_info->display);
224
225   free (object);
226 }
227
228 static void
229 free_device (void *object)
230 {
231   MWDevice *device = object;
232   MPlist *plist;
233
234   for (plist = device->realized_fontset_list;
235        mplist_key (plist) != Mnil; plist = mplist_next (plist))
236     mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist));
237   M17N_OBJECT_UNREF (device->realized_fontset_list);
238
239   if (MPLIST_VAL (device->realized_font_list))
240     mfont__free_realized (MPLIST_VAL (device->realized_font_list));
241   M17N_OBJECT_UNREF (device->realized_font_list);
242
243   MPLIST_DO (plist, device->realized_face_list)
244     {
245       MRealizedFace *rface = MPLIST_VAL (plist);
246
247       free (rface->info);
248       mface__free_realized (rface);
249     }
250   M17N_OBJECT_UNREF (device->realized_face_list);
251
252   MPLIST_DO (plist, device->gc_list)
253     {
254       XFreeGC (device->display_info->display,
255                ((RGB_GC *) MPLIST_VAL (plist))->gc);
256       free (MPLIST_VAL (plist));
257     }
258   M17N_OBJECT_UNREF (device->gc_list);
259   XFreeGC (device->display_info->display, device->scratch_gc);
260
261 #ifdef HAVE_XFT2
262   XftDrawDestroy (device->xft_draw);
263 #endif
264
265   XFreePixmap (device->display_info->display, device->drawable);
266   M17N_OBJECT_UNREF (device->display_info);
267   free (object);
268 }
269
270
271 static void
272 find_modifier_bits (MDisplayInfo *disp_info)
273 {
274   Display *display = disp_info->display;
275   XModifierKeymap *mods;
276   KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L);
277   KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R);
278   KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L);
279   KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R);
280   KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
281   KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
282   KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
283   KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
284   int i, j;
285
286   mods = XGetModifierMapping (display);
287   /* We skip the first three sets for Shift, Lock, and Control.  The
288      remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5.  */
289   for (i = 3; i < 8; i++)
290     for (j = 0; j < mods->max_keypermod; j++)
291       {
292         KeyCode code = mods->modifiermap[i * mods->max_keypermod + j];
293
294         if (! code)
295           continue;
296         if (code == meta_l || code == meta_r)
297           disp_info->meta_mask |= (1 << i);
298         else if (code == alt_l || code == alt_r)
299           disp_info->alt_mask |= (1 << i);
300         else if (code == super_l || code == super_r)
301           disp_info->super_mask |= (1 << i);
302         else if (code == hyper_l || code == hyper_r)
303           disp_info->hyper_mask |= (1 << i);
304       }
305
306   /* If meta keys are not in any modifier, use alt keys as meta
307      keys.  */
308   if (! disp_info->meta_mask)
309     {
310       disp_info->meta_mask = disp_info->alt_mask;
311       disp_info->alt_mask = 0;
312     }
313   /* If both meta and alt are assigned to the same modifier, give meta
314      keys priority.  */
315   if (disp_info->meta_mask & disp_info->alt_mask)
316     disp_info->alt_mask &= ~disp_info->meta_mask;
317
318   XFreeModifiermap (mods);
319 }
320
321 static RGB_GC *
322 get_rgb_gc (MWDevice *device, XColor *xcolor)
323 {
324   int rgb = (((xcolor->red >> 8) << 16) | ((xcolor->green >> 8) << 8)
325              | (xcolor->blue >> 8));
326   MPlist *plist;
327   RGB_GC *rgb_gc;
328   unsigned long valuemask = GCForeground;
329   XGCValues values;
330
331   MPLIST_DO (plist, device->gc_list)
332     {
333       rgb_gc = MPLIST_VAL (plist);
334
335       if (rgb_gc->rgb == rgb)
336         return rgb_gc;
337       if (rgb_gc->rgb > rgb)
338         break;
339     }
340
341   if (! XAllocColor (device->display_info->display, device->cmap, xcolor))
342     return NULL;
343
344   rgb_gc = malloc (sizeof (RGB_GC));
345   rgb_gc->rgb = rgb;
346   values.foreground = xcolor->pixel;
347   rgb_gc->gc = XCreateGC (device->display_info->display,
348                           device->drawable, valuemask, &values);
349   mplist_push (plist, Mt, rgb_gc);
350   return rgb_gc;
351 }
352
353 static GC
354 get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret)
355 {
356   MWDevice *device = FRAME_DEVICE (frame);
357   XColor xcolor;
358   RGB_GC *rgb_gc;
359
360   if (color == Mnil)
361     {
362       if (frame->rface)
363         goto no_color;
364       color = for_foreground ? frame->foreground : frame->background;
365     }
366   if (! XParseColor (FRAME_DISPLAY (frame), device->cmap,
367                      msymbol_name (color), &xcolor))
368     goto no_color;
369   rgb_gc = get_rgb_gc (device, &xcolor);
370   if (! rgb_gc)
371     goto no_color;
372   if (rgb_ret)
373     *rgb_ret = rgb_gc->rgb;
374   return rgb_gc->gc;
375
376  no_color:
377   {
378     GCInfo *info = frame->rface->info;
379     GC gc;
380     int rgb;
381
382     if (for_foreground)
383       rgb = info->rgb_fore, gc = info->gc[GC_NORMAL];
384     else
385       rgb = info->rgb_back, gc = info->gc[GC_INVERSE];
386     if (rgb_ret)
387       *rgb_ret = rgb;
388     return gc;
389   }
390 }
391
392 static GC
393 get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity)
394 {
395   int rgb_fore, rgb_back;
396   XColor xcolor;
397   RGB_GC *rgb_gc;
398   GC gc;
399
400   if (info->gc[intensity])
401     return info->gc[intensity];
402
403   rgb_fore = info->rgb_fore, rgb_back = info->rgb_back;
404   xcolor.red = ((((rgb_fore & 0xFF0000) >> 16) * intensity
405                  + ((rgb_back & 0xFF0000) >> 16) * (7 - intensity)) / 7) << 8;
406   xcolor.green = ((((rgb_fore & 0xFF00) >> 8) * intensity
407                    + ((rgb_back & 0xFF00) >> 8) * (7 - intensity)) / 7) << 8;
408   xcolor.blue = (((rgb_fore & 0xFF) * intensity
409                   + (rgb_back & 0xFF) * (7 - intensity)) / 7) << 8;
410   rgb_gc = get_rgb_gc (device, &xcolor);
411   if (rgb_gc)
412     gc = rgb_gc->gc;
413   else
414     gc =get_gc_for_anti_alias (device, info,
415                                intensity < 4 ? intensity - 1 : intensity + 1);
416   return (info->gc[intensity] = gc);
417 }
418
419 static GC
420 set_region (MFrame *frame, GC gc, MDrawRegion region)
421 {
422   unsigned long valuemask = GCForeground;
423
424   XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
425            FRAME_DEVICE (frame)->scratch_gc);
426   XSetRegion (FRAME_DISPLAY (frame), FRAME_DEVICE (frame)->scratch_gc, region);
427   return FRAME_DEVICE (frame)->scratch_gc;
428 }
429
430 \f
431 /** X font handler */
432
433 static MFont *xfont_select (MFrame *, MFont *, int);
434 static MRealizedFont *xfont_open (MFrame *, MFont *, MFont *, MRealizedFont *);
435 static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int);
436 static int xfont_has_char (MFrame *, MFont *, MFont *, int, unsigned);
437 static unsigned xfont_encode_char (MFrame *, MFont *, MFont *, unsigned);
438 static void xfont_render (MDrawWindow, int, int, MGlyphString *,
439                           MGlyph *, MGlyph *, int, MDrawRegion);
440 static int xfont_list (MFrame *, MPlist *, MFont *, int);
441
442
443 static MFontDriver xfont_driver =
444   { xfont_select, xfont_open,
445     xfont_find_metric, xfont_has_char, xfont_encode_char,
446     xfont_render, xfont_list };
447
448 static int
449 font_compare (const void *p1, const void *p2)
450 {
451   return strcmp (*(char **) p1, *(char **) p2);
452 }
453
454 static MPlist *
455 xfont_registry_list (MFrame *frame, MSymbol registry)
456 {
457   MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
458   MPlist *font_list = disp_info->font_list;
459   MPlist *plist, *p;
460   char pattern[1024];
461   char **font_names, **names;
462   int nfonts;
463   int i, j;
464   MFont font;
465   int for_full_width;
466
467   plist = mplist_get (font_list, registry);
468   if (plist)
469     return plist;
470   plist = mplist ();
471   mplist_add (font_list, registry, plist);
472   sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", msymbol_name (registry));
473   font_names = XListFonts (disp_info->display, pattern, 0x8000, &nfonts);
474   if (nfonts == 0)
475     return plist;
476   {
477     char *reg_name = msymbol_name (registry);
478
479     for_full_width = (strncmp (reg_name, "jis", 3) == 0
480                       || strncmp (reg_name, "gb", 2) == 0
481                       || strncmp (reg_name, "big5", 4) == 0
482                       || strncmp (reg_name, "ksc", 3) == 0);
483   }
484   names = alloca (sizeof (char *) * nfonts);
485   memcpy (names, font_names, sizeof (char *) * nfonts);
486   qsort (names, nfonts, sizeof (char *), font_compare);
487   MFONT_INIT (&font);
488   for (i = 0, p = NULL; i < nfonts; i++)
489     if (mfont__parse_name_into_font (names[i], Mx, &font) == 0
490         && (font.size >= 50 || font.property[MFONT_RESY] == 0))
491       {
492         MSymbol family = FONT_PROPERTY (&font, MFONT_FAMILY);
493         MFontX *fontx, *fontx2;
494         unsigned sizes[256];
495         int nsizes = 0;
496         int size, smallest;
497         char *base_end;
498         int base_len;
499         int fields;
500         
501         if (p && MPLIST_KEY (p) != family)
502           p = mplist_find_by_key (plist, family);
503         if (! p)
504           p = mplist_push (plist, family, NULL);
505
506         /* Calculate how many bytes to compare to detect fonts of the
507            same base name.  */
508         for (base_end = names[i], fields = 0; *base_end; base_end++)
509           if (*base_end == '-'
510               && ++fields == 7  /* PIXEL_SIZE */)
511             break;
512         base_len = base_end - names[i] + 1;
513
514         size = smallest = font.size / 10;
515         sizes[nsizes++] = size;
516         for (j = i + 1; j < nfonts && ! strncmp (names[i], names[j], base_len);
517              i = j++)
518           if (mfont__parse_name_into_font (names[j], Mx, &font) == 0
519               && (font.size >= 50 || font.property[MFONT_RESY] == 0))
520             {
521               size = font.size / 10;
522               if (size < smallest)
523                 smallest = size;
524               if (nsizes < 256)
525                 sizes[nsizes++] = size;
526             }
527
528         font.for_full_width = for_full_width;
529         font.type = MFONT_TYPE_OBJECT;
530         font.source = MFONT_SOURCE_X;
531         MSTRUCT_CALLOC (fontx, MERROR_WIN);
532         fontx->core = font;
533         fontx->core.size = smallest * 10;
534         fontx->next = MPLIST_VAL (p);
535         MPLIST_VAL (p) = fontx;
536         if (smallest > 0)
537           for (j = 0; j < nsizes; j++)
538             {
539               if (sizes[j] <= 36)
540                 {
541                   if (sizes[j] != smallest)
542                     SET_SIZE (fontx, sizes[j]);
543                 }
544               else
545                 {
546                   MSTRUCT_CALLOC (fontx2, MERROR_WIN);
547                   fontx2->core = font;
548                   fontx2->core.size = sizes[j] * 10;
549                   fontx2->next = MPLIST_VAL (p);
550                   MPLIST_VAL (p) = fontx2;
551                 }
552             }
553       }
554   XFreeFontNames (font_names);
555   return plist;
556 }
557
558 static void
559 xfont_list_all (MFrame *frame)
560 {
561   MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
562   MPlist *font_encoding_list, *p;
563
564   if (disp_info->all_fonts_scaned)
565     return;
566   disp_info->all_fonts_scaned = 1;
567   font_encoding_list = mfont__encoding_list ();
568   if (! font_encoding_list)
569     return;
570   MPLIST_DO (p, font_encoding_list)
571     xfont_registry_list (frame, MPLIST_KEY (p));
572 }
573
574 typedef struct
575 {
576   M17NObject control;
577   Display *display;
578   XFontStruct *xfont;
579 } MRealizedFontX;
580
581 /* The X font driver function SELECT.  */
582
583 static MFont *
584 xfont_select (MFrame *frame, MFont *font, int limited_size)
585 {
586   MPlist *plist = mplist (), *pl;
587   int num = xfont_list (frame, plist, font, 0);
588   MFont *found = NULL;
589
590   if (num > 0)
591     MPLIST_DO (pl, plist)
592       {
593         font = MPLIST_VAL (pl);
594         if (limited_size == 0
595             || font->size == 0
596             || font->size <= limited_size)
597           {
598             found = font;
599             break;
600           }
601       }
602   M17N_OBJECT_UNREF (plist);
603   return found;
604 }
605
606 /* The X font driver function CLOSE.  */
607
608 static void
609 close_xfont (void *object)
610 {
611   MRealizedFontX *x_rfont = object;
612
613   XFreeFont (x_rfont->display, x_rfont->xfont);
614   free (x_rfont);
615 }
616
617 /* The X font driver function OPEN.  */
618
619 static MRealizedFont *
620 xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
621 {
622   int size = spec->size;
623   MRealizedFontX *x_rfont;
624   char *name;
625   Display *display = FRAME_DISPLAY (frame);
626   XFontStruct *xfont;
627   int mdebug_mask = MDEBUG_FONT;
628   MFont this;
629
630   if (rfont)
631     {
632       for (; rfont; rfont = rfont->next)
633         if (rfont->font == font && rfont->spec.size == size)
634           return rfont;
635     }
636
637   this = *font;
638   this.size = size;
639   /* This never fail to generate a valid fontname.  */
640   name = mfont_unparse_name (&this, Mx);
641   xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
642   if (! xfont)
643     {
644       MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
645       free (name);
646       font->type = MFONT_TYPE_FAILURE;
647       return NULL;
648     }
649   MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
650   free (name);
651   M17N_OBJECT (x_rfont, close_xfont, MERROR_FONT_X);
652   x_rfont->display = display;
653   x_rfont->xfont = xfont;
654   MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
655   rfont->spec = this;
656   rfont->spec.type = MFONT_TYPE_REALIZED;
657   rfont->spec.source = MFONT_SOURCE_X;
658   rfont->frame = frame;
659   rfont->font = font;
660   rfont->driver = &xfont_driver;
661   rfont->info = x_rfont;
662   rfont->ascent = xfont->ascent;
663   rfont->descent = xfont->descent;
664   rfont->max_advance = xfont->max_bounds.width;
665   rfont->fontp = xfont;
666   rfont->next = MPLIST_VAL (frame->realized_font_list);
667   MPLIST_VAL (frame->realized_font_list) = rfont;
668   return rfont;
669 }
670
671
672 /* The X font driver function FIND_METRIC.  */
673
674 static void
675 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
676                    int from, int to)
677 {
678   XFontStruct *xfont = rfont->fontp;
679   MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
680
681   for (; g != gend; g++)
682     {
683       if (g->code == MCHAR_INVALID_CODE)
684         {
685           g->lbearing = xfont->max_bounds.lbearing;
686           g->rbearing = xfont->max_bounds.rbearing;
687           g->width = xfont->max_bounds.width;
688           g->ascent = xfont->ascent;
689           g->descent = xfont->descent;
690         }
691       else
692         {
693           int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
694           XCharStruct *pcm = NULL;
695
696           if (xfont->per_char != NULL)
697             {
698               if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
699                 {
700                   if (byte1 == 0
701                       && byte2 >= xfont->min_char_or_byte2
702                       && byte2 <= xfont->max_char_or_byte2)
703                     pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
704                 }
705               else
706                 {
707                   if (byte1 >= xfont->min_byte1
708                       && byte1 <= xfont->max_byte1
709                       && byte2 >= xfont->min_char_or_byte2
710                       && byte2 <= xfont->max_char_or_byte2)
711                     {
712                       pcm = (xfont->per_char
713                              + ((xfont->max_char_or_byte2
714                                  - xfont->min_char_or_byte2 + 1)
715                                 * (byte1 - xfont->min_byte1))
716                              + (byte2 - xfont->min_char_or_byte2));
717                     }
718                 }
719             }
720
721           if (pcm)
722             {
723               g->lbearing = pcm->lbearing;
724               g->rbearing = pcm->rbearing;
725               g->width = pcm->width;
726               g->ascent = pcm->ascent;
727               g->descent = pcm->descent;
728             }
729           else
730             {
731               /* If the per_char pointer is null, all glyphs between
732                  the first and last character indexes inclusive have
733                  the same information, as given by both min_bounds and
734                  max_bounds.  */
735               g->lbearing = 0;
736               g->rbearing = xfont->max_bounds.width;
737               g->width = xfont->max_bounds.width;
738               g->ascent = xfont->ascent;
739               g->descent = xfont->descent;
740             }
741         }
742     }
743 }
744
745
746 static int
747 xfont_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
748 {
749   return (xfont_encode_char (frame, font, spec, code) != MCHAR_INVALID_CODE);
750 }
751
752 /* The X font driver function GET_GLYPH_ID.  */
753
754 static unsigned
755 xfont_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
756 {
757   MRealizedFont *rfont;
758   XFontStruct *xfont;
759   unsigned min_byte1, max_byte1, min_byte2, max_byte2;
760   int all_chars_exist;
761
762   if (font->type == MFONT_TYPE_REALIZED)
763     rfont = (MRealizedFont *) font;
764   else if (font->type == MFONT_TYPE_OBJECT)
765     {
766       int size = spec->size;
767
768       for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
769            rfont = rfont->next)
770         if (rfont->font == font && rfont->spec.size == size)
771           break;
772       if (! rfont)
773         {
774           rfont = xfont_open (frame, font, spec, NULL);
775           if (! rfont)
776             return MCHAR_INVALID_CODE;
777         }
778     }
779   else
780     MFATAL (MERROR_FONT_X);
781   xfont = rfont->fontp;
782   all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
783   min_byte1 = xfont->min_byte1;
784   max_byte1 = xfont->max_byte1;
785   min_byte2 = xfont->min_char_or_byte2;
786   max_byte2 = xfont->max_char_or_byte2;
787
788   if (min_byte1 == 0 && max_byte1 == 0)
789     {
790       XCharStruct *pcm;
791
792       if (code < min_byte2 || code > max_byte2)
793         return MCHAR_INVALID_CODE;
794       if (all_chars_exist)
795         return code;
796       pcm = xfont->per_char + (code - min_byte2);
797       return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
798               ? code : MCHAR_INVALID_CODE);
799     }
800   else
801     {
802       unsigned byte1 = code >> 8, byte2 = code & 0xFF;
803       XCharStruct *pcm;
804
805       if (byte1 < min_byte1 || byte1 > max_byte1
806           || byte2 < min_byte2 || byte2 > max_byte2)
807         return MCHAR_INVALID_CODE;
808
809       if (all_chars_exist)
810         return code;
811       pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
812                            + (byte2 - min_byte2));
813       return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
814               ? code : MCHAR_INVALID_CODE);
815     }
816 }
817
818 /* The X font driver function RENDER.  */
819
820 static void
821 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
822               MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
823 {
824   MRealizedFace *rface = from->rface;
825   Display *display = FRAME_DISPLAY (rface->frame);
826   XChar2b *code;
827   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
828   MGlyph *g;
829   int i;
830
831   if (from == to)
832     return;
833
834   if (region)
835     gc = set_region (rface->frame, gc, region);
836   XSetFont (display, gc, ((XFontStruct *) rface->rfont->fontp)->fid);
837   code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
838   for (i = 0, g = from; g < to; i++, g++)
839     {
840       code[i].byte1 = g->code >> 8;
841       code[i].byte2 = g->code & 0xFF;
842     }
843
844   g = from;
845   while (g < to)
846     {
847       if (g->type == GLYPH_PAD)
848         x += g++->width;
849       else if (g->type == GLYPH_SPACE)
850         for (; g < to && g->type == GLYPH_SPACE; g++)
851           x += g->width;
852       else if (! g->rface->rfont)
853         {
854           if ((g->c >= 0x200B && g->c <= 0x200F)
855               || (g->c >= 0x202A && g->c <= 0x202E))
856             x += g++->width;
857           else
858             {
859               /* As a font is not found for this character, draw an
860                  empty box.  */
861               int box_width = g->width;
862               int box_height = gstring->ascent + gstring->descent;
863
864               if (box_width > 4)
865                 box_width -= 2;
866               if (box_height > 4)
867                 box_height -= 2;
868               XDrawRectangle (display, (Window) win, gc,
869                               x, y - gstring->ascent, box_width, box_height);
870               x += g++->width;
871             }
872         }
873       else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
874         {
875           XDrawString16 (display, (Window) win, gc,
876                          x + g->xoff, y + g->yoff, code + (g - from), 1);
877           x += g->width;
878           g++;
879         }
880       else
881         {
882           int orig_x = x;
883           int code_idx = g - from;
884
885           for (i = 0;
886                g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
887                i++, g++)
888               x += g->width;
889           XDrawString16 (display, (Window) win, gc, orig_x, y,
890                          code + code_idx, i);
891         }
892     }
893 }
894
895 static int
896 xfont_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum)
897 {
898   MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
899   MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil;
900   MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil;
901   int size = font ? font->size : 0;
902   MPlist *pl, *p;
903   int num = 0;
904   int mdebug_mask = MDEBUG_FONT;
905
906   MDEBUG_PRINT2 (" [X-FONT] listing %s-%s...",
907                  family ? msymbol_name (family) : "*",
908                  registry ? msymbol_name (registry) : "*");
909
910   if (registry == Mnil)
911     xfont_list_all (frame);
912   else
913     xfont_registry_list (frame, registry);
914
915   MPLIST_DO (pl, disp_info->font_list)
916     {
917       if (registry != Mnil && registry != MPLIST_KEY (pl))
918         continue;
919       MPLIST_DO (p, MPLIST_VAL (pl))
920         {
921           MFontX *fontx;
922
923           if (family != Mnil && family != MPLIST_KEY (p))
924             continue;
925           for (fontx = MPLIST_VAL (p); fontx; fontx = fontx->next)
926             if (! font
927                 || (mfont__match_p (&fontx->core, font, MFONT_REGISTRY)))
928               {
929                 if (fontx->core.size == size
930                     || fontx->core.size == 0)
931                   {
932                     mplist_push (plist, MPLIST_KEY (p), fontx);
933                     num++;
934                   }
935                 else if (size == 0
936                          || (size <= 360 && HAVE_SIZE (fontx, (size / 10))))
937                   {
938                     unsigned size5_36 = fontx->size5_36;
939                     MFontX *fontx2;
940                     int i;
941
942                     fontx->size5_36 = 0;
943                     for (i = fontx->core.size / 10; i <= 36; i++)
944                       if (size5_36 & (1 << (i - 5)))
945                         {
946                           MSTRUCT_CALLOC (fontx2, MERROR_WIN);
947                           fontx2->core = fontx->core;
948                           fontx2->core.size = i * 10;
949                           fontx2->next = fontx->next;
950                           fontx->next = fontx2;
951                           fontx = fontx2;
952                           if ((size == 0 || size == fontx->core.size)
953                               && (maxnum == 0 || num < maxnum))
954                             {
955                               mplist_push (plist, MPLIST_KEY (p), fontx);
956                               num++;
957                             }
958                         }
959                   }
960                 if (maxnum > 0 && maxnum == num)
961                   break;
962               }
963           if (maxnum > 0 && maxnum == num)
964             break;
965         }
966       if (maxnum > 0 && maxnum == num)
967         break;
968     }
969
970   MDEBUG_PRINT1 (" %d found\n", num);
971   return num;
972 }
973
974 \f
975 /* Xft Handler */
976
977 #ifdef HAVE_XFT2
978
979 typedef struct
980 {
981   M17NObject control;
982   Display *display;
983   XftFont *font_aa;
984   XftFont *font_no_aa;
985   FT_Face ft_face;
986   /* Pointer to MRealizedFontFT */
987   void *info;
988 } MRealizedFontXft;
989
990 static MRealizedFont *xft_open (MFrame *frame, MFont *font, MFont *spec,
991                                 MRealizedFont *);
992 static int xft_has_char (MFrame *frame, MFont *font, MFont *spec,
993                          int c, unsigned code);
994 static unsigned xft_encode_char (MFrame *frame, MFont *font, MFont *spec,
995                                  unsigned code);
996 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
997 static void xft_render (MDrawWindow, int, int, MGlyphString *,
998                         MGlyph *, MGlyph *, int, MDrawRegion);
999
1000 MFontDriver xft_driver =
1001   { NULL, xft_open,
1002     xft_find_metric, xft_has_char, xft_encode_char, xft_render, NULL };
1003
1004 static void
1005 close_xft (void *object)
1006 {
1007   MRealizedFontXft *rfont_xft = object;
1008
1009   if (rfont_xft->font_aa)
1010     XftFontClose (rfont_xft->display, rfont_xft->font_aa);
1011   if (rfont_xft->font_no_aa)
1012     XftFontClose (rfont_xft->display, rfont_xft->font_no_aa);
1013   M17N_OBJECT_UNREF (rfont_xft->info);
1014   free (rfont_xft);
1015 }
1016
1017
1018 static XftFont *
1019 xft_open_font (Display *display, MSymbol file, double size,
1020                FcBool anti_alias)
1021 {
1022   FcPattern *pattern;
1023   XftFont *font;
1024
1025   pattern = FcPatternCreate ();
1026   FcPatternAddString (pattern, FC_FILE, (FcChar8 *) msymbol_name (file));
1027   FcPatternAddDouble (pattern, FC_PIXEL_SIZE, size);
1028   FcPatternAddBool (pattern, FC_ANTIALIAS, anti_alias);
1029   font = XftFontOpenPattern (display, pattern);
1030   return font;
1031 }
1032
1033
1034 static MRealizedFont *
1035 xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
1036 {
1037   Display *display = FRAME_DISPLAY (frame);
1038   int reg = spec->property[MFONT_REGISTRY];
1039   FT_Face ft_face;
1040   MRealizedFontXft *rfont_xft;
1041   FcBool anti_alias = FRAME_DEVICE (frame)->depth > 1 ? FcTrue : FcFalse;
1042   double size = font->size ? font->size : spec->size;
1043   XftFont *xft_font;
1044
1045   if (rfont)
1046     {
1047       MRealizedFont *save = NULL;
1048
1049       for (; rfont; rfont = rfont->next)
1050         if (rfont->font == font
1051             && (rfont->font->size ? rfont->font->size == size
1052                 : rfont->spec.size == size)
1053             && rfont->spec.property[MFONT_REGISTRY] == reg)
1054           {
1055             if (! save)
1056               save = rfont;
1057             if (rfont->driver == &xft_driver)
1058               return rfont;
1059           }
1060       rfont = save;
1061     }
1062   rfont = (mfont__ft_driver.open) (frame, font, spec, rfont);
1063   if (! rfont)
1064     return NULL;
1065   spec = &rfont->spec;
1066   ft_face = rfont->fontp;
1067   xft_font = xft_open_font (display, font->file, size / 10, anti_alias);
1068   if (! xft_font)
1069     return NULL;
1070   M17N_OBJECT (rfont_xft, close_xft, MERROR_WIN);
1071   rfont_xft->display = display;
1072   if (anti_alias == FcTrue)
1073     rfont_xft->font_aa = xft_font;
1074   else
1075     rfont_xft->font_no_aa = xft_font;
1076   rfont_xft->ft_face = ft_face;
1077   rfont_xft->info = rfont->info;
1078   M17N_OBJECT_REF (rfont->info);
1079   MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
1080   rfont->spec = *spec;
1081   rfont->frame = frame;
1082   rfont->font = font;
1083   rfont->driver = &xft_driver;
1084   rfont->info = rfont_xft;
1085   rfont->ascent = ft_face->size->metrics.ascender >> 6;
1086   rfont->descent = - ft_face->size->metrics.descender >> 6;
1087   rfont->max_advance = ft_face->size->metrics.max_advance >> 6;
1088   rfont->fontp = xft_font;
1089   rfont->next = MPLIST_VAL (frame->realized_font_list);
1090   MPLIST_VAL (frame->realized_font_list) = rfont;
1091   return rfont;
1092 }
1093
1094 static void
1095 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1096                 int from, int to)
1097 {
1098   Display *display = FRAME_DISPLAY (rfont->frame);
1099   XftFont *xft_font = rfont->fontp;
1100   MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1101
1102   for (; g != gend; g++)
1103     {
1104       if (g->code == MCHAR_INVALID_CODE)
1105         {
1106           g->lbearing = 0;
1107           g->rbearing = xft_font->max_advance_width;
1108           g->width = g->rbearing;
1109           g->ascent = xft_font->ascent;
1110           g->descent = xft_font->descent;
1111         }
1112       else
1113         {
1114           XGlyphInfo extents;
1115
1116           XftGlyphExtents (display, xft_font, &g->code, 1, &extents);
1117           g->lbearing = - extents.x;
1118           g->rbearing = extents.width - extents.x;
1119           g->width = extents.xOff;
1120           g->ascent = extents.y;
1121           g->descent = extents.height - extents.y;
1122         }
1123     }
1124 }
1125
1126 static int
1127 xft_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
1128 {
1129   int result;
1130
1131   if (font->type == MFONT_TYPE_REALIZED)
1132     {
1133       MRealizedFont *rfont = (MRealizedFont *) font;
1134       MRealizedFontXft *rfont_xft = rfont->info;
1135       
1136       rfont->info = rfont_xft->info;
1137       result = mfont__ft_driver.has_char (frame, font, spec, c, code);
1138       rfont->info = rfont_xft;
1139     }
1140   else
1141     result = mfont__ft_driver.has_char (frame, font, spec, c, code);
1142   return result;
1143 }
1144
1145 static unsigned
1146 xft_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
1147 {
1148   if (font->type == MFONT_TYPE_REALIZED)
1149     {
1150       MRealizedFont *rfont = (MRealizedFont *) font;
1151       MRealizedFontXft *rfont_xft = rfont->info;
1152       
1153       rfont->info = rfont_xft->info;
1154       code = mfont__ft_driver.encode_char (frame, font, spec, code);
1155       rfont->info = rfont_xft;
1156     }
1157   else
1158     code = mfont__ft_driver.encode_char (frame, font, spec, code);
1159   return code;
1160 }
1161
1162 static void 
1163 xft_render (MDrawWindow win, int x, int y,
1164             MGlyphString *gstring, MGlyph *from, MGlyph *to,
1165             int reverse, MDrawRegion region)
1166 {
1167   MRealizedFace *rface = from->rface;
1168   MFrame *frame = rface->frame;
1169   Display *display = FRAME_DISPLAY (frame);
1170   MRealizedFont *rfont = rface->rfont;
1171   MRealizedFontXft *rfont_xft = rfont->info;
1172   XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1173   XftColor *xft_color = (! reverse
1174                          ? &((GCInfo *) rface->info)->xft_color_fore
1175                          : &((GCInfo *) rface->info)->xft_color_back);
1176   int anti_alias = (gstring->control.anti_alias
1177                     && FRAME_DEVICE (frame)->depth > 1);
1178   XftFont *xft_font;
1179   MGlyph *g;
1180   FT_UInt *glyphs;
1181   int last_x;
1182   int nglyphs;
1183
1184   if (from == to)
1185     return;
1186
1187   if (anti_alias)
1188     {
1189       if (rfont_xft->font_aa)
1190         xft_font = rfont_xft->font_aa;
1191       else
1192         {
1193           double size = rfont->spec.size;
1194
1195           xft_font = xft_open_font (display, rfont->spec.file, size / 10,
1196                                     FcTrue);
1197           if (xft_font)
1198             rfont_xft->font_aa = xft_font;
1199           else
1200             xft_font = rfont->fontp;
1201         }
1202     }
1203   else
1204     {
1205       if (rfont_xft->font_no_aa)
1206         xft_font = rfont_xft->font_no_aa;
1207       else
1208         {
1209           double size = rfont->spec.size;
1210
1211           xft_font = xft_open_font (display, rfont->spec.file, size / 10,
1212                                     FcTrue);
1213           if (xft_font)
1214             rfont_xft->font_no_aa = xft_font;
1215           else
1216             xft_font = rfont->fontp;
1217         }
1218     }
1219
1220   XftDrawChange (xft_draw, (Drawable) win);
1221   XftDrawSetClip (xft_draw, (Region) region);
1222       
1223   glyphs = alloca (sizeof (FT_UInt) * (to - from));
1224   for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1225     {
1226       if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1227         glyphs[nglyphs++] = g->code;
1228       else
1229         {
1230           if (nglyphs > 0)
1231             XftDrawGlyphs (xft_draw, xft_color, xft_font,
1232                            last_x, y, glyphs, nglyphs);
1233           nglyphs = 0;
1234           XftDrawGlyphs (xft_draw, xft_color, xft_font,
1235                          x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1236           last_x = x + g->width;
1237         }
1238     }
1239   if (nglyphs > 0)
1240     XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1241 }
1242
1243 #endif  /* HAVE_XFT2 */
1244
1245 \f
1246 /* Functions for the device driver.  */
1247
1248 static void
1249 mwin__close_device (MFrame *frame)
1250 {
1251   MWDevice *device = FRAME_DEVICE (frame);
1252
1253   M17N_OBJECT_UNREF (device);
1254 }
1255
1256 static void *
1257 mwin__device_get_prop (MFrame *frame, MSymbol key)
1258 {
1259   MWDevice *device = FRAME_DEVICE (frame);
1260
1261   if (key == Mdisplay)
1262     return (void *) device->display_info->display;
1263   if (key == Mscreen)
1264     return (void *) ScreenOfDisplay(device->display_info->display,
1265                                     device->screen_num);
1266   if (key == Mcolormap)
1267     return (void *) device->cmap;
1268   if (key == Mdepth)
1269     return (void *) device->depth;
1270   return NULL;
1271 }
1272
1273 static void
1274 mwin__realize_face (MRealizedFace *rface)
1275 {
1276   MFrame *frame;
1277   MSymbol foreground, background, videomode;
1278   MFaceHLineProp *hline;
1279   MFaceBoxProp *box;
1280   GCInfo *info;
1281
1282   if (rface != rface->ascii_rface)
1283     {
1284       rface->info = rface->ascii_rface->info;
1285       return;
1286     }
1287
1288   frame = rface->frame;
1289   MSTRUCT_CALLOC (info, MERROR_WIN);
1290
1291   foreground = rface->face.property[MFACE_FOREGROUND];
1292   background = rface->face.property[MFACE_BACKGROUND];
1293   videomode = rface->face.property[MFACE_VIDEOMODE];
1294   if (! videomode)
1295     videomode = frame->videomode;
1296   if (videomode != Mreverse)
1297     {
1298       info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1299       info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1300     }
1301   else
1302     {
1303       info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1304       info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1305     }
1306 #ifdef HAVE_XFT2
1307   if (foreground == Mnil)
1308     foreground = frame->foreground;
1309   if (background == Mnil)
1310     background = frame->background;
1311   if (videomode == Mreverse)
1312     {
1313       MSymbol temp = foreground;
1314       foreground = background;
1315       background = temp;
1316     }
1317   if (! XftColorAllocName (FRAME_DISPLAY (frame),
1318                            FRAME_VISUAL (frame),
1319                            FRAME_CMAP (frame),
1320                            MSYMBOL_NAME (foreground),
1321                            &info->xft_color_fore))
1322     mdebug_hook ();
1323   if (! XftColorAllocName (FRAME_DISPLAY (frame),
1324                            FRAME_VISUAL (frame),
1325                            FRAME_CMAP (frame),
1326                            MSYMBOL_NAME (background),
1327                            &info->xft_color_back))
1328     mdebug_hook ();
1329 #endif  /* HAVE_XFT2 */
1330
1331   hline = rface->hline;
1332   if (hline)
1333     {
1334       if (hline->color)
1335         info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1336       else
1337         info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1338     }
1339
1340   box = rface->box;
1341   if (box)
1342     {
1343       if (box->color_top)
1344         info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1345       else
1346         info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1347
1348       if (box->color_left && box->color_left != box->color_top)
1349         info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1350       else
1351         info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1352
1353       if (box->color_bottom && box->color_bottom != box->color_top)
1354         info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1355       else
1356         info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1357
1358       if (box->color_right && box->color_right != box->color_bottom)
1359         info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1360       else
1361         info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1362     }
1363
1364   rface->info = info;
1365 }
1366
1367
1368 static void
1369 mwin__free_realized_face (MRealizedFace *rface)
1370 {
1371   if (rface == rface->ascii_rface)
1372     free (rface->info);
1373 }
1374
1375
1376 static void
1377 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1378                   int reverse,
1379                   int x, int y, int width, int height, MDrawRegion region)
1380 {
1381   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1382
1383   if (region)
1384     gc = set_region (frame, gc, region);
1385
1386   XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1387                   x, y, width, height);
1388 }
1389
1390
1391 static void
1392 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1393                         MGlyphString *gstring, MGlyph *from, MGlyph *to,
1394                         int reverse, MDrawRegion region)
1395 {
1396   MRealizedFace *rface = from->rface;
1397   Display *display = FRAME_DISPLAY (rface->frame);
1398   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1399
1400   if (from == to)
1401     return;
1402
1403   if (region)
1404     gc = set_region (rface->frame, gc, region);
1405   for (; from < to; from++)
1406     {
1407       XDrawRectangle (display, (Window) win, gc,
1408                       x, y - gstring->ascent + 1, from->width - 1,
1409                       gstring->ascent + gstring->descent - 2);
1410       x += from->width;
1411     }
1412 }
1413
1414
1415 static void
1416 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1417                  MRealizedFace *rface, int reverse,
1418                  int x, int y, int width, MDrawRegion region)
1419 {
1420   enum MFaceHLineType type = rface->hline->type;
1421   GCInfo *info = rface->info;
1422   GC gc = gc = info->gc[GC_HLINE];
1423   int i;
1424
1425   y = (type == MFACE_HLINE_BOTTOM
1426        ? y + gstring->text_descent - rface->hline->width
1427        : type == MFACE_HLINE_UNDER
1428        ? y + 1
1429        : type == MFACE_HLINE_STRIKE_THROUGH
1430        ? y - ((gstring->ascent + gstring->descent) / 2)
1431        : y - gstring->text_ascent);
1432   if (region)
1433     gc = set_region (frame, gc, region);
1434
1435   for (i = 0; i < rface->hline->width; i++)
1436     XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1437                x, y + i, x + width - 1, y + i);
1438 }
1439
1440
1441 static void
1442 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1443                 MGlyph *g, int x, int y, int width, MDrawRegion region)
1444 {
1445   Display *display = FRAME_DISPLAY (frame);
1446   MRealizedFace *rface = g->rface;
1447   MFaceBoxProp *box = rface->box;
1448   GCInfo *info = rface->info;
1449   GC gc_top, gc_left, gc_right, gc_btm;
1450   int y0, y1;
1451   int i;
1452
1453   y0 = y - (gstring->text_ascent
1454             + rface->box->inner_vmargin + rface->box->width);
1455   y1 = y + (gstring->text_descent
1456             + rface->box->inner_vmargin + rface->box->width - 1);
1457
1458   gc_top = info->gc[GC_BOX_TOP];
1459   if (region)
1460     gc_top = set_region (frame, gc_top, region);
1461   if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1462     gc_btm = gc_top;
1463   else
1464     gc_btm = info->gc[GC_BOX_BOTTOM];
1465
1466   if (g->type == GLYPH_BOX)
1467     {
1468       int x0, x1;
1469
1470       if (g->left_padding)
1471         x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1472       else
1473         x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1474
1475       /* Draw the top side.  */
1476       for (i = 0; i < box->width; i++)
1477         XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1478
1479       /* Draw the bottom side.  */
1480       if (region && gc_btm != gc_top)
1481         gc_btm = set_region (frame, gc_btm, region);
1482       for (i = 0; i < box->width; i++)
1483         XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1484
1485       if (g->left_padding > 0)
1486         {
1487           /* Draw the left side.  */
1488           if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1489             gc_left = gc_top;
1490           else
1491             {
1492               gc_left = info->gc[GC_BOX_LEFT];
1493               if (region)
1494                 gc_left = set_region (frame, gc_left, region);
1495             }
1496           for (i = 0; i < rface->box->width; i++)
1497             XDrawLine (display, (Window) win, gc_left,
1498                        x0 + i, y0 + i, x0 + i, y1 - i);
1499         }
1500       else
1501         {
1502           /* Draw the right side.  */
1503           if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1504             gc_right = gc_top;
1505           else
1506             {
1507               gc_right = info->gc[GC_BOX_RIGHT];
1508               if (region)
1509                 gc_right = set_region (frame, gc_right, region);
1510             }
1511           for (i = 0; i < rface->box->width; i++)
1512             XDrawLine (display, (Window) win, gc_right,
1513                        x1 - i, y0 + i, x1 - i, y1 - i);
1514         }
1515     }
1516   else
1517     {
1518       /* Draw the top side.  */
1519       for (i = 0; i < box->width; i++)
1520         XDrawLine (display, (Window) win, gc_top,
1521                    x, y0 + i, x + width - 1, y0 + i);
1522
1523       /* Draw the bottom side.  */
1524       if (region && gc_btm != gc_top)
1525         gc_btm = set_region (frame, gc_btm, region);
1526       for (i = 0; i < box->width; i++)
1527         XDrawLine (display, (Window) win, gc_btm,
1528                    x, y1 - i, x + width - 1, y1 - i);
1529     }
1530 }
1531
1532
1533 #if 0
1534 static void
1535 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1536                    int reverse, int x, int y,
1537                    int width, int height, int row_bytes, unsigned char *bmp,
1538                    MDrawRegion region)
1539 {
1540   Display *display = FRAME_DISPLAY (frame);
1541   int i, j;
1542   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1543
1544   if (region)
1545     gc = set_region (frame, gc, region);
1546
1547   for (i = 0; i < height; i++, bmp += row_bytes)
1548     for (j = 0; j < width; j++)
1549       if (bmp[j / 8] & (1 << (7 - (j % 8))))
1550         XDrawPoint (display, (Window) win, gc, x + j, y + i);
1551 }
1552 #endif
1553
1554 static void
1555 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1556                    int intensity, MDrawPoint *points, int num,
1557                    MDrawRegion region)
1558 {
1559   GCInfo *info = rface->info;
1560   GC gc;
1561
1562   if (! (gc = info->gc[intensity]))
1563     gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1564                                                       info, intensity);
1565   if (region)
1566     gc = set_region (frame, gc, region);
1567
1568   XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1569                (XPoint *) points, num, CoordModeOrigin);
1570 }
1571
1572
1573 static MDrawRegion
1574 mwin__region_from_rect (MDrawMetric *rect)
1575 {
1576   MDrawRegion region1 = XCreateRegion ();
1577   MDrawRegion region2 = XCreateRegion ();
1578   XRectangle xrect;
1579
1580   xrect.x = rect->x;
1581   xrect.y = rect->y;
1582   xrect.width = rect->width;
1583   xrect.height = rect->height;
1584   XUnionRectWithRegion (&xrect, region1, region2);
1585   XDestroyRegion (region1);
1586   return region2;
1587 }
1588
1589 static void
1590 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1591 {
1592   MDrawRegion region1 = XCreateRegion ();
1593   XRectangle xrect;
1594
1595   xrect.x = rect->x;
1596   xrect.y = rect->y;
1597   xrect.width = rect->width;
1598   xrect.height = rect->height;
1599
1600   XUnionRegion (region, region, region1);
1601   XUnionRectWithRegion (&xrect, region1, region);
1602   XDestroyRegion (region1);
1603 }
1604
1605 static void
1606 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1607 {
1608   MDrawRegion region = XCreateRegion ();
1609
1610   XUnionRegion (region1, region1, region);
1611   XIntersectRegion (region, region2, region1);
1612   XDestroyRegion (region);
1613 }
1614
1615 static void
1616 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1617 {
1618   MDrawRegion region1 = XCreateRegion ();
1619   XRectangle xrect;
1620
1621   xrect.x = rect->x;
1622   xrect.y = rect->y;
1623   xrect.width = rect->width;
1624   xrect.height = rect->height;
1625   XUnionRectWithRegion (&xrect, region1, region);
1626   XDestroyRegion (region1);
1627 }
1628
1629 static void
1630 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1631 {
1632   XRectangle xrect;
1633
1634   XClipBox (region, &xrect);
1635   rect->x = xrect.x;
1636   rect->y = xrect.y;
1637   rect->width = xrect.width;
1638   rect->height = xrect.height;
1639 }
1640
1641 static void
1642 mwin__free_region (MDrawRegion region)
1643 {
1644   XDestroyRegion (region);
1645 }
1646
1647 static void
1648 mwin__dump_region (MDrawRegion region)
1649 {
1650   XRectangle rect;
1651   XClipBox (region, &rect);
1652   fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1653 }
1654
1655
1656 static MDrawWindow
1657 mwin__create_window (MFrame *frame, MDrawWindow parent)
1658 {
1659   Display *display = FRAME_DISPLAY (frame);
1660   Window win;
1661   XWMHints wm_hints = { InputHint, False };
1662   XClassHint class_hints = { "M17N-IM", "m17n-im" };
1663   XSetWindowAttributes set_attrs;
1664   unsigned long mask;
1665   XGCValues values;
1666   GCInfo *info = frame->rface->info;
1667
1668   if (! parent)
1669     parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1670   mask = GCForeground;
1671   XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1672   set_attrs.background_pixel = values.foreground;
1673   set_attrs.backing_store = Always;
1674   set_attrs.override_redirect = True;
1675   set_attrs.save_under = True;
1676   mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1677   win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1678                        CopyFromParent, InputOutput, CopyFromParent,
1679                        mask, &set_attrs);
1680   XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1681                     NULL, &wm_hints, &class_hints);
1682   XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1683   return (MDrawWindow) win;
1684 }
1685
1686 static void
1687 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1688 {
1689   XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1690 }
1691
1692 #if 0
1693 static MDrawWindow
1694 mwin__event_window (void *event)
1695 {
1696   return ((MDrawWindow) ((XEvent *) event)->xany.window);
1697 }
1698
1699 static void
1700 mwin__print_event (void *arg, char *win_name)
1701 {
1702   char *event_name;
1703   XEvent *event = (XEvent *) arg;
1704
1705   switch (event->xany.type)
1706     {
1707     case 2: event_name = "KeyPress"; break;
1708     case 3: event_name = "KeyRelease"; break;
1709     case 4: event_name = "ButtonPress"; break;
1710     case 5: event_name = "ButtonRelease"; break;
1711     case 6: event_name = "MotionNotify"; break;
1712     case 7: event_name = "EnterNotify"; break;
1713     case 8: event_name = "LeaveNotify"; break;
1714     case 9: event_name = "FocusIn"; break;
1715     case 10: event_name = "FocusOut"; break;
1716     case 11: event_name = "KeymapNotify"; break;
1717     case 12: event_name = "Expose"; break;
1718     case 13: event_name = "GraphicsExpose"; break;
1719     case 14: event_name = "NoExpose"; break;
1720     case 15: event_name = "VisibilityNotify"; break;
1721     case 16: event_name = "CreateNotify"; break;
1722     case 17: event_name = "DestroyNotify"; break;
1723     case 18: event_name = "UnmapNotify"; break;
1724     case 19: event_name = "MapNotify"; break;
1725     case 20: event_name = "MapRequest"; break;
1726     case 21: event_name = "ReparentNotify"; break;
1727     case 22: event_name = "ConfigureNotify"; break;
1728     case 23: event_name = "ConfigureRequest"; break;
1729     case 24: event_name = "GravityNotify"; break;
1730     case 25: event_name = "ResizeRequest"; break;
1731     case 26: event_name = "CirculateNotify"; break;
1732     case 27: event_name = "CirculateRequest"; break;
1733     case 28: event_name = "PropertyNotify"; break;
1734     case 29: event_name = "SelectionClear"; break;
1735     case 30: event_name = "SelectionRequest"; break;
1736     case 31: event_name = "SelectionNotify"; break;
1737     case 32: event_name = "ColormapNotify"; break;
1738     case 33: event_name = "ClientMessage"; break;
1739     case 34: event_name = "MappingNotify"; break;
1740     default: event_name = "unknown";
1741     }
1742
1743   fprintf (stderr, "%s: %s\n", win_name, event_name);
1744 }
1745 #endif
1746
1747 static void
1748 mwin__map_window (MFrame *frame, MDrawWindow win)
1749 {
1750   XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1751 }
1752
1753 static void
1754 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1755 {
1756   XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1757 }
1758
1759 static void
1760 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1761                        MDrawMetric *geometry)
1762 {
1763   Display *display = FRAME_DISPLAY (frame);
1764   XWindowAttributes attr;
1765   Window parent = (Window) parent_win, root;
1766
1767   XGetWindowAttributes (display, (Window) win, &attr);
1768   geometry->x = attr.x + attr.border_width;
1769   geometry->y = attr.y + attr.border_width;
1770   geometry->width = attr.width;
1771   geometry->height = attr.height; 
1772
1773   if (! parent)
1774     parent = RootWindow (display, FRAME_SCREEN (frame));
1775   while (1)
1776     {
1777       Window this_parent, *children;
1778       unsigned n;
1779
1780       XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1781       if (children)
1782         XFree (children);
1783       if (this_parent == parent || this_parent == root)
1784         break;
1785       win = (MDrawWindow) this_parent;
1786       XGetWindowAttributes (display, (Window) win, &attr);
1787       geometry->x += attr.x + attr.border_width;
1788       geometry->y += attr.y + attr.border_width;
1789     }
1790 }
1791
1792 static void
1793 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1794                      MDrawMetric *current, MDrawMetric *new)
1795 {
1796   Display *display = FRAME_DISPLAY (frame);
1797   unsigned int mask = 0;
1798   XWindowChanges values;
1799
1800   if (current->width != new->width)
1801     {
1802       mask |= CWWidth;
1803       if (new->width <= 0)
1804         new->width = 1;
1805       values.width = current->width = new->width;
1806     }
1807   if (current->height != new->height)
1808     {
1809       mask |= CWHeight;
1810       if (new->height <= 0)
1811         new->height = 1;
1812       values.height = current->height = new->height;
1813     }
1814   if (current->x != new->x)
1815     {
1816       mask |= CWX;
1817       values.x = current->x = new->x;
1818     }
1819   if (current->y != new->y)
1820     {
1821       mask |= CWY;
1822       current->y = new->y;
1823       values.y = current->y = new->y;
1824     }
1825   if (mask)
1826     XConfigureWindow (display, (Window) win, mask, &values);
1827   XClearWindow (display, (Window) win);
1828 }
1829
1830 static MSymbol
1831 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1832 {
1833   XEvent *event = (XEvent *) arg;
1834   MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1835   int len;
1836   char buf[512];
1837   KeySym keysym;
1838   MSymbol key = Mnil;
1839
1840   *modifiers = 0;
1841   if (event->xany.type != KeyPress
1842       /* && event->xany.type != KeyRelease */
1843       )
1844     return Mnil;
1845   len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1846   if (len > 1)
1847     return Mnil;
1848   if (len == 1)
1849     {
1850       int c = keysym;
1851
1852       if (c < XK_space || c > XK_asciitilde)
1853         c = buf[0];
1854       if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1855         *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1856       if (((XKeyEvent *) event)->state & ControlMask)
1857         {
1858           if (c >= 'a' && c <= 'z')
1859             c += 'A' - 'a';
1860           if (c >= ' ' && c < 127)
1861             *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1862         }
1863       key = minput__char_to_key (c);
1864     }
1865   else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1866     return Mnil;
1867   if (key == Mnil)
1868     {
1869       char *str = XKeysymToString (keysym);
1870
1871       if (! str)
1872         return Mnil;
1873       key = msymbol (str);
1874       if (((XKeyEvent *) event)->state & ShiftMask)
1875         *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1876       if (((XKeyEvent *) event)->state & ControlMask)
1877         *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1878     }
1879   if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1880     *modifiers |= MINPUT_KEY_META_MODIFIER;
1881   if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1882     *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1883   if (((XKeyEvent *) event)->state & disp_info->super_mask)
1884     *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1885   if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1886     *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1887
1888   return key;
1889 }
1890
1891
1892 void
1893 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1894 {
1895   unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1896   XGCValues values;
1897   Display *display = FRAME_DISPLAY (frame);
1898   GCInfo *info = rface->info;
1899   int i;
1900
1901   for (i = 0; i <= GC_INVERSE; i++)
1902     {
1903       XGetGCValues (display, info->gc[i], valuemask, &values);
1904       fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1905                values.foreground, values.background);
1906       fprintf (stderr, "\n");
1907     }
1908 }
1909
1910 static MDeviceDriver x_driver =
1911   {
1912     mwin__close_device,
1913     mwin__device_get_prop,
1914     mwin__realize_face,
1915     mwin__free_realized_face,
1916     mwin__fill_space,
1917     mwin__draw_empty_boxes,
1918     mwin__draw_hline,
1919     mwin__draw_box,
1920     mwin__draw_points,
1921     mwin__region_from_rect,
1922     mwin__union_rect_with_region,
1923     mwin__intersect_region,
1924     mwin__region_add_rect,
1925     mwin__region_to_rect,
1926     mwin__free_region,
1927     mwin__dump_region,
1928     mwin__create_window,
1929     mwin__destroy_window,
1930     mwin__map_window,
1931     mwin__unmap_window,
1932     mwin__window_geometry,
1933     mwin__adjust_window,
1934     mwin__parse_event
1935   };
1936
1937 /* Functions to be stored in MDeviceLibraryInterface by dlsym ().  */
1938
1939 int
1940 device_init ()
1941 {
1942   M_iso8859_1 = msymbol ("iso8859-1");
1943   M_iso10646_1 = msymbol ("iso10646-1");
1944
1945   display_info_list = mplist ();
1946   device_list = mplist ();
1947
1948 #ifdef HAVE_XFT2
1949   xft_driver.select = mfont__ft_driver.select;
1950   xft_driver.list = mfont__ft_driver.list;
1951 #endif
1952
1953   Mxim = msymbol ("xim");
1954   msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1955
1956   return 0;
1957 }
1958
1959 int
1960 device_fini ()
1961 {
1962   M17N_OBJECT_UNREF (display_info_list);
1963   M17N_OBJECT_UNREF (device_list);
1964   return 0;
1965 }
1966
1967
1968 #ifdef X_SET_ERROR_HANDLER
1969 static int
1970 x_error_handler (Display *display, XErrorEvent *error)
1971 {
1972   mdebug_hook ();
1973   return 0;
1974 }
1975
1976 static int
1977 x_io_error_handler (Display *display)
1978 {
1979   mdebug_hook ();
1980   return 0;
1981 }
1982 #endif
1983
1984 /** Return an MWDevice object corresponding to a display specified in
1985     PLIST.
1986
1987     It searches device_list for a device matching the display.  If
1988     found, return the found object.  Otherwise, return a newly created
1989     object.  */
1990
1991 int
1992 device_open (MFrame *frame, MPlist *param)
1993 {
1994   Display *display = NULL;
1995   Screen *screen = NULL;
1996   int screen_num;
1997   Drawable drawable = 0;
1998   Widget widget = NULL;
1999   Colormap cmap = 0;
2000   int auto_display = 0;
2001   MDisplayInfo *disp_info = NULL;
2002   MWDevice *device = NULL;
2003   MSymbol key;
2004   XWindowAttributes attr;
2005   unsigned depth = 0;
2006   MPlist *plist;
2007   AppData app_data;
2008   MFont *font = NULL;
2009   MFace *face;
2010   int use_xfont = 0, use_freetype = 0, use_xft = 0;
2011
2012   for (plist = param; (key = mplist_key (plist)) != Mnil;
2013        plist = mplist_next (plist))
2014     {
2015       if (key == Mdisplay)
2016         display = (Display *) mplist_value (plist);
2017       else if (key == Mscreen)
2018         screen = mplist_value (plist);
2019       else if (key == Mdrawable)
2020         drawable = (Drawable) mplist_value (plist);
2021       else if (key == Mdepth)
2022         depth = (unsigned) mplist_value (plist);
2023       else if (key == Mwidget)
2024         widget = (Widget) mplist_value (plist);
2025       else if (key == Mcolormap)
2026         cmap = (Colormap) mplist_value (plist);
2027       else if (key == Mfont)
2028         {
2029           MSymbol val = MPLIST_SYMBOL (plist);
2030
2031           if (val == Mx)
2032             use_xfont = 1;
2033 #ifdef HAVE_FREETYPE
2034           else if (val == Mfreetype)
2035             use_freetype = 1;
2036 #ifdef HAVE_XFT2
2037           else if (val == Mxft)
2038             use_xft = 1;
2039 #endif
2040 #endif
2041         }
2042     }
2043
2044   /* If none of them is specified, use all of them.  */
2045   if (! use_xfont && ! use_freetype && ! use_xft)
2046     use_xfont = use_freetype = use_xft = 1;
2047
2048   if (widget)
2049     {
2050       display = XtDisplay (widget);
2051       screen_num = XScreenNumberOfScreen (XtScreen (widget));
2052       depth = DefaultDepth (display, screen_num);
2053     }
2054   else if (drawable)
2055     {
2056       Window root_window;
2057       int x, y;
2058       unsigned width, height, border_width;
2059
2060       if (! display)
2061         MERROR (MERROR_WIN, -1);
2062       XGetGeometry (display, drawable, &root_window,
2063                     &x, &y, &width, &height, &border_width, &depth);
2064       XGetWindowAttributes (display, root_window, &attr);
2065       screen_num = XScreenNumberOfScreen (attr.screen);
2066     }
2067   else
2068     {
2069       if (screen)
2070         display = DisplayOfScreen (screen);
2071       else
2072         {
2073           if (! display)
2074             {
2075               display = XOpenDisplay (NULL);
2076               if (! display)
2077                 MERROR (MERROR_WIN, -1);
2078               auto_display = 1;
2079             }
2080           screen = DefaultScreenOfDisplay (display);
2081         }
2082       screen_num = XScreenNumberOfScreen (screen);
2083       if (! depth)
2084         depth = DefaultDepth (display, screen_num);
2085     }
2086
2087   if (! cmap)
2088     cmap = DefaultColormap (display, screen_num);
2089
2090   for (plist = display_info_list; mplist_key (plist) != Mnil;
2091        plist = mplist_next (plist))
2092     {
2093       disp_info = (MDisplayInfo *) mplist_value (plist);
2094       if (disp_info->display == display)
2095         break;
2096     }
2097
2098   if (mplist_key (plist) != Mnil)
2099     M17N_OBJECT_REF (disp_info);
2100   else
2101     {
2102       M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
2103       disp_info->display = display;
2104       disp_info->auto_display = auto_display;
2105       disp_info->font_list = mplist ();
2106       find_modifier_bits (disp_info);
2107       mplist_add (display_info_list, Mt, disp_info);
2108     }  
2109
2110   for (plist = device_list; mplist_key (plist) != Mnil;
2111        plist = mplist_next (plist))
2112     {
2113       device = (MWDevice *) mplist_value (plist);
2114       if (device->display_info == disp_info
2115           && device->depth == depth
2116           && device->cmap == cmap
2117           && device->screen_num == screen_num)
2118         break;
2119     }
2120
2121   if (mplist_key (plist) != Mnil)
2122     M17N_OBJECT_REF (device);
2123   else
2124     {
2125       unsigned long valuemask = GCForeground;
2126       XGCValues values;
2127       double pixels, mm;
2128
2129       M17N_OBJECT (device, free_device, MERROR_WIN);
2130       device->display_info = disp_info;
2131       device->screen_num = screen_num;
2132       /* A drawable on which to create GCs.  */
2133       device->drawable = XCreatePixmap (display,
2134                                         RootWindow (display, screen_num),
2135                                         1, 1, depth);
2136       device->depth = depth;
2137       device->cmap = cmap;
2138       pixels = DisplayHeight (display, screen_num);
2139       mm = DisplayHeightMM (display, screen_num);
2140       device->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
2141       device->realized_face_list = mplist ();
2142       device->realized_font_list = mplist ();
2143       mplist_add (device->realized_font_list, Mt, NULL);
2144       device->realized_fontset_list = mplist ();
2145       device->gc_list = mplist ();
2146       values.foreground = BlackPixel (display, screen_num);
2147       device->scratch_gc = XCreateGC (display, device->drawable,
2148                                       valuemask, &values);
2149 #ifdef HAVE_XFT2
2150       device->xft_draw = XftDrawCreate (display, device->drawable,
2151                                         DefaultVisual (display, screen_num),
2152                                         cmap);
2153 #endif
2154     }
2155
2156   frame->device = device;
2157   frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2158   frame->dpi = device->resy;
2159   frame->driver = &x_driver;
2160   frame->font_driver_list = mplist ();
2161 #ifdef HAVE_XFT2
2162   if (use_xft)
2163     {
2164       mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2165       use_freetype = 0;
2166     }
2167 #endif  /* HAVE_XFT2 */
2168 #ifdef HAVE_FREETYPE
2169   if (use_freetype)
2170     mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2171 #endif  /* HAVE_FREETYPE */
2172   if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list))
2173     mplist_push (frame->font_driver_list, Mx, &xfont_driver);
2174
2175   frame->realized_font_list = device->realized_font_list;
2176   frame->realized_face_list = device->realized_face_list;
2177   frame->realized_fontset_list = device->realized_fontset_list;
2178
2179   if (widget)
2180     {
2181       XtResource resources[] = {
2182         { XtNfont, XtCFont, XtRString, sizeof (String),
2183           XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2184         { XtNforeground, XtCForeground, XtRString, sizeof (String),
2185           XtOffset (AppDataPtr, foreground), XtRString, "black" },
2186         { XtNbackground, XtCBackground, XtRString, sizeof (String),
2187           XtOffset (AppDataPtr, background), XtRString, "white" },
2188         { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2189           XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2190       };
2191
2192       XtGetApplicationResources (widget, &app_data,
2193                                  resources, XtNumber (resources), NULL, 0);
2194       frame->foreground = msymbol (app_data.foreground);
2195       frame->background = msymbol (app_data.background);
2196       frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2197     }
2198   else
2199     {
2200       app_data.font = DEFAULT_FONT;
2201       frame->foreground = msymbol ("black");
2202       frame->background = msymbol ("white");
2203       frame->videomode = Mnormal;
2204     }
2205
2206   if (strcmp (app_data.font, DEFAULT_FONT) != 0)
2207     {
2208       XFontStruct *xfont = XLoadQueryFont (display, app_data.font);
2209       unsigned long value;
2210       char *name;
2211
2212       if (xfont)
2213         {
2214           font = mfont_parse_name (app_data.font, Mx);
2215           if (! font
2216               && XGetFontProperty (xfont, XA_FONT, &value)
2217               && (name = ((char *) XGetAtomName (display, (Atom) value))))
2218             font = mfont_parse_name (name, Mx);
2219           XFreeFont (display, xfont);
2220         }
2221     }
2222   if (! font)
2223       font = mfont_parse_name (DEFAULT_FONT, Mx);
2224   else if (! font->size)
2225     font->size = 130;
2226   face = mface_from_font (font);
2227   free (font);
2228   face->property[MFACE_FONTSET] = mfontset (NULL);
2229   face->property[MFACE_FOREGROUND] = frame->foreground;
2230   face->property[MFACE_BACKGROUND] = frame->background;
2231   mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2232   mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2233   face->property[MFACE_VIDEOMODE] = frame->videomode;
2234   mface_put_prop (face, Mhook_func, 
2235                   mface_get_prop (mface__default, Mhook_func));
2236   face->property[MFACE_RATIO] = (void *) 100;
2237   mplist_push (param, Mface, face);
2238   M17N_OBJECT_UNREF (face);
2239
2240 #ifdef X_SET_ERROR_HANDLER
2241   XSetErrorHandler (x_error_handler);
2242   XSetIOErrorHandler (x_io_error_handler);
2243 #endif
2244   return 0;
2245 }
2246
2247 \f
2248
2249 /* XIM (X Input Method) handler */
2250
2251 typedef struct MInputXIMMethodInfo
2252 {
2253   Display *display;
2254   XIM xim;
2255   MSymbol language;
2256   MSymbol coding;
2257 } MInputXIMMethodInfo;
2258
2259 typedef struct MInputXIMContextInfo
2260 {
2261   XIC xic;
2262   Window win;
2263   MConverter *converter;
2264 } MInputXIMContextInfo;
2265
2266 static int
2267 xim_open_im (MInputMethod *im)
2268 {
2269   MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2270   MLocale *saved, *this;
2271   char *save_modifier_list;
2272   XIM xim;
2273   MInputXIMMethodInfo *im_info;
2274
2275   saved = mlocale_set (LC_CTYPE, NULL);
2276   this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2277   if (! this)
2278     /* The specified locale is not supported.  */
2279     MERROR (MERROR_LOCALE, -1);
2280   if (mlocale_get_prop (this, Mcoding) == Mnil)
2281     {
2282       /* Unable to decode the output of XIM.  */
2283       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2284       MERROR (MERROR_LOCALE, -1);
2285     }
2286
2287   if (arg->modifier_list)
2288     save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2289   else
2290     save_modifier_list = XSetLocaleModifiers ("");
2291   if (! save_modifier_list)
2292     {
2293       /* The specified locale is not supported by X.  */
2294       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2295       MERROR (MERROR_LOCALE, -1);
2296     }
2297
2298   xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2299   if (! xim)
2300     {
2301       /* No input method is available in the current locale.  */
2302       XSetLocaleModifiers (save_modifier_list);
2303       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2304       MERROR (MERROR_WIN, -1);
2305     }
2306
2307   MSTRUCT_MALLOC (im_info, MERROR_WIN);
2308   im_info->display = arg->display;
2309   im_info->xim = xim;
2310   im_info->language = mlocale_get_prop (this, Mlanguage);
2311   im_info->coding = mlocale_get_prop (this, Mcoding);
2312   im->info = im_info;
2313
2314   XSetLocaleModifiers (save_modifier_list);
2315   mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2316
2317   return 0;
2318 }
2319
2320 static void
2321 xim_close_im (MInputMethod *im)
2322 {
2323   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2324
2325   XCloseIM (im_info->xim);
2326   free (im_info);
2327 }
2328
2329 static int
2330 xim_create_ic (MInputContext *ic)
2331 {
2332   MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2333   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2334   MInputXIMContextInfo *ic_info;
2335   XIC xic;
2336
2337   if (! arg->input_style)
2338     {
2339       /* By default, use Root style.  */
2340       arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2341       arg->preedit_attrs = NULL;
2342       arg->status_attrs = NULL;
2343     }
2344
2345   if (! arg->preedit_attrs && ! arg->status_attrs)
2346     xic = XCreateIC (im_info->xim,
2347                      XNInputStyle, arg->input_style,
2348                      XNClientWindow, arg->client_win,
2349                      XNFocusWindow, arg->focus_win,
2350                      NULL);
2351   else if (arg->preedit_attrs && ! arg->status_attrs)
2352     xic = XCreateIC (im_info->xim,
2353                      XNInputStyle, arg->input_style,
2354                      XNClientWindow, arg->client_win,
2355                      XNFocusWindow, arg->focus_win,
2356                      XNPreeditAttributes, arg->preedit_attrs,
2357                      NULL);
2358   else if (! arg->preedit_attrs && arg->status_attrs)
2359     xic = XCreateIC (im_info->xim,
2360                      XNInputStyle, arg->input_style,
2361                      XNClientWindow, arg->client_win,
2362                      XNFocusWindow, arg->focus_win,
2363                      XNStatusAttributes, arg->status_attrs,
2364                      NULL);
2365   else
2366     xic = XCreateIC (im_info->xim,
2367                      XNInputStyle, arg->input_style,
2368                      XNClientWindow, arg->client_win,
2369                      XNFocusWindow, arg->focus_win,
2370                      XNPreeditAttributes, arg->preedit_attrs,
2371                      XNStatusAttributes, arg->status_attrs,
2372                      NULL);
2373   if (! xic)
2374     MERROR (MERROR_WIN, -1);
2375
2376   MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2377   ic_info->xic = xic;
2378   ic_info->win = arg->focus_win;
2379   ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2380   ic->info = ic_info;
2381   return 0;
2382 }
2383
2384 static void
2385 xim_destroy_ic (MInputContext *ic)
2386 {
2387   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2388
2389   XDestroyIC (ic_info->xic);
2390   mconv_free_converter (ic_info->converter);
2391   free (ic_info);
2392   ic->info = NULL;
2393 }
2394
2395 static int
2396 xim_filter (MInputContext *ic, MSymbol key, void *event)
2397 {
2398   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2399
2400   return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2401 }
2402
2403
2404 static int
2405 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2406 {
2407   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2408   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2409   XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2410   KeySym keysym;
2411   Status status;
2412   char *buf;
2413   int len;
2414
2415   buf = (char *) alloca (512);
2416   len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2417   if (status == XBufferOverflow)
2418     {
2419       buf = (char *) alloca (len);
2420       len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2421     }
2422
2423   mtext_reset (ic->produced);
2424   if (len == 0)
2425     return 1;
2426
2427   mconv_reset_converter (ic_info->converter);
2428   mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2429   mconv_decode (ic_info->converter, ic->produced);
2430   mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2431                   Mlanguage, (void *) im_info->language);
2432   mtext_cpy (mt, ic->produced);
2433   mtext_reset (ic->produced);  
2434   return 0;
2435 }
2436
2437 \f
2438 /*=*/
2439
2440 /*** @} */
2441 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2442 \f
2443 /* External API */
2444
2445 /*** @addtogroup m17nInputMethodWin */
2446
2447 /*** @{ */
2448
2449 /***en
2450     @brief Input method driver for XIM.
2451
2452     The driver #minput_xim_driver is for the foreign input method of
2453     name #Mxim.  It uses XIM (X Input Methods) as a background input
2454     engine.
2455
2456     As the symbol #Mxim has property #Minput_driver whose value is
2457     a pointer to this driver, the input method of language #Mnil
2458     and name #Mxim uses this driver.
2459
2460     Therefore, for such input methods, the driver dependent arguments
2461     to the functions whose name begin with minput_ must be as follows.
2462
2463     The argument $ARG of the function minput_open_im () must be a
2464     pointer to the structure #MInputXIMArgIM.  See the documentation
2465     of #MInputXIMArgIM for more details.
2466
2467     The argument $ARG of the function minput_create_ic () must be a
2468     pointer to the structure #MInputXIMArgIC. See the documentation
2469     of #MInputXIMArgIC for more details.
2470
2471     The argument $ARG of the function minput_filter () must be a
2472     pointer to the structure @c XEvent.  The argument $KEY is ignored.
2473
2474     The argument $ARG of the function minput_lookup () must be the
2475     same one as that of the function minput_filter ().  The argument
2476     $KEY is ignored.  */
2477
2478 /***ja
2479     @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2480
2481     ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ê¡¢
2482     XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
2483
2484     ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2485     #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim 
2486     ¤Ç¤¢¤ëÆþÎϥ᥽¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2487
2488     ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ 
2489     ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2490
2491     ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIM 
2492     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò»²¾È¡£
2493
2494     ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIC 
2495     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ¤ò»²¾È¡£
2496
2497     ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ@c XEvent 
2498     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2499
2500     ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter () 
2501     ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì¤ë¡£  */
2502
2503 MInputDriver minput_xim_driver =
2504   { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2505     xim_filter, xim_lookup, NULL };
2506
2507 /*** @} */ 
2508
2509 /*
2510   Local Variables:
2511   coding: euc-japan
2512   End:
2513 */