tAdding a more flexible fontstring handling, shortcuts and a zoom function. - s… | |
git clone git://src.adamsgaard.dk/st | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 71b09ec4f172da9a89be2add54b5b94da8af3bea | |
parent 6d4e525ed95fbddc38be441394a02dc9233b157d | |
Author: Christoph Lohmann <[email protected]> | |
Date: Sun, 28 Oct 2012 13:25:53 +0100 | |
Adding a more flexible fontstring handling, shortcuts and a zoom function. | |
Diffstat: | |
M config.def.h | 14 ++++++++++++++ | |
M config.mk | 4 ++-- | |
M st.c | 186 +++++++++++++++++++----------… | |
3 files changed, 128 insertions(+), 76 deletions(-) | |
--- | |
diff --git a/config.def.h b/config.def.h | |
t@@ -1,4 +1,8 @@ | |
+/* | |
+ * Do not include the »pixelsize« parameter in your font definition. It is | |
+ * used to calculate zooming. | |
+ */ | |
#define FONT "Liberation Mono:pixelsize=12:antialias=false:autohint=false" | |
/* Space in pixels around the terminal buffer */ | |
t@@ -73,6 +77,15 @@ static Key key[] = { | |
{ XK_F12, XK_NO_MOD, "\033[24~" }, | |
}; | |
+/* Internal shortcuts. */ | |
+#define MODKEY Mod1Mask | |
+ | |
+static Shortcut shortcuts[] = { | |
+ /* modifier key function argument… | |
+ { MODKEY|ShiftMask, XK_Prior, xzoom, {.i … | |
+ { MODKEY|ShiftMask, XK_Next, xzoom, {.i =… | |
+}; | |
+ | |
/* Set TERM to this */ | |
#define TNAME "st-256color" | |
t@@ -81,3 +94,4 @@ static Key key[] = { | |
#define TRIPLECLICK_TIMEOUT (2*DOUBLECLICK_TIMEOUT) | |
#define TAB 8 | |
+ | |
diff --git a/config.mk b/config.mk | |
t@@ -16,8 +16,8 @@ LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lutil -lXext -lXft … | |
# flags | |
CPPFLAGS = -DVERSION=\"${VERSION}\" | |
-CFLAGS += -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} | |
-LDFLAGS += -s ${LIBS} | |
+CFLAGS += -g -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} | |
+LDFLAGS += -g ${LIBS} | |
# compiler and linker | |
CC ?= cc | |
diff --git a/st.c b/st.c | |
t@@ -60,6 +60,8 @@ | |
#define REDRAW_TIMEOUT (80*1000) /* 80 ms */ | |
+/* macros */ | |
+#define CLEANMASK(mask) (mask & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3M… | |
#define SERRNO strerror(errno) | |
#define MIN(a, b) ((a) < (b) ? (a) : (b)) | |
#define MAX(a, b) ((a) < (b) ? (b) : (a)) | |
t@@ -238,6 +240,24 @@ typedef struct { | |
struct timeval tclick2; | |
} Selection; | |
+typedef union { | |
+ int i; | |
+ unsigned int ui; | |
+ float f; | |
+ const void *v; | |
+} Arg; | |
+ | |
+typedef struct { | |
+ unsigned int mod; | |
+ KeySym keysym; | |
+ void (*func)(const Arg *); | |
+ const Arg arg; | |
+} Shortcut; | |
+ | |
+/* function definitions used in config.h */ | |
+static void xzoom(const Arg *); | |
+ | |
+/* Config.h for applying patches and the configuration. */ | |
#include "config.h" | |
/* Font structure */ | |
t@@ -321,6 +341,7 @@ static void unmap(XEvent *); | |
static char *kmap(KeySym, uint); | |
static void kpress(XEvent *); | |
static void cmessage(XEvent *); | |
+static void cresize(int width, int height); | |
static void resize(XEvent *); | |
static void focus(XEvent *); | |
static void brelease(XEvent *); | |
t@@ -345,7 +366,6 @@ static ssize_t xwrite(int, char *, size_t); | |
static void *xmalloc(size_t); | |
static void *xrealloc(void *, size_t); | |
static void *xcalloc(size_t nmemb, size_t size); | |
-static char *smstrcat(char *, ...); | |
static void (*handler[LASTEvent])(XEvent *) = { | |
[KeyPress] = kpress, | |
t@@ -381,6 +401,8 @@ static char *opt_embed = NULL; | |
static char *opt_class = NULL; | |
static char *opt_font = NULL; | |
+static char *usedfont = NULL; | |
+static int usedfontsize = 0; | |
ssize_t | |
xwrite(int fd, char *s, size_t len) { | |
t@@ -424,44 +446,6 @@ xcalloc(size_t nmemb, size_t size) { | |
return p; | |
} | |
-char * | |
-smstrcat(char *src, ...) | |
-{ | |
- va_list fmtargs; | |
- char *ret, *p, *v; | |
- int len, slen, flen; | |
- | |
- len = slen = strlen(src); | |
- | |
- va_start(fmtargs, src); | |
- for(;;) { | |
- v = va_arg(fmtargs, char *); | |
- if(v == NULL) | |
- break; | |
- len += strlen(v); | |
- } | |
- va_end(fmtargs); | |
- | |
- p = ret = xmalloc(len+1); | |
- memmove(p, src, slen); | |
- p += slen; | |
- | |
- va_start(fmtargs, src); | |
- for(;;) { | |
- v = va_arg(fmtargs, char *); | |
- if(v == NULL) | |
- break; | |
- flen = strlen(v); | |
- memmove(p, v, flen); | |
- p += flen; | |
- } | |
- va_end(fmtargs); | |
- | |
- ret[len] = '\0'; | |
- | |
- return ret; | |
-} | |
- | |
int | |
utf8decode(char *s, long *u) { | |
uchar c; | |
t@@ -2107,7 +2091,8 @@ tresize(int col, int row) { | |
*bp = 1; | |
} | |
/* update terminal size */ | |
- term.col = col, term.row = row; | |
+ term.col = col; | |
+ term.row = row; | |
/* make use of the LIMIT in tmoveto */ | |
tmoveto(term.c.x, term.c.y); | |
/* reset scrolling region */ | |
t@@ -2207,22 +2192,17 @@ xhints(void) { | |
XFree(sizeh); | |
} | |
-void | |
-xinitfont(Font *f, char *fontstr) { | |
- FcPattern *pattern, *match; | |
+int | |
+xloadfont(Font *f, FcPattern *pattern) { | |
+ FcPattern *match; | |
FcResult result; | |
- pattern = FcNameParse((FcChar8 *)fontstr); | |
- if(!pattern) | |
- die("st: can't open font %s\n", fontstr); | |
- | |
match = XftFontMatch(xw.dpy, xw.scr, pattern, &result); | |
- FcPatternDestroy(pattern); | |
if(!match) | |
- die("st: can't open font %s\n", fontstr); | |
+ return 1; | |
if(!(f->xft_set = XftFontOpenPattern(xw.dpy, match))) { | |
FcPatternDestroy(match); | |
- die("st: can't open font %s.\n", fontstr); | |
+ return 1; | |
} | |
f->ascent = f->xft_set->ascent; | |
t@@ -2232,27 +2212,68 @@ xinitfont(Font *f, char *fontstr) { | |
f->height = f->xft_set->height; | |
f->width = f->lbearing + f->rbearing; | |
+ | |
+ return 0; | |
} | |
void | |
-initfonts(char *fontstr) { | |
- char *fstr; | |
+xloadfonts(char *fontstr, int fontsize) { | |
+ FcPattern *pattern; | |
+ FcResult result; | |
+ double fontval; | |
+ | |
+ pattern = FcNameParse((FcChar8 *)fontstr); | |
+ if(!pattern) | |
+ die("st: can't open font %s\n", fontstr); | |
+ | |
+ if(fontsize > 0) { | |
+ FcPatternDel(pattern, FC_PIXEL_SIZE); | |
+ FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); | |
+ usedfontsize = fontsize; | |
+ } else { | |
+ result = FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontva… | |
+ if(result == FcResultMatch) { | |
+ usedfontsize = (int)fontval; | |
+ } else { | |
+ /* | |
+ * Default font size is 12, if none given. This is to | |
+ * have a known usedfontsize value. | |
+ */ | |
+ FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); | |
+ usedfontsize = 12; | |
+ } | |
+ } | |
- xinitfont(&dc.font, fontstr); | |
+ if(xloadfont(&dc.font, pattern)) | |
+ die("st: can't open font %s\n", fontstr); | |
+ | |
+ /* Setting character width and height. */ | |
xw.cw = dc.font.width; | |
xw.ch = dc.font.height; | |
- fstr = smstrcat(fontstr, ":weight=bold", NULL); | |
- xinitfont(&dc.bfont, fstr); | |
- free(fstr); | |
+ FcPatternDel(pattern, FC_WEIGHT); | |
+ FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); | |
+ if(xloadfont(&dc.bfont, pattern)) | |
+ die("st: can't open font %s\n", fontstr); | |
- fstr = smstrcat(fontstr, ":slant=italic,oblique", NULL); | |
- xinitfont(&dc.ifont, fstr); | |
- free(fstr); | |
+ FcPatternDel(pattern, FC_SLANT); | |
+ FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); | |
+ if(xloadfont(&dc.ibfont, pattern)) | |
+ die("st: can't open font %s\n", fontstr); | |
- fstr = smstrcat(fontstr, ":weight=bold:slant=italic,oblique", NULL); | |
- xinitfont(&dc.ibfont, fstr); | |
- free(fstr); | |
+ FcPatternDel(pattern, FC_WEIGHT); | |
+ if(xloadfont(&dc.ifont, pattern)) | |
+ die("st: can't open font %s\n", fontstr); | |
+ | |
+ FcPatternDestroy(pattern); | |
+} | |
+ | |
+void | |
+xzoom(const Arg *arg) | |
+{ | |
+ xloadfonts(usedfont, usedfontsize + arg->i); | |
+ cresize(0, 0); | |
+ draw(); | |
} | |
void | |
t@@ -2268,7 +2289,8 @@ xinit(void) { | |
xw.vis = XDefaultVisual(xw.dpy, xw.scr); | |
/* font */ | |
- initfonts((opt_font != NULL)? opt_font : FONT); | |
+ usedfont = (opt_font == NULL)? FONT : opt_font; | |
+ xloadfonts(usedfont, 0); | |
/* colors */ | |
xw.cmap = XDefaultColormap(xw.dpy, xw.scr); | |
t@@ -2604,11 +2626,8 @@ void | |
kpress(XEvent *ev) { | |
XKeyEvent *e = &ev->xkey; | |
KeySym ksym; | |
- char buf[32]; | |
- char *customkey; | |
- int len; | |
- int meta; | |
- int shift; | |
+ char buf[32], *customkey; | |
+ int len, meta, shift, i; | |
Status status; | |
if (IS_SET(MODE_KBDLOCK)) | |
t@@ -2618,7 +2637,17 @@ kpress(XEvent *ev) { | |
shift = e->state & ShiftMask; | |
len = XmbLookupString(xw.xic, e, buf, sizeof(buf), &ksym, &status); | |
- /* 1. custom keys from config.h */ | |
+ /* 1. shortcuts */ | |
+ for(i = 0; i < LEN(shortcuts); i++) { | |
+ if((ksym == shortcuts[i].keysym) | |
+ && (CLEANMASK(shortcuts[i].mod) == \ | |
+ CLEANMASK(e->state)) | |
+ && shortcuts[i].func) { | |
+ shortcuts[i].func(&(shortcuts[i].arg)); | |
+ } | |
+ } | |
+ | |
+ /* 2. custom keys from config.h */ | |
if((customkey = kmap(ksym, e->state))) { | |
ttywrite(customkey, strlen(customkey)); | |
/* 2. hardcoded (overrides X lookup) */ | |
t@@ -2676,14 +2705,15 @@ cmessage(XEvent *e) { | |
} | |
void | |
-resize(XEvent *e) { | |
+cresize(int width, int height) | |
+{ | |
int col, row; | |
- if(e->xconfigure.width == xw.w && e->xconfigure.height == xw.h) | |
- return; | |
+ if(width != 0) | |
+ xw.w = width; | |
+ if(height != 0) | |
+ xw.h = height; | |
- xw.w = e->xconfigure.width; | |
- xw.h = e->xconfigure.height; | |
col = (xw.w - 2*BORDER) / xw.cw; | |
row = (xw.h - 2*BORDER) / xw.ch; | |
if(col == term.col && row == term.row) | |
t@@ -2695,6 +2725,14 @@ resize(XEvent *e) { | |
} | |
void | |
+resize(XEvent *e) { | |
+ if(e->xconfigure.width == xw.w && e->xconfigure.height == xw.h) | |
+ return; | |
+ | |
+ cresize(e->xconfigure.width, e->xconfigure.height); | |
+} | |
+ | |
+void | |
run(void) { | |
XEvent ev; | |
fd_set rfd; |