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