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