-/* See LICENSE for licence details. */
+/* See LICENSE for license details. */
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
} TCursor;
/* CSI Escape sequence structs */
-/* ESC '[' [[ [<priv>] <arg> [;]] <mode>] */
+/* ESC '[' [[ [<priv>] <arg> [;]] <mode> [<mode>]] */
typedef struct {
char buf[ESC_BUF_SIZ]; /* raw string */
int len; /* raw string length */
char priv;
int arg[ESC_ARG_SIZ];
int narg; /* nb of args */
- char mode;
+ char mode[2];
} CSIEscape;
/* STR Escape sequence structs */
int ch; /* char height */
int cw; /* char width */
char state; /* focus, redraw, visible */
+ int cursor; /* cursor style */
} XWindow;
typedef struct {
static void csihandle(void);
static void csiparse(void);
static void csireset(void);
-static int eschandle(uchar ascii);
+static int eschandle(uchar);
static void strdump(void);
static void strhandle(void);
static void strparse(void);
static void ttyresize(void);
static void ttysend(char *, size_t);
static void ttywrite(const char *, size_t);
-static void tstrsequence(uchar c);
+static void tstrsequence(uchar);
+static inline ushort sixd_to_16bit(int);
static void xdraws(char *, Glyph, int, int, int, int);
static void xhints(void);
static void xclear(int, int, int, int);
static int xgeommasktogravity(int);
static int xloadfont(Font *, FcPattern *);
static void xloadfonts(char *, double);
-static int xloadfontset(Font *);
static void xsettitle(char *);
static void xresettitle(void);
static void xsetpointermotion(int);
static void selcopy(void);
static void selscroll(int, int);
static void selsnap(int, int *, int *, int);
+static int x2col(int);
+static int y2row(int);
static void getbuttoninfo(XEvent *);
static void mousereport(XEvent *);
return i;
}
-static void
+void
selinit(void) {
memset(&sel.tclick1, 0, sizeof(sel.tclick1));
memset(&sel.tclick2, 0, sizeof(sel.tclick2));
sel.xtarget = XA_STRING;
}
-static int
+int
x2col(int x) {
x -= borderpx;
x /= xw.cw;
return LIMIT(x, 0, term.col-1);
}
-static int
+int
y2row(int y) {
y -= borderpx;
y /= xw.ch;
return LIMIT(y, 0, term.row-1);
}
-static int tlinelen(int y) {
+int tlinelen(int y) {
int i = term.col;
if(term.line[y][i - 1].mode & ATTR_WRAP)
return i;
}
-static void
+void
selnormalize(void) {
int i;
sel.ne.x = term.col - 1;
}
-static inline bool
+bool
selected(int x, int y) {
if(sel.type == SEL_RECTANGULAR)
return BETWEEN(y, sel.nb.y, sel.ne.y)
ptr = str = xmalloc(bufsize);
/* append every set & selected glyph to the selection */
- for(y = sel.nb.y; y < sel.ne.y + 1; y++) {
+ for(y = sel.nb.y; y <= sel.ne.y; y++) {
linelen = tlinelen(y);
if(sel.type == SEL_RECTANGULAR) {
ofs = 0;
xsev = (XSelectionEvent *)e;
+ if (xsev->property == None)
+ return;
do {
if(XGetWindowProperty(xw.dpy, xw.win, xsev->property, ofs,
BUFSIZ/4, False, AnyPropertyType,
break;
p++;
}
- csiescseq.mode = *p;
+ csiescseq.mode[0] = *p++;
+ csiescseq.mode[1] = (p < csiescseq.buf+csiescseq.len) ? *p : '\0';
}
/* for absolute user moves, when decom is set */
miny = 0;
maxy = term.row - 1;
}
- LIMIT(x, 0, term.col-1);
- LIMIT(y, miny, maxy);
term.c.state &= ~CURSOR_WRAPNEXT;
- term.c.x = x;
- term.c.y = y;
+ term.c.x = LIMIT(x, 0, term.col-1);
+ term.c.y = LIMIT(y, miny, maxy);
}
void
char buf[40];
int len;
- switch(csiescseq.mode) {
+ switch(csiescseq.mode[0]) {
default:
unknown:
fprintf(stderr, "erresc: unknown csi ");
case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */
tcursor(CURSOR_LOAD);
break;
+ case ' ':
+ switch (csiescseq.mode[1]) {
+ case 'q': /* DECSCUSR -- Set Cursor Style */
+ DEFAULT(csiescseq.arg[0], 1);
+ if (!BETWEEN(csiescseq.arg[0], 0, 6)) {
+ goto unknown;
+ }
+ xw.cursor = csiescseq.arg[0];
+ break;
+ default:
+ goto unknown;
+ }
+ break;
}
}
void
strparse(void) {
+ int c;
char *p = strescseq.buf;
strescseq.narg = 0;
strescseq.buf[strescseq.len] = '\0';
- while(p && strescseq.narg < STR_ARG_SIZ)
- strescseq.args[strescseq.narg++] = strsep(&p, ";");
+
+ if(*p == '\0')
+ return;
+
+ while(strescseq.narg < STR_ARG_SIZ) {
+ strescseq.args[strescseq.narg++] = p;
+ while((c = *p) != ';' && c != '\0')
+ ++p;
+ if(c == '\0')
+ return;
+ *p++ = '\0';
+ }
}
void
void
tstrsequence(uchar c) {
- if (c & 0x80) {
- switch (c) {
- case 0x90: /* DCS -- Device Control String */
- c = 'P';
- break;
- case 0x9f: /* APC -- Application Program Command */
- c = '_';
- break;
- case 0x9e: /* PM -- Privacy Message */
- c = '^';
- break;
- case 0x9d: /* OSC -- Operating System Command */
- c = ']';
- break;
- }
+ switch (c) {
+ case 0x90: /* DCS -- Device Control String */
+ c = 'P';
+ break;
+ case 0x9f: /* APC -- Application Program Command */
+ c = '_';
+ break;
+ case 0x9e: /* PM -- Privacy Message */
+ c = '^';
+ break;
+ case 0x9d: /* OSC -- Operating System Command */
+ c = ']';
+ break;
}
strreset();
strescseq.type = c;
c = "\357\277\275"; /* UTF_INVALID */
width = 1;
}
- control = ISCONTROLC1(unicodep);
ascii = unicodep;
}
* character.
*/
if(term.esc & ESC_STR) {
- if(width == 1 &&
+ if(len == 1 &&
(ascii == '\a' || ascii == 030 ||
ascii == 032 || ascii == 033 ||
ISCONTROLC1(unicodep))) {
int i;
int minrow = MIN(row, term.row);
int mincol = MIN(col, term.col);
- int slide = term.c.y - row + 1;
bool *bp;
TCursor c;
return;
}
- /* free unneeded rows */
- i = 0;
- if(slide > 0) {
- /*
- * slide screen to keep cursor where we expect it -
- * tscrollup would work here, but we can optimize to
- * memmove because we're freeing the earlier lines
- */
- for(/* i = 0 */; i < slide; i++) {
- free(term.line[i]);
- free(term.alt[i]);
- }
- memmove(term.line, term.line + slide, row * sizeof(Line));
- memmove(term.alt, term.alt + slide, row * sizeof(Line));
+ /*
+ * slide screen to keep cursor where we expect it -
+ * tscrollup would work here, but we can optimize to
+ * memmove because we're freeing the earlier lines
+ */
+ for(i = 0; i <= term.c.y - row; i++) {
+ free(term.line[i]);
+ free(term.alt[i]);
+ }
+ if(i > 0) {
+ memmove(term.line, term.line + i, row * sizeof(Line));
+ memmove(term.alt, term.alt + i, row * sizeof(Line));
}
for(i += row; i < term.row; i++) {
free(term.line[i]);
xclear(0, 0, xw.w, xw.h);
}
-static inline ushort
+ushort
sixd_to_16bit(int x) {
return x == 0 ? 0 : 0x3737 + 0x2828 * x;
}
FcPatternDestroy(pattern);
}
-int
-xloadfontset(Font *f) {
- FcResult result;
-
- if(!(f->set = FcFontSort(0, f->pattern, FcTrue, 0, &result)))
- return 1;
- return 0;
-}
-
void
xunloadfont(Font *f) {
XftFontClose(xw.dpy, f->match);
/* Nothing was found. */
if(i >= frclen) {
if(!font->set)
- xloadfontset(font);
+ font->set = FcFontSort(0, font->pattern,
+ FcTrue, 0, &fcres);
fcsets[0] = font->set;
/*
/* draw the new one */
if(xw.state & WIN_FOCUSED) {
- if(IS_SET(MODE_REVERSE)) {
- g.mode |= ATTR_REVERSE;
- g.fg = defaultcs;
- g.bg = defaultfg;
- }
+ switch (xw.cursor) {
+ case 0: /* Blinking Block */
+ case 1: /* Blinking Block (Default) */
+ case 2: /* Steady Block */
+ if(IS_SET(MODE_REVERSE)) {
+ g.mode |= ATTR_REVERSE;
+ g.fg = defaultcs;
+ g.bg = defaultfg;
+ }
- 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);
+ 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);
+ break;
+ case 3: /* Blinking Underline */
+ case 4: /* Steady Underline */
+ XftDrawRect(xw.draw, &dc.col[defaultcs],
+ borderpx + curx * xw.cw,
+ borderpx + (term.c.y + 1) * xw.ch - cursorthickness,
+ xw.cw, cursorthickness);
+ break;
+ case 5: /* Blinking bar */
+ case 6: /* Steady bar */
+ XftDrawRect(xw.draw, &dc.col[defaultcs],
+ borderpx + curx * xw.cw,
+ borderpx + term.c.y * xw.ch,
+ cursorthickness, xw.ch);
+ break;
+ }
} else {
XftDrawRect(xw.draw, &dc.col[defaultcs],
borderpx + curx * xw.cw,
}
}
-static inline bool
+bool
match(uint mask, uint state) {
return mask == XK_ANY_MOD || mask == (state & ~ignoremod);
}
long deltatime;
/* Waiting for window mapping */
- while(1) {
+ do {
XNextEvent(xw.dpy, &ev);
- if(XFilterEvent(&ev, None))
- continue;
if(ev.type == ConfigureNotify) {
w = ev.xconfigure.width;
h = ev.xconfigure.height;
- } else if(ev.type == MapNotify) {
- break;
}
- }
+ } while(ev.type != MapNotify);
ttynew();
cresize(w, h);
int
main(int argc, char *argv[]) {
- char *titles;
uint cols = 80, rows = 24;
xw.l = xw.t = 0;
xw.isfixed = False;
+ xw.cursor = 0;
ARGBEGIN {
case 'a':
/* eat all remaining arguments */
if(argc > 1) {
opt_cmd = &argv[1];
- if(argv[1] != NULL && opt_title == NULL) {
- titles = xstrdup(argv[1]);
- opt_title = basename(titles);
- }
+ if(argv[1] != NULL && opt_title == NULL)
+ opt_title = basename(xstrdup(argv[1]));
}
goto run;
case 'f':
run:
setlocale(LC_CTYPE, "");
XSetLocaleModifiers("");
- tnew(cols? cols : 1, rows? rows : 1);
+ tnew(MAX(cols, 1), MAX(rows, 1));
xinit();
selinit();
run();