77b466cd0c2f374cb4affba508ecc22964a0b35b
[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   FT_Face ft_face = ft_info->ft_face;
1618   MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
1619
1620   for (; g != gend; g++)
1621     {
1622       if (g->code == MCHAR_INVALID_CODE)
1623         {
1624           MGlyph *start = g++;
1625
1626           while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
1627           (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
1628                                           GLYPH_INDEX (g));
1629           g--;
1630         }
1631       else
1632         {
1633           XGlyphInfo extents;
1634
1635           XftGlyphExtents (FRAME_DISPLAY (rfont->frame),
1636                            font_info->font_aa, &g->code, 1, &extents);
1637           g->lbearing = - extents.x;
1638           g->rbearing = extents.width - extents.x;
1639           g->width = extents.xOff;
1640           g->ascent = extents.y;
1641           g->descent = extents.height - extents.y;
1642         }
1643     }
1644 }
1645
1646
1647 void 
1648 xft_render (MDrawWindow win, int x, int y,
1649             MGlyphString *gstring, MGlyph *from, MGlyph *to,
1650             int reverse, MDrawRegion region)
1651 {
1652   MRealizedFace *rface = from->rface;
1653   MFrame *frame = rface->frame;
1654   MFTInfo *ft_info = rface->rfont->info;
1655   MXftFontInfo *font_info = ft_info->extra_info;
1656   XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
1657   XftColor *xft_color = (! reverse
1658                          ? &((GCInfo *) rface->info)->xft_color_fore
1659                          : &((GCInfo *) rface->info)->xft_color_back);
1660   XftFont *xft_font = (gstring->control.anti_alias
1661                        && FRAME_DEVICE (frame)->depth > 1
1662                        ? font_info->font_aa : font_info->font_no_aa);
1663   MGlyph *g;
1664   FT_UInt *glyphs;
1665   int last_x;
1666   int nglyphs;
1667
1668   if (from == to)
1669     return;
1670
1671   XftDrawChange (xft_draw, (Drawable) win);
1672   XftDrawSetClip (xft_draw, (Region) region);
1673       
1674   glyphs = alloca (sizeof (FT_UInt) * (to - from));
1675   for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
1676     {
1677       if (g->xoff == 0 && g->yoff == 0)
1678         glyphs[nglyphs++] = g->code;
1679       else
1680         {
1681           if (nglyphs > 0)
1682             XftDrawGlyphs (xft_draw, xft_color, xft_font,
1683                            last_x, y, glyphs, nglyphs);
1684           nglyphs = 0;
1685           XftDrawGlyphs (xft_draw, xft_color, xft_font,
1686                          x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
1687           last_x = x + g->width;
1688         }
1689     }
1690   if (nglyphs > 0)
1691     XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
1692 }
1693
1694 #endif
1695
1696 \f
1697
1698 /* XIM (X Input Method) handler */
1699
1700 typedef struct MInputXIMMethodInfo
1701 {
1702   Display *display;
1703   XIM xim;
1704   MSymbol language;
1705   MSymbol coding;
1706 } MInputXIMMethodInfo;
1707
1708 typedef struct MInputXIMContextInfo
1709 {
1710   XIC xic;
1711   Window win;
1712   MConverter *converter;
1713 } MInputXIMContextInfo;
1714
1715 static int
1716 xim_open_im (MInputMethod *im)
1717 {
1718   MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
1719   MLocale *saved, *this;
1720   char *save_modifier_list;
1721   XIM xim;
1722   MInputXIMMethodInfo *im_info;
1723
1724   saved = mlocale_set (LC_CTYPE, NULL);
1725   this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
1726   if (! this)
1727     /* The specified locale is not supported.  */
1728     MERROR (MERROR_LOCALE, -1);
1729   if (mlocale_get_prop (this, Mcoding) == Mnil)
1730     {
1731       /* Unable to decode the output of XIM.  */
1732       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
1733       MERROR (MERROR_LOCALE, -1);
1734     }
1735
1736   if (arg->modifier_list)
1737     save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
1738   else
1739     save_modifier_list = XSetLocaleModifiers ("");
1740   if (! save_modifier_list)
1741     {
1742       /* The specified locale is not supported by X.  */
1743       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
1744       MERROR (MERROR_LOCALE, -1);
1745     }
1746
1747   xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
1748   if (! xim)
1749     {
1750       /* No input method is available in the current locale.  */
1751       XSetLocaleModifiers (save_modifier_list);
1752       mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
1753       MERROR (MERROR_WIN, -1);
1754     }
1755
1756   MSTRUCT_MALLOC (im_info, MERROR_WIN);
1757   im_info->display = arg->display;
1758   im_info->xim = xim;
1759   im_info->language = mlocale_get_prop (this, Mlanguage);
1760   im_info->coding = mlocale_get_prop (this, Mcoding);
1761   im->info = im_info;
1762
1763   XSetLocaleModifiers (save_modifier_list);
1764   mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
1765
1766   return 0;
1767 }
1768
1769 static void
1770 xim_close_im (MInputMethod *im)
1771 {
1772   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
1773
1774   XCloseIM (im_info->xim);
1775   free (im_info);
1776 }
1777
1778 static int
1779 xim_create_ic (MInputContext *ic)
1780 {
1781   MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
1782   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
1783   MInputXIMContextInfo *ic_info;
1784   XIC xic;
1785
1786   if (! arg->input_style)
1787     {
1788       /* By default, use Root style.  */
1789       arg->input_style = XIMPreeditNothing | XIMStatusNothing;
1790       arg->preedit_attrs = NULL;
1791       arg->status_attrs = NULL;
1792     }
1793
1794   if (! arg->preedit_attrs && ! arg->status_attrs)
1795     xic = XCreateIC (im_info->xim,
1796                      XNInputStyle, arg->input_style,
1797                      XNClientWindow, arg->client_win,
1798                      XNFocusWindow, arg->focus_win,
1799                      NULL);
1800   else if (arg->preedit_attrs && ! arg->status_attrs)
1801     xic = XCreateIC (im_info->xim,
1802                      XNInputStyle, arg->input_style,
1803                      XNClientWindow, arg->client_win,
1804                      XNFocusWindow, arg->focus_win,
1805                      XNPreeditAttributes, arg->preedit_attrs,
1806                      NULL);
1807   else if (! arg->preedit_attrs && arg->status_attrs)
1808     xic = XCreateIC (im_info->xim,
1809                      XNInputStyle, arg->input_style,
1810                      XNClientWindow, arg->client_win,
1811                      XNFocusWindow, arg->focus_win,
1812                      XNStatusAttributes, arg->status_attrs,
1813                      NULL);
1814   else
1815     xic = XCreateIC (im_info->xim,
1816                      XNInputStyle, arg->input_style,
1817                      XNClientWindow, arg->client_win,
1818                      XNFocusWindow, arg->focus_win,
1819                      XNPreeditAttributes, arg->preedit_attrs,
1820                      XNStatusAttributes, arg->status_attrs,
1821                      NULL);
1822   if (! xic)
1823     MERROR (MERROR_WIN, -1);
1824
1825   MSTRUCT_MALLOC (ic_info, MERROR_WIN);
1826   ic_info->xic = xic;
1827   ic_info->win = arg->focus_win;
1828   ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
1829   ic->info = ic_info;
1830   return 0;
1831 }
1832
1833 static void
1834 xim_destroy_ic (MInputContext *ic)
1835 {
1836   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
1837
1838   XDestroyIC (ic_info->xic);
1839   mconv_free_converter (ic_info->converter);
1840   free (ic_info);
1841   ic->info = NULL;
1842 }
1843
1844 static int
1845 xim_filter (MInputContext *ic, MSymbol key, void *event)
1846 {
1847   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
1848
1849   return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
1850 }
1851
1852
1853 static int
1854 xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
1855 {
1856   MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
1857   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
1858   XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
1859   KeySym keysym;
1860   Status status;
1861   char *buf;
1862   int len;
1863
1864   buf = (char *) alloca (512);
1865   len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
1866   if (status == XBufferOverflow)
1867     {
1868       buf = (char *) alloca (len);
1869       len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
1870     }
1871
1872   mtext_reset (ic->produced);
1873   if (len == 0)
1874     return 1;
1875
1876   mconv_reset_converter (ic_info->converter);
1877   mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
1878   mconv_decode (ic_info->converter, ic->produced);
1879   mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
1880                   Mlanguage, (void *) im_info->language);
1881   mtext_cpy (mt, ic->produced);
1882   mtext_reset (ic->produced);  
1883   return 0;
1884 }
1885
1886 \f
1887
1888 #ifdef X_SET_ERROR_HANDLER
1889 static int
1890 x_error_handler (Display *display, XErrorEvent *error)
1891 {
1892   mdebug_hook ();
1893   return 0;
1894 }
1895
1896 static int
1897 x_io_error_handler (Display *display)
1898 {
1899   mdebug_hook ();
1900   return 0;
1901 }
1902 #endif
1903
1904 \f
1905
1906 /* Functions to be stored in MDeviceLibraryInterface by dlsym ().  */
1907
1908 int
1909 device_init ()
1910 {
1911   M_iso8859_1 = msymbol ("iso8859-1");
1912   M_iso10646_1 = msymbol ("iso10646-1");
1913
1914   display_info_list = mplist ();
1915   device_list = mplist ();
1916
1917 #ifdef HAVE_XFT2
1918   xft_driver.select = mfont__ft_driver.select;
1919   xft_driver.encode_char = mfont__ft_driver.encode_char;
1920 #endif
1921
1922   Mxim = msymbol ("xim");
1923   msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
1924
1925   return 0;
1926 }
1927
1928 int
1929 device_fini ()
1930 {
1931   M17N_OBJECT_UNREF (display_info_list);
1932   M17N_OBJECT_UNREF (device_list);
1933   return 0;
1934 }
1935
1936 /** Return an MWDevice object corresponding to a display specified in
1937     PLIST.
1938
1939     It searches device_list for a device matching the display.  If
1940     found, return the found object.  Otherwise, return a newly created
1941     object.  */
1942
1943 void *
1944 device_open (MFrame *frame, MPlist *param)
1945 {
1946   Display *display = NULL;
1947   Screen *screen = NULL;
1948   int screen_num;
1949   Drawable drawable = 0;
1950   Widget widget = NULL;
1951   Colormap cmap = 0;
1952   int auto_display = 0;
1953   MDisplayInfo *disp_info = NULL;
1954   MWDevice *device = NULL;
1955   MSymbol key;
1956   XWindowAttributes attr;
1957   unsigned depth = 0;
1958   MPlist *plist;
1959   AppData app_data;
1960   MFace *face;
1961
1962   for (plist = param; (key = mplist_key (plist)) != Mnil;
1963        plist = mplist_next (plist))
1964     {
1965       if (key == Mdisplay)
1966         display = (Display *) mplist_value (plist);
1967       else if (key == Mscreen)
1968         screen = mplist_value (plist);
1969       else if (key == Mdrawable)
1970         drawable = (Drawable) mplist_value (plist);
1971       else if (key == Mdepth)
1972         depth = (unsigned) mplist_value (plist);
1973       else if (key == Mwidget)
1974         widget = (Widget) mplist_value (plist);
1975       else if (key == Mcolormap)
1976         cmap = (Colormap) mplist_value (plist);
1977     }
1978
1979   if (widget)
1980     {
1981       display = XtDisplay (widget);
1982       screen_num = XScreenNumberOfScreen (XtScreen (widget));
1983       depth = DefaultDepth (display, screen_num);
1984     }
1985   else if (drawable)
1986     {
1987       Window root_window;
1988       int x, y;
1989       unsigned width, height, border_width;
1990
1991       if (! display)
1992         MERROR (MERROR_WIN, NULL);
1993       XGetGeometry (display, drawable, &root_window,
1994                     &x, &y, &width, &height, &border_width, &depth);
1995       XGetWindowAttributes (display, root_window, &attr);
1996       screen_num = XScreenNumberOfScreen (attr.screen);
1997     }
1998   else
1999     {
2000       if (screen)
2001         display = DisplayOfScreen (screen);
2002       else
2003         {
2004           if (! display)
2005             {
2006               display = XOpenDisplay (NULL);
2007               if (! display)
2008                 MERROR (MERROR_WIN, NULL);
2009               auto_display = 1;
2010             }
2011           screen = DefaultScreenOfDisplay (display);
2012         }
2013       screen_num = XScreenNumberOfScreen (screen);
2014       if (! depth)
2015         depth = DefaultDepth (display, screen_num);
2016     }
2017
2018   if (! cmap)
2019     cmap = DefaultColormap (display, screen_num);
2020
2021   for (plist = display_info_list; mplist_key (plist) != Mnil;
2022        plist = mplist_next (plist))
2023     {
2024       disp_info = (MDisplayInfo *) mplist_value (plist);
2025       if (disp_info->display == display)
2026         break;
2027     }
2028
2029   if (mplist_key (plist) != Mnil)
2030     M17N_OBJECT_REF (disp_info);
2031   else
2032     {
2033       M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
2034       disp_info->display = display;
2035       disp_info->auto_display = auto_display;
2036       disp_info->font_registry_list = mplist ();
2037       disp_info->iso8859_1_family_list = mplist ();
2038       disp_info->iso10646_1_family_list = mplist ();
2039       disp_info->realized_font_list = mplist ();
2040       find_modifier_bits (disp_info);
2041       mplist_add (display_info_list, Mt, disp_info);
2042     }  
2043
2044   for (plist = device_list; mplist_key (plist) != Mnil;
2045        plist = mplist_next (plist))
2046     {
2047       device = (MWDevice *) mplist_value (plist);
2048       if (device->display_info == disp_info
2049           && device->depth == depth
2050           && device->cmap == cmap)
2051         break;
2052     }
2053
2054   if (mplist_key (plist) != Mnil)
2055     M17N_OBJECT_REF (device);
2056   else
2057     {
2058       unsigned long valuemask = GCForeground;
2059       XGCValues values;
2060
2061       M17N_OBJECT (device, free_device, MERROR_WIN);
2062       device->display_info = disp_info;
2063       device->screen_num = screen_num;
2064       /* A drawable on which to create GCs.  */
2065       device->drawable = XCreatePixmap (display,
2066                                         RootWindow (display, screen_num),
2067                                         1, 1, depth);
2068       device->depth = depth;
2069       device->cmap = cmap;
2070       device->realized_face_list = mplist ();
2071       device->realized_fontset_list = mplist ();
2072       device->gc_list = mplist ();
2073       values.foreground = BlackPixel (display, screen_num);
2074       device->scratch_gc = XCreateGC (display, device->drawable,
2075                                       valuemask, &values);
2076 #ifdef HAVE_XFT2
2077       device->xft_draw = XftDrawCreate (display, device->drawable,
2078                                         DefaultVisual (display, screen_num),
2079                                         cmap);
2080 #endif
2081     }
2082
2083   frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
2084   frame->driver = &x_driver;
2085   frame->font_driver_list = mplist ();
2086   mplist_add (frame->font_driver_list, Mx, &xfont_driver);
2087 #ifdef HAVE_XFT2
2088   mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
2089 #elif HAVE_FREETYPE
2090   mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
2091 #endif
2092   frame->realized_font_list = disp_info->realized_font_list;
2093   frame->realized_face_list = device->realized_face_list;
2094   frame->realized_fontset_list = device->realized_fontset_list;
2095
2096   if (widget)
2097     {
2098       XtResource resources[] = {
2099         { XtNfont, XtCFont, XtRString, sizeof (String),
2100           XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
2101         { XtNforeground, XtCForeground, XtRString, sizeof (String),
2102           XtOffset (AppDataPtr, foreground), XtRString, "black" },
2103         { XtNbackground, XtCBackground, XtRString, sizeof (String),
2104           XtOffset (AppDataPtr, background), XtRString, "white" },
2105         { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
2106           XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
2107       };
2108
2109       XtGetApplicationResources (widget, &app_data,
2110                                  resources, XtNumber (resources), NULL, 0);
2111       frame->foreground = msymbol (app_data.foreground);
2112       frame->background = msymbol (app_data.background);
2113       frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
2114     }
2115   else
2116     {
2117       app_data.font = DEFAULT_FONT;
2118       frame->foreground = msymbol ("black");
2119       frame->background = msymbol ("white");
2120       frame->videomode = Mnormal;
2121     }
2122
2123   {
2124     int nfonts;
2125     char **names = XListFonts (display, app_data.font, 1, &nfonts);
2126
2127     if (nfonts > 0)
2128       {
2129         if (! (frame->font = mfont_parse_name (names[0], Mx)))
2130           {
2131             /* The font name does not conform to XLFD.  Try to open the
2132                font and get XA_FONT property.  */
2133             XFontStruct *xfont = XLoadQueryFont (display, names[0]);
2134
2135             nfonts = 0;
2136             if (xfont)
2137               {
2138                 unsigned long value;
2139                 char *name;
2140
2141                 if (XGetFontProperty (xfont, XA_FONT, &value)
2142                     && (name = ((char *)
2143                                 XGetAtomName (display, (Atom) value))))
2144                   {
2145                     if ((frame->font = mfont_parse_name (name, Mx)))
2146                       nfonts = 1;
2147                   }
2148                 XFreeFont (display, xfont);
2149               }
2150           }
2151         XFreeFontNames (names);
2152       }
2153     if (! nfonts)
2154       frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
2155   }
2156
2157   face = mface_from_font (frame->font);
2158   face->property[MFACE_FONTSET] = mfontset (NULL);
2159   face->property[MFACE_FOREGROUND] = frame->foreground;
2160   face->property[MFACE_BACKGROUND] = frame->background;
2161   mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
2162   mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
2163   face->property[MFACE_VIDEOMODE] = frame->videomode;
2164   mface_put_prop (face, Mhook_func, 
2165                   mface_get_prop (mface__default, Mhook_func));
2166   face->property[MFACE_RATIO] = (void *) 100;
2167   mplist_push (param, Mface, face);
2168   M17N_OBJECT_UNREF (face);
2169
2170 #ifdef X_SET_ERROR_HANDLER
2171   XSetErrorHandler (x_error_handler);
2172   XSetIOErrorHandler (x_io_error_handler);
2173 #endif
2174
2175   return device;
2176 }
2177
2178 /*** @} */
2179 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
2180 \f
2181 /* External API */
2182
2183 /*=*/
2184 /*** @addtogroup m17nInputMethodWin */
2185 /*=*/
2186 /*** @{ */
2187
2188 /***en
2189     @brief Input method driver for XIM.
2190
2191     The driver #minput_xim_driver is for the foreign input method of
2192     name #Mxim.  It uses XIM (X Input Methods) as a background input
2193     engine.
2194
2195     As the symbol #Mxim has property #Minput_driver whose value is
2196     a pointer to this driver, the input method of language #Mnil
2197     and name #Mxim uses this driver.
2198
2199     Therefore, for such input methods, the driver dependent arguments
2200     to the functions whose name begin with minput_ must be as follows.
2201
2202     The argument $ARG of the function minput_open_im () must be a
2203     pointer to the structure #MInputXIMArgIM.  See the documentation
2204     of #MInputXIMArgIM for more details.
2205
2206     The argument $ARG of the function minput_create_ic () must be a
2207     pointer to the structure #MInputXIMArgIC. See the documentation
2208     of #MInputXIMArgIC for more details.
2209
2210     The argument $ARG of the function minput_filter () must be a
2211     pointer to the structure @c XEvent.  The argument $KEY is ignored.
2212
2213     The argument $ARG of the function minput_lookup () must be the
2214     same one as that of the function minput_filter ().  The argument
2215     $KEY is ignored.  */
2216
2217 /***ja
2218     @brief XIMÍÑÆþÎϥɥ饤¥Ð.
2219
2220     ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
2221     ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
2222     ¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
2223
2224     ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
2225     #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
2226     ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
2227
2228     ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
2229     ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2230
2231     ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIM ¤Ø¤Î¥Ý
2232     ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
2233     »²¾È¡£
2234
2235     ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIC ¤Ø¤Î
2236     ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
2237     ¤ò»²¾È¡£
2238
2239     ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ@c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
2240     ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
2241
2242     ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter () 
2243     ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
2244     ¤ë¡£  */
2245
2246 MInputDriver minput_xim_driver =
2247   { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
2248     xim_filter, xim_lookup, NULL };
2249
2250 /*** @} */ 
2251
2252 /*
2253   Local Variables:
2254   coding: euc-japan
2255   End:
2256 */