X-Git-Url: https://jasonwoof.com/gitweb/?p=st.git;a=blobdiff_plain;f=st.c;h=45bc89d179e561ab7ecc317f08cdd8a33caad122;hp=78d8a01876e8ab81c9bf2845904874cc388e3c76;hb=ec3268961d1dc4072f6caa6f97db5436da2ff411;hpb=cf890e5bf06a65a35fe195aa1ef8ae3e1eb55f51 diff --git a/st.c b/st.c index 78d8a01..45bc89d 100644 --- a/st.c +++ b/st.c @@ -76,8 +76,7 @@ char *argv0; #define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) #define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || (a).bg != (b).bg) #define IS_SET(flag) ((term.mode & (flag)) != 0) -#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + (t1.tv_usec-t2.tv_usec)/1000) -#define CEIL(x) (((x) != (int) (x)) ? (x) + 1 : (x)) +#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + (t1.tv_nsec-t2.tv_nsec)/1E6) #define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) #define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) @@ -91,14 +90,17 @@ char *argv0; enum glyph_attribute { ATTR_NULL = 0, - ATTR_REVERSE = 1, - ATTR_UNDERLINE = 2, - ATTR_BOLD = 4, - ATTR_ITALIC = 8, + ATTR_BOLD = 1, + ATTR_FAINT = 2, + ATTR_ITALIC = 4, + ATTR_UNDERLINE = 8, ATTR_BLINK = 16, - ATTR_WRAP = 32, - ATTR_WIDE = 64, - ATTR_WDUMMY = 128, + ATTR_REVERSE = 32, + ATTR_INVISIBLE = 64, + ATTR_STRUCK = 128, + ATTR_WRAP = 256, + ATTR_WIDE = 512, + ATTR_WDUMMY = 1024, }; enum cursor_movement { @@ -179,8 +181,7 @@ typedef unsigned long ulong; typedef unsigned short ushort; typedef XftDraw *Draw; -typedef XftColor Colour; -typedef Colormap Colourmap; +typedef XftColor Color; typedef struct { char c[UTF_SIZ]; /* character code */ @@ -241,7 +242,7 @@ typedef struct { /* Purely graphic info */ typedef struct { Display *dpy; - Colourmap cmap; + Colormap cmap; Window win; Drawable buf; Atom xembed, wmdeletewin, netwmname, netwmpid; @@ -295,8 +296,8 @@ typedef struct { char *clip; Atom xtarget; bool alt; - struct timeval tclick1; - struct timeval tclick2; + struct timespec tclick1; + struct timespec tclick2; } Selection; typedef union { @@ -340,7 +341,7 @@ typedef struct { /* Drawing Context */ typedef struct { - Colour col[LEN(colorname) < 256 ? 256 : LEN(colorname)]; + Color col[MAX(LEN(colorname), 256)]; Font font, bfont, ifont, ibfont; GC gc; } DC; @@ -373,6 +374,7 @@ static void tdeletechar(int); static void tdeleteline(int); static void tinsertblank(int); static void tinsertblankline(int); +static int tlinelen(int); static void tmoveto(int, int); static void tmoveato(int, int); static void tnew(int, int); @@ -402,6 +404,7 @@ 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 xdraws(char *, Glyph, int, int, int, int); static void xhints(void); @@ -441,7 +444,7 @@ static void selclear(XEvent *); static void selrequest(XEvent *); static void selinit(void); -static void selsort(void); +static void selnormalize(void); static inline bool selected(int, int); static char *getsel(void); static void selcopy(void); @@ -657,9 +660,20 @@ y2row(int y) { return LIMIT(y, 0, term.row-1); } +static int tlinelen(int y) { + int i = term.col; + + while (i > 0 && term.line[y][i - 1].c[0] == ' ') + --i; + + return i; +} + static void -selsort(void) { - if(sel.ob.y == sel.oe.y) { +selnormalize(void) { + int i; + + if(sel.ob.y == sel.oe.y || sel.type == SEL_RECTANGULAR) { sel.nb.x = MIN(sel.ob.x, sel.oe.x); sel.ne.x = MAX(sel.ob.x, sel.oe.x); } else { @@ -668,6 +682,15 @@ selsort(void) { } sel.nb.y = MIN(sel.ob.y, sel.oe.y); sel.ne.y = MAX(sel.ob.y, sel.oe.y); + + /* expand selection over line breaks */ + if (sel.type == SEL_RECTANGULAR) + return; + i = tlinelen(sel.nb.y); + if (i < sel.nb.x) + sel.nb.x = i; + if (tlinelen(sel.ne.y) <= sel.ne.x) + sel.ne.x = term.col - 1; } static inline bool @@ -683,7 +706,8 @@ selected(int x, int y) { void selsnap(int mode, int *x, int *y, int direction) { - int i; + int newx, newy, xt, yt; + Glyph *gp; switch(mode) { case SNAP_WORD: @@ -692,36 +716,31 @@ selsnap(int mode, int *x, int *y, int direction) { * beginning of a line. */ for(;;) { - if(direction < 0 && *x <= 0) { - if(*y > 0 && term.line[*y - 1][term.col-1].mode - & ATTR_WRAP) { - *y -= 1; - *x = term.col-1; - } else { + newx = *x + direction; + newy = *y; + if(!BETWEEN(newx, 0, term.col - 1)) { + newy += direction; + newx = (newx + term.col) % term.col; + if (!BETWEEN(newy, 0, term.row - 1)) break; - } - } - if(direction > 0 && *x >= term.col-1) { - if(*y < term.row-1 && term.line[*y][*x].mode - & ATTR_WRAP) { - *y += 1; - *x = 0; - } else { + + if(direction > 0) + yt = *y, xt = *x; + else + yt = newy, xt = newx; + if(!(term.line[yt][xt].mode & ATTR_WRAP)) break; - } } - if(term.line[*y][*x+direction].mode & ATTR_WDUMMY) { - *x += direction; - continue; - } + if (newx >= tlinelen(newy)) + break; - if(strchr(worddelimiters, - term.line[*y][*x+direction].c[0])) { + gp = &term.line[newy][newx]; + if (!(gp->mode & ATTR_WDUMMY) && strchr(worddelimiters, gp->c[0])) break; - } - *x += direction; + *x = newx; + *y = newy; } break; case SNAP_LINE: @@ -747,18 +766,6 @@ selsnap(int mode, int *x, int *y, int direction) { } } break; - default: - /* - * Select the whole line when the end of line is reached. - */ - if(direction > 0) { - i = term.col; - while(--i > 0 && term.line[*y][i].c[0] == ' ') - /* nothing */; - if(i > 0 && i < *x) - *x = term.col - 1; - } - break; } } @@ -780,7 +787,7 @@ getbuttoninfo(XEvent *e) { selsnap(sel.snap, &sel.oe.x, &sel.oe.y, -1); selsnap(sel.snap, &sel.ob.x, &sel.ob.y, +1); } - selsort(); + selnormalize(); sel.type = SEL_REGULAR; for(type = 1; type < LEN(selmasks); ++type) { @@ -829,6 +836,8 @@ mousereport(XEvent *e) { /* MODE_MOUSEX10: no button release reporting */ if(IS_SET(MODE_MOUSEX10)) return; + if (button == 64 || button == 65) + return; } } @@ -855,7 +864,7 @@ mousereport(XEvent *e) { void bpress(XEvent *e) { - struct timeval now; + struct timespec now; Mousekey *mk; if(IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { @@ -872,7 +881,7 @@ bpress(XEvent *e) { } if(e->xbutton.button == Button1) { - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC, &now); /* Clear previous selection, logically and visually. */ selclear(NULL); @@ -894,7 +903,7 @@ bpress(XEvent *e) { } selsnap(sel.snap, &sel.ob.x, &sel.ob.y, -1); selsnap(sel.snap, &sel.oe.x, &sel.oe.y, +1); - selsort(); + selnormalize(); /* * Draw selection, unless it's regular and we don't want to @@ -912,7 +921,7 @@ bpress(XEvent *e) { char * getsel(void) { char *str, *ptr; - int x, y, bufsize, size, i, ex; + int y, bufsize, size, lastx, linelen; Glyph *gp, *last; if(sel.ob.x == -1) @@ -923,16 +932,19 @@ getsel(void) { /* append every set & selected glyph to the selection */ for(y = sel.nb.y; y < sel.ne.y + 1; y++) { - gp = &term.line[y][0]; - last = &gp[term.col-1]; + linelen = tlinelen(y); - while(last >= gp && !(selected(last - gp, y) && - strcmp(last->c, " ") != 0)) { - --last; + if(sel.type == SEL_RECTANGULAR) { + gp = &term.line[y][sel.nb.x]; + lastx = sel.ne.x; + } else { + gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0]; + lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; } + last = &term.line[y][MIN(lastx, linelen-1)]; - for(x = 0; gp <= last; x++, ++gp) { - if(!selected(x, y) || (gp->mode & ATTR_WDUMMY)) + for( ; gp <= last; ++gp) { + if(gp->mode & ATTR_WDUMMY) continue; size = utf8len(gp->c); @@ -949,23 +961,8 @@ getsel(void) { * st. * FIXME: Fix the computer world. */ - if(y < sel.ne.y && x > 0 && !((gp-1)->mode & ATTR_WRAP)) + if(sel.ne.y > y || lastx >= linelen) *ptr++ = '\n'; - - /* - * If the last selected line expands in the selection - * after the visible text '\n' is appended. - */ - if(y == sel.ne.y) { - i = term.col; - while(--i > 0 && term.line[y][i].c[0] == ' ') - /* nothing */; - ex = sel.ne.x; - if(sel.nb.y == sel.ne.y && sel.ne.x < sel.nb.x) - ex = sel.nb.x; - if(i < ex) - *ptr++ = '\n'; - } } *ptr = 0; return str; @@ -1179,16 +1176,15 @@ execsh(void) { void sigchld(int a) { - int stat = 0; + int stat, ret; if(waitpid(pid, &stat, 0) < 0) die("Waiting for pid %hd failed: %s\n", pid, strerror(errno)); - if(WIFEXITED(stat)) { - exit(WEXITSTATUS(stat)); - } else { - exit(EXIT_FAILURE); - } + ret = WIFEXITED(stat) ? WEXITSTATUS(stat) : EXIT_FAILURE; + if (ret != EXIT_SUCCESS) + die("child finished with error '%d'\n", stat); + exit(EXIT_SUCCESS); } void @@ -1449,7 +1445,7 @@ selscroll(int orig, int n) { sel.oe.x = term.col; } } - selsort(); + selnormalize(); } } @@ -1629,7 +1625,7 @@ tdefcolor(int *attr, int *npar, int l) { uint r, g, b; switch (attr[*npar + 1]) { - case 2: /* direct colour in RGB space */ + case 2: /* direct color in RGB space */ if (*npar + 4 >= l) { fprintf(stderr, "erresc(38): Incorrect number of parameters (%d)\n", @@ -1646,7 +1642,7 @@ tdefcolor(int *attr, int *npar, int l) { else idx = TRUECOLOR(r, g, b); break; - case 5: /* indexed colour */ + case 5: /* indexed color */ if (*npar + 2 >= l) { fprintf(stderr, "erresc(38): Incorrect number of parameters (%d)\n", @@ -1661,8 +1657,8 @@ tdefcolor(int *attr, int *npar, int l) { break; case 0: /* implemented defined (only foreground) */ case 1: /* transparent */ - case 3: /* direct colour in CMY space */ - case 4: /* direct colour in CMYK space */ + case 3: /* direct color in CMY space */ + case 4: /* direct color in CMYK space */ default: fprintf(stderr, "erresc(38): gfx attr %d unknown\n", attr[*npar]); @@ -1680,15 +1676,24 @@ tsetattr(int *attr, int l) { for(i = 0; i < l; i++) { switch(attr[i]) { case 0: - term.c.attr.mode &= ~(ATTR_REVERSE | ATTR_UNDERLINE \ - | ATTR_BOLD | ATTR_ITALIC \ - | ATTR_BLINK); + term.c.attr.mode &= ~( + ATTR_BOLD | + ATTR_FAINT | + ATTR_ITALIC | + ATTR_UNDERLINE | + ATTR_BLINK | + ATTR_REVERSE | + ATTR_INVISIBLE | + ATTR_STRUCK ); term.c.attr.fg = defaultfg; term.c.attr.bg = defaultbg; break; case 1: term.c.attr.mode |= ATTR_BOLD; break; + case 2: + term.c.attr.mode |= ATTR_FAINT; + break; case 3: term.c.attr.mode |= ATTR_ITALIC; break; @@ -1696,15 +1701,21 @@ tsetattr(int *attr, int l) { term.c.attr.mode |= ATTR_UNDERLINE; break; case 5: /* slow blink */ + /* FALLTHROUGH */ case 6: /* rapid blink */ term.c.attr.mode |= ATTR_BLINK; break; case 7: term.c.attr.mode |= ATTR_REVERSE; break; - case 21: + case 8: + term.c.attr.mode |= ATTR_INVISIBLE; + break; + case 9: + term.c.attr.mode |= ATTR_STRUCK; + break; case 22: - term.c.attr.mode &= ~ATTR_BOLD; + term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT); break; case 23: term.c.attr.mode &= ~ATTR_ITALIC; @@ -1713,12 +1724,17 @@ tsetattr(int *attr, int l) { term.c.attr.mode &= ~ATTR_UNDERLINE; break; case 25: - case 26: term.c.attr.mode &= ~ATTR_BLINK; break; case 27: term.c.attr.mode &= ~ATTR_REVERSE; break; + case 28: + term.c.attr.mode &= ~ATTR_INVISIBLE; + break; + case 29: + term.c.attr.mode &= ~ATTR_STRUCK; + break; case 38: if ((idx = tdefcolor(attr, &i, l)) >= 0) term.c.attr.fg = idx; @@ -2149,7 +2165,7 @@ strhandle(void) { /* FALLTHROUGH */ case 104: /* color reset, here p = NULL */ j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - if (!xsetcolorname(j, p)) { + if(xsetcolorname(j, p)) { fprintf(stderr, "erresc: invalid color %s\n", p); } else { /* @@ -2254,12 +2270,10 @@ tdumpline(int n) { Glyph *bp, *end; bp = &term.line[n][0]; - end = &bp[term.col-1]; - while(end > bp && !strcmp(" ", end->c)) - --end; - if(bp != end || strcmp(bp->c, " ")) { + end = &bp[MIN(tlinelen(n), term.col) - 1]; + if(bp != end || bp->c[0] != ' ') { for( ;bp <= end; ++bp) - tprinter(bp->c, strlen(bp->c)); + tprinter(bp->c, utf8len(bp->c)); } tprinter("\n", 1); } @@ -2313,19 +2327,39 @@ techo(char *buf, int len) { void tdeftran(char ascii) { - char c, (*bp)[2]; - static char tbl[][2] = { - {'0', CS_GRAPHIC0}, {'B', CS_USA}, - {0, 0} - }; - - for (bp = &tbl[0]; (c = (*bp)[0]) && c != ascii; ++bp) - /* nothing */; + static char cs[] = "0B"; + static int vcs[] = {CS_GRAPHIC0, CS_USA}; + char *p; - if (c == 0) + if((p = strchr(cs, ascii)) == NULL) { fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); - else - term.trantbl[term.icharset] = (*bp)[1]; + } else { + term.trantbl[term.icharset] = vcs[p - cs]; + } +} + +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; + } + } + strreset(); + strescseq.type = c; + term.esc |= ESC_STR; + return; } void @@ -2382,20 +2416,30 @@ tcontrolcode(uchar ascii) { case 0177: /* DEL (IGNORED) */ return; case 0x84: /* TODO: IND */ - case 0x85: /* TODO: NEL */ - case 0x88: /* TODO: HTS */ + break; + case 0x85: /* NEL -- Next line */ + tnewline(1); /* always go to first col */ + break; + case 0x88: /* HTS -- Horizontal tab stop */ + term.tabs[term.c.x] = 1; + break; case 0x8d: /* TODO: RI */ case 0x8e: /* TODO: SS2 */ case 0x8f: /* TODO: SS3 */ - case 0x90: /* TODO: DCS */ case 0x98: /* TODO: SOS */ - case 0x9a: /* TODO: DECID */ + break; + case 0x9a: /* DECID -- Identify Terminal */ + ttywrite(VT102ID, sizeof(VT102ID) - 1); + break; case 0x9b: /* TODO: CSI */ case 0x9c: /* TODO: ST */ - case 0x9d: /* TODO: OSC */ - case 0x9e: /* TODO: PM */ - case 0x9f: /* TODO: APC */ break; + case 0x90: /* DCS -- Device Control String */ + case 0x9f: /* APC -- Application Program Command */ + case 0x9e: /* PM -- Privacy Message */ + case 0x9d: /* OSC -- Operating System Command */ + tstrsequence(ascii); + return; } /* only CAN, SUB, \a and C1 chars interrupt a sequence */ term.esc &= ~(ESC_STR_END|ESC_STR); @@ -2511,9 +2555,7 @@ tputc(char *c, int len) { case '^': /* PM -- Privacy Message */ case ']': /* OSC -- Operating System Command */ case 'k': /* old title set compatibility */ - strreset(); - strescseq.type = ascii; - term.esc |= ESC_STR; + tstrsequence(ascii); return; case '(': /* set primary charset G0 */ case ')': /* set secondary charset G1 */ @@ -2715,17 +2757,17 @@ sixd_to_16bit(int x) { void xloadcols(void) { - int i, r, g, b; + int i; XRenderColor color = { .alpha = 0xffff }; static bool loaded; - Colour *cp; + Color *cp; if(loaded) { for (cp = dc.col; cp < dc.col + LEN(dc.col); ++cp) XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); } - /* load colors [0-15] colors and [256-LEN(colorname)[ (config.h) */ + /* load colors [0-15] and [256-LEN(colorname)] (config.h) */ for(i = 0; i < LEN(colorname); i++) { if(!colorname[i]) continue; @@ -2734,27 +2776,20 @@ xloadcols(void) { } } - /* load colors [16-255] ; same colors as xterm */ - for(i = 16, r = 0; r < 6; r++) { - for(g = 0; g < 6; g++) { - for(b = 0; b < 6; b++) { - color.red = sixd_to_16bit(r); - color.green = sixd_to_16bit(g); - color.blue = sixd_to_16bit(b); - if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, &dc.col[i])) { - die("Could not allocate color %d\n", i); - } - i++; - } - } + /* load colors [16-231] ; same colors as xterm */ + for(i = 16; i < 6*6*6+16; i++) { + color.red = sixd_to_16bit( ((i-16)/36)%6 ); + color.green = sixd_to_16bit( ((i-16)/6) %6 ); + color.blue = sixd_to_16bit( ((i-16)/1) %6 ); + if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, &dc.col[i])) + die("Could not allocate color %d\n", i); } - for(r = 0; r < 24; r++, i++) { - color.red = color.green = color.blue = 0x0808 + 0x0a0a * r; - if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, - &dc.col[i])) { + /* load colors [232-255] ; grayscale */ + for(; i < 256; i++) { + color.red = color.green = color.blue = 0x0808 + 0x0a0a * (i-(6*6*6+16)); + if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, &dc.col[i])) die("Could not allocate color %d\n", i); - } } loaded = true; } @@ -2762,33 +2797,45 @@ xloadcols(void) { int xsetcolorname(int x, const char *name) { XRenderColor color = { .alpha = 0xffff }; - Colour colour; + Color ncolor; + if(!BETWEEN(x, 0, LEN(colorname))) - return -1; + return 1; + if(!name) { - if(BETWEEN(x, 16, 16 + 215)) { - int r = (x - 16) / 36, g = ((x - 16) % 36) / 6, b = (x - 16) % 6; - color.red = sixd_to_16bit(r); - color.green = sixd_to_16bit(g); - color.blue = sixd_to_16bit(b); - if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, &colour)) - return 0; /* something went wrong */ - dc.col[x] = colour; - return 1; - } else if(BETWEEN(x, 16 + 216, 255)) { - color.red = color.green = color.blue = 0x0808 + 0x0a0a * (x - (16 + 216)); - if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &color, &colour)) - return 0; /* something went wrong */ - dc.col[x] = colour; - return 1; - } else { + if(BETWEEN(x, 16, 16 + 215)) { /* 256 color */ + color.red = sixd_to_16bit( ((x-16)/36)%6 ); + color.green = sixd_to_16bit( ((x-16)/6) %6 ); + color.blue = sixd_to_16bit( ((x-16)/1) %6 ); + if(!XftColorAllocValue(xw.dpy, xw.vis, + xw.cmap, &color, &ncolor)) { + return 1; + } + + XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); + dc.col[x] = ncolor; + return 0; + } else if(BETWEEN(x, 16 + 216, 255)) { /* greyscale */ + color.red = color.green = color.blue = \ + 0x0808 + 0x0a0a * (x - (16 + 216)); + if(!XftColorAllocValue(xw.dpy, xw.vis, + xw.cmap, &color, &ncolor)) { + return 1; + } + + XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); + dc.col[x] = ncolor; + return 0; + } else { /* system colors */ name = colorname[x]; } } - if(!XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, &colour)) - return 0; - dc.col[x] = colour; - return 1; + if(!XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, &ncolor)) + return 1; + + XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); + dc.col[x] = ncolor; + return 0; } void @@ -2889,6 +2936,7 @@ xloadfonts(char *fontstr, double fontsize) { FcPattern *pattern; FcResult r_sz, r_psz; double fontval; + float ceilf(float); if(fontstr[0] == '-') { pattern = XftXlfdParse(fontstr, False, False); @@ -2934,8 +2982,8 @@ xloadfonts(char *fontstr, double fontsize) { } /* Setting character width and height. */ - xw.cw = CEIL(dc.font.width * cwscale); - xw.ch = CEIL(dc.font.height * chscale); + xw.cw = ceilf(dc.font.width * cwscale); + xw.ch = ceilf(dc.font.height * chscale); FcPatternDel(pattern, FC_SLANT); FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); @@ -2990,6 +3038,7 @@ xzoom(const Arg *arg) { xloadfonts(usedfont, usedfontsize + arg->i); cresize(0, 0); redraw(0); + xhints(); } void @@ -3104,7 +3153,7 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { FcPattern *fcpattern, *fontpattern; FcFontSet *fcsets[] = { NULL }; FcCharSet *fccharset; - Colour *fg, *bg, *temp, revfg, revbg, truefg, truebg; + Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; XRenderColor colfg, colbg; XRectangle r; int oneatatime; @@ -3149,24 +3198,20 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { } if(base.mode & ATTR_BOLD) { - if(BETWEEN(base.fg, 0, 7)) { - /* basic system colors */ - fg = &dc.col[base.fg + 8]; - } else if(BETWEEN(base.fg, 16, 195)) { - /* 256 colors */ - fg = &dc.col[base.fg + 36]; - } else if(BETWEEN(base.fg, 232, 251)) { - /* greyscale */ - fg = &dc.col[base.fg + 4]; - } /* - * Those ranges will not be brightened: - * 8 - 15 – bright system colors - * 196 - 231 – highest 256 color cube - * 252 - 255 – brightest colors in greyscale + * change basic system colors [0-7] + * to bright system colors [8-15] */ - font = &dc.bfont; - frcflags = FRC_BOLD; + if(BETWEEN(base.fg, 0, 7) && !(base.mode & ATTR_FAINT)) + fg = &dc.col[base.fg + 8]; + + if(base.mode & ATTR_ITALIC) { + font = &dc.ibfont; + frcflags = FRC_ITALICBOLD; + } else { + font = &dc.bfont; + frcflags = FRC_BOLD; + } } if(IS_SET(MODE_REVERSE)) { @@ -3201,9 +3246,20 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { bg = temp; } + if(base.mode & ATTR_FAINT && !(base.mode & ATTR_BOLD)) { + colfg.red = fg->color.red / 2; + colfg.green = fg->color.green / 2; + colfg.blue = fg->color.blue / 2; + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); + fg = &revfg; + } + if(base.mode & ATTR_BLINK && term.mode & MODE_BLINK) fg = bg; + if(base.mode & ATTR_INVISIBLE) + fg = bg; + /* Intelligent cleaning up of the borders. */ if(x == 0) { xclear(0, (y == 0)? 0 : winy, borderpx, @@ -3246,28 +3302,22 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { bytelen -= u8cblen; doesexist = XftCharExists(xw.dpy, font->match, unicodep); - if(oneatatime || !doesexist || bytelen <= 0) { - if(oneatatime || bytelen <= 0) { - if(doesexist) { - u8fl++; - u8fblen += u8cblen; - } - } - - if(u8fl > 0) { - XftDrawStringUtf8(xw.draw, fg, - font->match, xp, - winy + font->ascent, - (FcChar8 *)u8fs, - u8fblen); - xp += xw.cw * u8fl; - - } - break; + if(doesexist) { + u8fl++; + u8fblen += u8cblen; + if(!oneatatime && bytelen > 0) + continue; } - u8fl++; - u8fblen += u8cblen; + if(u8fl > 0) { + XftDrawStringUtf8(xw.draw, fg, + font->match, xp, + winy + font->ascent, + (FcChar8 *)u8fs, + u8fblen); + xp += xw.cw * u8fl; + } + break; } if(doesexist) { if(oneatatime) @@ -3354,6 +3404,11 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { width, 1); } + if(base.mode & ATTR_STRUCK) { + XftDrawRect(xw.draw, fg, winx, winy + 2 * font->ascent / 3, + width, 1); + } + /* Reset clip to none. */ XftDrawSetClip(xw.draw, 0); } @@ -3715,11 +3770,14 @@ run(void) { 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; + struct timespec drawtimeout, *tv = NULL, now, last, lastblink; + long deltatime; /* Waiting for window mapping */ while(1) { XNextEvent(xw.dpy, &ev); + if(XFilterEvent(&ev, None)) + continue; if(ev.type == ConfigureNotify) { w = ev.xconfigure.width; h = ev.xconfigure.height; @@ -3731,17 +3789,15 @@ run(void) { ttynew(); cresize(w, h); - gettimeofday(&last, NULL); + clock_gettime(CLOCK_MONOTONIC, &last); 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(pselect(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) { if(errno == EINTR) continue; die("select failed: %s\n", strerror(errno)); @@ -3758,9 +3814,9 @@ run(void) { if(FD_ISSET(xfd, &rfd)) xev = actionfps; - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC, &now); drawtimeout.tv_sec = 0; - drawtimeout.tv_usec = (1000/xfps) * 1000; + drawtimeout.tv_nsec = (1000/xfps) * 1E6; tv = &drawtimeout; dodraw = 0; @@ -3795,9 +3851,9 @@ run(void) { if(blinkset) { if(TIMEDIFF(now, lastblink) \ > blinktimeout) { - drawtimeout.tv_usec = 1; + drawtimeout.tv_nsec = 1000; } else { - drawtimeout.tv_usec = (1000 * \ + drawtimeout.tv_nsec = (1E6 * \ (blinktimeout - \ TIMEDIFF(now, lastblink)));