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