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