#include <X11/keysym.h>
#include <X11/Xft/Xft.h>
#include <X11/XKBlib.h>
+#include <X11/Xresource.h>
char *argv0;
#include "arg.h"
#include "st.h"
#include "win.h"
+#include "normalMode.h"
/* types used in config.h */
typedef struct {
signed char appcursor; /* application cursor */
} Key;
+/* Xresources preferences */
+enum resource_type {
+ STRING = 0,
+ INTEGER = 1,
+ FLOAT = 2
+};
+
+typedef struct {
+ char *name;
+ enum resource_type type;
+ void *dst;
+} ResourcePref;
+
/* X modifiers */
#define XK_ANY_MOD UINT_MAX
#define XK_NO_MOD 0
static char *opt_title = NULL;
static int oldbutton = 3; /* button event on startup: 3 = release */
+static int cursorblinks = 0;
void
clipcopy(const Arg *dummy)
free(xsel.clipboard);
xsel.clipboard = NULL;
+ xsetsel(getsel());
if (xsel.primary != NULL) {
xsel.clipboard = xstrdup(xsel.primary);
return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor);
}
+void normalMode() { historyModeToggle((win.mode ^=MODE_NORMAL) & MODE_NORMAL); }
+
void
xloadcols(void)
{
void
xhints(void)
{
- XClassHint class = {opt_name ? opt_name : termname,
- opt_class ? opt_class : termname};
+ XClassHint class = {opt_name ? opt_name : "st",
+ opt_class ? opt_class : "St"};
XWMHints wm = {.flags = InputHint, .input = 1};
XSizeHints *sizeh;
pid_t thispid = getpid();
XColor xmousefg, xmousebg;
- if (!(xw.dpy = XOpenDisplay(NULL)))
- die("can't open display\n");
xw.scr = XDefaultScreen(xw.dpy);
xw.vis = XDefaultVisual(xw.dpy, xw.scr);
for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) {
/* Fetch rune and mode for current glyph. */
- rune = glyphs[i].u;
- mode = glyphs[i].mode;
+ Glyph g = glyphs[i];
+ historyOverlay(x+i, y, &g);
+ rune = g.u;
+ mode = g.mode;
/* Skip dummy wide-character spacing. */
if (mode == ATTR_WDUMMY)
/* draw the new one */
if (IS_SET(MODE_FOCUSED)) {
switch (win.cursor) {
- case 7: /* st extension */
- g.u = 0x2603; /* snowman (U+2603) */
+ case 0: /* Blinking block */
+ case 1: /* Blinking block (default) */
+ if (IS_SET(MODE_BLINK))
+ break;
/* FALLTHROUGH */
- case 0: /* Blinking Block */
- case 1: /* Blinking Block (Default) */
- case 2: /* Steady Block */
+ case 2: /* Steady block */
xdrawglyph(g, cx, cy);
break;
- case 3: /* Blinking Underline */
- case 4: /* Steady Underline */
+ case 3: /* Blinking underline */
+ if (IS_SET(MODE_BLINK))
+ break;
+ /* FALLTHROUGH */
+ case 4: /* Steady underline */
XftDrawRect(xw.draw, &drawcol,
borderpx + cx * win.cw,
borderpx + (cy + 1) * win.ch - \
win.cw, cursorthickness);
break;
case 5: /* Blinking bar */
+ if (IS_SET(MODE_BLINK))
+ break;
+ /* FALLTHROUGH */
case 6: /* Steady bar */
XftDrawRect(xw.draw, &drawcol,
borderpx + cx * win.cw,
borderpx + cy * win.ch,
cursorthickness, win.ch);
break;
+ case 7: /* Blinking st cursor */
+ if (IS_SET(MODE_BLINK))
+ break;
+ /* FALLTHROUGH */
+ case 8: /* Steady st cursor */
+ g.u = stcursor;
+ xdrawglyph(g, cx, cy);
+ break;
}
} else {
XftDrawRect(xw.draw, &drawcol,
i = ox = 0;
for (x = x1; x < x2 && i < numspecs; x++) {
new = line[x];
+ historyOverlay(x, y1, &new);
if (new.mode == ATTR_WDUMMY)
continue;
if (selected(x, y1))
int
xsetcursor(int cursor)
{
- if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */
+ if (!BETWEEN(cursor, 0, 8)) /* 7-8: st extensions */
return 1;
win.cursor = cursor;
+ cursorblinks = win.cursor == 0 || win.cursor == 1 ||
+ win.cursor == 3 || win.cursor == 5 ||
+ win.cursor == 7;
return 0;
}
len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status);
else
len = XLookupString(e, buf, sizeof buf, &ksym, NULL);
+ if (IS_SET(MODE_NORMAL)) {
+ if (kpressHist(buf, len, match(ControlMask, e->state), &ksym)
+ == finished) normalMode();
+ return;
+ }
/* 1. shortcuts */
for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) {
if (ksym == bp->keysym && match(bp->mod, e->state)) {
if (FD_ISSET(ttyfd, &rfd) || xev) {
if (!drawing) {
trigger = now;
+ if (IS_SET(MODE_BLINK)) {
+ win.mode ^= MODE_BLINK;
+ }
+ lastblink = now;
drawing = 1;
}
timeout = (maxlatency - TIMEDIFF(now, trigger)) \
/* idle detected or maxlatency exhausted -> draw */
timeout = -1;
- if (blinktimeout && tattrset(ATTR_BLINK)) {
+ if (blinktimeout && (cursorblinks || tattrset(ATTR_BLINK))) {
timeout = blinktimeout - TIMEDIFF(now, lastblink);
if (timeout <= 0) {
if (-timeout > blinktimeout) /* start visible */
}
}
+int
+resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
+{
+ char **sdst = dst;
+ int *idst = dst;
+ float *fdst = dst;
+
+ char fullname[256];
+ char fullclass[256];
+ char *type;
+ XrmValue ret;
+
+ snprintf(fullname, sizeof(fullname), "%s.%s",
+ opt_name ? opt_name : "st", name);
+ snprintf(fullclass, sizeof(fullclass), "%s.%s",
+ opt_class ? opt_class : "St", name);
+ fullname[sizeof(fullname) - 1] = fullclass[sizeof(fullclass) - 1] = '\0';
+
+ XrmGetResource(db, fullname, fullclass, &type, &ret);
+ if (ret.addr == NULL || strncmp("String", type, 64))
+ return 1;
+
+ switch (rtype) {
+ case STRING:
+ *sdst = ret.addr;
+ break;
+ case INTEGER:
+ *idst = strtoul(ret.addr, NULL, 10);
+ break;
+ case FLOAT:
+ *fdst = strtof(ret.addr, NULL);
+ break;
+ }
+ return 0;
+}
+
+void
+config_init(void)
+{
+ char *resm;
+ XrmDatabase db;
+ ResourcePref *p;
+
+ XrmInitialize();
+ resm = XResourceManagerString(xw.dpy);
+ if (!resm)
+ return;
+
+ db = XrmGetStringDatabase(resm);
+ for (p = resources; p < resources + LEN(resources); p++)
+ resource_load(db, p->name, p->type, p->dst);
+}
+
void
usage(void)
{
{
xw.l = xw.t = 0;
xw.isfixed = False;
- xsetcursor(cursorshape);
+ xsetcursor(cursorstyle);
ARGBEGIN {
case 'a':
setlocale(LC_CTYPE, "");
XSetLocaleModifiers("");
+
+ if(!(xw.dpy = XOpenDisplay(NULL)))
+ die("Can't open display\n");
+
+ config_init();
cols = MAX(cols, 1);
rows = MAX(rows, 1);
tnew(cols, rows);