X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=st.c;h=213541f50a0ebb2bbe5873769a4d887b2b6247dc;hb=c9bd58e4dd04e61aa3613eab57ba6fb716a41146;hp=a44095907b73ae4ee145bc973df7d831cb6e4e89;hpb=9c44229c626ea7351a7809540435f40cffb624bc;p=st.git diff --git a/st.c b/st.c index a440959..213541f 100644 --- a/st.c +++ b/st.c @@ -436,8 +436,8 @@ typedef struct { * the current length of used elements. */ -static Fontcache frc[256]; -static int frccur = 0, frclen = 0; +static Fontcache frc[1024]; +static int frccur = -1, frclen = 0; ssize_t xwrite(int fd, char *s, size_t len) { @@ -1390,7 +1390,7 @@ tsetattr(int *attr, int l) { case 1: term.c.attr.mode |= ATTR_BOLD; break; - case 3: /* enter standout (highlight) */ + case 3: term.c.attr.mode |= ATTR_ITALIC; break; case 4: @@ -1406,7 +1406,7 @@ tsetattr(int *attr, int l) { case 22: term.c.attr.mode &= ~ATTR_BOLD; break; - case 23: /* leave standout (highlight) mode */ + case 23: term.c.attr.mode &= ~ATTR_ITALIC; break; case 24: @@ -2406,11 +2406,11 @@ xunloadfonts(void) * from the frccur. */ for (i = 0, ip = frccur; i < frclen; i++, ip--) { - if (ip <= 0) + if (ip < 0) ip = LEN(frc) - 1; XftFontClose(xw.dpy, frc[ip].font); } - frccur = 0; + frccur = -1; frclen = 0; XftFontClose(xw.dpy, dc.font.match); @@ -2497,15 +2497,23 @@ xinit(void) { /* double buffering */ if(!XdbeQueryExtension(xw.dpy, &major, &minor)) die("Xdbe extension is not present\n"); - xw.buf = XdbeAllocateBackBufferName(xw.dpy, xw.win, XdbeCopied); + xw.buf = XdbeAllocateBackBufferName(xw.dpy, xw.win, XdbeBackground); /* Xft rendering context */ xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); /* input methods */ - xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); - if(xw.xim == NULL) - die("XOpenIM failed. Could not open input device.\n"); + if((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) { + XSetLocaleModifiers("@im=local"); + if((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) { + XSetLocaleModifiers("@im="); + if((xw.xim = XOpenIM(xw.dpy, + NULL, NULL, NULL)) == NULL) { + die("XOpenIM failed. Could not open input" + " device.\n"); + } + } + } xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, xw.win, XNFocusWindow, xw.win, NULL); @@ -2532,16 +2540,16 @@ xinit(void) { void xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { int winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch, - width = charlen * xw.cw, u8clen, xp, i, frp, frcflags; + width = charlen * xw.cw, xp, i; + int frp, frcflags; + int u8fl, u8fblen, u8cblen, doesexist; + char *u8c, *u8fs; long u8char; - char *u8c; Font *font = &dc.font; - XftFont *sfont; FcResult fcres; FcPattern *fcpattern, *fontpattern; FcFontSet *fcsets[] = { NULL }; FcCharSet *fccharset; - XGlyphInfo extents; Colour *fg = &dc.col[base.fg], *bg = &dc.col[base.bg], *temp, revfg, revbg; XRenderColor colfg, colbg; @@ -2608,11 +2616,6 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { bg = temp; } - /* Width of the whole string that should be printed. */ - XftTextExtentsUtf8(xw.dpy, font->match, (FcChar8 *)s, bytelen, - &extents); - width = extents.xOff; - /* Intelligent cleaning up of the borders. */ if(x == 0) { xclear(0, (y == 0)? 0 : winy, borderpx, @@ -2630,85 +2633,111 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { /* Clean up the region we want to draw to. */ XftDrawRect(xw.draw, bg, winx, winy, width, xw.ch); - /* - * Step through all UTF-8 characters one by one and search in the font - * cache ring buffer, whether there was some font found to display the - * unicode value of that UTF-8 character. - */ fcsets[0] = font->set; - for (xp = winx; bytelen > 0; ) { - u8c = s; - u8clen = utf8decode(s, &u8char); - s += u8clen; - bytelen -= u8clen; - - sfont = font->match; + for (xp = winx; bytelen > 0;) { /* - * Only check the font cache or load new fonts, if the - * characters is not represented in main font. + * Search for the range in the to be printed string of glyphs + * that are in the main font. Then print that range. If + * some glyph is found that is not in the font, do the + * fallback dance. */ - if (!XftCharExists(xw.dpy, font->match, u8char)) { - frp = frccur; - /* Search the font cache. */ - for (i = 0; i < frclen; i++, frp--) { - if (frp <= 0) - frp = LEN(frc) - 1; + u8fs = s; + u8fblen = 0; + u8fl = 0; + for (;;) { + u8c = s; + u8cblen = utf8decode(s, &u8char); + s += u8cblen; + bytelen -= u8cblen; + + doesexist = XftCharIndex(xw.dpy, font->match, u8char); + if (!doesexist || bytelen <= 0) { + if (bytelen <= 0) { + if (doesexist) { + u8fl++; + u8fblen += u8cblen; + } + } - if (frc[frp].c == u8char - && frc[frp].flags == frcflags) { - break; + if (u8fl > 0) { + XftDrawStringUtf8(xw.draw, fg, + font->match, xp, + winy + font->ascent, + (FcChar8 *)u8fs, + u8fblen); + xp += font->width * u8fl; } + break; } - if (i >= frclen) { - /* - * Nothing was found in the cache. Now use - * some dozen of Fontconfig calls to get the - * font for one single character. - */ - fcpattern = FcPatternDuplicate(font->pattern); - fccharset = FcCharSetCreate(); - - FcCharSetAddChar(fccharset, u8char); - FcPatternAddCharSet(fcpattern, FC_CHARSET, - fccharset); - FcPatternAddBool(fcpattern, FC_SCALABLE, - FcTrue); - - FcConfigSubstitute(0, fcpattern, - FcMatchPattern); - FcDefaultSubstitute(fcpattern); - - fontpattern = FcFontSetMatch(0, fcsets, - FcTrue, fcpattern, &fcres); - - frccur++; - frclen++; - if (frccur >= LEN(frc)) - frccur = 0; - if (frclen >= LEN(frc)) { - frclen = LEN(frc); - XftFontClose(xw.dpy, frc[frccur].font); - } - /* - * Overwrite or create the new cache entry - * entry. - */ - frc[frccur].font = XftFontOpenPattern(xw.dpy, - fontpattern); - frc[frccur].c = u8char; - frc[frccur].flags = frcflags; + u8fl++; + u8fblen += u8cblen; + } + if (doesexist) + break; + + frp = frccur; + /* Search the font cache. */ + for (i = 0; i < frclen; i++, frp--) { + if (frp <= 0) + frp = LEN(frc) - 1; - FcPatternDestroy(fcpattern); - FcCharSetDestroy(fccharset); + if (frc[frp].c == u8char + && frc[frp].flags == frcflags) { + break; + } + } + + /* Nothing was found. */ + if (i >= frclen) { + /* + * Nothing was found in the cache. Now use + * some dozen of Fontconfig calls to get the + * font for one single character. + */ + fcpattern = FcPatternDuplicate(font->pattern); + fccharset = FcCharSetCreate(); + + FcCharSetAddChar(fccharset, u8char); + FcPatternAddCharSet(fcpattern, FC_CHARSET, + fccharset); + FcPatternAddBool(fcpattern, FC_SCALABLE, + FcTrue); - frp = frccur; + FcConfigSubstitute(0, fcpattern, + FcMatchPattern); + FcDefaultSubstitute(fcpattern); + + fontpattern = FcFontSetMatch(0, fcsets, + FcTrue, fcpattern, &fcres); + + /* + * Overwrite or create the new cache entry + * entry. + */ + frccur++; + frclen++; + if (frccur >= LEN(frc)) + frccur = 0; + if (frclen > LEN(frc)) { + frclen = LEN(frc); + XftFontClose(xw.dpy, frc[frccur].font); } - sfont = frc[frp].font; + + frc[frccur].font = XftFontOpenPattern(xw.dpy, + fontpattern); + frc[frccur].c = u8char; + frc[frccur].flags = frcflags; + + FcPatternDestroy(fcpattern); + FcCharSetDestroy(fccharset); + + frp = frccur; } - XftDrawStringUtf8(xw.draw, fg, sfont, xp, winy + sfont->ascent, - (FcChar8 *)u8c, u8clen); + XftDrawStringUtf8(xw.draw, fg, frc[frp].font, + xp, winy + frc[frp].font->ascent, + (FcChar8 *)u8c, u8cblen); xp += font->width; }