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