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