X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=x.c;h=5989947e47833ee89400313febb139401df56045;hb=ddb08dfe82ca196bb4f6e554e7db0fd32da58ba2;hp=1dc44d65cd2fc114ec9791df6e325d2bd7dfdc04;hpb=914fb825df3bde7abdd7947e54f8bf4d2b55e34e;p=st.git diff --git a/x.c b/x.c index 1dc44d6..5989947 100644 --- a/x.c +++ b/x.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -14,11 +15,13 @@ #include #include #include +#include char *argv0; #include "arg.h" #include "st.h" #include "win.h" +#include "normalMode.h" /* types used in config.h */ typedef struct { @@ -45,6 +48,19 @@ 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 @@ -59,6 +75,7 @@ static void zoom(const Arg *); static void zoomabs(const Arg *); static void zoomreset(const Arg *); static void ttysend(const Arg *); +static void plumber(const Arg *); /* config.h for applying patches and the configuration. */ #include "config.h" @@ -181,11 +198,13 @@ static void selnotify(XEvent *); static void selclear_(XEvent *); static void selrequest(XEvent *); static void setsel(char *, Time); +static void plumb(char *sel); static void mousesel(XEvent *, int); static void mousereport(XEvent *); static char *kmap(KeySym, uint); static int match(uint, uint); + static void run(void); static void usage(void); @@ -216,6 +235,7 @@ static void (*handler[LASTEvent])(XEvent *) = { }; /* Globals */ +static int plumbsel; static DC dc; static XWindow xw; static XSelection xsel; @@ -253,6 +273,7 @@ static char *opt_name = NULL; static char *opt_title = NULL; static int oldbutton = 3; /* button event on startup: 3 = release */ +static int cursorblinks = 0; void clipcopy(const Arg *dummy) @@ -261,6 +282,7 @@ clipcopy(const Arg *dummy) free(xsel.clipboard); xsel.clipboard = NULL; + xsetsel(getsel()); if (xsel.primary != NULL) { xsel.clipboard = xstrdup(xsel.primary); @@ -328,6 +350,12 @@ ttysend(const Arg *arg) ttywrite(arg->s, strlen(arg->s), 1); } +void +plumber(const Arg *arg) +{ + plumb(xsel.primary); +} + int evcol(XEvent *e) { @@ -681,6 +709,37 @@ xsetsel(char *str) setsel(str, CurrentTime); } +void +plumbinit() +{ + for(plumbsel = 0; plumb_cmd[plumbsel]; plumbsel++); +} + +void +plumb(char *sel) { + if (sel == NULL) + return; + char cwd[PATH_MAX]; + pid_t child; + if (subprocwd(cwd) != 0) + return; + + plumb_cmd[plumbsel] = sel; + + switch(child = fork()) { + case -1: + return; + case 0: + if (chdir(cwd) != 0) + exit(1); + if (execvp(plumb_cmd[0], plumb_cmd) == -1) + exit(1); + exit(0); + default: + waitpid(child, NULL, 0); + } +} + void brelease(XEvent *e) { @@ -772,6 +831,8 @@ xloadcolor(int i, const char *name, Color *ncolor) return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor); } +void normalMode() { historyModeToggle((win.mode ^=MODE_NORMAL) & MODE_NORMAL); } + void xloadcols(void) { @@ -828,8 +889,8 @@ xclear(int x1, int y1, int x2, int y2) 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; @@ -1104,8 +1165,6 @@ xinit(int cols, int rows) 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); @@ -1225,8 +1284,10 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x 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) @@ -1526,16 +1587,19 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) /* draw the new one */ if (IS_SET(MODE_FOCUSED)) { switch (win.cursor) { - case 7: /* st extension: snowman (U+2603) */ - g.u = 0x2603; + 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 - \ @@ -1543,12 +1607,23 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) 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, @@ -1595,6 +1670,8 @@ xsettitle(char *p) int xstartdraw(void) { + if (IS_SET(MODE_VISIBLE)) + XCopyArea(xw.dpy, xw.win, xw.buf, dc.gc, 0, 0, win.w, win.h, 0, 0); return IS_SET(MODE_VISIBLE); } @@ -1609,6 +1686,7 @@ xdrawline(Line line, int x1, int y1, int x2) 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)) @@ -1690,10 +1768,12 @@ xsetmode(int set, unsigned int flags) int xsetcursor(int cursor) { - DEFAULT(cursor, 1); - if (!BETWEEN(cursor, 0, 6)) + 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; } @@ -1801,6 +1881,11 @@ kpress(XEvent *ev) 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)) { @@ -1937,6 +2022,10 @@ run(void) 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)) \ @@ -1947,7 +2036,7 @@ run(void) /* 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 */ @@ -1965,6 +2054,59 @@ run(void) } } +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) { @@ -1983,7 +2125,7 @@ main(int argc, char *argv[]) { xw.l = xw.t = 0; xw.isfixed = False; - win.cursor = cursorshape; + xsetcursor(cursorstyle); ARGBEGIN { case 'a': @@ -2030,6 +2172,7 @@ main(int argc, char *argv[]) } ARGEND; run: + plumbinit(); if (argc > 0) /* eat all remaining arguments */ opt_cmd = argv; @@ -2038,6 +2181,11 @@ run: 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);