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