diff options
author | Christoph Lohmann <20h@r-36.net> | 2012-10-28 13:25:53 +0100 |
---|---|---|
committer | Christoph Lohmann <20h@r-36.net> | 2012-10-28 13:25:53 +0100 |
commit | 53eda6d525899b661a961c97a9e9801ffb583cdb (patch) | |
tree | dcaf4aedf7d7b21afdf989de3a392b1b75e361ad | |
parent | 91804d72273e18ab9f4022f3dc1cc7d90eb3fea0 (diff) | |
download | st-patched-53eda6d525899b661a961c97a9e9801ffb583cdb.tar.bz2 st-patched-53eda6d525899b661a961c97a9e9801ffb583cdb.tar.xz st-patched-53eda6d525899b661a961c97a9e9801ffb583cdb.zip |
Adding a more flexible fontstring handling, shortcuts and a zoom function.
-rw-r--r-- | config.def.h | 14 | ||||
-rw-r--r-- | config.mk | 4 | ||||
-rw-r--r-- | st.c | 186 |
3 files changed, 128 insertions, 76 deletions
diff --git a/config.def.h b/config.def.h index 5c4c518..67b1316 100644 --- a/config.def.h +++ b/config.def.h | |||
@@ -1,4 +1,8 @@ | |||
1 | 1 | ||
2 | /* | ||
3 | * Do not include the »pixelsize« parameter in your font definition. It is | ||
4 | * used to calculate zooming. | ||
5 | */ | ||
2 | #define FONT "Liberation Mono:pixelsize=12:antialias=false:autohint=false" | 6 | #define FONT "Liberation Mono:pixelsize=12:antialias=false:autohint=false" |
3 | 7 | ||
4 | /* Space in pixels around the terminal buffer */ | 8 | /* Space in pixels around the terminal buffer */ |
@@ -73,6 +77,15 @@ static Key key[] = { | |||
73 | { XK_F12, XK_NO_MOD, "\033[24~" }, | 77 | { XK_F12, XK_NO_MOD, "\033[24~" }, |
74 | }; | 78 | }; |
75 | 79 | ||
80 | /* Internal shortcuts. */ | ||
81 | #define MODKEY Mod1Mask | ||
82 | |||
83 | static Shortcut shortcuts[] = { | ||
84 | /* modifier key function argument */ | ||
85 | { MODKEY|ShiftMask, XK_Prior, xzoom, {.i = +1} }, | ||
86 | { MODKEY|ShiftMask, XK_Next, xzoom, {.i = -1} }, | ||
87 | }; | ||
88 | |||
76 | /* Set TERM to this */ | 89 | /* Set TERM to this */ |
77 | #define TNAME "st-256color" | 90 | #define TNAME "st-256color" |
78 | 91 | ||
@@ -81,3 +94,4 @@ static Key key[] = { | |||
81 | #define TRIPLECLICK_TIMEOUT (2*DOUBLECLICK_TIMEOUT) | 94 | #define TRIPLECLICK_TIMEOUT (2*DOUBLECLICK_TIMEOUT) |
82 | 95 | ||
83 | #define TAB 8 | 96 | #define TAB 8 |
97 | |||
@@ -16,8 +16,8 @@ LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lutil -lXext -lXft -lfontconfig | |||
16 | 16 | ||
17 | # flags | 17 | # flags |
18 | CPPFLAGS = -DVERSION=\"${VERSION}\" | 18 | CPPFLAGS = -DVERSION=\"${VERSION}\" |
19 | CFLAGS += -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} | 19 | CFLAGS += -g -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} |
20 | LDFLAGS += -s ${LIBS} | 20 | LDFLAGS += -g ${LIBS} |
21 | 21 | ||
22 | # compiler and linker | 22 | # compiler and linker |
23 | CC ?= cc | 23 | CC ?= cc |
@@ -60,6 +60,8 @@ | |||
60 | 60 | ||
61 | #define REDRAW_TIMEOUT (80*1000) /* 80 ms */ | 61 | #define REDRAW_TIMEOUT (80*1000) /* 80 ms */ |
62 | 62 | ||
63 | /* macros */ | ||
64 | #define CLEANMASK(mask) (mask & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) | ||
63 | #define SERRNO strerror(errno) | 65 | #define SERRNO strerror(errno) |
64 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) | 66 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) |
65 | #define MAX(a, b) ((a) < (b) ? (b) : (a)) | 67 | #define MAX(a, b) ((a) < (b) ? (b) : (a)) |
@@ -238,6 +240,24 @@ typedef struct { | |||
238 | struct timeval tclick2; | 240 | struct timeval tclick2; |
239 | } Selection; | 241 | } Selection; |
240 | 242 | ||
243 | typedef union { | ||
244 | int i; | ||
245 | unsigned int ui; | ||
246 | float f; | ||
247 | const void *v; | ||
248 | } Arg; | ||
249 | |||
250 | typedef struct { | ||
251 | unsigned int mod; | ||
252 | KeySym keysym; | ||
253 | void (*func)(const Arg *); | ||
254 | const Arg arg; | ||
255 | } Shortcut; | ||
256 | |||
257 | /* function definitions used in config.h */ | ||
258 | static void xzoom(const Arg *); | ||
259 | |||
260 | /* Config.h for applying patches and the configuration. */ | ||
241 | #include "config.h" | 261 | #include "config.h" |
242 | 262 | ||
243 | /* Font structure */ | 263 | /* Font structure */ |
@@ -321,6 +341,7 @@ static void unmap(XEvent *); | |||
321 | static char *kmap(KeySym, uint); | 341 | static char *kmap(KeySym, uint); |
322 | static void kpress(XEvent *); | 342 | static void kpress(XEvent *); |
323 | static void cmessage(XEvent *); | 343 | static void cmessage(XEvent *); |
344 | static void cresize(int width, int height); | ||
324 | static void resize(XEvent *); | 345 | static void resize(XEvent *); |
325 | static void focus(XEvent *); | 346 | static void focus(XEvent *); |
326 | static void brelease(XEvent *); | 347 | static void brelease(XEvent *); |
@@ -345,7 +366,6 @@ static ssize_t xwrite(int, char *, size_t); | |||
345 | static void *xmalloc(size_t); | 366 | static void *xmalloc(size_t); |
346 | static void *xrealloc(void *, size_t); | 367 | static void *xrealloc(void *, size_t); |
347 | static void *xcalloc(size_t nmemb, size_t size); | 368 | static void *xcalloc(size_t nmemb, size_t size); |
348 | static char *smstrcat(char *, ...); | ||
349 | 369 | ||
350 | static void (*handler[LASTEvent])(XEvent *) = { | 370 | static void (*handler[LASTEvent])(XEvent *) = { |
351 | [KeyPress] = kpress, | 371 | [KeyPress] = kpress, |
@@ -381,6 +401,8 @@ static char *opt_embed = NULL; | |||
381 | static char *opt_class = NULL; | 401 | static char *opt_class = NULL; |
382 | static char *opt_font = NULL; | 402 | static char *opt_font = NULL; |
383 | 403 | ||
404 | static char *usedfont = NULL; | ||
405 | static int usedfontsize = 0; | ||
384 | 406 | ||
385 | ssize_t | 407 | ssize_t |
386 | xwrite(int fd, char *s, size_t len) { | 408 | xwrite(int fd, char *s, size_t len) { |
@@ -424,44 +446,6 @@ xcalloc(size_t nmemb, size_t size) { | |||
424 | return p; | 446 | return p; |
425 | } | 447 | } |
426 | 448 | ||
427 | char * | ||
428 | smstrcat(char *src, ...) | ||
429 | { | ||
430 | va_list fmtargs; | ||
431 | char *ret, *p, *v; | ||
432 | int len, slen, flen; | ||
433 | |||
434 | len = slen = strlen(src); | ||
435 | |||
436 | va_start(fmtargs, src); | ||
437 | for(;;) { | ||
438 | v = va_arg(fmtargs, char *); | ||
439 | if(v == NULL) | ||
440 | break; | ||
441 | len += strlen(v); | ||
442 | } | ||
443 | va_end(fmtargs); | ||
444 | |||
445 | p = ret = xmalloc(len+1); | ||
446 | memmove(p, src, slen); | ||
447 | p += slen; | ||
448 | |||
449 | va_start(fmtargs, src); | ||
450 | for(;;) { | ||
451 | v = va_arg(fmtargs, char *); | ||
452 | if(v == NULL) | ||
453 | break; | ||
454 | flen = strlen(v); | ||
455 | memmove(p, v, flen); | ||
456 | p += flen; | ||
457 | } | ||
458 | va_end(fmtargs); | ||
459 | |||
460 | ret[len] = '\0'; | ||
461 | |||
462 | return ret; | ||
463 | } | ||
464 | |||
465 | int | 449 | int |
466 | utf8decode(char *s, long *u) { | 450 | utf8decode(char *s, long *u) { |
467 | uchar c; | 451 | uchar c; |
@@ -2107,7 +2091,8 @@ tresize(int col, int row) { | |||
2107 | *bp = 1; | 2091 | *bp = 1; |
2108 | } | 2092 | } |
2109 | /* update terminal size */ | 2093 | /* update terminal size */ |
2110 | term.col = col, term.row = row; | 2094 | term.col = col; |
2095 | term.row = row; | ||
2111 | /* make use of the LIMIT in tmoveto */ | 2096 | /* make use of the LIMIT in tmoveto */ |
2112 | tmoveto(term.c.x, term.c.y); | 2097 | tmoveto(term.c.x, term.c.y); |
2113 | /* reset scrolling region */ | 2098 | /* reset scrolling region */ |
@@ -2207,22 +2192,17 @@ xhints(void) { | |||
2207 | XFree(sizeh); | 2192 | XFree(sizeh); |
2208 | } | 2193 | } |
2209 | 2194 | ||
2210 | void | 2195 | int |
2211 | xinitfont(Font *f, char *fontstr) { | 2196 | xloadfont(Font *f, FcPattern *pattern) { |
2212 | FcPattern *pattern, *match; | 2197 | FcPattern *match; |
2213 | FcResult result; | 2198 | FcResult result; |
2214 | 2199 | ||
2215 | pattern = FcNameParse((FcChar8 *)fontstr); | ||
2216 | if(!pattern) | ||
2217 | die("st: can't open font %s\n", fontstr); | ||
2218 | |||
2219 | match = XftFontMatch(xw.dpy, xw.scr, pattern, &result); | 2200 | match = XftFontMatch(xw.dpy, xw.scr, pattern, &result); |
2220 | FcPatternDestroy(pattern); | ||
2221 | if(!match) | 2201 | if(!match) |
2222 | die("st: can't open font %s\n", fontstr); | 2202 | return 1; |
2223 | if(!(f->xft_set = XftFontOpenPattern(xw.dpy, match))) { | 2203 | if(!(f->xft_set = XftFontOpenPattern(xw.dpy, match))) { |
2224 | FcPatternDestroy(match); | 2204 | FcPatternDestroy(match); |
2225 | die("st: can't open font %s.\n", fontstr); | 2205 | return 1; |
2226 | } | 2206 | } |
2227 | 2207 | ||
2228 | f->ascent = f->xft_set->ascent; | 2208 | f->ascent = f->xft_set->ascent; |
@@ -2232,27 +2212,68 @@ xinitfont(Font *f, char *fontstr) { | |||
2232 | 2212 | ||
2233 | f->height = f->xft_set->height; | 2213 | f->height = f->xft_set->height; |
2234 | f->width = f->lbearing + f->rbearing; | 2214 | f->width = f->lbearing + f->rbearing; |
2215 | |||
2216 | return 0; | ||
2235 | } | 2217 | } |
2236 | 2218 | ||
2237 | void | 2219 | void |
2238 | initfonts(char *fontstr) { | 2220 | xloadfonts(char *fontstr, int fontsize) { |
2239 | char *fstr; | 2221 | FcPattern *pattern; |
2222 | FcResult result; | ||
2223 | double fontval; | ||
2224 | |||
2225 | pattern = FcNameParse((FcChar8 *)fontstr); | ||
2226 | if(!pattern) | ||
2227 | die("st: can't open font %s\n", fontstr); | ||
2228 | |||
2229 | if(fontsize > 0) { | ||
2230 | FcPatternDel(pattern, FC_PIXEL_SIZE); | ||
2231 | FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); | ||
2232 | usedfontsize = fontsize; | ||
2233 | } else { | ||
2234 | result = FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval); | ||
2235 | if(result == FcResultMatch) { | ||
2236 | usedfontsize = (int)fontval; | ||
2237 | } else { | ||
2238 | /* | ||
2239 | * Default font size is 12, if none given. This is to | ||
2240 | * have a known usedfontsize value. | ||
2241 | */ | ||
2242 | FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); | ||
2243 | usedfontsize = 12; | ||
2244 | } | ||
2245 | } | ||
2240 | 2246 | ||
2241 | xinitfont(&dc.font, fontstr); | 2247 | if(xloadfont(&dc.font, pattern)) |
2248 | die("st: can't open font %s\n", fontstr); | ||
2249 | |||
2250 | /* Setting character width and height. */ | ||
2242 | xw.cw = dc.font.width; | 2251 | xw.cw = dc.font.width; |
2243 | xw.ch = dc.font.height; | 2252 | xw.ch = dc.font.height; |
2244 | 2253 | ||
2245 | fstr = smstrcat(fontstr, ":weight=bold", NULL); | 2254 | FcPatternDel(pattern, FC_WEIGHT); |
2246 | xinitfont(&dc.bfont, fstr); | 2255 | FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); |
2247 | free(fstr); | 2256 | if(xloadfont(&dc.bfont, pattern)) |
2257 | die("st: can't open font %s\n", fontstr); | ||
2248 | 2258 | ||
2249 | fstr = smstrcat(fontstr, ":slant=italic,oblique", NULL); | 2259 | FcPatternDel(pattern, FC_SLANT); |
2250 | xinitfont(&dc.ifont, fstr); | 2260 | FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); |
2251 | free(fstr); | 2261 | if(xloadfont(&dc.ibfont, pattern)) |
2262 | die("st: can't open font %s\n", fontstr); | ||
2252 | 2263 | ||
2253 | fstr = smstrcat(fontstr, ":weight=bold:slant=italic,oblique", NULL); | 2264 | FcPatternDel(pattern, FC_WEIGHT); |
2254 | xinitfont(&dc.ibfont, fstr); | 2265 | if(xloadfont(&dc.ifont, pattern)) |
2255 | free(fstr); | 2266 | die("st: can't open font %s\n", fontstr); |
2267 | |||
2268 | FcPatternDestroy(pattern); | ||
2269 | } | ||
2270 | |||
2271 | void | ||
2272 | xzoom(const Arg *arg) | ||
2273 | { | ||
2274 | xloadfonts(usedfont, usedfontsize + arg->i); | ||
2275 | cresize(0, 0); | ||
2276 | draw(); | ||
2256 | } | 2277 | } |
2257 | 2278 | ||
2258 | void | 2279 | void |
@@ -2268,7 +2289,8 @@ xinit(void) { | |||
2268 | xw.vis = XDefaultVisual(xw.dpy, xw.scr); | 2289 | xw.vis = XDefaultVisual(xw.dpy, xw.scr); |
2269 | 2290 | ||
2270 | /* font */ | 2291 | /* font */ |
2271 | initfonts((opt_font != NULL)? opt_font : FONT); | 2292 | usedfont = (opt_font == NULL)? FONT : opt_font; |
2293 | xloadfonts(usedfont, 0); | ||
2272 | 2294 | ||
2273 | /* colors */ | 2295 | /* colors */ |
2274 | xw.cmap = XDefaultColormap(xw.dpy, xw.scr); | 2296 | xw.cmap = XDefaultColormap(xw.dpy, xw.scr); |
@@ -2604,11 +2626,8 @@ void | |||
2604 | kpress(XEvent *ev) { | 2626 | kpress(XEvent *ev) { |
2605 | XKeyEvent *e = &ev->xkey; | 2627 | XKeyEvent *e = &ev->xkey; |
2606 | KeySym ksym; | 2628 | KeySym ksym; |
2607 | char buf[32]; | 2629 | char buf[32], *customkey; |
2608 | char *customkey; | 2630 | int len, meta, shift, i; |
2609 | int len; | ||
2610 | int meta; | ||
2611 | int shift; | ||
2612 | Status status; | 2631 | Status status; |
2613 | 2632 | ||
2614 | if (IS_SET(MODE_KBDLOCK)) | 2633 | if (IS_SET(MODE_KBDLOCK)) |
@@ -2618,7 +2637,17 @@ kpress(XEvent *ev) { | |||
2618 | shift = e->state & ShiftMask; | 2637 | shift = e->state & ShiftMask; |
2619 | len = XmbLookupString(xw.xic, e, buf, sizeof(buf), &ksym, &status); | 2638 | len = XmbLookupString(xw.xic, e, buf, sizeof(buf), &ksym, &status); |
2620 | 2639 | ||
2621 | /* 1. custom keys from config.h */ | 2640 | /* 1. shortcuts */ |
2641 | for(i = 0; i < LEN(shortcuts); i++) { | ||
2642 | if((ksym == shortcuts[i].keysym) | ||
2643 | && (CLEANMASK(shortcuts[i].mod) == \ | ||
2644 | CLEANMASK(e->state)) | ||
2645 | && shortcuts[i].func) { | ||
2646 | shortcuts[i].func(&(shortcuts[i].arg)); | ||
2647 | } | ||
2648 | } | ||
2649 | |||
2650 | /* 2. custom keys from config.h */ | ||
2622 | if((customkey = kmap(ksym, e->state))) { | 2651 | if((customkey = kmap(ksym, e->state))) { |
2623 | ttywrite(customkey, strlen(customkey)); | 2652 | ttywrite(customkey, strlen(customkey)); |
2624 | /* 2. hardcoded (overrides X lookup) */ | 2653 | /* 2. hardcoded (overrides X lookup) */ |
@@ -2676,14 +2705,15 @@ cmessage(XEvent *e) { | |||
2676 | } | 2705 | } |
2677 | 2706 | ||
2678 | void | 2707 | void |
2679 | resize(XEvent *e) { | 2708 | cresize(int width, int height) |
2709 | { | ||
2680 | int col, row; | 2710 | int col, row; |
2681 | 2711 | ||
2682 | if(e->xconfigure.width == xw.w && e->xconfigure.height == xw.h) | 2712 | if(width != 0) |
2683 | return; | 2713 | xw.w = width; |
2714 | if(height != 0) | ||
2715 | xw.h = height; | ||
2684 | 2716 | ||
2685 | xw.w = e->xconfigure.width; | ||
2686 | xw.h = e->xconfigure.height; | ||
2687 | col = (xw.w - 2*BORDER) / xw.cw; | 2717 | col = (xw.w - 2*BORDER) / xw.cw; |
2688 | row = (xw.h - 2*BORDER) / xw.ch; | 2718 | row = (xw.h - 2*BORDER) / xw.ch; |
2689 | if(col == term.col && row == term.row) | 2719 | if(col == term.col && row == term.row) |
@@ -2695,6 +2725,14 @@ resize(XEvent *e) { | |||
2695 | } | 2725 | } |
2696 | 2726 | ||
2697 | void | 2727 | void |
2728 | resize(XEvent *e) { | ||
2729 | if(e->xconfigure.width == xw.w && e->xconfigure.height == xw.h) | ||
2730 | return; | ||
2731 | |||
2732 | cresize(e->xconfigure.width, e->xconfigure.height); | ||
2733 | } | ||
2734 | |||
2735 | void | ||
2698 | run(void) { | 2736 | run(void) { |
2699 | XEvent ev; | 2737 | XEvent ev; |
2700 | fd_set rfd; | 2738 | fd_set rfd; |