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