diff --git a/caca/driver/x11.c b/caca/driver/x11.c index 97a401b..275a4bc 100644 --- a/caca/driver/x11.c +++ b/caca/driver/x11.c @@ -24,7 +24,7 @@ #include #include #include -#if defined(HAVE_X11_XKBLIB_H) +#if defined HAVE_X11_XKBLIB_H # include #endif @@ -52,13 +52,16 @@ struct driver_private long int event_mask; int font_width, font_height; int colors[4096]; +#if defined X_HAVE_UTF8_STRING + XFontSet font_set; +#endif Font font; XFontStruct *font_struct; int font_offset; Cursor pointer; Atom wm_protocols; Atom wm_delete_window; -#if defined(HAVE_X11_XKBLIB_H) +#if defined HAVE_X11_XKBLIB_H Bool autorepeat; #endif uint32_t max_char; @@ -77,6 +80,9 @@ static int x11_init_graphics(caca_display_t *dp) { Colormap colormap; XSetWindowAttributes x11_winattr; +#if defined X_HAVE_UTF8_STRING + XVaNestedList list; +#endif int (*old_error_handler)(Display *, XErrorEvent *); char const *fonts[] = { NULL, "8x13bold", "fixed", NULL }, **parser; char const *geometry; @@ -86,7 +92,7 @@ static int x11_init_graphics(caca_display_t *dp) dp->drv.p = malloc(sizeof(struct driver_private)); -#if defined(HAVE_GETENV) +#if defined HAVE_GETENV geometry = getenv("CACA_GEOMETRY"); if(geometry && *geometry) sscanf(geometry, "%ux%u", &width, &height); @@ -103,7 +109,7 @@ static int x11_init_graphics(caca_display_t *dp) if(dp->drv.p->dpy == NULL) return -1; -#if defined(HAVE_GETENV) +#if defined HAVE_GETENV fonts[0] = getenv("CACA_FONT"); if(fonts[0] && *fonts[0]) parser = fonts; @@ -117,6 +123,11 @@ static int x11_init_graphics(caca_display_t *dp) /* Parse our font list */ for( ; ; parser++) { +#if defined X_HAVE_UTF8_STRING + char **missing_charset_list; + char *def_string; + int missing_charset_count; +#endif uint32_t font_max_char; if(!*parser) @@ -126,6 +137,33 @@ static int x11_init_graphics(caca_display_t *dp) return -1; } +#if defined X_HAVE_UTF8_STRING + dp->drv.p->font_set = XCreateFontSet(dp->drv.p->dpy, *parser, + &missing_charset_list, + &missing_charset_count, + &def_string); + if (missing_charset_list) + XFreeStringList(missing_charset_list); + + if (!dp->drv.p->font_set || missing_charset_count) + { + char buf[BUFSIZ]; + + if (dp->drv.p->font_set) + XFreeFontSet(dp->drv.p->dpy, dp->drv.p->font_set); + snprintf(buf, BUFSIZ - 1, "%s,*", *parser); + dp->drv.p->font_set = XCreateFontSet(dp->drv.p->dpy, buf, + &missing_charset_list, + &missing_charset_count, + &def_string); + if (missing_charset_list) + XFreeStringList(missing_charset_list); + } + + if (dp->drv.p->font_set) + break; +#endif + dp->drv.p->font = XLoadFont(dp->drv.p->dpy, *parser); if(!dp->drv.p->font) continue; @@ -160,27 +198,42 @@ static int x11_init_graphics(caca_display_t *dp) /* Reset the default X11 error handler */ XSetErrorHandler(old_error_handler); - dp->drv.p->font_width = 0; - if(dp->drv.p->font_struct->per_char - && !dp->drv.p->font_struct->min_byte1 - && dp->drv.p->font_struct->min_char_or_byte2 <= 0x21 - && dp->drv.p->font_struct->max_char_or_byte2 >= 0x7e) + /* Set font width to the largest character in the set */ +#if defined X_HAVE_UTF8_STRING + if (dp->drv.p->font_set) + { + XFontSetExtents *ex = XExtentsOfFontSet(dp->drv.p->font_set); + dp->drv.p->font_width = + XmbTextEscapement(dp->drv.p->font_set, "CAca", 4) / 4; + dp->drv.p->font_height = ex->max_logical_extent.height; + dp->drv.p->font_offset = ex->max_logical_extent.height + + ex->max_logical_extent.y; + } + else +#endif { - for(i = 0x21; i < 0x7f; i++) + dp->drv.p->font_width = 0; + if(dp->drv.p->font_struct->per_char + && !dp->drv.p->font_struct->min_byte1 + && dp->drv.p->font_struct->min_char_or_byte2 <= 0x21 + && dp->drv.p->font_struct->max_char_or_byte2 >= 0x7e) { - int cw = dp->drv.p->font_struct->per_char[i - - dp->drv.p->font_struct->min_char_or_byte2].width; - if(cw > dp->drv.p->font_width) - dp->drv.p->font_width = cw; + for(i = 0x21; i < 0x7f; i++) + { + int cw = dp->drv.p->font_struct->per_char[i + - dp->drv.p->font_struct->min_char_or_byte2].width; + if(cw > dp->drv.p->font_width) + dp->drv.p->font_width = cw; + } } - } - if(!dp->drv.p->font_width) - dp->drv.p->font_width = dp->drv.p->font_struct->max_bounds.width; + if(!dp->drv.p->font_width) + dp->drv.p->font_width = dp->drv.p->font_struct->max_bounds.width; - dp->drv.p->font_height = dp->drv.p->font_struct->max_bounds.ascent - + dp->drv.p->font_struct->max_bounds.descent; - dp->drv.p->font_offset = dp->drv.p->font_struct->max_bounds.descent; + dp->drv.p->font_height = dp->drv.p->font_struct->max_bounds.ascent + + dp->drv.p->font_struct->max_bounds.descent; + dp->drv.p->font_offset = dp->drv.p->font_struct->max_bounds.descent; + } colormap = DefaultColormap(dp->drv.p->dpy, DefaultScreen(dp->drv.p->dpy)); for(i = 0x000; i < 0x1000; i++) @@ -221,7 +274,10 @@ static int x11_init_graphics(caca_display_t *dp) dp->drv.p->gc = XCreateGC(dp->drv.p->dpy, dp->drv.p->window, 0, NULL); XSetForeground(dp->drv.p->dpy, dp->drv.p->gc, dp->drv.p->colors[0x888]); - XSetFont(dp->drv.p->dpy, dp->drv.p->gc, dp->drv.p->font); +#if defined X_HAVE_UTF8_STRING + if (!dp->drv.p->font_set) +#endif + XSetFont(dp->drv.p->dpy, dp->drv.p->gc, dp->drv.p->font); for(;;) { @@ -231,7 +287,7 @@ static int x11_init_graphics(caca_display_t *dp) break; } -#if defined(HAVE_X11_XKBLIB_H) +#if defined HAVE_X11_XKBLIB_H /* Disable autorepeat */ XkbSetDetectableAutoRepeat(dp->drv.p->dpy, True, &dp->drv.p->autorepeat); if(!dp->drv.p->autorepeat) @@ -257,9 +313,16 @@ static int x11_init_graphics(caca_display_t *dp) dp->drv.p->dirty_cursor_x = -1; dp->drv.p->dirty_cursor_y = -1; +#if defined X_HAVE_UTF8_STRING + list = XVaCreateNestedList(0, XNFontSet, dp->drv.p->font_set, NULL); dp->drv.p->im = XOpenIM(dp->drv.p->dpy, NULL, NULL, NULL); - dp->drv.p->ic = XCreateIC(dp->drv.p->im, XNInputStyle, - XIMPreeditNothing | XIMStatusNothing, NULL); + dp->drv.p->ic = XCreateIC(dp->drv.p->im, + XNInputStyle, XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, dp->drv.p->window, + XNPreeditAttributes, list, + XNStatusAttributes, list, + NULL); +#endif return 0; } @@ -267,17 +330,24 @@ static int x11_init_graphics(caca_display_t *dp) static int x11_end_graphics(caca_display_t *dp) { XSync(dp->drv.p->dpy, False); -#if defined(HAVE_X11_XKBLIB_H) +#if defined HAVE_X11_XKBLIB_H if(!dp->drv.p->autorepeat) XAutoRepeatOn(dp->drv.p->dpy); #endif XFreePixmap(dp->drv.p->dpy, dp->drv.p->pixmap); - XFreeFont(dp->drv.p->dpy, dp->drv.p->font_struct); +#if defined X_HAVE_UTF8_STRING + if (dp->drv.p->font_set) + XFreeFontSet(dp->drv.p->dpy, dp->drv.p->font_set); + else +#endif + XFreeFont(dp->drv.p->dpy, dp->drv.p->font_struct); XFreeGC(dp->drv.p->dpy, dp->drv.p->gc); XUnmapWindow(dp->drv.p->dpy, dp->drv.p->window); XDestroyWindow(dp->drv.p->dpy, dp->drv.p->window); +#if defined X_HAVE_UTF8_STRING XDestroyIC(dp->drv.p->ic); XCloseIM(dp->drv.p->im); +#endif XCloseDisplay(dp->drv.p->dpy); free(dp->drv.p); @@ -665,7 +735,6 @@ static void x11_put_glyph(caca_display_t *dp, int x, int y, int yoff, Display *dpy = dp->drv.p->dpy; Pixmap px = dp->drv.p->pixmap; GC gc = dp->drv.p->gc; - XChar2b ch16; int fw; /* Underline */ @@ -822,22 +891,33 @@ static void x11_put_glyph(caca_display_t *dp, int x, int y, int yoff, } #if defined X_HAVE_UTF8_STRING - if(ch >= 0x00000020) -#else - if(ch >= 0x00000020 && ch <= dp->drv.p->max_char) -#endif + if (dp->drv.p->font_set) { - ch16.byte1 = (uint8_t)(ch >> 8); - ch16.byte2 = (uint8_t)ch; + wchar_t wch = ch; + XwcDrawString(dpy, px, dp->drv.p->font_set, gc, + x + (fw - w) / 2, yoff, &wch, 1); } else +#endif { - ch16.byte1 = 0; - ch16.byte2 = caca_utf32_to_ascii(ch); - } + XChar2b ch16; + +#if !defined X_HAVE_UTF8_STRING + if(ch > dp->drv.p->max_char) + { + ch16.byte1 = 0; + ch16.byte2 = caca_utf32_to_ascii(ch); + } + else +#endif + { + ch16.byte1 = (uint8_t)(ch >> 8); + ch16.byte2 = (uint8_t)ch; + } - XDrawString16(dpy, px, gc, - x + (ch16.byte1 ? 0 : (fw - w) / 2), yoff, &ch16, 1); + XDrawString16(dpy, px, gc, + x + (ch16.byte1 ? 0 : (fw - w) / 2), yoff, &ch16, 1); + } } /* @@ -846,7 +926,7 @@ static void x11_put_glyph(caca_display_t *dp, int x, int y, int yoff, int x11_install(caca_display_t *dp) { -#if defined(HAVE_GETENV) +#if defined HAVE_GETENV if(!getenv("DISPLAY") || !*(getenv("DISPLAY"))) return -1; #endif