376b12a762116fe1c082f212a65d318b7f88e079
[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 int xfont_list (MFrame *frame, MPlist *plist,
431                         MFont *font, MSymbol language, int maxnum);
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 int
906 xfont_list (MFrame *frame, MPlist *plist, MFont *font, MSymbol language,
907             int maxnum)
908 {
909   MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
910   MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil;
911   MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil;
912   MPlist *p, *pl;
913   int num = 0;
914
915   if (registry != Mnil)
916     xfont_registry_list (frame, registry);
917   else
918     xfont_list_all (frame);
919
920   /* As we have not yet implemented the language check, return all
921      base fonts.  */
922   if (! font)
923     MPLIST_DO (p, disp_info->base_font_list)
924       {
925         mplist_add (plist, MPLIST_KEY (p), MPLIST_VAL (p));
926         num++;
927         if (num == maxnum)
928           return num;
929       }
930   else
931     {
932       MXFontList *xfontlist;
933       MXFont *xfont;
934       int i;
935
936       pl = disp_info->font_list;
937       if (registry != Mnil)
938         {
939           pl = mplist_find_by_key (pl, registry);
940           if (! pl)
941             return 0;
942         }
943
944       MPLIST_DO (pl, pl)
945         {
946           p = MPLIST_VAL (pl);
947           if (family != Mnil)
948             {
949               p = mplist_find_by_key (p, family);
950               if (! p)
951                 return 0;
952             }
953           MPLIST_DO (p, p)
954             {
955               xfontlist = MPLIST_VAL (p);
956               for (i = 0; i < xfontlist->used; i++)
957                 {
958                   xfont = xfontlist->fonts + i;
959                   if (mfont__match_p (&xfont->core, font, MFONT_REGISTRY))
960                     {
961                       mplist_add (plist, MPLIST_KEY (p), &xfont->core);
962                       num++;
963                       if (num == maxnum)
964                         return num;
965                     }
966                 }
967               if (family != Mnil)
968                 break;
969             }
970           if (registry != Mnil)
971             break;
972         }
973     }
974   return num;
975 }
976
977 \f
978 /* Xft Handler */
979
980 #ifdef HAVE_XFT2
981
982 typedef struct
983 {
984   M17NObject control;
985   Display *display;
986   XftFont *font_aa;
987   XftFont *font_no_aa;
988 } MXftFontInfo;
989
990 static int xft_open (MRealizedFont *);
991 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
992 static void xft_render (MDrawWindow, int, int, MGlyphString *,
993                         MGlyph *, MGlyph *, int, MDrawRegion);
994
995 MFontDriver xft_driver =
996   { NULL,                       /* Set to ft_select in device_init (). */
997     xft_open, xft_find_metric,
998     NULL,                       /* Set to ft_encode_char in device_init (). */
999     xft_render,
1000     NULL                        /* Set to ft_list in device_init (). */
1001   };
1002
1003
1004 static void
1005 close_xft (void *object)
1006 {
1007   MXftFontInfo *font_info = object;
1008
1009   XftFontClose (font_info->display, font_info->font_aa);
1010   XftFontClose (font_info->display, font_info->font_no_aa);
1011   free (font_info);
1012 }
1013
1014
1015 static XftFont *
1016 xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
1017 {
1018   XftPattern *pattern;
1019   XftFontInfo *xft_font_info;
1020   XftFont *font;
1021
1022   pattern = XftPatternCreate ();
1023   XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
1024   XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
1025   XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
1026   xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
1027   if (! xft_font_info)
1028     return NULL;
1029   font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
1030   XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
1031   return font;
1032 }
1033
1034
1035 static int
1036 xft_open (MRealizedFont *rfont)
1037 {
1038   MFrame *frame;
1039   MFTInfo *ft_info;
1040   MXftFontInfo *font_info;
1041   int size;
1042
1043   if ((mfont__ft_driver.open) (rfont) < 0)
1044     return -1;
1045
1046   size = rfont->font.property[MFONT_SIZE] / 10;
1047   frame = rfont->frame;
1048
1049   ft_info = rfont->info;
1050   M17N_OBJECT (font_info, close_xft, MERROR_WIN);
1051   ft_info->extra_info = font_info;
1052   font_info->display = FRAME_DISPLAY (frame);
1053   font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
1054   if (font_info->font_aa)
1055     {
1056       font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
1057       if (font_info->font_no_aa)
1058         {
1059           rfont->type = Mxft;
1060           rfont->fontp = font_info->font_no_aa;
1061           return 0;
1062         }
1063       XftFontClose (FRAME_DISPLAY (rfont->frame), font_info->font_aa);
1064     }
1065   free (font_info);  
1066   ft_info->extra_info = NULL;
1067   rfont->status = -1;
1068   return -1;
1069 }
1070
1071
1072 static void
1073 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
1074                 int from, int to)
1075 {
1076   MFTInfo *ft_info = rfont->info;
1077   MXftFontInfo *font_info = ft_info->extra_info;
1078   MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1079
1080   for (; g != gend; g++)
1081     {
1082       if (g->code == MCHAR_INVALID_CODE)
1083         {
1084           MGlyph *start = g++;
1085
1086           while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
1087           (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
1088                                           GLYPH_INDEX (g));
1089           g--;
1090         }
1091       else
1092         {
1093           XGlyphInfo extents;
1094
1095           XftGlyphExtents (FRAME_DISPLAY (gstring->frame),
1096                            font_info->font_aa, &g->code, 1, &extents);
1097           g->lbearing = - extents.x;
1098           g->rbearing = extents.width - extents.x;
1099           g->width = extents.xOff;
1100           g->ascent = extents.y;
1101           g->descent = extents.height - extents.y;
1102         }
1103     }
1104 }
1105
1106
1107 static void 
1108 xft_render (MDrawWindow win, int x, int y,
1109             MGlyphString *gstring, MGlyph *from, MGlyph *to,
1110             int reverse, MDrawRegion region)
1111 {
1112   MRealizedFace *rface = from->rface;
1113   MFrame *frame = rface->frame;
1114   MFTInfo *ft_info = rface->rfont->info;
1115   MXftFontInfo *font_info = ft_info->extra_info;
1116   XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1117   XftColor *xft_color = (! reverse
1118                          ? &((GCInfo *) rface->info)->xft_color_fore
1119                          : &((GCInfo *) rface->info)->xft_color_back);
1120   XftFont *xft_font = (gstring->control.anti_alias
1121                        && FRAME_DEVICE (frame)->depth > 1
1122                        ? font_info->font_aa : font_info->font_no_aa);
1123   MGlyph *g;
1124   FT_UInt *glyphs;
1125   int last_x;
1126   int nglyphs;
1127
1128   if (from == to)
1129     return;
1130
1131   XftDrawChange (xft_draw, (Drawable) win);
1132   XftDrawSetClip (xft_draw, (Region) region);
1133       
1134   glyphs = alloca (sizeof (FT_UInt) * (to - from));
1135   for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1136     {
1137       if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
1138         glyphs[nglyphs++] = g->code;
1139       else
1140         {
1141           if (nglyphs > 0)
1142             XftDrawGlyphs (xft_draw, xft_color, xft_font,
1143                            last_x, y, glyphs, nglyphs);
1144           nglyphs = 0;
1145           XftDrawGlyphs (xft_draw, xft_color, xft_font,
1146                          x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1147           last_x = x + g->width;
1148         }
1149     }
1150   if (nglyphs > 0)
1151     XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1152 }
1153
1154 #endif
1155
1156 \f
1157 /* Functions for the device driver.  */
1158
1159 static void
1160 mwin__close_device (MFrame *frame)
1161 {
1162   M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
1163 }
1164
1165 static void *
1166 mwin__device_get_prop (MFrame *frame, MSymbol key)
1167 {
1168   MWDevice *device = FRAME_DEVICE (frame);
1169
1170   if (key == Mdisplay)
1171     return (void *) device->display_info->display;
1172   if (key == Mscreen)
1173     return (void *) ScreenOfDisplay(device->display_info->display,
1174                                     device->screen_num);
1175   if (key == Mcolormap)
1176     return (void *) device->cmap;
1177   if (key == Mdepth)
1178     return (void *) device->depth;
1179   return NULL;
1180 }
1181
1182 static void
1183 mwin__realize_face (MRealizedFace *rface)
1184 {
1185   MFrame *frame;
1186   MSymbol foreground, background, videomode;
1187   MFaceHLineProp *hline;
1188   MFaceBoxProp *box;
1189   GCInfo *info;
1190
1191   if (rface != rface->ascii_rface)
1192     {
1193       rface->info = rface->ascii_rface->info;
1194       return;
1195     }
1196
1197   frame = rface->frame;
1198   MSTRUCT_CALLOC (info, MERROR_WIN);
1199
1200   foreground = rface->face.property[MFACE_FOREGROUND];
1201   background = rface->face.property[MFACE_BACKGROUND];
1202   videomode = rface->face.property[MFACE_VIDEOMODE];
1203   if (! videomode)
1204     videomode = frame->videomode;
1205   if (videomode != Mreverse)
1206     {
1207       info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1208       info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1209     }
1210   else
1211     {
1212       info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1213       info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1214     }
1215 #ifdef HAVE_XFT2
1216   if (foreground == Mnil)
1217     foreground = frame->foreground;
1218   if (background == Mnil)
1219     background = frame->background;
1220   if (videomode == Mreverse)
1221     {
1222       MSymbol temp = foreground;
1223       foreground = background;
1224       background = temp;
1225     }
1226   if (! XftColorAllocName (FRAME_DISPLAY (frame),
1227                            FRAME_VISUAL (frame),
1228                            FRAME_CMAP (frame),
1229                            MSYMBOL_NAME (foreground),
1230                            &info->xft_color_fore))
1231     mdebug_hook ();
1232   if (! XftColorAllocName (FRAME_DISPLAY (frame),
1233                            FRAME_VISUAL (frame),
1234                            FRAME_CMAP (frame),
1235                            MSYMBOL_NAME (background),
1236                            &info->xft_color_back))
1237     mdebug_hook ();
1238 #endif
1239
1240   hline = rface->hline;
1241   if (hline)
1242     {
1243       if (hline->color)
1244         info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1245       else
1246         info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1247     }
1248
1249   box = rface->box;
1250   if (box)
1251     {
1252       if (box->color_top)
1253         info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1254       else
1255         info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1256
1257       if (box->color_left && box->color_left != box->color_top)
1258         info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1259       else
1260         info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
1261
1262       if (box->color_bottom && box->color_bottom != box->color_top)
1263         info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1264       else
1265         info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
1266
1267       if (box->color_right && box->color_right != box->color_bottom)
1268         info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1269       else
1270         info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
1271     }
1272
1273   rface->info = info;
1274 }
1275
1276
1277 static void
1278 mwin__free_realized_face (MRealizedFace *rface)
1279 {
1280   if (rface == rface->ascii_rface)
1281     free (rface->info);
1282 }
1283
1284
1285 static void
1286 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1287                   int reverse,
1288                   int x, int y, int width, int height, MDrawRegion region)
1289 {
1290   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1291
1292   if (region)
1293     gc = set_region (frame, gc, region);
1294
1295   XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1296                   x, y, width, height);
1297 }
1298
1299
1300 static void
1301 mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
1302                         MGlyphString *gstring, MGlyph *from, MGlyph *to,
1303                         int reverse, MDrawRegion region)
1304 {
1305   MRealizedFace *rface = from->rface;
1306   Display *display = FRAME_DISPLAY (rface->frame);
1307   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1308
1309   if (from == to)
1310     return;
1311
1312   if (region)
1313     gc = set_region (rface->frame, gc, region);
1314   for (; from < to; from++)
1315     {
1316       XDrawRectangle (display, (Window) win, gc,
1317                       x, y - gstring->ascent + 1, from->width - 1,
1318                       gstring->ascent + gstring->descent - 2);
1319       x += from->width;
1320     }
1321 }
1322
1323
1324 static void
1325 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1326                  MRealizedFace *rface, int reverse,
1327                  int x, int y, int width, MDrawRegion region)
1328 {
1329   enum MFaceHLineType type = rface->hline->type;
1330   GCInfo *info = rface->info;
1331   GC gc = gc = info->gc[GC_HLINE];
1332   int i;
1333
1334   y = (type == MFACE_HLINE_BOTTOM
1335        ? y + gstring->text_descent - rface->hline->width
1336        : type == MFACE_HLINE_UNDER
1337        ? y + 1
1338        : type == MFACE_HLINE_STRIKE_THROUGH
1339        ? y - ((gstring->ascent + gstring->descent) / 2)
1340        : y - gstring->text_ascent);
1341   if (region)
1342     gc = set_region (frame, gc, region);
1343
1344   for (i = 0; i < rface->hline->width; i++)
1345     XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1346                x, y + i, x + width - 1, y + i);
1347 }
1348
1349
1350 static void
1351 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1352                 MGlyph *g, int x, int y, int width, MDrawRegion region)
1353 {
1354   Display *display = FRAME_DISPLAY (frame);
1355   MRealizedFace *rface = g->rface;
1356   MFaceBoxProp *box = rface->box;
1357   GCInfo *info = rface->info;
1358   GC gc_top, gc_left, gc_right, gc_btm;
1359   int y0, y1;
1360   int i;
1361
1362   y0 = y - (gstring->text_ascent
1363             + rface->box->inner_vmargin + rface->box->width);
1364   y1 = y + (gstring->text_descent
1365             + rface->box->inner_vmargin + rface->box->width - 1);
1366
1367   gc_top = info->gc[GC_BOX_TOP];
1368   if (region)
1369     gc_top = set_region (frame, gc_top, region);
1370   if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1371     gc_btm = gc_top;
1372   else
1373     gc_btm = info->gc[GC_BOX_BOTTOM];
1374
1375   if (g->type == GLYPH_BOX)
1376     {
1377       int x0, x1;
1378
1379       if (g->left_padding)
1380         x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1381       else
1382         x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1383
1384       /* Draw the top side.  */
1385       for (i = 0; i < box->width; i++)
1386         XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1387
1388       /* Draw the bottom side.  */
1389       if (region && gc_btm != gc_top)
1390         gc_btm = set_region (frame, gc_btm, region);
1391       for (i = 0; i < box->width; i++)
1392         XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1393
1394       if (g->left_padding > 0)
1395         {
1396           /* Draw the left side.  */
1397           if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1398             gc_left = gc_top;
1399           else
1400             {
1401               gc_left = info->gc[GC_BOX_LEFT];
1402               if (region)
1403                 gc_left = set_region (frame, gc_left, region);
1404             }
1405           for (i = 0; i < rface->box->width; i++)
1406             XDrawLine (display, (Window) win, gc_left,
1407                        x0 + i, y0 + i, x0 + i, y1 - i);
1408         }
1409       else
1410         {
1411           /* Draw the right side.  */
1412           if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1413             gc_right = gc_top;
1414           else
1415             {
1416               gc_right = info->gc[GC_BOX_RIGHT];
1417               if (region)
1418                 gc_right = set_region (frame, gc_right, region);
1419             }
1420           for (i = 0; i < rface->box->width; i++)
1421             XDrawLine (display, (Window) win, gc_right,
1422                        x1 - i, y0 + i, x1 - i, y1 - i);
1423         }
1424     }
1425   else
1426     {
1427       /* Draw the top side.  */
1428       for (i = 0; i < box->width; i++)
1429         XDrawLine (display, (Window) win, gc_top,
1430                    x, y0 + i, x + width - 1, y0 + i);
1431
1432       /* Draw the bottom side.  */
1433       if (region && gc_btm != gc_top)
1434         gc_btm = set_region (frame, gc_btm, region);
1435       for (i = 0; i < box->width; i++)
1436         XDrawLine (display, (Window) win, gc_btm,
1437                    x, y1 - i, x + width - 1, y1 - i);
1438     }
1439 }
1440
1441
1442 #if 0
1443 static void
1444 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1445                    int reverse, int x, int y,
1446                    int width, int height, int row_bytes, unsigned char *bmp,
1447                    MDrawRegion region)
1448 {
1449   Display *display = FRAME_DISPLAY (frame);
1450   int i, j;
1451   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1452
1453   if (region)
1454     gc = set_region (frame, gc, region);
1455
1456   for (i = 0; i < height; i++, bmp += row_bytes)
1457     for (j = 0; j < width; j++)
1458       if (bmp[j / 8] & (1 << (7 - (j % 8))))
1459         XDrawPoint (display, (Window) win, gc, x + j, y + i);
1460 }
1461 #endif
1462
1463 static void
1464 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1465                    int intensity, MDrawPoint *points, int num,
1466                    MDrawRegion region)
1467 {
1468   GCInfo *info = rface->info;
1469   GC gc;
1470
1471   if (! (gc = info->gc[intensity]))
1472     gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
1473                                                       info, intensity);
1474   if (region)
1475     gc = set_region (frame, gc, region);
1476
1477   XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1478                (XPoint *) points, num, CoordModeOrigin);
1479 }
1480
1481
1482 static MDrawRegion
1483 mwin__region_from_rect (MDrawMetric *rect)
1484 {
1485   MDrawRegion region1 = XCreateRegion ();
1486   MDrawRegion region2 = XCreateRegion ();
1487   XRectangle xrect;
1488
1489   xrect.x = rect->x;
1490   xrect.y = rect->y;
1491   xrect.width = rect->width;
1492   xrect.height = rect->height;
1493   XUnionRectWithRegion (&xrect, region1, region2);
1494   XDestroyRegion (region1);
1495   return region2;
1496 }
1497
1498 static void
1499 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1500 {
1501   MDrawRegion region1 = XCreateRegion ();
1502   XRectangle xrect;
1503
1504   xrect.x = rect->x;
1505   xrect.y = rect->y;
1506   xrect.width = rect->width;
1507   xrect.height = rect->height;
1508
1509   XUnionRegion (region, region, region1);
1510   XUnionRectWithRegion (&xrect, region1, region);
1511   XDestroyRegion (region1);
1512 }
1513
1514 static void
1515 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1516 {
1517   MDrawRegion region = XCreateRegion ();
1518
1519   XUnionRegion (region1, region1, region);
1520   XIntersectRegion (region, region2, region1);
1521   XDestroyRegion (region);
1522 }
1523
1524 static void
1525 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1526 {
1527   MDrawRegion region1 = XCreateRegion ();
1528   XRectangle xrect;
1529
1530   xrect.x = rect->x;
1531   xrect.y = rect->y;
1532   xrect.width = rect->width;
1533   xrect.height = rect->height;
1534   XUnionRectWithRegion (&xrect, region1, region);
1535   XDestroyRegion (region1);
1536 }
1537
1538 static void
1539 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1540 {
1541   XRectangle xrect;
1542
1543   XClipBox (region, &xrect);
1544   rect->x = xrect.x;
1545   rect->y = xrect.y;
1546   rect->width = xrect.width;
1547   rect->height = xrect.height;
1548 }
1549
1550 static void
1551 mwin__free_region (MDrawRegion region)
1552 {
1553   XDestroyRegion (region);
1554 }
1555
1556 static void
1557 mwin__dump_region (MDrawRegion region)
1558 {
1559   XRectangle rect;
1560   XClipBox (region, &rect);
1561   fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1562 }
1563
1564
1565 static MDrawWindow
1566 mwin__create_window (MFrame *frame, MDrawWindow parent)
1567 {
1568   Display *display = FRAME_DISPLAY (frame);
1569   Window win;
1570   XWMHints wm_hints = { InputHint, False };
1571   XClassHint class_hints = { "M17N-IM", "m17n-im" };
1572   XSetWindowAttributes set_attrs;
1573   unsigned long mask;
1574   XGCValues values;
1575   GCInfo *info = frame->rface->info;
1576
1577   if (! parent)
1578     parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1579   mask = GCForeground;
1580   XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1581   set_attrs.background_pixel = values.foreground;
1582   set_attrs.backing_store = Always;
1583   set_attrs.override_redirect = True;
1584   set_attrs.save_under = True;
1585   mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1586   win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1587                        CopyFromParent, InputOutput, CopyFromParent,
1588                        mask, &set_attrs);
1589   XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1590                     NULL, &wm_hints, &class_hints);
1591   XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1592   return (MDrawWindow) win;
1593 }
1594
1595 static void
1596 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1597 {
1598   XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1599 }
1600
1601 #if 0
1602 static MDrawWindow
1603 mwin__event_window (void *event)
1604 {
1605   return ((MDrawWindow) ((XEvent *) event)->xany.window);
1606 }
1607
1608 static void
1609 mwin__print_event (void *arg, char *win_name)
1610 {
1611   char *event_name;
1612   XEvent *event = (XEvent *) arg;
1613
1614   switch (event->xany.type)
1615     {
1616     case 2: event_name = "KeyPress"; break;
1617     case 3: event_name = "KeyRelease"; break;
1618     case 4: event_name = "ButtonPress"; break;
1619     case 5: event_name = "ButtonRelease"; break;
1620     case 6: event_name = "MotionNotify"; break;
1621     case 7: event_name = "EnterNotify"; break;
1622     case 8: event_name = "LeaveNotify"; break;
1623     case 9: event_name = "FocusIn"; break;
1624     case 10: event_name = "FocusOut"; break;
1625     case 11: event_name = "KeymapNotify"; break;
1626     case 12: event_name = "Expose"; break;
1627     case 13: event_name = "GraphicsExpose"; break;
1628     case 14: event_name = "NoExpose"; break;
1629     case 15: event_name = "VisibilityNotify"; break;
1630     case 16: event_name = "CreateNotify"; break;
1631     case 17: event_name = "DestroyNotify"; break;
1632     case 18: event_name = "UnmapNotify"; break;
1633     case 19: event_name = "MapNotify"; break;
1634     case 20: event_name = "MapRequest"; break;
1635     case 21: event_name = "ReparentNotify"; break;
1636     case 22: event_name = "ConfigureNotify"; break;
1637     case 23: event_name = "ConfigureRequest"; break;
1638     case 24: event_name = "GravityNotify"; break;
1639     case 25: event_name = "ResizeRequest"; break;
1640     case 26: event_name = "CirculateNotify"; break;
1641     case 27: event_name = "CirculateRequest"; break;
1642     case 28: event_name = "PropertyNotify"; break;
1643     case 29: event_name = "SelectionClear"; break;
1644     case 30: event_name = "SelectionRequest"; break;
1645     case 31: event_name = "SelectionNotify"; break;
1646     case 32: event_name = "ColormapNotify"; break;
1647     case 33: event_name = "ClientMessage"; break;
1648     case 34: event_name = "MappingNotify"; break;
1649     default: event_name = "unknown";
1650     }
1651
1652   fprintf (stderr, "%s: %s\n", win_name, event_name);
1653 }
1654 #endif
1655
1656 static void
1657 mwin__map_window (MFrame *frame, MDrawWindow win)
1658 {
1659   XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1660 }
1661
1662 static void
1663 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1664 {
1665   XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1666 }
1667
1668 static void
1669 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1670                        MDrawMetric *geometry)
1671 {
1672   Display *display = FRAME_DISPLAY (frame);
1673   XWindowAttributes attr;
1674   Window parent = (Window) parent_win, root;
1675
1676   XGetWindowAttributes (display, (Window) win, &attr);
1677   geometry->x = attr.x + attr.border_width;
1678   geometry->y = attr.y + attr.border_width;
1679   geometry->width = attr.width;
1680   geometry->height = attr.height; 
1681
1682   if (! parent)
1683     parent = RootWindow (display, FRAME_SCREEN (frame));
1684   while (1)
1685     {
1686       Window this_parent, *children;
1687       unsigned n;
1688
1689       XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1690       if (children)
1691         XFree (children);
1692       if (this_parent == parent || this_parent == root)
1693         break;
1694       win = (MDrawWindow) this_parent;
1695       XGetWindowAttributes (display, (Window) win, &attr);
1696       geometry->x += attr.x + attr.border_width;
1697       geometry->y += attr.y + attr.border_width;
1698     }
1699 }
1700
1701 static void
1702 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1703                      MDrawMetric *current, MDrawMetric *new)
1704 {
1705   Display *display = FRAME_DISPLAY (frame);
1706   unsigned int mask = 0;
1707   XWindowChanges values;
1708
1709   if (current->width != new->width)
1710     {
1711       mask |= CWWidth;
1712       if (new->width <= 0)
1713         new->width = 1;
1714       values.width = current->width = new->width;
1715     }
1716   if (current->height != new->height)
1717     {
1718       mask |= CWHeight;
1719       if (new->height <= 0)
1720         new->height = 1;
1721       values.height = current->height = new->height;
1722     }
1723   if (current->x != new->x)
1724     {
1725       mask |= CWX;
1726       values.x = current->x = new->x;
1727     }
1728   if (current->y != new->y)
1729     {
1730       mask |= CWY;
1731       current->y = new->y;
1732       values.y = current->y = new->y;
1733     }
1734   if (mask)
1735     XConfigureWindow (display, (Window) win, mask, &values);
1736   XClearWindow (display, (Window) win);
1737 }
1738
1739 static MSymbol
1740 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
1741 {
1742   XEvent *event = (XEvent *) arg;
1743   MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
1744   int len;
1745   char buf[512];
1746   KeySym keysym;
1747   MSymbol key;
1748
1749   *modifiers = 0;
1750   if (event->xany.type != KeyPress
1751       /* && event->xany.type != KeyRelease */
1752       )
1753     return Mnil;
1754   len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
1755   if (len > 1)
1756     return Mnil;
1757   if (len == 1)
1758     {
1759       int c = keysym;
1760
1761       if (c < XK_space || c > XK_asciitilde)
1762         c = buf[0];
1763       if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
1764         *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1765       if (((XKeyEvent *) event)->state & ControlMask)
1766         {
1767           if (c >= 'a' && c <= 'z')
1768             c += 'A' - 'a';
1769           if (c >= ' ' && c < 127)
1770             *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1771         }
1772       key = minput__char_to_key (c);
1773     }
1774   else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
1775     return Mnil;
1776   else
1777     {
1778       char *str = XKeysymToString (keysym);
1779
1780       if (! str)
1781         return Mnil;
1782       key = msymbol (str);
1783       if (((XKeyEvent *) event)->state & ShiftMask)
1784         *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
1785       if (((XKeyEvent *) event)->state & ControlMask)
1786         *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
1787     }
1788   if (((XKeyEvent *) event)->state & disp_info->meta_mask)
1789     *modifiers |= MINPUT_KEY_META_MODIFIER;
1790   if (((XKeyEvent *) event)->state & disp_info->alt_mask)
1791     *modifiers |= MINPUT_KEY_ALT_MODIFIER;
1792   if (((XKeyEvent *) event)->state & disp_info->super_mask)
1793     *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
1794   if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
1795     *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
1796
1797   return key;
1798 }
1799
1800
1801 void
1802 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
1803 {
1804   unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
1805   XGCValues values;
1806   Display *display = FRAME_DISPLAY (frame);
1807   GCInfo *info = rface->info;
1808   int i;
1809
1810   for (i = 0; i <= GC_INVERSE; i++)
1811     {
1812       XGetGCValues (display, info->gc[i], valuemask, &values);
1813       fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
1814                values.foreground, values.background);
1815       fprintf (stderr, "\n");
1816     }
1817 }
1818
1819 static MDeviceDriver x_driver =
1820   {
1821     mwin__close_device,
1822     mwin__device_get_prop,
1823     mwin__realize_face,
1824     mwin__free_realized_face,
1825     mwin__fill_space,
1826     mwin__draw_empty_boxes,
1827     mwin__draw_hline,
1828     mwin__draw_box,
1829     mwin__draw_points,
1830     mwin__region_from_rect,
1831     mwin__union_rect_with_region,
1832     mwin__intersect_region,
1833     mwin__region_add_rect,
1834     mwin__region_to_rect,
1835     mwin__free_region,
1836     mwin__dump_region,
1837     mwin__create_window,
1838     mwin__destroy_window,
1839     mwin__map_window,
1840     mwin__unmap_window,
1841     mwin__window_geometry,
1842     mwin__adjust_window,
1843     mwin__parse_event
1844   };
1845
1846 /* Functions to be stored in MDeviceLibraryInterface by dlsym ().  */
1847
1848 int
1849 device_init ()
1850 {
1851   M_iso8859_1 = msymbol ("iso8859-1");
1852   M_iso10646_1 = msymbol ("iso10646-1");
1853
1854   display_info_list = mplist ();
1855   device_list = mplist ();
1856
1857 #ifdef HAVE_XFT2
1858   xft_driver.select = mfont__ft_driver.select;
1859   xft_driver.encode_char = mfont__ft_driver.encode_char;
1860   xft_driver.list = mfont__ft_driver.list;
1861 #endif
1862
1863   Mxim = msymbol ("xim");
1864   msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1865
1866   return 0;
1867 }
1868
1869 int
1870 device_fini ()
1871 {
1872   M17N_OBJECT_UNREF (display_info_list);
1873   M17N_OBJECT_UNREF (device_list);
1874   return 0;
1875 }
1876
1877 /** Return an MWDevice object corresponding to a display specified in
1878     PLIST.
1879
1880     It searches device_list for a device matching the display.  If
1881     found, return the found object.  Otherwise, return a newly created
1882     object.  */
1883
1884 int
1885 device_open (MFrame *frame, MPlist *param)
1886 {
1887   Display *display = NULL;
1888   Screen *screen = NULL;
1889   int screen_num;
1890   Drawable drawable = 0;
1891   Widget widget = NULL;
1892   Colormap cmap = 0;
1893   int auto_display = 0;
1894   MDisplayInfo *disp_info = NULL;
1895   MWDevice *device = NULL;
1896   MSymbol key;
1897   XWindowAttributes attr;
1898   unsigned depth = 0;
1899   MPlist *plist;
1900   AppData app_data;
1901   MFace *face;
1902   int use_xfont = 1, use_freetype = 1;
1903
1904   for (plist = param; (key = mplist_key (plist)) != Mnil;
1905        plist = mplist_next (plist))
1906     {
1907       if (key == Mdisplay)
1908         display = (Display *) mplist_value (plist);
1909       else if (key == Mscreen)
1910         screen = mplist_value (plist);
1911       else if (key == Mdrawable)
1912         drawable = (Drawable) mplist_value (plist);
1913       else if (key == Mdepth)
1914         depth = (unsigned) mplist_value (plist);
1915       else if (key == Mwidget)
1916         widget = (Widget) mplist_value (plist);
1917       else if (key == Mcolormap)
1918         cmap = (Colormap) mplist_value (plist);
1919       else if (key == Mfont)
1920         {
1921           MSymbol val = MPLIST_SYMBOL (plist);
1922
1923           if (val == Mx)
1924             use_freetype = 0;
1925 #ifdef HAVE_FREETYPE
1926           else if (val == Mfreetype)
1927             use_xfont = 0;
1928 #endif
1929         }
1930     }
1931
1932   if (widget)
1933     {
1934       display = XtDisplay (widget);
1935       screen_num = XScreenNumberOfScreen (XtScreen (widget));
1936       depth = DefaultDepth (display, screen_num);
1937     }
1938   else if (drawable)
1939     {
1940       Window root_window;
1941       int x, y;
1942       unsigned width, height, border_width;
1943
1944       if (! display)
1945         MERROR (MERROR_WIN, -1);
1946       XGetGeometry (display, drawable, &root_window,
1947                     &x, &y, &width, &height, &border_width, &depth);
1948       XGetWindowAttributes (display, root_window, &attr);
1949       screen_num = XScreenNumberOfScreen (attr.screen);
1950     }
1951   else
1952     {
1953       if (screen)
1954         display = DisplayOfScreen (screen);
1955       else
1956         {
1957           if (! display)
1958             {
1959               display = XOpenDisplay (NULL);
1960               if (! display)
1961                 MERROR (MERROR_WIN, -1);
1962               auto_display = 1;
1963             }
1964           screen = DefaultScreenOfDisplay (display);
1965         }
1966       screen_num = XScreenNumberOfScreen (screen);
1967       if (! depth)
1968         depth = DefaultDepth (display, screen_num);
1969     }
1970
1971   if (! cmap)
1972     cmap = DefaultColormap (display, screen_num);
1973
1974   for (plist = display_info_list; mplist_key (plist) != Mnil;
1975        plist = mplist_next (plist))
1976     {
1977       disp_info = (MDisplayInfo *) mplist_value (plist);
1978       if (disp_info->display == display)
1979         break;
1980     }
1981
1982   if (mplist_key (plist) != Mnil)
1983     M17N_OBJECT_REF (disp_info);
1984   else
1985     {
1986       M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
1987       disp_info->display = display;
1988       disp_info->auto_display = auto_display;
1989       disp_info->font_list = mplist ();
1990       disp_info->base_font_list = mplist ();
1991       find_modifier_bits (disp_info);
1992       mplist_add (display_info_list, Mt, disp_info);
1993     }  
1994
1995   for (plist = device_list; mplist_key (plist) != Mnil;
1996        plist = mplist_next (plist))
1997     {
1998       device = (MWDevice *) mplist_value (plist);
1999       if (device->display_info == disp_info
2000           && device->depth == depth
2001           && device->cmap == cmap)
2002         break;
2003     }
2004
2005   if (mplist_key (plist) != Mnil)
2006     M17N_OBJECT_REF (device);
2007   else
2008     {
2009       unsigned long valuemask = GCForeground;
2010       XGCValues values;
2011
2012       M17N_OBJECT (device, free_device, MERROR_WIN);
2013       device->display_info = disp_info;
2014       device->screen_num = screen_num;
2015       /* A drawable on which to create GCs.  */
2016       device->drawable = XCreatePixmap (display,
2017                                         RootWindow (display, screen_num),
2018                                         1, 1, depth);
2019       device->depth = depth;
2020       device->cmap = cmap;
2021       device->realized_face_list = mplist ();
2022       device->realized_font_list = mplist ();
2023       device->realized_fontset_list = mplist ();
2024       device->gc_list = mplist ();
2025       values.foreground = BlackPixel (display, screen_num);
2026       device->scratch_gc = XCreateGC (display, device->drawable,
2027                                       valuemask, &values);
2028 #ifdef HAVE_XFT2
2029       device->xft_draw = XftDrawCreate (display, device->drawable,
2030                                         DefaultVisual (display, screen_num),
2031                                         cmap);
2032 #endif
2033     }
2034
2035   frame->device = device;
2036   frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2037   frame->driver = &x_driver;
2038   frame->font_driver_list = mplist ();
2039   if (use_xfont)
2040     mplist_add (frame->font_driver_list, Mx, &xfont_driver);
2041 #ifdef HAVE_XFT2
2042   if (use_freetype)
2043     mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2044 #elif HAVE_FREETYPE
2045   if (use_freetype)
2046     mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2047 #endif
2048   frame->realized_font_list = device->realized_font_list;
2049   frame->realized_face_list = device->realized_face_list;
2050   frame->realized_fontset_list = device->realized_fontset_list;
2051
2052   if (widget)
2053     {
2054       XtResource resources[] = {
2055         { XtNfont, XtCFont, XtRString, sizeof (String),
2056           XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2057         { XtNforeground, XtCForeground, XtRString, sizeof (String),
2058           XtOffset (AppDataPtr, foreground), XtRString, "black" },
2059         { XtNbackground, XtCBackground, XtRString, sizeof (String),
2060           XtOffset (AppDataPtr, background), XtRString, "white" },
2061         { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2062           XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2063       };
2064
2065       XtGetApplicationResources (widget, &app_data,
2066                                  resources, XtNumber (resources), NULL, 0);
2067       frame->foreground = msymbol (app_data.foreground);
2068       frame->background = msymbol (app_data.background);
2069       frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2070     }
2071   else
2072     {
2073       app_data.font = DEFAULT_FONT;
2074       frame->foreground = msymbol ("black");
2075       frame->background = msymbol ("white");
2076       frame->videomode = Mnormal;
2077     }
2078
2079   {
2080     int nfonts;
2081     char **names = XListFonts (display, app_data.font, 1, &nfonts);
2082
2083     if (nfonts > 0)
2084       {
2085         if (! (frame->font = mfont_parse_name (names[0], Mx)))
2086           {
2087             /* The font name does not conform to XLFD.  Try to open the
2088                font and get XA_FONT property.  */
2089             XFontStruct *xfont = XLoadQueryFont (display, names[0]);
2090
2091             nfonts = 0;
2092             if (xfont)
2093               {
2094                 unsigned long value;
2095                 char *name;
2096
2097                 if (XGetFontProperty (xfont, XA_FONT, &value)
2098                     && (name = ((char *)
2099                                 XGetAtomName (display, (Atom) value))))
2100                   {
2101                     if ((frame->font = mfont_parse_name (name, Mx)))
2102                       nfonts = 1;
2103                   }
2104                 XFreeFont (display, xfont);
2105               }
2106           }
2107         XFreeFontNames (names);
2108       }
2109     if (! nfonts)
2110       frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
2111   }
2112
2113   face = mface_from_font (frame->font);
2114   face->property[MFACE_FONTSET] = mfontset (NULL);
2115   face->property[MFACE_FOREGROUND] = frame->foreground;
2116   face->property[MFACE_BACKGROUND] = frame->background;
2117   mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2118   mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2119   face->property[MFACE_VIDEOMODE] = frame->videomode;
2120   mface_put_prop (face, Mhook_func, 
2121                   mface_get_prop (mface__default, Mhook_func));
2122   face->property[MFACE_RATIO] = (void *) 100;
2123   mplist_push (param, Mface, face);
2124   M17N_OBJECT_UNREF (face);
2125
2126 #ifdef X_SET_ERROR_HANDLER
2127   XSetErrorHandler (x_error_handler);
2128   XSetIOErrorHandler (x_io_error_handler);
2129 #endif
2130
2131   return 0;
2132 }
2133
2134 \f
2135
2136 /* XIM (X Input Method) handler */
2137
2138 typedef struct MInputXIMMethodInfo
2139 {
2140   Display *display;
2141   XIM xim;
2142   MSymbol language;
2143   MSymbol coding;
2144 } MInputXIMMethodInfo;
2145
2146 typedef struct MInputXIMContextInfo
2147 {
2148   XIC xic;
2149   Window win;
2150   MConverter *converter;
2151 } MInputXIMContextInfo;
2152
2153 static int
2154 xim_open_im (MInputMethod *im)
2155 {
2156   MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
2157   MLocale *saved, *this;
2158   char *save_modifier_list;
2159   XIM xim;
2160   MInputXIMMethodInfo *im_info;
2161
2162   saved = mlocale_set (LC_CTYPE, NULL);
2163   this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
2164   if (! this)
2165     /* The specified locale is not supported.  */
2166     MERROR (MERROR_LOCALE, -1);
2167   if (mlocale_get_prop (this, Mcoding) == Mnil)
2168     {
2169       /* Unable to decode the output of XIM.  */
2170       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2171       MERROR (MERROR_LOCALE, -1);
2172     }
2173
2174   if (arg->modifier_list)
2175     save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
2176   else
2177     save_modifier_list = XSetLocaleModifiers ("");
2178   if (! save_modifier_list)
2179     {
2180       /* The specified locale is not supported by X.  */
2181       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2182       MERROR (MERROR_LOCALE, -1);
2183     }
2184
2185   xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
2186   if (! xim)
2187     {
2188       /* No input method is available in the current locale.  */
2189       XSetLocaleModifiers (save_modifier_list);
2190       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2191       MERROR (MERROR_WIN, -1);
2192     }
2193
2194   MSTRUCT_MALLOC (im_info, MERROR_WIN);
2195   im_info->display = arg->display;
2196   im_info->xim = xim;
2197   im_info->language = mlocale_get_prop (this, Mlanguage);
2198   im_info->coding = mlocale_get_prop (this, Mcoding);
2199   im->info = im_info;
2200
2201   XSetLocaleModifiers (save_modifier_list);
2202   mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
2203
2204   return 0;
2205 }
2206
2207 static void
2208 xim_close_im (MInputMethod *im)
2209 {
2210   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
2211
2212   XCloseIM (im_info->xim);
2213   free (im_info);
2214 }
2215
2216 static int
2217 xim_create_ic (MInputContext *ic)
2218 {
2219   MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
2220   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2221   MInputXIMContextInfo *ic_info;
2222   XIC xic;
2223
2224   if (! arg->input_style)
2225     {
2226       /* By default, use Root style.  */
2227       arg->input_style = XIMPreeditNothing | XIMStatusNothing;
2228       arg->preedit_attrs = NULL;
2229       arg->status_attrs = NULL;
2230     }
2231
2232   if (! arg->preedit_attrs && ! arg->status_attrs)
2233     xic = XCreateIC (im_info->xim,
2234                      XNInputStyle, arg->input_style,
2235                      XNClientWindow, arg->client_win,
2236                      XNFocusWindow, arg->focus_win,
2237                      NULL);
2238   else if (arg->preedit_attrs && ! arg->status_attrs)
2239     xic = XCreateIC (im_info->xim,
2240                      XNInputStyle, arg->input_style,
2241                      XNClientWindow, arg->client_win,
2242                      XNFocusWindow, arg->focus_win,
2243                      XNPreeditAttributes, arg->preedit_attrs,
2244                      NULL);
2245   else if (! arg->preedit_attrs && arg->status_attrs)
2246     xic = XCreateIC (im_info->xim,
2247                      XNInputStyle, arg->input_style,
2248                      XNClientWindow, arg->client_win,
2249                      XNFocusWindow, arg->focus_win,
2250                      XNStatusAttributes, arg->status_attrs,
2251                      NULL);
2252   else
2253     xic = XCreateIC (im_info->xim,
2254                      XNInputStyle, arg->input_style,
2255                      XNClientWindow, arg->client_win,
2256                      XNFocusWindow, arg->focus_win,
2257                      XNPreeditAttributes, arg->preedit_attrs,
2258                      XNStatusAttributes, arg->status_attrs,
2259                      NULL);
2260   if (! xic)
2261     MERROR (MERROR_WIN, -1);
2262
2263   MSTRUCT_MALLOC (ic_info, MERROR_WIN);
2264   ic_info->xic = xic;
2265   ic_info->win = arg->focus_win;
2266   ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
2267   ic->info = ic_info;
2268   return 0;
2269 }
2270
2271 static void
2272 xim_destroy_ic (MInputContext *ic)
2273 {
2274   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2275
2276   XDestroyIC (ic_info->xic);
2277   mconv_free_converter (ic_info->converter);
2278   free (ic_info);
2279   ic->info = NULL;
2280 }
2281
2282 static int
2283 xim_filter (MInputContext *ic, MSymbol key, void *event)
2284 {
2285   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2286
2287   return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
2288 }
2289
2290
2291 static int
2292 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
2293 {
2294   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
2295   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
2296   XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
2297   KeySym keysym;
2298   Status status;
2299   char *buf;
2300   int len;
2301
2302   buf = (char *) alloca (512);
2303   len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
2304   if (status == XBufferOverflow)
2305     {
2306       buf = (char *) alloca (len);
2307       len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
2308     }
2309
2310   mtext_reset (ic->produced);
2311   if (len == 0)
2312     return 1;
2313
2314   mconv_reset_converter (ic_info->converter);
2315   mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
2316   mconv_decode (ic_info->converter, ic->produced);
2317   mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
2318                   Mlanguage, (void *) im_info->language);
2319   mtext_cpy (mt, ic->produced);
2320   mtext_reset (ic->produced);  
2321   return 0;
2322 }
2323
2324 \f
2325
2326 #ifdef X_SET_ERROR_HANDLER
2327 static int
2328 x_error_handler (Display *display, XErrorEvent *error)
2329 {
2330   mdebug_hook ();
2331   return 0;
2332 }
2333
2334 static int
2335 x_io_error_handler (Display *display)
2336 {
2337   mdebug_hook ();
2338   return 0;
2339 }
2340 #endif
2341
2342 /*=*/
2343
2344 /*** @} */
2345 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2346 \f
2347 /* External API */
2348
2349 /*** @addtogroup m17nInputMethodWin */
2350 /*=*/
2351 /*** @{ */
2352
2353 /***en
2354     @brief Input method driver for XIM.
2355
2356     The driver #minput_xim_driver is for the foreign input method of
2357     name #Mxim.  It uses XIM (X Input Methods) as a background input
2358     engine.
2359
2360     As the symbol #Mxim has property #Minput_driver whose value is
2361     a pointer to this driver, the input method of language #Mnil
2362     and name #Mxim uses this driver.
2363
2364     Therefore, for such input methods, the driver dependent arguments
2365     to the functions whose name begin with minput_ must be as follows.
2366
2367     The argument $ARG of the function minput_open_im () must be a
2368     pointer to the structure #MInputXIMArgIM.  See the documentation
2369     of #MInputXIMArgIM for more details.
2370
2371     The argument $ARG of the function minput_create_ic () must be a
2372     pointer to the structure #MInputXIMArgIC. See the documentation
2373     of #MInputXIMArgIC for more details.
2374
2375     The argument $ARG of the function minput_filter () must be a
2376     pointer to the structure @c XEvent.  The argument $KEY is ignored.
2377
2378     The argument $ARG of the function minput_lookup () must be the
2379     same one as that of the function minput_filter ().  The argument
2380     $KEY is ignored.  */
2381
2382 /***ja
2383     @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2384
2385     ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
2386     ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
2387     ¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
2388
2389     ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2390     #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
2391     ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2392
2393     ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
2394     ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2395
2396     ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIM ¤Ø¤Î¥Ý
2397     ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
2398     »²¾È¡£
2399
2400     ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIC ¤Ø¤Î
2401     ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
2402     ¤ò»²¾È¡£
2403
2404     ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ@c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2405     ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2406
2407     ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter () 
2408     ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2409     ¤ë¡£  */
2410
2411 MInputDriver minput_xim_driver =
2412   { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2413     xim_filter, xim_lookup, NULL };
2414
2415 /*** @} */ 
2416
2417 /*
2418   Local Variables:
2419   coding: euc-japan
2420   End:
2421 */