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