merge FLT
[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   MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
661   free (name);
662   M17N_OBJECT (x_rfont, close_xfont, MERROR_FONT_X);
663   x_rfont->display = display;
664   x_rfont->xfont = xfont;
665   MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
666   rfont->spec = this;
667   rfont->spec.type = MFONT_TYPE_REALIZED;
668   rfont->spec.source = MFONT_SOURCE_X;
669   rfont->frame = frame;
670   rfont->font = font;
671   rfont->driver = &xfont_driver;
672   rfont->info = x_rfont;
673   {
674     MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
675     unsigned long value;
676
677     rfont->baseline_offset
678       = (XGetFontProperty (xfont, disp_info->MULE_BASELINE_OFFSET, &value)
679          ? (int) (value << 6) : 0);
680     rfont->average_width
681       = (XGetFontProperty (xfont, disp_info->AVERAGE_WIDTH, &value)
682          ? (int) (value << 6) / 10 : 0);
683   }
684   rfont->ascent = (xfont->ascent << 6) + rfont->baseline_offset;
685   rfont->descent = (xfont->descent << 6) - rfont->baseline_offset;
686   rfont->max_advance = xfont->max_bounds.width << 6;
687   rfont->x_ppem = rfont->y_ppem = size / 10;
688   rfont->fontp = xfont;
689   rfont->next = MPLIST_VAL (frame->realized_font_list);
690   MPLIST_VAL (frame->realized_font_list) = rfont;
691   return rfont;
692 }
693
694
695 /* The X font driver function FIND_METRIC.  */
696
697 static void
698 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
699                    int from, int to)
700 {
701   XFontStruct *xfont = rfont->fontp;
702   MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
703
704   for (; g != gend; g++)
705     if (! g->g.measured)
706       {
707         if (g->g.code == MCHAR_INVALID_CODE)
708           {
709             g->g.lbearing = xfont->max_bounds.lbearing << 6;
710             g->g.rbearing = xfont->max_bounds.rbearing << 6;
711             g->g.xadv = xfont->max_bounds.width << 6;
712             g->g.ascent = xfont->ascent << 6;
713             g->g.descent = xfont->descent << 6;
714           }
715         else
716           {
717             int byte1 = g->g.code >> 8, byte2 = g->g.code & 0xFF;
718             XCharStruct *pcm = NULL;
719
720             if (xfont->per_char != NULL)
721               {
722                 if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
723                   {
724                     if (byte1 == 0
725                         && byte2 >= xfont->min_char_or_byte2
726                         && byte2 <= xfont->max_char_or_byte2)
727                       pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
728                   }
729                 else
730                   {
731                     if (byte1 >= xfont->min_byte1
732                         && byte1 <= xfont->max_byte1
733                         && byte2 >= xfont->min_char_or_byte2
734                         && byte2 <= xfont->max_char_or_byte2)
735                       {
736                         pcm = (xfont->per_char
737                                + ((xfont->max_char_or_byte2
738                                    - xfont->min_char_or_byte2 + 1)
739                                   * (byte1 - xfont->min_byte1))
740                                + (byte2 - xfont->min_char_or_byte2));
741                       }
742                   }
743               }
744
745             if (pcm)
746               {
747                 g->g.lbearing = pcm->lbearing << 6;
748                 g->g.rbearing = pcm->rbearing << 6;
749                 g->g.xadv = pcm->width << 6;
750                 g->g.ascent = pcm->ascent << 6;
751                 g->g.descent = pcm->descent << 6;
752               }
753             else
754               {
755                 /* If the per_char pointer is null, all glyphs between
756                    the first and last character indexes inclusive have
757                    the same information, as given by both min_bounds and
758                    max_bounds.  */
759                 g->g.lbearing = 0;
760                 g->g.rbearing = xfont->max_bounds.width << 6;
761                 g->g.xadv = xfont->max_bounds.width << 6;
762                 g->g.ascent = xfont->ascent << 6;
763                 g->g.descent = xfont->descent << 6;
764               }
765           }
766         g->g.yadv = 0;
767         g->g.ascent += rfont->baseline_offset;
768         g->g.descent -= rfont->baseline_offset;
769         g->g.measured = 1;
770       }
771 }
772
773
774 static int
775 xfont_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
776 {
777   return (xfont_encode_char (frame, font, spec, code) != MCHAR_INVALID_CODE);
778 }
779
780 /* The X font driver function GET_GLYPH_ID.  */
781
782 static unsigned
783 xfont_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
784 {
785   MRealizedFont *rfont;
786   XFontStruct *xfont;
787   unsigned min_byte1, max_byte1, min_byte2, max_byte2;
788   int all_chars_exist;
789
790   if (font->type == MFONT_TYPE_REALIZED)
791     rfont = (MRealizedFont *) font;
792   else if (font->type == MFONT_TYPE_OBJECT)
793     {
794       for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
795            rfont = rfont->next)
796         if (rfont->font == font)
797           break;
798       if (! rfont)
799         {
800           rfont = xfont_open (frame, font, spec, NULL);
801           if (! rfont)
802             return MCHAR_INVALID_CODE;
803         }
804     }
805   else
806     MFATAL (MERROR_FONT_X);
807   xfont = rfont->fontp;
808   all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
809   min_byte1 = xfont->min_byte1;
810   max_byte1 = xfont->max_byte1;
811   min_byte2 = xfont->min_char_or_byte2;
812   max_byte2 = xfont->max_char_or_byte2;
813
814   if (min_byte1 == 0 && max_byte1 == 0)
815     {
816       XCharStruct *pcm;
817
818       if (code < min_byte2 || code > max_byte2)
819         return MCHAR_INVALID_CODE;
820       if (all_chars_exist)
821         return code;
822       pcm = xfont->per_char + (code - min_byte2);
823       return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
824               ? code : MCHAR_INVALID_CODE);
825     }
826   else
827     {
828       unsigned byte1 = code >> 8, byte2 = code & 0xFF;
829       XCharStruct *pcm;
830
831       if (byte1 < min_byte1 || byte1 > max_byte1
832           || byte2 < min_byte2 || byte2 > max_byte2)
833         return MCHAR_INVALID_CODE;
834
835       if (all_chars_exist)
836         return code;
837       pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
838                            + (byte2 - min_byte2));
839       return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
840               ? code : MCHAR_INVALID_CODE);
841     }
842 }
843
844 /* The X font driver function RENDER.  */
845
846 static void
847 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
848               MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
849 {
850   MRealizedFace *rface = from->rface;
851   Display *display = FRAME_DISPLAY (rface->frame);
852   XChar2b *code;
853   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
854   MGlyph *g;
855   int i;
856   int baseline_offset;
857
858   if (from == to)
859     return;
860
861   baseline_offset = rface->rfont->baseline_offset >> 6;
862   if (region)
863     gc = set_region (rface->frame, gc, region);
864   XSetFont (display, gc, ((XFontStruct *) rface->rfont->fontp)->fid);
865   code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
866   for (i = 0, g = from; g < to; i++, g++)
867     {
868       code[i].byte1 = g->g.code >> 8;
869       code[i].byte2 = g->g.code & 0xFF;
870     }
871
872   g = from;
873   while (g < to)
874     {
875       if (g->type == GLYPH_PAD)
876         x += g++->g.xadv;
877       else if (g->type == GLYPH_SPACE)
878         for (; g < to && g->type == GLYPH_SPACE; g++)
879           x += g->g.xadv;
880       else if (! g->rface->rfont)
881         {
882           if ((g->g.c >= 0x200B && g->g.c <= 0x200F)
883               || (g->g.c >= 0x202A && g->g.c <= 0x202E))
884             x += g++->g.xadv;
885           else
886             {
887               /* As a font is not found for this character, draw an
888                  empty box.  */
889               int box_width = g->g.xadv;
890               int box_height = gstring->ascent + gstring->descent;
891
892               if (box_width > 4)
893                 box_width -= 2;
894               if (box_height > 4)
895                 box_height -= 2;
896               XDrawRectangle (display, (Window) win, gc,
897                               x, y - gstring->ascent, box_width, box_height);
898               x += g++->g.xadv;
899             }
900         }
901       else if (g->g.xoff != 0 || g->g.yoff != 0 || g->right_padding)
902         {
903           XDrawString16 (display, (Window) win, gc,
904                          x + g->g.xoff, y + g->g.yoff - baseline_offset,
905                          code + (g - from), 1);
906           x += g->g.xadv;
907           g++;
908         }
909       else
910         {
911           int orig_x = x;
912           int code_idx = g - from;
913
914           for (i = 0;
915                g < to && g->type == GLYPH_CHAR && g->g.xoff == 0 && g->g.yoff == 0;
916                i++, g++)
917               x += g->g.xadv;
918           XDrawString16 (display, (Window) win, gc,
919                          orig_x, y - baseline_offset, code + code_idx, i);
920         }
921     }
922 }
923
924 static int
925 xfont_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum)
926 {
927   MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
928   MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil;
929   MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil;
930   int size = font ? font->size : 0;
931   MPlist *pl, *p;
932   int num = 0;
933   int mdebug_flag = MDEBUG_FONT;
934
935   MDEBUG_PRINT2 (" [X-FONT] listing %s-%s...",
936                  family ? msymbol_name (family) : "*",
937                  registry ? msymbol_name (registry) : "*");
938
939   if (registry == Mnil)
940     xfont_list_all (frame);
941   else
942     xfont_registry_list (frame, registry);
943
944   MPLIST_DO (pl, disp_info->font_list)
945     if (registry == Mnil || registry == MPLIST_KEY (pl))
946       {
947         MPLIST_DO (p, MPLIST_VAL (pl))
948           if (family == Mnil || family == MPLIST_KEY (p))
949             {
950               MFont *fontx = MPLIST_VAL (p);
951
952               if (! font || (mfont__match_p (fontx, font, MFONT_REGISTRY)))
953                 {
954                   if (fontx->size != 0 && size)
955                     {
956                       if (fontx->multiple_sizes)
957                         {
958                           if (size < 60 || size > 290
959                               || ! (fontx->size & (1 << (size / 10 - 6))))
960                             continue;
961                         }
962                       else if (fontx->size != size)
963                         continue;
964                     }
965                   mplist_push (plist, MPLIST_KEY (p), fontx);
966                   num++;
967                   if (maxnum > 0 && maxnum == num)
968                     goto done;
969                 }
970             }
971       }
972
973  done:
974   MDEBUG_PRINT1 (" %d found\n", num);
975   return num;
976 }
977
978 static void
979 xfont_list_family_names (MFrame *frame, MPlist *plist)
980 {
981   MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
982   char **font_names;
983   int i, nfonts;
984   MSymbol last_family = Mnil;
985
986   font_names = XListFonts (disp_info->display,
987                            "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", 0x8000, &nfonts);
988   for (i = 0; i < nfonts; i++)
989     {
990       MSymbol family;
991       char foundry[256], fam[256];
992       MPlist *p;
993       
994       if (sscanf (font_names[i], "-%s-%s-", foundry, fam) < 2)
995         continue;
996       family = msymbol (fam);
997       if (family == last_family)
998         continue;
999       last_family = family;
1000
1001       MPLIST_DO (p, plist)
1002         {
1003           MSymbol sym = MPLIST_SYMBOL (p);
1004
1005           if (sym == family)
1006             break;
1007           if (strcmp (MSYMBOL_NAME (sym), fam) > 0)
1008             {
1009               mplist_push (p, Msymbol, family);
1010               break;
1011             }
1012         }
1013       if (MPLIST_TAIL_P (p))
1014         mplist_push (p, Msymbol, family);
1015     }
1016   if (font_names)
1017     XFreeFontNames (font_names);
1018 }
1019
1020 static int 
1021 xfont_check_capability (MRealizedFont *rfont, MSymbol capability)
1022 {
1023   /* Currently X font driver doesn't support any capability.  */
1024   return -1;
1025 }
1026
1027 \f
1028 /* Xft Handler */
1029
1030 #ifdef HAVE_XFT2
1031
1032 typedef struct
1033 {
1034   M17NObject control;
1035   FT_Face ft_face;              /* This must be the 2nd member. */
1036   Display *display;
1037   XftFont *font_aa;
1038   XftFont *font_no_aa;
1039   /* Pointer to MRealizedFontFT */
1040   void *info;
1041 } MRealizedFontXft;
1042
1043 static MRealizedFont *xft_open (MFrame *frame, MFont *font, MFont *spec,
1044                                 MRealizedFont *);
1045 static int xft_has_char (MFrame *frame, MFont *font, MFont *spec,
1046                          int c, unsigned code);
1047 static unsigned xft_encode_char (MFrame *frame, MFont *font, MFont *spec,
1048                                  unsigned code);
1049 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
1050 static void xft_render (MDrawWindow, int, int, MGlyphString *,
1051                         MGlyph *, MGlyph *, int, MDrawRegion);
1052 static int xft_check_capability (MRealizedFont *rfont, MSymbol capability);
1053 static int xft_check_otf (MFLTFont *font, MFLTOtfSpec *spec);
1054 static int xft_drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
1055                           MFLTGlyphString *in, int from, int to,
1056                           MFLTGlyphString *out,
1057                           MFLTGlyphAdjustment *adjustment);
1058
1059 static MFontDriver xft_driver =
1060   { NULL, xft_open,
1061     xft_find_metric, xft_has_char, xft_encode_char, xft_render, NULL, NULL,
1062     xft_check_capability, NULL, NULL, xft_check_otf, xft_drive_otf
1063   };
1064
1065 static void
1066 close_xft (void *object)
1067 {
1068   MRealizedFontXft *rfont_xft = object;
1069
1070   if (rfont_xft->font_aa)
1071     XftFontClose (rfont_xft->display, rfont_xft->font_aa);
1072   if (rfont_xft->font_no_aa)
1073     XftFontClose (rfont_xft->display, rfont_xft->font_no_aa);
1074   M17N_OBJECT_UNREF (rfont_xft->info);
1075   free (rfont_xft);
1076 }
1077
1078
1079 static XftFont *
1080 xft_open_font (Display *display, MSymbol file, double size,
1081                FcBool anti_alias)
1082 {
1083   FcPattern *pattern;
1084   XftFont *font;
1085
1086   pattern = FcPatternCreate ();
1087   FcPatternAddString (pattern, FC_FILE, (FcChar8 *) msymbol_name (file));
1088   FcPatternAddDouble (pattern, FC_PIXEL_SIZE, size);
1089   FcPatternAddBool (pattern, FC_ANTIALIAS, anti_alias);
1090   font = XftFontOpenPattern (display, pattern);
1091   return font;
1092 }
1093
1094
1095 static MRealizedFont *
1096 xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
1097 {
1098   Display *display = FRAME_DISPLAY (frame);
1099   int reg = spec->property[MFONT_REGISTRY];
1100   FT_Face ft_face;
1101   MRealizedFontXft *rfont_xft;
1102   FcBool anti_alias = FRAME_DEVICE (frame)->depth > 1 ? FcTrue : FcFalse;
1103   int size;
1104   XftFont *xft_font;
1105   int ascent, descent, max_advance, average_width, baseline_offset;
1106
1107   if (font->size)
1108     /* non-scalable font */
1109     size = font->size;
1110   else if (spec->size)
1111     {
1112       int ratio = mfont_resize_ratio (font);
1113
1114       size = ratio == 100 ? spec->size : spec->size * ratio / 100;
1115     }
1116   else
1117     size = 120;
1118
1119   if (rfont)
1120     {
1121       MRealizedFont *save = NULL;
1122
1123       for (; rfont; rfont = rfont->next)
1124         if (rfont->font == font
1125             && (rfont->font->size ? rfont->font->size == size
1126                 : rfont->spec.size == size)
1127             && rfont->spec.property[MFONT_REGISTRY] == reg)
1128           {
1129             if (! save)
1130               save = rfont;
1131             if (rfont->driver == &xft_driver)
1132               return rfont;
1133           }
1134       rfont = save;
1135     }
1136   rfont = (mfont__ft_driver.open) (frame, font, spec, rfont);
1137   if (! rfont)
1138     return NULL;
1139   ascent = rfont->ascent;
1140   descent = rfont->descent;
1141   max_advance = rfont->max_advance;
1142   average_width = rfont->average_width;
1143   baseline_offset = rfont->baseline_offset;
1144   spec = &rfont->spec;
1145   ft_face = rfont->fontp;
1146   xft_font = xft_open_font (display, font->file, size / 10, anti_alias);
1147   if (! xft_font)
1148     return NULL;
1149   M17N_OBJECT (rfont_xft, close_xft, MERROR_WIN);
1150   rfont_xft->display = display;
1151   if (anti_alias == FcTrue)
1152     rfont_xft->font_aa = xft_font;
1153   else
1154     rfont_xft->font_no_aa = xft_font;
1155   rfont_xft->ft_face = ft_face;
1156   rfont_xft->info = rfont->info;
1157   M17N_OBJECT_REF (rfont->info);
1158   MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
1159   rfont->spec = *spec;
1160   rfont->spec.size = size;
1161   rfont->frame = frame;
1162   rfont->font = font;
1163   rfont->driver = &xft_driver;
1164   rfont->info = rfont_xft;
1165   rfont->ascent = ascent;
1166   rfont->descent = descent;
1167   rfont->max_advance = max_advance;
1168   rfont->average_width = average_width;
1169   rfont->baseline_offset = baseline_offset;
1170   rfont->x_ppem = ft_face->size->metrics.x_ppem;
1171   rfont->y_ppem = ft_face->size->metrics.y_ppem;
1172   rfont->fontp = xft_font;
1173   rfont->next = MPLIST_VAL (frame->realized_font_list);
1174   MPLIST_VAL (frame->realized_font_list) = rfont;
1175   return rfont;
1176 }
1177
1178 static void
1179 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1180                 int from, int to)
1181 {
1182   Display *display = FRAME_DISPLAY (rfont->frame);
1183   XftFont *xft_font = rfont->fontp;
1184   MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1185
1186   for (; g != gend; g++)
1187     if (! g->g.measured)
1188       {
1189         if (g->g.code == MCHAR_INVALID_CODE)
1190           {
1191             g->g.lbearing = 0;
1192             g->g.rbearing = xft_font->max_advance_width << 6;
1193             g->g.xadv = g->g.rbearing << 6;
1194             g->g.ascent = xft_font->ascent << 6;
1195             g->g.descent = xft_font->descent << 6;
1196           }
1197         else
1198           {
1199             XGlyphInfo extents;
1200
1201             XftGlyphExtents (display, xft_font, &g->g.code, 1, &extents);
1202             g->g.lbearing = (- extents.x) << 6;
1203             g->g.rbearing = (extents.width - extents.x) << 6;
1204             g->g.xadv = extents.xOff << 6;
1205             g->g.ascent = extents.y << 6;
1206             g->g.descent = (extents.height - extents.y) << 6;
1207           }
1208         g->g.yadv = 0;
1209         g->g.measured = 0;
1210       }
1211 }
1212
1213 static int
1214 xft_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
1215 {
1216   int result;
1217
1218   if (font->type == MFONT_TYPE_REALIZED)
1219     {
1220       MRealizedFont *rfont = (MRealizedFont *) font;
1221       MRealizedFontXft *rfont_xft = rfont->info;
1222       
1223       rfont->info = rfont_xft->info;
1224       result = mfont__ft_driver.has_char (frame, font, spec, c, code);
1225       rfont->info = rfont_xft;
1226     }
1227   else
1228     result = mfont__ft_driver.has_char (frame, font, spec, c, code);
1229   return result;
1230 }
1231
1232 static unsigned
1233 xft_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
1234 {
1235   if (font->type == MFONT_TYPE_REALIZED)
1236     {
1237       MRealizedFont *rfont = (MRealizedFont *) font;
1238       MRealizedFontXft *rfont_xft = rfont->info;
1239       
1240       rfont->info = rfont_xft->info;
1241       code = mfont__ft_driver.encode_char (frame, font, spec, code);
1242       rfont->info = rfont_xft;
1243     }
1244   else
1245     code = mfont__ft_driver.encode_char (frame, font, spec, code);
1246   return code;
1247 }
1248
1249 static void 
1250 xft_render (MDrawWindow win, int x, int y,
1251             MGlyphString *gstring, MGlyph *from, MGlyph *to,
1252             int reverse, MDrawRegion region)
1253 {
1254   MRealizedFace *rface = from->rface;
1255   MFrame *frame = rface->frame;
1256   Display *display = FRAME_DISPLAY (frame);
1257   MRealizedFont *rfont = rface->rfont;
1258   MRealizedFontXft *rfont_xft = rfont->info;
1259   XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1260   XftColor *xft_color = (! reverse
1261                          ? &((GCInfo *) rface->info)->xft_color_fore
1262                          : &((GCInfo *) rface->info)->xft_color_back);
1263   int anti_alias = (gstring->control.anti_alias
1264                     && FRAME_DEVICE (frame)->depth > 1);
1265   XftFont *xft_font;
1266   MGlyph *g;
1267   FT_UInt *glyphs;
1268   int last_x;
1269   int nglyphs;
1270
1271   if (from == to)
1272     return;
1273
1274   if (anti_alias)
1275     {
1276       if (rfont_xft->font_aa)
1277         xft_font = rfont_xft->font_aa;
1278       else
1279         {
1280           double size = rfont->spec.size;
1281
1282           xft_font = xft_open_font (display, rfont->spec.file, size / 10,
1283                                     FcTrue);
1284           if (xft_font)
1285             rfont_xft->font_aa = xft_font;
1286           else
1287             xft_font = rfont->fontp;
1288         }
1289     }
1290   else
1291     {
1292       if (rfont_xft->font_no_aa)
1293         xft_font = rfont_xft->font_no_aa;
1294       else
1295         {
1296           double size = rfont->spec.size;
1297
1298           xft_font = xft_open_font (display, rfont->spec.file, size / 10,
1299                                     FcTrue);
1300           if (xft_font)
1301             rfont_xft->font_no_aa = xft_font;
1302           else
1303             xft_font = rfont->fontp;
1304         }
1305     }
1306
1307   XftDrawChange (xft_draw, (Drawable) win);
1308   XftDrawSetClip (xft_draw, (Region) region);
1309       
1310   y -= rfont->baseline_offset >> 6;
1311   glyphs = alloca (sizeof (FT_UInt) * (to - from));
1312   for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->g.xadv)
1313     {
1314       if (g->g.xoff == 0 && g->g.yoff == 0 && !g->left_padding && !g->right_padding)
1315         glyphs[nglyphs++] = g->g.code;
1316       else
1317         {
1318           if (nglyphs > 0)
1319             XftDrawGlyphs (xft_draw, xft_color, xft_font,
1320                            last_x, y, glyphs, nglyphs);
1321           nglyphs = 0;
1322           XftDrawGlyphs (xft_draw, xft_color, xft_font,
1323                          x + g->g.xoff, y + g->g.yoff, (FT_UInt *) &g->g.code, 1);
1324           last_x = x + g->g.xadv;
1325         }
1326     }
1327   if (nglyphs > 0)
1328     XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1329 }
1330
1331 static int
1332 xft_check_capability (MRealizedFont *rfont, MSymbol capability)
1333 {
1334   MRealizedFontXft *rfont_xft = rfont->info;
1335   int result;
1336       
1337   rfont->info = rfont_xft->info;
1338   result = mfont__ft_driver.check_capability (rfont, capability);
1339   rfont->info = rfont_xft;
1340   return result;
1341 }
1342
1343 static int
1344 xft_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
1345 {
1346   MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
1347   MRealizedFontXft *rfont_xft = rfont->info;
1348   int result;
1349       
1350   rfont->info = rfont_xft->info;
1351   result = mfont__ft_driver.check_otf (font, spec);
1352   rfont->info = rfont_xft;
1353   return result;
1354 }
1355
1356 static int
1357 xft_drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
1358                MFLTGlyphString *in, int from, int to,
1359                MFLTGlyphString *out,
1360                MFLTGlyphAdjustment *adjustment)
1361 {
1362   MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
1363   MRealizedFontXft *rfont_xft = rfont->info;
1364   int result;
1365       
1366   rfont->info = rfont_xft->info;
1367   result = mfont__ft_driver.drive_otf (font, spec, in, from, to, out,
1368                                        adjustment);
1369   rfont->info = rfont_xft;
1370   return result;
1371 }
1372
1373 #endif  /* HAVE_XFT2 */
1374
1375 \f
1376 /* Functions for the device driver.  */
1377
1378 static void
1379 mwin__close_device (MFrame *frame)
1380 {
1381   MWDevice *device = FRAME_DEVICE (frame);
1382
1383   M17N_OBJECT_UNREF (device);
1384 }
1385
1386 static void *
1387 mwin__device_get_prop (MFrame *frame, MSymbol key)
1388 {
1389   MWDevice *device = FRAME_DEVICE (frame);
1390
1391   if (key == Mdisplay)
1392     return (void *) device->display_info->display;
1393   if (key == Mscreen)
1394     return (void *) ScreenOfDisplay(device->display_info->display,
1395                                     device->screen_num);
1396   if (key == Mcolormap)
1397     return (void *) device->cmap;
1398   if (key == Mdepth)
1399     return (void *) device->depth;
1400   return NULL;
1401 }
1402
1403 static void
1404 mwin__realize_face (MRealizedFace *rface)
1405 {
1406   MFrame *frame;
1407   MSymbol foreground, background, videomode;
1408   MFaceHLineProp *hline;
1409   MFaceBoxProp *box;
1410   GCInfo *info;
1411
1412   if (rface != rface->ascii_rface)
1413     {
1414       rface->info = rface->ascii_rface->info;
1415       return;
1416     }
1417
1418   frame = rface->frame;
1419   MSTRUCT_CALLOC (info, MERROR_WIN);
1420
1421   foreground = rface->face.property[MFACE_FOREGROUND];
1422   background = rface->face.property[MFACE_BACKGROUND];
1423   videomode = rface->face.property[MFACE_VIDEOMODE];
1424   if (! videomode)
1425     videomode = frame->videomode;
1426   if (videomode != Mreverse)
1427     {
1428       info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1429       info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1430     }
1431   else
1432     {
1433       info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1434       info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1435     }
1436 #ifdef HAVE_XFT2
1437   if (foreground == Mnil)
1438     foreground = frame->foreground;
1439   if (background == Mnil)
1440     background = frame->background;
1441   if (videomode == Mreverse)
1442     {
1443       MSymbol temp = foreground;
1444       foreground = background;
1445       background = temp;
1446     }
1447   if (! XftColorAllocName (FRAME_DISPLAY (frame),
1448                            FRAME_VISUAL (frame),
1449                            FRAME_CMAP (frame),
1450                            MSYMBOL_NAME (foreground),
1451                            &info->xft_color_fore))
1452     mdebug_hook ();
1453   if (! XftColorAllocName (FRAME_DISPLAY (frame),
1454                            FRAME_VISUAL (frame),
1455                            FRAME_CMAP (frame),
1456                            MSYMBOL_NAME (background),
1457                            &info->xft_color_back))
1458     mdebug_hook ();
1459 #endif  /* HAVE_XFT2 */
1460
1461   hline = rface->hline;
1462   if (hline)
1463     {
1464       if (hline->color)
1465         info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1466       else
1467         info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1468     }
1469
1470   box = rface->box;
1471   if (box)
1472     {
1473       if (box->color_top)
1474         info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1475       else
1476         info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1477
1478       if (box->color_left && box->color_left != box->color_top)
1479         info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1480       else
1481         info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1482
1483       if (box->color_bottom && box->color_bottom != box->color_top)
1484         info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1485       else
1486         info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1487
1488       if (box->color_right && box->color_right != box->color_bottom)
1489         info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1490       else
1491         info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1492     }
1493
1494   rface->info = info;
1495 }
1496
1497
1498 static void
1499 mwin__free_realized_face (MRealizedFace *rface)
1500 {
1501   if (rface == rface->ascii_rface)
1502     free (rface->info);
1503 }
1504
1505
1506 static void
1507 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1508                   int reverse,
1509                   int x, int y, int width, int height, MDrawRegion region)
1510 {
1511   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1512
1513   if (region)
1514     gc = set_region (frame, gc, region);
1515
1516   XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1517                   x, y, width, height);
1518 }
1519
1520
1521 static void
1522 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1523                         MGlyphString *gstring, MGlyph *from, MGlyph *to,
1524                         int reverse, MDrawRegion region)
1525 {
1526   MRealizedFace *rface = from->rface;
1527   Display *display = FRAME_DISPLAY (rface->frame);
1528   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1529
1530   if (from == to)
1531     return;
1532
1533   if (region)
1534     gc = set_region (rface->frame, gc, region);
1535   for (; from < to; from++)
1536     {
1537       XDrawRectangle (display, (Window) win, gc,
1538                       x, y - gstring->ascent + 1, from->g.xadv - 1,
1539                       gstring->ascent + gstring->descent - 2);
1540       x += from->g.xadv;
1541     }
1542 }
1543
1544
1545 static void
1546 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1547                  MRealizedFace *rface, int reverse,
1548                  int x, int y, int width, MDrawRegion region)
1549 {
1550   enum MFaceHLineType type = rface->hline->type;
1551   GCInfo *info = rface->info;
1552   GC gc = gc = info->gc[GC_HLINE];
1553   int i;
1554
1555   y = (type == MFACE_HLINE_BOTTOM
1556        ? y + gstring->text_descent - rface->hline->width
1557        : type == MFACE_HLINE_UNDER
1558        ? y + 1
1559        : type == MFACE_HLINE_STRIKE_THROUGH
1560        ? y - ((gstring->ascent + gstring->descent) / 2)
1561        : y - gstring->text_ascent);
1562   if (region)
1563     gc = set_region (frame, gc, region);
1564
1565   for (i = 0; i < rface->hline->width; i++)
1566     XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1567                x, y + i, x + width - 1, y + i);
1568 }
1569
1570
1571 static void
1572 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1573                 MGlyph *g, int x, int y, int width, MDrawRegion region)
1574 {
1575   Display *display = FRAME_DISPLAY (frame);
1576   MRealizedFace *rface = g->rface;
1577   MFaceBoxProp *box = rface->box;
1578   GCInfo *info = rface->info;
1579   GC gc_top, gc_left, gc_right, gc_btm;
1580   int y0, y1;
1581   int i;
1582
1583   y0 = y - (gstring->text_ascent
1584             + rface->box->inner_vmargin + rface->box->width);
1585   y1 = y + (gstring->text_descent
1586             + rface->box->inner_vmargin + rface->box->width - 1);
1587
1588   gc_top = info->gc[GC_BOX_TOP];
1589   if (region)
1590     gc_top = set_region (frame, gc_top, region);
1591   if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1592     gc_btm = gc_top;
1593   else
1594     gc_btm = info->gc[GC_BOX_BOTTOM];
1595
1596   if (g->type == GLYPH_BOX)
1597     {
1598       int x0, x1;
1599
1600       if (g->left_padding)
1601         x0 = x + box->outer_hmargin, x1 = x + g->g.xadv - 1;
1602       else
1603         x0 = x, x1 = x + g->g.xadv - box->outer_hmargin - 1;
1604
1605       /* Draw the top side.  */
1606       for (i = 0; i < box->width; i++)
1607         XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1608
1609       /* Draw the bottom side.  */
1610       if (region && gc_btm != gc_top)
1611         gc_btm = set_region (frame, gc_btm, region);
1612       for (i = 0; i < box->width; i++)
1613         XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1614
1615       if (g->left_padding > 0)
1616         {
1617           /* Draw the left side.  */
1618           if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1619             gc_left = gc_top;
1620           else
1621             {
1622               gc_left = info->gc[GC_BOX_LEFT];
1623               if (region)
1624                 gc_left = set_region (frame, gc_left, region);
1625             }
1626           for (i = 0; i < rface->box->width; i++)
1627             XDrawLine (display, (Window) win, gc_left,
1628                        x0 + i, y0 + i, x0 + i, y1 - i);
1629         }
1630       else
1631         {
1632           /* Draw the right side.  */
1633           if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1634             gc_right = gc_top;
1635           else
1636             {
1637               gc_right = info->gc[GC_BOX_RIGHT];
1638               if (region)
1639                 gc_right = set_region (frame, gc_right, region);
1640             }
1641           for (i = 0; i < rface->box->width; i++)
1642             XDrawLine (display, (Window) win, gc_right,
1643                        x1 - i, y0 + i, x1 - i, y1 - i);
1644         }
1645     }
1646   else
1647     {
1648       /* Draw the top side.  */
1649       for (i = 0; i < box->width; i++)
1650         XDrawLine (display, (Window) win, gc_top,
1651                    x, y0 + i, x + width - 1, y0 + i);
1652
1653       /* Draw the bottom side.  */
1654       if (region && gc_btm != gc_top)
1655         gc_btm = set_region (frame, gc_btm, region);
1656       for (i = 0; i < box->width; i++)
1657         XDrawLine (display, (Window) win, gc_btm,
1658                    x, y1 - i, x + width - 1, y1 - i);
1659     }
1660 }
1661
1662
1663 #if 0
1664 static void
1665 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1666                    int reverse, int x, int y,
1667                    int width, int height, int row_bytes, unsigned char *bmp,
1668                    MDrawRegion region)
1669 {
1670   Display *display = FRAME_DISPLAY (frame);
1671   int i, j;
1672   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1673
1674   if (region)
1675     gc = set_region (frame, gc, region);
1676
1677   for (i = 0; i < height; i++, bmp += row_bytes)
1678     for (j = 0; j < width; j++)
1679       if (bmp[j / 8] & (1 << (7 - (j % 8))))
1680         XDrawPoint (display, (Window) win, gc, x + j, y + i);
1681 }
1682 #endif
1683
1684 static void
1685 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1686                    int intensity, MDrawPoint *points, int num,
1687                    MDrawRegion region)
1688 {
1689   GCInfo *info = rface->info;
1690   GC gc;
1691
1692   if (! (gc = info->gc[intensity]))
1693     gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1694                                                       info, intensity);
1695   if (region)
1696     gc = set_region (frame, gc, region);
1697
1698   XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1699                (XPoint *) points, num, CoordModeOrigin);
1700 }
1701
1702
1703 static MDrawRegion
1704 mwin__region_from_rect (MDrawMetric *rect)
1705 {
1706   MDrawRegion region1 = XCreateRegion ();
1707   MDrawRegion region2 = XCreateRegion ();
1708   XRectangle xrect;
1709
1710   xrect.x = rect->x;
1711   xrect.y = rect->y;
1712   xrect.width = rect->width;
1713   xrect.height = rect->height;
1714   XUnionRectWithRegion (&xrect, region1, region2);
1715   XDestroyRegion (region1);
1716   return region2;
1717 }
1718
1719 static void
1720 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1721 {
1722   MDrawRegion region1 = XCreateRegion ();
1723   XRectangle xrect;
1724
1725   xrect.x = rect->x;
1726   xrect.y = rect->y;
1727   xrect.width = rect->width;
1728   xrect.height = rect->height;
1729
1730   XUnionRegion (region, region, region1);
1731   XUnionRectWithRegion (&xrect, region1, region);
1732   XDestroyRegion (region1);
1733 }
1734
1735 static void
1736 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1737 {
1738   MDrawRegion region = XCreateRegion ();
1739
1740   XUnionRegion (region1, region1, region);
1741   XIntersectRegion (region, region2, region1);
1742   XDestroyRegion (region);
1743 }
1744
1745 static void
1746 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1747 {
1748   MDrawRegion region1 = XCreateRegion ();
1749   XRectangle xrect;
1750
1751   xrect.x = rect->x;
1752   xrect.y = rect->y;
1753   xrect.width = rect->width;
1754   xrect.height = rect->height;
1755   XUnionRectWithRegion (&xrect, region1, region);
1756   XDestroyRegion (region1);
1757 }
1758
1759 static void
1760 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1761 {
1762   XRectangle xrect;
1763
1764   XClipBox (region, &xrect);
1765   rect->x = xrect.x;
1766   rect->y = xrect.y;
1767   rect->width = xrect.width;
1768   rect->height = xrect.height;
1769 }
1770
1771 static void
1772 mwin__free_region (MDrawRegion region)
1773 {
1774   XDestroyRegion (region);
1775 }
1776
1777 static void
1778 mwin__dump_region (MDrawRegion region)
1779 {
1780   XRectangle rect;
1781   XClipBox (region, &rect);
1782   fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1783 }
1784
1785
1786 static MDrawWindow
1787 mwin__create_window (MFrame *frame, MDrawWindow parent)
1788 {
1789   Display *display = FRAME_DISPLAY (frame);
1790   Window win;
1791   XWMHints wm_hints = { InputHint, False };
1792   XClassHint class_hints = { "M17N-IM", "m17n-im" };
1793   XSetWindowAttributes set_attrs;
1794   unsigned long mask;
1795   XGCValues values;
1796   GCInfo *info = frame->rface->info;
1797
1798   if (! parent)
1799     parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1800   mask = GCForeground;
1801   XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1802   set_attrs.background_pixel = values.foreground;
1803   set_attrs.backing_store = Always;
1804   set_attrs.override_redirect = True;
1805   set_attrs.save_under = True;
1806   mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1807   win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1808                        CopyFromParent, InputOutput, CopyFromParent,
1809                        mask, &set_attrs);
1810   XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1811                     NULL, &wm_hints, &class_hints);
1812   XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1813   return (MDrawWindow) win;
1814 }
1815
1816 static void
1817 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1818 {
1819 #ifdef HAVE_XFT2
1820   XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1821
1822   if (XftDrawDrawable (xft_draw) == (Drawable) win)
1823     XftDrawChange (xft_draw, FRAME_DEVICE (frame)->drawable);
1824 #endif  /* HAVE_XFT2 */
1825   XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1826 }
1827
1828 #if 0
1829 static MDrawWindow
1830 mwin__event_window (void *event)
1831 {
1832   return ((MDrawWindow) ((XEvent *) event)->xany.window);
1833 }
1834
1835 static void
1836 mwin__print_event (void *arg, char *win_name)
1837 {
1838   char *event_name;
1839   XEvent *event = (XEvent *) arg;
1840
1841   switch (event->xany.type)
1842     {
1843     case 2: event_name = "KeyPress"; break;
1844     case 3: event_name = "KeyRelease"; break;
1845     case 4: event_name = "ButtonPress"; break;
1846     case 5: event_name = "ButtonRelease"; break;
1847     case 6: event_name = "MotionNotify"; break;
1848     case 7: event_name = "EnterNotify"; break;
1849     case 8: event_name = "LeaveNotify"; break;
1850     case 9: event_name = "FocusIn"; break;
1851     case 10: event_name = "FocusOut"; break;
1852     case 11: event_name = "KeymapNotify"; break;
1853     case 12: event_name = "Expose"; break;
1854     case 13: event_name = "GraphicsExpose"; break;
1855     case 14: event_name = "NoExpose"; break;
1856     case 15: event_name = "VisibilityNotify"; break;
1857     case 16: event_name = "CreateNotify"; break;
1858     case 17: event_name = "DestroyNotify"; break;
1859     case 18: event_name = "UnmapNotify"; break;
1860     case 19: event_name = "MapNotify"; break;
1861     case 20: event_name = "MapRequest"; break;
1862     case 21: event_name = "ReparentNotify"; break;
1863     case 22: event_name = "ConfigureNotify"; break;
1864     case 23: event_name = "ConfigureRequest"; break;
1865     case 24: event_name = "GravityNotify"; break;
1866     case 25: event_name = "ResizeRequest"; break;
1867     case 26: event_name = "CirculateNotify"; break;
1868     case 27: event_name = "CirculateRequest"; break;
1869     case 28: event_name = "PropertyNotify"; break;
1870     case 29: event_name = "SelectionClear"; break;
1871     case 30: event_name = "SelectionRequest"; break;
1872     case 31: event_name = "SelectionNotify"; break;
1873     case 32: event_name = "ColormapNotify"; break;
1874     case 33: event_name = "ClientMessage"; break;
1875     case 34: event_name = "MappingNotify"; break;
1876     default: event_name = "unknown";
1877     }
1878
1879   fprintf (stderr, "%s: %s\n", win_name, event_name);
1880 }
1881 #endif
1882
1883 static void
1884 mwin__map_window (MFrame *frame, MDrawWindow win)
1885 {
1886   XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1887 }
1888
1889 static void
1890 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1891 {
1892   XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1893 }
1894
1895 static void
1896 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1897                        MDrawMetric *geometry)
1898 {
1899   Display *display = FRAME_DISPLAY (frame);
1900   XWindowAttributes attr;
1901   Window parent = (Window) parent_win, root;
1902
1903   XGetWindowAttributes (display, (Window) win, &attr);
1904   geometry->x = attr.x + attr.border_width;
1905   geometry->y = attr.y + attr.border_width;
1906   geometry->width = attr.width;
1907   geometry->height = attr.height; 
1908
1909   if (! parent)
1910     parent = RootWindow (display, FRAME_SCREEN (frame));
1911   while (1)
1912     {
1913       Window this_parent, *children;
1914       unsigned n;
1915
1916       XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1917       if (children)
1918         XFree (children);
1919       if (this_parent == parent || this_parent == root)
1920         break;
1921       win = (MDrawWindow) this_parent;
1922       XGetWindowAttributes (display, (Window) win, &attr);
1923       geometry->x += attr.x + attr.border_width;
1924       geometry->y += attr.y + attr.border_width;
1925     }
1926 }
1927
1928 static void
1929 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1930                      MDrawMetric *current, MDrawMetric *new)
1931 {
1932   Display *display = FRAME_DISPLAY (frame);
1933   unsigned int mask = 0;
1934   XWindowChanges values;
1935
1936   if (current->width != new->width)
1937     {
1938       mask |= CWWidth;
1939       if (new->width <= 0)
1940         new->width = 1;
1941       values.width = current->width = new->width;
1942     }
1943   if (current->height != new->height)
1944     {
1945       mask |= CWHeight;
1946       if (new->height <= 0)
1947         new->height = 1;
1948       values.height = current->height = new->height;
1949     }
1950   if (current->x != new->x)
1951     {
1952       mask |= CWX;
1953       values.x = current->x = new->x;
1954     }
1955   if (current->y != new->y)
1956     {
1957       mask |= CWY;
1958       current->y = new->y;
1959       values.y = current->y = new->y;
1960     }
1961   if (mask)
1962     XConfigureWindow (display, (Window) win, mask, &values);
1963   XClearWindow (display, (Window) win);
1964 }
1965
1966 static MSymbol
1967 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1968 {
1969   XEvent *event = (XEvent *) arg;
1970   MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1971   int len;
1972   char buf[512];
1973   KeySym keysym;
1974   MSymbol key;
1975
1976   *modifiers = 0;
1977   if (event->xany.type != KeyPress
1978       /* && event->xany.type != KeyRelease */
1979       )
1980     return Mnil;
1981   len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1982   if (len > 1)
1983     return Mnil;
1984   if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1985     return Mnil;
1986   if (len == 1 && keysym >= XK_space && keysym <= XK_asciitilde)
1987     {
1988       int c = keysym;
1989
1990       key = minput__char_to_key (c);
1991       if (c == ' ' && ((XKeyEvent *) event)->state & ShiftMask)
1992         *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1993     }
1994   else
1995     {
1996       char *str = XKeysymToString (keysym);
1997
1998       if (! str)
1999         return Mnil;
2000       key = msymbol (str);
2001       if (((XKeyEvent *) event)->state & ShiftMask)
2002         *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
2003     }
2004   if (((XKeyEvent *) event)->state & ControlMask)
2005     *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
2006   if (((XKeyEvent *) event)->state & disp_info->meta_mask)
2007     *modifiers |= MINPUT_KEY_META_MODIFIER;
2008   if (((XKeyEvent *) event)->state & disp_info->alt_mask)
2009     *modifiers |= MINPUT_KEY_ALT_MODIFIER;
2010   if (((XKeyEvent *) event)->state & disp_info->super_mask)
2011     *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
2012   if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
2013     *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
2014
2015   return key;
2016 }
2017
2018
2019 void
2020 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
2021 {
2022   unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
2023   XGCValues values;
2024   Display *display = FRAME_DISPLAY (frame);
2025   GCInfo *info = rface->info;
2026   int i;
2027
2028   for (i = 0; i <= GC_INVERSE; i++)
2029     {
2030       XGetGCValues (display, info->gc[i], valuemask, &values);
2031       fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
2032                values.foreground, values.background);
2033       fprintf (stderr, "\n");
2034     }
2035 }
2036
2037 static MDeviceDriver x_driver =
2038   {
2039     mwin__close_device,
2040     mwin__device_get_prop,
2041     mwin__realize_face,
2042     mwin__free_realized_face,
2043     mwin__fill_space,
2044     mwin__draw_empty_boxes,
2045     mwin__draw_hline,
2046     mwin__draw_box,
2047     mwin__draw_points,
2048     mwin__region_from_rect,
2049     mwin__union_rect_with_region,
2050     mwin__intersect_region,
2051     mwin__region_add_rect,
2052     mwin__region_to_rect,
2053     mwin__free_region,
2054     mwin__dump_region,
2055     mwin__create_window,
2056     mwin__destroy_window,
2057     mwin__map_window,
2058     mwin__unmap_window,
2059     mwin__window_geometry,
2060     mwin__adjust_window,
2061     mwin__parse_event
2062   };
2063
2064 /* Functions to be stored in MDeviceLibraryInterface by dlsym ().  */
2065
2066 int
2067 device_init ()
2068 {
2069   M_iso8859_1 = msymbol ("iso8859-1");
2070   M_iso10646_1 = msymbol ("iso10646-1");
2071
2072   display_info_list = mplist ();
2073   device_list = mplist ();
2074
2075 #ifdef HAVE_XFT2
2076   xft_driver.select = mfont__ft_driver.select;
2077   xft_driver.list = mfont__ft_driver.list;
2078   xft_driver.list_family_names = mfont__ft_driver.list_family_names;
2079 #endif
2080
2081   Mxim = msymbol ("xim");
2082   msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
2083
2084   return 0;
2085 }
2086
2087 int
2088 device_fini ()
2089 {
2090   M17N_OBJECT_UNREF (display_info_list);
2091   M17N_OBJECT_UNREF (device_list);
2092   return 0;
2093 }
2094
2095
2096 #ifdef X_SET_ERROR_HANDLER
2097 static int
2098 x_error_handler (Display *display, XErrorEvent *error)
2099 {
2100   mdebug_hook ();
2101   return 0;
2102 }
2103
2104 static int
2105 x_io_error_handler (Display *display)
2106 {
2107   mdebug_hook ();
2108   return 0;
2109 }
2110 #endif
2111
2112 /** Return an MWDevice object corresponding to a display specified in
2113     PLIST.
2114
2115     It searches device_list for a device matching the display.  If
2116     found, return the found object.  Otherwise, return a newly created
2117     object.  */
2118
2119 int
2120 device_open (MFrame *frame, MPlist *param)
2121 {
2122   Display *display = NULL;
2123   Screen *screen = NULL;
2124   int screen_num;
2125   Drawable drawable = 0;
2126   Widget widget = NULL;
2127   Colormap cmap = 0;
2128   int auto_display = 0;
2129   MDisplayInfo *disp_info = NULL;
2130   MWDevice *device = NULL;
2131   MSymbol key;
2132   XWindowAttributes attr;
2133   unsigned depth = 0;
2134   MPlist *plist;
2135   AppData app_data;
2136   MFont *font = NULL;
2137   MFace *face;
2138   int use_xfont = 0, use_freetype = 0, use_xft = 0;
2139
2140   for (plist = param; (key = mplist_key (plist)) != Mnil;
2141        plist = mplist_next (plist))
2142     {
2143       if (key == Mdisplay)
2144         display = (Display *) mplist_value (plist);
2145       else if (key == Mscreen)
2146         screen = mplist_value (plist);
2147       else if (key == Mdrawable)
2148         drawable = (Drawable) mplist_value (plist);
2149       else if (key == Mdepth)
2150         depth = (unsigned) mplist_value (plist);
2151       else if (key == Mwidget)
2152         widget = (Widget) mplist_value (plist);
2153       else if (key == Mcolormap)
2154         cmap = (Colormap) mplist_value (plist);
2155       else if (key == Mfont)
2156         {
2157           MSymbol val = MPLIST_SYMBOL (plist);
2158
2159           if (val == Mx)
2160             use_xfont = 1;
2161 #ifdef HAVE_FREETYPE
2162           else if (val == Mfreetype)
2163             use_freetype = 1;
2164 #ifdef HAVE_XFT2
2165           else if (val == Mxft)
2166             use_xft = 1;
2167 #endif
2168 #endif
2169         }
2170     }
2171
2172   /* If none of them is specified, use all of them.  */
2173   if (! use_xfont && ! use_freetype && ! use_xft)
2174     use_xfont = use_freetype = use_xft = 1;
2175
2176   if (widget)
2177     {
2178       display = XtDisplay (widget);
2179       screen_num = XScreenNumberOfScreen (XtScreen (widget));
2180       depth = DefaultDepth (display, screen_num);
2181     }
2182   else if (drawable)
2183     {
2184       Window root_window;
2185       int x, y;
2186       unsigned width, height, border_width;
2187
2188       if (! display)
2189         MERROR (MERROR_WIN, -1);
2190       XGetGeometry (display, drawable, &root_window,
2191                     &x, &y, &width, &height, &border_width, &depth);
2192       XGetWindowAttributes (display, root_window, &attr);
2193       screen_num = XScreenNumberOfScreen (attr.screen);
2194     }
2195   else
2196     {
2197       if (screen)
2198         display = DisplayOfScreen (screen);
2199       else
2200         {
2201           if (! display)
2202             {
2203               display = XOpenDisplay (NULL);
2204               if (! display)
2205                 MERROR (MERROR_WIN, -1);
2206               auto_display = 1;
2207             }
2208           screen = DefaultScreenOfDisplay (display);
2209         }
2210       screen_num = XScreenNumberOfScreen (screen);
2211       if (! depth)
2212         depth = DefaultDepth (display, screen_num);
2213     }
2214
2215   if (! cmap)
2216     cmap = DefaultColormap (display, screen_num);
2217
2218   for (plist = display_info_list; mplist_key (plist) != Mnil;
2219        plist = mplist_next (plist))
2220     {
2221       disp_info = (MDisplayInfo *) mplist_value (plist);
2222       if (disp_info->display == display)
2223         break;
2224     }
2225
2226   if (mplist_key (plist) != Mnil)
2227     M17N_OBJECT_REF (disp_info);
2228   else
2229     {
2230       M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
2231       disp_info->display = display;
2232       disp_info->auto_display = auto_display;
2233       disp_info->font_list = mplist ();
2234       find_modifier_bits (disp_info);
2235       disp_info->MULE_BASELINE_OFFSET
2236         = XInternAtom (display, "_MULE_BASELINE_OFFSET", False);
2237       disp_info->AVERAGE_WIDTH
2238         = XInternAtom (display, "AVERAGE_WIDTH", False);
2239       mplist_add (display_info_list, Mt, disp_info);
2240     }  
2241
2242   for (plist = device_list; mplist_key (plist) != Mnil;
2243        plist = mplist_next (plist))
2244     {
2245       device = (MWDevice *) mplist_value (plist);
2246       if (device->display_info == disp_info
2247           && device->depth == depth
2248           && device->cmap == cmap
2249           && device->screen_num == screen_num)
2250         break;
2251     }
2252
2253   if (mplist_key (plist) != Mnil)
2254     M17N_OBJECT_REF (device);
2255   else
2256     {
2257       unsigned long valuemask = GCForeground;
2258       XGCValues values;
2259       double pixels, mm;
2260
2261       M17N_OBJECT (device, free_device, MERROR_WIN);
2262       device->display_info = disp_info;
2263       device->screen_num = screen_num;
2264       /* A drawable on which to create GCs.  */
2265       device->drawable = XCreatePixmap (display,
2266                                         RootWindow (display, screen_num),
2267                                         1, 1, depth);
2268       device->depth = depth;
2269       device->cmap = cmap;
2270       pixels = DisplayHeight (display, screen_num);
2271       mm = DisplayHeightMM (display, screen_num);
2272       device->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
2273       device->realized_face_list = mplist ();
2274       device->realized_font_list = mplist ();
2275       mplist_add (device->realized_font_list, Mt, NULL);
2276       device->realized_fontset_list = mplist ();
2277       device->gc_list = mplist ();
2278       values.foreground = BlackPixel (display, screen_num);
2279       device->scratch_gc = XCreateGC (display, device->drawable,
2280                                       valuemask, &values);
2281 #ifdef HAVE_XFT2
2282       device->xft_draw = XftDrawCreate (display, device->drawable,
2283                                         DefaultVisual (display, screen_num),
2284                                         cmap);
2285 #endif
2286     }
2287
2288   frame->device = device;
2289   frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2290   frame->dpi = device->resy;
2291   frame->driver = &x_driver;
2292   frame->font_driver_list = mplist ();
2293 #ifdef HAVE_XFT2
2294   if (use_xft)
2295     {
2296       mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2297       use_freetype = 0;
2298     }
2299 #endif  /* HAVE_XFT2 */
2300 #ifdef HAVE_FREETYPE
2301   if (use_freetype)
2302     mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2303 #endif  /* HAVE_FREETYPE */
2304   if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list))
2305     mplist_add (frame->font_driver_list, Mx, &xfont_driver);
2306
2307   frame->realized_font_list = device->realized_font_list;
2308   frame->realized_face_list = device->realized_face_list;
2309   frame->realized_fontset_list = device->realized_fontset_list;
2310
2311   if (widget)
2312     {
2313       XtResource resources[] = {
2314         { XtNfont, XtCFont, XtRString, sizeof (String),
2315           XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2316         { XtNforeground, XtCForeground, XtRString, sizeof (String),
2317           XtOffset (AppDataPtr, foreground), XtRString, "black" },
2318         { XtNbackground, XtCBackground, XtRString, sizeof (String),
2319           XtOffset (AppDataPtr, background), XtRString, "white" },
2320         { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2321           XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2322       };
2323
2324       XtGetApplicationResources (widget, &app_data,
2325                                  resources, XtNumber (resources), NULL, 0);
2326       frame->foreground = msymbol (app_data.foreground);
2327       frame->background = msymbol (app_data.background);
2328       frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2329     }
2330   else
2331     {
2332       app_data.font = DEFAULT_FONT;
2333       frame->foreground = msymbol ("black");
2334       frame->background = msymbol ("white");
2335       frame->videomode = Mnormal;
2336     }
2337
2338   if (strcmp (app_data.font, DEFAULT_FONT) != 0)
2339     {
2340       XFontStruct *xfont = XLoadQueryFont (display, app_data.font);
2341       unsigned long value;
2342       char *name;
2343
2344       if (xfont)
2345         {
2346           font = mfont_parse_name (app_data.font, Mx);
2347           if (! font
2348               && XGetFontProperty (xfont, XA_FONT, &value)
2349               && (name = ((char *) XGetAtomName (display, (Atom) value))))
2350             font = mfont_parse_name (name, Mx);
2351           XFreeFont (display, xfont);
2352         }
2353     }
2354   if (! font)
2355       font = mfont_parse_name (DEFAULT_FONT, Mx);
2356   else if (! font->size)
2357     font->size = 130;
2358   face = mface_from_font (font);
2359   free (font);
2360   face->property[MFACE_FONTSET] = mfontset (NULL);
2361   face->property[MFACE_FOREGROUND] = frame->foreground;
2362   face->property[MFACE_BACKGROUND] = frame->background;
2363   mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2364   mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2365   face->property[MFACE_VIDEOMODE] = frame->videomode;
2366   mface_put_prop (face, Mhook_func, 
2367                   mface_get_prop (mface__default, Mhook_func));
2368   face->property[MFACE_RATIO] = (void *) 100;
2369   mplist_push (param, Mface, face);
2370   M17N_OBJECT_UNREF (face);
2371
2372 #ifdef X_SET_ERROR_HANDLER
2373   XSetErrorHandler (x_error_handler);
2374   XSetIOErrorHandler (x_io_error_handler);
2375 #endif
2376   return 0;
2377 }
2378
2379 \f
2380
2381 /* XIM (X Input Method) handler */
2382
2383 typedef struct MInputXIMMethodInfo
2384 {
2385   Display *display;
2386   XIM xim;
2387   MSymbol language;
2388   MSymbol coding;
2389 } MInputXIMMethodInfo;
2390
2391 typedef struct MInputXIMContextInfo
2392 {
2393   XIC xic;
2394   Window win;
2395   MConverter *converter;
2396 } MInputXIMContextInfo;
2397
2398 static int
2399 xim_open_im (MInputMethod *im)
2400 {
2401   MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2402   MLocale *saved, *this;
2403   char *save_modifier_list;
2404   XIM xim;
2405   MInputXIMMethodInfo *im_info;
2406
2407   saved = mlocale_set (LC_CTYPE, NULL);
2408   this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2409   if (! this)
2410     /* The specified locale is not supported.  */
2411     MERROR (MERROR_LOCALE, -1);
2412   if (mlocale_get_prop (this, Mcoding) == Mnil)
2413     {
2414       /* Unable to decode the output of XIM.  */
2415       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2416       MERROR (MERROR_LOCALE, -1);
2417     }
2418
2419   if (arg->modifier_list)
2420     save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2421   else
2422     save_modifier_list = XSetLocaleModifiers ("");
2423   if (! save_modifier_list)
2424     {
2425       /* The specified locale is not supported by X.  */
2426       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2427       MERROR (MERROR_LOCALE, -1);
2428     }
2429
2430   xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2431   if (! xim)
2432     {
2433       /* No input method is available in the current locale.  */
2434       XSetLocaleModifiers (save_modifier_list);
2435       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2436       MERROR (MERROR_WIN, -1);
2437     }
2438
2439   MSTRUCT_MALLOC (im_info, MERROR_WIN);
2440   im_info->display = arg->display;
2441   im_info->xim = xim;
2442   im_info->language = mlocale_get_prop (this, Mlanguage);
2443   im_info->coding = mlocale_get_prop (this, Mcoding);
2444   im->info = im_info;
2445
2446   XSetLocaleModifiers (save_modifier_list);
2447   mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2448
2449   return 0;
2450 }
2451
2452 static void
2453 xim_close_im (MInputMethod *im)
2454 {
2455   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2456
2457   XCloseIM (im_info->xim);
2458   free (im_info);
2459 }
2460
2461 static int
2462 xim_create_ic (MInputContext *ic)
2463 {
2464   MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2465   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2466   MInputXIMContextInfo *ic_info;
2467   XIC xic;
2468
2469   if (! arg->input_style)
2470     {
2471       /* By default, use Root style.  */
2472       arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2473       arg->preedit_attrs = NULL;
2474       arg->status_attrs = NULL;
2475     }
2476
2477   if (! arg->preedit_attrs && ! arg->status_attrs)
2478     xic = XCreateIC (im_info->xim,
2479                      XNInputStyle, arg->input_style,
2480                      XNClientWindow, arg->client_win,
2481                      XNFocusWindow, arg->focus_win,
2482                      NULL);
2483   else if (arg->preedit_attrs && ! arg->status_attrs)
2484     xic = XCreateIC (im_info->xim,
2485                      XNInputStyle, arg->input_style,
2486                      XNClientWindow, arg->client_win,
2487                      XNFocusWindow, arg->focus_win,
2488                      XNPreeditAttributes, arg->preedit_attrs,
2489                      NULL);
2490   else if (! arg->preedit_attrs && arg->status_attrs)
2491     xic = XCreateIC (im_info->xim,
2492                      XNInputStyle, arg->input_style,
2493                      XNClientWindow, arg->client_win,
2494                      XNFocusWindow, arg->focus_win,
2495                      XNStatusAttributes, arg->status_attrs,
2496                      NULL);
2497   else
2498     xic = XCreateIC (im_info->xim,
2499                      XNInputStyle, arg->input_style,
2500                      XNClientWindow, arg->client_win,
2501                      XNFocusWindow, arg->focus_win,
2502                      XNPreeditAttributes, arg->preedit_attrs,
2503                      XNStatusAttributes, arg->status_attrs,
2504                      NULL);
2505   if (! xic)
2506     MERROR (MERROR_WIN, -1);
2507
2508   MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2509   ic_info->xic = xic;
2510   ic_info->win = arg->focus_win;
2511   ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2512   ic->info = ic_info;
2513   return 0;
2514 }
2515
2516 static void
2517 xim_destroy_ic (MInputContext *ic)
2518 {
2519   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2520
2521   XDestroyIC (ic_info->xic);
2522   mconv_free_converter (ic_info->converter);
2523   free (ic_info);
2524   ic->info = NULL;
2525 }
2526
2527 static int
2528 xim_filter (MInputContext *ic, MSymbol key, void *event)
2529 {
2530   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2531
2532   return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2533 }
2534
2535
2536 static int
2537 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2538 {
2539   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2540   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2541   XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2542   KeySym keysym;
2543   Status status;
2544   char *buf;
2545   int len;
2546
2547   buf = (char *) alloca (512);
2548   len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2549   if (status == XBufferOverflow)
2550     {
2551       buf = (char *) alloca (len);
2552       len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2553     }
2554
2555   mtext_reset (ic->produced);
2556   if (len == 0)
2557     return 1;
2558
2559   mconv_reset_converter (ic_info->converter);
2560   mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2561   mconv_decode (ic_info->converter, ic->produced);
2562   mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2563                   Mlanguage, (void *) im_info->language);
2564   mtext_cpy (mt, ic->produced);
2565   mtext_reset (ic->produced);  
2566   return 0;
2567 }
2568
2569 \f
2570 /*=*/
2571
2572 /*** @} */
2573 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2574 \f
2575 /* External API */
2576
2577 /*** @addtogroup m17nInputMethodWin */
2578
2579 /*** @{ */
2580
2581 /***en
2582     @brief Input method driver for XIM.
2583
2584     The driver #minput_xim_driver is for the foreign input method of
2585     name #Mxim.  It uses XIM (X Input Methods) as a background input
2586     engine.
2587
2588     As the symbol #Mxim has property #Minput_driver whose value is
2589     a pointer to this driver, the input method of language #Mnil
2590     and name #Mxim uses this driver.
2591
2592     Therefore, for such input methods, the driver dependent arguments
2593     to the functions whose name begin with minput_ must be as follows.
2594
2595     The argument $ARG of the function minput_open_im () must be a
2596     pointer to the structure #MInputXIMArgIM.  See the documentation
2597     of #MInputXIMArgIM for more details.
2598
2599     The argument $ARG of the function minput_create_ic () must be a
2600     pointer to the structure #MInputXIMArgIC. See the documentation
2601     of #MInputXIMArgIC for more details.
2602
2603     The argument $ARG of the function minput_filter () must be a
2604     pointer to the structure @c XEvent.  The argument $KEY is ignored.
2605
2606     The argument $ARG of the function minput_lookup () must be the
2607     same one as that of the function minput_filter ().  The argument
2608     $KEY is ignored.  */
2609
2610 /***ja
2611     @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2612
2613     ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ê¡¢
2614     XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
2615
2616     ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2617     #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim 
2618     ¤Ç¤¢¤ëÆþÎϥ᥽¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2619
2620     ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ 
2621     ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2622
2623     ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIM 
2624     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò»²¾È¡£
2625
2626     ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIC 
2627     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ¤ò»²¾È¡£
2628
2629     ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ@c XEvent 
2630     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2631
2632     ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter () 
2633     ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì¤ë¡£  */
2634
2635 MInputDriver minput_xim_driver =
2636   { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2637     xim_filter, xim_lookup, NULL };
2638
2639 /*** @} */ 
2640
2641 #else  /* not HAVE_X11 */
2642
2643 int device_open () { return -1; }
2644
2645 #endif  /* not HAVE_X11 */
2646
2647 /*
2648   Local Variables:
2649   coding: euc-japan
2650   End:
2651 */