#define Glyph Glyph_
#define Font Font_
-#define Draw XftDraw *
-#define Colour XftColor
-#define Colourmap Colormap
-#define Rectangle XRectangle
#if defined(__linux)
#include <pty.h>
#define XEMBED_FOCUS_OUT 5
/* Arbitrary sizes */
+#define UTF_INVALID 0xFFFD
#define UTF_SIZ 4
#define ESC_BUF_SIZ (128*UTF_SIZ)
#define ESC_ARG_SIZ 16
#define REDRAW_TIMEOUT (80*1000) /* 80 ms */
/* macros */
-#define SERRNO strerror(errno)
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) < (b) ? (b) : (a))
-#define LEN(a) (sizeof(a) / sizeof(a[0]))
+#define LEN(a) (sizeof(a) / sizeof(a)[0])
#define DEFAULT(a, b) (a) = (a) ? (a) : (b)
#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b))
#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x)
#define IS_SET(flag) ((term.mode & (flag)) != 0)
#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + (t1.tv_usec-t2.tv_usec)/1000)
#define CEIL(x) (((x) != (int) (x)) ? (x) + 1 : (x))
+#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit)))
#define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b))
#define IS_TRUECOL(x) (1 << 24 & (x))
MODE_MOUSEX10 = 131072,
MODE_MOUSEMANY = 262144,
MODE_BRCKTPASTE = 524288,
+ MODE_PRINT = 1048576,
MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\
|MODE_MOUSEMANY,
};
typedef unsigned long ulong;
typedef unsigned short ushort;
+typedef XftDraw *Draw;
+typedef XftColor Colour;
+typedef Colormap Colourmap;
+
typedef struct {
char c[UTF_SIZ]; /* character code */
ushort mode; /* attribute flags */
typedef union {
int i;
- unsigned int ui;
+ uint ui;
float f;
const void *v;
} Arg;
typedef struct {
- unsigned int mod;
+ uint mod;
KeySym keysym;
void (*func)(const Arg *);
const Arg arg;
static void numlock(const Arg *);
static void selpaste(const Arg *);
static void xzoom(const Arg *);
+static void printsel(const Arg *);
+static void printscreen(const Arg *) ;
+static void toggleprinter(const Arg *);
/* Config.h for applying patches and the configuration. */
#include "config.h"
static void strreset(void);
static int tattrset(int);
+static void tprinter(char *, size_t);
+static void tdumpsel(void);
+static void tdumpline(int);
+static void tdump(void);
static void tclearregion(int, int, int, int);
static void tcursor(int);
static void tdeletechar(int);
static void tinsertblank(int);
static void tinsertblankline(int);
static void tmoveto(int, int);
-static void tmoveato(int x, int y);
+static void tmoveato(int, int);
static void tnew(int, int);
static void tnewline(int);
static void tputtab(bool);
static int tresize(int, int);
static void tscrollup(int, int);
static void tscrolldown(int, int);
-static void tsetattr(int*, int);
+static void tsetattr(int *, int);
static void tsetchar(char *, Glyph *, int, int);
static void tsetscroll(int, int);
static void tswapscreen(void);
static void xresettitle(void);
static void xsetpointermotion(int);
static void xseturgency(int);
-static void xsetsel(char*);
+static void xsetsel(char *);
static void xtermclear(int, int, int, int);
-static void xunloadfont(Font *f);
+static void xunloadfont(Font *);
static void xunloadfonts(void);
static void xresize(int, int);
static void selinit(void);
static void selsort(void);
static inline bool selected(int, int);
+static char *getsel(void);
static void selcopy(void);
static void selscroll(int, int);
static void selsnap(int, int *, int *, int);
-static int utf8decode(char *, long *);
-static int utf8encode(long *, char *);
-static int utf8size(char *);
-static int isfullutf8(char *, int);
+static size_t utf8decode(char *, long *, size_t);
+static long utf8decodebyte(char, size_t *);
+static size_t utf8encode(long, char *, size_t);
+static char utf8encodebyte(long, size_t);
+static size_t utf8len(char *);
+static size_t utf8validate(long *, size_t);
static ssize_t xwrite(int, char *, size_t);
static void *xmalloc(size_t);
static void *xrealloc(void *, size_t);
+static char *xstrdup(char *);
static void (*handler[LASTEvent])(XEvent *) = {
[KeyPress] = kpress,
static int cmdfd;
static pid_t pid;
static Selection sel;
-static int iofd = -1;
+static int iofd = STDOUT_FILENO;
static char **opt_cmd = NULL;
static char *opt_io = NULL;
static char *opt_title = NULL;
static char *usedfont = NULL;
static double usedfontsize = 0;
+static uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
+static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
+static long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000};
+static long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
+
/* Font Ring Cache */
enum {
FRC_NORMAL,
return p;
}
-int
-utf8decode(char *s, long *u) {
- uchar c;
- int i, n, rtn;
-
- rtn = 1;
- c = *s;
- if(~c & 0x80) { /* 0xxxxxxx */
- *u = c;
- return rtn;
- } else if((c & 0xE0) == 0xC0) { /* 110xxxxx */
- *u = c & 0x1F;
- n = 1;
- } else if((c & 0xF0) == 0xE0) { /* 1110xxxx */
- *u = c & 0x0F;
- n = 2;
- } else if((c & 0xF8) == 0xF0) { /* 11110xxx */
- *u = c & 0x07;
- n = 3;
- } else {
- goto invalid;
- }
-
- for(i = n, ++s; i > 0; --i, ++rtn, ++s) {
- c = *s;
- if((c & 0xC0) != 0x80) /* 10xxxxxx */
- goto invalid;
- *u <<= 6;
- *u |= c & 0x3F;
- }
-
- if((n == 1 && *u < 0x80) ||
- (n == 2 && *u < 0x800) ||
- (n == 3 && *u < 0x10000) ||
- (*u >= 0xD800 && *u <= 0xDFFF)) {
- goto invalid;
- }
-
- return rtn;
-invalid:
- *u = 0xFFFD;
+char *
+xstrdup(char *s) {
+ if((s = strdup(s)) == NULL)
+ die("Out of memory\n");
- return rtn;
+ return s;
}
-int
-utf8encode(long *u, char *s) {
- uchar *sp;
- ulong uc;
- int i, n;
-
- sp = (uchar *)s;
- uc = *u;
- if(uc < 0x80) {
- *sp = uc; /* 0xxxxxxx */
+size_t
+utf8decode(char *c, long *u, size_t clen) {
+ size_t i, j, len, type;
+ long udecoded;
+
+ *u = UTF_INVALID;
+ if(!clen)
+ return 0;
+ udecoded = utf8decodebyte(c[0], &len);
+ if(!BETWEEN(len, 1, UTF_SIZ))
return 1;
- } else if(*u < 0x800) {
- *sp = (uc >> 6) | 0xC0; /* 110xxxxx */
- n = 1;
- } else if(uc < 0x10000) {
- *sp = (uc >> 12) | 0xE0; /* 1110xxxx */
- n = 2;
- } else if(uc <= 0x10FFFF) {
- *sp = (uc >> 18) | 0xF0; /* 11110xxx */
- n = 3;
- } else {
- goto invalid;
+ for(i = 1, j = 1; i < clen && j < len; ++i, ++j) {
+ udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
+ if(type != 0)
+ return j;
}
+ if(j < len)
+ return 0;
+ *u = udecoded;
+ utf8validate(u, len);
+ return len;
+}
- for(i=n,++sp; i>0; --i,++sp)
- *sp = ((uc >> 6*(i-1)) & 0x3F) | 0x80; /* 10xxxxxx */
-
- return n+1;
-invalid:
- /* U+FFFD */
- *s++ = '\xEF';
- *s++ = '\xBF';
- *s = '\xBD';
-
- return 3;
+long
+utf8decodebyte(char c, size_t *i) {
+ for(*i = 0; *i < LEN(utfmask); ++(*i))
+ if(((uchar)c & utfmask[*i]) == utfbyte[*i])
+ return (uchar)c & ~utfmask[*i];
+ return 0;
}
-/* use this if your buffer is less than UTF_SIZ, it returns 1 if you can decode
- UTF-8 otherwise return 0 */
-int
-isfullutf8(char *s, int b) {
- uchar *c1, *c2, *c3;
+size_t
+utf8encode(long u, char *c, size_t clen) {
+ size_t len, i;
- c1 = (uchar *)s;
- c2 = (uchar *)++s;
- c3 = (uchar *)++s;
- if(b < 1) {
- return 0;
- } else if((*c1 & 0xE0) == 0xC0 && b == 1) {
- return 0;
- } else if((*c1 & 0xF0) == 0xE0 &&
- ((b == 1) ||
- ((b == 2) && (*c2 & 0xC0) == 0x80))) {
- return 0;
- } else if((*c1 & 0xF8) == 0xF0 &&
- ((b == 1) ||
- ((b == 2) && (*c2 & 0xC0) == 0x80) ||
- ((b == 3) && (*c2 & 0xC0) == 0x80 && (*c3 & 0xC0) == 0x80))) {
+ len = utf8validate(&u, 0);
+ if(clen < len)
return 0;
- } else {
- return 1;
+ for(i = len - 1; i != 0; --i) {
+ c[i] = utf8encodebyte(u, 0);
+ u >>= 6;
}
+ c[0] = utf8encodebyte(u, len);
+ return len;
}
-int
-utf8size(char *s) {
- uchar c = *s;
+char
+utf8encodebyte(long u, size_t i) {
+ return utfbyte[i] | (u & ~utfmask[i]);
+}
- if(~c & 0x80) {
- return 1;
- } else if((c & 0xE0) == 0xC0) {
- return 2;
- } else if((c & 0xF0) == 0xE0) {
- return 3;
- } else {
- return 4;
- }
+size_t
+utf8len(char *c) {
+ return utf8decode(c, &(long){0}, UTF_SIZ);
+}
+
+size_t
+utf8validate(long *u, size_t i) {
+ if(!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
+ *u = UTF_INVALID;
+ for(i = 1; *u > utfmax[i]; ++i)
+ ;
+ return i;
}
static void
}
}
-void
-selcopy(void) {
+char *
+getsel(void) {
char *str, *ptr;
int x, y, bufsize, size, i, ex;
Glyph *gp, *last;
/* append every set & selected glyph to the selection */
for(y = sel.nb.y; y < sel.ne.y + 1; y++) {
gp = &term.line[y][0];
- last = gp + term.col;
+ last = &gp[term.col-1];
- while(--last >= gp && !(selected(last - gp, y) && \
- strcmp(last->c, " ") != 0))
- /* nothing */;
+ while(last >= gp && !(selected(last - gp, y) &&
+ strcmp(last->c, " ") != 0)) {
+ --last;
+ }
for(x = 0; gp <= last; x++, ++gp) {
if(!selected(x, y) || (gp->mode & ATTR_WDUMMY))
continue;
- size = utf8size(gp->c);
+ size = utf8len(gp->c);
memcpy(ptr, gp->c, size);
ptr += size;
}
}
*ptr = 0;
}
- xsetsel(str);
+ return str;
+}
+
+void
+selcopy(void) {
+ xsetsel(getsel());
}
void
int stat = 0;
if(waitpid(pid, &stat, 0) < 0)
- die("Waiting for pid %hd failed: %s\n", pid, SERRNO);
+ die("Waiting for pid %hd failed: %s\n", pid, strerror(errno));
if(WIFEXITED(stat)) {
exit(WEXITSTATUS(stat));
/* seems to work fine on linux, openbsd and freebsd */
if(openpty(&m, &s, NULL, NULL, &w) < 0)
- die("openpty failed: %s\n", SERRNO);
+ die("openpty failed: %s\n", strerror(errno));
switch(pid = fork()) {
case -1:
dup2(s, STDOUT_FILENO);
dup2(s, STDERR_FILENO);
if(ioctl(s, TIOCSCTTY, NULL) < 0)
- die("ioctl TIOCSCTTY failed: %s\n", SERRNO);
+ die("ioctl TIOCSCTTY failed: %s\n", strerror(errno));
close(s);
close(m);
execsh();
cmdfd = m;
signal(SIGCHLD, sigchld);
if(opt_io) {
+ term.mode |= MODE_PRINT;
iofd = (!strcmp(opt_io, "-")) ?
STDOUT_FILENO :
open(opt_io, O_WRONLY | O_CREAT, 0666);
char *ptr;
char s[UTF_SIZ];
int charsize; /* size of utf8 char in bytes */
- long utf8c;
+ long unicodep;
int ret;
/* append read bytes to unprocessed bytes */
if((ret = read(cmdfd, buf+buflen, LEN(buf)-buflen)) < 0)
- die("Couldn't read from shell: %s\n", SERRNO);
+ die("Couldn't read from shell: %s\n", strerror(errno));
/* process every complete utf8 char */
buflen += ret;
ptr = buf;
- while(buflen >= UTF_SIZ || isfullutf8(ptr,buflen)) {
- charsize = utf8decode(ptr, &utf8c);
- utf8encode(&utf8c, s);
+ while((charsize = utf8decode(ptr, &unicodep, buflen))) {
+ utf8encode(unicodep, s, UTF_SIZ);
tputc(s, charsize);
ptr += charsize;
buflen -= charsize;
void
ttywrite(const char *s, size_t n) {
if(write(cmdfd, s, n) == -1)
- die("write error on tty: %s\n", SERRNO);
+ die("write error on tty: %s\n", strerror(errno));
}
void
w.ws_xpixel = xw.tw;
w.ws_ypixel = xw.th;
if(ioctl(cmdfd, TIOCSWINSZ, &w) < 0)
- fprintf(stderr, "Couldn't set window size: %s\n", SERRNO);
+ fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno));
}
int
LIMIT(n, 0, term.bot-orig+1);
+ tsetdirt(orig, term.bot-n);
tclearregion(0, term.bot-n+1, term.col-1, term.bot);
for(i = term.bot; i >= orig+n; i--) {
temp = term.line[i];
term.line[i] = term.line[i-n];
term.line[i-n] = temp;
-
- term.dirty[i] = 1;
- term.dirty[i-n] = 1;
}
selscroll(orig, n);
tscrollup(int orig, int n) {
int i;
Line temp;
+
LIMIT(n, 0, term.bot-orig+1);
tclearregion(0, orig, term.col-1, orig+n-1);
+ tsetdirt(orig+n, term.bot);
for(i = orig; i <= term.bot-n; i++) {
- temp = term.line[i];
- term.line[i] = term.line[i+n];
- term.line[i+n] = temp;
-
- term.dirty[i] = 1;
- term.dirty[i+n] = 1;
+ temp = term.line[i];
+ term.line[i] = term.line[i+n];
+ term.line[i+n] = temp;
}
selscroll(orig, -n);
* The table is proudly stolen from rxvt.
*/
if(attr->mode & ATTR_GFX) {
- if(c[0] >= 0x41 && c[0] <= 0x7e
- && vt100_0[c[0] - 0x41]) {
+ if(BETWEEN(c[0], 0x41, 0x7e) && vt100_0[c[0] - 0x41]) {
c = vt100_0[c[0] - 0x41];
}
}
void
tdeletechar(int n) {
- int src = term.c.x + n;
- int dst = term.c.x;
- int size = term.col - src;
+ int dst, src, size;
- term.dirty[term.c.y] = 1;
+ LIMIT(n, 0, term.col - term.c.x);
- if(src >= term.col) {
- tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
- return;
- }
+ dst = term.c.x;
+ src = term.c.x + n;
+ size = term.col - src;
memmove(&term.line[term.c.y][dst], &term.line[term.c.y][src],
- size * sizeof(Glyph));
+ size * sizeof(Glyph));
tclearregion(term.col-n, term.c.y, term.col-1, term.c.y);
}
void
tinsertblank(int n) {
- int src = term.c.x;
- int dst = src + n;
- int size = term.col - dst;
+ int dst, src, size;
- term.dirty[term.c.y] = 1;
+ LIMIT(n, 0, term.col - term.c.x);
- if(dst >= term.col) {
- tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
- return;
- }
+ dst = term.c.x + n;
+ src = term.c.x;
+ size = term.col - dst;
memmove(&term.line[term.c.y][dst], &term.line[term.c.y][src],
- size * sizeof(Glyph));
+ size * sizeof(Glyph));
tclearregion(src, term.c.y, dst - 1, term.c.y);
}
void
tinsertblankline(int n) {
- if(term.c.y < term.top || term.c.y > term.bot)
- return;
-
- tscrolldown(term.c.y, n);
+ if(BETWEEN(term.c.y, term.top, term.bot))
+ tscrolldown(term.c.y, n);
}
void
tdeleteline(int n) {
- if(term.c.y < term.top || term.c.y > term.bot)
- return;
-
- tscrollup(term.c.y, n);
+ if(BETWEEN(term.c.y, term.top, term.bot))
+ tscrollup(term.c.y, n);
}
int32_t
term.bot = b;
}
-#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit)))
-
void
tsetmode(bool priv, bool set, int *args, int narg) {
int *lim, mode;
MODBIT(term.mode, set, MODE_8BIT);
break;
case 1049: /* swap screen & set/restore cursor as xterm */
+ if (!allowaltscreen)
+ break;
tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD);
+ /* FALLTHRU */
case 47: /* swap screen */
case 1047:
if (!allowaltscreen)
DEFAULT(csiescseq.arg[0], 1);
tmoveto(term.c.x, term.c.y+csiescseq.arg[0]);
break;
+ case 'i': /* MC -- Media Copy */
+ switch(csiescseq.arg[0]) {
+ case 0:
+ tdump();
+ break;
+ case 1:
+ tdumpline(term.c.y);
+ break;
+ case 2:
+ tdumpsel();
+ break;
+ case 4:
+ term.mode &= ~MODE_PRINT;
+ break;
+ case 5:
+ term.mode |= MODE_PRINT;
+ break;
+ }
+ break;
case 'c': /* DA -- Device Attributes */
if(csiescseq.arg[0] == 0)
ttywrite(VT102ID, sizeof(VT102ID) - 1);
memset(&strescseq, 0, sizeof(strescseq));
}
+void
+tprinter(char *s, size_t len) {
+ if(iofd != -1 && xwrite(iofd, s, len) < 0) {
+ fprintf(stderr, "Error writing in %s:%s\n",
+ opt_io, strerror(errno));
+ close(iofd);
+ iofd = -1;
+ }
+}
+
+void
+toggleprinter(const Arg *arg) {
+ term.mode ^= MODE_PRINT;
+}
+
+void
+printscreen(const Arg *arg) {
+ tdump();
+}
+
+void
+printsel(const Arg *arg) {
+ tdumpsel();
+}
+
+void
+tdumpsel(void) {
+ char *ptr;
+
+ if((ptr = getsel())) {
+ tprinter(ptr, strlen(ptr));
+ free(ptr);
+ }
+}
+
+void
+tdumpline(int n) {
+ Glyph *bp, *end;
+
+ bp = &term.line[n][0];
+ end = &bp[term.col-1];
+ while(end > bp && !strcmp(" ", end->c))
+ --end;
+ if(bp != end || strcmp(bp->c, " ")) {
+ for( ;bp <= end; ++bp)
+ tprinter(bp->c, strlen(bp->c));
+ }
+ tprinter("\n", 1);
+}
+
+void
+tdump(void) {
+ int i;
+
+ for(i = 0; i < term.row; ++i)
+ tdumpline(i);
+}
+
void
tputtab(bool forward) {
uint x = term.c.x;
for(; len > 0; buf++, len--) {
char c = *buf;
- if(c == '\033') { /* escape */
- tputc("^", 1);
- tputc("[", 1);
- } else if(c < '\x20') { /* control code */
+ if(c < 0x20 || c == 0177) { /* control code */
if(c != '\n' && c != '\r' && c != '\t') {
- c |= '\x40';
+ c ^= '\x40';
tputc("^", 1);
}
tputc(&c, 1);
void
tselcs(void) {
- if (term.trantbl[term.charset] == CS_GRAPHIC0)
- term.c.attr.mode |= ATTR_GFX;
- else
- term.c.attr.mode &= ~ATTR_GFX;
+ MODBIT(term.c.attr.mode,
+ term.trantbl[term.charset] == CS_GRAPHIC0,
+ ATTR_GFX);
}
void
tputc(char *c, int len) {
uchar ascii = *c;
bool control = ascii < '\x20' || ascii == 0177;
- long u8char;
+ long unicodep;
int width;
if(len == 1) {
width = 1;
} else {
- utf8decode(c, &u8char);
- width = wcwidth(u8char);
+ utf8decode(c, &unicodep, UTF_SIZ);
+ width = wcwidth(unicodep);
}
- if(iofd != -1) {
- if(xwrite(iofd, c, len) < 0) {
- fprintf(stderr, "Error writing in %s:%s\n",
- opt_io, strerror(errno));
- close(iofd);
- iofd = -1;
- }
- }
+ if(IS_SET(MODE_PRINT))
+ tprinter(c, len);
/*
* STR sequences must be checked before anything else
sizeh->min_height = sizeh->max_height = xw.fh;
}
- XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm, &class);
+ XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm,
+ &class);
XFree(sizeh);
}
xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False);
XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32,
- PropModeReplace, (unsigned char *)&thispid, 1);
+ PropModeReplace, (uchar *)&thispid, 1);
xresettitle();
XMapWindow(xw.dpy, xw.win);
xhints();
- XSync(xw.dpy, 0);
+ XSync(xw.dpy, False);
}
void
int frcflags;
int u8fl, u8fblen, u8cblen, doesexist;
char *u8c, *u8fs;
- long u8char;
+ long unicodep;
Font *font = &dc.font;
FcResult fcres;
FcPattern *fcpattern, *fontpattern;
FcCharSet *fccharset;
Colour *fg, *bg, *temp, revfg, revbg, truefg, truebg;
XRenderColor colfg, colbg;
- Rectangle r;
+ XRectangle r;
int oneatatime;
frcflags = FRC_NORMAL;
if(base.fg == defaultfg)
base.fg = defaultunderline;
}
+
if(IS_TRUECOL(base.fg)) {
colfg.alpha = 0xffff;
colfg.red = TRUERED(base.fg);
bg = &dc.col[base.bg];
}
-
-
if(base.mode & ATTR_BOLD) {
if(BETWEEN(base.fg, 0, 7)) {
/* basic system colors */
colfg.green = ~fg->color.green;
colfg.blue = ~fg->color.blue;
colfg.alpha = fg->color.alpha;
- XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg);
+ XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg,
+ &revfg);
fg = &revfg;
}
colbg.green = ~bg->color.green;
colbg.blue = ~bg->color.blue;
colbg.alpha = bg->color.alpha;
- XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &revbg);
+ XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg,
+ &revbg);
bg = &revbg;
}
}
oneatatime = font->width != xw.cw;
for(;;) {
u8c = s;
- u8cblen = utf8decode(s, &u8char);
+ u8cblen = utf8decode(s, &unicodep, UTF_SIZ);
s += u8cblen;
bytelen -= u8cblen;
- doesexist = XftCharExists(xw.dpy, font->match, u8char);
+ doesexist = XftCharExists(xw.dpy, font->match, unicodep);
if(oneatatime || !doesexist || bytelen <= 0) {
if(oneatatime || bytelen <= 0) {
if(doesexist) {
u8fblen += u8cblen;
}
if(doesexist) {
- if (oneatatime)
+ if(oneatatime)
continue;
break;
}
/* Search the font cache. */
for(i = 0; i < frclen; i++) {
- if(XftCharExists(xw.dpy, frc[i].font, u8char)
+ if(XftCharExists(xw.dpy, frc[i].font, unicodep)
&& frc[i].flags == frcflags) {
break;
}
* Nothing was found in the cache. Now use
* some dozen of Fontconfig calls to get the
* font for one single character.
+ *
+ * Xft and fontconfig are design failures.
*/
fcpattern = FcPatternDuplicate(font->pattern);
fccharset = FcCharSetCreate();
- FcCharSetAddChar(fccharset, u8char);
+ FcCharSetAddChar(fccharset, unicodep);
FcPatternAddCharSet(fcpattern, FC_CHARSET,
fccharset);
FcPatternAddBool(fcpattern, FC_SCALABLE,
xp, winy + frc[i].font->ascent,
(FcChar8 *)u8c, u8cblen);
- xp += xw.cw * wcwidth(u8char);
+ xp += xw.cw * wcwidth(unicodep);
}
+ /*
+ * This is how the loop above actually should be. Why does the
+ * application have to care about font details?
+ *
+ * I have to repeat: Xft and Fontconfig are design failures.
+ */
/*
XftDrawStringUtf8(xw.draw, fg, font->set, winx,
winy + font->ascent, (FcChar8 *)s, bytelen);
XftDrawRect(xw.draw, fg, winx, winy + font->ascent + 1,
width, 1);
}
- XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, winx, winy, width,
- CEIL((font->ascent + font->descent) * chscale), winx, winy);
/* Reset clip to none. */
XftDrawSetClip(xw.draw, 0);
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);
+ sl = utf8len(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,
oldy, width, sl);
g.bg = defaultfg;
}
- sl = utf8size(g.c);
+ sl = utf8len(g.c);
width = (term.line[term.c.y][curx].mode & ATTR_WIDE)\
? 2 : 1;
xdraws(g.c, g, term.c.x, term.c.y, width, sl);
redraw(int timeout) {
struct timespec tv = {0, timeout * 1000};
- tfulldirt();
draw();
if(timeout > 0) {
void
draw(void) {
drawregion(0, 0, term.col, term.row);
+ XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, xw.w,
+ xw.h, 0, 0);
XSetForeground(xw.dpy, dc.gc,
dc.col[IS_SET(MODE_REVERSE)?
defaultfg : defaultbg].pixel);
Glyph base, new;
char buf[DRAW_BUF_SIZ];
bool ena_sel = sel.ob.x != -1;
- long u8char;
+ long unicodep;
if(sel.alt ^ IS_SET(MODE_ALTSCREEN))
ena_sel = 0;
base = new;
}
- sl = utf8decode(new.c, &u8char);
+ sl = utf8decode(new.c, &unicodep, UTF_SIZ);
memcpy(buf+ib, new.c, sl);
ib += sl;
ic += (new.mode & ATTR_WIDE)? 2 : 1;
if(IS_SET(MODE_8BIT)) {
if(*buf < 0177) {
c = *buf | 0x80;
- len = utf8encode(&c, buf);
+ len = utf8encode(c, buf, UTF_SIZ);
}
} else {
buf[1] = buf[0];
else
cresize(xw.fw, xw.fh);
- gettimeofday(&lastblink, NULL);
gettimeofday(&last, NULL);
+ lastblink = last;
for(xev = actionfps;;) {
long deltatime;
if(select(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, tv) < 0) {
if(errno == EINTR)
continue;
- die("select failed: %s\n", SERRNO);
+ die("select failed: %s\n", strerror(errno));
}
if(FD_ISSET(cmdfd, &rfd)) {
ttyread();
if(blinktimeout && TIMEDIFF(now, lastblink) > blinktimeout) {
tsetdirtattr(ATTR_BLINK);
term.mode ^= MODE_BLINK;
- gettimeofday(&lastblink, NULL);
+ lastblink = now;
dodraw = 1;
}
deltatime = TIMEDIFF(now, last);
void
usage(void) {
- die("%s " VERSION " (c) 2010-2013 st engineers\n" \
+ die("%s " VERSION " (c) 2010-2014 st engineers\n" \
"usage: st [-a] [-v] [-c class] [-f font] [-g geometry] [-o file]" \
" [-t title] [-w windowid] [-e command ...]\n", argv0);
}
if(argc > 1) {
opt_cmd = &argv[1];
if(argv[1] != NULL && opt_title == NULL) {
- titles = strdup(argv[1]);
+ titles = xstrdup(argv[1]);
opt_title = basename(titles);
}
}