X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=x.c;h=7bfa1b75891edd6bc2d88f3cc4de92640186b67c;hb=d84f3f4bd15e7d65fc0334cf7d62913c901bad00;hp=c484dfcf8a5c258303e850b546b55060f5a7cb68;hpb=1f24bde82b19912c080fbb4a0b153a248cd6c6ea;p=st.git diff --git a/x.c b/x.c index c484dfc..7bfa1b7 100644 --- a/x.c +++ b/x.c @@ -15,13 +15,50 @@ #include #include +static char *argv0; #include "arg.h" +#include "st.h" +#include "win.h" -#define Glyph Glyph_ -#define Font Font_ +/* types used in config.h */ +typedef struct { + uint mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; +} Shortcut; -#include "win.h" -#include "st.h" +typedef struct { + uint b; + uint mask; + char *s; +} MouseShortcut; + +typedef struct { + KeySym k; + uint mask; + char *s; + /* three valued logic variables: 0 indifferent, 1 on, -1 off */ + signed char appkey; /* application keypad */ + signed char appcursor; /* application cursor */ + signed char crlf; /* crlf mode */ +} Key; + +/* X modifiers */ +#define XK_ANY_MOD UINT_MAX +#define XK_NO_MOD 0 +#define XK_SWITCH_MOD (1<<13) + +/* function definitions used in config.h */ +static void clipcopy(const Arg *); +static void clippaste(const Arg *); +static void selpaste(const Arg *); +static void zoom(const Arg *); +static void zoomabs(const Arg *); +static void zoomreset(const Arg *); + +/* config.h for applying patches and the configuration. */ +#include "config.h" /* XEMBED messages */ #define XEMBED_FOCUS_IN 4 @@ -34,6 +71,7 @@ typedef XftDraw *Draw; typedef XftColor Color; +typedef XftGlyphFontSpec GlyphFontSpec; /* Purely graphic info */ typedef struct { @@ -41,6 +79,7 @@ typedef struct { Colormap cmap; Window win; Drawable buf; + GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ Atom xembed, wmdeletewin, netwmname, netwmpid; XIM xim; XIC xic; @@ -58,6 +97,7 @@ typedef struct { } XSelection; /* Font structure */ +#define Font Font_ typedef struct { int height; int width; @@ -87,8 +127,17 @@ static void xdrawglyph(Glyph, int, int); static void xclear(int, int, int, int); static void xdrawcursor(void); static int xgeommasktogravity(int); +static void xinit(void); +static void cresize(int, int); +static void xresize(int, int); static int xloadfont(Font *, FcPattern *); +static void xloadfonts(char *, double); static void xunloadfont(Font *); +static void xunloadfonts(void); +static void xsetenv(void); +static void xseturgency(int); +static int x2col(int); +static int y2row(int); static void expose(XEvent *); static void visibility(XEvent *); @@ -104,10 +153,14 @@ static void propnotify(XEvent *); static void selnotify(XEvent *); static void selclear_(XEvent *); static void selrequest(XEvent *); - -static void selcopy(Time); +static void setsel(char *, Time); static void getbuttoninfo(XEvent *); static void mousereport(XEvent *); +static char *kmap(KeySym, uint); +static int match(uint, uint); + +static void run(void); +static void usage(void); static void (*handler[LASTEvent])(XEvent *) = { [KeyPress] = kpress, @@ -139,6 +192,12 @@ static void (*handler[LASTEvent])(XEvent *) = { static DC dc; static XWindow xw; static XSelection xsel; +static TermWindow win; + +enum window_state { + WIN_VISIBLE = 1, + WIN_FOCUSED = 2 +}; /* Font Ring Cache */ enum { @@ -157,6 +216,98 @@ typedef struct { /* Fontcache is an array now. A new font will be appended to the array. */ static Fontcache frc[16]; static int frclen = 0; +static char *usedfont = NULL; +static double usedfontsize = 0; +static double defaultfontsize = 0; + +static char *opt_class = NULL; +static char **opt_cmd = NULL; +static char *opt_embed = NULL; +static char *opt_font = NULL; +static char *opt_io = NULL; +static char *opt_line = NULL; +static char *opt_name = NULL; +static char *opt_title = NULL; + +void +clipcopy(const Arg *dummy) +{ + Atom clipboard; + + if (sel.clipboard != NULL) + free(sel.clipboard); + + if (sel.primary != NULL) { + sel.clipboard = xstrdup(sel.primary); + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); + } +} + +void +clippaste(const Arg *dummy) +{ + Atom clipboard; + + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, + xw.win, CurrentTime); +} + +void +selpaste(const Arg *dummy) +{ + XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, + xw.win, CurrentTime); +} + +void +zoom(const Arg *arg) +{ + Arg larg; + + larg.f = usedfontsize + arg->f; + zoomabs(&larg); +} + +void +zoomabs(const Arg *arg) +{ + xunloadfonts(); + xloadfonts(usedfont, arg->f); + cresize(0, 0); + redraw(); + xhints(); +} + +void +zoomreset(const Arg *arg) +{ + Arg larg; + + if (defaultfontsize > 0) { + larg.f = defaultfontsize; + zoomabs(&larg); + } +} + +int +x2col(int x) +{ + x -= borderpx; + x /= win.cw; + + return LIMIT(x, 0, term.col-1); +} + +int +y2row(int y) +{ + y -= borderpx; + y /= win.ch; + + return LIMIT(y, 0, term.row-1); +} void getbuttoninfo(XEvent *e) @@ -171,7 +322,7 @@ getbuttoninfo(XEvent *e) selnormalize(); sel.type = SEL_REGULAR; - for (type = 1; type < selmaskslen; ++type) { + for (type = 1; type < LEN(selmasks); ++type) { if (match(selmasks[type], state)) { sel.type = type; break; @@ -254,7 +405,7 @@ bpress(XEvent *e) return; } - for (ms = mshortcuts; ms < mshortcuts + mshortcutslen; ms++) { + for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { if (e->xbutton.button == ms->b && match(ms->mask, e->xbutton.state)) { ttysend(ms->s, strlen(ms->s)); @@ -293,12 +444,6 @@ bpress(XEvent *e) } } -void -selcopy(Time t) -{ - xsetsel(getsel(), t); -} - void propnotify(XEvent *e) { @@ -402,36 +547,10 @@ selnotify(XEvent *e) XDeleteProperty(xw.dpy, xw.win, (int)property); } -void -xselpaste(void) -{ - XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, - xw.win, CurrentTime); -} - void xclipcopy(void) { - Atom clipboard; - - if (sel.clipboard != NULL) - free(sel.clipboard); - - if (sel.primary != NULL) { - sel.clipboard = xstrdup(sel.primary); - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); - } -} - -void -xclippaste(void) -{ - Atom clipboard; - - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, - xw.win, CurrentTime); + clipcopy(NULL); } void @@ -499,7 +618,7 @@ selrequest(XEvent *e) } void -xsetsel(char *str, Time t) +setsel(char *str, Time t) { free(sel.primary); sel.primary = str; @@ -509,6 +628,12 @@ xsetsel(char *str, Time t) selclear_(NULL); } +void +xsetsel(char *str) +{ + setsel(str, CurrentTime); +} + void brelease(XEvent *e) { @@ -518,11 +643,11 @@ brelease(XEvent *e) } if (e->xbutton.button == Button2) { - xselpaste(); + selpaste(NULL); } else if (e->xbutton.button == Button1) { if (sel.mode == SEL_READY) { getbuttoninfo(e); - selcopy(e->xbutton.time); + setsel(getsel(), e->xbutton.time); } else selclear_(NULL); sel.mode = SEL_IDLE; @@ -554,6 +679,24 @@ bmotion(XEvent *e) tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); } +void +cresize(int width, int height) +{ + int col, row; + + if (width != 0) + win.w = width; + if (height != 0) + win.h = height; + + col = (win.w - 2 * borderpx) / win.cw; + row = (win.h - 2 * borderpx) / win.ch; + + tresize(col, row); + xresize(col, row); + ttyresize(win.tw, win.th); +} + void xresize(int col, int row) { @@ -565,6 +708,9 @@ xresize(int col, int row) DefaultDepth(xw.dpy, xw.scr)); XftDrawChange(xw.draw, xw.buf); xclear(0, 0, win.w, win.h); + + /* resize to new width */ + xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec)); } ushort @@ -604,7 +750,7 @@ xloadcols(void) static int loaded; Color *cp; - dc.collen = MAX(colornamelen, 256); + dc.collen = MAX(LEN(colorname), 256); dc.col = xmalloc(dc.collen * sizeof(Color)); if (loaded) { @@ -925,6 +1071,9 @@ xinit(void) XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); + /* font spec buffer */ + xw.specbuf = xmalloc(term.col * sizeof(GlyphFontSpec)); + /* Xft rendering context */ xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); @@ -1380,6 +1529,7 @@ void xsettitle(char *p) { XTextProperty prop; + DEFAULT(p, "st"); Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, &prop); @@ -1416,7 +1566,7 @@ drawregion(int x1, int y1, int x2, int y2) term.dirty[y] = 0; - specs = term.specbuf; + specs = xw.specbuf; numspecs = xmakeglyphfontspecs(specs, &term.line[y][x1], x2 - x1, x1, y); i = ox = 0; @@ -1471,6 +1621,16 @@ xsetpointermotion(int set) XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); } +int +xsetcursor(int cursor) +{ + DEFAULT(cursor, 1); + if (!BETWEEN(cursor, 0, 6)) + return 1; + win.cursor = cursor; + return 0; +} + void xseturgency(int add) { @@ -1482,15 +1642,12 @@ xseturgency(int add) } void -xbell(int vol) -{ - XkbBell(xw.dpy, xw.win, vol, (Atom)NULL); -} - -unsigned long -xwinid(void) +xbell(void) { - return xw.win; + if (!(win.state & WIN_FOCUSED)) + xseturgency(1); + if (bellvolume) + XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); } void @@ -1515,6 +1672,52 @@ focus(XEvent *ev) } } +int +match(uint mask, uint state) +{ + return mask == XK_ANY_MOD || mask == (state & ~ignoremod); +} + +char* +kmap(KeySym k, uint state) +{ + Key *kp; + int i; + + /* Check for mapped keys out of X11 function keys. */ + for (i = 0; i < LEN(mappedkeys); i++) { + if (mappedkeys[i] == k) + break; + } + if (i == LEN(mappedkeys)) { + if ((k & 0xFFFF) < 0xFD00) + return NULL; + } + + for (kp = key; kp < key + LEN(key); kp++) { + if (kp->k != k) + continue; + + if (!match(kp->mask, state)) + continue; + + if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) + continue; + if (term.numlock && kp->appkey == 2) + continue; + + if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) + continue; + + if (IS_SET(MODE_CRLF) ? kp->crlf < 0 : kp->crlf > 0) + continue; + + return kp->s; + } + + return NULL; +} + void kpress(XEvent *ev) { @@ -1531,7 +1734,7 @@ kpress(XEvent *ev) len = XmbLookupString(xw.xic, e, buf, sizeof buf, &ksym, &status); /* 1. shortcuts */ - for (bp = shortcuts; bp < shortcuts + shortcutslen; bp++) { + for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { if (ksym == bp->keysym && match(bp->mod, e->state)) { bp->func(&(bp->arg)); return; @@ -1591,7 +1794,6 @@ resize(XEvent *e) return; cresize(e->xconfigure.width, e->xconfigure.height); - ttyresize(); } void @@ -1620,9 +1822,8 @@ run(void) } } while (ev.type != MapNotify); + ttynew(opt_line, opt_io, opt_cmd); cresize(w, h); - ttynew(); - ttyresize(); clock_gettime(CLOCK_MONOTONIC, &last); lastblink = last; @@ -1703,6 +1904,19 @@ run(void) } } +void +usage(void) +{ + die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid]" + " [[-e] command [args ...]]\n" + " %s [-aiv] [-c class] [-f font] [-g geometry]" + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid] -l line" + " [stty_args ...]\n", argv0, argv0); +} + int main(int argc, char *argv[]) { @@ -1765,6 +1979,7 @@ run: XSetLocaleModifiers(""); tnew(MAX(cols, 1), MAX(rows, 1)); xinit(); + xsetenv(); selinit(); run();