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