diff options
author | Christoph Lohmann <20h@r-36.net> | 2013-09-07 12:41:36 +0200 |
---|---|---|
committer | Christoph Lohmann <20h@r-36.net> | 2013-09-07 12:41:36 +0200 |
commit | 210dda9570095443bac887c2bfcd75f2bcc23780 (patch) | |
tree | 91136e0906b2443653858bdddb1e4669c8854876 /st.c | |
parent | a4358a1fbd1c71269129404c9af4f539b2d7627c (diff) | |
download | st-patched-210dda9570095443bac887c2bfcd75f2bcc23780.tar.bz2 st-patched-210dda9570095443bac887c2bfcd75f2bcc23780.tar.xz st-patched-210dda9570095443bac887c2bfcd75f2bcc23780.zip |
Wide character support.
Thanks "Eon S. Jeon" <esjeon@hyunmu.am>!
Diffstat (limited to 'st.c')
-rw-r--r-- | st.c | 84 |
1 files changed, 68 insertions, 16 deletions
@@ -27,6 +27,7 @@ | |||
27 | #include <X11/keysym.h> | 27 | #include <X11/keysym.h> |
28 | #include <X11/Xft/Xft.h> | 28 | #include <X11/Xft/Xft.h> |
29 | #include <fontconfig/fontconfig.h> | 29 | #include <fontconfig/fontconfig.h> |
30 | #include <wchar.h> | ||
30 | 31 | ||
31 | #include "arg.h" | 32 | #include "arg.h" |
32 | 33 | ||
@@ -96,6 +97,8 @@ enum glyph_attribute { | |||
96 | ATTR_ITALIC = 16, | 97 | ATTR_ITALIC = 16, |
97 | ATTR_BLINK = 32, | 98 | ATTR_BLINK = 32, |
98 | ATTR_WRAP = 64, | 99 | ATTR_WRAP = 64, |
100 | ATTR_WIDE = 128, | ||
101 | ATTR_WDUMMY = 256, | ||
99 | }; | 102 | }; |
100 | 103 | ||
101 | enum cursor_movement { | 104 | enum cursor_movement { |
@@ -165,7 +168,7 @@ typedef unsigned short ushort; | |||
165 | 168 | ||
166 | typedef struct { | 169 | typedef struct { |
167 | char c[UTF_SIZ]; /* character code */ | 170 | char c[UTF_SIZ]; /* character code */ |
168 | uchar mode; /* attribute flags */ | 171 | ushort mode; /* attribute flags */ |
169 | ulong fg; /* foreground */ | 172 | ulong fg; /* foreground */ |
170 | ulong bg; /* background */ | 173 | ulong bg; /* background */ |
171 | } Glyph; | 174 | } Glyph; |
@@ -719,8 +722,13 @@ selsnap(int mode, int *x, int *y, int direction) { | |||
719 | } | 722 | } |
720 | } | 723 | } |
721 | 724 | ||
725 | if(term.line[*y][*x+direction].mode & ATTR_WDUMMY) { | ||
726 | *x += direction; | ||
727 | continue; | ||
728 | } | ||
729 | |||
722 | if(strchr(worddelimiters, | 730 | if(strchr(worddelimiters, |
723 | term.line[*y][*x + direction].c[0])) { | 731 | term.line[*y][*x+direction].c[0])) { |
724 | break; | 732 | break; |
725 | } | 733 | } |
726 | 734 | ||
@@ -932,7 +940,7 @@ selcopy(void) { | |||
932 | /* nothing */; | 940 | /* nothing */; |
933 | 941 | ||
934 | for(x = 0; gp <= last; x++, ++gp) { | 942 | for(x = 0; gp <= last; x++, ++gp) { |
935 | if(!selected(x, y)) | 943 | if(!selected(x, y) || (gp->mode & ATTR_WDUMMY)) |
936 | continue; | 944 | continue; |
937 | 945 | ||
938 | size = utf8size(gp->c); | 946 | size = utf8size(gp->c); |
@@ -1533,6 +1541,16 @@ tsetchar(char *c, Glyph *attr, int x, int y) { | |||
1533 | } | 1541 | } |
1534 | } | 1542 | } |
1535 | 1543 | ||
1544 | if(term.line[y][x].mode & ATTR_WIDE) { | ||
1545 | if(x+1 < term.col) { | ||
1546 | term.line[y][x+1].c[0] = ' '; | ||
1547 | term.line[y][x+1].mode &= ~ATTR_WDUMMY; | ||
1548 | } | ||
1549 | } else if(term.line[y][x].mode & ATTR_WDUMMY) { | ||
1550 | term.line[y][x-1].c[0] = ' '; | ||
1551 | term.line[y][x-1].mode &= ~ATTR_WIDE; | ||
1552 | } | ||
1553 | |||
1536 | term.dirty[y] = 1; | 1554 | term.dirty[y] = 1; |
1537 | term.line[y][x] = *attr; | 1555 | term.line[y][x] = *attr; |
1538 | memcpy(term.line[y][x].c, c, UTF_SIZ); | 1556 | memcpy(term.line[y][x].c, c, UTF_SIZ); |
@@ -2222,6 +2240,15 @@ void | |||
2222 | tputc(char *c, int len) { | 2240 | tputc(char *c, int len) { |
2223 | uchar ascii = *c; | 2241 | uchar ascii = *c; |
2224 | bool control = ascii < '\x20' || ascii == 0177; | 2242 | bool control = ascii < '\x20' || ascii == 0177; |
2243 | long u8char; | ||
2244 | int width; | ||
2245 | |||
2246 | if(len == 1) { | ||
2247 | width = 1; | ||
2248 | } else { | ||
2249 | utf8decode(c, &u8char); | ||
2250 | width = wcwidth(u8char); | ||
2251 | } | ||
2225 | 2252 | ||
2226 | if(iofd != -1) { | 2253 | if(iofd != -1) { |
2227 | if(xwrite(iofd, c, len) < 0) { | 2254 | if(xwrite(iofd, c, len) < 0) { |
@@ -2469,9 +2496,20 @@ tputc(char *c, int len) { | |||
2469 | (term.col - term.c.x - 1) * sizeof(Glyph)); | 2496 | (term.col - term.c.x - 1) * sizeof(Glyph)); |
2470 | } | 2497 | } |
2471 | 2498 | ||
2499 | if(term.c.x+width > term.col) | ||
2500 | tnewline(1); | ||
2501 | |||
2472 | tsetchar(c, &term.c.attr, term.c.x, term.c.y); | 2502 | tsetchar(c, &term.c.attr, term.c.x, term.c.y); |
2473 | if(term.c.x+1 < term.col) { | 2503 | |
2474 | tmoveto(term.c.x+1, term.c.y); | 2504 | if(width == 2) { |
2505 | term.line[term.c.y][term.c.x].mode |= ATTR_WIDE; | ||
2506 | if(term.c.x+1 < term.col) { | ||
2507 | term.line[term.c.y][term.c.x+1].c[0] = '\0'; | ||
2508 | term.line[term.c.y][term.c.x+1].mode = ATTR_WDUMMY; | ||
2509 | } | ||
2510 | } | ||
2511 | if(term.c.x+width < term.col) { | ||
2512 | tmoveto(term.c.x+width, term.c.y); | ||
2475 | } else { | 2513 | } else { |
2476 | term.c.state |= CURSOR_WRAPNEXT; | 2514 | term.c.state |= CURSOR_WRAPNEXT; |
2477 | } | 2515 | } |
@@ -3173,7 +3211,7 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { | |||
3173 | xp, winy + frc[i].font->ascent, | 3211 | xp, winy + frc[i].font->ascent, |
3174 | (FcChar8 *)u8c, u8cblen); | 3212 | (FcChar8 *)u8c, u8cblen); |
3175 | 3213 | ||
3176 | xp += xw.cw; | 3214 | xp += xw.cw * wcwidth(u8char); |
3177 | } | 3215 | } |
3178 | 3216 | ||
3179 | /* | 3217 | /* |
@@ -3193,18 +3231,27 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { | |||
3193 | void | 3231 | void |
3194 | xdrawcursor(void) { | 3232 | xdrawcursor(void) { |
3195 | static int oldx = 0, oldy = 0; | 3233 | static int oldx = 0, oldy = 0; |
3196 | int sl; | 3234 | int sl, width, curx; |
3197 | Glyph g = {{' '}, ATTR_NULL, defaultbg, defaultcs}; | 3235 | Glyph g = {{' '}, ATTR_NULL, defaultbg, defaultcs}; |
3198 | 3236 | ||
3199 | LIMIT(oldx, 0, term.col-1); | 3237 | LIMIT(oldx, 0, term.col-1); |
3200 | LIMIT(oldy, 0, term.row-1); | 3238 | LIMIT(oldy, 0, term.row-1); |
3201 | 3239 | ||
3240 | curx = term.c.x; | ||
3241 | |||
3242 | /* adjust position if in dummy */ | ||
3243 | if(term.line[oldy][oldx].mode & ATTR_WDUMMY) | ||
3244 | oldx--; | ||
3245 | if(term.line[term.c.y][curx].mode & ATTR_WDUMMY) | ||
3246 | curx--; | ||
3247 | |||
3202 | memcpy(g.c, term.line[term.c.y][term.c.x].c, UTF_SIZ); | 3248 | memcpy(g.c, term.line[term.c.y][term.c.x].c, UTF_SIZ); |
3203 | 3249 | ||
3204 | /* remove the old cursor */ | 3250 | /* remove the old cursor */ |
3205 | sl = utf8size(term.line[oldy][oldx].c); | 3251 | sl = utf8size(term.line[oldy][oldx].c); |
3252 | width = (term.line[oldy][oldx].mode & ATTR_WIDE)? 2 : 1; | ||
3206 | xdraws(term.line[oldy][oldx].c, term.line[oldy][oldx], oldx, | 3253 | xdraws(term.line[oldy][oldx].c, term.line[oldy][oldx], oldx, |
3207 | oldy, 1, sl); | 3254 | oldy, width, sl); |
3208 | 3255 | ||
3209 | /* draw the new one */ | 3256 | /* draw the new one */ |
3210 | if(!(IS_SET(MODE_HIDE))) { | 3257 | if(!(IS_SET(MODE_HIDE))) { |
@@ -3216,26 +3263,28 @@ xdrawcursor(void) { | |||
3216 | } | 3263 | } |
3217 | 3264 | ||
3218 | sl = utf8size(g.c); | 3265 | sl = utf8size(g.c); |
3219 | xdraws(g.c, g, term.c.x, term.c.y, 1, sl); | 3266 | width = (term.line[term.c.y][curx].mode & ATTR_WIDE)\ |
3267 | ? 2 : 1; | ||
3268 | xdraws(g.c, g, term.c.x, term.c.y, width, sl); | ||
3220 | } else { | 3269 | } else { |
3221 | XftDrawRect(xw.draw, &dc.col[defaultcs], | 3270 | XftDrawRect(xw.draw, &dc.col[defaultcs], |
3222 | borderpx + term.c.x * xw.cw, | 3271 | borderpx + curx * xw.cw, |
3223 | borderpx + term.c.y * xw.ch, | 3272 | borderpx + term.c.y * xw.ch, |
3224 | xw.cw - 1, 1); | 3273 | xw.cw - 1, 1); |
3225 | XftDrawRect(xw.draw, &dc.col[defaultcs], | 3274 | XftDrawRect(xw.draw, &dc.col[defaultcs], |
3226 | borderpx + term.c.x * xw.cw, | 3275 | borderpx + curx * xw.cw, |
3227 | borderpx + term.c.y * xw.ch, | 3276 | borderpx + term.c.y * xw.ch, |
3228 | 1, xw.ch - 1); | 3277 | 1, xw.ch - 1); |
3229 | XftDrawRect(xw.draw, &dc.col[defaultcs], | 3278 | XftDrawRect(xw.draw, &dc.col[defaultcs], |
3230 | borderpx + (term.c.x + 1) * xw.cw - 1, | 3279 | borderpx + (curx + 1) * xw.cw - 1, |
3231 | borderpx + term.c.y * xw.ch, | 3280 | borderpx + term.c.y * xw.ch, |
3232 | 1, xw.ch - 1); | 3281 | 1, xw.ch - 1); |
3233 | XftDrawRect(xw.draw, &dc.col[defaultcs], | 3282 | XftDrawRect(xw.draw, &dc.col[defaultcs], |
3234 | borderpx + term.c.x * xw.cw, | 3283 | borderpx + curx * xw.cw, |
3235 | borderpx + (term.c.y + 1) * xw.ch - 1, | 3284 | borderpx + (term.c.y + 1) * xw.ch - 1, |
3236 | xw.cw, 1); | 3285 | xw.cw, 1); |
3237 | } | 3286 | } |
3238 | oldx = term.c.x, oldy = term.c.y; | 3287 | oldx = curx, oldy = term.c.y; |
3239 | } | 3288 | } |
3240 | } | 3289 | } |
3241 | 3290 | ||
@@ -3284,6 +3333,7 @@ drawregion(int x1, int y1, int x2, int y2) { | |||
3284 | Glyph base, new; | 3333 | Glyph base, new; |
3285 | char buf[DRAW_BUF_SIZ]; | 3334 | char buf[DRAW_BUF_SIZ]; |
3286 | bool ena_sel = sel.ob.x != -1; | 3335 | bool ena_sel = sel.ob.x != -1; |
3336 | long u8char; | ||
3287 | 3337 | ||
3288 | if(sel.alt ^ IS_SET(MODE_ALTSCREEN)) | 3338 | if(sel.alt ^ IS_SET(MODE_ALTSCREEN)) |
3289 | ena_sel = 0; | 3339 | ena_sel = 0; |
@@ -3301,6 +3351,8 @@ drawregion(int x1, int y1, int x2, int y2) { | |||
3301 | ic = ib = ox = 0; | 3351 | ic = ib = ox = 0; |
3302 | for(x = x1; x < x2; x++) { | 3352 | for(x = x1; x < x2; x++) { |
3303 | new = term.line[y][x]; | 3353 | new = term.line[y][x]; |
3354 | if(new.mode == ATTR_WDUMMY) | ||
3355 | continue; | ||
3304 | if(ena_sel && selected(x, y)) | 3356 | if(ena_sel && selected(x, y)) |
3305 | new.mode ^= ATTR_REVERSE; | 3357 | new.mode ^= ATTR_REVERSE; |
3306 | if(ib > 0 && (ATTRCMP(base, new) | 3358 | if(ib > 0 && (ATTRCMP(base, new) |
@@ -3313,10 +3365,10 @@ drawregion(int x1, int y1, int x2, int y2) { | |||
3313 | base = new; | 3365 | base = new; |
3314 | } | 3366 | } |
3315 | 3367 | ||
3316 | sl = utf8size(new.c); | 3368 | sl = utf8decode(new.c, &u8char); |
3317 | memcpy(buf+ib, new.c, sl); | 3369 | memcpy(buf+ib, new.c, sl); |
3318 | ib += sl; | 3370 | ib += sl; |
3319 | ++ic; | 3371 | ic += (new.mode & ATTR_WIDE)? 2 : 1; |
3320 | } | 3372 | } |
3321 | if(ib > 0) | 3373 | if(ib > 0) |
3322 | xdraws(buf, base, ox, y, ic, ib); | 3374 | xdraws(buf, base, ox, y, ic, ib); |