diff options
-rw-r--r-- | config.def.h | 9 | ||||
-rw-r--r-- | config.mk | 4 | ||||
-rw-r--r-- | st.c | 130 |
3 files changed, 65 insertions, 78 deletions
diff --git a/config.def.h b/config.def.h index 7746eaf..5cb1fd2 100644 --- a/config.def.h +++ b/config.def.h | |||
@@ -1,9 +1,8 @@ | |||
1 | 1 | ||
2 | #define FONT "-*-*-medium-r-*-*-*-120-75-75-*-70-*-*" | 2 | #define FONT "Bitstream Vera Sans Mono:pixelsize=12:antialias=false:autohint=true" |
3 | #define BOLDFONT "-*-*-bold-r-*-*-*-120-75-75-*-70-*-*" | 3 | #define BOLDFONT FONT ":weight=bold" |
4 | /* If italic is not available, fall back to bold. */ | 4 | #define ITALICFONT FONT ":slant=italic,oblique" |
5 | #define ITALICFONT "-*-*-medium-o-*-*-*-120-75-75-*-70-*-*," BOLDFONT | 5 | #define ITALICBOLDFONT BOLDFONT ":slant=italic,oblique" |
6 | #define ITALICBOLDFONT "-*-*-bold-o-*-*-*-120-75-75-*-70-*-*," BOLDFONT | ||
7 | 6 | ||
8 | /* Space in pixels around the terminal buffer */ | 7 | /* Space in pixels around the terminal buffer */ |
9 | #define BORDER 2 | 8 | #define BORDER 2 |
@@ -11,8 +11,8 @@ X11INC = /usr/X11R6/include | |||
11 | X11LIB = /usr/X11R6/lib | 11 | X11LIB = /usr/X11R6/lib |
12 | 12 | ||
13 | # includes and libs | 13 | # includes and libs |
14 | INCS = -I. -I/usr/include -I${X11INC} | 14 | INCS = -I. -I/usr/include -I${X11INC} -I/usr/include/freetype2 |
15 | LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lutil -lXext | 15 | LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lutil -lXext -lXft |
16 | 16 | ||
17 | # flags | 17 | # flags |
18 | CPPFLAGS = -DVERSION=\"${VERSION}\" | 18 | CPPFLAGS = -DVERSION=\"${VERSION}\" |
@@ -25,6 +25,9 @@ | |||
25 | #include <X11/cursorfont.h> | 25 | #include <X11/cursorfont.h> |
26 | #include <X11/keysym.h> | 26 | #include <X11/keysym.h> |
27 | #include <X11/extensions/Xdbe.h> | 27 | #include <X11/extensions/Xdbe.h> |
28 | #include <X11/Xft/Xft.h> | ||
29 | #define Glyph Glyph_ | ||
30 | #define Font Font_ | ||
28 | 31 | ||
29 | #if defined(__linux) | 32 | #if defined(__linux) |
30 | #include <pty.h> | 33 | #include <pty.h> |
@@ -195,6 +198,8 @@ typedef struct { | |||
195 | Atom xembed; | 198 | Atom xembed; |
196 | XIM xim; | 199 | XIM xim; |
197 | XIC xic; | 200 | XIC xic; |
201 | XftDraw *xft_draw; | ||
202 | Visual *vis; | ||
198 | int scr; | 203 | int scr; |
199 | Bool isfixed; /* is fixed geometry? */ | 204 | Bool isfixed; /* is fixed geometry? */ |
200 | int fx, fy, fw, fh; /* fixed geometry */ | 205 | int fx, fy, fw, fh; /* fixed geometry */ |
@@ -212,7 +217,6 @@ typedef struct { | |||
212 | char s[ESC_BUF_SIZ]; | 217 | char s[ESC_BUF_SIZ]; |
213 | } Key; | 218 | } Key; |
214 | 219 | ||
215 | |||
216 | /* TODO: use better name for vars... */ | 220 | /* TODO: use better name for vars... */ |
217 | typedef struct { | 221 | typedef struct { |
218 | int mode; | 222 | int mode; |
@@ -228,17 +232,22 @@ typedef struct { | |||
228 | 232 | ||
229 | #include "config.h" | 233 | #include "config.h" |
230 | 234 | ||
235 | /* Font structure */ | ||
236 | typedef struct { | ||
237 | int ascent; | ||
238 | int descent; | ||
239 | short lbearing; | ||
240 | short rbearing; | ||
241 | XFontSet set; | ||
242 | XftFont* xft_set; | ||
243 | } Font; | ||
244 | |||
231 | /* Drawing Context */ | 245 | /* Drawing Context */ |
232 | typedef struct { | 246 | typedef struct { |
233 | ulong col[LEN(colorname) < 256 ? 256 : LEN(colorname)]; | 247 | ulong col[LEN(colorname) < 256 ? 256 : LEN(colorname)]; |
248 | XftColor xft_col[LEN(colorname) < 256 ? 256 : LEN(colorname)]; | ||
234 | GC gc; | 249 | GC gc; |
235 | struct { | 250 | Font font, bfont, ifont, ibfont; |
236 | int ascent; | ||
237 | int descent; | ||
238 | short lbearing; | ||
239 | short rbearing; | ||
240 | XFontSet set; | ||
241 | } font, bfont, ifont, ibfont; | ||
242 | } DC; | 251 | } DC; |
243 | 252 | ||
244 | static void die(const char*, ...); | 253 | static void die(const char*, ...); |
@@ -1840,47 +1849,49 @@ void | |||
1840 | xresize(int col, int row) { | 1849 | xresize(int col, int row) { |
1841 | xw.tw = MAX(1, 2*BORDER + col * xw.cw); | 1850 | xw.tw = MAX(1, 2*BORDER + col * xw.cw); |
1842 | xw.th = MAX(1, 2*BORDER + row * xw.ch); | 1851 | xw.th = MAX(1, 2*BORDER + row * xw.ch); |
1852 | |||
1853 | XftDrawChange(xw.xft_draw, xw.buf); | ||
1843 | } | 1854 | } |
1844 | 1855 | ||
1845 | void | 1856 | void |
1846 | xloadcols(void) { | 1857 | xloadcols(void) { |
1847 | int i, r, g, b; | 1858 | int i, r, g, b; |
1848 | XColor color; | 1859 | XRenderColor xft_color = { .alpha = 0 }; |
1849 | ulong white = WhitePixel(xw.dpy, xw.scr); | 1860 | ulong white = WhitePixel(xw.dpy, xw.scr); |
1850 | 1861 | ||
1851 | /* load colors [0-15] colors and [256-LEN(colorname)[ (config.h) */ | 1862 | /* load colors [0-15] colors and [256-LEN(colorname)[ (config.h) */ |
1852 | for(i = 0; i < LEN(colorname); i++) { | 1863 | for(i = 0; i < LEN(colorname); i++) { |
1853 | if(!colorname[i]) | 1864 | if(!colorname[i]) |
1854 | continue; | 1865 | continue; |
1855 | if(!XAllocNamedColor(xw.dpy, xw.cmap, colorname[i], &color, &color)) { | 1866 | if(!XftColorAllocName(xw.dpy, xw.vis, xw.cmap, colorname[i], &dc.xft_col[i])) { |
1856 | dc.col[i] = white; | 1867 | dc.col[i] = white; |
1857 | fprintf(stderr, "Could not allocate color '%s'\n", colorname[i]); | 1868 | fprintf(stderr, "Could not allocate color '%s'\n", colorname[i]); |
1858 | } else | 1869 | } else |
1859 | dc.col[i] = color.pixel; | 1870 | dc.col[i] = dc.xft_col[i].pixel; |
1860 | } | 1871 | } |
1861 | 1872 | ||
1862 | /* load colors [16-255] ; same colors as xterm */ | 1873 | /* load colors [16-255] ; same colors as xterm */ |
1863 | for(i = 16, r = 0; r < 6; r++) | 1874 | for(i = 16, r = 0; r < 6; r++) |
1864 | for(g = 0; g < 6; g++) | 1875 | for(g = 0; g < 6; g++) |
1865 | for(b = 0; b < 6; b++) { | 1876 | for(b = 0; b < 6; b++) { |
1866 | color.red = r == 0 ? 0 : 0x3737 + 0x2828 * r; | 1877 | xft_color.red = r == 0 ? 0 : 0x3737 + 0x2828 * r; |
1867 | color.green = g == 0 ? 0 : 0x3737 + 0x2828 * g; | 1878 | xft_color.green = g == 0 ? 0 : 0x3737 + 0x2828 * g; |
1868 | color.blue = b == 0 ? 0 : 0x3737 + 0x2828 * b; | 1879 | xft_color.blue = b == 0 ? 0 : 0x3737 + 0x2828 * b; |
1869 | if(!XAllocColor(xw.dpy, xw.cmap, &color)) { | 1880 | if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &xft_color, &dc.xft_col[i])) { |
1870 | dc.col[i] = white; | 1881 | dc.col[i] = white; |
1871 | fprintf(stderr, "Could not allocate color %d\n", i); | 1882 | fprintf(stderr, "Could not allocate color %d\n", i); |
1872 | } else | 1883 | } else |
1873 | dc.col[i] = color.pixel; | 1884 | dc.col[i] = dc.xft_col[i].pixel; |
1874 | i++; | 1885 | i++; |
1875 | } | 1886 | } |
1876 | 1887 | ||
1877 | for(r = 0; r < 24; r++, i++) { | 1888 | for(r = 0; r < 24; r++, i++) { |
1878 | color.red = color.green = color.blue = 0x0808 + 0x0a0a * r; | 1889 | xft_color.red = xft_color.green = xft_color.blue = 0x0808 + 0x0a0a * r; |
1879 | if(!XAllocColor(xw.dpy, xw.cmap, &color)) { | 1890 | if(!XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &xft_color, &dc.xft_col[i])) { |
1880 | dc.col[i] = white; | 1891 | dc.col[i] = white; |
1881 | fprintf(stderr, "Could not allocate color %d\n", i); | 1892 | fprintf(stderr, "Could not allocate color %d\n", i); |
1882 | } else | 1893 | } else |
1883 | dc.col[i] = color.pixel; | 1894 | dc.col[i] = dc.xft_col[i].pixel; |
1884 | } | 1895 | } |
1885 | } | 1896 | } |
1886 | 1897 | ||
@@ -1917,58 +1928,25 @@ xhints(void) { | |||
1917 | XFree(sizeh); | 1928 | XFree(sizeh); |
1918 | } | 1929 | } |
1919 | 1930 | ||
1920 | XFontSet | ||
1921 | xinitfont(char *fontstr) { | ||
1922 | XFontSet set; | ||
1923 | char *def, **missing; | ||
1924 | int n; | ||
1925 | |||
1926 | missing = NULL; | ||
1927 | set = XCreateFontSet(xw.dpy, fontstr, &missing, &n, &def); | ||
1928 | if(missing) { | ||
1929 | while(n--) | ||
1930 | fprintf(stderr, "st: missing fontset: %s\n", missing[n]); | ||
1931 | XFreeStringList(missing); | ||
1932 | } | ||
1933 | return set; | ||
1934 | } | ||
1935 | |||
1936 | void | 1931 | void |
1937 | xgetfontinfo(XFontSet set, int *ascent, int *descent, short *lbearing, short *rbearing) { | 1932 | xinitfont(Font *f, char *fontstr) { |
1938 | XFontStruct **xfonts; | 1933 | f->xft_set = XftFontOpenName(xw.dpy, xw.scr, fontstr); |
1939 | char **font_names; | ||
1940 | int i, n; | ||
1941 | 1934 | ||
1942 | *ascent = *descent = *lbearing = *rbearing = 0; | 1935 | if(!f->xft_set) |
1943 | n = XFontsOfFontSet(set, &xfonts, &font_names); | 1936 | die("st: can't open font %s.\n", fontstr); |
1944 | for(i = 0; i < n; i++) { | 1937 | |
1945 | *ascent = MAX(*ascent, (*xfonts)->ascent); | 1938 | f->ascent = f->xft_set->ascent; |
1946 | *descent = MAX(*descent, (*xfonts)->descent); | 1939 | f->descent = f->xft_set->descent; |
1947 | *lbearing = MAX(*lbearing, (*xfonts)->min_bounds.lbearing); | 1940 | f->lbearing = 0; |
1948 | *rbearing = MAX(*rbearing, (*xfonts)->max_bounds.rbearing); | 1941 | f->rbearing = f->xft_set->max_advance_width; |
1949 | xfonts++; | ||
1950 | } | ||
1951 | } | 1942 | } |
1952 | 1943 | ||
1953 | void | 1944 | void |
1954 | initfonts(char *fontstr, char *bfontstr, char *ifontstr, char *ibfontstr) { | 1945 | initfonts(char *fontstr, char *bfontstr, char *ifontstr, char *ibfontstr) { |
1955 | if((dc.font.set = xinitfont(fontstr)) == NULL) | 1946 | xinitfont(&dc.font, fontstr); |
1956 | die("Can't load font %s\n", fontstr); | 1947 | xinitfont(&dc.bfont, bfontstr); |
1957 | if((dc.bfont.set = xinitfont(bfontstr)) == NULL) | 1948 | xinitfont(&dc.ifont, ifontstr); |
1958 | die("Can't load bfont %s\n", bfontstr); | 1949 | xinitfont(&dc.ibfont, ibfontstr); |
1959 | if((dc.ifont.set = xinitfont(ifontstr)) == NULL) | ||
1960 | die("Can't load ifont %s\n", ifontstr); | ||
1961 | if((dc.ibfont.set = xinitfont(ibfontstr)) == NULL) | ||
1962 | die("Can't load ibfont %s\n", ibfontstr); | ||
1963 | |||
1964 | xgetfontinfo(dc.font.set, &dc.font.ascent, &dc.font.descent, | ||
1965 | &dc.font.lbearing, &dc.font.rbearing); | ||
1966 | xgetfontinfo(dc.bfont.set, &dc.bfont.ascent, &dc.bfont.descent, | ||
1967 | &dc.bfont.lbearing, &dc.bfont.rbearing); | ||
1968 | xgetfontinfo(dc.ifont.set, &dc.ifont.ascent, &dc.ifont.descent, | ||
1969 | &dc.ifont.lbearing, &dc.ifont.rbearing); | ||
1970 | xgetfontinfo(dc.ibfont.set, &dc.ibfont.ascent, &dc.ibfont.descent, | ||
1971 | &dc.ibfont.lbearing, &dc.ibfont.rbearing); | ||
1972 | } | 1950 | } |
1973 | 1951 | ||
1974 | void | 1952 | void |
@@ -1981,6 +1959,7 @@ xinit(void) { | |||
1981 | if(!(xw.dpy = XOpenDisplay(NULL))) | 1959 | if(!(xw.dpy = XOpenDisplay(NULL))) |
1982 | die("Can't open display\n"); | 1960 | die("Can't open display\n"); |
1983 | xw.scr = XDefaultScreen(xw.dpy); | 1961 | xw.scr = XDefaultScreen(xw.dpy); |
1962 | xw.vis = XDefaultVisual(xw.dpy, xw.scr); | ||
1984 | 1963 | ||
1985 | /* font */ | 1964 | /* font */ |
1986 | initfonts(FONT, BOLDFONT, ITALICFONT, ITALICBOLDFONT); | 1965 | initfonts(FONT, BOLDFONT, ITALICFONT, ITALICBOLDFONT); |
@@ -2023,14 +2002,19 @@ xinit(void) { | |||
2023 | parent = opt_embed ? strtol(opt_embed, NULL, 0) : XRootWindow(xw.dpy, xw.scr); | 2002 | parent = opt_embed ? strtol(opt_embed, NULL, 0) : XRootWindow(xw.dpy, xw.scr); |
2024 | xw.win = XCreateWindow(xw.dpy, parent, xw.fx, xw.fy, | 2003 | xw.win = XCreateWindow(xw.dpy, parent, xw.fx, xw.fy, |
2025 | xw.w, xw.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, | 2004 | xw.w, xw.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, |
2026 | XDefaultVisual(xw.dpy, xw.scr), | 2005 | xw.vis, |
2027 | CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask | 2006 | CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask |
2028 | | CWColormap, | 2007 | | CWColormap, |
2029 | &attrs); | 2008 | &attrs); |
2009 | |||
2010 | /* double buffering */ | ||
2030 | if(!XdbeQueryExtension(xw.dpy, &major, &minor)) | 2011 | if(!XdbeQueryExtension(xw.dpy, &major, &minor)) |
2031 | die("Xdbe extension is not present\n"); | 2012 | die("Xdbe extension is not present\n"); |
2032 | xw.buf = XdbeAllocateBackBufferName(xw.dpy, xw.win, XdbeCopied); | 2013 | xw.buf = XdbeAllocateBackBufferName(xw.dpy, xw.win, XdbeCopied); |
2033 | 2014 | ||
2015 | /* Xft rendering context */ | ||
2016 | xw.xft_draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); | ||
2017 | |||
2034 | /* input methods */ | 2018 | /* input methods */ |
2035 | xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); | 2019 | xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); |
2036 | xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing | 2020 | xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing |
@@ -2058,7 +2042,8 @@ void | |||
2058 | xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { | 2042 | xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { |
2059 | int fg = base.fg, bg = base.bg, temp; | 2043 | int fg = base.fg, bg = base.bg, temp; |
2060 | int winx = BORDER+x*xw.cw, winy = BORDER+y*xw.ch + dc.font.ascent, width = charlen*xw.cw; | 2044 | int winx = BORDER+x*xw.cw, winy = BORDER+y*xw.ch + dc.font.ascent, width = charlen*xw.cw; |
2061 | XFontSet fontset = dc.font.set; | 2045 | Font *font = &dc.font; |
2046 | XGlyphInfo extents; | ||
2062 | int i; | 2047 | int i; |
2063 | 2048 | ||
2064 | /* only switch default fg/bg if term is in RV mode */ | 2049 | /* only switch default fg/bg if term is in RV mode */ |
@@ -2074,13 +2059,13 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { | |||
2074 | 2059 | ||
2075 | if(base.mode & ATTR_BOLD) { | 2060 | if(base.mode & ATTR_BOLD) { |
2076 | fg += 8; | 2061 | fg += 8; |
2077 | fontset = dc.bfont.set; | 2062 | font = &dc.bfont; |
2078 | } | 2063 | } |
2079 | 2064 | ||
2080 | if(base.mode & ATTR_ITALIC) | 2065 | if(base.mode & ATTR_ITALIC) |
2081 | fontset = dc.ifont.set; | 2066 | font = &dc.ifont; |
2082 | if(base.mode & (ATTR_ITALIC|ATTR_ITALIC)) | 2067 | if(base.mode & (ATTR_ITALIC|ATTR_ITALIC)) |
2083 | fontset = dc.ibfont.set; | 2068 | font = &dc.ibfont; |
2084 | 2069 | ||
2085 | XSetBackground(xw.dpy, dc.gc, dc.col[bg]); | 2070 | XSetBackground(xw.dpy, dc.gc, dc.col[bg]); |
2086 | XSetForeground(xw.dpy, dc.gc, dc.col[fg]); | 2071 | XSetForeground(xw.dpy, dc.gc, dc.col[fg]); |
@@ -2095,7 +2080,10 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { | |||
2095 | } | 2080 | } |
2096 | } | 2081 | } |
2097 | 2082 | ||
2098 | XmbDrawImageString(xw.dpy, xw.buf, fontset, dc.gc, winx, winy, s, bytelen); | 2083 | XftTextExtentsUtf8(xw.dpy, font->xft_set, (FcChar8 *)s, bytelen, &extents); |
2084 | width = extents.xOff; | ||
2085 | XftDrawRect(xw.xft_draw, &dc.xft_col[bg], winx, winy - font->ascent, width, xw.ch); | ||
2086 | XftDrawStringUtf8(xw.xft_draw, &dc.xft_col[fg], font->xft_set, winx, winy, (FcChar8 *)s, bytelen); | ||
2099 | 2087 | ||
2100 | if(base.mode & ATTR_UNDERLINE) | 2088 | if(base.mode & ATTR_UNDERLINE) |
2101 | XDrawLine(xw.dpy, xw.buf, dc.gc, winx, winy+1, winx+width-1, winy+1); | 2089 | XDrawLine(xw.dpy, xw.buf, dc.gc, winx, winy+1, winx+width-1, winy+1); |