-
-void
-drawregion(int x1, int y1, int x2, int y2) {
- int ic, ib, x, y, ox, sl;
- Glyph base, new;
- char buf[DRAW_BUF_SIZ];
- bool ena_sel = sel.ob.x != -1 && sel.alt == IS_SET(MODE_ALTSCREEN);
- long unicodep;
-
- if(!(xw.state & WIN_VISIBLE))
- return;
-
- for(y = y1; y < y2; y++) {
- if(!term.dirty[y])
- continue;
-
- xtermclear(0, y, term.col, y);
- term.dirty[y] = 0;
- base = term.line[y][0];
- ic = ib = ox = 0;
- for(x = x1; x < x2; x++) {
- new = term.line[y][x];
- if(new.mode == ATTR_WDUMMY)
- continue;
- if(ena_sel && selected(x, y))
- new.mode ^= ATTR_REVERSE;
- if(ib > 0 && (ATTRCMP(base, new)
- || ib >= DRAW_BUF_SIZ-UTF_SIZ)) {
- xdraws(buf, base, ox, y, ic, ib);
- ic = ib = 0;
- }
- if(ib == 0) {
- ox = x;
- base = new;
- }
-
- sl = utf8decode(new.c, &unicodep, UTF_SIZ);
- memcpy(buf+ib, new.c, sl);
- ib += sl;
- ic += (new.mode & ATTR_WIDE)? 2 : 1;
- }
- if(ib > 0)
- xdraws(buf, base, ox, y, ic, ib);
- }
- xdrawcursor();
-}
-
-void
-expose(XEvent *ev) {
- XExposeEvent *e = &ev->xexpose;
-
- if(xw.state & WIN_REDRAW) {
- if(!e->count)
- xw.state &= ~WIN_REDRAW;
- }
- redraw(0);
-}
-
-void
-visibility(XEvent *ev) {
- XVisibilityEvent *e = &ev->xvisibility;
-
- if(e->state == VisibilityFullyObscured) {
- xw.state &= ~WIN_VISIBLE;
- } else if(!(xw.state & WIN_VISIBLE)) {
- /* need a full redraw for next Expose, not just a buf copy */
- xw.state |= WIN_VISIBLE | WIN_REDRAW;
- }
-}
-
-void
-unmap(XEvent *ev) {
- xw.state &= ~WIN_VISIBLE;
-}
-
-void
-xsetpointermotion(int set) {
- MODBIT(xw.attrs.event_mask, set, PointerMotionMask);
- XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs);
-}
-
-void
-xseturgency(int add) {
- XWMHints *h = XGetWMHints(xw.dpy, xw.win);
-
- MODBIT(h->flags, add, XUrgencyHint);
- XSetWMHints(xw.dpy, xw.win, h);
- XFree(h);
-}
-
-void
-focus(XEvent *ev) {
- XFocusChangeEvent *e = &ev->xfocus;
-
- if(e->mode == NotifyGrab)
- return;
-
- if(ev->type == FocusIn) {
- XSetICFocus(xw.xic);
- xw.state |= WIN_FOCUSED;
- xseturgency(0);
- if(IS_SET(MODE_FOCUS))
- ttywrite("\033[I", 3);
- } else {
- XUnsetICFocus(xw.xic);
- xw.state &= ~WIN_FOCUSED;
- if(IS_SET(MODE_FOCUS))
- ttywrite("\033[O", 3);
- }
-}
-
-static inline bool
-match(uint mask, uint state) {
- return mask == XK_ANY_MOD || mask == (state & ~ignoremod);
-}
-
-void
-numlock(const Arg *dummy) {
- term.numlock ^= 1;
-}
-
-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) {
- XKeyEvent *e = &ev->xkey;
- KeySym ksym;
- char buf[32], *customkey;
- int len;
- long c;
- Status status;
- Shortcut *bp;
-
- if(IS_SET(MODE_KBDLOCK))
- return;
-
- len = XmbLookupString(xw.xic, e, buf, sizeof buf, &ksym, &status);
- /* 1. shortcuts */
- for(bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) {
- if(ksym == bp->keysym && match(bp->mod, e->state)) {
- bp->func(&(bp->arg));
- return;
- }
- }
-
- /* 2. custom keys from config.h */
- if((customkey = kmap(ksym, e->state))) {
- ttysend(customkey, strlen(customkey));
- return;
- }
-
- /* 3. composed string from input method */
- if(len == 0)
- return;
- if(len == 1 && e->state & Mod1Mask) {
- if(IS_SET(MODE_8BIT)) {
- if(*buf < 0177) {
- c = *buf | 0x80;
- len = utf8encode(c, buf, UTF_SIZ);
- }
- } else {
- buf[1] = buf[0];
- buf[0] = '\033';
- len = 2;
- }
- }
- ttysend(buf, len);
-}
-
-
-void
-cmessage(XEvent *e) {
- /*
- * See xembed specs
- * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html
- */
- if(e->xclient.message_type == xw.xembed && e->xclient.format == 32) {
- if(e->xclient.data.l[1] == XEMBED_FOCUS_IN) {
- xw.state |= WIN_FOCUSED;
- xseturgency(0);
- } else if(e->xclient.data.l[1] == XEMBED_FOCUS_OUT) {
- xw.state &= ~WIN_FOCUSED;
- }
- } else if(e->xclient.data.l[0] == xw.wmdeletewin) {
- /* Send SIGHUP to shell */
- kill(pid, SIGHUP);
- exit(EXIT_SUCCESS);
- }
-}
-
-void
-cresize(int width, int height) {
- int col, row;
-
- if(width != 0)
- xw.w = width;
- if(height != 0)
- xw.h = height;
-
- col = (xw.w - 2 * borderpx) / xw.cw;
- row = (xw.h - 2 * borderpx) / xw.ch;
-
- tresize(col, row);
- xresize(col, row);
- ttyresize();
-}
-
-void
-resize(XEvent *e) {
- if(e->xconfigure.width == xw.w && e->xconfigure.height == xw.h)
- return;
-
- cresize(e->xconfigure.width, e->xconfigure.height);
-}
-
-void
-run(void) {
- XEvent ev;
- int w = xw.w, h = xw.h;
- fd_set rfd;
- int xfd = XConnectionNumber(xw.dpy), xev, blinkset = 0, dodraw = 0;
- struct timeval drawtimeout, *tv = NULL, now, last, lastblink;
-
- /* Waiting for window mapping */
- while(1) {
- XNextEvent(xw.dpy, &ev);
- if(ev.type == ConfigureNotify) {
- w = ev.xconfigure.width;
- h = ev.xconfigure.height;
- } else if(ev.type == MapNotify) {
- break;
- }
- }
-
- ttynew();
- cresize(w, h);
-
- gettimeofday(&last, NULL);
- lastblink = last;
-
- for(xev = actionfps;;) {
- long deltatime;
-
- FD_ZERO(&rfd);
- FD_SET(cmdfd, &rfd);
- FD_SET(xfd, &rfd);
-
- if(select(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, tv) < 0) {
- if(errno == EINTR)
- continue;
- die("select failed: %s\n", strerror(errno));
- }
- if(FD_ISSET(cmdfd, &rfd)) {
- ttyread();
- if(blinktimeout) {
- blinkset = tattrset(ATTR_BLINK);
- if(!blinkset)
- MODBIT(term.mode, 0, MODE_BLINK);
- }
- }
-
- if(FD_ISSET(xfd, &rfd))
- xev = actionfps;
-
- gettimeofday(&now, NULL);
- drawtimeout.tv_sec = 0;
- drawtimeout.tv_usec = (1000/xfps) * 1000;
- tv = &drawtimeout;
-
- dodraw = 0;
- if(blinktimeout && TIMEDIFF(now, lastblink) > blinktimeout) {
- tsetdirtattr(ATTR_BLINK);
- term.mode ^= MODE_BLINK;
- lastblink = now;
- dodraw = 1;
- }
- deltatime = TIMEDIFF(now, last);
- if(deltatime > (xev? (1000/xfps) : (1000/actionfps))
- || deltatime < 0) {
- dodraw = 1;
- last = now;
- }
-
- if(dodraw) {
- while(XPending(xw.dpy)) {
- XNextEvent(xw.dpy, &ev);
- if(XFilterEvent(&ev, None))
- continue;
- if(handler[ev.type])
- (handler[ev.type])(&ev);
- }
-
- draw();
- XFlush(xw.dpy);
-
- if(xev && !FD_ISSET(xfd, &rfd))
- xev--;
- if(!FD_ISSET(cmdfd, &rfd) && !FD_ISSET(xfd, &rfd)) {
- if(blinkset) {
- if(TIMEDIFF(now, lastblink) \
- > blinktimeout) {
- drawtimeout.tv_usec = 1;
- } else {
- drawtimeout.tv_usec = (1000 * \
- (blinktimeout - \
- TIMEDIFF(now,
- lastblink)));
- }
- } else {
- tv = NULL;
- }
- }
- }
- }
-}
-
-void
-usage(void) {
- 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);
-}
-
-int
-main(int argc, char *argv[]) {
- char *titles;
- uint cols = 80, rows = 24;
-
- xw.l = xw.t = 0;
- xw.isfixed = False;
-
- ARGBEGIN {
- case 'a':
- allowaltscreen = false;
- break;
- case 'c':
- opt_class = EARGF(usage());
- break;
- case 'e':
- /* 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);
- }
- }
- goto run;
- case 'f':
- opt_font = EARGF(usage());
- break;
- case 'g':
- xw.gm = XParseGeometry(EARGF(usage()),
- &xw.l, &xw.t, &cols, &rows);
- break;
- case 'i':
- xw.isfixed = True;
- break;
- case 'o':
- opt_io = EARGF(usage());
- break;
- case 't':
- opt_title = EARGF(usage());
- break;
- case 'w':
- opt_embed = EARGF(usage());
- break;
- case 'v':
- default:
- usage();
- } ARGEND;
-
-run:
- setlocale(LC_CTYPE, "");
- XSetLocaleModifiers("");
- tnew(cols? cols : 1, rows? rows : 1);
- xinit();
- selinit();
- run();
-
- return 0;
-}
-