X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=st.c;h=4f5cf9ed78cc93be6e1be821ed5ae2604c4dc7f6;hb=e6dd0f825da9bf68c7642f45afd069500879f5e2;hp=2b4d52cf09bdaf81c5c3803daf579f879387122a;hpb=dc8c5c82aa14e75305bd5b0e42b4f8bba45702a8;p=st.git diff --git a/st.c b/st.c index 2b4d52c..4f5cf9e 100644 --- a/st.c +++ b/st.c @@ -1,4 +1,4 @@ -/* See LICENSE for licence details. */ +/* See LICENSE for license details. */ #include #include #include @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -62,8 +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)) @@ -198,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 */ @@ -258,6 +257,7 @@ typedef struct { int ch; /* char height */ int cw; /* char width */ char state; /* focus, redraw, visible */ + int cursor; /* cursor style */ } XWindow; typedef struct { @@ -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; @@ -313,6 +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 *); @@ -348,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); @@ -358,7 +359,7 @@ static void csidump(void); static void csihandle(void); static void csiparse(void); static void csireset(void); -static int eschandle(uchar ascii); +static int eschandle(uchar); static void strdump(void); static void strhandle(void); static void strparse(void); @@ -405,8 +406,9 @@ static void ttyread(void); static void ttyresize(void); static void ttysend(char *, size_t); static void ttywrite(const char *, size_t); -static void tstrsequence(uchar c); +static void tstrsequence(uchar); +static inline ushort sixd_to_16bit(int); static void xdraws(char *, Glyph, int, int, int, int); static void xhints(void); static void xclear(int, int, int, int); @@ -417,7 +419,6 @@ static int xsetcolorname(int, const char *); static int xgeommasktogravity(int); static int xloadfont(Font *, FcPattern *); static void xloadfonts(char *, double); -static int xloadfontset(Font *); static void xsettitle(char *); static void xresettitle(void); static void xsetpointermotion(int); @@ -451,6 +452,8 @@ static char *getsel(void); static void selcopy(void); static void selscroll(int, int); static void selsnap(int, int *, int *, int); +static int x2col(int); +static int y2row(int); static void getbuttoninfo(XEvent *); static void mousereport(XEvent *); @@ -480,7 +483,11 @@ static void (*handler[LASTEvent])(XEvent *) = { [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, }; @@ -523,6 +530,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. */ @@ -634,19 +642,20 @@ utf8validate(long *u, size_t i) { return i; } -static void +void selinit(void) { memset(&sel.tclick1, 0, sizeof(sel.tclick1)); 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; } -static int +int x2col(int x) { x -= borderpx; x /= xw.cw; @@ -654,7 +663,7 @@ x2col(int x) { return LIMIT(x, 0, term.col-1); } -static int +int y2row(int y) { y -= borderpx; y /= xw.ch; @@ -662,7 +671,7 @@ y2row(int y) { return LIMIT(y, 0, term.row-1); } -static int tlinelen(int y) { +int tlinelen(int y) { int i = term.col; if(term.line[y][i - 1].mode & ATTR_WRAP) @@ -674,7 +683,7 @@ static int tlinelen(int y) { return i; } -static void +void selnormalize(void) { int i; @@ -701,7 +710,7 @@ selnormalize(void) { sel.ne.x = term.col - 1; } -static inline bool +bool selected(int x, int y) { if(sel.type == SEL_RECTANGULAR) return BETWEEN(y, sel.nb.y, sel.ne.y) @@ -935,7 +944,7 @@ getsel(void) { ptr = str = xmalloc(bufsize); /* append every set & selected glyph to the selection */ - for(y = sel.nb.y; y < sel.ne.y + 1; y++) { + for(y = sel.nb.y; y <= sel.ne.y; y++) { linelen = tlinelen(y); if(sel.type == SEL_RECTANGULAR) { @@ -946,6 +955,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) @@ -983,12 +994,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; } @@ -1023,12 +1039,26 @@ selpaste(const Arg *dummy) { xw.win, CurrentTime); } +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); } @@ -1044,7 +1074,8 @@ void selrequest(XEvent *e) { XSelectionRequestEvent *xsre; XSelectionEvent xev; - Atom xa_targets, string; + Atom xa_targets, string, clipboard; + char *seltext; xsre = (XSelectionRequestEvent *) e; xev.type = SelectionNotify; @@ -1063,11 +1094,29 @@ selrequest(XEvent *e) { 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 */ @@ -1077,16 +1126,10 @@ selrequest(XEvent *e) { 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 @@ -1145,7 +1188,7 @@ die(const char *errstr, ...) { void execsh(void) { - char **args, *sh; + char **args, *sh, *prog; const struct passwd *pw; char buf[sizeof(long) * 8 + 1]; @@ -1157,13 +1200,18 @@ execsh(void) { die("who are you?\n"); } - if (utmp) - sh = utmp; - else if (pw->pw_shell[0]) - sh = pw->pw_shell; + if (!(sh = getenv("SHELL"))) { + sh = (pw->pw_shell[0]) ? pw->pw_shell : shell; + } + + if(opt_cmd) + prog = opt_cmd[0]; + else if(utmp) + prog = utmp; else - sh = shell; - args = (opt_cmd) ? opt_cmd : (char *[]){sh, NULL}; + prog = sh; + args = (opt_cmd) ? opt_cmd : (char *[]) {prog, NULL}; + snprintf(buf, sizeof(buf), "%lu", xw.win); unsetenv("COLUMNS"); @@ -1171,7 +1219,7 @@ execsh(void) { unsetenv("TERMCAP"); setenv("LOGNAME", pw->pw_name, 1); setenv("USER", pw->pw_name, 1); - setenv("SHELL", args[0], 1); + setenv("SHELL", sh, 1); setenv("HOME", pw->pw_dir, 1); setenv("TERM", termname, 1); setenv("WINDOWID", buf, 1); @@ -1183,8 +1231,8 @@ execsh(void) { signal(SIGTERM, SIG_DFL); signal(SIGALRM, SIG_DFL); - execvp(args[0], args); - exit(EXIT_FAILURE); + execvp(prog, args); + _exit(EXIT_FAILURE); } void @@ -1502,7 +1550,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 */ @@ -1522,11 +1571,9 @@ tmoveto(int x, int y) { miny = 0; maxy = term.row - 1; } - LIMIT(x, 0, term.col-1); - LIMIT(y, miny, maxy); term.c.state &= ~CURSOR_WRAPNEXT; - term.c.x = x; - term.c.y = y; + term.c.x = LIMIT(x, 0, term.col-1); + term.c.y = LIMIT(y, miny, maxy); } void @@ -1818,7 +1865,7 @@ tsetmode(bool priv, bool set, int *args, int narg) { 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); @@ -1940,7 +1987,7 @@ csihandle(void) { char buf[40]; int len; - switch(csiescseq.mode) { + switch(csiescseq.mode[0]) { default: unknown: fprintf(stderr, "erresc: unknown csi "); @@ -2128,6 +2175,19 @@ csihandle(void) { 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; } } @@ -2192,7 +2252,7 @@ strhandle(void) { * TODO if defaultbg color is changed, borders * are dirty */ - redraw(0); + redraw(); } return; } @@ -2212,12 +2272,23 @@ strhandle(void) { 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 @@ -2373,21 +2444,19 @@ tdectest(char c) { void tstrsequence(uchar c) { - if (c & 0x80) { - switch (c) { - case 0x90: /* DCS -- Device Control String */ - c = 'P'; - break; - case 0x9f: /* APC -- Application Program Command */ - c = '_'; - break; - case 0x9e: /* PM -- Privacy Message */ - c = '^'; - break; - case 0x9d: /* OSC -- Operating System Command */ - c = ']'; - break; - } + switch (c) { + case 0x90: /* DCS -- Device Control String */ + c = 'P'; + break; + case 0x9f: /* APC -- Application Program Command */ + c = '_'; + break; + case 0x9e: /* PM -- Privacy Message */ + c = '^'; + break; + case 0x9d: /* OSC -- Operating System Command */ + c = ']'; + break; } strreset(); strescseq.type = c; @@ -2423,7 +2492,7 @@ tcontrolcode(uchar ascii) { if(!(xw.state & WIN_FOCUSED)) xseturgency(1); if (bellvolume) - XBell(xw.dpy, bellvolume); + XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); } break; case '\033': /* ESC */ @@ -2431,11 +2500,9 @@ tcontrolcode(uchar ascii) { term.esc &= ~(ESC_CSI|ESC_ALTCHARSET|ESC_TEST); term.esc |= ESC_START; return; - case '\016': /* SO */ - term.charset = 0; - return; - case '\017': /* SI */ - term.charset = 1; + case '\016': /* SO (LS1 -- Locking shift 1) */ + case '\017': /* SI (LS0 -- Locking shift 0) */ + term.charset = 1 - (ascii - '\016'); return; case '\032': /* SUB */ tsetchar(question, &term.c.attr, term.c.x, term.c.y); @@ -2499,6 +2566,10 @@ eschandle(uchar ascii) { case 'k': /* old title set compatibility */ tstrsequence(ascii); return 0; + case 'n': /* LS2 -- Locking shift 2 */ + case 'o': /* LS3 -- Locking shift 3 */ + term.charset = 2 + (ascii - 'n'); + break; case '(': /* GZD4 -- set primary charset G0 */ case ')': /* G1D4 -- set secondary charset G1 */ case '*': /* G2D4 -- set tertiary charset G2 */ @@ -2571,8 +2642,10 @@ tputc(char *c, int len) { unicodep = ascii = *c; } else { utf8decode(c, &unicodep, UTF_SIZ); - width = wcwidth(unicodep); - control = ISCONTROLC1(unicodep); + if ((width = wcwidth(unicodep)) == -1) { + c = "\357\277\275"; /* UTF_INVALID */ + width = 1; + } ascii = unicodep; } @@ -2587,7 +2660,7 @@ tputc(char *c, int len) { * character. */ if(term.esc & ESC_STR) { - if(width == 1 && + if(len == 1 && (ascii == '\a' || ascii == 030 || ascii == 032 || ascii == 033 || ISCONTROLC1(unicodep))) { @@ -2660,13 +2733,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); @@ -2689,7 +2765,6 @@ tresize(int col, int row) { int i; int minrow = MIN(row, term.row); int mincol = MIN(col, term.col); - int slide = term.c.y - row + 1; bool *bp; TCursor c; @@ -2699,20 +2774,18 @@ tresize(int col, int row) { return; } - /* free unneeded rows */ - i = 0; - if(slide > 0) { - /* - * slide screen to keep cursor where we expect it - - * tscrollup would work here, but we can optimize to - * memmove because we're freeing the earlier lines - */ - for(/* i = 0 */; i < slide; i++) { - free(term.line[i]); - free(term.alt[i]); - } - memmove(term.line, term.line + slide, row * sizeof(Line)); - memmove(term.alt, term.alt + slide, row * sizeof(Line)); + /* + * slide screen to keep cursor where we expect it - + * tscrollup would work here, but we can optimize to + * memmove because we're freeing the earlier lines + */ + for(i = 0; i <= term.c.y - row; i++) { + free(term.line[i]); + free(term.alt[i]); + } + if(i > 0) { + memmove(term.line, term.line + i, row * sizeof(Line)); + memmove(term.alt, term.alt + i, row * sizeof(Line)); } for(i += row; i < term.row; i++) { free(term.line[i]); @@ -2779,7 +2852,7 @@ xresize(int col, int row) { xclear(0, 0, xw.w, xw.h); } -static inline ushort +ushort sixd_to_16bit(int x) { return x == 0 ? 0 : 0x3737 + 0x2828 * x; } @@ -2976,7 +3049,7 @@ xloadfonts(char *fontstr, double fontsize) { 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); @@ -3035,15 +3108,6 @@ xloadfonts(char *fontstr, double fontsize) { FcPatternDestroy(pattern); } -int -xloadfontset(Font *f) { - FcResult result; - - if(!(f->set = FcFontSort(0, f->pattern, FcTrue, 0, &result))) - return 1; - return 0; -} - void xunloadfont(Font *f) { XftFontClose(xw.dpy, f->match); @@ -3064,10 +3128,10 @@ xunloadfonts(void) { xunloadfont(&dc.ibfont); } - void xzoom(const Arg *arg) { Arg larg; + larg.i = usedfontsize + arg->i; xzoomabs(&larg); } @@ -3077,13 +3141,14 @@ xzoomabs(const Arg *arg) { xunloadfonts(); xloadfonts(usedfont, arg->i); cresize(0, 0); - redraw(0); + redraw(); xhints(); } void xzoomreset(const Arg *arg) { Arg larg; + if(defaultfontsize > 0) { larg.i = defaultfontsize; xzoomabs(&larg); @@ -3130,8 +3195,8 @@ xinit(void) { | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; xw.attrs.colormap = xw.cmap; - parent = opt_embed ? strtol(opt_embed, NULL, 0) : \ - XRootWindow(xw.dpy, xw.scr); + if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) + parent = XRootWindow(xw.dpy, xw.scr); xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, xw.w, xw.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity @@ -3193,7 +3258,7 @@ void 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; @@ -3376,8 +3441,13 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { /* 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; } } @@ -3385,7 +3455,8 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { /* Nothing was found. */ if(i >= frclen) { if(!font->set) - xloadfontset(font); + font->set = FcFontSort(0, font->pattern, + FcTrue, 0, &fcres); fcsets[0] = font->set; /* @@ -3408,8 +3479,8 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { FcMatchPattern); FcDefaultSubstitute(fcpattern); - fontpattern = FcFontSetMatch(0, fcsets, - FcTrue, fcpattern, &fcres); + fontpattern = FcFontSetMatch(0, fcsets, 1, + fcpattern, &fcres); /* * Overwrite or create the new cache entry. @@ -3417,11 +3488,13 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { 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++; @@ -3492,16 +3565,36 @@ xdrawcursor(void) { /* draw the new one */ if(xw.state & WIN_FOCUSED) { - if(IS_SET(MODE_REVERSE)) { - g.mode |= ATTR_REVERSE; - g.fg = defaultcs; - g.bg = defaultfg; - } + 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 - cursorthickness, + xw.cw, cursorthickness); + 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, + cursorthickness, xw.ch); + break; + } } else { XftDrawRect(xw.draw, &dc.col[defaultcs], borderpx + curx * xw.cw, @@ -3541,16 +3634,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 @@ -3617,7 +3703,7 @@ expose(XEvent *ev) { if(!e->count) xw.state &= ~WIN_REDRAW; } - redraw(0); + redraw(); } void @@ -3673,7 +3759,7 @@ focus(XEvent *ev) { } } -static inline bool +bool match(uint mask, uint state) { return mask == XK_ANY_MOD || mask == (state & ~ignoremod); } @@ -3824,17 +3910,13 @@ run(void) { long deltatime; /* Waiting for window mapping */ - while(1) { + do { XNextEvent(xw.dpy, &ev); - if(XFilterEvent(&ev, None)) - continue; if(ev.type == ConfigureNotify) { w = ev.xconfigure.width; h = ev.xconfigure.height; - } else if(ev.type == MapNotify) { - break; } - } + } while(ev.type != MapNotify); ttynew(); cresize(w, h); @@ -3908,6 +3990,9 @@ run(void) { TIMEDIFF(now, lastblink))); } + drawtimeout.tv_sec = \ + drawtimeout.tv_nsec / 1E9; + drawtimeout.tv_nsec %= (long)1E9; } else { tv = NULL; } @@ -3918,7 +4003,7 @@ run(void) { 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); } @@ -3930,6 +4015,7 @@ main(int argc, char *argv[]) { xw.l = xw.t = 0; xw.isfixed = False; + xw.cursor = 0; ARGBEGIN { case 'a': @@ -3975,7 +4061,7 @@ main(int argc, char *argv[]) { run: setlocale(LC_CTYPE, ""); XSetLocaleModifiers(""); - tnew(cols? cols : 1, rows? rows : 1); + tnew(MAX(cols, 1), MAX(rows, 1)); xinit(); selinit(); run();