Fix 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 #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
918
919 static void
920 close_xft (void *object)
921 {
922   MXftFontInfo *font_info = object;
923
924   XftFontClose (font_info->display, font_info->font_aa);
925   XftFontClose (font_info->display, font_info->font_no_aa);
926   free (font_info);
927 }
928
929
930 static XftFont *
931 xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
932 {
933   XftPattern *pattern;
934   XftFontInfo *xft_font_info;
935   XftFont *font;
936
937   pattern = XftPatternCreate ();
938   XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
939   XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
940   XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
941   xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
942   if (! xft_font_info)
943     return NULL;
944   font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
945   XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
946   return font;
947 }
948
949
950 static int
951 xft_open (MRealizedFont *rfont)
952 {
953   MFrame *frame;
954   MFTInfo *ft_info;
955   MXftFontInfo *font_info;
956   int size;
957
958   if ((mfont__ft_driver.open) (rfont) < 0)
959     return -1;
960
961   size = rfont->font.property[MFONT_SIZE] / 10;
962   frame = rfont->frame;
963
964   ft_info = rfont->info;
965   M17N_OBJECT (font_info, close_xft, MERROR_WIN);
966   ft_info->extra_info = font_info;
967   font_info->display = FRAME_DISPLAY (frame);
968   font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
969   if (font_info->font_aa)
970     {
971       font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
972       if (font_info->font_no_aa)
973         {
974           rfont->type = Mxft;
975           rfont->fontp = font_info->font_no_aa;
976           return 0;
977         }
978       XftFontClose (FRAME_DISPLAY (rfont->frame), font_info->font_aa);
979     }
980   free (font_info);  
981   ft_info->extra_info = NULL;
982   rfont->status = -1;
983   return -1;
984 }
985
986
987 static void
988 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
989                 int from, int to)
990 {
991   MFTInfo *ft_info = rfont->info;
992   MXftFontInfo *font_info = ft_info->extra_info;
993   MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
994
995   for (; g != gend; g++)
996     {
997       if (g->code == MCHAR_INVALID_CODE)
998         {
999           MGlyph *start = g++;
1000
1001           while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
1002           (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
1003                                           GLYPH_INDEX (g));
1004           g--;
1005         }
1006       else
1007         {
1008           XGlyphInfo extents;
1009
1010           XftGlyphExtents (FRAME_DISPLAY (gstring->frame),
1011                            font_info->font_aa, &g->code, 1, &extents);
1012           g->lbearing = - extents.x;
1013           g->rbearing = extents.width - extents.x;
1014           g->width = extents.xOff;
1015           g->ascent = extents.y;
1016           g->descent = extents.height - extents.y;
1017         }
1018     }
1019 }
1020
1021
1022 static void 
1023 xft_render (MDrawWindow win, int x, int y,
1024             MGlyphString *gstring, MGlyph *from, MGlyph *to,
1025             int reverse, MDrawRegion region)
1026 {
1027   MRealizedFace *rface = from->rface;
1028   MFrame *frame = rface->frame;
1029   MFTInfo *ft_info = rface->rfont->info;
1030   MXftFontInfo *font_info = ft_info->extra_info;
1031   XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1032   XftColor *xft_color = (! reverse
1033                          ? &((GCInfo *) rface->info)->xft_color_fore
1034                          : &((GCInfo *) rface->info)->xft_color_back);
1035   XftFont *xft_font = (gstring->control.anti_alias
1036                        && FRAME_DEVICE (frame)->depth > 1
1037                        ? font_info->font_aa : font_info->font_no_aa);
1038   MGlyph *g;
1039   FT_UInt *glyphs;
1040   int last_x;
1041   int nglyphs;
1042
1043   if (from == to)
1044     return;
1045
1046   XftDrawChange (xft_draw, (Drawable) win);
1047   XftDrawSetClip (xft_draw, (Region) region);
1048       
1049   glyphs = alloca (sizeof (FT_UInt) * (to - from));
1050   for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1051     {
1052       if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1053         glyphs[nglyphs++] = g->code;
1054       else
1055         {
1056           if (nglyphs > 0)
1057             XftDrawGlyphs (xft_draw, xft_color, xft_font,
1058                            last_x, y, glyphs, nglyphs);
1059           nglyphs = 0;
1060           XftDrawGlyphs (xft_draw, xft_color, xft_font,
1061                          x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1062           last_x = x + g->width;
1063         }
1064     }
1065   if (nglyphs > 0)
1066     XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1067 }
1068
1069 #endif
1070
1071 \f
1072 /* Functions for the device driver.  */
1073
1074 static void
1075 mwin__close_device (MFrame *frame)
1076 {
1077   M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
1078 }
1079
1080 static void *
1081 mwin__device_get_prop (MFrame *frame, MSymbol key)
1082 {
1083   MWDevice *device = FRAME_DEVICE (frame);
1084
1085   if (key == Mdisplay)
1086     return (void *) device->display_info->display;
1087   if (key == Mscreen)
1088     return (void *) ScreenOfDisplay(device->display_info->display,
1089                                     device->screen_num);
1090   if (key == Mcolormap)
1091     return (void *) device->cmap;
1092   if (key == Mdepth)
1093     return (void *) device->depth;
1094   return NULL;
1095 }
1096
1097 static void
1098 mwin__realize_face (MRealizedFace *rface)
1099 {
1100   MFrame *frame;
1101   MSymbol foreground, background, videomode;
1102   MFaceHLineProp *hline;
1103   MFaceBoxProp *box;
1104   GCInfo *info;
1105
1106   if (rface != rface->ascii_rface)
1107     {
1108       rface->info = rface->ascii_rface->info;
1109       return;
1110     }
1111
1112   frame = rface->frame;
1113   MSTRUCT_CALLOC (info, MERROR_WIN);
1114
1115   foreground = rface->face.property[MFACE_FOREGROUND];
1116   background = rface->face.property[MFACE_BACKGROUND];
1117   videomode = rface->face.property[MFACE_VIDEOMODE];
1118   if (! videomode)
1119     videomode = frame->videomode;
1120   if (videomode != Mreverse)
1121     {
1122       info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1123       info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1124     }
1125   else
1126     {
1127       info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1128       info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1129     }
1130 #ifdef HAVE_XFT2
1131   if (foreground == Mnil)
1132     foreground = frame->foreground;
1133   if (background == Mnil)
1134     background = frame->background;
1135   if (videomode == Mreverse)
1136     {
1137       MSymbol temp = foreground;
1138       foreground = background;
1139       background = temp;
1140     }
1141   if (! XftColorAllocName (FRAME_DISPLAY (frame),
1142                            FRAME_VISUAL (frame),
1143                            FRAME_CMAP (frame),
1144                            MSYMBOL_NAME (foreground),
1145                            &info->xft_color_fore))
1146     mdebug_hook ();
1147   if (! XftColorAllocName (FRAME_DISPLAY (frame),
1148                            FRAME_VISUAL (frame),
1149                            FRAME_CMAP (frame),
1150                            MSYMBOL_NAME (background),
1151                            &info->xft_color_back))
1152     mdebug_hook ();
1153 #endif
1154
1155   hline = rface->hline;
1156   if (hline)
1157     {
1158       if (hline->color)
1159         info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1160       else
1161         info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1162     }
1163
1164   box = rface->box;
1165   if (box)
1166     {
1167       if (box->color_top)
1168         info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1169       else
1170         info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1171
1172       if (box->color_left && box->color_left != box->color_top)
1173         info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1174       else
1175         info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1176
1177       if (box->color_bottom && box->color_bottom != box->color_top)
1178         info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1179       else
1180         info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1181
1182       if (box->color_right && box->color_right != box->color_bottom)
1183         info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1184       else
1185         info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1186     }
1187
1188   rface->info = info;
1189 }
1190
1191
1192 static void
1193 mwin__free_realized_face (MRealizedFace *rface)
1194 {
1195   if (rface == rface->ascii_rface)
1196     free (rface->info);
1197 }
1198
1199
1200 static void
1201 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1202                   int reverse,
1203                   int x, int y, int width, int height, MDrawRegion region)
1204 {
1205   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1206
1207   if (region)
1208     gc = set_region (frame, gc, region);
1209
1210   XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1211                   x, y, width, height);
1212 }
1213
1214
1215 static void
1216 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1217                         MGlyphString *gstring, MGlyph *from, MGlyph *to,
1218                         int reverse, MDrawRegion region)
1219 {
1220   MRealizedFace *rface = from->rface;
1221   Display *display = FRAME_DISPLAY (rface->frame);
1222   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1223
1224   if (from == to)
1225     return;
1226
1227   if (region)
1228     gc = set_region (rface->frame, gc, region);
1229   for (; from < to; from++)
1230     {
1231       XDrawRectangle (display, (Window) win, gc,
1232                       x, y - gstring->ascent + 1, from->width - 1,
1233                       gstring->ascent + gstring->descent - 2);
1234       x += from->width;
1235     }
1236 }
1237
1238
1239 static void
1240 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1241                  MRealizedFace *rface, int reverse,
1242                  int x, int y, int width, MDrawRegion region)
1243 {
1244   enum MFaceHLineType type = rface->hline->type;
1245   GCInfo *info = rface->info;
1246   GC gc = gc = info->gc[GC_HLINE];
1247   int i;
1248
1249   y = (type == MFACE_HLINE_BOTTOM
1250        ? y + gstring->text_descent - rface->hline->width
1251        : type == MFACE_HLINE_UNDER
1252        ? y + 1
1253        : type == MFACE_HLINE_STRIKE_THROUGH
1254        ? y - ((gstring->ascent + gstring->descent) / 2)
1255        : y - gstring->text_ascent);
1256   if (region)
1257     gc = set_region (frame, gc, region);
1258
1259   for (i = 0; i < rface->hline->width; i++)
1260     XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1261                x, y + i, x + width - 1, y + i);
1262 }
1263
1264
1265 static void
1266 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1267                 MGlyph *g, int x, int y, int width, MDrawRegion region)
1268 {
1269   Display *display = FRAME_DISPLAY (frame);
1270   MRealizedFace *rface = g->rface;
1271   MFaceBoxProp *box = rface->box;
1272   GCInfo *info = rface->info;
1273   GC gc_top, gc_left, gc_right, gc_btm;
1274   int y0, y1;
1275   int i;
1276
1277   y0 = y - (gstring->text_ascent
1278             + rface->box->inner_vmargin + rface->box->width);
1279   y1 = y + (gstring->text_descent
1280             + rface->box->inner_vmargin + rface->box->width - 1);
1281
1282   gc_top = info->gc[GC_BOX_TOP];
1283   if (region)
1284     gc_top = set_region (frame, gc_top, region);
1285   if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1286     gc_btm = gc_top;
1287   else
1288     gc_btm = info->gc[GC_BOX_BOTTOM];
1289
1290   if (g->type == GLYPH_BOX)
1291     {
1292       int x0, x1;
1293
1294       if (g->left_padding)
1295         x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1296       else
1297         x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1298
1299       /* Draw the top side.  */
1300       for (i = 0; i < box->width; i++)
1301         XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1302
1303       /* Draw the bottom side.  */
1304       if (region && gc_btm != gc_top)
1305         gc_btm = set_region (frame, gc_btm, region);
1306       for (i = 0; i < box->width; i++)
1307         XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1308
1309       if (g->left_padding > 0)
1310         {
1311           /* Draw the left side.  */
1312           if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1313             gc_left = gc_top;
1314           else
1315             {
1316               gc_left = info->gc[GC_BOX_LEFT];
1317               if (region)
1318                 gc_left = set_region (frame, gc_left, region);
1319             }
1320           for (i = 0; i < rface->box->width; i++)
1321             XDrawLine (display, (Window) win, gc_left,
1322                        x0 + i, y0 + i, x0 + i, y1 - i);
1323         }
1324       else
1325         {
1326           /* Draw the right side.  */
1327           if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1328             gc_right = gc_top;
1329           else
1330             {
1331               gc_right = info->gc[GC_BOX_RIGHT];
1332               if (region)
1333                 gc_right = set_region (frame, gc_right, region);
1334             }
1335           for (i = 0; i < rface->box->width; i++)
1336             XDrawLine (display, (Window) win, gc_right,
1337                        x1 - i, y0 + i, x1 - i, y1 - i);
1338         }
1339     }
1340   else
1341     {
1342       /* Draw the top side.  */
1343       for (i = 0; i < box->width; i++)
1344         XDrawLine (display, (Window) win, gc_top,
1345                    x, y0 + i, x + width - 1, y0 + i);
1346
1347       /* Draw the bottom side.  */
1348       if (region && gc_btm != gc_top)
1349         gc_btm = set_region (frame, gc_btm, region);
1350       for (i = 0; i < box->width; i++)
1351         XDrawLine (display, (Window) win, gc_btm,
1352                    x, y1 - i, x + width - 1, y1 - i);
1353     }
1354 }
1355
1356
1357 #if 0
1358 static void
1359 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1360                    int reverse, int x, int y,
1361                    int width, int height, int row_bytes, unsigned char *bmp,
1362                    MDrawRegion region)
1363 {
1364   Display *display = FRAME_DISPLAY (frame);
1365   int i, j;
1366   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1367
1368   if (region)
1369     gc = set_region (frame, gc, region);
1370
1371   for (i = 0; i < height; i++, bmp += row_bytes)
1372     for (j = 0; j < width; j++)
1373       if (bmp[j / 8] & (1 << (7 - (j % 8))))
1374         XDrawPoint (display, (Window) win, gc, x + j, y + i);
1375 }
1376 #endif
1377
1378 static void
1379 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1380                    int intensity, MDrawPoint *points, int num,
1381                    MDrawRegion region)
1382 {
1383   GCInfo *info = rface->info;
1384   GC gc;
1385
1386   if (! (gc = info->gc[intensity]))
1387     gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1388                                                       info, intensity);
1389   if (region)
1390     gc = set_region (frame, gc, region);
1391
1392   XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1393                (XPoint *) points, num, CoordModeOrigin);
1394 }
1395
1396
1397 static MDrawRegion
1398 mwin__region_from_rect (MDrawMetric *rect)
1399 {
1400   MDrawRegion region1 = XCreateRegion ();
1401   MDrawRegion region2 = XCreateRegion ();
1402   XRectangle xrect;
1403
1404   xrect.x = rect->x;
1405   xrect.y = rect->y;
1406   xrect.width = rect->width;
1407   xrect.height = rect->height;
1408   XUnionRectWithRegion (&xrect, region1, region2);
1409   XDestroyRegion (region1);
1410   return region2;
1411 }
1412
1413 static void
1414 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1415 {
1416   MDrawRegion region1 = XCreateRegion ();
1417   XRectangle xrect;
1418
1419   xrect.x = rect->x;
1420   xrect.y = rect->y;
1421   xrect.width = rect->width;
1422   xrect.height = rect->height;
1423
1424   XUnionRegion (region, region, region1);
1425   XUnionRectWithRegion (&xrect, region1, region);
1426   XDestroyRegion (region1);
1427 }
1428
1429 static void
1430 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1431 {
1432   MDrawRegion region = XCreateRegion ();
1433
1434   XUnionRegion (region1, region1, region);
1435   XIntersectRegion (region, region2, region1);
1436   XDestroyRegion (region);
1437 }
1438
1439 static void
1440 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1441 {
1442   MDrawRegion region1 = XCreateRegion ();
1443   XRectangle xrect;
1444
1445   xrect.x = rect->x;
1446   xrect.y = rect->y;
1447   xrect.width = rect->width;
1448   xrect.height = rect->height;
1449   XUnionRectWithRegion (&xrect, region1, region);
1450   XDestroyRegion (region1);
1451 }
1452
1453 static void
1454 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1455 {
1456   XRectangle xrect;
1457
1458   XClipBox (region, &xrect);
1459   rect->x = xrect.x;
1460   rect->y = xrect.y;
1461   rect->width = xrect.width;
1462   rect->height = xrect.height;
1463 }
1464
1465 static void
1466 mwin__free_region (MDrawRegion region)
1467 {
1468   XDestroyRegion (region);
1469 }
1470
1471 static void
1472 mwin__dump_region (MDrawRegion region)
1473 {
1474   XRectangle rect;
1475   XClipBox (region, &rect);
1476   fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1477 }
1478
1479
1480 static MDrawWindow
1481 mwin__create_window (MFrame *frame, MDrawWindow parent)
1482 {
1483   Display *display = FRAME_DISPLAY (frame);
1484   Window win;
1485   XWMHints wm_hints = { InputHint, False };
1486   XClassHint class_hints = { "M17N-IM", "m17n-im" };
1487   XSetWindowAttributes set_attrs;
1488   unsigned long mask;
1489   XGCValues values;
1490   GCInfo *info = frame->rface->info;
1491
1492   if (! parent)
1493     parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1494   mask = GCForeground;
1495   XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1496   set_attrs.background_pixel = values.foreground;
1497   set_attrs.backing_store = Always;
1498   set_attrs.override_redirect = True;
1499   set_attrs.save_under = True;
1500   mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1501   win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1502                        CopyFromParent, InputOutput, CopyFromParent,
1503                        mask, &set_attrs);
1504   XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1505                     NULL, &wm_hints, &class_hints);
1506   XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1507   return (MDrawWindow) win;
1508 }
1509
1510 static void
1511 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1512 {
1513   XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1514 }
1515
1516 #if 0
1517 static MDrawWindow
1518 mwin__event_window (void *event)
1519 {
1520   return ((MDrawWindow) ((XEvent *) event)->xany.window);
1521 }
1522
1523 static void
1524 mwin__print_event (void *arg, char *win_name)
1525 {
1526   char *event_name;
1527   XEvent *event = (XEvent *) arg;
1528
1529   switch (event->xany.type)
1530     {
1531     case 2: event_name = "KeyPress"; break;
1532     case 3: event_name = "KeyRelease"; break;
1533     case 4: event_name = "ButtonPress"; break;
1534     case 5: event_name = "ButtonRelease"; break;
1535     case 6: event_name = "MotionNotify"; break;
1536     case 7: event_name = "EnterNotify"; break;
1537     case 8: event_name = "LeaveNotify"; break;
1538     case 9: event_name = "FocusIn"; break;
1539     case 10: event_name = "FocusOut"; break;
1540     case 11: event_name = "KeymapNotify"; break;
1541     case 12: event_name = "Expose"; break;
1542     case 13: event_name = "GraphicsExpose"; break;
1543     case 14: event_name = "NoExpose"; break;
1544     case 15: event_name = "VisibilityNotify"; break;
1545     case 16: event_name = "CreateNotify"; break;
1546     case 17: event_name = "DestroyNotify"; break;
1547     case 18: event_name = "UnmapNotify"; break;
1548     case 19: event_name = "MapNotify"; break;
1549     case 20: event_name = "MapRequest"; break;
1550     case 21: event_name = "ReparentNotify"; break;
1551     case 22: event_name = "ConfigureNotify"; break;
1552     case 23: event_name = "ConfigureRequest"; break;
1553     case 24: event_name = "GravityNotify"; break;
1554     case 25: event_name = "ResizeRequest"; break;
1555     case 26: event_name = "CirculateNotify"; break;
1556     case 27: event_name = "CirculateRequest"; break;
1557     case 28: event_name = "PropertyNotify"; break;
1558     case 29: event_name = "SelectionClear"; break;
1559     case 30: event_name = "SelectionRequest"; break;
1560     case 31: event_name = "SelectionNotify"; break;
1561     case 32: event_name = "ColormapNotify"; break;
1562     case 33: event_name = "ClientMessage"; break;
1563     case 34: event_name = "MappingNotify"; break;
1564     default: event_name = "unknown";
1565     }
1566
1567   fprintf (stderr, "%s: %s\n", win_name, event_name);
1568 }
1569 #endif
1570
1571 static void
1572 mwin__map_window (MFrame *frame, MDrawWindow win)
1573 {
1574   XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1575 }
1576
1577 static void
1578 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1579 {
1580   XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1581 }
1582
1583 static void
1584 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1585                        MDrawMetric *geometry)
1586 {
1587   Display *display = FRAME_DISPLAY (frame);
1588   XWindowAttributes attr;
1589   Window parent = (Window) parent_win, root;
1590
1591   XGetWindowAttributes (display, (Window) win, &attr);
1592   geometry->x = attr.x + attr.border_width;
1593   geometry->y = attr.y + attr.border_width;
1594   geometry->width = attr.width;
1595   geometry->height = attr.height; 
1596
1597   if (! parent)
1598     parent = RootWindow (display, FRAME_SCREEN (frame));
1599   while (1)
1600     {
1601       Window this_parent, *children;
1602       unsigned n;
1603
1604       XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1605       if (children)
1606         XFree (children);
1607       if (this_parent == parent || this_parent == root)
1608         break;
1609       win = (MDrawWindow) this_parent;
1610       XGetWindowAttributes (display, (Window) win, &attr);
1611       geometry->x += attr.x + attr.border_width;
1612       geometry->y += attr.y + attr.border_width;
1613     }
1614 }
1615
1616 static void
1617 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1618                      MDrawMetric *current, MDrawMetric *new)
1619 {
1620   Display *display = FRAME_DISPLAY (frame);
1621   unsigned int mask = 0;
1622   XWindowChanges values;
1623
1624   if (current->width != new->width)
1625     {
1626       mask |= CWWidth;
1627       if (new->width <= 0)
1628         new->width = 1;
1629       values.width = current->width = new->width;
1630     }
1631   if (current->height != new->height)
1632     {
1633       mask |= CWHeight;
1634       if (new->height <= 0)
1635         new->height = 1;
1636       values.height = current->height = new->height;
1637     }
1638   if (current->x != new->x)
1639     {
1640       mask |= CWX;
1641       values.x = current->x = new->x;
1642     }
1643   if (current->y != new->y)
1644     {
1645       mask |= CWY;
1646       current->y = new->y;
1647       values.y = current->y = new->y;
1648     }
1649   if (mask)
1650     XConfigureWindow (display, (Window) win, mask, &values);
1651   XClearWindow (display, (Window) win);
1652 }
1653
1654 static MSymbol
1655 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1656 {
1657   XEvent *event = (XEvent *) arg;
1658   MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1659   int len;
1660   char buf[512];
1661   KeySym keysym;
1662   MSymbol key;
1663
1664   *modifiers = 0;
1665   if (event->xany.type != KeyPress
1666       /* && event->xany.type != KeyRelease */
1667       )
1668     return Mnil;
1669   len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1670   if (len > 1)
1671     return Mnil;
1672   if (len == 1)
1673     {
1674       int c = keysym;
1675
1676       if (c < XK_space || c > XK_asciitilde)
1677         c = buf[0];
1678       if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1679         *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1680       if (((XKeyEvent *) event)->state & ControlMask)
1681         {
1682           if (c >= 'a' && c <= 'z')
1683             c += 'A' - 'a';
1684           if (c >= ' ' && c < 127)
1685             *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1686         }
1687       key = minput__char_to_key (c);
1688     }
1689   else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1690     return Mnil;
1691   else
1692     {
1693       char *str = XKeysymToString (keysym);
1694
1695       if (! str)
1696         return Mnil;
1697       key = msymbol (str);
1698       if (((XKeyEvent *) event)->state & ShiftMask)
1699         *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1700       if (((XKeyEvent *) event)->state & ControlMask)
1701         *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1702     }
1703   if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1704     *modifiers |= MINPUT_KEY_META_MODIFIER;
1705   if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1706     *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1707   if (((XKeyEvent *) event)->state & disp_info->super_mask)
1708     *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1709   if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1710     *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1711
1712   return key;
1713 }
1714
1715
1716 void
1717 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1718 {
1719   unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1720   XGCValues values;
1721   Display *display = FRAME_DISPLAY (frame);
1722   GCInfo *info = rface->info;
1723   int i;
1724
1725   for (i = 0; i <= GC_INVERSE; i++)
1726     {
1727       XGetGCValues (display, info->gc[i], valuemask, &values);
1728       fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1729                values.foreground, values.background);
1730       fprintf (stderr, "\n");
1731     }
1732 }
1733
1734 static MDeviceDriver x_driver =
1735   {
1736     mwin__close_device,
1737     mwin__device_get_prop,
1738     mwin__realize_face,
1739     mwin__free_realized_face,
1740     mwin__fill_space,
1741     mwin__draw_empty_boxes,
1742     mwin__draw_hline,
1743     mwin__draw_box,
1744     mwin__draw_points,
1745     mwin__region_from_rect,
1746     mwin__union_rect_with_region,
1747     mwin__intersect_region,
1748     mwin__region_add_rect,
1749     mwin__region_to_rect,
1750     mwin__free_region,
1751     mwin__dump_region,
1752     mwin__create_window,
1753     mwin__destroy_window,
1754     mwin__map_window,
1755     mwin__unmap_window,
1756     mwin__window_geometry,
1757     mwin__adjust_window,
1758     mwin__parse_event
1759   };
1760
1761 /* Functions to be stored in MDeviceLibraryInterface by dlsym ().  */
1762
1763 int
1764 device_init ()
1765 {
1766   M_iso8859_1 = msymbol ("iso8859-1");
1767   M_iso10646_1 = msymbol ("iso10646-1");
1768
1769   display_info_list = mplist ();
1770   device_list = mplist ();
1771
1772 #ifdef HAVE_XFT2
1773   xft_driver.select = mfont__ft_driver.select;
1774   xft_driver.encode_char = mfont__ft_driver.encode_char;
1775 #endif
1776
1777   Mxim = msymbol ("xim");
1778   msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1779
1780   return 0;
1781 }
1782
1783 int
1784 device_fini ()
1785 {
1786   M17N_OBJECT_UNREF (display_info_list);
1787   M17N_OBJECT_UNREF (device_list);
1788   return 0;
1789 }
1790
1791 /** Return an MWDevice object corresponding to a display specified in
1792     PLIST.
1793
1794     It searches device_list for a device matching the display.  If
1795     found, return the found object.  Otherwise, return a newly created
1796     object.  */
1797
1798 int
1799 device_open (MFrame *frame, MPlist *param)
1800 {
1801   Display *display = NULL;
1802   Screen *screen = NULL;
1803   int screen_num;
1804   Drawable drawable = 0;
1805   Widget widget = NULL;
1806   Colormap cmap = 0;
1807   int auto_display = 0;
1808   MDisplayInfo *disp_info = NULL;
1809   MWDevice *device = NULL;
1810   MSymbol key;
1811   XWindowAttributes attr;
1812   unsigned depth = 0;
1813   MPlist *plist;
1814   AppData app_data;
1815   MFace *face;
1816
1817   for (plist = param; (key = mplist_key (plist)) != Mnil;
1818        plist = mplist_next (plist))
1819     {
1820       if (key == Mdisplay)
1821         display = (Display *) mplist_value (plist);
1822       else if (key == Mscreen)
1823         screen = mplist_value (plist);
1824       else if (key == Mdrawable)
1825         drawable = (Drawable) mplist_value (plist);
1826       else if (key == Mdepth)
1827         depth = (unsigned) mplist_value (plist);
1828       else if (key == Mwidget)
1829         widget = (Widget) mplist_value (plist);
1830       else if (key == Mcolormap)
1831         cmap = (Colormap) mplist_value (plist);
1832     }
1833
1834   if (widget)
1835     {
1836       display = XtDisplay (widget);
1837       screen_num = XScreenNumberOfScreen (XtScreen (widget));
1838       depth = DefaultDepth (display, screen_num);
1839     }
1840   else if (drawable)
1841     {
1842       Window root_window;
1843       int x, y;
1844       unsigned width, height, border_width;
1845
1846       if (! display)
1847         MERROR (MERROR_WIN, -1);
1848       XGetGeometry (display, drawable, &root_window,
1849                     &x, &y, &width, &height, &border_width, &depth);
1850       XGetWindowAttributes (display, root_window, &attr);
1851       screen_num = XScreenNumberOfScreen (attr.screen);
1852     }
1853   else
1854     {
1855       if (screen)
1856         display = DisplayOfScreen (screen);
1857       else
1858         {
1859           if (! display)
1860             {
1861               display = XOpenDisplay (NULL);
1862               if (! display)
1863                 MERROR (MERROR_WIN, -1);
1864               auto_display = 1;
1865             }
1866           screen = DefaultScreenOfDisplay (display);
1867         }
1868       screen_num = XScreenNumberOfScreen (screen);
1869       if (! depth)
1870         depth = DefaultDepth (display, screen_num);
1871     }
1872
1873   if (! cmap)
1874     cmap = DefaultColormap (display, screen_num);
1875
1876   for (plist = display_info_list; mplist_key (plist) != Mnil;
1877        plist = mplist_next (plist))
1878     {
1879       disp_info = (MDisplayInfo *) mplist_value (plist);
1880       if (disp_info->display == display)
1881         break;
1882     }
1883
1884   if (mplist_key (plist) != Mnil)
1885     M17N_OBJECT_REF (disp_info);
1886   else
1887     {
1888       M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
1889       disp_info->display = display;
1890       disp_info->auto_display = auto_display;
1891       disp_info->font_list = mplist ();
1892       disp_info->base_font_list = mplist ();
1893       find_modifier_bits (disp_info);
1894       mplist_add (display_info_list, Mt, disp_info);
1895     }  
1896
1897   for (plist = device_list; mplist_key (plist) != Mnil;
1898        plist = mplist_next (plist))
1899     {
1900       device = (MWDevice *) mplist_value (plist);
1901       if (device->display_info == disp_info
1902           && device->depth == depth
1903           && device->cmap == cmap)
1904         break;
1905     }
1906
1907   if (mplist_key (plist) != Mnil)
1908     M17N_OBJECT_REF (device);
1909   else
1910     {
1911       unsigned long valuemask = GCForeground;
1912       XGCValues values;
1913
1914       M17N_OBJECT (device, free_device, MERROR_WIN);
1915       device->display_info = disp_info;
1916       device->screen_num = screen_num;
1917       /* A drawable on which to create GCs.  */
1918       device->drawable = XCreatePixmap (display,
1919                                         RootWindow (display, screen_num),
1920                                         1, 1, depth);
1921       device->depth = depth;
1922       device->cmap = cmap;
1923       device->realized_face_list = mplist ();
1924       device->realized_font_list = mplist ();
1925       device->realized_fontset_list = mplist ();
1926       device->gc_list = mplist ();
1927       values.foreground = BlackPixel (display, screen_num);
1928       device->scratch_gc = XCreateGC (display, device->drawable,
1929                                       valuemask, &values);
1930 #ifdef HAVE_XFT2
1931       device->xft_draw = XftDrawCreate (display, device->drawable,
1932                                         DefaultVisual (display, screen_num),
1933                                         cmap);
1934 #endif
1935     }
1936
1937   frame->device = device;
1938   frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
1939   frame->driver = &x_driver;
1940   frame->font_driver_list = mplist ();
1941   mplist_add (frame->font_driver_list, Mx, &xfont_driver);
1942 #ifdef HAVE_XFT2
1943   mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
1944 #elif HAVE_FREETYPE
1945   mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
1946 #endif
1947   frame->realized_font_list = device->realized_font_list;
1948   frame->realized_face_list = device->realized_face_list;
1949   frame->realized_fontset_list = device->realized_fontset_list;
1950
1951   if (widget)
1952     {
1953       XtResource resources[] = {
1954         { XtNfont, XtCFont, XtRString, sizeof (String),
1955           XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
1956         { XtNforeground, XtCForeground, XtRString, sizeof (String),
1957           XtOffset (AppDataPtr, foreground), XtRString, "black" },
1958         { XtNbackground, XtCBackground, XtRString, sizeof (String),
1959           XtOffset (AppDataPtr, background), XtRString, "white" },
1960         { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
1961           XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
1962       };
1963
1964       XtGetApplicationResources (widget, &app_data,
1965                                  resources, XtNumber (resources), NULL, 0);
1966       frame->foreground = msymbol (app_data.foreground);
1967       frame->background = msymbol (app_data.background);
1968       frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
1969     }
1970   else
1971     {
1972       app_data.font = DEFAULT_FONT;
1973       frame->foreground = msymbol ("black");
1974       frame->background = msymbol ("white");
1975       frame->videomode = Mnormal;
1976     }
1977
1978   {
1979     int nfonts;
1980     char **names = XListFonts (display, app_data.font, 1, &nfonts);
1981
1982     if (nfonts > 0)
1983       {
1984         if (! (frame->font = mfont_parse_name (names[0], Mx)))
1985           {
1986             /* The font name does not conform to XLFD.  Try to open the
1987                font and get XA_FONT property.  */
1988             XFontStruct *xfont = XLoadQueryFont (display, names[0]);
1989
1990             nfonts = 0;
1991             if (xfont)
1992               {
1993                 unsigned long value;
1994                 char *name;
1995
1996                 if (XGetFontProperty (xfont, XA_FONT, &value)
1997                     && (name = ((char *)
1998                                 XGetAtomName (display, (Atom) value))))
1999                   {
2000                     if ((frame->font = mfont_parse_name (name, Mx)))
2001                       nfonts = 1;
2002                   }
2003                 XFreeFont (display, xfont);
2004               }
2005           }
2006         XFreeFontNames (names);
2007       }
2008     if (! nfonts)
2009       frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
2010   }
2011
2012   face = mface_from_font (frame->font);
2013   face->property[MFACE_FONTSET] = mfontset (NULL);
2014   face->property[MFACE_FOREGROUND] = frame->foreground;
2015   face->property[MFACE_BACKGROUND] = frame->background;
2016   mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2017   mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2018   face->property[MFACE_VIDEOMODE] = frame->videomode;
2019   mface_put_prop (face, Mhook_func, 
2020                   mface_get_prop (mface__default, Mhook_func));
2021   face->property[MFACE_RATIO] = (void *) 100;
2022   mplist_push (param, Mface, face);
2023   M17N_OBJECT_UNREF (face);
2024
2025 #ifdef X_SET_ERROR_HANDLER
2026   XSetErrorHandler (x_error_handler);
2027   XSetIOErrorHandler (x_io_error_handler);
2028 #endif
2029
2030   return 0;
2031 }
2032
2033 \f
2034
2035 /* XIM (X Input Method) handler */
2036
2037 typedef struct MInputXIMMethodInfo
2038 {
2039   Display *display;
2040   XIM xim;
2041   MSymbol language;
2042   MSymbol coding;
2043 } MInputXIMMethodInfo;
2044
2045 typedef struct MInputXIMContextInfo
2046 {
2047   XIC xic;
2048   Window win;
2049   MConverter *converter;
2050 } MInputXIMContextInfo;
2051
2052 static int
2053 xim_open_im (MInputMethod *im)
2054 {
2055   MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2056   MLocale *saved, *this;
2057   char *save_modifier_list;
2058   XIM xim;
2059   MInputXIMMethodInfo *im_info;
2060
2061   saved = mlocale_set (LC_CTYPE, NULL);
2062   this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2063   if (! this)
2064     /* The specified locale is not supported.  */
2065     MERROR (MERROR_LOCALE, -1);
2066   if (mlocale_get_prop (this, Mcoding) == Mnil)
2067     {
2068       /* Unable to decode the output of XIM.  */
2069       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2070       MERROR (MERROR_LOCALE, -1);
2071     }
2072
2073   if (arg->modifier_list)
2074     save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2075   else
2076     save_modifier_list = XSetLocaleModifiers ("");
2077   if (! save_modifier_list)
2078     {
2079       /* The specified locale is not supported by X.  */
2080       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2081       MERROR (MERROR_LOCALE, -1);
2082     }
2083
2084   xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2085   if (! xim)
2086     {
2087       /* No input method is available in the current locale.  */
2088       XSetLocaleModifiers (save_modifier_list);
2089       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2090       MERROR (MERROR_WIN, -1);
2091     }
2092
2093   MSTRUCT_MALLOC (im_info, MERROR_WIN);
2094   im_info->display = arg->display;
2095   im_info->xim = xim;
2096   im_info->language = mlocale_get_prop (this, Mlanguage);
2097   im_info->coding = mlocale_get_prop (this, Mcoding);
2098   im->info = im_info;
2099
2100   XSetLocaleModifiers (save_modifier_list);
2101   mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2102
2103   return 0;
2104 }
2105
2106 static void
2107 xim_close_im (MInputMethod *im)
2108 {
2109   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2110
2111   XCloseIM (im_info->xim);
2112   free (im_info);
2113 }
2114
2115 static int
2116 xim_create_ic (MInputContext *ic)
2117 {
2118   MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2119   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2120   MInputXIMContextInfo *ic_info;
2121   XIC xic;
2122
2123   if (! arg->input_style)
2124     {
2125       /* By default, use Root style.  */
2126       arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2127       arg->preedit_attrs = NULL;
2128       arg->status_attrs = NULL;
2129     }
2130
2131   if (! arg->preedit_attrs && ! arg->status_attrs)
2132     xic = XCreateIC (im_info->xim,
2133                      XNInputStyle, arg->input_style,
2134                      XNClientWindow, arg->client_win,
2135                      XNFocusWindow, arg->focus_win,
2136                      NULL);
2137   else if (arg->preedit_attrs && ! arg->status_attrs)
2138     xic = XCreateIC (im_info->xim,
2139                      XNInputStyle, arg->input_style,
2140                      XNClientWindow, arg->client_win,
2141                      XNFocusWindow, arg->focus_win,
2142                      XNPreeditAttributes, arg->preedit_attrs,
2143                      NULL);
2144   else if (! arg->preedit_attrs && arg->status_attrs)
2145     xic = XCreateIC (im_info->xim,
2146                      XNInputStyle, arg->input_style,
2147                      XNClientWindow, arg->client_win,
2148                      XNFocusWindow, arg->focus_win,
2149                      XNStatusAttributes, arg->status_attrs,
2150                      NULL);
2151   else
2152     xic = XCreateIC (im_info->xim,
2153                      XNInputStyle, arg->input_style,
2154                      XNClientWindow, arg->client_win,
2155                      XNFocusWindow, arg->focus_win,
2156                      XNPreeditAttributes, arg->preedit_attrs,
2157                      XNStatusAttributes, arg->status_attrs,
2158                      NULL);
2159   if (! xic)
2160     MERROR (MERROR_WIN, -1);
2161
2162   MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2163   ic_info->xic = xic;
2164   ic_info->win = arg->focus_win;
2165   ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2166   ic->info = ic_info;
2167   return 0;
2168 }
2169
2170 static void
2171 xim_destroy_ic (MInputContext *ic)
2172 {
2173   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2174
2175   XDestroyIC (ic_info->xic);
2176   mconv_free_converter (ic_info->converter);
2177   free (ic_info);
2178   ic->info = NULL;
2179 }
2180
2181 static int
2182 xim_filter (MInputContext *ic, MSymbol key, void *event)
2183 {
2184   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2185
2186   return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2187 }
2188
2189
2190 static int
2191 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2192 {
2193   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2194   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2195   XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2196   KeySym keysym;
2197   Status status;
2198   char *buf;
2199   int len;
2200
2201   buf = (char *) alloca (512);
2202   len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2203   if (status == XBufferOverflow)
2204     {
2205       buf = (char *) alloca (len);
2206       len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2207     }
2208
2209   mtext_reset (ic->produced);
2210   if (len == 0)
2211     return 1;
2212
2213   mconv_reset_converter (ic_info->converter);
2214   mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2215   mconv_decode (ic_info->converter, ic->produced);
2216   mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2217                   Mlanguage, (void *) im_info->language);
2218   mtext_cpy (mt, ic->produced);
2219   mtext_reset (ic->produced);  
2220   return 0;
2221 }
2222
2223 \f
2224
2225 #ifdef X_SET_ERROR_HANDLER
2226 static int
2227 x_error_handler (Display *display, XErrorEvent *error)
2228 {
2229   mdebug_hook ();
2230   return 0;
2231 }
2232
2233 static int
2234 x_io_error_handler (Display *display)
2235 {
2236   mdebug_hook ();
2237   return 0;
2238 }
2239 #endif
2240
2241 /*=*/
2242
2243 /*** @} */
2244 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2245 \f
2246 /* External API */
2247
2248 /*** @addtogroup m17nInputMethodWin */
2249 /*=*/
2250 /*** @{ */
2251
2252 /***en
2253     @brief Input method driver for XIM.
2254
2255     The driver #minput_xim_driver is for the foreign input method of
2256     name #Mxim.  It uses XIM (X Input Methods) as a background input
2257     engine.
2258
2259     As the symbol #Mxim has property #Minput_driver whose value is
2260     a pointer to this driver, the input method of language #Mnil
2261     and name #Mxim uses this driver.
2262
2263     Therefore, for such input methods, the driver dependent arguments
2264     to the functions whose name begin with minput_ must be as follows.
2265
2266     The argument $ARG of the function minput_open_im () must be a
2267     pointer to the structure #MInputXIMArgIM.  See the documentation
2268     of #MInputXIMArgIM for more details.
2269
2270     The argument $ARG of the function minput_create_ic () must be a
2271     pointer to the structure #MInputXIMArgIC. See the documentation
2272     of #MInputXIMArgIC for more details.
2273
2274     The argument $ARG of the function minput_filter () must be a
2275     pointer to the structure @c XEvent.  The argument $KEY is ignored.
2276
2277     The argument $ARG of the function minput_lookup () must be the
2278     same one as that of the function minput_filter ().  The argument
2279     $KEY is ignored.  */
2280
2281 /***ja
2282     @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2283
2284     ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
2285     ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
2286     ¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
2287
2288     ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2289     #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
2290     ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2291
2292     ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
2293     ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2294
2295     ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIM ¤Ø¤Î¥Ý
2296     ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
2297     »²¾È¡£
2298
2299     ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIC ¤Ø¤Î
2300     ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
2301     ¤ò»²¾È¡£
2302
2303     ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ@c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2304     ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2305
2306     ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter () 
2307     ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2308     ¤ë¡£  */
2309
2310 MInputDriver minput_xim_driver =
2311   { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2312     xim_filter, xim_lookup, NULL };
2313
2314 /*** @} */ 
2315
2316 /*
2317   Local Variables:
2318   coding: euc-japan
2319   End:
2320 */