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