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