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