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