ESC_STR = 4, /* DSC, OSC, PM, APC */
ESC_ALTCHARSET = 8,
ESC_STR_END = 16, /* a final string was encountered */
+ ESC_TEST = 32, /* Enter in test mode */
};
enum window_state {
static void tscrollup(int, int);
static void tscrolldown(int, int);
static void tsetattr(int*, int);
-static void tsetchar(char*);
+static void tsetchar(char *, Glyph *, int, int);
static void tsetscroll(int, int);
static void tswapscreen(void);
static void tsetdirt(int, int);
static int utf8size(char *);
static int isfullutf8(char *, int);
+static ssize_t xwrite(int, char *, size_t);
static void *xmalloc(size_t);
static void *xrealloc(void *, size_t);
static void *xcalloc(size_t nmemb, size_t size);
static char *opt_class = NULL;
static char *opt_font = NULL;
+
+ssize_t
+xwrite(int fd, char *s, size_t len) {
+ size_t aux = len;
+
+ while(len > 0) {
+ ssize_t r = write(fd, s, len);
+ if(r < 0)
+ return r;
+ len -= r;
+ s += r;
+ }
+ return aux;
+}
+
void *
xmalloc(size_t len) {
void *p = malloc(len);
void
selcopy(void) {
- char *str, *ptr, *p;
+ char *str, *ptr;
int x, y, bufsize, is_selected = 0, size;
Glyph *gp;
for(x = 0; x < term.col; x++) {
gp = &term.line[y][x];
- if(!(is_selected = selected(x, y)))
+ if(!(is_selected = selected(x, y))
+ || !(gp->state & GLYPH_SET)) {
continue;
- p = (gp->state & GLYPH_SET) ? gp->c : " ";
- size = utf8size(p);
- memcpy(ptr, p, size);
+ }
+ size = utf8size(gp->c);
+ memcpy(ptr, gp->c, size);
ptr += size;
}
/* \n at the end of every selected line except for the last one */
DEFAULT(envshell, SHELL);
putenv("TERM="TNAME);
- args = opt_cmd ? opt_cmd : (char*[]){envshell, "-i", NULL};
+ args = opt_cmd ? opt_cmd : (char *[]){envshell, "-i", NULL};
execvp(args[0], args);
exit(EXIT_FAILURE);
}
cmdfd = m;
signal(SIGCHLD, sigchld);
if(opt_io) {
- if(!strcmp(opt_io, "-")) {
- iofd = STDOUT_FILENO;
- } else {
- if((iofd = open(opt_io, O_WRONLY | O_CREAT, 0666)) < 0) {
- fprintf(stderr, "Error opening %s:%s\n",
- opt_io, strerror(errno));
- }
+ iofd = (!strcmp(opt_io, "-")) ?
+ STDOUT_FILENO :
+ open(opt_io, O_WRONLY | O_CREAT, 0666);
+ if(iofd < 0) {
+ fprintf(stderr, "Error opening %s:%s\n",
+ opt_io, strerror(errno));
}
}
}
}
void
-tsetchar(char *c) {
+tsetchar(char *c, Glyph *attr, int x, int y) {
static char *vt100_0[62] = { /* 0x41 - 0x7e */
"↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */
0, 0, 0, 0, 0, 0, 0, 0, /* H - O */
/*
* The table is proudly stolen from rxvt.
*/
- if(term.c.attr.mode & ATTR_GFX) {
+ if(attr->mode & ATTR_GFX) {
if(c[0] >= 0x41 && c[0] <= 0x7e
&& vt100_0[c[0] - 0x41]) {
c = vt100_0[c[0] - 0x41];
}
}
- term.dirty[term.c.y] = 1;
- term.line[term.c.y][term.c.x] = term.c.attr;
- memcpy(term.line[term.c.y][term.c.x].c, c, UTF_SIZ);
- term.line[term.c.y][term.c.x].state |= GLYPH_SET;
+ term.dirty[y] = 1;
+ term.line[y][x] = *attr;
+ memcpy(term.line[y][x].c, c, UTF_SIZ);
+ term.line[y][x].state |= GLYPH_SET;
}
void
uchar ascii = *c;
bool control = ascii < '\x20' || ascii == 0177;
- if(iofd != -1)
- write(iofd, c, len);
+ if(iofd != -1) {
+ if (xwrite(iofd, c, len) < 0) {
+ fprintf(stderr, "Error writting in %s:%s\n",
+ opt_io, strerror(errno));
+ close(iofd);
+ iofd = -1;
+ }
+ }
/*
* STR sequences must be checked before of anything
* because it can use some control codes as part of the sequence
fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii);
}
term.esc = 0;
+ } else if(term.esc & ESC_TEST) {
+ if(ascii == '8') { /* DEC screen alignment test. */
+ char E[UTF_SIZ] = "E";
+ int x, y;
+
+ for(x = 0; x < term.col; ++x) {
+ for(y = 0; y < term.row; ++y)
+ tsetchar(E, &term.c.attr, x, y);
+ }
+ }
+ term.esc = 0;
} else {
switch(ascii) {
case '[':
term.esc |= ESC_CSI;
break;
+ case '#':
+ term.esc |= ESC_TEST;
+ break;
case 'P': /* DCS -- Device Control String */
case '_': /* APC -- Application Program Command */
case '^': /* PM -- Privacy Message */
sel.bx = -1;
if(IS_SET(MODE_WRAP) && term.c.state & CURSOR_WRAPNEXT)
tnewline(1); /* always go to first col */
- tsetchar(c);
+ 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);
else