diff options
| -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; |
