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