Xinqi Bao's Git
projects
/
st.git
/ diff
summary
|
log
|
commit
|
diff
|
tree
raw
|
patch
|
inline
| side by side (parent:
a4358a1
)
Wide character support.
author
Christoph Lohmann <
[email protected]
>
Sat, 7 Sep 2013 10:41:36 +0000
(12:41 +0200)
committer
Christoph Lohmann <
[email protected]
>
Sat, 7 Sep 2013 10:41:36 +0000
(12:41 +0200)
Thanks "Eon S. Jeon" <
[email protected]
>!
TODO
diff
|
blob
|
history
st.c
diff
|
blob
|
history
diff --git
a/TODO
b/TODO
index
794b71b
..
0c538e5
100644
(file)
--- a/
TODO
+++ b/
TODO
@@
-1,7
+1,6
@@
vt emulation
------------
vt emulation
------------
-* wide-character support in conjunction with fallback xft code
* double-height support
code & interface
* double-height support
code & interface
diff --git
a/st.c
b/st.c
index
0fa0c86
..
96d45bf
100644
(file)
--- a/
st.c
+++ b/
st.c
@@
-27,6
+27,7
@@
#include <X11/keysym.h>
#include <X11/Xft/Xft.h>
#include <fontconfig/fontconfig.h>
#include <X11/keysym.h>
#include <X11/Xft/Xft.h>
#include <fontconfig/fontconfig.h>
+#include <wchar.h>
#include "arg.h"
#include "arg.h"
@@
-96,6
+97,8
@@
enum glyph_attribute {
ATTR_ITALIC = 16,
ATTR_BLINK = 32,
ATTR_WRAP = 64,
ATTR_ITALIC = 16,
ATTR_BLINK = 32,
ATTR_WRAP = 64,
+ ATTR_WIDE = 128,
+ ATTR_WDUMMY = 256,
};
enum cursor_movement {
};
enum cursor_movement {
@@
-165,7
+168,7
@@
typedef unsigned short ushort;
typedef struct {
char c[UTF_SIZ]; /* character code */
typedef struct {
char c[UTF_SIZ]; /* character code */
- u
char
mode; /* attribute flags */
+ u
short
mode; /* attribute flags */
ulong fg; /* foreground */
ulong bg; /* background */
} Glyph;
ulong fg; /* foreground */
ulong bg; /* background */
} Glyph;
@@
-719,8
+722,13
@@
selsnap(int mode, int *x, int *y, int direction) {
}
}
}
}
+ if(term.line[*y][*x+direction].mode & ATTR_WDUMMY) {
+ *x += direction;
+ continue;
+ }
+
if(strchr(worddelimiters,
if(strchr(worddelimiters,
- term.line[*y][*x
+
direction].c[0])) {
+ term.line[*y][*x
+
direction].c[0])) {
break;
}
break;
}
@@
-932,7
+940,7
@@
selcopy(void) {
/* nothing */;
for(x = 0; gp <= last; x++, ++gp) {
/* nothing */;
for(x = 0; gp <= last; x++, ++gp) {
- if(!selected(x, y))
+ if(!selected(x, y)
|| (gp->mode & ATTR_WDUMMY)
)
continue;
size = utf8size(gp->c);
continue;
size = utf8size(gp->c);
@@
-1533,6
+1541,16
@@
tsetchar(char *c, Glyph *attr, int x, int y) {
}
}
}
}
+ if(term.line[y][x].mode & ATTR_WIDE) {
+ if(x+1 < term.col) {
+ term.line[y][x+1].c[0] = ' ';
+ term.line[y][x+1].mode &= ~ATTR_WDUMMY;
+ }
+ } else if(term.line[y][x].mode & ATTR_WDUMMY) {
+ term.line[y][x-1].c[0] = ' ';
+ term.line[y][x-1].mode &= ~ATTR_WIDE;
+ }
+
term.dirty[y] = 1;
term.line[y][x] = *attr;
memcpy(term.line[y][x].c, c, UTF_SIZ);
term.dirty[y] = 1;
term.line[y][x] = *attr;
memcpy(term.line[y][x].c, c, UTF_SIZ);
@@
-2222,6
+2240,15
@@
void
tputc(char *c, int len) {
uchar ascii = *c;
bool control = ascii < '\x20' || ascii == 0177;
tputc(char *c, int len) {
uchar ascii = *c;
bool control = ascii < '\x20' || ascii == 0177;
+ long u8char;
+ int width;
+
+ if(len == 1) {
+ width = 1;
+ } else {
+ utf8decode(c, &u8char);
+ width = wcwidth(u8char);
+ }
if(iofd != -1) {
if(xwrite(iofd, c, len) < 0) {
if(iofd != -1) {
if(xwrite(iofd, c, len) < 0) {
@@
-2469,9
+2496,20
@@
tputc(char *c, int len) {
(term.col - term.c.x - 1) * sizeof(Glyph));
}
(term.col - term.c.x - 1) * sizeof(Glyph));
}
+ if(term.c.x+width > term.col)
+ tnewline(1);
+
tsetchar(c, &term.c.attr, term.c.x, term.c.y);
tsetchar(c, &term.c.attr, term.c.x, term.c.y);
- if(term.c.x+1 < term.col) {
- tmoveto(term.c.x+1, term.c.y);
+
+ if(width == 2) {
+ term.line[term.c.y][term.c.x].mode |= ATTR_WIDE;
+ if(term.c.x+1 < term.col) {
+ term.line[term.c.y][term.c.x+1].c[0] = '\0';
+ term.line[term.c.y][term.c.x+1].mode = ATTR_WDUMMY;
+ }
+ }
+ if(term.c.x+width < term.col) {
+ tmoveto(term.c.x+width, term.c.y);
} else {
term.c.state |= CURSOR_WRAPNEXT;
}
} else {
term.c.state |= CURSOR_WRAPNEXT;
}
@@
-3173,7
+3211,7
@@
xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
xp, winy + frc[i].font->ascent,
(FcChar8 *)u8c, u8cblen);
xp, winy + frc[i].font->ascent,
(FcChar8 *)u8c, u8cblen);
- xp += xw.cw;
+ xp += xw.cw
* wcwidth(u8char)
;
}
/*
}
/*
@@
-3193,18
+3231,27
@@
xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
void
xdrawcursor(void) {
static int oldx = 0, oldy = 0;
void
xdrawcursor(void) {
static int oldx = 0, oldy = 0;
- int sl;
+ int sl
, width, curx
;
Glyph g = {{' '}, ATTR_NULL, defaultbg, defaultcs};
LIMIT(oldx, 0, term.col-1);
LIMIT(oldy, 0, term.row-1);
Glyph g = {{' '}, ATTR_NULL, defaultbg, defaultcs};
LIMIT(oldx, 0, term.col-1);
LIMIT(oldy, 0, term.row-1);
+ curx = term.c.x;
+
+ /* adjust position if in dummy */
+ if(term.line[oldy][oldx].mode & ATTR_WDUMMY)
+ oldx--;
+ if(term.line[term.c.y][curx].mode & ATTR_WDUMMY)
+ curx--;
+
memcpy(g.c, term.line[term.c.y][term.c.x].c, UTF_SIZ);
/* remove the old cursor */
sl = utf8size(term.line[oldy][oldx].c);
memcpy(g.c, term.line[term.c.y][term.c.x].c, UTF_SIZ);
/* remove the old cursor */
sl = utf8size(term.line[oldy][oldx].c);
+ width = (term.line[oldy][oldx].mode & ATTR_WIDE)? 2 : 1;
xdraws(term.line[oldy][oldx].c, term.line[oldy][oldx], oldx,
xdraws(term.line[oldy][oldx].c, term.line[oldy][oldx], oldx,
- oldy,
1
, sl);
+ oldy,
width
, sl);
/* draw the new one */
if(!(IS_SET(MODE_HIDE))) {
/* draw the new one */
if(!(IS_SET(MODE_HIDE))) {
@@
-3216,26
+3263,28
@@
xdrawcursor(void) {
}
sl = utf8size(g.c);
}
sl = utf8size(g.c);
- xdraws(g.c, g, term.c.x, term.c.y, 1, sl);
+ width = (term.line[term.c.y][curx].mode & ATTR_WIDE)\
+ ? 2 : 1;
+ xdraws(g.c, g, term.c.x, term.c.y, width, sl);
} else {
XftDrawRect(xw.draw, &dc.col[defaultcs],
} else {
XftDrawRect(xw.draw, &dc.col[defaultcs],
- borderpx +
term.c.
x * xw.cw,
+ borderpx +
cur
x * xw.cw,
borderpx + term.c.y * xw.ch,
xw.cw - 1, 1);
XftDrawRect(xw.draw, &dc.col[defaultcs],
borderpx + term.c.y * xw.ch,
xw.cw - 1, 1);
XftDrawRect(xw.draw, &dc.col[defaultcs],
- borderpx +
term.c.
x * xw.cw,
+ borderpx +
cur
x * xw.cw,
borderpx + term.c.y * xw.ch,
1, xw.ch - 1);
XftDrawRect(xw.draw, &dc.col[defaultcs],
borderpx + term.c.y * xw.ch,
1, xw.ch - 1);
XftDrawRect(xw.draw, &dc.col[defaultcs],
- borderpx + (
term.c.
x + 1) * xw.cw - 1,
+ borderpx + (
cur
x + 1) * xw.cw - 1,
borderpx + term.c.y * xw.ch,
1, xw.ch - 1);
XftDrawRect(xw.draw, &dc.col[defaultcs],
borderpx + term.c.y * xw.ch,
1, xw.ch - 1);
XftDrawRect(xw.draw, &dc.col[defaultcs],
- borderpx +
term.c.
x * xw.cw,
+ borderpx +
cur
x * xw.cw,
borderpx + (term.c.y + 1) * xw.ch - 1,
xw.cw, 1);
}
borderpx + (term.c.y + 1) * xw.ch - 1,
xw.cw, 1);
}
- oldx =
term.c.
x, oldy = term.c.y;
+ oldx =
cur
x, oldy = term.c.y;
}
}
}
}
@@
-3284,6
+3333,7
@@
drawregion(int x1, int y1, int x2, int y2) {
Glyph base, new;
char buf[DRAW_BUF_SIZ];
bool ena_sel = sel.ob.x != -1;
Glyph base, new;
char buf[DRAW_BUF_SIZ];
bool ena_sel = sel.ob.x != -1;
+ long u8char;
if(sel.alt ^ IS_SET(MODE_ALTSCREEN))
ena_sel = 0;
if(sel.alt ^ IS_SET(MODE_ALTSCREEN))
ena_sel = 0;
@@
-3301,6
+3351,8
@@
drawregion(int x1, int y1, int x2, int y2) {
ic = ib = ox = 0;
for(x = x1; x < x2; x++) {
new = term.line[y][x];
ic = ib = ox = 0;
for(x = x1; x < x2; x++) {
new = term.line[y][x];
+ if(new.mode == ATTR_WDUMMY)
+ continue;
if(ena_sel && selected(x, y))
new.mode ^= ATTR_REVERSE;
if(ib > 0 && (ATTRCMP(base, new)
if(ena_sel && selected(x, y))
new.mode ^= ATTR_REVERSE;
if(ib > 0 && (ATTRCMP(base, new)
@@
-3313,10
+3365,10
@@
drawregion(int x1, int y1, int x2, int y2) {
base = new;
}
base = new;
}
- sl = utf8
size(new.c
);
+ sl = utf8
decode(new.c, &u8char
);
memcpy(buf+ib, new.c, sl);
ib += sl;
memcpy(buf+ib, new.c, sl);
ib += sl;
-
++ic
;
+
ic += (new.mode & ATTR_WIDE)? 2 : 1
;
}
if(ib > 0)
xdraws(buf, base, ox, y, ic, ib);
}
if(ib > 0)
xdraws(buf, base, ox, y, ic, ib);