| @@ -24,7 +24,7 @@ | |||
| #include <X11/Xlib.h> | |||
| #include <X11/Xutil.h> | |||
| #include <X11/keysym.h> | |||
| #if defined(HAVE_X11_XKBLIB_H) | |||
| #if defined HAVE_X11_XKBLIB_H | |||
| # include <X11/XKBlib.h> | |||
| #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 | |||