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