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