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