X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=st.c;h=9733a9be4368b0c66c46047dea4574c358df9eee;hb=587bc939f63b49c6155c4f1fdf97e73380207446;hp=289ecb84c5032f746ea0c7f69be74568feb4be0b;hpb=40e4d76d227d9c517054036f546acd49431bca42;p=st.git diff --git a/st.c b/st.c index 289ecb8..9733a9b 100644 --- a/st.c +++ b/st.c @@ -76,6 +76,14 @@ char *argv0; #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 TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) +#define IS_TRUECOL(x) (1 << 24 & (x)) +#define TRUERED(x) (((x) & 0xff0000) >> 8) +#define TRUEGREEN(x) (((x) & 0xff00)) +#define TRUEBLUE(x) (((x) & 0xff) << 8) + #define VT102ID "\033[?6c" @@ -158,8 +166,8 @@ typedef unsigned short ushort; typedef struct { char c[UTF_SIZ]; /* character code */ uchar mode; /* attribute flags */ - ushort fg; /* foreground */ - ushort bg; /* background */ + ulong fg; /* foreground */ + ulong bg; /* background */ } Glyph; typedef Glyph *Line; @@ -354,7 +362,7 @@ static void tsetdirtattr(int); static void tsetmode(bool, bool, int *, int); static void tfulldirt(void); static void techo(char *, int); - +static long tdefcolor(int *, int *, int); static inline bool match(uint, uint); static void ttynew(void); static void ttyread(void); @@ -462,17 +470,12 @@ enum { typedef struct { XftFont *font; - long c; int flags; } Fontcache; -/* - * Fontcache is a ring buffer, with frccur as current position and frclen as - * the current length of used elements. - */ - -static Fontcache frc[1024]; -static int frccur = -1, frclen = 0; +/* Fontcache is an array now. A new font will be appended to the array. */ +static Fontcache frc[16]; +static int frclen = 0; ssize_t xwrite(int fd, char *s, size_t len) { @@ -1623,9 +1626,58 @@ tdeleteline(int n) { tscrollup(term.c.y, n); } +long +tdefcolor(int *attr, int *npar, int l) { + long idx = -1; + uint r, g, b; + + switch (attr[*npar + 1]) { + case 2: /* direct colour in RGB space */ + if (*npar + 4 >= l) { + fprintf(stderr, + "erresc(38): Incorrect number of parameters (%d)\n", + *npar); + break; + } + r = attr[*npar + 2]; + g = attr[*npar + 3]; + b = attr[*npar + 4]; + *npar += 4; + if(!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255)) + fprintf(stderr, "erresc: bad rgb color (%d,%d,%d)\n", + r, g, b); + else + idx = TRUECOLOR(r, g, b); + break; + case 5: /* indexed colour */ + if (*npar + 2 >= l) { + fprintf(stderr, + "erresc(38): Incorrect number of parameters (%d)\n", + *npar); + break; + } + *npar += 2; + if(!BETWEEN(attr[*npar], 0, 255)) + fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]); + else + idx = attr[*npar]; + break; + case 0: /* implemented defined (only foreground) */ + case 1: /* transparent */ + case 3: /* direct colour in CMY space */ + case 4: /* direct colour in CMYK space */ + default: + fprintf(stderr, + "erresc(38): gfx attr %d unknown\n", attr[*npar]); + } + + return idx; +} + void tsetattr(int *attr, int l) { int i; + long idx; for(i = 0; i < l; i++) { switch(attr[i]) { @@ -1670,39 +1722,15 @@ tsetattr(int *attr, int l) { term.c.attr.mode &= ~ATTR_REVERSE; break; case 38: - if(i + 2 < l && attr[i + 1] == 5) { - i += 2; - if(BETWEEN(attr[i], 0, 255)) { - term.c.attr.fg = attr[i]; - } else { - fprintf(stderr, - "erresc: bad fgcolor %d\n", - attr[i]); - } - } else { - fprintf(stderr, - "erresc(38): gfx attr %d unknown\n", - attr[i]); - } + if ((idx = tdefcolor(attr, &i, l)) >= 0) + term.c.attr.fg = idx; break; case 39: term.c.attr.fg = defaultfg; break; case 48: - if(i + 2 < l && attr[i + 1] == 5) { - i += 2; - if(BETWEEN(attr[i], 0, 255)) { - term.c.attr.bg = attr[i]; - } else { - fprintf(stderr, - "erresc: bad bgcolor %d\n", - attr[i]); - } - } else { - fprintf(stderr, - "erresc(48): gfx attr %d unknown\n", - attr[i]); - } + if ((idx = tdefcolor(attr, &i, l)) >= 0) + term.c.attr.bg = idx; break; case 49: term.c.attr.bg = defaultbg; @@ -2401,6 +2429,7 @@ tputc(char *c, int len) { treset(); term.esc = 0; xresettitle(); + xloadcols(); break; case '=': /* DECPAM -- Application keypad */ term.mode |= MODE_APPKEYPAD; @@ -2562,6 +2591,13 @@ void xloadcols(void) { int i, r, g, b; XRenderColor color = { .alpha = 0xffff }; + static bool loaded; + Colour *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) */ for(i = 0; i < LEN(colorname); i++) { @@ -2594,6 +2630,7 @@ xloadcols(void) { die("Could not allocate color %d\n", i); } } + loaded = true; } int @@ -2741,8 +2778,8 @@ xloadfonts(char *fontstr, int fontsize) { die("st: can't open font %s\n", fontstr); /* Setting character width and height. */ - xw.cw = dc.font.width; - xw.ch = dc.font.height; + xw.cw = CEIL(dc.font.width * cwscale); + xw.ch = CEIL(dc.font.height * chscale); FcPatternDel(pattern, FC_SLANT); FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); @@ -2781,18 +2818,12 @@ xunloadfont(Font *f) { void xunloadfonts(void) { - int i, ip; + int i; - /* - * Free the loaded fonts in the font cache. This is done backwards - * from the frccur. - */ - for(i = 0, ip = frccur; i < frclen; i++, ip--) { - if(ip < 0) - ip = LEN(frc) - 1; - XftFontClose(xw.dpy, frc[ip].font); + /* Free the loaded fonts in the font cache. */ + for(i = 0; i < frclen; i++) { + XftFontClose(xw.dpy, frc[i].font); } - frccur = -1; frclen = 0; xunloadfont(&dc.font); @@ -2918,7 +2949,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 frp, frcflags; + int frcflags; int u8fl, u8fblen, u8cblen, doesexist; char *u8c, *u8fs; long u8char; @@ -2927,9 +2958,10 @@ 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; + Colour *fg, *bg, *temp, revfg, revbg, truefg, truebg; XRenderColor colfg, colbg; Rectangle r; + int oneatatime; frcflags = FRC_NORMAL; @@ -2947,8 +2979,27 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { if(base.fg == defaultfg) base.fg = defaultunderline; } - fg = &dc.col[base.fg]; - bg = &dc.col[base.bg]; + if(IS_TRUECOL(base.fg)) { + colfg.red = TRUERED(base.fg); + colfg.green = TRUEGREEN(base.fg); + colfg.blue = TRUEBLUE(base.fg); + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg); + fg = &truefg; + } else { + fg = &dc.col[base.fg]; + } + + if(IS_TRUECOL(base.bg)) { + colbg.green = TRUEGREEN(base.bg); + colbg.red = TRUERED(base.bg); + colbg.blue = TRUEBLUE(base.bg); + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg); + bg = &truebg; + } else { + bg = &dc.col[base.bg]; + } + + if(base.mode & ATTR_BOLD) { if(BETWEEN(base.fg, 0, 7)) { @@ -3038,15 +3089,16 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { u8fs = s; u8fblen = 0; u8fl = 0; + oneatatime = font->width != xw.cw; for(;;) { u8c = s; u8cblen = utf8decode(s, &u8char); s += u8cblen; bytelen -= u8cblen; - doesexist = XftCharIndex(xw.dpy, font->match, u8char); - if(!doesexist || bytelen <= 0) { - if(bytelen <= 0) { + doesexist = XftCharExists(xw.dpy, font->match, u8char); + if(oneatatime || !doesexist || bytelen <= 0) { + if(oneatatime || bytelen <= 0) { if(doesexist) { u8fl++; u8fblen += u8cblen; @@ -3059,7 +3111,7 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { winy + font->ascent, (FcChar8 *)u8fs, u8fblen); - xp += font->width * u8fl; + xp += CEIL(font->width * cwscale * u8fl); } break; @@ -3068,17 +3120,16 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { u8fl++; u8fblen += u8cblen; } - if(doesexist) + if(doesexist) { + if (oneatatime); + continue; break; + } - frp = frccur; /* Search the font cache. */ - for(i = 0; i < frclen; i++, frp--) { - if(frp <= 0) - frp = LEN(frc) - 1; - - if(frc[frp].c == u8char - && frc[frp].flags == frcflags) { + for(i = 0; i < frclen; i++) { + if(XftCharExists(xw.dpy, frc[i].font, u8char) + && frc[i].flags == frcflags) { break; } } @@ -3113,31 +3164,27 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { /* * Overwrite or create the new cache entry. */ - frccur++; - frclen++; - if(frccur >= LEN(frc)) - frccur = 0; - if(frclen > LEN(frc)) { - frclen = LEN(frc); - XftFontClose(xw.dpy, frc[frccur].font); + if(frclen >= LEN(frc)) { + frclen = LEN(frc) - 1; + XftFontClose(xw.dpy, frc[frclen].font); } - frc[frccur].font = XftFontOpenPattern(xw.dpy, + frc[frclen].font = XftFontOpenPattern(xw.dpy, fontpattern); - frc[frccur].c = u8char; - frc[frccur].flags = frcflags; + frc[frclen].flags = frcflags; + + i = frclen; + frclen++; FcPatternDestroy(fcpattern); FcCharSetDestroy(fccharset); - - frp = frccur; } - XftDrawStringUtf8(xw.draw, fg, frc[frp].font, - xp, winy + frc[frp].font->ascent, + XftDrawStringUtf8(xw.draw, fg, frc[i].font, + xp, winy + frc[i].font->ascent, (FcChar8 *)u8c, u8cblen); - xp += font->width; + xp += CEIL(font->width * cwscale); } /* @@ -3211,6 +3258,7 @@ xsettitle(char *p) { Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, &prop); XSetWMName(xw.dpy, xw.win, &prop); + XFree(prop.value); } void @@ -3559,8 +3607,8 @@ run(void) { ttyread(); if(blinktimeout) { blinkset = tattrset(ATTR_BLINK); - if(!blinkset && term.mode & ATTR_BLINK) - term.mode &= ~(MODE_BLINK); + if(!blinkset) + MODBIT(term.mode, 0, MODE_BLINK); } } @@ -3666,7 +3714,7 @@ main(int argc, char *argv[]) { xw.fh = (int)hr; if(bitm & XNegative && xw.fx == 0) xw.fx = -1; - if(bitm & XNegative && xw.fy == 0) + if(bitm & YNegative && xw.fy == 0) xw.fy = -1; if(xw.fh != 0 && xw.fw != 0)