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