aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurélien Aptel <aurelien.aptel@gmail.com>2010-11-18 01:00:04 +0100
committerAurélien Aptel <aurelien.aptel@gmail.com>2010-11-18 01:00:04 +0100
commitdb3a27c8e643ea223a91238f868c3c244b41d7ef (patch)
treec45b32598a5beecc045952774374feed73779fce
parentf8d22ad159eeffc8c1f2bde2b3c437f99e6d7ae2 (diff)
downloadst-patched-db3a27c8e643ea223a91238f868c3c244b41d7ef.tar.bz2
st-patched-db3a27c8e643ea223a91238f868c3c244b41d7ef.tar.xz
st-patched-db3a27c8e643ea223a91238f868c3c244b41d7ef.zip
utf8 support! print text in delicious unicode greatness! all hail to the glorious Damian Okrasa for the patch!
TERM set back to xterm. changed default fonts. Note: drawing is now (even) slower.
-rw-r--r--config.def.h29
-rw-r--r--st.c322
2 files changed, 260 insertions, 91 deletions
diff --git a/config.def.h b/config.def.h
index 36982db..b33e9b6 100644
--- a/config.def.h
+++ b/config.def.h
@@ -1,7 +1,7 @@
1#define TAB 8 1#define TAB 8
2#define TNAME "st-256color" 2#define TNAME "xterm"
3#define FONT "-misc-*-medium-r-semicondensed-*-13-*-*-*-*-*-iso8859-*" 3#define FONT "-*-*-medium-r-*-*-*-120-75-75-*-60-*-*"
4#define BOLDFONT "-misc-*-bold-r-semicondensed-*-13-*-*-*-*-*-iso8859-*" 4#define BOLDFONT "-*-*-bold-r-*-*-*-120-75-75-*-60-*-*"
5#define BORDER 2 5#define BORDER 2
6#define SHELL "/bin/sh" 6#define SHELL "/bin/sh"
7 7
@@ -55,31 +55,8 @@ static Key key[] = {
55 55
56/* Line drawing characters (sometime specific to each font...) */ 56/* Line drawing characters (sometime specific to each font...) */
57static char gfx[] = { 57static char gfx[] = {
58 ['`'] = 0x01,
59 ['a'] = 0x02,
60 ['f'] = 'o', 58 ['f'] = 'o',
61 ['g'] = '+', 59 ['g'] = '+',
62 ['i'] = '#', 60 ['i'] = '#',
63 ['j'] = 0x0B,
64 ['k'] = 0x0C,
65 ['l'] = 0x0D,
66 ['m'] = 0x0E,
67 ['n'] = 0x0F,
68 ['o'] = 0x10,
69 ['p'] = 0x11,
70 ['q'] = 0x12,
71 ['r'] = 0x13,
72 ['s'] = 0x14,
73 ['t'] = 0x15,
74 ['u'] = 0x16,
75 ['v'] = 0x17,
76 ['w'] = 0x18,
77 ['x'] = 0x19,
78 ['y'] = 0x1A,
79 ['z'] = 0x1B,
80 ['{'] = 0x1C,
81 ['|'] = 0x1D,
82 ['}'] = 0x1E,
83 ['~'] = 0x1F,
84 [255] = 0, 61 [255] = 0,
85}; 62};
diff --git a/st.c b/st.c
index 895519d..da72497 100644
--- a/st.c
+++ b/st.c
@@ -38,6 +38,7 @@
38#define ESC_BUF_SIZ 256 38#define ESC_BUF_SIZ 256
39#define ESC_ARG_SIZ 16 39#define ESC_ARG_SIZ 16
40#define DRAW_BUF_SIZ 1024 40#define DRAW_BUF_SIZ 1024
41#define UTF_SIZ 4
41 42
42#define SERRNO strerror(errno) 43#define SERRNO strerror(errno)
43#define MIN(a, b) ((a) < (b) ? (a) : (b)) 44#define MIN(a, b) ((a) < (b) ? (a) : (b))
@@ -61,8 +62,11 @@ enum { ESC_START=1, ESC_CSI=2, ESC_OSC=4, ESC_TITLE=8, ESC_ALTCHARSET=16 };
61enum { SCREEN_UPDATE, SCREEN_REDRAW }; 62enum { SCREEN_UPDATE, SCREEN_REDRAW };
62enum { WIN_VISIBLE=1, WIN_REDRAW=2, WIN_FOCUSED=4 }; 63enum { WIN_VISIBLE=1, WIN_REDRAW=2, WIN_FOCUSED=4 };
63 64
65#undef B0
66enum { B0=1, B1=2, B2=4, B3=8, B4=16, B5=32, B6=64, B7=128 };
67
64typedef struct { 68typedef struct {
65 char c; /* character code */ 69 char c[UTF_SIZ]; /* character code */
66 char mode; /* attribute flags */ 70 char mode; /* attribute flags */
67 int fg; /* foreground */ 71 int fg; /* foreground */
68 int bg; /* background */ 72 int bg; /* background */
@@ -127,11 +131,19 @@ typedef struct {
127 char s[ESC_BUF_SIZ]; 131 char s[ESC_BUF_SIZ];
128} Key; 132} Key;
129 133
134typedef struct {
135 XFontSet fs;
136 short lbearing;
137 short rbearing;
138 int ascent;
139 int descent;
140} FontInfo;
141
130/* Drawing Context */ 142/* Drawing Context */
131typedef struct { 143typedef struct {
132 unsigned long col[256]; 144 unsigned long col[256];
133 XFontStruct* font; 145 FontInfo font;
134 XFontStruct* bfont; 146 FontInfo bfont;
135 GC gc; 147 GC gc;
136} DC; 148} DC;
137 149
@@ -167,14 +179,13 @@ static void tmoveto(int, int);
167static void tnew(int, int); 179static void tnew(int, int);
168static void tnewline(int); 180static void tnewline(int);
169static void tputtab(void); 181static void tputtab(void);
170static void tputc(char); 182static void tputc(char*);
171static void tputs(char*, int);
172static void treset(void); 183static void treset(void);
173static int tresize(int, int); 184static int tresize(int, int);
174static void tscrollup(int, int); 185static void tscrollup(int, int);
175static void tscrolldown(int, int); 186static void tscrolldown(int, int);
176static void tsetattr(int*, int); 187static void tsetattr(int*, int);
177static void tsetchar(char); 188static void tsetchar(char*);
178static void tsetscroll(int, int); 189static void tsetscroll(int, int);
179static void tswapscreen(void); 190static void tswapscreen(void);
180 191
@@ -183,7 +194,7 @@ static void ttyread(void);
183static void ttyresize(int, int); 194static void ttyresize(int, int);
184static void ttywrite(const char *, size_t); 195static void ttywrite(const char *, size_t);
185 196
186static void xdraws(char *, Glyph, int, int, int); 197static void xdraws(char *, Glyph, int, int, int, int);
187static void xhints(void); 198static void xhints(void);
188static void xclear(int, int, int, int); 199static void xclear(int, int, int, int);
189static void xdrawcursor(void); 200static void xdrawcursor(void);
@@ -205,6 +216,11 @@ static void bmotion(XEvent *);
205static void selection_notify(XEvent *); 216static void selection_notify(XEvent *);
206static void selection_request(XEvent *); 217static void selection_request(XEvent *);
207 218
219static int stou(char *, long *);
220static int utos(long *, char *);
221static int slen(char *);
222static int canstou(char *, int);
223
208static void (*handler[LASTEvent])(XEvent *) = { 224static void (*handler[LASTEvent])(XEvent *) = {
209 [KeyPress] = kpress, 225 [KeyPress] = kpress,
210 [ConfigureNotify] = resize, 226 [ConfigureNotify] = resize,
@@ -231,6 +247,133 @@ static Selection sel;
231static char *opt_cmd = NULL; 247static char *opt_cmd = NULL;
232static char *opt_title = NULL; 248static char *opt_title = NULL;
233 249
250/* UTF-8 decode */
251static int
252stou(char *s, long *u)
253{
254 unsigned char c;
255 int i, n, rtn;
256
257 rtn = 1;
258 c = *s;
259 if(~c&B7) { /* 0xxxxxxx */
260 *u = c;
261 return rtn;
262 } else if ((c&(B7|B6|B5)) == (B7|B6)) { /* 110xxxxx */
263 *u = c&(B4|B3|B2|B1|B0);
264 n = 1;
265 } else if ((c&(B7|B6|B5|B4)) == (B7|B6|B5)) { /* 1110xxxx */
266 *u = c&(B3|B2|B1|B0);
267 n = 2;
268 } else if ((c&(B7|B6|B5|B4|B3)) == (B7|B6|B5|B4)) { /* 11110xxx */
269 *u = c&(B2|B1|B0);
270 n = 3;
271 } else
272 goto invalid;
273 for (i=n,++s; i>0; --i,++rtn,++s) {
274 c = *s;
275 if ((c&(B7|B6)) != B7) /* 10xxxxxx */
276 goto invalid;
277 *u <<= 6;
278 *u |= c&(B5|B4|B3|B2|B1|B0);
279 }
280 if ((n == 1 && *u < 0x80) ||
281 (n == 2 && *u < 0x800) ||
282 (n == 3 && *u < 0x10000) ||
283 (*u >= 0xD800 && *u <= 0xDFFF))
284 goto invalid;
285 return rtn;
286invalid:
287 *u = 0xFFFD;
288 return rtn;
289}
290
291/* UTF-8 encode */
292static int
293utos(long *u, char *s)
294{
295 unsigned char *sp;
296 unsigned long uc;
297 int i, n;
298
299 sp = (unsigned char*) s;
300 uc = *u;
301 if (uc < 0x80) {
302 *sp = uc; /* 0xxxxxxx */
303 return 1;
304 } else if (*u < 0x800) {
305 *sp = (uc >> 6) | (B7|B6); /* 110xxxxx */
306 n = 1;
307 } else if (uc < 0x10000) {
308 *sp = (uc >> 12) | (B7|B6|B5); /* 1110xxxx */
309 n = 2;
310 } else if (uc <= 0x10FFFF) {
311 *sp = (uc >> 18) | (B7|B6|B5|B4); /* 11110xxx */
312 n = 3;
313 } else {
314 goto invalid;
315 }
316 for (i=n,++sp; i>0; --i,++sp)
317 *sp = ((uc >> 6*(i-1)) & (B5|B4|B3|B2|B1|B0)) | B7; /* 10xxxxxx */
318 return n+1;
319invalid:
320 /* U+FFFD */
321 *s++ = '\xEF';
322 *s++ = '\xBF';
323 *s = '\xBD';
324 return 3;
325}
326
327/*
328 * use this if your buffer is less than UTF_SIZ, it returns 1 if you can decode UTF-8
329 * otherwise return 0
330 */
331static int
332canstou(char *s, int b)
333{
334 unsigned char c;
335 int n;
336
337 c = *s;
338 if (b < 1)
339 return 0;
340 else if (~c&B7)
341 return 1;
342 else if ((c&(B7|B6|B5)) == (B7|B6))
343 n = 1;
344 else if ((c&(B7|B6|B5|B4)) == (B7|B6|B5))
345 n = 2;
346 else if ((c&(B7|B6|B5|B4|B3)) == (B7|B6|B5|B4))
347 n = 3;
348 else
349 return 1;
350 for (--b,++s; n>0&&b>0; --n,--b,++s) {
351 c = *s;
352 if ((c&(B7|B6)) != B7)
353 break;
354 }
355 if (n > 0 && b == 0)
356 return 0;
357 else
358 return 1;
359}
360
361static int
362slen(char *s)
363{
364 unsigned char c;
365
366 c = *s;
367 if (~c&B7)
368 return 1;
369 else if ((c&(B7|B6|B5)) == (B7|B6))
370 return 2;
371 else if ((c&(B7|B6|B5|B4)) == (B7|B6|B5))
372 return 3;
373 else
374 return 4;
375}
376
234void 377void
235selinit(void) { 378selinit(void) {
236 sel.mode = 0; 379 sel.mode = 0;
@@ -268,15 +411,18 @@ static void bpress(XEvent *e) {
268 411
269static char *getseltext() { 412static char *getseltext() {
270 char *str, *ptr; 413 char *str, *ptr;
271 int ls, x, y, sz; 414 int ls, x, y, sz, sl;
272 if(sel.bx == -1) 415 if(sel.bx == -1)
273 return NULL; 416 return NULL;
274 sz = (term.col+1) * (sel.e.y-sel.b.y+1); 417 sz = (term.col+1) * (sel.e.y-sel.b.y+1) * UTF_SIZ;
275 ptr = str = malloc(sz); 418 ptr = str = malloc(sz);
276 for(y = 0; y < term.row; y++) { 419 for(y = 0; y < term.row; y++) {
277 for(x = 0; x < term.col; x++) 420 for(x = 0; x < term.col; x++)
278 if(term.line[y][x].state & GLYPH_SET && (ls = selected(x, y))) 421 if(term.line[y][x].state & GLYPH_SET && (ls = selected(x, y))) {
279 *ptr = term.line[y][x].c, ptr++; 422 sl = slen(term.line[y][x].c);
423 memcpy(ptr, term.line[y][x].c, sl);
424 ptr += sl;
425 }
280 if(ls) 426 if(ls)
281 *ptr = '\n', ptr++; 427 *ptr = '\n', ptr++;
282 } 428 }
@@ -476,13 +622,24 @@ dump(char c) {
476 622
477void 623void
478ttyread(void) { 624ttyread(void) {
479 char buf[BUFSIZ]; 625 char buf[BUFSIZ], *ptr;
480 int ret; 626 char s[UTF_SIZ];
627 int ret, br;
628 static int buflen = 0;
629 long u;
481 630
482 if((ret = read(cmdfd, buf, LEN(buf))) < 0) 631 if((ret = read(cmdfd, buf+buflen, LEN(buf)-buflen)) < 0)
483 die("Couldn't read from shell: %s\n", SERRNO); 632 die("Couldn't read from shell: %s\n", SERRNO);
484 else 633 else {
485 tputs(buf, ret); 634 buflen += ret;
635 for(ptr=buf; buflen>=UTF_SIZ||canstou(ptr,buflen); buflen-=br) {
636 br = stou(ptr, &u);
637 utos(&u, s);
638 tputc(s);
639 ptr += br;
640 }
641 memcpy(buf, ptr, buflen);
642 }
486} 643}
487 644
488void 645void
@@ -622,9 +779,9 @@ tmoveto(int x, int y) {
622} 779}
623 780
624void 781void
625tsetchar(char c) { 782tsetchar(char *c) {
626 term.line[term.c.y][term.c.x] = term.c.attr; 783 term.line[term.c.y][term.c.x] = term.c.attr;
627 term.line[term.c.y][term.c.x].c = c; 784 memcpy(term.line[term.c.y][term.c.x].c, c, UTF_SIZ);
628 term.line[term.c.y][term.c.x].state |= GLYPH_SET; 785 term.line[term.c.y][term.c.x].state |= GLYPH_SET;
629} 786}
630 787
@@ -1025,30 +1182,31 @@ tputtab(void) {
1025} 1182}
1026 1183
1027void 1184void
1028tputc(char c) { 1185tputc(char *c) {
1186 char ascii = *c;
1029 if(term.esc & ESC_START) { 1187 if(term.esc & ESC_START) {
1030 if(term.esc & ESC_CSI) { 1188 if(term.esc & ESC_CSI) {
1031 escseq.buf[escseq.len++] = c; 1189 escseq.buf[escseq.len++] = ascii;
1032 if(BETWEEN(c, 0x40, 0x7E) || escseq.len >= ESC_BUF_SIZ) { 1190 if(BETWEEN(ascii, 0x40, 0x7E) || escseq.len >= ESC_BUF_SIZ) {
1033 term.esc = 0; 1191 term.esc = 0;
1034 csiparse(), csihandle(); 1192 csiparse(), csihandle();
1035 } 1193 }
1036 /* TODO: handle other OSC */ 1194 /* TODO: handle other OSC */
1037 } else if(term.esc & ESC_OSC) { 1195 } else if(term.esc & ESC_OSC) {
1038 if(c == ';') { 1196 if(ascii == ';') {
1039 term.titlelen = 0; 1197 term.titlelen = 0;
1040 term.esc = ESC_START | ESC_TITLE; 1198 term.esc = ESC_START | ESC_TITLE;
1041 } 1199 }
1042 } else if(term.esc & ESC_TITLE) { 1200 } else if(term.esc & ESC_TITLE) {
1043 if(c == '\a' || term.titlelen+1 >= ESC_TITLE_SIZ) { 1201 if(ascii == '\a' || term.titlelen+1 >= ESC_TITLE_SIZ) {
1044 term.esc = 0; 1202 term.esc = 0;
1045 term.title[term.titlelen] = '\0'; 1203 term.title[term.titlelen] = '\0';
1046 XStoreName(xw.dis, xw.win, term.title); 1204 XStoreName(xw.dis, xw.win, term.title);
1047 } else { 1205 } else {
1048 term.title[term.titlelen++] = c; 1206 term.title[term.titlelen++] = ascii;
1049 } 1207 }
1050 } else if(term.esc & ESC_ALTCHARSET) { 1208 } else if(term.esc & ESC_ALTCHARSET) {
1051 switch(c) { 1209 switch(ascii) {
1052 case '0': /* Line drawing crap */ 1210 case '0': /* Line drawing crap */
1053 term.c.attr.mode |= ATTR_GFX; 1211 term.c.attr.mode |= ATTR_GFX;
1054 break; 1212 break;
@@ -1056,11 +1214,11 @@ tputc(char c) {
1056 term.c.attr.mode &= ~ATTR_GFX; 1214 term.c.attr.mode &= ~ATTR_GFX;
1057 break; 1215 break;
1058 default: 1216 default:
1059 printf("esc unhandled charset: ESC ( %c\n", c); 1217 printf("esc unhandled charset: ESC ( %c\n", ascii);
1060 } 1218 }
1061 term.esc = 0; 1219 term.esc = 0;
1062 } else { 1220 } else {
1063 switch(c) { 1221 switch(ascii) {
1064 case '[': 1222 case '[':
1065 term.esc |= ESC_CSI; 1223 term.esc |= ESC_CSI;
1066 break; 1224 break;
@@ -1109,12 +1267,13 @@ tputc(char c) {
1109 term.esc = 0; 1267 term.esc = 0;
1110 break; 1268 break;
1111 default: 1269 default:
1112 fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", c, isprint(c)?c:'.'); 1270 fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n",
1271 (unsigned char) ascii, isprint(ascii)?ascii:'.');
1113 term.esc = 0; 1272 term.esc = 0;
1114 } 1273 }
1115 } 1274 }
1116 } else { 1275 } else {
1117 switch(c) { 1276 switch(ascii) {
1118 case '\t': 1277 case '\t':
1119 tputtab(); 1278 tputtab();
1120 break; 1279 break;
@@ -1151,12 +1310,6 @@ tputc(char c) {
1151 } 1310 }
1152} 1311}
1153 1312
1154void
1155tputs(char *s, int len) {
1156 for(; len > 0; len--)
1157 tputc(*s++);
1158}
1159
1160int 1313int
1161tresize(int col, int row) { 1314tresize(int col, int row) {
1162 int i, x; 1315 int i, x;
@@ -1309,20 +1462,52 @@ xhints(void)
1309} 1462}
1310 1463
1311void 1464void
1465xsetfontinfo(FontInfo *fi)
1466{
1467 XFontStruct **xfonts;
1468 int fnum;
1469 int i;
1470 char **fontnames;
1471
1472 fi->lbearing = 0;
1473 fi->rbearing = 0;
1474 fi->ascent = 0;
1475 fi->descent = 0;
1476 fnum = XFontsOfFontSet(fi->fs, &xfonts, &fontnames);
1477 for(i=0; i<fnum; i++,xfonts++,fontnames++) {
1478 puts(*fontnames);
1479 if(fi->ascent < (*xfonts)->ascent)
1480 fi->ascent = (*xfonts)->ascent;
1481 if(fi->descent < (*xfonts)->descent)
1482 fi->descent = (*xfonts)->descent;
1483 if(fi->rbearing < (*xfonts)->max_bounds.rbearing)
1484 fi->rbearing = (*xfonts)->max_bounds.rbearing;
1485 if(fi->lbearing < (*xfonts)->min_bounds.lbearing)
1486 fi->lbearing = (*xfonts)->min_bounds.lbearing;
1487 }
1488}
1489
1490void
1312xinit(void) { 1491xinit(void) {
1313 XSetWindowAttributes attrs; 1492 XSetWindowAttributes attrs;
1493 char **mc;
1494 char *ds;
1495 int nmc;
1314 1496
1315 if(!(xw.dis = XOpenDisplay(NULL))) 1497 if(!(xw.dis = XOpenDisplay(NULL)))
1316 die("Can't open display\n"); 1498 die("Can't open display\n");
1317 xw.scr = XDefaultScreen(xw.dis); 1499 xw.scr = XDefaultScreen(xw.dis);
1318 1500
1319 /* font */ 1501 /* font */
1320 if(!(dc.font = XLoadQueryFont(xw.dis, FONT)) || !(dc.bfont = XLoadQueryFont(xw.dis, BOLDFONT))) 1502 if ((dc.font.fs = XCreateFontSet(xw.dis, FONT, &mc, &nmc, &ds)) == NULL ||
1321 die("Can't load font %s\n", dc.font ? BOLDFONT : FONT); 1503 (dc.bfont.fs = XCreateFontSet(xw.dis, BOLDFONT, &mc, &nmc, &ds)) == NULL)
1504 die("Can't load font %s\n", dc.font.fs ? BOLDFONT : FONT);
1505 xsetfontinfo(&dc.font);
1506 xsetfontinfo(&dc.bfont);
1322 1507
1323 /* XXX: Assuming same size for bold font */ 1508 /* XXX: Assuming same size for bold font */
1324 xw.cw = dc.font->max_bounds.rbearing - dc.font->min_bounds.lbearing; 1509 xw.cw = dc.font.rbearing - dc.font.lbearing;
1325 xw.ch = dc.font->ascent + dc.font->descent; 1510 xw.ch = dc.font.ascent + dc.font.descent;
1326 1511
1327 /* colors */ 1512 /* colors */
1328 xw.cmap = XDefaultColormap(xw.dis, xw.scr); 1513 xw.cmap = XDefaultColormap(xw.dis, xw.scr);
@@ -1366,9 +1551,9 @@ xinit(void) {
1366} 1551}
1367 1552
1368void 1553void
1369xdraws(char *s, Glyph base, int x, int y, int len) { 1554xdraws(char *s, Glyph base, int x, int y, int cl, int sl) {
1370 unsigned long xfg, xbg; 1555 unsigned long xfg, xbg;
1371 int winx = x*xw.cw, winy = y*xw.ch + dc.font->ascent, width = len*xw.cw; 1556 int winx = x*xw.cw, winy = y*xw.ch + dc.font.ascent, width = cl*xw.cw;
1372 int i; 1557 int i;
1373 1558
1374 if(base.mode & ATTR_REVERSE) 1559 if(base.mode & ATTR_REVERSE)
@@ -1378,9 +1563,9 @@ xdraws(char *s, Glyph base, int x, int y, int len) {
1378 1563
1379 XSetBackground(xw.dis, dc.gc, xbg); 1564 XSetBackground(xw.dis, dc.gc, xbg);
1380 XSetForeground(xw.dis, dc.gc, xfg); 1565 XSetForeground(xw.dis, dc.gc, xfg);
1381 1566
1382 if(base.mode & ATTR_GFX) 1567 if(base.mode & ATTR_GFX)
1383 for(i = 0; i < len; i++) { 1568 for(i = 0; i < cl; i++) {
1384 char c = gfx[(unsigned int)s[i] % 256]; 1569 char c = gfx[(unsigned int)s[i] % 256];
1385 if(c) 1570 if(c)
1386 s[i] = c; 1571 s[i] = c;
@@ -1388,8 +1573,8 @@ xdraws(char *s, Glyph base, int x, int y, int len) {
1388 s[i] -= 0x5f; 1573 s[i] -= 0x5f;
1389 } 1574 }
1390 1575
1391 XSetFont(xw.dis, dc.gc, base.mode & ATTR_BOLD ? dc.bfont->fid : dc.font->fid); 1576 XmbDrawImageString(xw.dis, xw.buf, base.mode & ATTR_BOLD ? dc.bfont.fs : dc.font.fs,
1392 XDrawImageString(xw.dis, xw.buf, dc.gc, winx, winy, s, len); 1577 dc.gc, winx, winy, s, sl);
1393 1578
1394 if(base.mode & ATTR_UNDERLINE) 1579 if(base.mode & ATTR_UNDERLINE)
1395 XDrawLine(xw.dis, xw.buf, dc.gc, winx, winy+1, winx+width-1, winy+1); 1580 XDrawLine(xw.dis, xw.buf, dc.gc, winx, winy+1, winx+width-1, winy+1);
@@ -1399,23 +1584,26 @@ void
1399xdrawcursor(void) { 1584xdrawcursor(void) {
1400 static int oldx = 0; 1585 static int oldx = 0;
1401 static int oldy = 0; 1586 static int oldy = 0;
1402 Glyph g = {' ', ATTR_NULL, DefaultBG, DefaultCS, 0}; 1587 int sl;
1588 Glyph g = {{' '}, ATTR_NULL, DefaultBG, DefaultCS, 0};
1403 1589
1404 LIMIT(oldx, 0, term.col-1); 1590 LIMIT(oldx, 0, term.col-1);
1405 LIMIT(oldy, 0, term.row-1); 1591 LIMIT(oldy, 0, term.row-1);
1406 1592
1407 if(term.line[term.c.y][term.c.x].state & GLYPH_SET) 1593 if(term.line[term.c.y][term.c.x].state & GLYPH_SET)
1408 g.c = term.line[term.c.y][term.c.x].c; 1594 memcpy(g.c, term.line[term.c.y][term.c.x].c, UTF_SIZ);
1409 1595
1410 /* remove the old cursor */ 1596 /* remove the old cursor */
1411 if(term.line[oldy][oldx].state & GLYPH_SET) 1597 if(term.line[oldy][oldx].state & GLYPH_SET) {
1412 xdraws(&term.line[oldy][oldx].c, term.line[oldy][oldx], oldx, oldy, 1); 1598 sl = slen(term.line[oldy][oldx].c);
1413 else 1599 xdraws(term.line[oldy][oldx].c, term.line[oldy][oldx], oldx, oldy, 1, sl);
1600 } else
1414 xclear(oldx, oldy, oldx, oldy); 1601 xclear(oldx, oldy, oldx, oldy);
1415 1602
1416 /* draw the new one */ 1603 /* draw the new one */
1417 if(!(term.c.state & CURSOR_HIDE) && (xw.state & WIN_FOCUSED)) { 1604 if(!(term.c.state & CURSOR_HIDE) && (xw.state & WIN_FOCUSED)) {
1418 xdraws(&g.c, g, term.c.x, term.c.y, 1); 1605 sl = slen(g.c);
1606 xdraws(g.c, g, term.c.x, term.c.y, 1, sl);
1419 oldx = term.c.x, oldy = term.c.y; 1607 oldx = term.c.x, oldy = term.c.y;
1420 } 1608 }
1421} 1609}
@@ -1424,11 +1612,12 @@ xdrawcursor(void) {
1424/* basic drawing routines */ 1612/* basic drawing routines */
1425void 1613void
1426xdrawc(int x, int y, Glyph g) { 1614xdrawc(int x, int y, Glyph g) {
1615 int sl = slen(g.c);
1427 XRectangle r = { x * xw.cw, y * xw.ch, xw.cw, xw.ch }; 1616 XRectangle r = { x * xw.cw, y * xw.ch, xw.cw, xw.ch };
1428 XSetBackground(xw.dis, dc.gc, dc.col[g.bg]); 1617 XSetBackground(xw.dis, dc.gc, dc.col[g.bg]);
1429 XSetForeground(xw.dis, dc.gc, dc.col[g.fg]); 1618 XSetForeground(xw.dis, dc.gc, dc.col[g.fg]);
1430 XSetFont(xw.dis, dc.gc, g.mode & ATTR_BOLD ? dc.bfont->fid : dc.font->fid); 1619 XmbDrawImageString(xw.dis, xw.buf, g.mode&ATTR_BOLD?dc.bfont.fs:dc.font.fs,
1431 XDrawImageString(xw.dis, xw.buf, dc.gc, r.x, r.y+dc.font->ascent, &g.c, 1); 1620 dc.gc, r.x, r.y+dc.font.ascent, g.c, sl);
1432} 1621}
1433 1622
1434void 1623void
@@ -1450,7 +1639,7 @@ draw(int dummy) {
1450/* optimized drawing routine */ 1639/* optimized drawing routine */
1451void 1640void
1452draw(int redraw_all) { 1641draw(int redraw_all) {
1453 int i, x, y, ox; 1642 int ic, ib, x, y, ox, sl;
1454 Glyph base, new; 1643 Glyph base, new;
1455 char buf[DRAW_BUF_SIZ]; 1644 char buf[DRAW_BUF_SIZ];
1456 1645
@@ -1460,26 +1649,29 @@ draw(int redraw_all) {
1460 xclear(0, 0, term.col-1, term.row-1); 1649 xclear(0, 0, term.col-1, term.row-1);
1461 for(y = 0; y < term.row; y++) { 1650 for(y = 0; y < term.row; y++) {
1462 base = term.line[y][0]; 1651 base = term.line[y][0];
1463 i = ox = 0; 1652 ic = ib = ox = 0;
1464 for(x = 0; x < term.col; x++) { 1653 for(x = 0; x < term.col; x++) {
1465 new = term.line[y][x]; 1654 new = term.line[y][x];
1466 if(sel.bx!=-1 && new.c && selected(x, y)) 1655 if(sel.bx!=-1 && *(new.c) && selected(x, y))
1467 new.mode ^= ATTR_REVERSE; 1656 new.mode ^= ATTR_REVERSE;
1468 if(i > 0 && (!(new.state & GLYPH_SET) || ATTRCMP(base, new) || 1657 if(ib > 0 && (!(new.state & GLYPH_SET) || ATTRCMP(base, new) ||
1469 i >= DRAW_BUF_SIZ)) { 1658 ib >= DRAW_BUF_SIZ-UTF_SIZ)) {
1470 xdraws(buf, base, ox, y, i); 1659 xdraws(buf, base, ox, y, ic, ib);
1471 i = 0; 1660 ic = ib = 0;
1472 } 1661 }
1473 if(new.state & GLYPH_SET) { 1662 if(new.state & GLYPH_SET) {
1474 if(i == 0) { 1663 if(ib == 0) {
1475 ox = x; 1664 ox = x;
1476 base = new; 1665 base = new;
1477 } 1666 }
1478 buf[i++] = new.c; 1667 sl = slen(new.c);
1668 memcpy(buf+ib, new.c, sl);
1669 ib += sl;
1670 ++ic;
1479 } 1671 }
1480 } 1672 }
1481 if(i > 0) 1673 if(ib > 0)
1482 xdraws(buf, base, ox, y, i); 1674 xdraws(buf, base, ox, y, ic, ib);
1483 } 1675 }
1484 xdrawcursor(); 1676 xdrawcursor();
1485 XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, 0, 0, xw.bufw, xw.bufh, BORDER, BORDER); 1677 XCopyArea(xw.dis, xw.buf, xw.win, dc.gc, 0, 0, xw.bufw, xw.bufh, BORDER, BORDER);