|
|
|
@ -38,7 +38,7 @@
|
|
|
|
|
|
|
|
|
|
/* macros */
|
|
|
|
|
#define IS_SET(flag) ((term.mode & (flag)) != 0)
|
|
|
|
|
#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == 0x7f)
|
|
|
|
|
#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == '\177')
|
|
|
|
|
#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f))
|
|
|
|
|
#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c))
|
|
|
|
|
#define ISDELIM(u) (u && wcschr(worddelimiters, u))
|
|
|
|
@ -51,6 +51,7 @@ enum term_mode {
|
|
|
|
|
MODE_ECHO = 1 << 4,
|
|
|
|
|
MODE_PRINT = 1 << 5,
|
|
|
|
|
MODE_UTF8 = 1 << 6,
|
|
|
|
|
MODE_SIXEL = 1 << 7,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum cursor_movement {
|
|
|
|
@ -77,11 +78,12 @@ enum charset {
|
|
|
|
|
enum escape_state {
|
|
|
|
|
ESC_START = 1,
|
|
|
|
|
ESC_CSI = 2,
|
|
|
|
|
ESC_STR = 4, /* DCS, OSC, PM, APC */
|
|
|
|
|
ESC_STR = 4, /* OSC, PM, APC */
|
|
|
|
|
ESC_ALTCHARSET = 8,
|
|
|
|
|
ESC_STR_END = 16, /* a final string was encountered */
|
|
|
|
|
ESC_TEST = 32, /* Enter in test mode */
|
|
|
|
|
ESC_UTF8 = 64,
|
|
|
|
|
ESC_DCS =128,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
@ -127,7 +129,6 @@ typedef struct {
|
|
|
|
|
int charset; /* current charset */
|
|
|
|
|
int icharset; /* selected charset for sequence */
|
|
|
|
|
int *tabs;
|
|
|
|
|
Rune lastc; /* last printed char outside of sequence, 0 if control */
|
|
|
|
|
} Term;
|
|
|
|
|
|
|
|
|
|
/* CSI Escape sequence structs */
|
|
|
|
@ -161,7 +162,6 @@ static void csidump(void);
|
|
|
|
|
static void csihandle(void);
|
|
|
|
|
static void csiparse(void);
|
|
|
|
|
static void csireset(void);
|
|
|
|
|
static void osc_color_response(int, int, int);
|
|
|
|
|
static int eschandle(uchar);
|
|
|
|
|
static void strdump(void);
|
|
|
|
|
static void strhandle(void);
|
|
|
|
@ -187,17 +187,18 @@ static void tputc(Rune);
|
|
|
|
|
static void treset(void);
|
|
|
|
|
static void tscrollup(int, int);
|
|
|
|
|
static void tscrolldown(int, int);
|
|
|
|
|
static void tsetattr(const int *, int);
|
|
|
|
|
static void tsetchar(Rune, const Glyph *, int, int);
|
|
|
|
|
static void tsetattr(int *, int);
|
|
|
|
|
static void tsetchar(Rune, Glyph *, int, int);
|
|
|
|
|
static void tsetdirt(int, int);
|
|
|
|
|
static void tsetscroll(int, int);
|
|
|
|
|
static void tswapscreen(void);
|
|
|
|
|
static void tsetmode(int, int, const int *, int);
|
|
|
|
|
static void tsetmode(int, int, int *, int);
|
|
|
|
|
static int twrite(const char *, int, int);
|
|
|
|
|
static void tfulldirt(void);
|
|
|
|
|
static void tcontrolcode(uchar );
|
|
|
|
|
static void tdectest(char );
|
|
|
|
|
static void tdefutf8(char);
|
|
|
|
|
static int32_t tdefcolor(const int *, int *, int);
|
|
|
|
|
static int32_t tdefcolor(int *, int *, int);
|
|
|
|
|
static void tdeftran(char);
|
|
|
|
|
static void tstrsequence(uchar);
|
|
|
|
|
|
|
|
|
@ -226,10 +227,10 @@ static int iofd = 1;
|
|
|
|
|
static int cmdfd;
|
|
|
|
|
static pid_t pid;
|
|
|
|
|
|
|
|
|
|
static const uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
|
|
|
|
|
static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
|
|
|
|
|
static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000};
|
|
|
|
|
static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
|
|
|
|
|
static uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
|
|
|
|
|
static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
|
|
|
|
|
static Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000};
|
|
|
|
|
static Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
|
|
|
|
|
|
|
|
|
|
ssize_t
|
|
|
|
|
xwrite(int fd, const char *s, size_t len)
|
|
|
|
@ -269,14 +270,12 @@ xrealloc(void *p, size_t len)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
|
xstrdup(const char *s)
|
|
|
|
|
xstrdup(char *s)
|
|
|
|
|
{
|
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
|
|
if ((p = strdup(s)) == NULL)
|
|
|
|
|
if ((s = strdup(s)) == NULL)
|
|
|
|
|
die("strdup: %s\n", strerror(errno));
|
|
|
|
|
|
|
|
|
|
return p;
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t
|
|
|
|
@ -349,10 +348,25 @@ utf8validate(Rune *u, size_t i)
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char base64_digits[] = {
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0,
|
|
|
|
|
63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, -1, 0, 0, 0, 0, 1,
|
|
|
|
|
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
|
|
|
|
22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34,
|
|
|
|
|
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
char
|
|
|
|
|
base64dec_getc(const char **src)
|
|
|
|
|
{
|
|
|
|
|
while (**src && !isprint((unsigned char)**src))
|
|
|
|
|
while (**src && !isprint(**src))
|
|
|
|
|
(*src)++;
|
|
|
|
|
return **src ? *((*src)++) : '='; /* emulate padding if string ends */
|
|
|
|
|
}
|
|
|
|
@ -362,13 +376,6 @@ base64dec(const char *src)
|
|
|
|
|
{
|
|
|
|
|
size_t in_len = strlen(src);
|
|
|
|
|
char *result, *dst;
|
|
|
|
|
static const char base64_digits[256] = {
|
|
|
|
|
[43] = 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
|
|
|
|
|
0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
|
|
|
|
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0,
|
|
|
|
|
0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
|
|
|
|
|
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (in_len % 4)
|
|
|
|
|
in_len += 4 - (in_len % 4);
|
|
|
|
@ -512,7 +519,7 @@ selsnap(int *x, int *y, int direction)
|
|
|
|
|
{
|
|
|
|
|
int newx, newy, xt, yt;
|
|
|
|
|
int delim, prevdelim;
|
|
|
|
|
const Glyph *gp, *prevgp;
|
|
|
|
|
Glyph *gp, *prevgp;
|
|
|
|
|
|
|
|
|
|
switch (sel.snap) {
|
|
|
|
|
case SNAP_WORD:
|
|
|
|
@ -585,7 +592,7 @@ getsel(void)
|
|
|
|
|
{
|
|
|
|
|
char *str, *ptr;
|
|
|
|
|
int y, bufsize, lastx, linelen;
|
|
|
|
|
const Glyph *gp, *last;
|
|
|
|
|
Glyph *gp, *last;
|
|
|
|
|
|
|
|
|
|
if (sel.ob.x == -1)
|
|
|
|
|
return NULL;
|
|
|
|
@ -627,8 +634,7 @@ getsel(void)
|
|
|
|
|
* st.
|
|
|
|
|
* FIXME: Fix the computer world.
|
|
|
|
|
*/
|
|
|
|
|
if ((y < sel.ne.y || lastx >= linelen) &&
|
|
|
|
|
(!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR))
|
|
|
|
|
if ((y < sel.ne.y || lastx >= linelen) && !(last->mode & ATTR_WRAP))
|
|
|
|
|
*ptr++ = '\n';
|
|
|
|
|
}
|
|
|
|
|
*ptr = 0;
|
|
|
|
@ -724,7 +730,7 @@ sigchld(int a)
|
|
|
|
|
die("child exited with status %d\n", WEXITSTATUS(stat));
|
|
|
|
|
else if (WIFSIGNALED(stat))
|
|
|
|
|
die("child terminated due to signal %d\n", WTERMSIG(stat));
|
|
|
|
|
_exit(0);
|
|
|
|
|
exit(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
@ -752,7 +758,7 @@ stty(char **args)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
ttynew(const char *line, char *cmd, const char *out, char **args)
|
|
|
|
|
ttynew(char *line, char *cmd, char *out, char **args)
|
|
|
|
|
{
|
|
|
|
|
int m, s;
|
|
|
|
|
|
|
|
|
@ -785,15 +791,14 @@ ttynew(const char *line, char *cmd, const char *out, char **args)
|
|
|
|
|
break;
|
|
|
|
|
case 0:
|
|
|
|
|
close(iofd);
|
|
|
|
|
close(m);
|
|
|
|
|
setsid(); /* create a new process group */
|
|
|
|
|
dup2(s, 0);
|
|
|
|
|
dup2(s, 1);
|
|
|
|
|
dup2(s, 2);
|
|
|
|
|
if (ioctl(s, TIOCSCTTY, NULL) < 0)
|
|
|
|
|
die("ioctl TIOCSCTTY failed: %s\n", strerror(errno));
|
|
|
|
|
if (s > 2)
|
|
|
|
|
close(s);
|
|
|
|
|
close(s);
|
|
|
|
|
close(m);
|
|
|
|
|
#ifdef __OpenBSD__
|
|
|
|
|
if (pledge("stdio getpw proc exec", NULL) == -1)
|
|
|
|
|
die("pledge\n");
|
|
|
|
@ -836,6 +841,7 @@ ttyread(void)
|
|
|
|
|
if (buflen > 0)
|
|
|
|
|
memmove(buf, buf + written, buflen);
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -938,7 +944,7 @@ ttyresize(int tw, int th)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ttyhangup(void)
|
|
|
|
|
ttyhangup()
|
|
|
|
|
{
|
|
|
|
|
/* Send SIGHUP to shell */
|
|
|
|
|
kill(pid, SIGHUP);
|
|
|
|
@ -1099,17 +1105,27 @@ selscroll(int orig, int n)
|
|
|
|
|
if (sel.ob.x == -1)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) {
|
|
|
|
|
selclear();
|
|
|
|
|
} else if (BETWEEN(sel.nb.y, orig, term.bot)) {
|
|
|
|
|
sel.ob.y += n;
|
|
|
|
|
sel.oe.y += n;
|
|
|
|
|
if (sel.ob.y < term.top || sel.ob.y > term.bot ||
|
|
|
|
|
sel.oe.y < term.top || sel.oe.y > term.bot) {
|
|
|
|
|
if (BETWEEN(sel.ob.y, orig, term.bot) || BETWEEN(sel.oe.y, orig, term.bot)) {
|
|
|
|
|
if ((sel.ob.y += n) > term.bot || (sel.oe.y += n) < term.top) {
|
|
|
|
|
selclear();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (sel.type == SEL_RECTANGULAR) {
|
|
|
|
|
if (sel.ob.y < term.top)
|
|
|
|
|
sel.ob.y = term.top;
|
|
|
|
|
if (sel.oe.y > term.bot)
|
|
|
|
|
sel.oe.y = term.bot;
|
|
|
|
|
} else {
|
|
|
|
|
selnormalize();
|
|
|
|
|
if (sel.ob.y < term.top) {
|
|
|
|
|
sel.ob.y = term.top;
|
|
|
|
|
sel.ob.x = 0;
|
|
|
|
|
}
|
|
|
|
|
if (sel.oe.y > term.bot) {
|
|
|
|
|
sel.oe.y = term.bot;
|
|
|
|
|
sel.oe.x = term.col;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
selnormalize();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1181,9 +1197,9 @@ tmoveto(int x, int y)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
tsetchar(Rune u, const Glyph *attr, int x, int y)
|
|
|
|
|
tsetchar(Rune u, Glyph *attr, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
static const char *vt100_0[62] = { /* 0x41 - 0x7e */
|
|
|
|
|
static char *vt100_0[62] = { /* 0x41 - 0x7e */
|
|
|
|
|
"↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, /* H - O */
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, /* P - W */
|
|
|
|
@ -1295,7 +1311,7 @@ tdeleteline(int n)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t
|
|
|
|
|
tdefcolor(const int *attr, int *npar, int l)
|
|
|
|
|
tdefcolor(int *attr, int *npar, int l)
|
|
|
|
|
{
|
|
|
|
|
int32_t idx = -1;
|
|
|
|
|
uint r, g, b;
|
|
|
|
@ -1345,7 +1361,7 @@ tdefcolor(const int *attr, int *npar, int l)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
tsetattr(const int *attr, int l)
|
|
|
|
|
tsetattr(int *attr, int l)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
int32_t idx;
|
|
|
|
@ -1463,9 +1479,9 @@ tsetscroll(int t, int b)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
tsetmode(int priv, int set, const int *args, int narg)
|
|
|
|
|
tsetmode(int priv, int set, int *args, int narg)
|
|
|
|
|
{
|
|
|
|
|
int alt; const int *lim;
|
|
|
|
|
int alt, *lim;
|
|
|
|
|
|
|
|
|
|
for (lim = args + narg; args < lim; ++args) {
|
|
|
|
|
if (priv) {
|
|
|
|
@ -1641,12 +1657,6 @@ csihandle(void)
|
|
|
|
|
if (csiescseq.arg[0] == 0)
|
|
|
|
|
ttywrite(vtiden, strlen(vtiden), 0);
|
|
|
|
|
break;
|
|
|
|
|
case 'b': /* REP -- if last char is printable print it <n> more times */
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1);
|
|
|
|
|
if (term.lastc)
|
|
|
|
|
while (csiescseq.arg[0]-- > 0)
|
|
|
|
|
tputc(term.lastc);
|
|
|
|
|
break;
|
|
|
|
|
case 'C': /* CUF -- Cursor <n> Forward */
|
|
|
|
|
case 'a': /* HPR -- Cursor <n> Forward */
|
|
|
|
|
DEFAULT(csiescseq.arg[0], 1);
|
|
|
|
@ -1770,7 +1780,7 @@ csihandle(void)
|
|
|
|
|
break;
|
|
|
|
|
case 'n': /* DSR – Device Status Report (cursor position) */
|
|
|
|
|
if (csiescseq.arg[0] == 6) {
|
|
|
|
|
len = snprintf(buf, sizeof(buf), "\033[%i;%iR",
|
|
|
|
|
len = snprintf(buf, sizeof(buf),"\033[%i;%iR",
|
|
|
|
|
term.c.y+1, term.c.x+1);
|
|
|
|
|
ttywrite(buf, len, 0);
|
|
|
|
|
}
|
|
|
|
@ -1834,41 +1844,11 @@ csireset(void)
|
|
|
|
|
memset(&csiescseq, 0, sizeof(csiescseq));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
osc_color_response(int num, int index, int is_osc4)
|
|
|
|
|
{
|
|
|
|
|
int n;
|
|
|
|
|
char buf[32];
|
|
|
|
|
unsigned char r, g, b;
|
|
|
|
|
|
|
|
|
|
if (xgetcolor(is_osc4 ? num : index, &r, &g, &b)) {
|
|
|
|
|
fprintf(stderr, "erresc: failed to fetch %s color %d\n",
|
|
|
|
|
is_osc4 ? "osc4" : "osc",
|
|
|
|
|
is_osc4 ? num : index);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007",
|
|
|
|
|
is_osc4 ? "4;" : "", num, r, r, g, g, b, b);
|
|
|
|
|
if (n < 0 || n >= sizeof(buf)) {
|
|
|
|
|
fprintf(stderr, "error: %s while printing %s response\n",
|
|
|
|
|
n < 0 ? "snprintf failed" : "truncation occurred",
|
|
|
|
|
is_osc4 ? "osc4" : "osc");
|
|
|
|
|
} else {
|
|
|
|
|
ttywrite(buf, n, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
strhandle(void)
|
|
|
|
|
{
|
|
|
|
|
char *p = NULL, *dec;
|
|
|
|
|
int j, narg, par;
|
|
|
|
|
const struct { int idx; char *str; } osc_table[] = {
|
|
|
|
|
{ defaultfg, "foreground" },
|
|
|
|
|
{ defaultbg, "background" },
|
|
|
|
|
{ defaultcs, "cursor" }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
term.esc &= ~(ESC_STR_END|ESC_STR);
|
|
|
|
|
strparse();
|
|
|
|
@ -1878,21 +1858,13 @@ strhandle(void)
|
|
|
|
|
case ']': /* OSC -- Operating System Command */
|
|
|
|
|
switch (par) {
|
|
|
|
|
case 0:
|
|
|
|
|
if (narg > 1) {
|
|
|
|
|
xsettitle(strescseq.args[1]);
|
|
|
|
|
xseticontitle(strescseq.args[1]);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 1:
|
|
|
|
|
if (narg > 1)
|
|
|
|
|
xseticontitle(strescseq.args[1]);
|
|
|
|
|
return;
|
|
|
|
|
case 2:
|
|
|
|
|
if (narg > 1)
|
|
|
|
|
xsettitle(strescseq.args[1]);
|
|
|
|
|
return;
|
|
|
|
|
case 52:
|
|
|
|
|
if (narg > 2 && allowwindowops) {
|
|
|
|
|
if (narg > 2) {
|
|
|
|
|
dec = base64dec(strescseq.args[2]);
|
|
|
|
|
if (dec) {
|
|
|
|
|
xsetsel(dec);
|
|
|
|
@ -1902,35 +1874,14 @@ strhandle(void)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 10:
|
|
|
|
|
case 11:
|
|
|
|
|
case 12:
|
|
|
|
|
if (narg < 2)
|
|
|
|
|
break;
|
|
|
|
|
p = strescseq.args[1];
|
|
|
|
|
if ((j = par - 10) < 0 || j >= LEN(osc_table))
|
|
|
|
|
break; /* shouldn't be possible */
|
|
|
|
|
|
|
|
|
|
if (!strcmp(p, "?")) {
|
|
|
|
|
osc_color_response(par, osc_table[j].idx, 0);
|
|
|
|
|
} else if (xsetcolorname(osc_table[j].idx, p)) {
|
|
|
|
|
fprintf(stderr, "erresc: invalid %s color: %s\n",
|
|
|
|
|
osc_table[j].str, p);
|
|
|
|
|
} else {
|
|
|
|
|
tfulldirt();
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case 4: /* color set */
|
|
|
|
|
if (narg < 3)
|
|
|
|
|
break;
|
|
|
|
|
p = strescseq.args[2];
|
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
|
case 104: /* color reset */
|
|
|
|
|
case 104: /* color reset, here p = NULL */
|
|
|
|
|
j = (narg > 1) ? atoi(strescseq.args[1]) : -1;
|
|
|
|
|
|
|
|
|
|
if (p && !strcmp(p, "?")) {
|
|
|
|
|
osc_color_response(j, 0, 1);
|
|
|
|
|
} else if (xsetcolorname(j, p)) {
|
|
|
|
|
if (xsetcolorname(j, p)) {
|
|
|
|
|
if (par == 104 && narg <= 1)
|
|
|
|
|
return; /* color reset without parameter */
|
|
|
|
|
fprintf(stderr, "erresc: invalid color j=%d, p=%s\n",
|
|
|
|
@ -1940,7 +1891,7 @@ strhandle(void)
|
|
|
|
|
* TODO if defaultbg color is changed, borders
|
|
|
|
|
* are dirty
|
|
|
|
|
*/
|
|
|
|
|
tfulldirt();
|
|
|
|
|
redraw();
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -1949,6 +1900,7 @@ strhandle(void)
|
|
|
|
|
xsettitle(strescseq.args[0]);
|
|
|
|
|
return;
|
|
|
|
|
case 'P': /* DCS -- Device Control String */
|
|
|
|
|
term.mode |= ESC_DCS;
|
|
|
|
|
case '_': /* APC -- Application Program Command */
|
|
|
|
|
case '^': /* PM -- Privacy Message */
|
|
|
|
|
return;
|
|
|
|
@ -2066,12 +2018,12 @@ void
|
|
|
|
|
tdumpline(int n)
|
|
|
|
|
{
|
|
|
|
|
char buf[UTF_SIZ];
|
|
|
|
|
const Glyph *bp, *end;
|
|
|
|
|
Glyph *bp, *end;
|
|
|
|
|
|
|
|
|
|
bp = &term.line[n][0];
|
|
|
|
|
end = &bp[MIN(tlinelen(n), term.col) - 1];
|
|
|
|
|
if (bp != end || bp->u != ' ') {
|
|
|
|
|
for ( ; bp <= end; ++bp)
|
|
|
|
|
for ( ;bp <= end; ++bp)
|
|
|
|
|
tprinter(buf, utf8encode(bp->u, buf));
|
|
|
|
|
}
|
|
|
|
|
tprinter("\n", 1);
|
|
|
|
@ -2142,9 +2094,12 @@ tdectest(char c)
|
|
|
|
|
void
|
|
|
|
|
tstrsequence(uchar c)
|
|
|
|
|
{
|
|
|
|
|
strreset();
|
|
|
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
|
case 0x90: /* DCS -- Device Control String */
|
|
|
|
|
c = 'P';
|
|
|
|
|
term.esc |= ESC_DCS;
|
|
|
|
|
break;
|
|
|
|
|
case 0x9f: /* APC -- Application Program Command */
|
|
|
|
|
c = '_';
|
|
|
|
@ -2156,7 +2111,6 @@ tstrsequence(uchar c)
|
|
|
|
|
c = ']';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
strreset();
|
|
|
|
|
strescseq.type = c;
|
|
|
|
|
term.esc |= ESC_STR;
|
|
|
|
|
}
|
|
|
|
@ -2199,7 +2153,6 @@ tcontrolcode(uchar ascii)
|
|
|
|
|
return;
|
|
|
|
|
case '\032': /* SUB */
|
|
|
|
|
tsetchar('?', &term.c.attr, term.c.x, term.c.y);
|
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
|
case '\030': /* CAN */
|
|
|
|
|
csireset();
|
|
|
|
|
break;
|
|
|
|
@ -2354,13 +2307,15 @@ tputc(Rune u)
|
|
|
|
|
Glyph *gp;
|
|
|
|
|
|
|
|
|
|
control = ISCONTROL(u);
|
|
|
|
|
if (u < 127 || !IS_SET(MODE_UTF8)) {
|
|
|
|
|
if (!IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) {
|
|
|
|
|
c[0] = u;
|
|
|
|
|
width = len = 1;
|
|
|
|
|
} else {
|
|
|
|
|
len = utf8encode(u, c);
|
|
|
|
|
if (!control && (width = wcwidth(u)) == -1)
|
|
|
|
|
if (!control && (width = wcwidth(u)) == -1) {
|
|
|
|
|
memcpy(c, "\357\277\275", 4); /* UTF_INVALID */
|
|
|
|
|
width = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IS_SET(MODE_PRINT))
|
|
|
|
@ -2375,11 +2330,23 @@ tputc(Rune u)
|
|
|
|
|
if (term.esc & ESC_STR) {
|
|
|
|
|
if (u == '\a' || u == 030 || u == 032 || u == 033 ||
|
|
|
|
|
ISCONTROLC1(u)) {
|
|
|
|
|
term.esc &= ~(ESC_START|ESC_STR);
|
|
|
|
|
term.esc &= ~(ESC_START|ESC_STR|ESC_DCS);
|
|
|
|
|
if (IS_SET(MODE_SIXEL)) {
|
|
|
|
|
/* TODO: render sixel */;
|
|
|
|
|
term.mode &= ~MODE_SIXEL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
term.esc |= ESC_STR_END;
|
|
|
|
|
goto check_control_code;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IS_SET(MODE_SIXEL)) {
|
|
|
|
|
/* TODO: implement sixel mode */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (term.esc&ESC_DCS && strescseq.len == 0 && u == 'q')
|
|
|
|
|
term.mode |= MODE_SIXEL;
|
|
|
|
|
|
|
|
|
|
if (strescseq.len+len >= strescseq.siz) {
|
|
|
|
|
/*
|
|
|
|
|
* Here is a bug in terminals. If the user never sends
|
|
|
|
@ -2416,8 +2383,6 @@ check_control_code:
|
|
|
|
|
/*
|
|
|
|
|
* control codes are not shown ever
|
|
|
|
|
*/
|
|
|
|
|
if (!term.esc)
|
|
|
|
|
term.lastc = 0;
|
|
|
|
|
return;
|
|
|
|
|
} else if (term.esc & ESC_START) {
|
|
|
|
|
if (term.esc & ESC_CSI) {
|
|
|
|
@ -2448,7 +2413,7 @@ check_control_code:
|
|
|
|
|
*/
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (selected(term.c.x, term.c.y))
|
|
|
|
|
if (sel.ob.x != -1 && BETWEEN(term.c.y, sel.ob.y, sel.oe.y))
|
|
|
|
|
selclear();
|
|
|
|
|
|
|
|
|
|
gp = &term.line[term.c.y][term.c.x];
|
|
|
|
@ -2467,15 +2432,10 @@ check_control_code:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tsetchar(u, &term.c.attr, term.c.x, term.c.y);
|
|
|
|
|
term.lastc = u;
|
|
|
|
|
|
|
|
|
|
if (width == 2) {
|
|
|
|
|
gp->mode |= ATTR_WIDE;
|
|
|
|
|
if (term.c.x+1 < term.col) {
|
|
|
|
|
if (gp[1].mode == ATTR_WIDE && term.c.x+2 < term.col) {
|
|
|
|
|
gp[2].u = ' ';
|
|
|
|
|
gp[2].mode &= ~ATTR_WDUMMY;
|
|
|
|
|
}
|
|
|
|
|
gp[1].u = '\0';
|
|
|
|
|
gp[1].mode = ATTR_WDUMMY;
|
|
|
|
|
}
|
|
|
|
@ -2495,7 +2455,7 @@ twrite(const char *buf, int buflen, int show_ctrl)
|
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
for (n = 0; n < buflen; n += charsize) {
|
|
|
|
|
if (IS_SET(MODE_UTF8)) {
|
|
|
|
|
if (IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) {
|
|
|
|
|
/* process a complete utf8 char */
|
|
|
|
|
charsize = utf8decode(buf + n, &u, buflen - n);
|
|
|
|
|
if (charsize == 0)
|