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