Adding a more flexible fontstring handling, shortcuts and a zoom function.
This commit is contained in:
		
							
								
								
									
										14
									
								
								config.def.h
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								config.def.h
									
									
									
									
									
								
							| @@ -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" | #define FONT "Liberation Mono:pixelsize=12:antialias=false:autohint=false" | ||||||
|  |  | ||||||
| /* Space in pixels around the terminal buffer */ | /* Space in pixels around the terminal buffer */ | ||||||
| @@ -73,6 +77,15 @@ static Key key[] = { | |||||||
| 	{ XK_F12,       XK_NO_MOD, "\033[24~" }, | 	{ 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 = +1} }, | ||||||
|  | 	{ MODKEY|ShiftMask,	XK_Next,	xzoom,		{.i = -1} }, | ||||||
|  | }; | ||||||
|  |  | ||||||
| /* Set TERM to this */ | /* Set TERM to this */ | ||||||
| #define TNAME "st-256color" | #define TNAME "st-256color" | ||||||
|  |  | ||||||
| @@ -81,3 +94,4 @@ static Key key[] = { | |||||||
| #define TRIPLECLICK_TIMEOUT (2*DOUBLECLICK_TIMEOUT) | #define TRIPLECLICK_TIMEOUT (2*DOUBLECLICK_TIMEOUT) | ||||||
|  |  | ||||||
| #define TAB 8 | #define TAB 8 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -16,8 +16,8 @@ LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lutil -lXext -lXft -lfontconfig | |||||||
|  |  | ||||||
| # flags | # flags | ||||||
| CPPFLAGS = -DVERSION=\"${VERSION}\" | CPPFLAGS = -DVERSION=\"${VERSION}\" | ||||||
| CFLAGS += -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} | CFLAGS += -g -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} | ||||||
| LDFLAGS += -s ${LIBS} | LDFLAGS += -g ${LIBS} | ||||||
|  |  | ||||||
| # compiler and linker | # compiler and linker | ||||||
| CC ?= cc | CC ?= cc | ||||||
|   | |||||||
							
								
								
									
										186
									
								
								st.c
									
									
									
									
									
								
							
							
						
						
									
										186
									
								
								st.c
									
									
									
									
									
								
							| @@ -60,6 +60,8 @@ | |||||||
|  |  | ||||||
| #define REDRAW_TIMEOUT (80*1000) /* 80 ms */ | #define REDRAW_TIMEOUT (80*1000) /* 80 ms */ | ||||||
|  |  | ||||||
|  | /* macros */ | ||||||
|  | #define CLEANMASK(mask) (mask & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) | ||||||
| #define SERRNO strerror(errno) | #define SERRNO strerror(errno) | ||||||
| #define MIN(a, b)  ((a) < (b) ? (a) : (b)) | #define MIN(a, b)  ((a) < (b) ? (a) : (b)) | ||||||
| #define MAX(a, b)  ((a) < (b) ? (b) : (a)) | #define MAX(a, b)  ((a) < (b) ? (b) : (a)) | ||||||
| @@ -238,6 +240,24 @@ typedef struct { | |||||||
| 	struct timeval tclick2; | 	struct timeval tclick2; | ||||||
| } Selection; | } 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" | #include "config.h" | ||||||
|  |  | ||||||
| /* Font structure */ | /* Font structure */ | ||||||
| @@ -321,6 +341,7 @@ static void unmap(XEvent *); | |||||||
| static char *kmap(KeySym, uint); | static char *kmap(KeySym, uint); | ||||||
| static void kpress(XEvent *); | static void kpress(XEvent *); | ||||||
| static void cmessage(XEvent *); | static void cmessage(XEvent *); | ||||||
|  | static void cresize(int width, int height); | ||||||
| static void resize(XEvent *); | static void resize(XEvent *); | ||||||
| static void focus(XEvent *); | static void focus(XEvent *); | ||||||
| static void brelease(XEvent *); | static void brelease(XEvent *); | ||||||
| @@ -345,7 +366,6 @@ static ssize_t xwrite(int, char *, size_t); | |||||||
| static void *xmalloc(size_t); | static void *xmalloc(size_t); | ||||||
| static void *xrealloc(void *, size_t); | static void *xrealloc(void *, size_t); | ||||||
| static void *xcalloc(size_t nmemb, size_t size); | static void *xcalloc(size_t nmemb, size_t size); | ||||||
| static char *smstrcat(char *, ...); |  | ||||||
|  |  | ||||||
| static void (*handler[LASTEvent])(XEvent *) = { | static void (*handler[LASTEvent])(XEvent *) = { | ||||||
| 	[KeyPress] = kpress, | 	[KeyPress] = kpress, | ||||||
| @@ -381,6 +401,8 @@ static char *opt_embed = NULL; | |||||||
| static char *opt_class = NULL; | static char *opt_class = NULL; | ||||||
| static char *opt_font = NULL; | static char *opt_font = NULL; | ||||||
|  |  | ||||||
|  | static char *usedfont = NULL; | ||||||
|  | static int usedfontsize = 0; | ||||||
|  |  | ||||||
| ssize_t | ssize_t | ||||||
| xwrite(int fd, char *s, size_t len) { | xwrite(int fd, char *s, size_t len) { | ||||||
| @@ -424,44 +446,6 @@ xcalloc(size_t nmemb, size_t size) { | |||||||
| 	return p; | 	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 | int | ||||||
| utf8decode(char *s, long *u) { | utf8decode(char *s, long *u) { | ||||||
| 	uchar c; | 	uchar c; | ||||||
| @@ -2107,7 +2091,8 @@ tresize(int col, int row) { | |||||||
| 			*bp = 1; | 			*bp = 1; | ||||||
| 	} | 	} | ||||||
| 	/* update terminal size */ | 	/* update terminal size */ | ||||||
| 	term.col = col, term.row = row; | 	term.col = col; | ||||||
|  | 	term.row = row; | ||||||
| 	/* make use of the LIMIT in tmoveto */ | 	/* make use of the LIMIT in tmoveto */ | ||||||
| 	tmoveto(term.c.x, term.c.y); | 	tmoveto(term.c.x, term.c.y); | ||||||
| 	/* reset scrolling region */ | 	/* reset scrolling region */ | ||||||
| @@ -2207,22 +2192,17 @@ xhints(void) { | |||||||
| 	XFree(sizeh); | 	XFree(sizeh); | ||||||
| } | } | ||||||
|  |  | ||||||
| void | int | ||||||
| xinitfont(Font *f, char *fontstr) { | xloadfont(Font *f, FcPattern *pattern) { | ||||||
| 	FcPattern *pattern, *match; | 	FcPattern *match; | ||||||
| 	FcResult result; | 	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); | 	match = XftFontMatch(xw.dpy, xw.scr, pattern, &result); | ||||||
| 	FcPatternDestroy(pattern); |  | ||||||
| 	if(!match) | 	if(!match) | ||||||
| 		die("st: can't open font %s\n", fontstr); | 		return 1; | ||||||
| 	if(!(f->xft_set = XftFontOpenPattern(xw.dpy, match))) { | 	if(!(f->xft_set = XftFontOpenPattern(xw.dpy, match))) { | ||||||
| 		FcPatternDestroy(match); | 		FcPatternDestroy(match); | ||||||
| 		die("st: can't open font %s.\n", fontstr); | 		return 1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	f->ascent = f->xft_set->ascent; | 	f->ascent = f->xft_set->ascent; | ||||||
| @@ -2232,27 +2212,68 @@ xinitfont(Font *f, char *fontstr) { | |||||||
|  |  | ||||||
| 	f->height = f->xft_set->height; | 	f->height = f->xft_set->height; | ||||||
| 	f->width = f->lbearing + f->rbearing; | 	f->width = f->lbearing + f->rbearing; | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| void | void | ||||||
| initfonts(char *fontstr) { | xloadfonts(char *fontstr, int fontsize) { | ||||||
| 	char *fstr; | 	FcPattern *pattern; | ||||||
|  | 	FcResult result; | ||||||
|  | 	double fontval; | ||||||
|  |  | ||||||
| 	xinitfont(&dc.font, fontstr); | 	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, &fontval); | ||||||
|  | 		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; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	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.cw = dc.font.width; | ||||||
| 	xw.ch = dc.font.height; | 	xw.ch = dc.font.height; | ||||||
|  |  | ||||||
| 	fstr = smstrcat(fontstr, ":weight=bold", NULL); | 	FcPatternDel(pattern, FC_WEIGHT); | ||||||
| 	xinitfont(&dc.bfont, fstr); | 	FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); | ||||||
| 	free(fstr); | 	if(xloadfont(&dc.bfont, pattern)) | ||||||
|  | 		die("st: can't open font %s\n", fontstr); | ||||||
|  |  | ||||||
| 	fstr = smstrcat(fontstr, ":slant=italic,oblique", NULL); | 	FcPatternDel(pattern, FC_SLANT); | ||||||
| 	xinitfont(&dc.ifont, fstr); | 	FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); | ||||||
| 	free(fstr); | 	if(xloadfont(&dc.ibfont, pattern)) | ||||||
|  | 		die("st: can't open font %s\n", fontstr); | ||||||
|  |  | ||||||
| 	fstr = smstrcat(fontstr, ":weight=bold:slant=italic,oblique", NULL); | 	FcPatternDel(pattern, FC_WEIGHT); | ||||||
| 	xinitfont(&dc.ibfont, fstr); | 	if(xloadfont(&dc.ifont, pattern)) | ||||||
| 	free(fstr); | 		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 | void | ||||||
| @@ -2268,7 +2289,8 @@ xinit(void) { | |||||||
| 	xw.vis = XDefaultVisual(xw.dpy, xw.scr); | 	xw.vis = XDefaultVisual(xw.dpy, xw.scr); | ||||||
|  |  | ||||||
| 	/* font */ | 	/* font */ | ||||||
| 	initfonts((opt_font != NULL)? opt_font : FONT); | 	usedfont = (opt_font == NULL)? FONT : opt_font; | ||||||
|  | 	xloadfonts(usedfont, 0); | ||||||
|  |  | ||||||
| 	/* colors */ | 	/* colors */ | ||||||
| 	xw.cmap = XDefaultColormap(xw.dpy, xw.scr); | 	xw.cmap = XDefaultColormap(xw.dpy, xw.scr); | ||||||
| @@ -2604,11 +2626,8 @@ void | |||||||
| kpress(XEvent *ev) { | kpress(XEvent *ev) { | ||||||
| 	XKeyEvent *e = &ev->xkey; | 	XKeyEvent *e = &ev->xkey; | ||||||
| 	KeySym ksym; | 	KeySym ksym; | ||||||
| 	char buf[32]; | 	char buf[32], *customkey; | ||||||
| 	char *customkey; | 	int len, meta, shift, i; | ||||||
| 	int len; |  | ||||||
| 	int meta; |  | ||||||
| 	int shift; |  | ||||||
| 	Status status; | 	Status status; | ||||||
|  |  | ||||||
| 	if (IS_SET(MODE_KBDLOCK)) | 	if (IS_SET(MODE_KBDLOCK)) | ||||||
| @@ -2618,7 +2637,17 @@ kpress(XEvent *ev) { | |||||||
| 	shift = e->state & ShiftMask; | 	shift = e->state & ShiftMask; | ||||||
| 	len = XmbLookupString(xw.xic, e, buf, sizeof(buf), &ksym, &status); | 	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))) { | 	if((customkey = kmap(ksym, e->state))) { | ||||||
| 		ttywrite(customkey, strlen(customkey)); | 		ttywrite(customkey, strlen(customkey)); | ||||||
| 	/* 2. hardcoded (overrides X lookup) */ | 	/* 2. hardcoded (overrides X lookup) */ | ||||||
| @@ -2676,14 +2705,15 @@ cmessage(XEvent *e) { | |||||||
| } | } | ||||||
|  |  | ||||||
| void | void | ||||||
| resize(XEvent *e) { | cresize(int width, int height) | ||||||
|  | { | ||||||
| 	int col, row; | 	int col, row; | ||||||
|  |  | ||||||
| 	if(e->xconfigure.width == xw.w && e->xconfigure.height == xw.h) | 	if(width != 0) | ||||||
| 		return; | 		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; | 	col = (xw.w - 2*BORDER) / xw.cw; | ||||||
| 	row = (xw.h - 2*BORDER) / xw.ch; | 	row = (xw.h - 2*BORDER) / xw.ch; | ||||||
| 	if(col == term.col && row == term.row) | 	if(col == term.col && row == term.row) | ||||||
| @@ -2694,6 +2724,14 @@ resize(XEvent *e) { | |||||||
| 	ttyresize(); | 	ttyresize(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void | ||||||
|  | resize(XEvent *e) { | ||||||
|  | 	if(e->xconfigure.width == xw.w && e->xconfigure.height == xw.h) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	cresize(e->xconfigure.width, e->xconfigure.height); | ||||||
|  | } | ||||||
|  |  | ||||||
| void | void | ||||||
| run(void) { | run(void) { | ||||||
| 	XEvent ev; | 	XEvent ev; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user