X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fm17n-X.c;h=80cbeb37f1c294e1eaeb766ea76368f561af1af3;hb=6ac495c3a791ab71a4fb0a19b2d9f88f77efb558;hp=974dd2265782e0af9a498ed290d6d22b75ab6c1d;hpb=1359a5c46aaaa266d1d6a0f30f2478a18e439b5c;p=m17n%2Fm17n-lib.git diff --git a/src/m17n-X.c b/src/m17n-X.c index 974dd22..80cbeb3 100644 --- a/src/m17n-X.c +++ b/src/m17n-X.c @@ -17,9 +17,13 @@ You should have received a copy of the GNU Lesser General Public License along with the m17n library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 02111-1307, USA. */ +#include "config.h" + +#ifdef HAVE_X11 + #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) /*** @addtogroup m17nInternal @{ */ @@ -39,6 +43,11 @@ #include #include +#ifdef HAVE_XFT2 +#include +#include +#endif /* HAVE_XFT2 */ + #include "m17n-gui.h" #include "m17n-X.h" #include "m17n-misc.h" @@ -61,30 +70,61 @@ typedef struct be closed on freeing this structure. */ int auto_display; - /** List of available fonts on the display (except for iso8859-1 and - iso10646-1 fonts). Keys are font registries, values are - (MFontList *). */ - MPlist *font_registry_list; - - MPlist *iso8859_1_family_list; + /** List of available X-core fonts on the display. Keys are + registries and values are plists whose keys are families and + values are pointers to MFont. */ + MPlist *font_list; - MPlist *iso10646_1_family_list; - - /* List of information about each font. Keys are font registries, - values are (MFontInfo *). */ - MPlist *realized_font_list; + /** Nonzero means that already contains all available + fonts on the display. */ + int all_fonts_scaned; /** Modifier bit masks of the display. */ int meta_mask; int alt_mask; int super_mask; int hyper_mask; + + Atom MULE_BASELINE_OFFSET; + Atom AVERAGE_WIDTH; } MDisplayInfo; /* Anchor of the chain of MDisplayInfo objects. */ static MPlist *display_info_list; -struct MWDevice + +/* Color value and the corresponding GC. */ +typedef struct +{ + unsigned int rgb; /* (red << 16) | (green << 8) | blue */ + GC gc; +} RGB_GC; + +enum gc_index + { + GC_INVERSE, + GC_NORMAL = GC_INVERSE + 7, + GC_HLINE, + GC_BOX_TOP, + GC_BOX_BOTTOM, + GC_BOX_LEFT, + GC_BOX_RIGHT, + GC_MAX + }; + +typedef struct +{ + int rgb_fore; + int rgb_back; + /* The first 8 elements are indexed by an intensity for + anti-aliasing. The 2nd to 7th are created on demand. */ + GC gc[GC_MAX]; +#ifdef HAVE_XFT2 + XftColor xft_color_fore, xft_color_back; +#endif +} GCInfo; + +typedef struct { /* Common header for the m17n object. */ M17NObject control; @@ -99,66 +139,62 @@ struct MWDevice Colormap cmap; - unsigned long foreground, background; + GC scratch_gc; + + int resy; + +#ifdef HAVE_XFT2 + XftDraw *xft_draw; +#endif /** List of pointers to realized faces on the frame. */ MPlist *realized_face_list; + /* List of single element whose value is a root of chain of realized + fonts. */ + MPlist *realized_font_list; + /** List of pointers to realized fontsets on the frame. */ MPlist *realized_fontset_list; -}; + /** List of XColors vs GCs on the frame. */ + MPlist *gc_list; +} MWDevice; static MPlist *device_list; static MSymbol M_iso8859_1, M_iso10646_1; -#define FRAME_DISPLAY(frame) (frame->device->display_info->display) -#define FRAME_SCREEN(frame) (frame->device->screen_num) +#define FRAME_DEVICE(frame) ((MWDevice *) (frame)->device) +#define FRAME_DISPLAY(frame) (FRAME_DEVICE (frame)->display_info->display) +#define FRAME_SCREEN(frame) (FRAME_DEVICE (frame)->screen_num) +#define FRAME_CMAP(frame) (FRAME_DEVICE (frame)->cmap) +#define FRAME_VISUAL(frame) DefaultVisual (FRAME_DISPLAY (frame), \ + FRAME_SCREEN (frame)) + +#define DEFAULT_FONT "-*-*-medium-r-normal--13-*-*-*-c-*-iso8859-1" + +typedef struct +{ + String font; + String foreground; + String background; + Boolean reverse_video; +} AppData, *AppDataPtr; static void free_display_info (void *object) { MDisplayInfo *disp_info = (MDisplayInfo *) object; - MPlist *plist; - - for (plist = disp_info->font_registry_list; - mplist_key (plist) != Mnil; plist = mplist_next (plist)) - { - MFontList *registry_list = mplist_value (plist); - - if (registry_list->fonts) - free (registry_list->fonts); - free (registry_list); - } - M17N_OBJECT_UNREF (disp_info->font_registry_list); + MPlist *plist, *pl; - for (plist = disp_info->iso8859_1_family_list; - mplist_key (plist) != Mnil; plist = mplist_next (plist)) - { - MFontList *family_list = mplist_value (plist); - - if (family_list->fonts) - free (family_list->fonts); - free (family_list); - } - M17N_OBJECT_UNREF (disp_info->iso8859_1_family_list); - - for (plist = disp_info->iso10646_1_family_list; - mplist_key (plist) != Mnil; plist = mplist_next (plist)) + MPLIST_DO (plist, disp_info->font_list) { - MFontList *family_list = mplist_value (plist); - - if (family_list->fonts) - free (family_list->fonts); - free (family_list); + MPLIST_DO (pl, MPLIST_VAL (plist)) + free (MPLIST_VAL (pl)); + M17N_OBJECT_UNREF (MPLIST_VAL (plist)); } - M17N_OBJECT_UNREF (disp_info->iso10646_1_family_list); - - for (plist = disp_info->realized_font_list; - mplist_key (plist) != Mnil; plist = mplist_next (plist)) - mfont__free_realized ((MRealizedFont *) mplist_value (plist)); - M17N_OBJECT_UNREF (disp_info->realized_font_list); + M17N_OBJECT_UNREF (disp_info->font_list); if (disp_info->auto_display) XCloseDisplay (disp_info->display); @@ -169,7 +205,7 @@ free_display_info (void *object) static void free_device (void *object) { - MWDevice *device = (MWDevice *) object; + MWDevice *device = object; MPlist *plist; for (plist = device->realized_fontset_list; @@ -177,11 +213,32 @@ free_device (void *object) mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist)); M17N_OBJECT_UNREF (device->realized_fontset_list); - for (plist = device->realized_face_list; - mplist_key (plist) != Mnil; plist = mplist_next (plist)) - mface__free_realized ((MRealizedFace *) mplist_value (plist)); + if (MPLIST_VAL (device->realized_font_list)) + mfont__free_realized (MPLIST_VAL (device->realized_font_list)); + M17N_OBJECT_UNREF (device->realized_font_list); + + MPLIST_DO (plist, device->realized_face_list) + { + MRealizedFace *rface = MPLIST_VAL (plist); + + free (rface->info); + mface__free_realized (rface); + } M17N_OBJECT_UNREF (device->realized_face_list); + MPLIST_DO (plist, device->gc_list) + { + XFreeGC (device->display_info->display, + ((RGB_GC *) MPLIST_VAL (plist))->gc); + free (MPLIST_VAL (plist)); + } + M17N_OBJECT_UNREF (device->gc_list); + XFreeGC (device->display_info->display, device->scratch_gc); + +#ifdef HAVE_XFT2 + XftDrawDestroy (device->xft_draw); +#endif + XFreePixmap (device->display_info->display, device->drawable); M17N_OBJECT_UNREF (device->display_info); free (object); @@ -238,465 +295,526 @@ find_modifier_bits (MDisplayInfo *disp_info) XFreeModifiermap (mods); } -unsigned long -get_color (Display *display, Colormap cmap, - MSymbol color_name, MSymbol default_name, - unsigned long default_pixel) +static RGB_GC * +get_rgb_gc (MWDevice *device, XColor *xcolor) { - XColor exact_def; + int rgb = (((xcolor->red >> 8) << 16) | ((xcolor->green >> 8) << 8) + | (xcolor->blue >> 8)); + MPlist *plist; + RGB_GC *rgb_gc; + unsigned long valuemask = GCForeground; + XGCValues values; + + MPLIST_DO (plist, device->gc_list) + { + rgb_gc = MPLIST_VAL (plist); - if (XParseColor (display, cmap, msymbol_name (color_name), &exact_def) - && XAllocColor (display, cmap, &exact_def)) - return exact_def.pixel; + if (rgb_gc->rgb == rgb) + return rgb_gc; + if (rgb_gc->rgb > rgb) + break; + } - if (XParseColor (display, cmap, msymbol_name (default_name), &exact_def) - && XAllocColor (display, cmap, &exact_def)) - return exact_def.pixel; + if (! XAllocColor (device->display_info->display, device->cmap, xcolor)) + return NULL; - return default_pixel; + rgb_gc = malloc (sizeof (RGB_GC)); + rgb_gc->rgb = rgb; + values.foreground = xcolor->pixel; + rgb_gc->gc = XCreateGC (device->display_info->display, + device->drawable, valuemask, &values); + mplist_push (plist, Mt, rgb_gc); + return rgb_gc; } - -/** X font handler */ - -/** Indices to each field of split font name. */ +static GC +get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret) +{ + MWDevice *device = FRAME_DEVICE (frame); + XColor xcolor; + RGB_GC *rgb_gc; -enum xlfd_field_idx + if (color == Mnil) + { + if (frame->rface) + goto no_color; + color = for_foreground ? frame->foreground : frame->background; + } + if (! XParseColor (FRAME_DISPLAY (frame), device->cmap, + msymbol_name (color), &xcolor)) + goto no_color; + rgb_gc = get_rgb_gc (device, &xcolor); + if (! rgb_gc) + goto no_color; + if (rgb_ret) + *rgb_ret = rgb_gc->rgb; + return rgb_gc->gc; + + no_color: { - XLFD_FOUNDRY, - XLFD_FAMILY, - XLFD_WEIGHT, - XLFD_SLANT, - XLFD_SWIDTH, - XLFD_ADSTYLE, - XLFD_PIXEL, - XLFD_POINT, - XLFD_RESX, - XLFD_RESY, - XLFD_SPACING, - XLFD_AVGWIDTH, - XLFD_REGISTRY, - XLFD_ENCODING, - /* anchor */ - XLFD_FIELD_MAX - }; + GCInfo *info = frame->rface->info; + GC gc; + int rgb; + + if (for_foreground) + rgb = info->rgb_fore, gc = info->gc[GC_NORMAL]; + else + rgb = info->rgb_back, gc = info->gc[GC_INVERSE]; + if (rgb_ret) + *rgb_ret = rgb; + return gc; + } +} -/** Split the fontname NAME into each XLFD field destructively. Set - each element of the table pointed by PROPERTY_IDX to a pointer to - the corresponding font property name. Store the point size and - the resolution-Y of the font to the place pointed by POINT and - RESY respectively. +static GC +get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity) +{ + int rgb_fore, rgb_back; + XColor xcolor; + RGB_GC *rgb_gc; + GC gc; - If NAME does not contain all XLFD fields, the unspecified fields is - treated as wild cards. */ + if (info->gc[intensity]) + return info->gc[intensity]; + + rgb_fore = info->rgb_fore, rgb_back = info->rgb_back; + xcolor.red = ((((rgb_fore & 0xFF0000) >> 16) * intensity + + ((rgb_back & 0xFF0000) >> 16) * (7 - intensity)) / 7) << 8; + xcolor.green = ((((rgb_fore & 0xFF00) >> 8) * intensity + + ((rgb_back & 0xFF00) >> 8) * (7 - intensity)) / 7) << 8; + xcolor.blue = (((rgb_fore & 0xFF) * intensity + + (rgb_back & 0xFF) * (7 - intensity)) / 7) << 8; + rgb_gc = get_rgb_gc (device, &xcolor); + if (rgb_gc) + gc = rgb_gc->gc; + else + gc =get_gc_for_anti_alias (device, info, + intensity < 4 ? intensity - 1 : intensity + 1); + return (info->gc[intensity] = gc); +} -static int -split_font_name (char *name, char **field, - unsigned short *size, unsigned short *resy) +static GC +set_region (MFrame *frame, GC gc, MDrawRegion region) { - int i; - char *p; + unsigned long valuemask = GCForeground; - for (i = 0, p = name; *p; p++) - { - *p = tolower (*p); - if (*p == '-' && i < XLFD_FIELD_MAX) - { - field[i] = p + 1; - if (i != XLFD_ENCODING) - *p = '\0'; - i++; - } - } - if (i < XLFD_REGISTRY) - return -1; - for (; i < XLFD_FIELD_MAX; i++) - field[i] = "*"; + XCopyGC (FRAME_DISPLAY (frame), gc, valuemask, + FRAME_DEVICE (frame)->scratch_gc); + XSetRegion (FRAME_DISPLAY (frame), FRAME_DEVICE (frame)->scratch_gc, region); + return FRAME_DEVICE (frame)->scratch_gc; +} - if (*(field[XLFD_RESY]) == '*') - *resy = 0; - else - *resy = atoi (field[XLFD_RESY]); - if (*(field[XLFD_PIXEL]) == '*') - { - if (*(field[XLFD_POINT]) != '*') - *size = atoi (field[XLFD_POINT]) * *resy / 72; - else - *size = 0; - } - else if (*(field[XLFD_PIXEL]) == '[') - { - /* The pixel size field specifies a transformation matrix of the - form "[A B C D]". The XLFD spec says that the scalar value N - for the pixel size is equivalent to D. */ - char *p0 = field[XLFD_PIXEL] + 1, *p1; - double d; - - for (i = 0; i < 4; i++, p0 = p1) - d = strtod (p0, &p1); - *size = d * 10; - } - else - *size = atoi (field[XLFD_PIXEL]) * 10; - if (*size == 0 && *(field[XLFD_POINT]) != '*') - { - *size = atoi (field[XLFD_POINT]); - if (*resy) - *size = *size * *resy / 72; - else - *size = *size * 100 / 72; - } + +/** X font handler */ - return 0; -} +static MFont *xfont_select (MFrame *, MFont *, int); +static MRealizedFont *xfont_open (MFrame *, MFont *, MFont *, MRealizedFont *); +static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int); +static int xfont_has_char (MFrame *, MFont *, MFont *, int, unsigned); +static unsigned xfont_encode_char (MFrame *, MFont *, MFont *, unsigned); +static void xfont_render (MDrawWindow, int, int, MGlyphString *, + MGlyph *, MGlyph *, int, MDrawRegion); +static int xfont_list (MFrame *, MPlist *, MFont *, int); +static void xfont_list_family_names (MFrame *, MPlist *); +static int xfont_check_capability (MRealizedFont *rfont, MSymbol capability); -static int -build_font_name (MFont *font, char *name, int limit) -{ - MSymbol prop[7]; - char *str[7]; - int len, i; - unsigned short size, resy; - - prop[0] = (MSymbol) mfont_get_prop (font, Mfoundry); - prop[1] = (MSymbol) mfont_get_prop (font, Mfamily); - prop[2] = (MSymbol) mfont_get_prop (font, Mweight); - prop[3] = (MSymbol) mfont_get_prop (font, Mstyle); - prop[4] = (MSymbol) mfont_get_prop (font, Mstretch); - prop[5] = (MSymbol) mfont_get_prop (font, Madstyle); - prop[6] = (MSymbol) mfont_get_prop (font, Mregistry); - for (len = 0, i = 0; i < 7; i++) - { - if (prop[i] != Mnil) - { - str[i] = msymbol_name (prop[i]); - len += strlen (str[i]); - } - else - { - str[i] = "*"; - len++; - } - } - if ((len - + 12 /* 12 dashes */ - + 3 /* 3 asterisks */ - + 30 /* 3 integers (each 10 digits) */ - + 1) /* '\0' terminal */ - > limit) - return -1; - - size = (int) mfont_get_prop (font, Msize); - if ((size % 10) < 5) - size /= 10; - else - size = size / 10 + 1; - resy = (int) mfont_get_prop (font, Mresolution); +static MFontDriver xfont_driver = + { xfont_select, xfont_open, + xfont_find_metric, xfont_has_char, xfont_encode_char, + xfont_render, xfont_list, xfont_list_family_names, xfont_check_capability }; - sprintf (name, "-%s-%s-%s-%s-%s-%s-%d-*-%d-%d-*-*-%s", - str[0], str[1], str[2], str[3], str[4], str[5], - size, resy, resy, str[6]); - return 0; +static int +font_compare (const void *p1, const void *p2) +{ + return strcmp (*(char **) p1, *(char **) p2); } -static MFontList * -build_font_list (MFrame *frame, MSymbol family, MSymbol registry, - MPlist *plist) +static MPlist * +xfont_registry_list (MFrame *frame, MSymbol registry) { + MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info; + MPlist *font_list = disp_info->font_list; + MPlist *plist, *p; char pattern[1024]; - MFontList *font_list; - char **fontnames; + char **font_names, **names; int nfonts; int i, j; + MFont font; + int for_full_width; + + plist = mplist_get (font_list, registry); + if (plist) + return plist; + p = plist = mplist (); + mplist_add (font_list, registry, plist); + sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", msymbol_name (registry)); + font_names = XListFonts (disp_info->display, pattern, 0x8000, &nfonts); + if (nfonts == 0) + return plist; + { + char *reg_name = msymbol_name (registry); + + for_full_width = (strncmp (reg_name, "jis", 3) == 0 + || strncmp (reg_name, "gb", 2) == 0 + || strncmp (reg_name, "big5", 4) == 0 + || strncmp (reg_name, "ksc", 3) == 0); + } + names = alloca (sizeof (char *) * nfonts); + memcpy (names, font_names, sizeof (char *) * nfonts); + qsort (names, nfonts, sizeof (char *), font_compare); + MFONT_INIT (&font); + for (i = 0; i < nfonts; i++) + if (mfont__parse_name_into_font (names[i], Mx, &font) == 0 + && (font.size > 0 || font.property[MFONT_RESY] == 0)) + { + MSymbol family = FONT_PROPERTY (&font, MFONT_FAMILY); + MFont *fontx; + unsigned sizes[256]; + int nsizes = 0; + int limit; + int size, normal_size; + char *base_end; + int base_len; + int fields; + + /* Calculate how many bytes to compare to detect fonts of the + same base name. */ + for (base_end = names[i], fields = 0; *base_end; base_end++) + if (*base_end == '-' + && ++fields == 7 /* PIXEL_SIZE */) + break; + base_len = base_end - names[i] + 1; + + size = font.size / 10; + sizes[nsizes++] = size; + normal_size = (size >= 6 && size <= 29); + limit = (i + 256 < nfonts ? i + 256 : nfonts); + for (j = i + 1; j < limit && ! memcmp (names[i], names[j], base_len); + i = j++) + if (mfont__parse_name_into_font (names[j], Mx, &font) == 0 + && (font.size > 0 || font.property[MFONT_RESY] == 0)) + { + size = font.size / 10; + sizes[nsizes++] = size; + normal_size |= (size >= 6 && size <= 29); + } - MSTRUCT_CALLOC (font_list, MERROR_WIN); - - if (family == Mnil) - { - sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", - msymbol_name (registry)); - font_list->tag = registry; - } - else - { - sprintf (pattern, "-*-%s-*-*-*-*-*-*-*-*-*-*-%s", - msymbol_name (family), msymbol_name (registry)); - font_list->tag = family; - } - - fontnames = XListFonts (FRAME_DISPLAY (frame), pattern, 0x8000, &nfonts); - if (nfonts > 0) - { - MTABLE_MALLOC (font_list->fonts, nfonts, MERROR_WIN); - for (i = j = 0; i < nfonts; i++) - if (mwin__parse_font_name (fontnames[i], font_list->fonts + j) >= 0 - && (font_list->fonts[j].property[MFONT_SIZE] != 0 - || font_list->fonts[j].property[MFONT_RESY] == 0)) + font.for_full_width = for_full_width; + font.type = MFONT_TYPE_OBJECT; + font.source = MFONT_SOURCE_X; + if (normal_size) { - font_list->fonts[j].property[MFONT_TYPE] = MFONT_TYPE_WIN + 1; - j++; + MSTRUCT_CALLOC (fontx, MERROR_WIN); + *fontx = font; + fontx->multiple_sizes = 1; + fontx->size = 0; + for (j = 0; j < nsizes; j++) + if (sizes[j] >= 6 && sizes[j] <= 29) + fontx->size |= 1 << (sizes[j] - 6); + p = mplist_add (p, family, fontx); } - XFreeFontNames (fontnames); - font_list->nfonts = j; - } - mplist_add (plist, font_list->tag, font_list); - return (nfonts > 0 ? font_list : NULL); + for (j = 0; j < nsizes; j++) + if (sizes[j] < 6 || sizes[j] > 29) + { + MSTRUCT_CALLOC (fontx, MERROR_WIN); + *fontx = font; + fontx->multiple_sizes = 0; + fontx->size = sizes[j] * 10; + if (sizes[j] == 0) + fontx->property[MFONT_RESY] = 0; + p = mplist_add (p, family, fontx); + } + } + XFreeFontNames (font_names); + return plist; } +static void +xfont_list_all (MFrame *frame) +{ + MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info; + MPlist *font_encoding_list, *p; -static MRealizedFont *xfont_select (MFrame *, MFont *, MFont *, int); -static int xfont_open (MRealizedFont *); -static void xfont_close (MRealizedFont *); -static void xfont_find_metric (MRealizedFont *, MGlyph *); -static unsigned xfont_encode_char (MRealizedFont *, int, unsigned); -static void xfont_render (MDrawWindow, int, int, MGlyphString *, - MGlyph *, MGlyph *, int, MDrawRegion); + if (disp_info->all_fonts_scaned) + return; + disp_info->all_fonts_scaned = 1; + font_encoding_list = mfont__encoding_list (); + if (! font_encoding_list) + return; + MPLIST_DO (p, font_encoding_list) + xfont_registry_list (frame, MPLIST_KEY (p)); +} -MFontDriver xfont_driver = - { xfont_select, xfont_open, xfont_close, - xfont_find_metric, xfont_encode_char, xfont_render }; +typedef struct +{ + M17NObject control; + Display *display; + XFontStruct *xfont; +} MRealizedFontX; /* The X font driver function SELECT. */ -static MRealizedFont * -xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size) +static MFont * +xfont_select (MFrame *frame, MFont *font, int limited_size) { - MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY); - MRealizedFont *rfont; - MFontList *font_list = NULL; - int i; - MFont *best_font; - int best_score, score; - - if (registry == Mnil - || ! strchr (MSYMBOL_NAME (registry), '-')) - return NULL; - - /* We handles iso8859-1 and iso10646-1 fonts specially because there - exists so many such fonts. */ - if (registry == M_iso8859_1 || registry == M_iso10646_1) - { - MPlist *family_list - = (registry == M_iso8859_1 - ? frame->device->display_info->iso8859_1_family_list - : frame->device->display_info->iso10646_1_family_list); - MSymbol family = FONT_PROPERTY (spec, MFONT_FAMILY); - - if (family != Mnil) - { - font_list = (MFontList *) mplist_get (family_list, family); - if (! font_list) - font_list = build_font_list (frame, family, registry, family_list); - } - if (! font_list) - { - family = FONT_PROPERTY (request, MFONT_FAMILY); - font_list = (MFontList *) mplist_get (family_list, family); - if (! font_list) - font_list = build_font_list (frame, family, registry, family_list); - } - } - if (! font_list) - { - MPlist *registry_list - = frame->device->display_info->font_registry_list; - - font_list = (MFontList *) mplist_get (registry_list, registry); - if (! font_list) - font_list = build_font_list (frame, Mnil, registry, registry_list); - } - if (! font_list) - return NULL; + MPlist *plist = mplist (), *pl; + int num = xfont_list (frame, plist, font, 0); + MFont *found = NULL; - for (i = 0, best_score = -1, best_font = NULL; i < font_list->nfonts; i++) - if ((best_score = mfont__score (font_list->fonts + i, spec, request, - limited_size)) >= 0) - break; - if (best_score < 0) - return NULL; - best_font = font_list->fonts + i; - for (; best_score > 0 && i < font_list->nfonts ; i++) - { - score = mfont__score (font_list->fonts + i, spec, request, - limited_size); - if (score >= 0 && score < best_score) - { - best_font = font_list->fonts + i; - best_score = score; - } - } - - MSTRUCT_CALLOC (rfont, MERROR_WIN); - rfont->frame = frame; - rfont->spec = *spec; - rfont->request = *request; - rfont->font = *best_font; - if (best_font->property[MFONT_SIZE] == 0) - rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE]; - rfont->score = best_score; - rfont->driver = &xfont_driver; - return rfont; + if (num > 0) + MPLIST_DO (pl, plist) + { + font = MPLIST_VAL (pl); + if (limited_size == 0 + || font->size == 0 + || font->size <= limited_size) + { + found = font; + break; + } + } + M17N_OBJECT_UNREF (plist); + return found; } -typedef struct -{ - M17NObject control; - MFrame *frame; - XFontStruct *f; -} MXFontInfo; +/* The X font driver function CLOSE. */ static void close_xfont (void *object) { - MXFontInfo *xfont = (MXFontInfo *) object; + MRealizedFontX *x_rfont = object; - if (xfont->f) - XFreeFont (FRAME_DISPLAY (xfont->frame), xfont->f); - free (object); + XFreeFont (x_rfont->display, x_rfont->xfont); + free (x_rfont); } - /* The X font driver function OPEN. */ -static int -xfont_open (MRealizedFont *rfont) +static MRealizedFont * +xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont) { - char name[1024]; - MXFontInfo *xfont; - MFrame *frame = rfont->frame; + int size; + MRealizedFontX *x_rfont; + char *name; + Display *display = FRAME_DISPLAY (frame); + XFontStruct *xfont; int mdebug_mask = MDEBUG_FONT; + MFont this; - /* This never fail to generate a valid fontname because open_spec - should correspond to a font available on the system. */ - build_font_name (&rfont->font, name, 1024); - M17N_OBJECT (xfont, close_xfont, MERROR_WIN); - rfont->info = xfont; - xfont->frame = frame; - xfont->f = XLoadQueryFont (FRAME_DISPLAY (frame), name); - if (! xfont->f) + size = spec->size; + if (size) { - rfont->status = -1; - MDEBUG_PRINT1 (" [XFONT] x %s\n", name); - return -1; + int ratio = mfont_resize_ratio (font); + + if (ratio != 100) + size = size * ratio / 100; } - MDEBUG_PRINT1 (" [XFONT] o %s\n", name); - rfont->status = 1; - rfont->ascent = xfont->f->ascent; - rfont->descent = xfont->f->descent; - return 0; -} + else + size = 120; + if (font->size) + { + /* non-scalable font */ + if (font->multiple_sizes) + { + int i; + + if (size < 60) + size = 60; + else if (size > 290) + size = 290; + for (i = size / 10 - 6; i >= 0; i--) + if (font->size & (1 << i)) + break; + if (i == 0) + for (i = size / 10 - 5; i < 24; i++) + if (font->size & (1 << i)) + break; + size = (i + 6) * 10; + } + else + size = font->size; + } -/* The X font driver function CLOSE. */ + if (rfont) + { + for (; rfont; rfont = rfont->next) + if (rfont->font == font && rfont->spec.size == size) + return rfont; + } -static void -xfont_close (MRealizedFont *rfont) -{ - M17N_OBJECT_UNREF (rfont->info); + this = *font; + this.multiple_sizes = 0; + this.size = size; + /* This never fail to generate a valid fontname. */ + name = mfont_unparse_name (&this, Mx); + xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name); + if (! xfont) + { + MDEBUG_PRINT1 (" [XFONT] x %s\n", name); + free (name); + font->type = MFONT_TYPE_FAILURE; + return NULL; + } + MDEBUG_PRINT1 (" [XFONT] o %s\n", name); + free (name); + M17N_OBJECT (x_rfont, close_xfont, MERROR_FONT_X); + x_rfont->display = display; + x_rfont->xfont = xfont; + MSTRUCT_CALLOC (rfont, MERROR_FONT_X); + rfont->spec = this; + rfont->spec.type = MFONT_TYPE_REALIZED; + rfont->spec.source = MFONT_SOURCE_X; + rfont->frame = frame; + rfont->font = font; + rfont->driver = &xfont_driver; + rfont->info = x_rfont; + { + MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info; + unsigned long value; + + rfont->baseline_offset + = (XGetFontProperty (xfont, disp_info->MULE_BASELINE_OFFSET, &value) + ? (int) value : 0); + rfont->average_width + = (XGetFontProperty (xfont, disp_info->AVERAGE_WIDTH, &value) + ? (int) value / 10 : 0); + } + rfont->ascent = xfont->ascent + rfont->baseline_offset; + rfont->descent = xfont->descent - rfont->baseline_offset; + rfont->max_advance = xfont->max_bounds.width; + rfont->fontp = xfont; + rfont->next = MPLIST_VAL (frame->realized_font_list); + MPLIST_VAL (frame->realized_font_list) = rfont; + return rfont; } + /* The X font driver function FIND_METRIC. */ static void -xfont_find_metric (MRealizedFont *rfont, MGlyph *g) +xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring, + int from, int to) { - XCharStruct *pcm = NULL; - MXFontInfo *xfont = (MXFontInfo *) rfont->info; - XFontStruct *f = xfont->f; - int byte1, byte2; - - if (g->code == MCHAR_INVALID_CODE) - { - g->lbearing = f->max_bounds.lbearing; - g->rbearing = f->max_bounds.rbearing; - g->width = f->max_bounds.width; - g->ascent = f->ascent; - g->descent = f->descent; - return; - } - - byte1 = g->code >> 8; - byte2 = g->code & 0xFF; + XFontStruct *xfont = rfont->fontp; + MGlyph *g = MGLYPH (from), *gend = MGLYPH (to); - if (f->per_char != NULL) + for (; g != gend; g++) { - if (f->min_byte1 == 0 && f->max_byte1 == 0) + if (g->code == MCHAR_INVALID_CODE) { - if (byte1 == 0 - && byte2 >= f->min_char_or_byte2 - && byte2 <= f->max_char_or_byte2) - pcm = f->per_char + byte2 - f->min_char_or_byte2; + g->lbearing = xfont->max_bounds.lbearing; + g->rbearing = xfont->max_bounds.rbearing; + g->width = xfont->max_bounds.width; + g->ascent = xfont->ascent; + g->descent = xfont->descent; } else { - if (byte1 >= f->min_byte1 - && byte1 <= f->max_byte1 - && byte2 >= f->min_char_or_byte2 - && byte2 <= f->max_char_or_byte2) + int byte1 = g->code >> 8, byte2 = g->code & 0xFF; + XCharStruct *pcm = NULL; + + if (xfont->per_char != NULL) { - pcm = (f->per_char - + ((f->max_char_or_byte2-f->min_char_or_byte2 + 1) - * (byte1 - f->min_byte1)) - + (byte2 - f->min_char_or_byte2)); + if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0) + { + if (byte1 == 0 + && byte2 >= xfont->min_char_or_byte2 + && byte2 <= xfont->max_char_or_byte2) + pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2; + } + else + { + if (byte1 >= xfont->min_byte1 + && byte1 <= xfont->max_byte1 + && byte2 >= xfont->min_char_or_byte2 + && byte2 <= xfont->max_char_or_byte2) + { + pcm = (xfont->per_char + + ((xfont->max_char_or_byte2 + - xfont->min_char_or_byte2 + 1) + * (byte1 - xfont->min_byte1)) + + (byte2 - xfont->min_char_or_byte2)); + } + } } - } - } - if (pcm) - { - g->lbearing = pcm->lbearing; - g->rbearing = pcm->rbearing; - g->width = pcm->width; - g->ascent = pcm->ascent; - g->descent = pcm->descent; - } - else - { - /* If the per_char pointer is null, all glyphs between the first - and last character indexes inclusive have the same - information, as given by both min_bounds and max_bounds. */ - g->lbearing = 0; - g->rbearing = f->max_bounds.width; - g->width = f->max_bounds.width; - g->ascent = f->ascent; - g->descent = f->descent; + if (pcm) + { + g->lbearing = pcm->lbearing; + g->rbearing = pcm->rbearing; + g->width = pcm->width; + g->ascent = pcm->ascent; + g->descent = pcm->descent; + } + else + { + /* If the per_char pointer is null, all glyphs between + the first and last character indexes inclusive have + the same information, as given by both min_bounds and + max_bounds. */ + g->lbearing = 0; + g->rbearing = xfont->max_bounds.width; + g->width = xfont->max_bounds.width; + g->ascent = xfont->ascent; + g->descent = xfont->descent; + } + } + g->ascent += rfont->baseline_offset; + g->descent -= rfont->baseline_offset; } } -/* The X font driver function ENCODE_CHAR. */ +static int +xfont_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code) +{ + return (xfont_encode_char (frame, font, spec, code) != MCHAR_INVALID_CODE); +} + +/* The X font driver function GET_GLYPH_ID. */ static unsigned -xfont_encode_char (MRealizedFont *rfont, int c, unsigned code) +xfont_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code) { - MXFontInfo *xfont; - XFontStruct *f; + MRealizedFont *rfont; + XFontStruct *xfont; unsigned min_byte1, max_byte1, min_byte2, max_byte2; int all_chars_exist; - if (rfont->status < 0) - return -1; - if (rfont->status == 0) + if (font->type == MFONT_TYPE_REALIZED) + rfont = (MRealizedFont *) font; + else if (font->type == MFONT_TYPE_OBJECT) { - if (xfont_open (rfont) < 0) - return -1; + for (rfont = MPLIST_VAL (frame->realized_font_list); rfont; + rfont = rfont->next) + if (rfont->font == font) + break; + if (! rfont) + { + rfont = xfont_open (frame, font, spec, NULL); + if (! rfont) + return MCHAR_INVALID_CODE; + } } - xfont = (MXFontInfo *) rfont->info; - f = xfont->f; - all_chars_exist = (! f->per_char || f->all_chars_exist == True); - min_byte1 = f->min_byte1; - max_byte1 = f->max_byte1; - min_byte2 = f->min_char_or_byte2; - max_byte2 = f->max_char_or_byte2; + else + MFATAL (MERROR_FONT_X); + xfont = rfont->fontp; + all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True); + min_byte1 = xfont->min_byte1; + max_byte1 = xfont->max_byte1; + min_byte2 = xfont->min_char_or_byte2; + max_byte2 = xfont->max_char_or_byte2; if (min_byte1 == 0 && max_byte1 == 0) { XCharStruct *pcm; + if (code < min_byte2 || code > max_byte2) + return MCHAR_INVALID_CODE; if (all_chars_exist) - return ((code >= min_byte2 && code <= max_byte2) - ? code : MCHAR_INVALID_CODE); - pcm = f->per_char + (code - min_byte2); + return code; + pcm = xfont->per_char + (code - min_byte2); return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing) ? code : MCHAR_INVALID_CODE); } @@ -705,30 +823,19 @@ xfont_encode_char (MRealizedFont *rfont, int c, unsigned code) unsigned byte1 = code >> 8, byte2 = code & 0xFF; XCharStruct *pcm; + if (byte1 < min_byte1 || byte1 > max_byte1 + || byte2 < min_byte2 || byte2 > max_byte2) + return MCHAR_INVALID_CODE; + if (all_chars_exist) - return ((byte1 >= min_byte1 && byte1 <= max_byte1 - && byte2 >= min_byte2 && byte2 <= max_byte2) - ? code : MCHAR_INVALID_CODE); - pcm = f->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1) + return code; + pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1) + (byte2 - min_byte2)); return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing) ? code : MCHAR_INVALID_CODE); } } -static GC -set_region (Display *display, MRealizedFace *rface, GC gc, MDrawRegion region) -{ - GC gc1; - XRectangle xrect; - - XClipBox (region, &xrect); - gc1 = ((GC *) rface->info)[MFACE_GC_SCRATCH]; - XCopyGC (display, gc, GCFont | GCForeground | GCBackground, gc1); - XSetRegion (display, gc1, region); - return gc1; -} - /* The X font driver function RENDER. */ static void @@ -736,43 +843,26 @@ xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring, MGlyph *from, MGlyph *to, int reverse, MDrawRegion region) { MRealizedFace *rface = from->rface; - Display *display; + Display *display = FRAME_DISPLAY (rface->frame); XChar2b *code; - GC *gcs = rface->info; - GC gc = gcs[reverse ? MFACE_GC_INVERSE : MFACE_GC_NORMAL]; + GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL]; MGlyph *g; int i; + int baseline_offset; if (from == to) return; - /* It is assured that the all glyphs in the current range use the - same realized face. */ - display = FRAME_DISPLAY (rface->frame); - + baseline_offset = rface->rfont->baseline_offset; if (region) - gc = set_region (display, rface, gc, region); - - if (from->code == MCHAR_INVALID_CODE) + gc = set_region (rface->frame, gc, region); + XSetFont (display, gc, ((XFontStruct *) rface->rfont->fontp)->fid); + code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from)); + for (i = 0, g = from; g < to; i++, g++) { - int x0 = x; - - for (; from < to; from++) - { - XDrawRectangle (display, (Window) win, gc, - x0, y - gstring->ascent + 1, from->width - 1, - gstring->ascent + gstring->descent - 2); - x0 += from->width; - } - return; - } - - code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from)); - for (i = 0, g = from; g < to; i++, g++) - { - code[i].byte1 = g->code >> 8; - code[i].byte2 = g->code & 0xFF; - } + code[i].byte1 = g->code >> 8; + code[i].byte2 = g->code & 0xFF; + } g = from; while (g < to) @@ -806,7 +896,8 @@ xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring, else if (g->xoff != 0 || g->yoff != 0 || g->right_padding) { XDrawString16 (display, (Window) win, gc, - x + g->xoff, y + g->yoff, code + (g - from), 1); + x + g->xoff, y + g->yoff - baseline_offset, + code + (g - from), 1); x += g->width; g++; } @@ -819,542 +910,439 @@ xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring, g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0; i++, g++) x += g->width; - XDrawString16 (display, (Window) win, gc, orig_x, y, - code + code_idx, i); + XDrawString16 (display, (Window) win, gc, + orig_x, y - baseline_offset, code + code_idx, i); } } } - - -/* XIM (X Input Method) handler */ - -typedef struct MInputXIMMethodInfo -{ - Display *display; - XIM xim; - MSymbol language; - MSymbol coding; -} MInputXIMMethodInfo; - -typedef struct MInputXIMContextInfo -{ - XIC xic; - Window win; - MConverter *converter; -} MInputXIMContextInfo; - static int -xim_open_im (MInputMethod *im) +xfont_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum) { - MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg; - MLocale *saved, *this; - char *save_modifier_list; - XIM xim; - MInputXIMMethodInfo *im_info; + MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info; + MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil; + MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil; + int size = font ? font->size : 0; + MPlist *pl, *p; + int num = 0; + int mdebug_mask = MDEBUG_FONT; - saved = mlocale_set (LC_CTYPE, NULL); - this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : ""); - if (! this) - /* The specified locale is not supported. */ - MERROR (MERROR_LOCALE, -1); - if (mlocale_get_prop (this, Mcoding) == Mnil) - { - /* Unable to decode the output of XIM. */ - mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname))); - MERROR (MERROR_LOCALE, -1); - } + MDEBUG_PRINT2 (" [X-FONT] listing %s-%s...", + family ? msymbol_name (family) : "*", + registry ? msymbol_name (registry) : "*"); - if (arg->modifier_list) - save_modifier_list = XSetLocaleModifiers (arg->modifier_list); + if (registry == Mnil) + xfont_list_all (frame); else - save_modifier_list = XSetLocaleModifiers (""); - if (! save_modifier_list) - { - /* The specified locale is not supported by X. */ - mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname))); - MERROR (MERROR_LOCALE, -1); - } - - xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class); - if (! xim) - { - /* No input method is available in the current locale. */ - XSetLocaleModifiers (save_modifier_list); - mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname))); - MERROR (MERROR_WIN, -1); - } + xfont_registry_list (frame, registry); - MSTRUCT_MALLOC (im_info, MERROR_WIN); - im_info->display = arg->display; - im_info->xim = xim; - im_info->language = mlocale_get_prop (this, Mlanguage); - im_info->coding = mlocale_get_prop (this, Mcoding); - im->info = im_info; + MPLIST_DO (pl, disp_info->font_list) + if (registry == Mnil || registry == MPLIST_KEY (pl)) + { + MPLIST_DO (p, MPLIST_VAL (pl)) + if (family == Mnil || family == MPLIST_KEY (p)) + { + MFont *fontx = MPLIST_VAL (p); - XSetLocaleModifiers (save_modifier_list); - mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname))); + if (! font || (mfont__match_p (fontx, font, MFONT_REGISTRY))) + { + if (fontx->size != 0 && size) + { + if (fontx->multiple_sizes) + { + if (size < 60 || size > 290 + || ! (fontx->size & (1 << (size / 10 - 6)))) + continue; + } + else if (fontx->size != size) + continue; + } + mplist_push (plist, MPLIST_KEY (p), fontx); + num++; + if (maxnum > 0 && maxnum == num) + goto done; + } + } + } - return 0; + done: + MDEBUG_PRINT1 (" %d found\n", num); + return num; } static void -xim_close_im (MInputMethod *im) +xfont_list_family_names (MFrame *frame, MPlist *plist) { - MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info; + MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info; + char **font_names; + int i, nfonts; + MSymbol last_family = Mnil; + + font_names = XListFonts (disp_info->display, + "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", 0x8000, &nfonts); + for (i = 0; i < nfonts; i++) + { + MSymbol family; + char foundry[256], fam[256]; + MPlist *p; + + if (sscanf (font_names[i], "-%s-%s-", foundry, fam) < 2) + continue; + family = msymbol (fam); + if (family == last_family) + continue; + last_family = family; + + MPLIST_DO (p, plist) + { + MSymbol sym = MPLIST_SYMBOL (p); - XCloseIM (im_info->xim); - free (im_info); + if (sym == family) + break; + if (strcmp (MSYMBOL_NAME (sym), fam) > 0) + { + mplist_push (p, Msymbol, family); + break; + } + } + if (MPLIST_TAIL_P (p)) + mplist_push (p, Msymbol, family); + } + if (font_names) + XFreeFontNames (font_names); } -int -xim_create_ic (MInputContext *ic) +static int +xfont_check_capability (MRealizedFont *rfont, MSymbol capability) { - MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg; - MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info; - MInputXIMContextInfo *ic_info; - XIC xic; - - if (! arg->input_style) - { - /* By default, use Root style. */ - arg->input_style = XIMPreeditNothing | XIMStatusNothing; - arg->preedit_attrs = NULL; - arg->status_attrs = NULL; - } + /* Currently X font driver doesn't support any capability. */ + return -1; +} - if (! arg->preedit_attrs && ! arg->status_attrs) - xic = XCreateIC (im_info->xim, - XNInputStyle, arg->input_style, - XNClientWindow, arg->client_win, - XNFocusWindow, arg->focus_win, - NULL); - else if (arg->preedit_attrs && ! arg->status_attrs) - xic = XCreateIC (im_info->xim, - XNInputStyle, arg->input_style, - XNClientWindow, arg->client_win, - XNFocusWindow, arg->focus_win, - XNPreeditAttributes, arg->preedit_attrs, - NULL); - else if (! arg->preedit_attrs && arg->status_attrs) - xic = XCreateIC (im_info->xim, - XNInputStyle, arg->input_style, - XNClientWindow, arg->client_win, - XNFocusWindow, arg->focus_win, - XNStatusAttributes, arg->status_attrs, - NULL); - else - xic = XCreateIC (im_info->xim, - XNInputStyle, arg->input_style, - XNClientWindow, arg->client_win, - XNFocusWindow, arg->focus_win, - XNPreeditAttributes, arg->preedit_attrs, - XNStatusAttributes, arg->status_attrs, - NULL); - if (! xic) - MERROR (MERROR_WIN, -1); + +/* Xft Handler */ - MSTRUCT_MALLOC (ic_info, MERROR_WIN); - ic_info->xic = xic; - ic_info->win = arg->focus_win; - ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0); - ic->info = ic_info; - return 0; -} +#ifdef HAVE_XFT2 -void -xim_destroy_ic (MInputContext *ic) +typedef struct { - MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info; + M17NObject control; + FT_Face ft_face; /* This must be the 2nd member. */ + Display *display; + XftFont *font_aa; + XftFont *font_no_aa; + /* Pointer to MRealizedFontFT */ + void *info; +} MRealizedFontXft; + +static MRealizedFont *xft_open (MFrame *frame, MFont *font, MFont *spec, + MRealizedFont *); +static int xft_has_char (MFrame *frame, MFont *font, MFont *spec, + int c, unsigned code); +static unsigned xft_encode_char (MFrame *frame, MFont *font, MFont *spec, + unsigned code); +static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int); +static void xft_render (MDrawWindow, int, int, MGlyphString *, + MGlyph *, MGlyph *, int, MDrawRegion); +static int xft_check_capability (MRealizedFont *rfont, MSymbol capability); + +static MFontDriver xft_driver = + { NULL, xft_open, + xft_find_metric, xft_has_char, xft_encode_char, xft_render, NULL, NULL, + xft_check_capability + }; - XDestroyIC (ic_info->xic); - mconv_free_converter (ic_info->converter); - free (ic_info); - ic->info = NULL; +static void +close_xft (void *object) +{ + MRealizedFontXft *rfont_xft = object; + + if (rfont_xft->font_aa) + XftFontClose (rfont_xft->display, rfont_xft->font_aa); + if (rfont_xft->font_no_aa) + XftFontClose (rfont_xft->display, rfont_xft->font_no_aa); + M17N_OBJECT_UNREF (rfont_xft->info); + free (rfont_xft); } -static int -xim_filter (MInputContext *ic, MSymbol key, void *event) -{ - MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info; - return (XFilterEvent ((XEvent *) event, ic_info->win) == True); +static XftFont * +xft_open_font (Display *display, MSymbol file, double size, + FcBool anti_alias) +{ + FcPattern *pattern; + XftFont *font; + + pattern = FcPatternCreate (); + FcPatternAddString (pattern, FC_FILE, (FcChar8 *) msymbol_name (file)); + FcPatternAddDouble (pattern, FC_PIXEL_SIZE, size); + FcPatternAddBool (pattern, FC_ANTIALIAS, anti_alias); + font = XftFontOpenPattern (display, pattern); + return font; } -static int -xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt) +static MRealizedFont * +xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont) { - MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info; - MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info; - XKeyPressedEvent *ev = (XKeyPressedEvent *) arg; - KeySym keysym; - Status status; - char *buf; - int len; - - buf = (char *) alloca (512); - len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status); - if (status == XBufferOverflow) + Display *display = FRAME_DISPLAY (frame); + int reg = spec->property[MFONT_REGISTRY]; + FT_Face ft_face; + MRealizedFontXft *rfont_xft; + FcBool anti_alias = FRAME_DEVICE (frame)->depth > 1 ? FcTrue : FcFalse; + int size; + XftFont *xft_font; + int ascent, descent, max_advance, average_width, baseline_offset; + + if (font->size) + /* non-scalable font */ + size = font->size; + else if (spec->size) { - buf = (char *) alloca (len); - len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status); + int ratio = mfont_resize_ratio (font); + + size = ratio == 100 ? spec->size : spec->size * ratio / 100; } + else + size = 120; - mtext_reset (ic->produced); - if (len == 0) - return 1; + if (rfont) + { + MRealizedFont *save = NULL; - mconv_reset_converter (ic_info->converter); - mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len); - mconv_decode (ic_info->converter, ic->produced); - mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced), - Mlanguage, (void *) im_info->language); - mtext_cpy (mt, ic->produced); - mtext_reset (ic->produced); - return 0; + for (; rfont; rfont = rfont->next) + if (rfont->font == font + && (rfont->font->size ? rfont->font->size == size + : rfont->spec.size == size) + && rfont->spec.property[MFONT_REGISTRY] == reg) + { + if (! save) + save = rfont; + if (rfont->driver == &xft_driver) + return rfont; + } + rfont = save; + } + rfont = (mfont__ft_driver.open) (frame, font, spec, rfont); + if (! rfont) + return NULL; + ascent = rfont->ascent; + descent = rfont->descent; + max_advance = rfont->max_advance; + average_width = rfont->average_width; + baseline_offset = rfont->baseline_offset; + spec = &rfont->spec; + ft_face = rfont->fontp; + xft_font = xft_open_font (display, font->file, size / 10, anti_alias); + if (! xft_font) + return NULL; + M17N_OBJECT (rfont_xft, close_xft, MERROR_WIN); + rfont_xft->display = display; + if (anti_alias == FcTrue) + rfont_xft->font_aa = xft_font; + else + rfont_xft->font_no_aa = xft_font; + rfont_xft->ft_face = ft_face; + rfont_xft->info = rfont->info; + M17N_OBJECT_REF (rfont->info); + MSTRUCT_CALLOC (rfont, MERROR_FONT_X); + rfont->spec = *spec; + rfont->spec.size = size; + rfont->frame = frame; + rfont->font = font; + rfont->driver = &xft_driver; + rfont->info = rfont_xft; + rfont->ascent = ascent; + rfont->descent = descent; + rfont->max_advance = max_advance; + rfont->average_width = average_width; + rfont->baseline_offset = baseline_offset; + rfont->fontp = xft_font; + rfont->next = MPLIST_VAL (frame->realized_font_list); + MPLIST_VAL (frame->realized_font_list) = rfont; + return rfont; } - - -#if 1 -int -x_error_handler (Display *display, XErrorEvent *error) +static void +xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring, + int from, int to) { - mdebug_hook (); - return 0; -} + Display *display = FRAME_DISPLAY (rfont->frame); + XftFont *xft_font = rfont->fontp; + MGlyph *g = MGLYPH (from), *gend = MGLYPH (to); -int -x_io_error_handler (Display *display) -{ - mdebug_hook (); - return 0; + for (; g != gend; g++) + { + if (g->code == MCHAR_INVALID_CODE) + { + g->lbearing = 0; + g->rbearing = xft_font->max_advance_width; + g->width = g->rbearing; + g->ascent = xft_font->ascent; + g->descent = xft_font->descent; + } + else + { + XGlyphInfo extents; + + XftGlyphExtents (display, xft_font, &g->code, 1, &extents); + g->lbearing = - extents.x; + g->rbearing = extents.width - extents.x; + g->width = extents.xOff; + g->ascent = extents.y; + g->descent = extents.height - extents.y; + } + } } -#endif - - -int -mwin__init () +static int +xft_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code) { - Mdisplay = msymbol ("display"); - Mscreen = msymbol ("screen"); - Mdrawable = msymbol ("drawable"); - Mdepth = msymbol ("depth"); - Mwidget = msymbol ("widget"); - M_iso8859_1 = msymbol ("iso8859-1"); - M_iso10646_1 = msymbol ("iso10646-1"); - - display_info_list = mplist (); - device_list = mplist (); - - mfont__driver_list[MFONT_TYPE_WIN] = &xfont_driver; - - Mxim = msymbol ("xim"); - msymbol_put (Mxim, Minput_driver, &minput_xim_driver); + int result; - return 0; + if (font->type == MFONT_TYPE_REALIZED) + { + MRealizedFont *rfont = (MRealizedFont *) font; + MRealizedFontXft *rfont_xft = rfont->info; + + rfont->info = rfont_xft->info; + result = mfont__ft_driver.has_char (frame, font, spec, c, code); + rfont->info = rfont_xft; + } + else + result = mfont__ft_driver.has_char (frame, font, spec, c, code); + return result; } -void -mwin__fini () +static unsigned +xft_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code) { - M17N_OBJECT_UNREF (display_info_list); - M17N_OBJECT_UNREF (device_list); + if (font->type == MFONT_TYPE_REALIZED) + { + MRealizedFont *rfont = (MRealizedFont *) font; + MRealizedFontXft *rfont_xft = rfont->info; + + rfont->info = rfont_xft->info; + code = mfont__ft_driver.encode_char (frame, font, spec, code); + rfont->info = rfont_xft; + } + else + code = mfont__ft_driver.encode_char (frame, font, spec, code); + return code; } -typedef struct +static void +xft_render (MDrawWindow win, int x, int y, + MGlyphString *gstring, MGlyph *from, MGlyph *to, + int reverse, MDrawRegion region) { - String font; - String foreground; - String background; - Boolean reverse_video; -} AppData, *AppDataPtr; - - -int -mwin__parse_font_name (char *name, MFont *font) -{ - char *field[XLFD_FIELD_MAX]; - unsigned short size, resy; - MSymbol attrs[MFONT_PROPERTY_MAX]; - char *copy = (char *) alloca (512); - int i, len; - char *p, *last = NULL; - - len = strlen (name) + 1; - for (i = 0, p = name; *p; p++) - { - if (*p == '-') - i++; - else if (p > name && *p == '*' && p[-1] == '-') - last = p + 1; - } - if (i == 14) - memcpy (copy, name, len); - else if (last) - { - memcpy (copy, name, last - name); - for (; i < 14; i++) - strcat (copy, "-*"); - strcat (copy, last); - } - - if (split_font_name (copy, field, &size, &resy) < 0) - return -1; - attrs[MFONT_FOUNDRY] - = *(field[XLFD_FOUNDRY]) != '*' ? msymbol (field[XLFD_FOUNDRY]) : Mnil; - attrs[MFONT_FAMILY] - = *(field[XLFD_FAMILY]) != '*' ? msymbol (field[XLFD_FAMILY]) : Mnil; - attrs[MFONT_WEIGHT] - = *(field[XLFD_WEIGHT]) != '*' ? msymbol (field[XLFD_WEIGHT]) : Mnil; - attrs[MFONT_STYLE] - = *(field[XLFD_SLANT]) != '*' ? msymbol (field[XLFD_SLANT]) : Mnil; - attrs[MFONT_STRETCH] - = *(field[XLFD_SWIDTH]) != '*' ? msymbol (field[XLFD_SWIDTH]) : Mnil; - attrs[MFONT_ADSTYLE] - = *(field[XLFD_ADSTYLE]) != '*' ? msymbol (field[XLFD_ADSTYLE]) : Mnil; - attrs[MFONT_REGISTRY] - = *(field[XLFD_REGISTRY]) != '*' ? msymbol (field[XLFD_REGISTRY]) : Mnil; - mfont__set_spec (font, attrs, size, resy); - return 0; -} - - -char * -mwin__build_font_name (MFont *font) -{ - char name[1024]; - - if (build_font_name (font, name, 1024) < 0) - return NULL; - return strdup (name); -} - -/** Return an MWDevice object corresponding to a display specified in - PLIST. - - It searches device_list for a device matching the display. If - found, return the found object. Otherwise, return a newly created - object. */ - -MWDevice * -mwin__open_device (MFrame *frame, MPlist *param) -{ - Display *display = NULL; - Screen *screen = NULL; - int screen_num; - Drawable drawable = 0; - Widget widget = NULL; - Colormap cmap = 0; - int auto_display = 0; - MDisplayInfo *disp_info = NULL; - MWDevice *device = NULL; - MSymbol key; - XWindowAttributes attr; - unsigned depth = 0; - MPlist *plist; - - if (param) - for (plist = param; (key = mplist_key (plist)) != Mnil; - plist = mplist_next (plist)) - { - if (key == Mdisplay) - display = (Display *) mplist_value (plist); - else if (key == Mscreen) - screen = mplist_value (plist); - else if (key == Mdrawable) - drawable = (Drawable) mplist_value (plist); - else if (key == Mdepth) - depth = (unsigned) mplist_value (plist); - else if (key == Mwidget) - widget = (Widget) mplist_value (plist); - else if (key == Mcolormap) - cmap = (Colormap) mplist_value (plist); - } + MRealizedFace *rface = from->rface; + MFrame *frame = rface->frame; + Display *display = FRAME_DISPLAY (frame); + MRealizedFont *rfont = rface->rfont; + MRealizedFontXft *rfont_xft = rfont->info; + XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw; + XftColor *xft_color = (! reverse + ? &((GCInfo *) rface->info)->xft_color_fore + : &((GCInfo *) rface->info)->xft_color_back); + int anti_alias = (gstring->control.anti_alias + && FRAME_DEVICE (frame)->depth > 1); + XftFont *xft_font; + MGlyph *g; + FT_UInt *glyphs; + int last_x; + int nglyphs; - if (widget) - { - display = XtDisplay (widget); - screen_num = XScreenNumberOfScreen (XtScreen (widget)); - depth = DefaultDepth (display, screen_num); - } - else if (drawable) - { - Window root_window; - int x, y; - unsigned width, height, border_width; + if (from == to) + return; - if (! display) - MERROR (MERROR_WIN, NULL); - XGetGeometry (display, drawable, &root_window, - &x, &y, &width, &height, &border_width, &depth); - XGetWindowAttributes (display, root_window, &attr); - screen_num = XScreenNumberOfScreen (attr.screen); - } - else + if (anti_alias) { - if (screen) - display = DisplayOfScreen (screen); + if (rfont_xft->font_aa) + xft_font = rfont_xft->font_aa; else { - if (! display) - { - display = XOpenDisplay (NULL); - if (! display) - MERROR (MERROR_WIN, NULL); - auto_display = 1; - } - screen = DefaultScreenOfDisplay (display); - } - screen_num = XScreenNumberOfScreen (screen); - if (! depth) - depth = DefaultDepth (display, screen_num); - } - - if (! cmap) - cmap = DefaultColormap (display, screen_num); - - for (plist = display_info_list; mplist_key (plist) != Mnil; - plist = mplist_next (plist)) - { - disp_info = (MDisplayInfo *) mplist_value (plist); - if (disp_info->display == display) - break; - } - - if (mplist_key (plist) != Mnil) - M17N_OBJECT_REF (disp_info); - else - { - M17N_OBJECT (disp_info, free_display_info, MERROR_WIN); - disp_info->display = display; - disp_info->auto_display = auto_display; - disp_info->font_registry_list = mplist (); - disp_info->iso8859_1_family_list = mplist (); - disp_info->iso10646_1_family_list = mplist (); - disp_info->realized_font_list = mplist (); - find_modifier_bits (disp_info); - mplist_add (display_info_list, Mt, disp_info); - } + double size = rfont->spec.size; - for (plist = device_list; mplist_key (plist) != Mnil; - plist = mplist_next (plist)) - { - device = (MWDevice *) mplist_value (plist); - if (device->display_info == disp_info - && device->depth == depth - && device->cmap == cmap) - break; + xft_font = xft_open_font (display, rfont->spec.file, size / 10, + FcTrue); + if (xft_font) + rfont_xft->font_aa = xft_font; + else + xft_font = rfont->fontp; + } } - - if (mplist_key (plist) != Mnil) - M17N_OBJECT_REF (device); else { - M17N_OBJECT (device, free_device, MERROR_WIN); - device->display_info = disp_info; - device->screen_num = screen_num; - /* A drawable on which to create GCs. */ - device->drawable = XCreatePixmap (display, - RootWindow (display, screen_num), - 1, 1, depth); - device->depth = depth; - device->cmap = cmap; - device->realized_face_list = mplist (); - device->realized_fontset_list = mplist (); - device->foreground = BlackPixel (display, screen_num); - device->background = WhitePixel (display, screen_num); - } - - frame->realized_font_list = disp_info->realized_font_list; - frame->realized_face_list = device->realized_face_list; - frame->realized_fontset_list = device->realized_fontset_list; - - if (widget) - { - AppData app_data; - XtResource resources[] = { - { XtNfont, XtCFont, XtRString, sizeof (String), - XtOffset (AppDataPtr, font), XtRString, - "-misc-fixed-medium-r-normal--*-120-*-*-*-*-iso8859-1" }, - { XtNforeground, XtCForeground, XtRString, sizeof (String), - XtOffset (AppDataPtr, foreground), XtRString, "black" }, - { XtNbackground, XtCBackground, XtRString, sizeof (String), - XtOffset (AppDataPtr, background), XtRString, "white" }, - { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean), - XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE } - }; - MFace *face = NULL; - MFont font; - char **names; - int nfonts; - - XtGetApplicationResources (widget, &app_data, - resources, XtNumber (resources), NULL, 0); - names = XListFonts (display, app_data.font, 1, &nfonts); - if (nfonts == 1) + if (rfont_xft->font_no_aa) + xft_font = rfont_xft->font_no_aa; + else { - if (mwin__parse_font_name (names[0], &font) >= 0) - face = mface_from_font (&font); - else - { - /* The font name does not conform to XLFD. Try to open the - font and get XA_FONT property. */ - XFontStruct *xfont = XLoadQueryFont (display, names[0]); - - if (xfont) - { - unsigned long value; - char *name; + double size = rfont->spec.size; - if (XGetFontProperty (xfont, XA_FONT, &value) - && (name = ((char *) - XGetAtomName (display, (Atom) value)))) - { - if (mwin__parse_font_name (name, &font) >= 0) - face = mface_from_font (&font); - } - XFreeFont (display, xfont); - } - } - XFreeFontNames (names); + xft_font = xft_open_font (display, rfont->spec.file, size / 10, + FcTrue); + if (xft_font) + rfont_xft->font_no_aa = xft_font; + else + xft_font = rfont->fontp; } + } - if (app_data.reverse_video == True) - { - if (! face) - face = mface (); - mface_put_prop (face, Mvideomode, Mreverse); - } - if (face) + XftDrawChange (xft_draw, (Drawable) win); + XftDrawSetClip (xft_draw, (Region) region); + + y -= rfont->baseline_offset; + glyphs = alloca (sizeof (FT_UInt) * (to - from)); + for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width) + { + if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding) + glyphs[nglyphs++] = g->code; + else { - mplist_push (param, Mface, face); - M17N_OBJECT_UNREF (face); + if (nglyphs > 0) + XftDrawGlyphs (xft_draw, xft_color, xft_font, + last_x, y, glyphs, nglyphs); + nglyphs = 0; + XftDrawGlyphs (xft_draw, xft_color, xft_font, + x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1); + last_x = x + g->width; } - device->foreground - = get_color (display, cmap, msymbol (app_data.foreground), Mnil, - device->foreground); - device->background - = get_color (display, cmap, msymbol (app_data.background), Mnil, - device->background); } - XSetErrorHandler (x_error_handler); - /* XSetIOErrorHandler (x_io_error_handler); */ + if (nglyphs > 0) + XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs); +} - return device; +static int +xft_check_capability (MRealizedFont *rfont, MSymbol capability) +{ + MRealizedFontXft *rfont_xft = rfont->info; + int result; + + rfont->info = rfont_xft->info; + result = mfont__ft_driver.check_capability (rfont, capability); + rfont->info = rfont_xft; + return result; } -void +#endif /* HAVE_XFT2 */ + + +/* Functions for the device driver. */ + +static void mwin__close_device (MFrame *frame) { - M17N_OBJECT_UNREF (frame->device); + MWDevice *device = FRAME_DEVICE (frame); + + M17N_OBJECT_UNREF (device); } -void * -mwin__device_get_prop (MWDevice *device, MSymbol key) +static void * +mwin__device_get_prop (MFrame *frame, MSymbol key) { + MWDevice *device = FRAME_DEVICE (frame); + if (key == Mdisplay) return (void *) device->display_info->display; if (key == Mscreen) @@ -1367,202 +1355,156 @@ mwin__device_get_prop (MWDevice *device, MSymbol key) return NULL; } -struct { - int size, inc, used; - GC *gc_table; -} gc_list; - -#define REGISTER_GC(gc) \ - do { \ - if (! gc_list.size) \ - MLIST_INIT1 (&gc_list, gc_table, 100); \ - MLIST_APPEND1 (&gc_list, gc_table, gc, MERROR_WIN); \ - } while (0) - - -#define UNREGISTER_GC(gc) \ - do { \ - int j; \ - for (j = 0; j < gc_list.used; j++) \ - if (gc_list.gc_table[j] == gc) \ - gc_list.gc_table[j] = (GC) NULL; \ - } while (0) - - -void +static void mwin__realize_face (MRealizedFace *rface) { - MFrame *frame = rface->frame; - MWDevice *device = frame->device; - Display *display = FRAME_DISPLAY (frame); - XGCValues values; - int mask = GCForeground | GCBackground; - MSymbol foreground = rface->face.property[MFACE_FOREGROUND]; - MSymbol background = rface->face.property[MFACE_BACKGROUND]; - MFaceHLineProp *hline = rface->hline; - MFaceBoxProp *box = rface->box; - MFaceHookFunc func = (MFaceHookFunc) rface->face.property[MFACE_HOOK_FUNC]; - MSymbol default_foreground - = (MSymbol) mface_get_prop (frame->face, Mforeground); - MSymbol default_background - = (MSymbol) mface_get_prop (frame->face, Mbackground); - GC *gcs; - unsigned long pixel; - - MTABLE_CALLOC (gcs, MFACE_GCS, MERROR_WIN); - - values.foreground = get_color (display, device->cmap, foreground, - default_foreground, device->foreground); - values.background = get_color (display, device->cmap, background, - default_background, device->background); - if (rface->face.property[MFACE_VIDEOMODE] == Mreverse) - pixel = values.foreground, - values.foreground = values.background, - values.background = pixel; - - if (rface->rfont - && rface->rfont->font.property[MFONT_TYPE] - 1 == MFONT_TYPE_WIN) + MFrame *frame; + MSymbol foreground, background, videomode; + MFaceHLineProp *hline; + MFaceBoxProp *box; + GCInfo *info; + + if (rface != rface->ascii_rface) { - values.font = ((MXFontInfo *) (rface->rfont->info))->f->fid; - mask |= GCFont; + rface->info = rface->ascii_rface->info; + return; } - gcs[MFACE_GC_NORMAL] = XCreateGC (display, device->drawable, mask, &values); - REGISTER_GC (gcs[MFACE_GC_NORMAL]); - - gcs[MFACE_GC_SCRATCH] = XCreateGC (display, device->drawable, mask, &values); - REGISTER_GC (gcs[MFACE_GC_SCRATCH]); + frame = rface->frame; + MSTRUCT_CALLOC (info, MERROR_WIN); - pixel = values.foreground; - values.foreground = values.background; - values.background = pixel; - gcs[MFACE_GC_INVERSE] = XCreateGC (display, device->drawable, mask, &values); - REGISTER_GC (gcs[MFACE_GC_INVERSE]); - values.background = values.foreground; - values.foreground = pixel; - - mask &= ~GCFont; - - if (rface == rface->ascii_rface) + foreground = rface->face.property[MFACE_FOREGROUND]; + background = rface->face.property[MFACE_BACKGROUND]; + videomode = rface->face.property[MFACE_VIDEOMODE]; + if (! videomode) + videomode = frame->videomode; + if (videomode != Mreverse) { - /* This realized face is for ASCII. Setup GCs for hline and - box. */ - if (hline && hline->color != foreground) - { - values.foreground - = get_color (display, device->cmap, hline->color, - default_foreground, device->foreground); - gcs[MFACE_GC_HLINE] - = XCreateGC (display, device->drawable, mask, &values); - REGISTER_GC (gcs[MFACE_GC_HLINE]); - values.foreground = pixel; - } - - if (box) - { - if (box->color_top) - { - values.foreground - = get_color (display, device->cmap, box->color_top, - default_foreground, device->foreground); - gcs[MFACE_GC_BOX_TOP] - = XCreateGC (display, device->drawable, mask, &values); - REGISTER_GC (gcs[MFACE_GC_BOX_TOP]); - } - - if (box->color_left - && box->color_left != box->color_top) - { - values.foreground - = get_color (display, device->cmap, box->color_left, - default_foreground, device->foreground); - gcs[MFACE_GC_BOX_LEFT] - = XCreateGC (display, device->drawable, mask, &values); - REGISTER_GC (gcs[MFACE_GC_BOX_LEFT]); - } - - if (box->color_right - && box->color_right != box->color_top) - { - values.foreground - = get_color (display, device->cmap, box->color_right, - default_foreground, device->foreground); - gcs[MFACE_GC_BOX_RIGHT] - = XCreateGC (display, device->drawable, mask, &values); - REGISTER_GC (gcs[MFACE_GC_BOX_RIGHT]); - } - - if (box->color_bottom - && box->color_bottom != box->color_top) - { - values.foreground - = get_color (display, device->cmap, box->color_bottom, - default_foreground, device->foreground); - gcs[MFACE_GC_BOX_BOTTOM] - = XCreateGC (display, device->drawable, mask, &values); - REGISTER_GC (gcs[MFACE_GC_BOX_BOTTOM]); - } - } + info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore); + info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back); } else { - /* This realized face is not for ASCII. GCs for hline and box - are shared with that of the corresponding ASCII face. */ - GC *ascii_gcs = rface->ascii_rface->info; - int i; + info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore); + info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back); + } +#ifdef HAVE_XFT2 + if (foreground == Mnil) + foreground = frame->foreground; + if (background == Mnil) + background = frame->background; + if (videomode == Mreverse) + { + MSymbol temp = foreground; + foreground = background; + background = temp; + } + if (! XftColorAllocName (FRAME_DISPLAY (frame), + FRAME_VISUAL (frame), + FRAME_CMAP (frame), + MSYMBOL_NAME (foreground), + &info->xft_color_fore)) + mdebug_hook (); + if (! XftColorAllocName (FRAME_DISPLAY (frame), + FRAME_VISUAL (frame), + FRAME_CMAP (frame), + MSYMBOL_NAME (background), + &info->xft_color_back)) + mdebug_hook (); +#endif /* HAVE_XFT2 */ + + hline = rface->hline; + if (hline) + { + if (hline->color) + info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL); + else + info->gc[GC_HLINE] = info->gc[GC_NORMAL]; + } + + box = rface->box; + if (box) + { + if (box->color_top) + info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL); + else + info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL]; - for (i = MFACE_GC_HLINE; i < MFACE_GCS; i++) - gcs[i] = ascii_gcs[i]; + if (box->color_left && box->color_left != box->color_top) + info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL); + else + info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP]; + + if (box->color_bottom && box->color_bottom != box->color_top) + info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL); + else + info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP]; + + if (box->color_right && box->color_right != box->color_bottom) + info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL); + else + info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM]; } - rface->info = gcs; - if (func) - (func) (&(rface->face), rface->info, rface->face.property[MFACE_HOOK_ARG]); + rface->info = info; } -void +static void mwin__free_realized_face (MRealizedFace *rface) { - GC *gcs = rface->info; - enum face_gc limit - = rface == rface->ascii_rface ? MFACE_GCS : MFACE_GC_HLINE; - int i; - - for (i = 0; i < limit; i++) - if (gcs[i]) - { - UNREGISTER_GC (gcs[i]); - XFreeGC (FRAME_DISPLAY (rface->frame), gcs[i]); - } - free (gcs); + if (rface == rface->ascii_rface) + free (rface->info); } -void +static void mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface, int reverse, int x, int y, int width, int height, MDrawRegion region) { - GC *gcs = rface->info; - GC gc = gcs[reverse ? MFACE_GC_NORMAL : MFACE_GC_INVERSE]; + GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE]; if (region) - gc = set_region (FRAME_DISPLAY (frame), rface, gc, region); + gc = set_region (frame, gc, region); XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc, x, y, width, height); } -void +static void +mwin__draw_empty_boxes (MDrawWindow win, int x, int y, + MGlyphString *gstring, MGlyph *from, MGlyph *to, + int reverse, MDrawRegion region) +{ + MRealizedFace *rface = from->rface; + Display *display = FRAME_DISPLAY (rface->frame); + GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL]; + + if (from == to) + return; + + if (region) + gc = set_region (rface->frame, gc, region); + for (; from < to; from++) + { + XDrawRectangle (display, (Window) win, gc, + x, y - gstring->ascent + 1, from->width - 1, + gstring->ascent + gstring->descent - 2); + x += from->width; + } +} + + +static void mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring, MRealizedFace *rface, int reverse, int x, int y, int width, MDrawRegion region) { enum MFaceHLineType type = rface->hline->type; - GC *gcs = rface->info; - GC gc; + GCInfo *info = rface->info; + GC gc = gc = info->gc[GC_HLINE]; int i; y = (type == MFACE_HLINE_BOTTOM @@ -1572,15 +1514,8 @@ mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring, : type == MFACE_HLINE_STRIKE_THROUGH ? y - ((gstring->ascent + gstring->descent) / 2) : y - gstring->text_ascent); - if (reverse) - gc = gcs[MFACE_GC_INVERSE]; - else if (gcs[MFACE_GC_HLINE]) - gc = gcs[MFACE_GC_HLINE]; - else - gc = gcs[MFACE_GC_NORMAL]; - if (region) - gc = set_region (FRAME_DISPLAY (frame), rface, gc, region); + gc = set_region (frame, gc, region); for (i = 0; i < rface->hline->width; i++) XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc, @@ -1588,14 +1523,14 @@ mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring, } -void +static void mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring, MGlyph *g, int x, int y, int width, MDrawRegion region) { Display *display = FRAME_DISPLAY (frame); MRealizedFace *rface = g->rface; MFaceBoxProp *box = rface->box; - GC *gcs = rface->info; + GCInfo *info = rface->info; GC gc_top, gc_left, gc_right, gc_btm; int y0, y1; int i; @@ -1605,14 +1540,13 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring, y1 = y + (gstring->text_descent + rface->box->inner_vmargin + rface->box->width - 1); - gc_top = gcs[MFACE_GC_BOX_TOP]; - if (! gc_top) - gc_top = gcs[MFACE_GC_NORMAL]; + gc_top = info->gc[GC_BOX_TOP]; if (region) - gc_top = set_region (FRAME_DISPLAY (frame), rface, gc_top, region); - gc_btm = gcs[MFACE_GC_BOX_BOTTOM]; - if (! gc_btm) + gc_top = set_region (frame, gc_top, region); + if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM]) gc_btm = gc_top; + else + gc_btm = info->gc[GC_BOX_BOTTOM]; if (g->type == GLYPH_BOX) { @@ -1628,19 +1562,22 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring, XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i); /* Draw the bottom side. */ - if (region) - gc_btm = set_region (display, rface, gc_btm, region); + if (region && gc_btm != gc_top) + gc_btm = set_region (frame, gc_btm, region); for (i = 0; i < box->width; i++) XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i); if (g->left_padding > 0) { /* Draw the left side. */ - gc_left = gcs[MFACE_GC_BOX_LEFT]; - if (! gc_left) + if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP]) gc_left = gc_top; - else if (region) - gc_left = set_region (display, rface, gc_left, region); + else + { + gc_left = info->gc[GC_BOX_LEFT]; + if (region) + gc_left = set_region (frame, gc_left, region); + } for (i = 0; i < rface->box->width; i++) XDrawLine (display, (Window) win, gc_left, x0 + i, y0 + i, x0 + i, y1 - i); @@ -1648,11 +1585,14 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring, else { /* Draw the right side. */ - gc_right = gcs[MFACE_GC_BOX_RIGHT]; - if (! gc_right) + if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP]) gc_right = gc_top; - else if (region) - gc_right = set_region (display, rface, gc_right, region); + else + { + gc_right = info->gc[GC_BOX_RIGHT]; + if (region) + gc_right = set_region (frame, gc_right, region); + } for (i = 0; i < rface->box->width; i++) XDrawLine (display, (Window) win, gc_right, x1 - i, y0 + i, x1 - i, y1 - i); @@ -1666,8 +1606,8 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring, x, y0 + i, x + width - 1, y0 + i); /* Draw the bottom side. */ - if (region) - gc_btm = set_region (display, rface, gc_btm, region); + if (region && gc_btm != gc_top) + gc_btm = set_region (frame, gc_btm, region); for (i = 0; i < box->width; i++) XDrawLine (display, (Window) win, gc_btm, x, y1 - i, x + width - 1, y1 - i); @@ -1675,7 +1615,8 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring, } -void +#if 0 +static void mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface, int reverse, int x, int y, int width, int height, int row_bytes, unsigned char *bmp, @@ -1683,20 +1624,38 @@ mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface, { Display *display = FRAME_DISPLAY (frame); int i, j; - GC *gcs = rface->info; - GC gc = gcs[reverse ? MFACE_GC_INVERSE : MFACE_GC_NORMAL]; + GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL]; if (region) - gc = set_region (FRAME_DISPLAY (frame), rface, gc, region); + gc = set_region (frame, gc, region); for (i = 0; i < height; i++, bmp += row_bytes) for (j = 0; j < width; j++) if (bmp[j / 8] & (1 << (7 - (j % 8)))) XDrawPoint (display, (Window) win, gc, x + j, y + i); } +#endif +static void +mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface, + int intensity, MDrawPoint *points, int num, + MDrawRegion region) +{ + GCInfo *info = rface->info; + GC gc; -MDrawRegion + if (! (gc = info->gc[intensity])) + gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame), + info, intensity); + if (region) + gc = set_region (frame, gc, region); + + XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc, + (XPoint *) points, num, CoordModeOrigin); +} + + +static MDrawRegion mwin__region_from_rect (MDrawMetric *rect) { MDrawRegion region1 = XCreateRegion (); @@ -1712,7 +1671,7 @@ mwin__region_from_rect (MDrawMetric *rect) return region2; } -void +static void mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect) { MDrawRegion region1 = XCreateRegion (); @@ -1728,7 +1687,7 @@ mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect) XDestroyRegion (region1); } -void +static void mwin__intersect_region (MDrawRegion region1, MDrawRegion region2) { MDrawRegion region = XCreateRegion (); @@ -1738,7 +1697,7 @@ mwin__intersect_region (MDrawRegion region1, MDrawRegion region2) XDestroyRegion (region); } -void +static void mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect) { MDrawRegion region1 = XCreateRegion (); @@ -1752,7 +1711,7 @@ mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect) XDestroyRegion (region1); } -void +static void mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect) { XRectangle xrect; @@ -1764,13 +1723,13 @@ mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect) rect->height = xrect.height; } -void +static void mwin__free_region (MDrawRegion region) { XDestroyRegion (region); } -void +static void mwin__dump_region (MDrawRegion region) { XRectangle rect; @@ -1778,58 +1737,57 @@ mwin__dump_region (MDrawRegion region) fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height); } -void -mwin__verify_region (MFrame *frame, MDrawRegion region) -{ - set_region (FRAME_DISPLAY (frame), frame->rface, - ((GC *) frame->rface->info)[MFACE_GC_NORMAL], region); -} -MDrawWindow +static MDrawWindow mwin__create_window (MFrame *frame, MDrawWindow parent) { - MWDevice *device = frame->device; Display *display = FRAME_DISPLAY (frame); - int screen = FRAME_SCREEN (frame); Window win; XWMHints wm_hints = { InputHint, False }; XClassHint class_hints = { "M17N-IM", "m17n-im" }; - XSetWindowAttributes attrs; + XSetWindowAttributes set_attrs; unsigned long mask; - MSymbol background = mface_get_prop (frame->face, Mbackground); - - attrs.background_pixel = get_color (display, device->cmap, - background, background, - WhitePixel (display, screen)); - attrs.backing_store = Always; - attrs.override_redirect = True; - attrs.save_under = True; - mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder; + XGCValues values; + GCInfo *info = frame->rface->info; + if (! parent) - parent = (MDrawWindow) RootWindow (display, screen); + parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame)); + mask = GCForeground; + XGetGCValues (display, info->gc[GC_INVERSE], mask, &values); + set_attrs.background_pixel = values.foreground; + set_attrs.backing_store = Always; + set_attrs.override_redirect = True; + set_attrs.save_under = True; + mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder; win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0, CopyFromParent, InputOutput, CopyFromParent, - mask, &attrs); + mask, &set_attrs); XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0, NULL, &wm_hints, &class_hints); XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask); return (MDrawWindow) win; } -void +static void mwin__destroy_window (MFrame *frame, MDrawWindow win) { +#ifdef HAVE_XFT2 + XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw; + + if (XftDrawDrawable (xft_draw) == (Drawable) win) + XftDrawChange (xft_draw, FRAME_DEVICE (frame)->drawable); +#endif /* HAVE_XFT2 */ XDestroyWindow (FRAME_DISPLAY (frame), (Window) win); } #if 0 -MDrawWindow +static MDrawWindow mwin__event_window (void *event) { return ((MDrawWindow) ((XEvent *) event)->xany.window); } -void +static void mwin__print_event (void *arg, char *win_name) { char *event_name; @@ -1877,19 +1835,19 @@ mwin__print_event (void *arg, char *win_name) } #endif -void +static void mwin__map_window (MFrame *frame, MDrawWindow win) { XMapRaised (FRAME_DISPLAY (frame), (Window) win); } -void +static void mwin__unmap_window (MFrame *frame, MDrawWindow win) { XUnmapWindow (FRAME_DISPLAY (frame), (Window) win); } -void +static void mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win, MDrawMetric *geometry) { @@ -1922,7 +1880,7 @@ mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win, } } -void +static void mwin__adjust_window (MFrame *frame, MDrawWindow win, MDrawMetric *current, MDrawMetric *new) { @@ -1957,13 +1915,14 @@ mwin__adjust_window (MFrame *frame, MDrawWindow win, } if (mask) XConfigureWindow (display, (Window) win, mask, &values); + XClearWindow (display, (Window) win); } -MSymbol +static MSymbol mwin__parse_event (MFrame *frame, void *arg, int *modifiers) { XEvent *event = (XEvent *) arg; - MDisplayInfo *disp_info = frame->device->display_info; + MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info; int len; char buf[512]; KeySym keysym; @@ -1977,24 +1936,16 @@ mwin__parse_event (MFrame *frame, void *arg, int *modifiers) len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL); if (len > 1) return Mnil; - if (len == 1) + if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R) + return Mnil; + if (len == 1 && keysym >= XK_space && keysym <= XK_asciitilde) { - int c = buf[0]; + int c = keysym; - if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask) - *modifiers |= MINPUT_KEY_SHIFT_MODIFIER; - if (((XKeyEvent *) event)->state & ControlMask) - { - c &= 0x1F; - if (((XKeyEvent *) event)->state & ShiftMask) - *modifiers |= MINPUT_KEY_SHIFT_MODIFIER; - } - if (((XKeyEvent *) event)->state & disp_info->meta_mask) - c |= 0x80; key = minput__char_to_key (c); + if (c == ' ' && ((XKeyEvent *) event)->state & ShiftMask) + *modifiers |= MINPUT_KEY_SHIFT_MODIFIER; } - else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R) - return Mnil; else { char *str = XKeysymToString (keysym); @@ -2004,9 +1955,9 @@ mwin__parse_event (MFrame *frame, void *arg, int *modifiers) key = msymbol (str); if (((XKeyEvent *) event)->state & ShiftMask) *modifiers |= MINPUT_KEY_SHIFT_MODIFIER; - if (((XKeyEvent *) event)->state & ControlMask) - *modifiers |= MINPUT_KEY_CONTROL_MODIFIER; } + if (((XKeyEvent *) event)->state & ControlMask) + *modifiers |= MINPUT_KEY_CONTROL_MODIFIER; if (((XKeyEvent *) event)->state & disp_info->meta_mask) *modifiers |= MINPUT_KEY_META_MODIFIER; if (((XKeyEvent *) event)->state & disp_info->alt_mask) @@ -2020,66 +1971,574 @@ mwin__parse_event (MFrame *frame, void *arg, int *modifiers) } -MText * -mwin__get_selection_text (MFrame *frame) -{ - return NULL; -} - - void mwin__dump_gc (MFrame *frame, MRealizedFace *rface) { unsigned long valuemask = GCForeground | GCBackground | GCClipMask; XGCValues values; Display *display = FRAME_DISPLAY (frame); - GC *gcs = rface->info; + GCInfo *info = rface->info; int i; - for (i = 0; i <= MFACE_GC_SCRATCH; i++) + for (i = 0; i <= GC_INVERSE; i++) { - XGetGCValues (display, gcs[i], valuemask, &values); + XGetGCValues (display, info->gc[i], valuemask, &values); fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i, values.foreground, values.background); fprintf (stderr, "\n"); } } -/*** @} */ -#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ +static MDeviceDriver x_driver = + { + mwin__close_device, + mwin__device_get_prop, + mwin__realize_face, + mwin__free_realized_face, + mwin__fill_space, + mwin__draw_empty_boxes, + mwin__draw_hline, + mwin__draw_box, + mwin__draw_points, + mwin__region_from_rect, + mwin__union_rect_with_region, + mwin__intersect_region, + mwin__region_add_rect, + mwin__region_to_rect, + mwin__free_region, + mwin__dump_region, + mwin__create_window, + mwin__destroy_window, + mwin__map_window, + mwin__unmap_window, + mwin__window_geometry, + mwin__adjust_window, + mwin__parse_event + }; + +/* Functions to be stored in MDeviceLibraryInterface by dlsym (). */ + +int +device_init () +{ + M_iso8859_1 = msymbol ("iso8859-1"); + M_iso10646_1 = msymbol ("iso10646-1"); + + display_info_list = mplist (); + device_list = mplist (); + +#ifdef HAVE_XFT2 + xft_driver.select = mfont__ft_driver.select; + xft_driver.list = mfont__ft_driver.list; + xft_driver.list_family_names = mfont__ft_driver.list_family_names; +#endif + + Mxim = msymbol ("xim"); + msymbol_put (Mxim, Minput_driver, &minput_xim_driver); + + return 0; +} + +int +device_fini () +{ + M17N_OBJECT_UNREF (display_info_list); + M17N_OBJECT_UNREF (device_list); + return 0; +} + + +#ifdef X_SET_ERROR_HANDLER +static int +x_error_handler (Display *display, XErrorEvent *error) +{ + mdebug_hook (); + return 0; +} + +static int +x_io_error_handler (Display *display) +{ + mdebug_hook (); + return 0; +} +#endif + +/** Return an MWDevice object corresponding to a display specified in + PLIST. + + It searches device_list for a device matching the display. If + found, return the found object. Otherwise, return a newly created + object. */ + +int +device_open (MFrame *frame, MPlist *param) +{ + Display *display = NULL; + Screen *screen = NULL; + int screen_num; + Drawable drawable = 0; + Widget widget = NULL; + Colormap cmap = 0; + int auto_display = 0; + MDisplayInfo *disp_info = NULL; + MWDevice *device = NULL; + MSymbol key; + XWindowAttributes attr; + unsigned depth = 0; + MPlist *plist; + AppData app_data; + MFont *font = NULL; + MFace *face; + int use_xfont = 0, use_freetype = 0, use_xft = 0; + + for (plist = param; (key = mplist_key (plist)) != Mnil; + plist = mplist_next (plist)) + { + if (key == Mdisplay) + display = (Display *) mplist_value (plist); + else if (key == Mscreen) + screen = mplist_value (plist); + else if (key == Mdrawable) + drawable = (Drawable) mplist_value (plist); + else if (key == Mdepth) + depth = (unsigned) mplist_value (plist); + else if (key == Mwidget) + widget = (Widget) mplist_value (plist); + else if (key == Mcolormap) + cmap = (Colormap) mplist_value (plist); + else if (key == Mfont) + { + MSymbol val = MPLIST_SYMBOL (plist); + + if (val == Mx) + use_xfont = 1; +#ifdef HAVE_FREETYPE + else if (val == Mfreetype) + use_freetype = 1; +#ifdef HAVE_XFT2 + else if (val == Mxft) + use_xft = 1; +#endif +#endif + } + } + + /* If none of them is specified, use all of them. */ + if (! use_xfont && ! use_freetype && ! use_xft) + use_xfont = use_freetype = use_xft = 1; + + if (widget) + { + display = XtDisplay (widget); + screen_num = XScreenNumberOfScreen (XtScreen (widget)); + depth = DefaultDepth (display, screen_num); + } + else if (drawable) + { + Window root_window; + int x, y; + unsigned width, height, border_width; + + if (! display) + MERROR (MERROR_WIN, -1); + XGetGeometry (display, drawable, &root_window, + &x, &y, &width, &height, &border_width, &depth); + XGetWindowAttributes (display, root_window, &attr); + screen_num = XScreenNumberOfScreen (attr.screen); + } + else + { + if (screen) + display = DisplayOfScreen (screen); + else + { + if (! display) + { + display = XOpenDisplay (NULL); + if (! display) + MERROR (MERROR_WIN, -1); + auto_display = 1; + } + screen = DefaultScreenOfDisplay (display); + } + screen_num = XScreenNumberOfScreen (screen); + if (! depth) + depth = DefaultDepth (display, screen_num); + } + + if (! cmap) + cmap = DefaultColormap (display, screen_num); + + for (plist = display_info_list; mplist_key (plist) != Mnil; + plist = mplist_next (plist)) + { + disp_info = (MDisplayInfo *) mplist_value (plist); + if (disp_info->display == display) + break; + } + + if (mplist_key (plist) != Mnil) + M17N_OBJECT_REF (disp_info); + else + { + M17N_OBJECT (disp_info, free_display_info, MERROR_WIN); + disp_info->display = display; + disp_info->auto_display = auto_display; + disp_info->font_list = mplist (); + find_modifier_bits (disp_info); + disp_info->MULE_BASELINE_OFFSET + = XInternAtom (display, "_MULE_BASELINE_OFFSET", False); + disp_info->AVERAGE_WIDTH + = XInternAtom (display, "AVERAGE_WIDTH", False); + mplist_add (display_info_list, Mt, disp_info); + } + + for (plist = device_list; mplist_key (plist) != Mnil; + plist = mplist_next (plist)) + { + device = (MWDevice *) mplist_value (plist); + if (device->display_info == disp_info + && device->depth == depth + && device->cmap == cmap + && device->screen_num == screen_num) + break; + } + + if (mplist_key (plist) != Mnil) + M17N_OBJECT_REF (device); + else + { + unsigned long valuemask = GCForeground; + XGCValues values; + double pixels, mm; + + M17N_OBJECT (device, free_device, MERROR_WIN); + device->display_info = disp_info; + device->screen_num = screen_num; + /* A drawable on which to create GCs. */ + device->drawable = XCreatePixmap (display, + RootWindow (display, screen_num), + 1, 1, depth); + device->depth = depth; + device->cmap = cmap; + pixels = DisplayHeight (display, screen_num); + mm = DisplayHeightMM (display, screen_num); + device->resy = (mm < 1) ? 100 : pixels * 25.4 / mm; + device->realized_face_list = mplist (); + device->realized_font_list = mplist (); + mplist_add (device->realized_font_list, Mt, NULL); + device->realized_fontset_list = mplist (); + device->gc_list = mplist (); + values.foreground = BlackPixel (display, screen_num); + device->scratch_gc = XCreateGC (display, device->drawable, + valuemask, &values); +#ifdef HAVE_XFT2 + device->xft_draw = XftDrawCreate (display, device->drawable, + DefaultVisual (display, screen_num), + cmap); +#endif + } + + frame->device = device; + frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT; + frame->dpi = device->resy; + frame->driver = &x_driver; + frame->font_driver_list = mplist (); +#ifdef HAVE_XFT2 + if (use_xft) + { + mplist_add (frame->font_driver_list, Mfreetype, &xft_driver); + use_freetype = 0; + } +#endif /* HAVE_XFT2 */ +#ifdef HAVE_FREETYPE + if (use_freetype) + mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver); +#endif /* HAVE_FREETYPE */ + if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list)) + mplist_push (frame->font_driver_list, Mx, &xfont_driver); + + frame->realized_font_list = device->realized_font_list; + frame->realized_face_list = device->realized_face_list; + frame->realized_fontset_list = device->realized_fontset_list; + + if (widget) + { + XtResource resources[] = { + { XtNfont, XtCFont, XtRString, sizeof (String), + XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT }, + { XtNforeground, XtCForeground, XtRString, sizeof (String), + XtOffset (AppDataPtr, foreground), XtRString, "black" }, + { XtNbackground, XtCBackground, XtRString, sizeof (String), + XtOffset (AppDataPtr, background), XtRString, "white" }, + { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean), + XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE } + }; + + XtGetApplicationResources (widget, &app_data, + resources, XtNumber (resources), NULL, 0); + frame->foreground = msymbol (app_data.foreground); + frame->background = msymbol (app_data.background); + frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal; + } + else + { + app_data.font = DEFAULT_FONT; + frame->foreground = msymbol ("black"); + frame->background = msymbol ("white"); + frame->videomode = Mnormal; + } + + if (strcmp (app_data.font, DEFAULT_FONT) != 0) + { + XFontStruct *xfont = XLoadQueryFont (display, app_data.font); + unsigned long value; + char *name; + + if (xfont) + { + font = mfont_parse_name (app_data.font, Mx); + if (! font + && XGetFontProperty (xfont, XA_FONT, &value) + && (name = ((char *) XGetAtomName (display, (Atom) value)))) + font = mfont_parse_name (name, Mx); + XFreeFont (display, xfont); + } + } + if (! font) + font = mfont_parse_name (DEFAULT_FONT, Mx); + else if (! font->size) + font->size = 130; + face = mface_from_font (font); + free (font); + face->property[MFACE_FONTSET] = mfontset (NULL); + face->property[MFACE_FOREGROUND] = frame->foreground; + face->property[MFACE_BACKGROUND] = frame->background; + mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline)); + mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox)); + face->property[MFACE_VIDEOMODE] = frame->videomode; + mface_put_prop (face, Mhook_func, + mface_get_prop (mface__default, Mhook_func)); + face->property[MFACE_RATIO] = (void *) 100; + mplist_push (param, Mface, face); + M17N_OBJECT_UNREF (face); + +#ifdef X_SET_ERROR_HANDLER + XSetErrorHandler (x_error_handler); + XSetIOErrorHandler (x_io_error_handler); +#endif + return 0; +} + -/* External API */ -/*=*/ -/*** @addtogroup m17nFrame */ -/*** @{ */ -/*=*/ +/* XIM (X Input Method) handler */ -/***en - @name Variables: Keys of frame parameter (X specific). +typedef struct MInputXIMMethodInfo +{ + Display *display; + XIM xim; + MSymbol language; + MSymbol coding; +} MInputXIMMethodInfo; - These are the symbols to use as parameter keys for the function - mframe () (which see). They are also keys of a frame property - (except for #Mwidget). */ +typedef struct MInputXIMContextInfo +{ + XIC xic; + Window win; + MConverter *converter; +} MInputXIMContextInfo; + +static int +xim_open_im (MInputMethod *im) +{ + MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg; + MLocale *saved, *this; + char *save_modifier_list; + XIM xim; + MInputXIMMethodInfo *im_info; + + saved = mlocale_set (LC_CTYPE, NULL); + this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : ""); + if (! this) + /* The specified locale is not supported. */ + MERROR (MERROR_LOCALE, -1); + if (mlocale_get_prop (this, Mcoding) == Mnil) + { + /* Unable to decode the output of XIM. */ + mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname))); + MERROR (MERROR_LOCALE, -1); + } + + if (arg->modifier_list) + save_modifier_list = XSetLocaleModifiers (arg->modifier_list); + else + save_modifier_list = XSetLocaleModifiers (""); + if (! save_modifier_list) + { + /* The specified locale is not supported by X. */ + mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname))); + MERROR (MERROR_LOCALE, -1); + } + + xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class); + if (! xim) + { + /* No input method is available in the current locale. */ + XSetLocaleModifiers (save_modifier_list); + mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname))); + MERROR (MERROR_WIN, -1); + } + + MSTRUCT_MALLOC (im_info, MERROR_WIN); + im_info->display = arg->display; + im_info->xim = xim; + im_info->language = mlocale_get_prop (this, Mlanguage); + im_info->coding = mlocale_get_prop (this, Mcoding); + im->info = im_info; + + XSetLocaleModifiers (save_modifier_list); + mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname))); + + return 0; +} + +static void +xim_close_im (MInputMethod *im) +{ + MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info; + + XCloseIM (im_info->xim); + free (im_info); +} + +static int +xim_create_ic (MInputContext *ic) +{ + MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg; + MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info; + MInputXIMContextInfo *ic_info; + XIC xic; + + if (! arg->input_style) + { + /* By default, use Root style. */ + arg->input_style = XIMPreeditNothing | XIMStatusNothing; + arg->preedit_attrs = NULL; + arg->status_attrs = NULL; + } + + if (! arg->preedit_attrs && ! arg->status_attrs) + xic = XCreateIC (im_info->xim, + XNInputStyle, arg->input_style, + XNClientWindow, arg->client_win, + XNFocusWindow, arg->focus_win, + NULL); + else if (arg->preedit_attrs && ! arg->status_attrs) + xic = XCreateIC (im_info->xim, + XNInputStyle, arg->input_style, + XNClientWindow, arg->client_win, + XNFocusWindow, arg->focus_win, + XNPreeditAttributes, arg->preedit_attrs, + NULL); + else if (! arg->preedit_attrs && arg->status_attrs) + xic = XCreateIC (im_info->xim, + XNInputStyle, arg->input_style, + XNClientWindow, arg->client_win, + XNFocusWindow, arg->focus_win, + XNStatusAttributes, arg->status_attrs, + NULL); + else + xic = XCreateIC (im_info->xim, + XNInputStyle, arg->input_style, + XNClientWindow, arg->client_win, + XNFocusWindow, arg->focus_win, + XNPreeditAttributes, arg->preedit_attrs, + XNStatusAttributes, arg->status_attrs, + NULL); + if (! xic) + MERROR (MERROR_WIN, -1); + + MSTRUCT_MALLOC (ic_info, MERROR_WIN); + ic_info->xic = xic; + ic_info->win = arg->focus_win; + ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0); + ic->info = ic_info; + return 0; +} + +static void +xim_destroy_ic (MInputContext *ic) +{ + MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info; + + XDestroyIC (ic_info->xic); + mconv_free_converter (ic_info->converter); + free (ic_info); + ic->info = NULL; +} + +static int +xim_filter (MInputContext *ic, MSymbol key, void *event) +{ + MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info; + + return (XFilterEvent ((XEvent *) event, ic_info->win) == True); +} + + +static int +xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt) +{ + MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info; + MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info; + XKeyPressedEvent *ev = (XKeyPressedEvent *) arg; + KeySym keysym; + Status status; + char *buf; + int len; + + buf = (char *) alloca (512); + len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status); + if (status == XBufferOverflow) + { + buf = (char *) alloca (len); + len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status); + } + + mtext_reset (ic->produced); + if (len == 0) + return 1; + + mconv_reset_converter (ic_info->converter); + mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len); + mconv_decode (ic_info->converter, ic->produced); + mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced), + Mlanguage, (void *) im_info->language); + mtext_cpy (mt, ic->produced); + mtext_reset (ic->produced); + return 0; +} + + /*=*/ -/*** @{ */ -/* Keywords for mwin__open_device (). */ -MSymbol Mdisplay, Mscreen, Mdrawable, Mdepth, Mwidget, Mcolormap; /*** @} */ -/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + +/* External API */ -/*=*/ /*** @addtogroup m17nInputMethodWin */ -/*=*/ + /*** @{ */ /***en - @brief Input driver for XIM. + @brief Input method driver for XIM. - The input driver #minput_xim_driver is for the foreign input - method of name #Mxim. It uses XIM (X Input Methods) as a - background input engine. + The driver #minput_xim_driver is for the foreign input method of + name #Mxim. It uses XIM (X Input Methods) as a background input + engine. As the symbol #Mxim has property #Minput_driver whose value is a pointer to this driver, the input method of language #Mnil @@ -2090,11 +2549,11 @@ MSymbol Mdisplay, Mscreen, Mdrawable, Mdepth, Mwidget, Mcolormap; The argument $ARG of the function minput_open_im () must be a pointer to the structure #MInputXIMArgIM. See the documentation - of #MInputXIMArgIM for more detail. + of #MInputXIMArgIM for more details. The argument $ARG of the function minput_create_ic () must be a pointer to the structure #MInputXIMArgIC. See the documentation - of #MInputXIMArgIC for more detail. + of #MInputXIMArgIC for more details. The argument $ARG of the function minput_filter () must be a pointer to the structure @c XEvent. The argument $KEY is ignored. @@ -2104,50 +2563,41 @@ MSymbol Mdisplay, Mscreen, Mdrawable, Mdepth, Mwidget, Mcolormap; $KEY is ignored. */ /***ja - @brief XIMÍÑÆþÎϥɥ饤¥Ð + @brief XIMÍÑÆþÎϥɥ饤¥Ð. - ÆþÎϥɥ饤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°Éô - ÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤Î - ÆþÎÏ¥¨¥ó¥¸¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£ + ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ê¡¢ + XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£ ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£ - #Minput_driver ¤ò»ý¤Ä¤¿¤á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç - ¤¢¤ëÆþÎϥ᥽¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£ + #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim + ¤Ç¤¢¤ëÆþÎϥ᥽¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£ - ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥ÉÍѤˤϡ¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä - °Ê²¼¤Î´Ø¿ô·²¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é - ¤Ê¤¤¡£ + ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ + ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ - ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM ¤Ø¤Î - ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤Î¥É - ¥­¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£ + ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIM + ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò»²¾È¡£ - ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC ¤Ø - ¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤Î - ¥É¥­¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£ + ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ #MInputXIMArgIC + ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ¤ò»²¾È¡£ - ´Ø¿ô minput_filter () ¤Î°ú¿ô %ARG ¤Ï¹½Â¤ÂÎ @c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿ - ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£ + ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂÎ @c XEvent + ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£ ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter () - ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì - ¤ë¡£ */ + ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì¤ë¡£ */ MInputDriver minput_xim_driver = { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic, xim_filter, xim_lookup, NULL }; -/*=*/ - -/***en - @brief Symbol of the name "xim". +/*** @} */ - The variable Mxim is a symbol of name "xim". It is a name of the - input method driver #minput_xim_driver. */ +#else /* not HAVE_X11 */ -MSymbol Mxim; +int device_open () { return -1; } -/*** @} */ +#endif /* not HAVE_X11 */ /* Local Variables: