diff options
| -rw-r--r-- | st.c | 383 |
1 files changed, 187 insertions, 196 deletions
| @@ -58,7 +58,6 @@ char *argv0; | |||
| 58 | #define ESC_ARG_SIZ 16 | 58 | #define ESC_ARG_SIZ 16 |
| 59 | #define STR_BUF_SIZ ESC_BUF_SIZ | 59 | #define STR_BUF_SIZ ESC_BUF_SIZ |
| 60 | #define STR_ARG_SIZ ESC_ARG_SIZ | 60 | #define STR_ARG_SIZ ESC_ARG_SIZ |
| 61 | #define DRAW_BUF_SIZ 20*1024 | ||
| 62 | #define XK_ANY_MOD UINT_MAX | 61 | #define XK_ANY_MOD UINT_MAX |
| 63 | #define XK_NO_MOD 0 | 62 | #define XK_NO_MOD 0 |
| 64 | #define XK_SWITCH_MOD (1<<13) | 63 | #define XK_SWITCH_MOD (1<<13) |
| @@ -87,18 +86,19 @@ char *argv0; | |||
| 87 | 86 | ||
| 88 | 87 | ||
| 89 | enum glyph_attribute { | 88 | enum glyph_attribute { |
| 90 | ATTR_NULL = 0, | 89 | ATTR_NULL = 0, |
| 91 | ATTR_BOLD = 1 << 0, | 90 | ATTR_BOLD = 1 << 0, |
| 92 | ATTR_FAINT = 1 << 1, | 91 | ATTR_FAINT = 1 << 1, |
| 93 | ATTR_ITALIC = 1 << 2, | 92 | ATTR_ITALIC = 1 << 2, |
| 94 | ATTR_UNDERLINE = 1 << 3, | 93 | ATTR_UNDERLINE = 1 << 3, |
| 95 | ATTR_BLINK = 1 << 4, | 94 | ATTR_BLINK = 1 << 4, |
| 96 | ATTR_REVERSE = 1 << 5, | 95 | ATTR_REVERSE = 1 << 5, |
| 97 | ATTR_INVISIBLE = 1 << 6, | 96 | ATTR_INVISIBLE = 1 << 6, |
| 98 | ATTR_STRUCK = 1 << 7, | 97 | ATTR_STRUCK = 1 << 7, |
| 99 | ATTR_WRAP = 1 << 8, | 98 | ATTR_WRAP = 1 << 8, |
| 100 | ATTR_WIDE = 1 << 9, | 99 | ATTR_WIDE = 1 << 9, |
| 101 | ATTR_WDUMMY = 1 << 10, | 100 | ATTR_WDUMMY = 1 << 10, |
| 101 | ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, | ||
| 102 | }; | 102 | }; |
| 103 | 103 | ||
| 104 | enum cursor_movement { | 104 | enum cursor_movement { |
| @@ -232,6 +232,7 @@ typedef struct { | |||
| 232 | Line *line; /* screen */ | 232 | Line *line; /* screen */ |
| 233 | Line *alt; /* alternate screen */ | 233 | Line *alt; /* alternate screen */ |
| 234 | bool *dirty; /* dirtyness of lines */ | 234 | bool *dirty; /* dirtyness of lines */ |
| 235 | XftGlyphFontSpec *specbuf; /* font spec buffer used for rendering */ | ||
| 235 | TCursor c; /* cursor */ | 236 | TCursor c; /* cursor */ |
| 236 | int top; /* top scroll limit */ | 237 | int top; /* top scroll limit */ |
| 237 | int bot; /* bottom scroll limit */ | 238 | int bot; /* bottom scroll limit */ |
| @@ -418,7 +419,8 @@ static void ttywrite(const char *, size_t); | |||
| 418 | static void tstrsequence(uchar); | 419 | static void tstrsequence(uchar); |
| 419 | 420 | ||
| 420 | static inline ushort sixd_to_16bit(int); | 421 | static inline ushort sixd_to_16bit(int); |
| 421 | static void xdraws(char *, Glyph, int, int, int, int); | 422 | static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); |
| 423 | static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); | ||
| 422 | static void xdrawglyph(Glyph, int, int); | 424 | static void xdrawglyph(Glyph, int, int); |
| 423 | static void xhints(void); | 425 | static void xhints(void); |
| 424 | static void xclear(int, int, int, int); | 426 | static void xclear(int, int, int, int); |
| @@ -2819,6 +2821,9 @@ tresize(int col, int row) { | |||
| 2819 | free(term.alt[i]); | 2821 | free(term.alt[i]); |
| 2820 | } | 2822 | } |
| 2821 | 2823 | ||
| 2824 | /* resize to new width */ | ||
| 2825 | term.specbuf = xrealloc(term.specbuf, col * sizeof(XftGlyphFontSpec)); | ||
| 2826 | |||
| 2822 | /* resize to new height */ | 2827 | /* resize to new height */ |
| 2823 | term.line = xrealloc(term.line, row * sizeof(Line)); | 2828 | term.line = xrealloc(term.line, row * sizeof(Line)); |
| 2824 | term.alt = xrealloc(term.alt, row * sizeof(Line)); | 2829 | term.alt = xrealloc(term.alt, row * sizeof(Line)); |
| @@ -3257,38 +3262,155 @@ xinit(void) { | |||
| 3257 | XSync(xw.dpy, False); | 3262 | XSync(xw.dpy, False); |
| 3258 | } | 3263 | } |
| 3259 | 3264 | ||
| 3260 | void | 3265 | int |
| 3261 | xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { | 3266 | xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) |
| 3262 | int winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch, | 3267 | { |
| 3263 | width = charlen * xw.cw, xp, i; | 3268 | float winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch, xp, yp; |
| 3264 | int frcflags, charexists; | 3269 | ushort mode, prevmode = USHRT_MAX; |
| 3265 | int u8fl, u8fblen, u8cblen, doesexist; | ||
| 3266 | char *u8c, *u8fs; | ||
| 3267 | Rune unicodep; | ||
| 3268 | Font *font = &dc.font; | 3270 | Font *font = &dc.font; |
| 3271 | int frcflags = FRC_NORMAL; | ||
| 3272 | float runewidth = xw.cw; | ||
| 3273 | Rune rune; | ||
| 3274 | FT_UInt glyphidx; | ||
| 3269 | FcResult fcres; | 3275 | FcResult fcres; |
| 3270 | FcPattern *fcpattern, *fontpattern; | 3276 | FcPattern *fcpattern, *fontpattern; |
| 3271 | FcFontSet *fcsets[] = { NULL }; | 3277 | FcFontSet *fcsets[] = { NULL }; |
| 3272 | FcCharSet *fccharset; | 3278 | FcCharSet *fccharset; |
| 3279 | int i, f, numspecs = 0; | ||
| 3280 | |||
| 3281 | for(i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { | ||
| 3282 | /* Fetch rune and mode for current glyph. */ | ||
| 3283 | rune = glyphs[i].u; | ||
| 3284 | mode = glyphs[i].mode; | ||
| 3285 | |||
| 3286 | /* Skip dummy wide-character spacing. */ | ||
| 3287 | if(mode == ATTR_WDUMMY) | ||
| 3288 | continue; | ||
| 3289 | |||
| 3290 | /* Determine font for glyph if different from previous glyph. */ | ||
| 3291 | if(prevmode != mode) { | ||
| 3292 | prevmode = mode; | ||
| 3293 | font = &dc.font; | ||
| 3294 | frcflags = FRC_NORMAL; | ||
| 3295 | runewidth = xw.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f); | ||
| 3296 | if((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { | ||
| 3297 | font = &dc.ibfont; | ||
| 3298 | frcflags = FRC_ITALICBOLD; | ||
| 3299 | } else if(mode & ATTR_ITALIC) { | ||
| 3300 | font = &dc.ifont; | ||
| 3301 | frcflags = FRC_ITALIC; | ||
| 3302 | } else if(mode & ATTR_BOLD) { | ||
| 3303 | font = &dc.bfont; | ||
| 3304 | frcflags = FRC_BOLD; | ||
| 3305 | } | ||
| 3306 | yp = winy + font->ascent; | ||
| 3307 | } | ||
| 3308 | |||
| 3309 | /* Lookup character index with default font. */ | ||
| 3310 | glyphidx = XftCharIndex(xw.dpy, font->match, rune); | ||
| 3311 | if(glyphidx) { | ||
| 3312 | specs[numspecs].font = font->match; | ||
| 3313 | specs[numspecs].glyph = glyphidx; | ||
| 3314 | specs[numspecs].x = (short)xp; | ||
| 3315 | specs[numspecs].y = (short)yp; | ||
| 3316 | xp += runewidth; | ||
| 3317 | numspecs++; | ||
| 3318 | continue; | ||
| 3319 | } | ||
| 3320 | |||
| 3321 | /* Fallback on font cache, search the font cache for match. */ | ||
| 3322 | for(f = 0; f < frclen; f++) { | ||
| 3323 | glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune); | ||
| 3324 | /* Everything correct. */ | ||
| 3325 | if(glyphidx && frc[f].flags == frcflags) | ||
| 3326 | break; | ||
| 3327 | /* We got a default font for a not found glyph. */ | ||
| 3328 | if(!glyphidx && frc[f].flags == frcflags | ||
| 3329 | && frc[f].unicodep == rune) { | ||
| 3330 | break; | ||
| 3331 | } | ||
| 3332 | } | ||
| 3333 | |||
| 3334 | /* Nothing was found. Use fontconfig to find matching font. */ | ||
| 3335 | if(f >= frclen) { | ||
| 3336 | if(!font->set) | ||
| 3337 | font->set = FcFontSort(0, font->pattern, | ||
| 3338 | FcTrue, 0, &fcres); | ||
| 3339 | fcsets[0] = font->set; | ||
| 3340 | |||
| 3341 | /* | ||
| 3342 | * Nothing was found in the cache. Now use | ||
| 3343 | * some dozen of Fontconfig calls to get the | ||
| 3344 | * font for one single character. | ||
| 3345 | * | ||
| 3346 | * Xft and fontconfig are design failures. | ||
| 3347 | */ | ||
| 3348 | fcpattern = FcPatternDuplicate(font->pattern); | ||
| 3349 | fccharset = FcCharSetCreate(); | ||
| 3350 | |||
| 3351 | FcCharSetAddChar(fccharset, rune); | ||
| 3352 | FcPatternAddCharSet(fcpattern, FC_CHARSET, | ||
| 3353 | fccharset); | ||
| 3354 | FcPatternAddBool(fcpattern, FC_SCALABLE, | ||
| 3355 | FcTrue); | ||
| 3356 | |||
| 3357 | FcConfigSubstitute(0, fcpattern, | ||
| 3358 | FcMatchPattern); | ||
| 3359 | FcDefaultSubstitute(fcpattern); | ||
| 3360 | |||
| 3361 | fontpattern = FcFontSetMatch(0, fcsets, 1, | ||
| 3362 | fcpattern, &fcres); | ||
| 3363 | |||
| 3364 | /* | ||
| 3365 | * Overwrite or create the new cache entry. | ||
| 3366 | */ | ||
| 3367 | if(frclen >= LEN(frc)) { | ||
| 3368 | frclen = LEN(frc) - 1; | ||
| 3369 | XftFontClose(xw.dpy, frc[frclen].font); | ||
| 3370 | frc[frclen].unicodep = 0; | ||
| 3371 | } | ||
| 3372 | |||
| 3373 | frc[frclen].font = XftFontOpenPattern(xw.dpy, | ||
| 3374 | fontpattern); | ||
| 3375 | frc[frclen].flags = frcflags; | ||
| 3376 | frc[frclen].unicodep = rune; | ||
| 3377 | |||
| 3378 | glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune); | ||
| 3379 | |||
| 3380 | f = frclen; | ||
| 3381 | frclen++; | ||
| 3382 | |||
| 3383 | FcPatternDestroy(fcpattern); | ||
| 3384 | FcCharSetDestroy(fccharset); | ||
| 3385 | } | ||
| 3386 | |||
| 3387 | specs[numspecs].font = frc[f].font; | ||
| 3388 | specs[numspecs].glyph = glyphidx; | ||
| 3389 | specs[numspecs].x = (short)xp; | ||
| 3390 | specs[numspecs].y = (short)(winy + frc[f].font->ascent); | ||
| 3391 | xp += runewidth; | ||
| 3392 | numspecs++; | ||
| 3393 | } | ||
| 3394 | |||
| 3395 | return numspecs; | ||
| 3396 | } | ||
| 3397 | |||
| 3398 | void | ||
| 3399 | xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) { | ||
| 3400 | int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); | ||
| 3401 | int winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch, | ||
| 3402 | width = charlen * xw.cw; | ||
| 3273 | Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; | 3403 | Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; |
| 3274 | XRenderColor colfg, colbg; | 3404 | XRenderColor colfg, colbg; |
| 3275 | XRectangle r; | 3405 | XRectangle r; |
| 3276 | int oneatatime; | ||
| 3277 | 3406 | ||
| 3278 | frcflags = FRC_NORMAL; | 3407 | /* Determine foreground and background colors based on mode. */ |
| 3279 | 3408 | if(base.fg == defaultfg) { | |
| 3280 | if(base.mode & ATTR_ITALIC) { | 3409 | if(base.mode & ATTR_ITALIC) |
| 3281 | if(base.fg == defaultfg) | ||
| 3282 | base.fg = defaultitalic; | 3410 | base.fg = defaultitalic; |
| 3283 | font = &dc.ifont; | 3411 | else if((base.mode & ATTR_ITALIC) && (base.mode & ATTR_BOLD)) |
| 3284 | frcflags = FRC_ITALIC; | ||
| 3285 | } else if((base.mode & ATTR_ITALIC) && (base.mode & ATTR_BOLD)) { | ||
| 3286 | if(base.fg == defaultfg) | ||
| 3287 | base.fg = defaultitalic; | 3412 | base.fg = defaultitalic; |
| 3288 | font = &dc.ibfont; | 3413 | else if(base.mode & ATTR_UNDERLINE) |
| 3289 | frcflags = FRC_ITALICBOLD; | ||
| 3290 | } else if(base.mode & ATTR_UNDERLINE) { | ||
| 3291 | if(base.fg == defaultfg) | ||
| 3292 | base.fg = defaultunderline; | 3414 | base.fg = defaultunderline; |
| 3293 | } | 3415 | } |
| 3294 | 3416 | ||
| @@ -3314,22 +3436,9 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { | |||
| 3314 | bg = &dc.col[base.bg]; | 3436 | bg = &dc.col[base.bg]; |
| 3315 | } | 3437 | } |
| 3316 | 3438 | ||
| 3317 | if(base.mode & ATTR_BOLD) { | 3439 | /* Change basic system colors [0-7] to bright system colors [8-15] */ |
| 3318 | /* | 3440 | if((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7)) |
| 3319 | * change basic system colors [0-7] | 3441 | fg = &dc.col[base.fg + 8]; |
| 3320 | * to bright system colors [8-15] | ||
| 3321 | */ | ||
| 3322 | if(BETWEEN(base.fg, 0, 7) && !(base.mode & ATTR_FAINT)) | ||
| 3323 | fg = &dc.col[base.fg + 8]; | ||
| 3324 | |||
| 3325 | if(base.mode & ATTR_ITALIC) { | ||
| 3326 | font = &dc.ibfont; | ||
| 3327 | frcflags = FRC_ITALICBOLD; | ||
| 3328 | } else { | ||
| 3329 | font = &dc.bfont; | ||
| 3330 | frcflags = FRC_BOLD; | ||
| 3331 | } | ||
| 3332 | } | ||
| 3333 | 3442 | ||
| 3334 | if(IS_SET(MODE_REVERSE)) { | 3443 | if(IS_SET(MODE_REVERSE)) { |
| 3335 | if(fg == &dc.col[defaultfg]) { | 3444 | if(fg == &dc.col[defaultfg]) { |
| @@ -3363,7 +3472,7 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { | |||
| 3363 | bg = temp; | 3472 | bg = temp; |
| 3364 | } | 3473 | } |
| 3365 | 3474 | ||
| 3366 | if(base.mode & ATTR_FAINT && !(base.mode & ATTR_BOLD)) { | 3475 | if((base.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) { |
| 3367 | colfg.red = fg->color.red / 2; | 3476 | colfg.red = fg->color.red / 2; |
| 3368 | colfg.green = fg->color.green / 2; | 3477 | colfg.green = fg->color.green / 2; |
| 3369 | colfg.blue = fg->color.blue / 2; | 3478 | colfg.blue = fg->color.blue / 2; |
| @@ -3401,136 +3510,17 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { | |||
| 3401 | r.width = width; | 3510 | r.width = width; |
| 3402 | XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); | 3511 | XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); |
| 3403 | 3512 | ||
| 3404 | for(xp = winx; bytelen > 0;) { | 3513 | /* Render the glyphs. */ |
| 3405 | /* | 3514 | XftDrawGlyphFontSpec(xw.draw, fg, specs, len); |
| 3406 | * Search for the range in the to be printed string of glyphs | ||
| 3407 | * that are in the main font. Then print that range. If | ||
| 3408 | * some glyph is found that is not in the font, do the | ||
| 3409 | * fallback dance. | ||
| 3410 | */ | ||
| 3411 | u8fs = s; | ||
| 3412 | u8fblen = 0; | ||
| 3413 | u8fl = 0; | ||
| 3414 | oneatatime = font->width != xw.cw; | ||
| 3415 | for(;;) { | ||
| 3416 | u8c = s; | ||
| 3417 | u8cblen = utf8decode(s, &unicodep, UTF_SIZ); | ||
| 3418 | s += u8cblen; | ||
| 3419 | bytelen -= u8cblen; | ||
| 3420 | |||
| 3421 | doesexist = XftCharExists(xw.dpy, font->match, unicodep); | ||
| 3422 | if(doesexist) { | ||
| 3423 | u8fl++; | ||
| 3424 | u8fblen += u8cblen; | ||
| 3425 | if(!oneatatime && bytelen > 0) | ||
| 3426 | continue; | ||
| 3427 | } | ||
| 3428 | |||
| 3429 | if(u8fl > 0) { | ||
| 3430 | XftDrawStringUtf8(xw.draw, fg, | ||
| 3431 | font->match, xp, | ||
| 3432 | winy + font->ascent, | ||
| 3433 | (FcChar8 *)u8fs, | ||
| 3434 | u8fblen); | ||
| 3435 | xp += xw.cw * u8fl; | ||
| 3436 | } | ||
| 3437 | break; | ||
| 3438 | } | ||
| 3439 | if(doesexist) { | ||
| 3440 | if(oneatatime) | ||
| 3441 | continue; | ||
| 3442 | break; | ||
| 3443 | } | ||
| 3444 | |||
| 3445 | /* Search the font cache. */ | ||
| 3446 | for(i = 0; i < frclen; i++) { | ||
| 3447 | charexists = XftCharExists(xw.dpy, frc[i].font, unicodep); | ||
| 3448 | /* Everything correct. */ | ||
| 3449 | if(charexists && frc[i].flags == frcflags) | ||
| 3450 | break; | ||
| 3451 | /* We got a default font for a not found glyph. */ | ||
| 3452 | if(!charexists && frc[i].flags == frcflags \ | ||
| 3453 | && frc[i].unicodep == unicodep) { | ||
| 3454 | break; | ||
| 3455 | } | ||
| 3456 | } | ||
| 3457 | |||
| 3458 | /* Nothing was found. */ | ||
| 3459 | if(i >= frclen) { | ||
| 3460 | if(!font->set) | ||
| 3461 | font->set = FcFontSort(0, font->pattern, | ||
| 3462 | FcTrue, 0, &fcres); | ||
| 3463 | fcsets[0] = font->set; | ||
| 3464 | |||
| 3465 | /* | ||
| 3466 | * Nothing was found in the cache. Now use | ||
| 3467 | * some dozen of Fontconfig calls to get the | ||
| 3468 | * font for one single character. | ||
| 3469 | * | ||
| 3470 | * Xft and fontconfig are design failures. | ||
| 3471 | */ | ||
| 3472 | fcpattern = FcPatternDuplicate(font->pattern); | ||
| 3473 | fccharset = FcCharSetCreate(); | ||
| 3474 | |||
| 3475 | FcCharSetAddChar(fccharset, unicodep); | ||
| 3476 | FcPatternAddCharSet(fcpattern, FC_CHARSET, | ||
| 3477 | fccharset); | ||
| 3478 | FcPatternAddBool(fcpattern, FC_SCALABLE, | ||
| 3479 | FcTrue); | ||
| 3480 | |||
| 3481 | FcConfigSubstitute(0, fcpattern, | ||
| 3482 | FcMatchPattern); | ||
| 3483 | FcDefaultSubstitute(fcpattern); | ||
| 3484 | |||
| 3485 | fontpattern = FcFontSetMatch(0, fcsets, 1, | ||
| 3486 | fcpattern, &fcres); | ||
| 3487 | |||
| 3488 | /* | ||
| 3489 | * Overwrite or create the new cache entry. | ||
| 3490 | */ | ||
| 3491 | if(frclen >= LEN(frc)) { | ||
| 3492 | frclen = LEN(frc) - 1; | ||
| 3493 | XftFontClose(xw.dpy, frc[frclen].font); | ||
| 3494 | frc[frclen].unicodep = 0; | ||
| 3495 | } | ||
| 3496 | |||
| 3497 | frc[frclen].font = XftFontOpenPattern(xw.dpy, | ||
| 3498 | fontpattern); | ||
| 3499 | frc[frclen].flags = frcflags; | ||
| 3500 | frc[frclen].unicodep = unicodep; | ||
| 3501 | |||
| 3502 | i = frclen; | ||
| 3503 | frclen++; | ||
| 3504 | |||
| 3505 | FcPatternDestroy(fcpattern); | ||
| 3506 | FcCharSetDestroy(fccharset); | ||
| 3507 | } | ||
| 3508 | |||
| 3509 | XftDrawStringUtf8(xw.draw, fg, frc[i].font, | ||
| 3510 | xp, winy + frc[i].font->ascent, | ||
| 3511 | (FcChar8 *)u8c, u8cblen); | ||
| 3512 | |||
| 3513 | xp += xw.cw * wcwidth(unicodep); | ||
| 3514 | } | ||
| 3515 | |||
| 3516 | /* | ||
| 3517 | * This is how the loop above actually should be. Why does the | ||
| 3518 | * application have to care about font details? | ||
| 3519 | * | ||
| 3520 | * I have to repeat: Xft and Fontconfig are design failures. | ||
| 3521 | */ | ||
| 3522 | /* | ||
| 3523 | XftDrawStringUtf8(xw.draw, fg, font->set, winx, | ||
| 3524 | winy + font->ascent, (FcChar8 *)s, bytelen); | ||
| 3525 | */ | ||
| 3526 | 3515 | ||
| 3516 | /* Render underline and strikethrough. */ | ||
| 3527 | if(base.mode & ATTR_UNDERLINE) { | 3517 | if(base.mode & ATTR_UNDERLINE) { |
| 3528 | XftDrawRect(xw.draw, fg, winx, winy + font->ascent + 1, | 3518 | XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, |
| 3529 | width, 1); | 3519 | width, 1); |
| 3530 | } | 3520 | } |
| 3531 | 3521 | ||
| 3532 | if(base.mode & ATTR_STRUCK) { | 3522 | if(base.mode & ATTR_STRUCK) { |
| 3533 | XftDrawRect(xw.draw, fg, winx, winy + 2 * font->ascent / 3, | 3523 | XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, |
| 3534 | width, 1); | 3524 | width, 1); |
| 3535 | } | 3525 | } |
| 3536 | 3526 | ||
| @@ -3540,11 +3530,10 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { | |||
| 3540 | 3530 | ||
| 3541 | void | 3531 | void |
| 3542 | xdrawglyph(Glyph g, int x, int y) { | 3532 | xdrawglyph(Glyph g, int x, int y) { |
| 3543 | static char buf[UTF_SIZ]; | 3533 | int numspecs; |
| 3544 | size_t len = utf8encode(g.u, buf); | 3534 | XftGlyphFontSpec spec; |
| 3545 | int width = g.mode & ATTR_WIDE ? 2 : 1; | 3535 | numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); |
| 3546 | 3536 | xdrawglyphfontspecs(&spec, g, numspecs, x, y); | |
| 3547 | xdraws(buf, g, x, y, width, len); | ||
| 3548 | } | 3537 | } |
| 3549 | 3538 | ||
| 3550 | void | 3539 | void |
| @@ -3658,9 +3647,9 @@ draw(void) { | |||
| 3658 | 3647 | ||
| 3659 | void | 3648 | void |
| 3660 | drawregion(int x1, int y1, int x2, int y2) { | 3649 | drawregion(int x1, int y1, int x2, int y2) { |
| 3661 | int ic, ib, x, y, ox; | 3650 | int i, x, y, ox, numspecs; |
| 3662 | Glyph base, new; | 3651 | Glyph base, new; |
| 3663 | char buf[DRAW_BUF_SIZ]; | 3652 | XftGlyphFontSpec* specs; |
| 3664 | bool ena_sel = sel.ob.x != -1 && sel.alt == IS_SET(MODE_ALTSCREEN); | 3653 | bool ena_sel = sel.ob.x != -1 && sel.alt == IS_SET(MODE_ALTSCREEN); |
| 3665 | 3654 | ||
| 3666 | if(!(xw.state & WIN_VISIBLE)) | 3655 | if(!(xw.state & WIN_VISIBLE)) |
| @@ -3672,29 +3661,31 @@ drawregion(int x1, int y1, int x2, int y2) { | |||
| 3672 | 3661 | ||
| 3673 | xtermclear(0, y, term.col, y); | 3662 | xtermclear(0, y, term.col, y); |
| 3674 | term.dirty[y] = 0; | 3663 | term.dirty[y] = 0; |
| 3675 | base = term.line[y][0]; | 3664 | |
| 3676 | ic = ib = ox = 0; | 3665 | specs = term.specbuf; |
| 3677 | for(x = x1; x < x2; x++) { | 3666 | numspecs = xmakeglyphfontspecs(specs, &term.line[y][0], x2 - x1, x1, y); |
| 3667 | |||
| 3668 | i = ox = 0; | ||
| 3669 | for(x = x1; x < x2 && i < numspecs; x++) { | ||
| 3678 | new = term.line[y][x]; | 3670 | new = term.line[y][x]; |
| 3679 | if(new.mode == ATTR_WDUMMY) | 3671 | if(new.mode == ATTR_WDUMMY) |
| 3680 | continue; | 3672 | continue; |
| 3681 | if(ena_sel && selected(x, y)) | 3673 | if(ena_sel && selected(x, y)) |
| 3682 | new.mode ^= ATTR_REVERSE; | 3674 | new.mode ^= ATTR_REVERSE; |
| 3683 | if(ib > 0 && (ATTRCMP(base, new) | 3675 | if(i > 0 && ATTRCMP(base, new)) { |
| 3684 | || ib >= DRAW_BUF_SIZ-UTF_SIZ)) { | 3676 | xdrawglyphfontspecs(specs, base, i, ox, y); |
| 3685 | xdraws(buf, base, ox, y, ic, ib); | 3677 | specs += i; |
| 3686 | ic = ib = 0; | 3678 | numspecs -= i; |
| 3679 | i = 0; | ||
| 3687 | } | 3680 | } |
| 3688 | if(ib == 0) { | 3681 | if(i == 0) { |
| 3689 | ox = x; | 3682 | ox = x; |
| 3690 | base = new; | 3683 | base = new; |
| 3691 | } | 3684 | } |
| 3692 | 3685 | i++; | |
| 3693 | ib += utf8encode(new.u, buf+ib); | ||
| 3694 | ic += (new.mode & ATTR_WIDE)? 2 : 1; | ||
| 3695 | } | 3686 | } |
| 3696 | if(ib > 0) | 3687 | if(i > 0) |
| 3697 | xdraws(buf, base, ox, y, ic, ib); | 3688 | xdrawglyphfontspecs(specs, base, i, ox, y); |
| 3698 | } | 3689 | } |
| 3699 | xdrawcursor(); | 3690 | xdrawcursor(); |
| 3700 | } | 3691 | } |
