(xfont_encode_char): Return MCHAR_INVALID_CODE if code
[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 (all_chars_exist)
833         return ((code >= min_byte2 && code <= max_byte2)
834                 ? code : MCHAR_INVALID_CODE);
835       pcm = f->per_char + (code - min_byte2);
836       return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
837               ? code : MCHAR_INVALID_CODE);
838     }
839   else
840     {
841       unsigned byte1 = code >> 8, byte2 = code & 0xFF;
842       XCharStruct *pcm;
843
844       if (all_chars_exist)
845         return ((byte1 >= min_byte1 && byte1 <= max_byte1
846                  && byte2 >= min_byte2 && byte2 <= max_byte2)
847                 ? code : MCHAR_INVALID_CODE);
848       pcm = f->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
849                            + (byte2 - min_byte2));
850       return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
851               ? code : MCHAR_INVALID_CODE);
852     }
853 }
854
855 static GC
856 set_region (MFrame *frame, GC gc, MDrawRegion region)
857 {
858   unsigned long valuemask = GCForeground;
859
860   XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
861            frame->device->scratch_gc);
862   XSetRegion (FRAME_DISPLAY (frame), frame->device->scratch_gc, region);
863   return frame->device->scratch_gc;
864 }
865
866 /* The X font driver function RENDER.  */
867
868 static void
869 xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
870               MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
871 {
872   MRealizedFace *rface = from->rface;
873   Display *display;
874   XChar2b *code;
875   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
876   MGlyph *g;
877   int i;
878
879   if (from == to)
880     return;
881
882   /* It is assured that the all glyphs in the current range use the
883      same realized face.  */
884   display = FRAME_DISPLAY (rface->frame);
885
886   if (region)
887     gc = set_region (rface->frame, gc, region);
888   if (! rface->rfont || from->code == MCHAR_INVALID_CODE)
889     {
890       int x0 = x;
891
892       for (; from < to; from++)
893         {
894           XDrawRectangle (display, (Window) win, gc,
895                           x0, y - gstring->ascent + 1, from->width - 1,
896                           gstring->ascent + gstring->descent - 2);
897           x0 += from->width;
898         }
899       return;
900     }
901
902   XSetFont (display, gc, ((MXFontInfo *) (rface->rfont->info))->f->fid);
903   code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
904   for (i = 0, g = from; g < to; i++, g++)
905     {
906       code[i].byte1 = g->code >> 8;
907       code[i].byte2 = g->code & 0xFF;
908     }
909
910   g = from;
911   while (g < to)
912     {
913       if (g->type == GLYPH_PAD)
914         x += g++->width;
915       else if (g->type == GLYPH_SPACE)
916         for (; g < to && g->type == GLYPH_SPACE; g++)
917           x += g->width;
918       else if (! g->rface->rfont)
919         {
920           if ((g->c >= 0x200B && g->c <= 0x200F)
921               || (g->c >= 0x202A && g->c <= 0x202E))
922             x += g++->width;
923           else
924             {
925               /* As a font is not found for this character, draw an
926                  empty box.  */
927               int box_width = g->width;
928               int box_height = gstring->ascent + gstring->descent;
929
930               if (box_width > 4)
931                 box_width -= 2;
932               if (box_height > 4)
933                 box_height -= 2;
934               XDrawRectangle (display, (Window) win, gc,
935                               x, y - gstring->ascent, box_width, box_height);
936               x += g++->width;
937             }
938         }
939       else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
940         {
941           XDrawString16 (display, (Window) win, gc,
942                          x + g->xoff, y + g->yoff, code + (g - from), 1);
943           x += g->width;
944           g++;
945         }
946       else
947         {
948           int orig_x = x;
949           int code_idx = g - from;
950
951           for (i = 0;
952                g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
953                i++, g++)
954               x += g->width;
955           XDrawString16 (display, (Window) win, gc, orig_x, y,
956                          code + code_idx, i);
957         }
958     }
959 }
960
961 \f
962
963 /* XIM (X Input Method) handler */
964
965 typedef struct MInputXIMMethodInfo
966 {
967   Display *display;
968   XIM xim;
969   MSymbol language;
970   MSymbol coding;
971 } MInputXIMMethodInfo;
972
973 typedef struct MInputXIMContextInfo
974 {
975   XIC xic;
976   Window win;
977   MConverter *converter;
978 } MInputXIMContextInfo;
979
980 static int
981 xim_open_im (MInputMethod *im)
982 {
983   MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
984   MLocale *saved, *this;
985   char *save_modifier_list;
986   XIM xim;
987   MInputXIMMethodInfo *im_info;
988
989   saved = mlocale_set (LC_CTYPE, NULL);
990   this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
991   if (! this)
992     /* The specified locale is not supported.  */
993     MERROR (MERROR_LOCALE, -1);
994   if (mlocale_get_prop (this, Mcoding) == Mnil)
995     {
996       /* Unable to decode the output of XIM.  */
997       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
998       MERROR (MERROR_LOCALE, -1);
999     }
1000
1001   if (arg->modifier_list)
1002     save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
1003   else
1004     save_modifier_list = XSetLocaleModifiers ("");
1005   if (! save_modifier_list)
1006     {
1007       /* The specified locale is not supported by X.  */
1008       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
1009       MERROR (MERROR_LOCALE, -1);
1010     }
1011
1012   xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
1013   if (! xim)
1014     {
1015       /* No input method is available in the current locale.  */
1016       XSetLocaleModifiers (save_modifier_list);
1017       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
1018       MERROR (MERROR_WIN, -1);
1019     }
1020
1021   MSTRUCT_MALLOC (im_info, MERROR_WIN);
1022   im_info->display = arg->display;
1023   im_info->xim = xim;
1024   im_info->language = mlocale_get_prop (this, Mlanguage);
1025   im_info->coding = mlocale_get_prop (this, Mcoding);
1026   im->info = im_info;
1027
1028   XSetLocaleModifiers (save_modifier_list);
1029   mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
1030
1031   return 0;
1032 }
1033
1034 static void
1035 xim_close_im (MInputMethod *im)
1036 {
1037   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
1038
1039   XCloseIM (im_info->xim);
1040   free (im_info);
1041 }
1042
1043 static int
1044 xim_create_ic (MInputContext *ic)
1045 {
1046   MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
1047   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
1048   MInputXIMContextInfo *ic_info;
1049   XIC xic;
1050
1051   if (! arg->input_style)
1052     {
1053       /* By default, use Root style.  */
1054       arg->input_style = XIMPreeditNothing | XIMStatusNothing;
1055       arg->preedit_attrs = NULL;
1056       arg->status_attrs = NULL;
1057     }
1058
1059   if (! arg->preedit_attrs && ! arg->status_attrs)
1060     xic = XCreateIC (im_info->xim,
1061                      XNInputStyle, arg->input_style,
1062                      XNClientWindow, arg->client_win,
1063                      XNFocusWindow, arg->focus_win,
1064                      NULL);
1065   else if (arg->preedit_attrs && ! arg->status_attrs)
1066     xic = XCreateIC (im_info->xim,
1067                      XNInputStyle, arg->input_style,
1068                      XNClientWindow, arg->client_win,
1069                      XNFocusWindow, arg->focus_win,
1070                      XNPreeditAttributes, arg->preedit_attrs,
1071                      NULL);
1072   else if (! arg->preedit_attrs && arg->status_attrs)
1073     xic = XCreateIC (im_info->xim,
1074                      XNInputStyle, arg->input_style,
1075                      XNClientWindow, arg->client_win,
1076                      XNFocusWindow, arg->focus_win,
1077                      XNStatusAttributes, arg->status_attrs,
1078                      NULL);
1079   else
1080     xic = XCreateIC (im_info->xim,
1081                      XNInputStyle, arg->input_style,
1082                      XNClientWindow, arg->client_win,
1083                      XNFocusWindow, arg->focus_win,
1084                      XNPreeditAttributes, arg->preedit_attrs,
1085                      XNStatusAttributes, arg->status_attrs,
1086                      NULL);
1087   if (! xic)
1088     MERROR (MERROR_WIN, -1);
1089
1090   MSTRUCT_MALLOC (ic_info, MERROR_WIN);
1091   ic_info->xic = xic;
1092   ic_info->win = arg->focus_win;
1093   ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
1094   ic->info = ic_info;
1095   return 0;
1096 }
1097
1098 static void
1099 xim_destroy_ic (MInputContext *ic)
1100 {
1101   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
1102
1103   XDestroyIC (ic_info->xic);
1104   mconv_free_converter (ic_info->converter);
1105   free (ic_info);
1106   ic->info = NULL;
1107 }
1108
1109 static int
1110 xim_filter (MInputContext *ic, MSymbol key, void *event)
1111 {
1112   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
1113
1114   return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
1115 }
1116
1117
1118 static int
1119 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
1120 {
1121   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
1122   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
1123   XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
1124   KeySym keysym;
1125   Status status;
1126   char *buf;
1127   int len;
1128
1129   buf = (char *) alloca (512);
1130   len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
1131   if (status == XBufferOverflow)
1132     {
1133       buf = (char *) alloca (len);
1134       len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
1135     }
1136
1137   mtext_reset (ic->produced);
1138   if (len == 0)
1139     return 1;
1140
1141   mconv_reset_converter (ic_info->converter);
1142   mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
1143   mconv_decode (ic_info->converter, ic->produced);
1144   mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
1145                   Mlanguage, (void *) im_info->language);
1146   mtext_cpy (mt, ic->produced);
1147   mtext_reset (ic->produced);  
1148   return 0;
1149 }
1150
1151 \f
1152
1153 #ifdef X_SET_ERROR_HANDLER
1154 static int
1155 x_error_handler (Display *display, XErrorEvent *error)
1156 {
1157   mdebug_hook ();
1158   return 0;
1159 }
1160
1161 static int
1162 x_io_error_handler (Display *display)
1163 {
1164   mdebug_hook ();
1165   return 0;
1166 }
1167 #endif
1168
1169 \f
1170
1171 int
1172 mwin__init ()
1173 {
1174   Mdisplay = msymbol ("display");
1175   Mscreen = msymbol ("screen");
1176   Mdrawable = msymbol ("drawable");
1177   Mdepth = msymbol ("depth");
1178   Mwidget = msymbol ("widget");
1179   M_iso8859_1 = msymbol ("iso8859-1");
1180   M_iso10646_1 = msymbol ("iso10646-1");
1181
1182   display_info_list = mplist ();
1183   device_list = mplist ();
1184
1185   mfont__driver_list[MFONT_TYPE_WIN] = &xfont_driver;
1186
1187   Mxim = msymbol ("xim");
1188   msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1189
1190   return 0;
1191 }
1192
1193 void
1194 mwin__fini ()
1195 {
1196   M17N_OBJECT_UNREF (display_info_list);
1197   M17N_OBJECT_UNREF (device_list);
1198 }
1199
1200 int
1201 mwin__parse_font_name (char *name, MFont *font)
1202 {
1203   char *field[XLFD_FIELD_MAX];
1204   unsigned short size, resy;
1205   MSymbol attrs[MFONT_PROPERTY_MAX];
1206   char *copy = (char *) alloca (512);
1207   int i, len;
1208   char *p, *last = NULL;
1209
1210   len = strlen (name) + 1;
1211   for (i = 0, p = name; *p; p++)
1212     {
1213       if (*p == '-')
1214         i++;
1215       else if (p > name && *p == '*' && p[-1] == '-')
1216         last = p + 1;
1217     }
1218   if (i == 14)
1219     memcpy (copy, name, len);
1220   else if (last)
1221     {
1222       memcpy (copy, name, last - name);
1223       for (; i < 14; i++)
1224         strcat (copy, "-*");
1225       strcat (copy, last);
1226     }
1227
1228   if (split_font_name (copy, field, &size, &resy) < 0)
1229     return -1;
1230   attrs[MFONT_FOUNDRY]
1231     = *(field[XLFD_FOUNDRY]) != '*' ? msymbol (field[XLFD_FOUNDRY]) : Mnil;
1232   attrs[MFONT_FAMILY]
1233     = *(field[XLFD_FAMILY]) != '*' ? msymbol (field[XLFD_FAMILY]) : Mnil;
1234   attrs[MFONT_WEIGHT]
1235     = *(field[XLFD_WEIGHT]) != '*' ? msymbol (field[XLFD_WEIGHT]) : Mnil;
1236   attrs[MFONT_STYLE]
1237     = *(field[XLFD_SLANT]) != '*' ? msymbol (field[XLFD_SLANT]) : Mnil;
1238   attrs[MFONT_STRETCH]
1239     = *(field[XLFD_SWIDTH]) != '*' ? msymbol (field[XLFD_SWIDTH]) : Mnil;
1240   attrs[MFONT_ADSTYLE]
1241     = *(field[XLFD_ADSTYLE]) != '*' ? msymbol (field[XLFD_ADSTYLE]) : Mnil;
1242   attrs[MFONT_REGISTRY]
1243     = *(field[XLFD_REGISTRY]) != '*' ? msymbol (field[XLFD_REGISTRY]) : Mnil;
1244   mfont__set_spec (font, attrs, size, resy);
1245   return 0;
1246 }
1247
1248
1249 char *
1250 mwin__build_font_name (MFont *font)
1251 {
1252   char name[1024];
1253
1254   if (build_font_name (font, name, 1024) < 0)
1255     return NULL;
1256   return strdup (name);
1257 }
1258
1259 /** Return an MWDevice object corresponding to a display specified in
1260     PLIST.
1261
1262     It searches device_list for a device matching the display.  If
1263     found, return the found object.  Otherwise, return a newly created
1264     object.  */
1265
1266 MWDevice *
1267 mwin__open_device (MFrame *frame, MPlist *param)
1268 {
1269   Display *display = NULL;
1270   Screen *screen = NULL;
1271   int screen_num;
1272   Drawable drawable = 0;
1273   Widget widget = NULL;
1274   Colormap cmap = 0;
1275   int auto_display = 0;
1276   MDisplayInfo *disp_info = NULL;
1277   MWDevice *device = NULL;
1278   MSymbol key;
1279   XWindowAttributes attr;
1280   unsigned depth = 0;
1281   MPlist *plist;
1282   AppData app_data;
1283
1284   if (param)
1285     for (plist = param; (key = mplist_key (plist)) != Mnil;
1286          plist = mplist_next (plist))
1287       {
1288         if (key == Mdisplay)
1289           display = (Display *) mplist_value (plist);
1290         else if (key == Mscreen)
1291           screen = mplist_value (plist);
1292         else if (key == Mdrawable)
1293           drawable = (Drawable) mplist_value (plist);
1294         else if (key == Mdepth)
1295           depth = (unsigned) mplist_value (plist);
1296         else if (key == Mwidget)
1297           widget = (Widget) mplist_value (plist);
1298         else if (key == Mcolormap)
1299           cmap = (Colormap) mplist_value (plist);
1300       }
1301
1302   if (widget)
1303     {
1304       display = XtDisplay (widget);
1305       screen_num = XScreenNumberOfScreen (XtScreen (widget));
1306       depth = DefaultDepth (display, screen_num);
1307     }
1308   else if (drawable)
1309     {
1310       Window root_window;
1311       int x, y;
1312       unsigned width, height, border_width;
1313
1314       if (! display)
1315         MERROR (MERROR_WIN, NULL);
1316       XGetGeometry (display, drawable, &root_window,
1317                     &x, &y, &width, &height, &border_width, &depth);
1318       XGetWindowAttributes (display, root_window, &attr);
1319       screen_num = XScreenNumberOfScreen (attr.screen);
1320     }
1321   else
1322     {
1323       if (screen)
1324         display = DisplayOfScreen (screen);
1325       else
1326         {
1327           if (! display)
1328             {
1329               display = XOpenDisplay (NULL);
1330               if (! display)
1331                 MERROR (MERROR_WIN, NULL);
1332               auto_display = 1;
1333             }
1334           screen = DefaultScreenOfDisplay (display);
1335         }
1336       screen_num = XScreenNumberOfScreen (screen);
1337       if (! depth)
1338         depth = DefaultDepth (display, screen_num);
1339     }
1340
1341   if (! cmap)
1342     cmap = DefaultColormap (display, screen_num);
1343
1344   for (plist = display_info_list; mplist_key (plist) != Mnil;
1345        plist = mplist_next (plist))
1346     {
1347       disp_info = (MDisplayInfo *) mplist_value (plist);
1348       if (disp_info->display == display)
1349         break;
1350     }
1351
1352   if (mplist_key (plist) != Mnil)
1353     M17N_OBJECT_REF (disp_info);
1354   else
1355     {
1356       M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
1357       disp_info->display = display;
1358       disp_info->auto_display = auto_display;
1359       disp_info->font_registry_list = mplist ();
1360       disp_info->iso8859_1_family_list = mplist ();
1361       disp_info->iso10646_1_family_list = mplist ();
1362       disp_info->realized_font_list = mplist ();
1363       find_modifier_bits (disp_info);
1364       mplist_add (display_info_list, Mt, disp_info);
1365     }  
1366
1367   for (plist = device_list; mplist_key (plist) != Mnil;
1368        plist = mplist_next (plist))
1369     {
1370       device = (MWDevice *) mplist_value (plist);
1371       if (device->display_info == disp_info
1372           && device->depth == depth
1373           && device->cmap == cmap)
1374         break;
1375     }
1376
1377   if (mplist_key (plist) != Mnil)
1378     M17N_OBJECT_REF (device);
1379   else
1380     {
1381       unsigned long valuemask = GCForeground;
1382       XGCValues values;
1383
1384       M17N_OBJECT (device, free_device, MERROR_WIN);
1385       device->display_info = disp_info;
1386       device->screen_num = screen_num;
1387       /* A drawable on which to create GCs.  */
1388       device->drawable = XCreatePixmap (display,
1389                                         RootWindow (display, screen_num),
1390                                         1, 1, depth);
1391       device->depth = depth;
1392       device->cmap = cmap;
1393       device->realized_face_list = mplist ();
1394       device->realized_fontset_list = mplist ();
1395       device->gc_list = mplist ();
1396       values.foreground = BlackPixel (display, screen_num);
1397       device->scratch_gc = XCreateGC (display, device->drawable,
1398                                       valuemask, &values);
1399     }
1400
1401   frame->realized_font_list = disp_info->realized_font_list;
1402   frame->realized_face_list = device->realized_face_list;
1403   frame->realized_fontset_list = device->realized_fontset_list;
1404
1405   if (widget)
1406     {
1407       XtResource resources[] = {
1408         { XtNfont, XtCFont, XtRString, sizeof (String),
1409           XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
1410         { XtNforeground, XtCForeground, XtRString, sizeof (String),
1411           XtOffset (AppDataPtr, foreground), XtRString, "black" },
1412         { XtNbackground, XtCBackground, XtRString, sizeof (String),
1413           XtOffset (AppDataPtr, background), XtRString, "white" },
1414         { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
1415           XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
1416       };
1417
1418       XtGetApplicationResources (widget, &app_data,
1419                                  resources, XtNumber (resources), NULL, 0);
1420       frame->foreground = msymbol (app_data.foreground);
1421       frame->background = msymbol (app_data.background);
1422       frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
1423     }
1424   else
1425     {
1426       app_data.font = DEFAULT_FONT;
1427       frame->foreground = msymbol ("black");
1428       frame->background = msymbol ("white");
1429       frame->videomode = Mnormal;
1430     }
1431
1432   frame->font = mfont ();
1433   {
1434     int nfonts;
1435     char **names = XListFonts (display, app_data.font, 1, &nfonts);
1436
1437     if (nfonts > 0)
1438       {
1439         if (mwin__parse_font_name (names[0], frame->font) < 0)
1440           {
1441             /* The font name does not conform to XLFD.  Try to open the
1442                font and get XA_FONT property.  */
1443             XFontStruct *xfont = XLoadQueryFont (display, names[0]);
1444
1445             nfonts = 0;
1446             if (xfont)
1447               {
1448                 unsigned long value;
1449                 char *name;
1450
1451                 if (XGetFontProperty (xfont, XA_FONT, &value)
1452                     && (name = ((char *)
1453                                 XGetAtomName (display, (Atom) value))))
1454                   {
1455                     if (mwin__parse_font_name (name, frame->font) >= 0)
1456                       nfonts = 1;
1457                   }
1458                 XFreeFont (display, xfont);
1459               }
1460           }
1461         XFreeFontNames (names);
1462       }
1463     if (! nfonts)
1464       mwin__parse_font_name (FALLBACK_FONT, frame->font);
1465   }
1466
1467 #ifdef X_SET_ERROR_HANDLER
1468   XSetErrorHandler (x_error_handler);
1469   XSetIOErrorHandler (x_io_error_handler);
1470 #endif
1471
1472   return device;
1473 }
1474
1475 void
1476 mwin__close_device (MFrame *frame)
1477 {
1478   M17N_OBJECT_UNREF (frame->device);
1479 }
1480
1481 void *
1482 mwin__device_get_prop (MWDevice *device, MSymbol key)
1483 {
1484   if (key == Mdisplay)
1485     return (void *) device->display_info->display;
1486   if (key == Mscreen)
1487     return (void *) ScreenOfDisplay(device->display_info->display,
1488                                     device->screen_num);
1489   if (key == Mcolormap)
1490     return (void *) device->cmap;
1491   if (key == Mdepth)
1492     return (void *) device->depth;
1493   return NULL;
1494 }
1495
1496 void
1497 mwin__realize_face (MRealizedFace *rface)
1498 {
1499   MFrame *frame;
1500   MSymbol foreground, background, videomode;
1501   MFaceHLineProp *hline;
1502   MFaceBoxProp *box;
1503   MFaceHookFunc func;
1504   GCInfo *info;
1505
1506   if (rface != rface->ascii_rface)
1507     {
1508       rface->info = rface->ascii_rface->info;
1509       return;
1510     }
1511
1512   frame = rface->frame;
1513   MSTRUCT_CALLOC (info, MERROR_WIN);
1514
1515   foreground = rface->face.property[MFACE_FOREGROUND];
1516   background = rface->face.property[MFACE_BACKGROUND];
1517   videomode = rface->face.property[MFACE_VIDEOMODE];
1518   if (! videomode)
1519     videomode = frame->videomode;
1520   if (videomode != Mreverse)
1521     {
1522       info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
1523       info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
1524     }
1525   else
1526     {
1527       info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
1528       info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
1529     }
1530
1531   hline = rface->hline;
1532   if (hline)
1533     {
1534       if (hline->color)
1535         info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
1536       else
1537         info->gc[GC_HLINE] = info->gc[GC_NORMAL];
1538     }
1539
1540   box = rface->box;
1541   if (box)
1542     {
1543       if (box->color_top)
1544         info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
1545       else
1546         info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
1547
1548       if (box->color_left && box->color_left != box->color_top)
1549         info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
1550       else
1551         info->gc[GC_BOX_LEFT] = info->gc[GC_NORMAL];
1552
1553       if (box->color_bottom && box->color_bottom != box->color_top)
1554         info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
1555       else
1556         info->gc[GC_BOX_BOTTOM] = info->gc[GC_NORMAL];
1557
1558       if (box->color_right && box->color_right != box->color_top)
1559         info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
1560       else
1561         info->gc[GC_BOX_RIGHT] = info->gc[GC_NORMAL];
1562     }
1563
1564   rface->info = info;
1565
1566   func = (MFaceHookFunc) rface->face.property[MFACE_HOOK_FUNC];
1567   if (func)
1568     (func) (&(rface->face), rface->info, rface->face.property[MFACE_HOOK_ARG]);
1569 }
1570
1571
1572 void
1573 mwin__free_realized_face (MRealizedFace *rface)
1574 {
1575   if (rface == rface->ascii_rface)
1576     free (rface->info);
1577 }
1578
1579
1580 void
1581 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1582                   int reverse,
1583                   int x, int y, int width, int height, MDrawRegion region)
1584 {
1585   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
1586
1587   if (region)
1588     gc = set_region (frame, gc, region);
1589
1590   XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
1591                   x, y, width, height);
1592 }
1593
1594
1595 void
1596 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1597                  MRealizedFace *rface, int reverse,
1598                  int x, int y, int width, MDrawRegion region)
1599 {
1600   enum MFaceHLineType type = rface->hline->type;
1601   GCInfo *info = rface->info;
1602   GC gc = gc = info->gc[GC_HLINE];
1603   int i;
1604
1605   y = (type == MFACE_HLINE_BOTTOM
1606        ? y + gstring->text_descent - rface->hline->width
1607        : type == MFACE_HLINE_UNDER
1608        ? y + 1
1609        : type == MFACE_HLINE_STRIKE_THROUGH
1610        ? y - ((gstring->ascent + gstring->descent) / 2)
1611        : y - gstring->text_ascent);
1612   if (region)
1613     gc = set_region (frame, gc, region);
1614
1615   for (i = 0; i < rface->hline->width; i++)
1616     XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
1617                x, y + i, x + width - 1, y + i);
1618 }
1619
1620
1621 void
1622 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
1623                 MGlyph *g, int x, int y, int width, MDrawRegion region)
1624 {
1625   Display *display = FRAME_DISPLAY (frame);
1626   MRealizedFace *rface = g->rface;
1627   MFaceBoxProp *box = rface->box;
1628   GCInfo *info = rface->info;
1629   GC gc_top, gc_left, gc_right, gc_btm;
1630   int y0, y1;
1631   int i;
1632
1633   y0 = y - (gstring->text_ascent
1634             + rface->box->inner_vmargin + rface->box->width);
1635   y1 = y + (gstring->text_descent
1636             + rface->box->inner_vmargin + rface->box->width - 1);
1637
1638   gc_top = info->gc[GC_BOX_TOP];
1639   if (region)
1640     gc_top = set_region (frame, gc_top, region);
1641   if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
1642     gc_btm = gc_top;
1643   else
1644     gc_btm = info->gc[GC_BOX_BOTTOM];
1645
1646   if (g->type == GLYPH_BOX)
1647     {
1648       int x0, x1;
1649
1650       if (g->left_padding)
1651         x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
1652       else
1653         x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
1654
1655       /* Draw the top side.  */
1656       for (i = 0; i < box->width; i++)
1657         XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
1658
1659       /* Draw the bottom side.  */
1660       if (region && gc_btm != gc_top)
1661         gc_btm = set_region (frame, gc_btm, region);
1662       for (i = 0; i < box->width; i++)
1663         XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
1664
1665       if (g->left_padding > 0)
1666         {
1667           /* Draw the left side.  */
1668           if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
1669             gc_left = gc_top;
1670           else
1671             {
1672               gc_left = info->gc[GC_BOX_LEFT];
1673               if (region)
1674                 gc_left = set_region (frame, gc_left, region);
1675             }
1676           for (i = 0; i < rface->box->width; i++)
1677             XDrawLine (display, (Window) win, gc_left,
1678                        x0 + i, y0 + i, x0 + i, y1 - i);
1679         }
1680       else
1681         {
1682           /* Draw the right side.  */
1683           if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
1684             gc_right = gc_top;
1685           else
1686             {
1687               gc_right = info->gc[GC_BOX_RIGHT];
1688               if (region)
1689                 gc_right = set_region (frame, gc_right, region);
1690             }
1691           for (i = 0; i < rface->box->width; i++)
1692             XDrawLine (display, (Window) win, gc_right,
1693                        x1 - i, y0 + i, x1 - i, y1 - i);
1694         }
1695     }
1696   else
1697     {
1698       /* Draw the top side.  */
1699       for (i = 0; i < box->width; i++)
1700         XDrawLine (display, (Window) win, gc_top,
1701                    x, y0 + i, x + width - 1, y0 + i);
1702
1703       /* Draw the bottom side.  */
1704       if (region && gc_btm != gc_top)
1705         gc_btm = set_region (frame, gc_btm, region);
1706       for (i = 0; i < box->width; i++)
1707         XDrawLine (display, (Window) win, gc_btm,
1708                    x, y1 - i, x + width - 1, y1 - i);
1709     }
1710 }
1711
1712
1713 #if 0
1714 void
1715 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1716                    int reverse, int x, int y,
1717                    int width, int height, int row_bytes, unsigned char *bmp,
1718                    MDrawRegion region)
1719 {
1720   Display *display = FRAME_DISPLAY (frame);
1721   int i, j;
1722   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
1723
1724   if (region)
1725     gc = set_region (frame, gc, region);
1726
1727   for (i = 0; i < height; i++, bmp += row_bytes)
1728     for (j = 0; j < width; j++)
1729       if (bmp[j / 8] & (1 << (7 - (j % 8))))
1730         XDrawPoint (display, (Window) win, gc, x + j, y + i);
1731 }
1732 #endif
1733
1734 void
1735 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
1736                    int intensity, MDrawPoint *points, int num,
1737                    MDrawRegion region)
1738 {
1739   GCInfo *info = rface->info;
1740   GC gc;
1741
1742   if (! (gc = info->gc[intensity]))
1743     gc = info->gc[intensity] = get_gc_for_anti_alias (frame->device, info,
1744                                                       intensity);
1745   if (region)
1746     gc = set_region (frame, gc, region);
1747
1748   XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
1749                (XPoint *) points, num, CoordModeOrigin);
1750 }
1751
1752
1753 MDrawRegion
1754 mwin__region_from_rect (MDrawMetric *rect)
1755 {
1756   MDrawRegion region1 = XCreateRegion ();
1757   MDrawRegion region2 = XCreateRegion ();
1758   XRectangle xrect;
1759
1760   xrect.x = rect->x;
1761   xrect.y = rect->y;
1762   xrect.width = rect->width;
1763   xrect.height = rect->height;
1764   XUnionRectWithRegion (&xrect, region1, region2);
1765   XDestroyRegion (region1);
1766   return region2;
1767 }
1768
1769 void
1770 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
1771 {
1772   MDrawRegion region1 = XCreateRegion ();
1773   XRectangle xrect;
1774
1775   xrect.x = rect->x;
1776   xrect.y = rect->y;
1777   xrect.width = rect->width;
1778   xrect.height = rect->height;
1779
1780   XUnionRegion (region, region, region1);
1781   XUnionRectWithRegion (&xrect, region1, region);
1782   XDestroyRegion (region1);
1783 }
1784
1785 void
1786 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
1787 {
1788   MDrawRegion region = XCreateRegion ();
1789
1790   XUnionRegion (region1, region1, region);
1791   XIntersectRegion (region, region2, region1);
1792   XDestroyRegion (region);
1793 }
1794
1795 void
1796 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
1797 {
1798   MDrawRegion region1 = XCreateRegion ();
1799   XRectangle xrect;
1800
1801   xrect.x = rect->x;
1802   xrect.y = rect->y;
1803   xrect.width = rect->width;
1804   xrect.height = rect->height;
1805   XUnionRectWithRegion (&xrect, region1, region);
1806   XDestroyRegion (region1);
1807 }
1808
1809 void
1810 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
1811 {
1812   XRectangle xrect;
1813
1814   XClipBox (region, &xrect);
1815   rect->x = xrect.x;
1816   rect->y = xrect.y;
1817   rect->width = xrect.width;
1818   rect->height = xrect.height;
1819 }
1820
1821 void
1822 mwin__free_region (MDrawRegion region)
1823 {
1824   XDestroyRegion (region);
1825 }
1826
1827 void
1828 mwin__dump_region (MDrawRegion region)
1829 {
1830   XRectangle rect;
1831   XClipBox (region, &rect);
1832   fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
1833 }
1834
1835 void
1836 mwin__verify_region (MFrame *frame, MDrawRegion region)
1837 {
1838   set_region (frame, ((GCInfo *) frame->rface->info)->gc[GC_NORMAL], region);
1839 }
1840
1841 MDrawWindow
1842 mwin__create_window (MFrame *frame, MDrawWindow parent)
1843 {
1844   Display *display = FRAME_DISPLAY (frame);
1845   Window win;
1846   XWMHints wm_hints = { InputHint, False };
1847   XClassHint class_hints = { "M17N-IM", "m17n-im" };
1848   XSetWindowAttributes set_attrs;
1849   unsigned long mask;
1850   XGCValues values;
1851   GCInfo *info = frame->rface->info;
1852
1853   if (! parent)
1854     parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
1855   mask = GCForeground;
1856   XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
1857   set_attrs.background_pixel = values.foreground;
1858   set_attrs.backing_store = Always;
1859   set_attrs.override_redirect = True;
1860   set_attrs.save_under = True;
1861   mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
1862   win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
1863                        CopyFromParent, InputOutput, CopyFromParent,
1864                        mask, &set_attrs);
1865   XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
1866                     NULL, &wm_hints, &class_hints);
1867   XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
1868   return (MDrawWindow) win;
1869 }
1870
1871 void
1872 mwin__destroy_window (MFrame *frame, MDrawWindow win)
1873 {
1874   XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
1875 }
1876
1877 #if 0
1878 MDrawWindow
1879 mwin__event_window (void *event)
1880 {
1881   return ((MDrawWindow) ((XEvent *) event)->xany.window);
1882 }
1883
1884 void
1885 mwin__print_event (void *arg, char *win_name)
1886 {
1887   char *event_name;
1888   XEvent *event = (XEvent *) arg;
1889
1890   switch (event->xany.type)
1891     {
1892     case 2: event_name = "KeyPress"; break;
1893     case 3: event_name = "KeyRelease"; break;
1894     case 4: event_name = "ButtonPress"; break;
1895     case 5: event_name = "ButtonRelease"; break;
1896     case 6: event_name = "MotionNotify"; break;
1897     case 7: event_name = "EnterNotify"; break;
1898     case 8: event_name = "LeaveNotify"; break;
1899     case 9: event_name = "FocusIn"; break;
1900     case 10: event_name = "FocusOut"; break;
1901     case 11: event_name = "KeymapNotify"; break;
1902     case 12: event_name = "Expose"; break;
1903     case 13: event_name = "GraphicsExpose"; break;
1904     case 14: event_name = "NoExpose"; break;
1905     case 15: event_name = "VisibilityNotify"; break;
1906     case 16: event_name = "CreateNotify"; break;
1907     case 17: event_name = "DestroyNotify"; break;
1908     case 18: event_name = "UnmapNotify"; break;
1909     case 19: event_name = "MapNotify"; break;
1910     case 20: event_name = "MapRequest"; break;
1911     case 21: event_name = "ReparentNotify"; break;
1912     case 22: event_name = "ConfigureNotify"; break;
1913     case 23: event_name = "ConfigureRequest"; break;
1914     case 24: event_name = "GravityNotify"; break;
1915     case 25: event_name = "ResizeRequest"; break;
1916     case 26: event_name = "CirculateNotify"; break;
1917     case 27: event_name = "CirculateRequest"; break;
1918     case 28: event_name = "PropertyNotify"; break;
1919     case 29: event_name = "SelectionClear"; break;
1920     case 30: event_name = "SelectionRequest"; break;
1921     case 31: event_name = "SelectionNotify"; break;
1922     case 32: event_name = "ColormapNotify"; break;
1923     case 33: event_name = "ClientMessage"; break;
1924     case 34: event_name = "MappingNotify"; break;
1925     default: event_name = "unknown";
1926     }
1927
1928   fprintf (stderr, "%s: %s\n", win_name, event_name);
1929 }
1930 #endif
1931
1932 void
1933 mwin__map_window (MFrame *frame, MDrawWindow win)
1934 {
1935   XMapRaised (FRAME_DISPLAY (frame), (Window) win);
1936 }
1937
1938 void
1939 mwin__unmap_window (MFrame *frame, MDrawWindow win)
1940 {
1941   XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
1942 }
1943
1944 void
1945 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
1946                        MDrawMetric *geometry)
1947 {
1948   Display *display = FRAME_DISPLAY (frame);
1949   XWindowAttributes attr;
1950   Window parent = (Window) parent_win, root;
1951
1952   XGetWindowAttributes (display, (Window) win, &attr);
1953   geometry->x = attr.x + attr.border_width;
1954   geometry->y = attr.y + attr.border_width;
1955   geometry->width = attr.width;
1956   geometry->height = attr.height; 
1957
1958   if (! parent)
1959     parent = RootWindow (display, FRAME_SCREEN (frame));
1960   while (1)
1961     {
1962       Window this_parent, *children;
1963       unsigned n;
1964
1965       XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
1966       if (children)
1967         XFree (children);
1968       if (this_parent == parent || this_parent == root)
1969         break;
1970       win = (MDrawWindow) this_parent;
1971       XGetWindowAttributes (display, (Window) win, &attr);
1972       geometry->x += attr.x + attr.border_width;
1973       geometry->y += attr.y + attr.border_width;
1974     }
1975 }
1976
1977 void
1978 mwin__adjust_window (MFrame *frame, MDrawWindow win,
1979                      MDrawMetric *current, MDrawMetric *new)
1980 {
1981   Display *display = FRAME_DISPLAY (frame);
1982   unsigned int mask = 0;
1983   XWindowChanges values;
1984
1985   if (current->width != new->width)
1986     {
1987       mask |= CWWidth;
1988       if (new->width <= 0)
1989         new->width = 1;
1990       values.width = current->width = new->width;
1991     }
1992   if (current->height != new->height)
1993     {
1994       mask |= CWHeight;
1995       if (new->height <= 0)
1996         new->height = 1;
1997       values.height = current->height = new->height;
1998     }
1999   if (current->x != new->x)
2000     {
2001       mask |= CWX;
2002       values.x = current->x = new->x;
2003     }
2004   if (current->y != new->y)
2005     {
2006       mask |= CWY;
2007       current->y = new->y;
2008       values.y = current->y = new->y;
2009     }
2010   if (mask)
2011     XConfigureWindow (display, (Window) win, mask, &values);
2012   XClearWindow (display, (Window) win);
2013 }
2014
2015 MSymbol
2016 mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
2017 {
2018   XEvent *event = (XEvent *) arg;
2019   MDisplayInfo *disp_info = frame->device->display_info;
2020   int len;
2021   char buf[512];
2022   KeySym keysym;
2023   MSymbol key;
2024
2025   *modifiers = 0;
2026   if (event->xany.type != KeyPress
2027       /* && event->xany.type != KeyRelease */
2028       )
2029     return Mnil;
2030   len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
2031   if (len > 1)
2032     return Mnil;
2033   if (len == 1)
2034     {
2035       int c = keysym;
2036
2037       if (c < XK_space || c > XK_asciitilde)
2038         c = buf[0];
2039       if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
2040         *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
2041       if (((XKeyEvent *) event)->state & ControlMask)
2042         {
2043           if (c >= 'a' && c <= 'z')
2044             c += 'A' - 'a';
2045           if (c >= ' ' && c < 127)
2046             *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
2047         }
2048       key = minput__char_to_key (c);
2049     }
2050   else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
2051     return Mnil;
2052   else
2053     {
2054       char *str = XKeysymToString (keysym);
2055
2056       if (! str)
2057         return Mnil;
2058       key = msymbol (str);
2059       if (((XKeyEvent *) event)->state & ShiftMask)
2060         *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
2061       if (((XKeyEvent *) event)->state & ControlMask)
2062         *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
2063     }
2064   if (((XKeyEvent *) event)->state & disp_info->meta_mask)
2065     *modifiers |= MINPUT_KEY_META_MODIFIER;
2066   if (((XKeyEvent *) event)->state & disp_info->alt_mask)
2067     *modifiers |= MINPUT_KEY_ALT_MODIFIER;
2068   if (((XKeyEvent *) event)->state & disp_info->super_mask)
2069     *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
2070   if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
2071     *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
2072
2073   return key;
2074 }
2075
2076
2077 MText *
2078 mwin__get_selection_text (MFrame *frame)
2079 {
2080   return NULL;
2081 }
2082
2083
2084 void
2085 mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
2086 {
2087   unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
2088   XGCValues values;
2089   Display *display = FRAME_DISPLAY (frame);
2090   GCInfo *info = rface->info;
2091   int i;
2092
2093   for (i = 0; i <= GC_INVERSE; i++)
2094     {
2095       XGetGCValues (display, info->gc[i], valuemask, &values);
2096       fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
2097                values.foreground, values.background);
2098       fprintf (stderr, "\n");
2099     }
2100 }
2101
2102 /*** @} */
2103 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2104 \f
2105 /* External API */
2106
2107 /*=*/
2108 /*** @addtogroup m17nFrame */
2109 /*** @{ */
2110 /*=*/
2111
2112 /***en
2113     @name Variables: Keys of frame parameter (X specific).
2114
2115     These are the symbols to use as parameter keys for the function
2116     mframe () (which see).  They are also keys of a frame property
2117     (except for #Mwidget).  */
2118 /*=*/
2119 /*** @{ */ 
2120 /* Keywords for mwin__open_device ().  */
2121 MSymbol Mdisplay, Mscreen, Mdrawable, Mdepth, Mwidget, Mcolormap;
2122
2123 /*** @} */
2124 /*** @} */
2125
2126 /*=*/
2127 /*** @addtogroup m17nInputMethodWin */
2128 /*=*/
2129 /*** @{ */
2130
2131 /***en
2132     @brief Input driver for XIM.
2133
2134     The input driver #minput_xim_driver is for the foreign input
2135     method of name #Mxim.  It uses XIM (X Input Methods) as a
2136     background input engine.
2137
2138     As the symbol #Mxim has property #Minput_driver whose value is
2139     a pointer to this driver, the input method of language #Mnil
2140     and name #Mxim uses this driver.
2141
2142     Therefore, for such input methods, the driver dependent arguments
2143     to the functions whose name begin with minput_ must be as follows.
2144
2145     The argument $ARG of the function minput_open_im () must be a
2146     pointer to the structure #MInputXIMArgIM.  See the documentation
2147     of #MInputXIMArgIM for more detail.
2148
2149     The argument $ARG of the function minput_create_ic () must be a
2150     pointer to the structure #MInputXIMArgIC. See the documentation
2151     of #MInputXIMArgIC for more detail.
2152
2153     The argument $ARG of the function minput_filter () must be a
2154     pointer to the structure @c XEvent.  The argument $KEY is ignored.
2155
2156     The argument $ARG of the function minput_lookup () must be the
2157     same one as that of the function minput_filter ().  The argument
2158     $KEY is ignored.  */
2159
2160 /***ja
2161     @brief XIMÍÑÆþÎϥɥ饤¥Ð
2162
2163     ÆþÎϥɥ饤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°Éô
2164     ÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤Î
2165     ÆþÎÏ¥¨¥ó¥¸¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
2166
2167     ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2168     #Minput_driver ¤ò»ý¤Ä¤¿¤á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç
2169     ¤¢¤ëÆþÎϥ᥽¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2170
2171     ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥ÉÍѤˤϡ¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä
2172     °Ê²¼¤Î´Ø¿ô·²¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é
2173     ¤Ê¤¤¡£
2174
2175     ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIM ¤Ø¤Î
2176     ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤Î¥É
2177     ¥­¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
2178
2179     ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIC ¤Ø
2180     ¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤Î
2181     ¥É¥­¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
2182
2183     ´Ø¿ô minput_filter () ¤Î°ú¿ô %ARG ¤Ï¹½Â¤ÂΠ@c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2184     ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2185
2186     ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter () 
2187     ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2188     ¤ë¡£  */
2189
2190 MInputDriver minput_xim_driver =
2191   { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2192     xim_filter, xim_lookup, NULL };
2193
2194 /*=*/
2195
2196 /***en
2197     @brief Symbol of the name "xim".
2198
2199     The variable Mxim is a symbol of name "xim".  It is a name of the
2200     input method driver #minput_xim_driver.  */ 
2201
2202 MSymbol Mxim;
2203
2204 /*** @} */ 
2205
2206 /*
2207   Local Variables:
2208   coding: euc-japan
2209   End:
2210 */