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