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