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