|
@ -27,6 +27,7 @@ |
|
|
#include <X11/keysym.h> |
|
|
#include <X11/keysym.h> |
|
|
#include <X11/Xft/Xft.h> |
|
|
#include <X11/Xft/Xft.h> |
|
|
#include <fontconfig/fontconfig.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_ITALIC = 16, |
|
|
ATTR_BLINK = 32, |
|
|
ATTR_BLINK = 32, |
|
|
ATTR_WRAP = 64, |
|
|
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 { |
|
|
typedef struct { |
|
|
char c[UTF_SIZ]; /* character code */ |
|
|
char c[UTF_SIZ]; /* character code */ |
|
|
uchar mode; /* attribute flags */ |
|
|
|
|
|
|
|
|
ushort mode; /* attribute flags */ |
|
|
ulong fg; /* foreground */ |
|
|
ulong fg; /* foreground */ |
|
|
ulong bg; /* background */ |
|
|
ulong bg; /* background */ |
|
|
} Glyph; |
|
|
} 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 */; |
|
|
/* nothing */; |
|
|
|
|
|
|
|
|
for(x = 0; gp <= last; x++, ++gp) { |
|
|
for(x = 0; gp <= last; x++, ++gp) { |
|
|
if(!selected(x, y)) |
|
|
|
|
|
|
|
|
if(!selected(x, y) || (gp->mode & ATTR_WDUMMY)) |
|
|
continue; |
|
|
continue; |
|
|
|
|
|
|
|
|
size = utf8size(gp->c); |
|
|
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.dirty[y] = 1; |
|
|
term.line[y][x] = *attr; |
|
|
term.line[y][x] = *attr; |
|
|
memcpy(term.line[y][x].c, c, UTF_SIZ); |
|
|
memcpy(term.line[y][x].c, c, UTF_SIZ); |
|
@ -2222,6 +2240,15 @@ void |
|
|
tputc(char *c, int len) { |
|
|
tputc(char *c, int len) { |
|
|
uchar ascii = *c; |
|
|
uchar ascii = *c; |
|
|
bool control = ascii < '\x20' || ascii == 0177; |
|
|
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(iofd != -1) { |
|
|
if(xwrite(iofd, c, len) < 0) { |
|
|
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 { |
|
|
} else { |
|
|
term.c.state |= CURSOR_WRAPNEXT; |
|
|
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, |
|
|
xp, winy + frc[i].font->ascent, |
|
|
(FcChar8 *)u8c, u8cblen); |
|
|
(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 |
|
|
void |
|
|
xdrawcursor(void) { |
|
|
xdrawcursor(void) { |
|
|
static int oldx = 0, oldy = 0; |
|
|
static int oldx = 0, oldy = 0; |
|
|
int sl; |
|
|
|
|
|
|
|
|
int sl, width, curx; |
|
|
Glyph g = {{' '}, ATTR_NULL, defaultbg, defaultcs}; |
|
|
Glyph g = {{' '}, ATTR_NULL, defaultbg, defaultcs}; |
|
|
|
|
|
|
|
|
LIMIT(oldx, 0, term.col-1); |
|
|
LIMIT(oldx, 0, term.col-1); |
|
|
LIMIT(oldy, 0, term.row-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); |
|
|
memcpy(g.c, term.line[term.c.y][term.c.x].c, UTF_SIZ); |
|
|
|
|
|
|
|
|
/* remove the old cursor */ |
|
|
/* remove the old cursor */ |
|
|
sl = utf8size(term.line[oldy][oldx].c); |
|
|
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 */ |
|
|
/* draw the new one */ |
|
|
if(!(IS_SET(MODE_HIDE))) { |
|
|
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 { |
|
|
} else { |
|
|
XftDrawRect(xw.draw, &dc.col[defaultcs], |
|
|
XftDrawRect(xw.draw, &dc.col[defaultcs], |
|
|
borderpx + term.c.x * xw.cw, |
|
|
|
|
|
|
|
|
borderpx + curx * xw.cw, |
|
|
borderpx + term.c.y * xw.ch, |
|
|
borderpx + term.c.y * xw.ch, |
|
|
xw.cw - 1, 1); |
|
|
xw.cw - 1, 1); |
|
|
XftDrawRect(xw.draw, &dc.col[defaultcs], |
|
|
XftDrawRect(xw.draw, &dc.col[defaultcs], |
|
|
borderpx + term.c.x * xw.cw, |
|
|
|
|
|
|
|
|
borderpx + curx * xw.cw, |
|
|
borderpx + term.c.y * xw.ch, |
|
|
borderpx + term.c.y * xw.ch, |
|
|
1, xw.ch - 1); |
|
|
1, xw.ch - 1); |
|
|
XftDrawRect(xw.draw, &dc.col[defaultcs], |
|
|
XftDrawRect(xw.draw, &dc.col[defaultcs], |
|
|
borderpx + (term.c.x + 1) * xw.cw - 1, |
|
|
|
|
|
|
|
|
borderpx + (curx + 1) * xw.cw - 1, |
|
|
borderpx + term.c.y * xw.ch, |
|
|
borderpx + term.c.y * xw.ch, |
|
|
1, xw.ch - 1); |
|
|
1, xw.ch - 1); |
|
|
XftDrawRect(xw.draw, &dc.col[defaultcs], |
|
|
XftDrawRect(xw.draw, &dc.col[defaultcs], |
|
|
borderpx + term.c.x * xw.cw, |
|
|
|
|
|
|
|
|
borderpx + curx * xw.cw, |
|
|
borderpx + (term.c.y + 1) * xw.ch - 1, |
|
|
borderpx + (term.c.y + 1) * xw.ch - 1, |
|
|
xw.cw, 1); |
|
|
xw.cw, 1); |
|
|
} |
|
|
} |
|
|
oldx = term.c.x, oldy = term.c.y; |
|
|
|
|
|
|
|
|
oldx = curx, oldy = term.c.y; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -3284,6 +3333,7 @@ drawregion(int x1, int y1, int x2, int y2) { |
|
|
Glyph base, new; |
|
|
Glyph base, new; |
|
|
char buf[DRAW_BUF_SIZ]; |
|
|
char buf[DRAW_BUF_SIZ]; |
|
|
bool ena_sel = sel.ob.x != -1; |
|
|
bool ena_sel = sel.ob.x != -1; |
|
|
|
|
|
long u8char; |
|
|
|
|
|
|
|
|
if(sel.alt ^ IS_SET(MODE_ALTSCREEN)) |
|
|
if(sel.alt ^ IS_SET(MODE_ALTSCREEN)) |
|
|
ena_sel = 0; |
|
|
ena_sel = 0; |
|
@ -3301,6 +3351,8 @@ drawregion(int x1, int y1, int x2, int y2) { |
|
|
ic = ib = ox = 0; |
|
|
ic = ib = ox = 0; |
|
|
for(x = x1; x < x2; x++) { |
|
|
for(x = x1; x < x2; x++) { |
|
|
new = term.line[y][x]; |
|
|
new = term.line[y][x]; |
|
|
|
|
|
if(new.mode == ATTR_WDUMMY) |
|
|
|
|
|
continue; |
|
|
if(ena_sel && selected(x, y)) |
|
|
if(ena_sel && selected(x, y)) |
|
|
new.mode ^= ATTR_REVERSE; |
|
|
new.mode ^= ATTR_REVERSE; |
|
|
if(ib > 0 && (ATTRCMP(base, new) |
|
|
if(ib > 0 && (ATTRCMP(base, new) |
|
@ -3313,10 +3365,10 @@ drawregion(int x1, int y1, int x2, int y2) { |
|
|
base = new; |
|
|
base = new; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
sl = utf8size(new.c); |
|
|
|
|
|
|
|
|
sl = utf8decode(new.c, &u8char); |
|
|
memcpy(buf+ib, new.c, sl); |
|
|
memcpy(buf+ib, new.c, sl); |
|
|
ib += sl; |
|
|
ib += sl; |
|
|
++ic; |
|
|
|
|
|
|
|
|
ic += (new.mode & ATTR_WIDE)? 2 : 1; |
|
|
} |
|
|
} |
|
|
if(ib > 0) |
|
|
if(ib > 0) |
|
|
xdraws(buf, base, ox, y, ic, ib); |
|
|
xdraws(buf, base, ox, y, ic, ib); |
|
|