aboutsummaryrefslogtreecommitdiff
path: root/st.c
diff options
context:
space:
mode:
authorChristoph Lohmann <20h@r-36.net>2013-09-07 12:41:36 +0200
committerChristoph Lohmann <20h@r-36.net>2013-09-07 12:41:36 +0200
commit210dda9570095443bac887c2bfcd75f2bcc23780 (patch)
tree91136e0906b2443653858bdddb1e4669c8854876 /st.c
parenta4358a1fbd1c71269129404c9af4f539b2d7627c (diff)
downloadst-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.c84
1 files changed, 68 insertions, 16 deletions
diff --git a/st.c b/st.c
index 0fa0c86..96d45bf 100644
--- a/st.c
+++ b/st.c
@@ -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
101enum cursor_movement { 104enum cursor_movement {
@@ -165,7 +168,7 @@ typedef unsigned short ushort;
165 168
166typedef struct { 169typedef 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
2222tputc(char *c, int len) { 2240tputc(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) {
3193void 3231void
3194xdrawcursor(void) { 3232xdrawcursor(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);