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