(mwin__parse_event): Fix handling of Shift and Control
[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;
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 (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1975     return Mnil;
1976   if (len == 1 && keysym >= XK_space && keysym <= XK_asciitilde)
1977     {
1978       int c = keysym;
1979
1980       key = minput__char_to_key (c);
1981       if (c == ' ' && ((XKeyEvent *) event)->state & ShiftMask)
1982         *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1983     }
1984   else
1985     {
1986       char *str = XKeysymToString (keysym);
1987
1988       if (! str)
1989         return Mnil;
1990       key = msymbol (str);
1991       if (((XKeyEvent *) event)->state & ShiftMask)
1992         *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1993     }
1994   if (((XKeyEvent *) event)->state & ControlMask)
1995     *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1996   if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1997     *modifiers |= MINPUT_KEY_META_MODIFIER;
1998   if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1999     *modifiers |= MINPUT_KEY_ALT_MODIFIER;
2000   if (((XKeyEvent *) event)->state & disp_info->super_mask)
2001     *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
2002   if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
2003     *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
2004
2005   return key;
2006 }
2007
2008
2009 void
2010 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
2011 {
2012   unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
2013   XGCValues values;
2014   Display *display = FRAME_DISPLAY (frame);
2015   GCInfo *info = rface->info;
2016   int i;
2017
2018   for (i = 0; i <= GC_INVERSE; i++)
2019     {
2020       XGetGCValues (display, info->gc[i], valuemask, &values);
2021       fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
2022                values.foreground, values.background);
2023       fprintf (stderr, "\n");
2024     }
2025 }
2026
2027 static MDeviceDriver x_driver =
2028   {
2029     mwin__close_device,
2030     mwin__device_get_prop,
2031     mwin__realize_face,
2032     mwin__free_realized_face,
2033     mwin__fill_space,
2034     mwin__draw_empty_boxes,
2035     mwin__draw_hline,
2036     mwin__draw_box,
2037     mwin__draw_points,
2038     mwin__region_from_rect,
2039     mwin__union_rect_with_region,
2040     mwin__intersect_region,
2041     mwin__region_add_rect,
2042     mwin__region_to_rect,
2043     mwin__free_region,
2044     mwin__dump_region,
2045     mwin__create_window,
2046     mwin__destroy_window,
2047     mwin__map_window,
2048     mwin__unmap_window,
2049     mwin__window_geometry,
2050     mwin__adjust_window,
2051     mwin__parse_event
2052   };
2053
2054 /* Functions to be stored in MDeviceLibraryInterface by dlsym ().  */
2055
2056 int
2057 device_init ()
2058 {
2059   M_iso8859_1 = msymbol ("iso8859-1");
2060   M_iso10646_1 = msymbol ("iso10646-1");
2061
2062   display_info_list = mplist ();
2063   device_list = mplist ();
2064
2065 #ifdef HAVE_XFT2
2066   xft_driver.select = mfont__ft_driver.select;
2067   xft_driver.list = mfont__ft_driver.list;
2068   xft_driver.list_family_names = mfont__ft_driver.list_family_names;
2069 #endif
2070
2071   Mxim = msymbol ("xim");
2072   msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
2073
2074   return 0;
2075 }
2076
2077 int
2078 device_fini ()
2079 {
2080   M17N_OBJECT_UNREF (display_info_list);
2081   M17N_OBJECT_UNREF (device_list);
2082   return 0;
2083 }
2084
2085
2086 #ifdef X_SET_ERROR_HANDLER
2087 static int
2088 x_error_handler (Display *display, XErrorEvent *error)
2089 {
2090   mdebug_hook ();
2091   return 0;
2092 }
2093
2094 static int
2095 x_io_error_handler (Display *display)
2096 {
2097   mdebug_hook ();
2098   return 0;
2099 }
2100 #endif
2101
2102 /** Return an MWDevice object corresponding to a display specified in
2103     PLIST.
2104
2105     It searches device_list for a device matching the display.  If
2106     found, return the found object.  Otherwise, return a newly created
2107     object.  */
2108
2109 int
2110 device_open (MFrame *frame, MPlist *param)
2111 {
2112   Display *display = NULL;
2113   Screen *screen = NULL;
2114   int screen_num;
2115   Drawable drawable = 0;
2116   Widget widget = NULL;
2117   Colormap cmap = 0;
2118   int auto_display = 0;
2119   MDisplayInfo *disp_info = NULL;
2120   MWDevice *device = NULL;
2121   MSymbol key;
2122   XWindowAttributes attr;
2123   unsigned depth = 0;
2124   MPlist *plist;
2125   AppData app_data;
2126   MFont *font = NULL;
2127   MFace *face;
2128   int use_xfont = 0, use_freetype = 0, use_xft = 0;
2129
2130   for (plist = param; (key = mplist_key (plist)) != Mnil;
2131        plist = mplist_next (plist))
2132     {
2133       if (key == Mdisplay)
2134         display = (Display *) mplist_value (plist);
2135       else if (key == Mscreen)
2136         screen = mplist_value (plist);
2137       else if (key == Mdrawable)
2138         drawable = (Drawable) mplist_value (plist);
2139       else if (key == Mdepth)
2140         depth = (unsigned) mplist_value (plist);
2141       else if (key == Mwidget)
2142         widget = (Widget) mplist_value (plist);
2143       else if (key == Mcolormap)
2144         cmap = (Colormap) mplist_value (plist);
2145       else if (key == Mfont)
2146         {
2147           MSymbol val = MPLIST_SYMBOL (plist);
2148
2149           if (val == Mx)
2150             use_xfont = 1;
2151 #ifdef HAVE_FREETYPE
2152           else if (val == Mfreetype)
2153             use_freetype = 1;
2154 #ifdef HAVE_XFT2
2155           else if (val == Mxft)
2156             use_xft = 1;
2157 #endif
2158 #endif
2159         }
2160     }
2161
2162   /* If none of them is specified, use all of them.  */
2163   if (! use_xfont && ! use_freetype && ! use_xft)
2164     use_xfont = use_freetype = use_xft = 1;
2165
2166   if (widget)
2167     {
2168       display = XtDisplay (widget);
2169       screen_num = XScreenNumberOfScreen (XtScreen (widget));
2170       depth = DefaultDepth (display, screen_num);
2171     }
2172   else if (drawable)
2173     {
2174       Window root_window;
2175       int x, y;
2176       unsigned width, height, border_width;
2177
2178       if (! display)
2179         MERROR (MERROR_WIN, -1);
2180       XGetGeometry (display, drawable, &root_window,
2181                     &x, &y, &width, &height, &border_width, &depth);
2182       XGetWindowAttributes (display, root_window, &attr);
2183       screen_num = XScreenNumberOfScreen (attr.screen);
2184     }
2185   else
2186     {
2187       if (screen)
2188         display = DisplayOfScreen (screen);
2189       else
2190         {
2191           if (! display)
2192             {
2193               display = XOpenDisplay (NULL);
2194               if (! display)
2195                 MERROR (MERROR_WIN, -1);
2196               auto_display = 1;
2197             }
2198           screen = DefaultScreenOfDisplay (display);
2199         }
2200       screen_num = XScreenNumberOfScreen (screen);
2201       if (! depth)
2202         depth = DefaultDepth (display, screen_num);
2203     }
2204
2205   if (! cmap)
2206     cmap = DefaultColormap (display, screen_num);
2207
2208   for (plist = display_info_list; mplist_key (plist) != Mnil;
2209        plist = mplist_next (plist))
2210     {
2211       disp_info = (MDisplayInfo *) mplist_value (plist);
2212       if (disp_info->display == display)
2213         break;
2214     }
2215
2216   if (mplist_key (plist) != Mnil)
2217     M17N_OBJECT_REF (disp_info);
2218   else
2219     {
2220       M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
2221       disp_info->display = display;
2222       disp_info->auto_display = auto_display;
2223       disp_info->font_list = mplist ();
2224       find_modifier_bits (disp_info);
2225       disp_info->MULE_BASELINE_OFFSET
2226         = XInternAtom (display, "_MULE_BASELINE_OFFSET", False);
2227       disp_info->AVERAGE_WIDTH
2228         = XInternAtom (display, "AVERAGE_WIDTH", False);
2229       mplist_add (display_info_list, Mt, disp_info);
2230     }  
2231
2232   for (plist = device_list; mplist_key (plist) != Mnil;
2233        plist = mplist_next (plist))
2234     {
2235       device = (MWDevice *) mplist_value (plist);
2236       if (device->display_info == disp_info
2237           && device->depth == depth
2238           && device->cmap == cmap
2239           && device->screen_num == screen_num)
2240         break;
2241     }
2242
2243   if (mplist_key (plist) != Mnil)
2244     M17N_OBJECT_REF (device);
2245   else
2246     {
2247       unsigned long valuemask = GCForeground;
2248       XGCValues values;
2249       double pixels, mm;
2250
2251       M17N_OBJECT (device, free_device, MERROR_WIN);
2252       device->display_info = disp_info;
2253       device->screen_num = screen_num;
2254       /* A drawable on which to create GCs.  */
2255       device->drawable = XCreatePixmap (display,
2256                                         RootWindow (display, screen_num),
2257                                         1, 1, depth);
2258       device->depth = depth;
2259       device->cmap = cmap;
2260       pixels = DisplayHeight (display, screen_num);
2261       mm = DisplayHeightMM (display, screen_num);
2262       device->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
2263       device->realized_face_list = mplist ();
2264       device->realized_font_list = mplist ();
2265       mplist_add (device->realized_font_list, Mt, NULL);
2266       device->realized_fontset_list = mplist ();
2267       device->gc_list = mplist ();
2268       values.foreground = BlackPixel (display, screen_num);
2269       device->scratch_gc = XCreateGC (display, device->drawable,
2270                                       valuemask, &values);
2271 #ifdef HAVE_XFT2
2272       device->xft_draw = XftDrawCreate (display, device->drawable,
2273                                         DefaultVisual (display, screen_num),
2274                                         cmap);
2275 #endif
2276     }
2277
2278   frame->device = device;
2279   frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2280   frame->dpi = device->resy;
2281   frame->driver = &x_driver;
2282   frame->font_driver_list = mplist ();
2283 #ifdef HAVE_XFT2
2284   if (use_xft)
2285     {
2286       mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2287       use_freetype = 0;
2288     }
2289 #endif  /* HAVE_XFT2 */
2290 #ifdef HAVE_FREETYPE
2291   if (use_freetype)
2292     mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2293 #endif  /* HAVE_FREETYPE */
2294   if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list))
2295     mplist_push (frame->font_driver_list, Mx, &xfont_driver);
2296
2297   frame->realized_font_list = device->realized_font_list;
2298   frame->realized_face_list = device->realized_face_list;
2299   frame->realized_fontset_list = device->realized_fontset_list;
2300
2301   if (widget)
2302     {
2303       XtResource resources[] = {
2304         { XtNfont, XtCFont, XtRString, sizeof (String),
2305           XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2306         { XtNforeground, XtCForeground, XtRString, sizeof (String),
2307           XtOffset (AppDataPtr, foreground), XtRString, "black" },
2308         { XtNbackground, XtCBackground, XtRString, sizeof (String),
2309           XtOffset (AppDataPtr, background), XtRString, "white" },
2310         { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2311           XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2312       };
2313
2314       XtGetApplicationResources (widget, &app_data,
2315                                  resources, XtNumber (resources), NULL, 0);
2316       frame->foreground = msymbol (app_data.foreground);
2317       frame->background = msymbol (app_data.background);
2318       frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2319     }
2320   else
2321     {
2322       app_data.font = DEFAULT_FONT;
2323       frame->foreground = msymbol ("black");
2324       frame->background = msymbol ("white");
2325       frame->videomode = Mnormal;
2326     }
2327
2328   if (strcmp (app_data.font, DEFAULT_FONT) != 0)
2329     {
2330       XFontStruct *xfont = XLoadQueryFont (display, app_data.font);
2331       unsigned long value;
2332       char *name;
2333
2334       if (xfont)
2335         {
2336           font = mfont_parse_name (app_data.font, Mx);
2337           if (! font
2338               && XGetFontProperty (xfont, XA_FONT, &value)
2339               && (name = ((char *) XGetAtomName (display, (Atom) value))))
2340             font = mfont_parse_name (name, Mx);
2341           XFreeFont (display, xfont);
2342         }
2343     }
2344   if (! font)
2345       font = mfont_parse_name (DEFAULT_FONT, Mx);
2346   else if (! font->size)
2347     font->size = 130;
2348   face = mface_from_font (font);
2349   free (font);
2350   face->property[MFACE_FONTSET] = mfontset (NULL);
2351   face->property[MFACE_FOREGROUND] = frame->foreground;
2352   face->property[MFACE_BACKGROUND] = frame->background;
2353   mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2354   mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2355   face->property[MFACE_VIDEOMODE] = frame->videomode;
2356   mface_put_prop (face, Mhook_func, 
2357                   mface_get_prop (mface__default, Mhook_func));
2358   face->property[MFACE_RATIO] = (void *) 100;
2359   mplist_push (param, Mface, face);
2360   M17N_OBJECT_UNREF (face);
2361
2362 #ifdef X_SET_ERROR_HANDLER
2363   XSetErrorHandler (x_error_handler);
2364   XSetIOErrorHandler (x_io_error_handler);
2365 #endif
2366   return 0;
2367 }
2368
2369 \f
2370
2371 /* XIM (X Input Method) handler */
2372
2373 typedef struct MInputXIMMethodInfo
2374 {
2375   Display *display;
2376   XIM xim;
2377   MSymbol language;
2378   MSymbol coding;
2379 } MInputXIMMethodInfo;
2380
2381 typedef struct MInputXIMContextInfo
2382 {
2383   XIC xic;
2384   Window win;
2385   MConverter *converter;
2386 } MInputXIMContextInfo;
2387
2388 static int
2389 xim_open_im (MInputMethod *im)
2390 {
2391   MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2392   MLocale *saved, *this;
2393   char *save_modifier_list;
2394   XIM xim;
2395   MInputXIMMethodInfo *im_info;
2396
2397   saved = mlocale_set (LC_CTYPE, NULL);
2398   this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2399   if (! this)
2400     /* The specified locale is not supported.  */
2401     MERROR (MERROR_LOCALE, -1);
2402   if (mlocale_get_prop (this, Mcoding) == Mnil)
2403     {
2404       /* Unable to decode the output of XIM.  */
2405       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2406       MERROR (MERROR_LOCALE, -1);
2407     }
2408
2409   if (arg->modifier_list)
2410     save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2411   else
2412     save_modifier_list = XSetLocaleModifiers ("");
2413   if (! save_modifier_list)
2414     {
2415       /* The specified locale is not supported by X.  */
2416       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2417       MERROR (MERROR_LOCALE, -1);
2418     }
2419
2420   xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2421   if (! xim)
2422     {
2423       /* No input method is available in the current locale.  */
2424       XSetLocaleModifiers (save_modifier_list);
2425       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2426       MERROR (MERROR_WIN, -1);
2427     }
2428
2429   MSTRUCT_MALLOC (im_info, MERROR_WIN);
2430   im_info->display = arg->display;
2431   im_info->xim = xim;
2432   im_info->language = mlocale_get_prop (this, Mlanguage);
2433   im_info->coding = mlocale_get_prop (this, Mcoding);
2434   im->info = im_info;
2435
2436   XSetLocaleModifiers (save_modifier_list);
2437   mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2438
2439   return 0;
2440 }
2441
2442 static void
2443 xim_close_im (MInputMethod *im)
2444 {
2445   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2446
2447   XCloseIM (im_info->xim);
2448   free (im_info);
2449 }
2450
2451 static int
2452 xim_create_ic (MInputContext *ic)
2453 {
2454   MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2455   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2456   MInputXIMContextInfo *ic_info;
2457   XIC xic;
2458
2459   if (! arg->input_style)
2460     {
2461       /* By default, use Root style.  */
2462       arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2463       arg->preedit_attrs = NULL;
2464       arg->status_attrs = NULL;
2465     }
2466
2467   if (! arg->preedit_attrs && ! arg->status_attrs)
2468     xic = XCreateIC (im_info->xim,
2469                      XNInputStyle, arg->input_style,
2470                      XNClientWindow, arg->client_win,
2471                      XNFocusWindow, arg->focus_win,
2472                      NULL);
2473   else if (arg->preedit_attrs && ! arg->status_attrs)
2474     xic = XCreateIC (im_info->xim,
2475                      XNInputStyle, arg->input_style,
2476                      XNClientWindow, arg->client_win,
2477                      XNFocusWindow, arg->focus_win,
2478                      XNPreeditAttributes, arg->preedit_attrs,
2479                      NULL);
2480   else if (! arg->preedit_attrs && arg->status_attrs)
2481     xic = XCreateIC (im_info->xim,
2482                      XNInputStyle, arg->input_style,
2483                      XNClientWindow, arg->client_win,
2484                      XNFocusWindow, arg->focus_win,
2485                      XNStatusAttributes, arg->status_attrs,
2486                      NULL);
2487   else
2488     xic = XCreateIC (im_info->xim,
2489                      XNInputStyle, arg->input_style,
2490                      XNClientWindow, arg->client_win,
2491                      XNFocusWindow, arg->focus_win,
2492                      XNPreeditAttributes, arg->preedit_attrs,
2493                      XNStatusAttributes, arg->status_attrs,
2494                      NULL);
2495   if (! xic)
2496     MERROR (MERROR_WIN, -1);
2497
2498   MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2499   ic_info->xic = xic;
2500   ic_info->win = arg->focus_win;
2501   ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2502   ic->info = ic_info;
2503   return 0;
2504 }
2505
2506 static void
2507 xim_destroy_ic (MInputContext *ic)
2508 {
2509   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2510
2511   XDestroyIC (ic_info->xic);
2512   mconv_free_converter (ic_info->converter);
2513   free (ic_info);
2514   ic->info = NULL;
2515 }
2516
2517 static int
2518 xim_filter (MInputContext *ic, MSymbol key, void *event)
2519 {
2520   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2521
2522   return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2523 }
2524
2525
2526 static int
2527 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2528 {
2529   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2530   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2531   XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2532   KeySym keysym;
2533   Status status;
2534   char *buf;
2535   int len;
2536
2537   buf = (char *) alloca (512);
2538   len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2539   if (status == XBufferOverflow)
2540     {
2541       buf = (char *) alloca (len);
2542       len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2543     }
2544
2545   mtext_reset (ic->produced);
2546   if (len == 0)
2547     return 1;
2548
2549   mconv_reset_converter (ic_info->converter);
2550   mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2551   mconv_decode (ic_info->converter, ic->produced);
2552   mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2553                   Mlanguage, (void *) im_info->language);
2554   mtext_cpy (mt, ic->produced);
2555   mtext_reset (ic->produced);  
2556   return 0;
2557 }
2558
2559 \f
2560 /*=*/
2561
2562 /*** @} */
2563 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2564 \f
2565 /* External API */
2566
2567 /*** @addtogroup m17nInputMethodWin */
2568
2569 /*** @{ */
2570
2571 /***en
2572     @brief Input method driver for XIM.
2573
2574     The driver #minput_xim_driver is for the foreign input method of
2575     name #Mxim.  It uses XIM (X Input Methods) as a background input
2576     engine.
2577
2578     As the symbol #Mxim has property #Minput_driver whose value is
2579     a pointer to this driver, the input method of language #Mnil
2580     and name #Mxim uses this driver.
2581
2582     Therefore, for such input methods, the driver dependent arguments
2583     to the functions whose name begin with minput_ must be as follows.
2584
2585     The argument $ARG of the function minput_open_im () must be a
2586     pointer to the structure #MInputXIMArgIM.  See the documentation
2587     of #MInputXIMArgIM for more details.
2588
2589     The argument $ARG of the function minput_create_ic () must be a
2590     pointer to the structure #MInputXIMArgIC. See the documentation
2591     of #MInputXIMArgIC for more details.
2592
2593     The argument $ARG of the function minput_filter () must be a
2594     pointer to the structure @c XEvent.  The argument $KEY is ignored.
2595
2596     The argument $ARG of the function minput_lookup () must be the
2597     same one as that of the function minput_filter ().  The argument
2598     $KEY is ignored.  */
2599
2600 /***ja
2601     @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2602
2603     ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ê¡¢
2604     XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
2605
2606     ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2607     #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim 
2608     ¤Ç¤¢¤ëÆþÎϥ᥽¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2609
2610     ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ 
2611     ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2612
2613     ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIM 
2614     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò»²¾È¡£
2615
2616     ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIC 
2617     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ¤ò»²¾È¡£
2618
2619     ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ@c XEvent 
2620     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2621
2622     ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter () 
2623     ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì¤ë¡£  */
2624
2625 MInputDriver minput_xim_driver =
2626   { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2627     xim_filter, xim_lookup, NULL };
2628
2629 /*** @} */ 
2630
2631 #else  /* not HAVE_X11 */
2632
2633 int device_open () { return -1; }
2634
2635 #endif  /* not HAVE_X11 */
2636
2637 /*
2638   Local Variables:
2639   coding: euc-japan
2640   End:
2641 */