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