From: Jason Woofenden Date: Sat, 28 Mar 2015 22:19:07 +0000 (-0400) Subject: Merge remote-tracking branch 'upstream/master' X-Git-Url: https://jasonwoof.com/gitweb/?p=st.git;a=commitdiff_plain;h=8365f93099bcfa6a708f3608cd3eb43c150a166e;hp=-c Merge remote-tracking branch 'upstream/master' Conflicts: st.c st.info --- 8365f93099bcfa6a708f3608cd3eb43c150a166e diff --combined config.mk index eb7c0e7,3026d87..3efb1d9 --- a/config.mk +++ b/config.mk @@@ -4,7 -4,7 +4,7 @@@ VERSION = 0. # Customize below to fit your system # paths -PREFIX = /usr/local +PREFIX = /home/jasonwoof/software/virt MANPREFIX = ${PREFIX}/share/man X11INC = /usr/X11R6/include @@@ -19,10 -19,10 +19,10 @@@ LIBS = -L/usr/lib -lc -L${X11LIB} -lm - `pkg-config --libs freetype2` # flags - CPPFLAGS = -DVERSION=\"${VERSION}\" -D_BSD_SOURCE -D_XOPEN_SOURCE=600 + CPPFLAGS = -DVERSION=\"${VERSION}\" -D_XOPEN_SOURCE=600 CFLAGS += -g -std=c99 -pedantic -Wall -Wvariadic-macros -Os ${INCS} ${CPPFLAGS} LDFLAGS += -g ${LIBS} # compiler and linker - CC ?= cc + # CC = cc diff --combined st.c index 80910f3,39d3fee..ce8c5c9 --- a/st.c +++ b/st.c @@@ -63,8 -63,6 +63,6 @@@ char *argv0 #define XK_NO_MOD 0 #define XK_SWITCH_MOD (1<<13) - #define REDRAW_TIMEOUT (80*1000) /* 80 ms */ - /* macros */ #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) < (b) ? (b) : (a)) @@@ -199,14 -197,14 +197,14 @@@ typedef struct } TCursor; /* CSI Escape sequence structs */ - /* ESC '[' [[ [] [;]] ] */ + /* ESC '[' [[ [] [;]] []] */ 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 */ @@@ -259,6 -257,7 +257,7 @@@ typedef struct int ch; /* char height */ int cw; /* char width */ char state; /* focus, redraw, visible */ + int cursor; /* cursor style */ } XWindow; typedef struct { @@@ -292,7 -291,7 +291,7 @@@ typedef struct int x, y; } nb, ne, ob, oe; - char *clip; + char *primary, *clipboard; Atom xtarget; bool alt; struct timespec tclick1; @@@ -314,6 -313,7 +313,7 @@@ typedef struct } Shortcut; /* function definitions used in config.h */ + static void clipcopy(const Arg *); static void clippaste(const Arg *); static void numlock(const Arg *); static void selpaste(const Arg *); @@@ -349,7 -349,7 +349,7 @@@ typedef struct static void die(const char *, ...); static void draw(void); - static void redraw(int); + static void redraw(void); static void drawregion(int, int, int, int); static void execsh(void); static void sigchld(int); @@@ -481,7 -481,11 +481,11 @@@ static void (*handler[LASTEvent])(XEven [MotionNotify] = bmotion, [ButtonPress] = bpress, [ButtonRelease] = brelease, - [SelectionClear] = selclear, + /* + * Uncomment if you want the selection to disappear when you select something + * different in another window. + */ + /* [SelectionClear] = selclear, */ [SelectionNotify] = selnotify, [SelectionRequest] = selrequest, }; @@@ -524,6 -528,7 +528,7 @@@ enum typedef struct { XftFont *font; int flags; + long unicodep; } Fontcache; /* Fontcache is an array now. A new font will be appended to the array. */ @@@ -641,7 -646,8 +646,8 @@@ selinit(void) memset(&sel.tclick2, 0, sizeof(sel.tclick2)); sel.mode = 0; sel.ob.x = -1; - sel.clip = NULL; + sel.primary = NULL; + sel.clipboard = NULL; sel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); if(sel.xtarget == None) sel.xtarget = XA_STRING; @@@ -947,6 -953,8 +953,8 @@@ getsel(void) lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; } last = &term.line[y][MIN(lastx, linelen-1)]; + while(last >= gp && last->c[0] == ' ') + --last; for( ; gp <= last; ++gp) { if(gp->mode & ATTR_WDUMMY) @@@ -984,12 -992,17 +992,17 @@@ selnotify(XEvent *e) int format; uchar *data, *last, *repl; Atom type; + XSelectionEvent *xsev; ofs = 0; + xsev = (XSelectionEvent *)e; + if (xsev->property == None) + return; do { - if(XGetWindowProperty(xw.dpy, xw.win, XA_PRIMARY, ofs, BUFSIZ/4, - False, AnyPropertyType, &type, &format, - &nitems, &rem, &data)) { + if(XGetWindowProperty(xw.dpy, xw.win, xsev->property, ofs, + BUFSIZ/4, False, AnyPropertyType, + &type, &format, &nitems, &rem, + &data)) { fprintf(stderr, "Clipboard allocation failed\n"); return; } @@@ -1025,11 -1038,25 +1038,25 @@@ selpaste(const Arg *dummy) } 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, sel.xtarget, XA_PRIMARY, + XConvertSelection(xw.dpy, clipboard, sel.xtarget, clipboard, xw.win, CurrentTime); } @@@ -1045,7 -1072,8 +1072,8 @@@ voi selrequest(XEvent *e) { XSelectionRequestEvent *xsre; XSelectionEvent xev; - Atom xa_targets, string; + Atom xa_targets, string, clipboard; + char *seltext; xsre = (XSelectionRequestEvent *) e; xev.type = SelectionNotify; @@@ -1064,11 -1092,29 +1092,29 @@@ XA_ATOM, 32, PropModeReplace, (uchar *) &string, 1); xev.property = xsre->property; - } else if(xsre->target == sel.xtarget && sel.clip != NULL) { - XChangeProperty(xsre->display, xsre->requestor, xsre->property, - xsre->target, 8, PropModeReplace, - (uchar *) sel.clip, strlen(sel.clip)); - xev.property = xsre->property; + } else if(xsre->target == sel.xtarget || xsre->target == XA_STRING) { + /* + * xith XA_STRING non ascii characters may be incorrect in the + * requestor. It is not our problem, use utf8. + */ + clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); + if(xsre->selection == XA_PRIMARY) { + seltext = sel.primary; + } else if(xsre->selection == clipboard) { + seltext = sel.clipboard; + } else { + fprintf(stderr, + "Unhandled clipboard selection 0x%lx\n", + xsre->selection); + return; + } + if(seltext != NULL) { + XChangeProperty(xsre->display, xsre->requestor, + xsre->property, xsre->target, + 8, PropModeReplace, + (uchar *)seltext, strlen(seltext)); + xev.property = xsre->property; + } } /* all done, send a notification to the listener */ @@@ -1078,16 -1124,10 +1124,10 @@@ void xsetsel(char *str) { - /* register the selection for both the clipboard and the primary */ - Atom clipboard; - - free(sel.clip); - sel.clip = str; + free(sel.primary); + sel.primary = str; XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, CurrentTime); - - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); } void @@@ -1190,7 -1230,7 +1230,7 @@@ execsh(void) signal(SIGALRM, SIG_DFL); execvp(prog, args); - exit(EXIT_FAILURE); + _exit(EXIT_FAILURE); } void @@@ -1508,7 -1548,8 +1548,8 @@@ csiparse(void) 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 */ @@@ -1824,7 -1865,7 +1865,7 @@@ tsetmode(bool priv, bool set, int *args mode = term.mode; MODBIT(term.mode, set, MODE_REVERSE); if(mode != term.mode) - redraw(REDRAW_TIMEOUT); + redraw(); break; case 6: /* DECOM -- Origin */ MODBIT(term.c.state, set, CURSOR_ORIGIN); @@@ -1946,7 -1987,7 +1987,7 @@@ csihandle(void) char buf[40]; int len; - switch(csiescseq.mode) { + switch(csiescseq.mode[0]) { default: unknown: fprintf(stderr, "erresc: unknown csi "); @@@ -2134,6 -2175,19 +2175,19 @@@ 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; } } @@@ -2198,7 -2252,7 +2252,7 @@@ strhandle(void) * TODO if defaultbg color is changed, borders * are dirty */ - redraw(0); + redraw(); } return; } @@@ -2218,12 -2272,23 +2272,23 @@@ 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 @@@ -2671,13 -2736,16 +2736,16 @@@ tputc(char *c, int len) if(IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { gp->mode |= ATTR_WRAP; tnewline(1); + gp = &term.line[term.c.y][term.c.x]; } - if(IS_SET(MODE_INSERT) && term.c.x+1 < term.col) - memmove(gp+1, gp, (term.col - term.c.x - 1) * sizeof(Glyph)); + if(IS_SET(MODE_INSERT) && term.c.x+width < term.col) + memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); - if(term.c.x+width > term.col) + if(term.c.x+width > term.col) { tnewline(1); + gp = &term.line[term.c.y][term.c.x]; + } tsetchar(c, &term.c.attr, term.c.x, term.c.y); @@@ -2987,7 -3055,7 +3055,7 @@@ xloadfonts(char *fontstr, double fontsi if(!pattern) die("st: can't open font %s\n", fontstr); - if(fontsize > 0) { + if(fontsize > 1) { FcPatternDel(pattern, FC_PIXEL_SIZE); FcPatternDel(pattern, FC_SIZE); FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); @@@ -3088,7 -3156,7 +3156,7 @@@ xzoomabs(const Arg *arg) xunloadfonts(); xloadfonts(usedfont, arg->i); cresize(0, 0); - redraw(0); + redraw(); xhints(); } @@@ -3205,7 -3273,7 +3273,7 @@@ voi xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { int winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch, width = charlen * xw.cw, xp, i; - int frcflags; + int frcflags, charexists; int u8fl, u8fblen, u8cblen, doesexist; char *u8c, *u8fs; long unicodep; @@@ -3388,8 -3456,13 +3456,13 @@@ /* Search the font cache. */ for(i = 0; i < frclen; i++) { - if(XftCharExists(xw.dpy, frc[i].font, unicodep) - && frc[i].flags == frcflags) { + charexists = XftCharExists(xw.dpy, frc[i].font, unicodep); + /* Everything correct. */ + if(charexists && frc[i].flags == frcflags) + break; + /* We got a default font for a not found glyph. */ + if(!charexists && frc[i].flags == frcflags \ + && frc[i].unicodep == unicodep) { break; } } @@@ -3420,8 -3493,8 +3493,8 @@@ FcMatchPattern); FcDefaultSubstitute(fcpattern); - fontpattern = FcFontSetMatch(0, fcsets, - FcTrue, fcpattern, &fcres); + fontpattern = FcFontSetMatch(0, fcsets, 1, + fcpattern, &fcres); /* * Overwrite or create the new cache entry. @@@ -3429,11 -3502,13 +3502,13 @@@ if(frclen >= LEN(frc)) { frclen = LEN(frc) - 1; XftFontClose(xw.dpy, frc[frclen].font); + frc[frclen].unicodep = 0; } frc[frclen].font = XftFontOpenPattern(xw.dpy, fontpattern); frc[frclen].flags = frcflags; + frc[frclen].unicodep = unicodep; i = frclen; frclen++; @@@ -3504,17 -3579,35 +3579,35 @@@ xdrawcursor(void) /* draw the new one */ if(xw.state & WIN_FOCUSED) { - if(term.mode & MODE_BLINK) { - if(IS_SET(MODE_REVERSE)) { - g.mode |= ATTR_REVERSE; - } - g.fg = term.line[term.c.y][curx].bg; - g.bg = term.line[term.c.y][curx].fg; + 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 - 1, + xw.cw, 1); + 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, + 1, xw.ch); + break; } } else { XftDrawRect(xw.draw, &dc.col[defaultcs], @@@ -3555,16 -3648,9 +3648,9 @@@ xresettitle(void) } void - redraw(int timeout) { - struct timespec tv = {0, timeout * 1000}; - + redraw(void) { tfulldirt(); draw(); - - if(timeout > 0) { - nanosleep(&tv, NULL); - XSync(xw.dpy, False); /* necessary for a good tput flash */ - } } void @@@ -3631,7 -3717,7 +3717,7 @@@ expose(XEvent *ev) if(!e->count) xw.state &= ~WIN_REDRAW; } - redraw(0); + redraw(); } void @@@ -3868,16 -3954,15 +3954,16 @@@ run(void) } 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)) + if(FD_ISSET(xfd, &rfd)) { xev = actionfps; + if(blinktimeout) { + lastblink = now; + MODBIT(term.mode, 1, MODE_BLINK); + blinkset = 1; + } + } clock_gettime(CLOCK_MONOTONIC, &now); drawtimeout.tv_sec = 0; @@@ -3923,6 -4008,9 +4009,9 @@@ TIMEDIFF(now, lastblink))); } + drawtimeout.tv_sec = \ + drawtimeout.tv_nsec / 1E9; + drawtimeout.tv_nsec %= (long)1E9; } else { tv = NULL; } @@@ -3933,7 -4021,7 +4022,7 @@@ void usage(void) { - die("%s " VERSION " (c) 2010-2014 st engineers\n" \ + die("%s " VERSION " (c) 2010-2015 st engineers\n" \ "usage: st [-a] [-v] [-c class] [-f font] [-g geometry] [-o file]\n" " [-i] [-t title] [-w windowid] [-e command ...]\n", argv0); } @@@ -3945,6 -4033,7 +4034,7 @@@ main(int argc, char *argv[]) xw.l = xw.t = 0; xw.isfixed = False; + xw.cursor = 0; ARGBEGIN { case 'a':