import new drw and util from libsl.
This commit is contained in:
		| @ -8,8 +8,10 @@ static char *fontfallbacks[] = { | ||||
| #define NUMFONTSCALES 42 | ||||
| #define FONTSZ(x) ((int)(10.0 * powf(1.1288, (x)))) /* x in [0, NUMFONTSCALES-1] */ | ||||
|  | ||||
| static const char *fgcol = "#000000"; | ||||
| static const char *bgcol = "#FFFFFF"; | ||||
| static const char *colors[] = { | ||||
| 	"#000000", /* foreground color */ | ||||
| 	"#FFFFFF", /* background color */ | ||||
| }; | ||||
|  | ||||
| static const float linespacing = 1.4; | ||||
|  | ||||
|  | ||||
							
								
								
									
										326
									
								
								drw.c
									
									
									
									
									
								
							
							
						
						
									
										326
									
								
								drw.c
									
									
									
									
									
								
							| @ -9,9 +9,7 @@ | ||||
| #include "util.h" | ||||
|  | ||||
| #define UTF_INVALID 0xFFFD | ||||
| #define UTF_SIZ 4 | ||||
|  | ||||
| static void drw_xfont_free(Fnt *font); | ||||
| #define UTF_SIZ     4 | ||||
|  | ||||
| static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80,    0, 0xC0, 0xE0, 0xF0}; | ||||
| static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; | ||||
| @ -19,50 +17,54 @@ static const long utfmin[UTF_SIZ + 1] = {       0,    0,  0x80,  0x800,  0x10000 | ||||
| static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; | ||||
|  | ||||
| static long | ||||
| utf8decodebyte(const char c, size_t *i) { | ||||
| 	for(*i = 0; *i < (UTF_SIZ + 1); ++(*i)) | ||||
| 		if(((unsigned char)c & utfmask[*i]) == utfbyte[*i]) | ||||
| utf8decodebyte(const char c, size_t *i) | ||||
| { | ||||
| 	for (*i = 0; *i < (UTF_SIZ + 1); ++(*i)) | ||||
| 		if (((unsigned char)c & utfmask[*i]) == utfbyte[*i]) | ||||
| 			return (unsigned char)c & ~utfmask[*i]; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static size_t | ||||
| utf8validate(long *u, size_t i) { | ||||
| 	if(!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) | ||||
| utf8validate(long *u, size_t i) | ||||
| { | ||||
| 	if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) | ||||
| 		*u = UTF_INVALID; | ||||
| 	for(i = 1; *u > utfmax[i]; ++i) | ||||
| 	for (i = 1; *u > utfmax[i]; ++i) | ||||
| 		; | ||||
| 	return i; | ||||
| } | ||||
|  | ||||
| static size_t | ||||
| utf8decode(const char *c, long *u, size_t clen) { | ||||
| utf8decode(const char *c, long *u, size_t clen) | ||||
| { | ||||
| 	size_t i, j, len, type; | ||||
| 	long udecoded; | ||||
|  | ||||
| 	*u = UTF_INVALID; | ||||
| 	if(!clen) | ||||
| 	if (!clen) | ||||
| 		return 0; | ||||
| 	udecoded = utf8decodebyte(c[0], &len); | ||||
| 	if(!BETWEEN(len, 1, UTF_SIZ)) | ||||
| 	if (!BETWEEN(len, 1, UTF_SIZ)) | ||||
| 		return 1; | ||||
| 	for(i = 1, j = 1; i < clen && j < len; ++i, ++j) { | ||||
| 	for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { | ||||
| 		udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); | ||||
| 		if(type != 0) | ||||
| 		if (type) | ||||
| 			return j; | ||||
| 	} | ||||
| 	if(j < len) | ||||
| 	if (j < len) | ||||
| 		return 0; | ||||
| 	*u = udecoded; | ||||
| 	utf8validate(u, len); | ||||
|  | ||||
| 	return len; | ||||
| } | ||||
|  | ||||
| Drw * | ||||
| drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) { | ||||
| 	Drw *drw = (Drw *)calloc(1, sizeof(Drw)); | ||||
| 	if(!drw) | ||||
| 		return NULL; | ||||
| drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) | ||||
| { | ||||
| 	Drw *drw = ecalloc(1, sizeof(Drw)); | ||||
|  | ||||
| 	drw->dpy = dpy; | ||||
| 	drw->screen = screen; | ||||
| 	drw->root = root; | ||||
| @ -71,22 +73,26 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h | ||||
| 	drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); | ||||
| 	drw->gc = XCreateGC(dpy, root, 0, NULL); | ||||
| 	XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); | ||||
|  | ||||
| 	return drw; | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_resize(Drw *drw, unsigned int w, unsigned int h) { | ||||
| 	if(!drw) | ||||
| drw_resize(Drw *drw, unsigned int w, unsigned int h) | ||||
| { | ||||
| 	if (!drw) | ||||
| 		return; | ||||
|  | ||||
| 	drw->w = w; | ||||
| 	drw->h = h; | ||||
| 	if(drw->drawable != 0) | ||||
| 	if (drw->drawable) | ||||
| 		XFreePixmap(drw->dpy, drw->drawable); | ||||
| 	drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_free(Drw *drw) { | ||||
| drw_free(Drw *drw) | ||||
| { | ||||
| 	XFreePixmap(drw->dpy, drw->drawable); | ||||
| 	XFreeGC(drw->dpy, drw->gc); | ||||
| 	free(drw); | ||||
| @ -96,119 +102,123 @@ drw_free(Drw *drw) { | ||||
|  * drw_fontset_create instead. | ||||
|  */ | ||||
| static Fnt * | ||||
| drw_font_xcreate(Drw *drw, const char *fontname, FcPattern *fontpattern) { | ||||
| xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) | ||||
| { | ||||
| 	Fnt *font; | ||||
|  | ||||
| 	if (!(fontname || fontpattern)) | ||||
| 		die("No font specified.\n"); | ||||
|  | ||||
| 	if (!(font = (Fnt *)calloc(1, sizeof(Fnt)))) | ||||
| 		return NULL; | ||||
| 	XftFont *xfont = NULL; | ||||
| 	FcPattern *pattern = NULL; | ||||
|  | ||||
| 	if (fontname) { | ||||
| 		/* Using the pattern found at font->xfont->pattern does not yield the | ||||
| 		 * same substitution results as using the pattern returned by | ||||
| 		 * FcNameParse; using the latter results in the desired fallback | ||||
| 		 * behaviour whereas the former just results in | ||||
| 		 * missing-character-rectangles being drawn, at least with some fonts. | ||||
| 		 */ | ||||
| 		if (!(font->xfont = XftFontOpenName(drw->dpy, drw->screen, fontname)) || | ||||
| 		    !(font->pattern = FcNameParse((const FcChar8 *) fontname))) { | ||||
| 			if (font->xfont) { | ||||
| 				XftFontClose(drw->dpy, font->xfont); | ||||
| 				font->xfont = NULL; | ||||
| 			} | ||||
| 			fprintf(stderr, "error, cannot load font: '%s'\n", fontname); | ||||
| 		 * behaviour whereas the former just results in missing-character | ||||
| 		 * rectangles being drawn, at least with some fonts. */ | ||||
| 		if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { | ||||
| 			fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		if (!(pattern = FcNameParse((FcChar8 *) fontname))) { | ||||
| 			fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); | ||||
| 			XftFontClose(drw->dpy, xfont); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 	} else if (fontpattern) { | ||||
| 		if (!(font->xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { | ||||
| 			fprintf(stderr, "error, cannot load font pattern.\n"); | ||||
| 		} else { | ||||
| 			font->pattern = NULL; | ||||
| 		if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { | ||||
| 			fprintf(stderr, "error, cannot load font from pattern.\n"); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 	} else { | ||||
| 		die("no font specified.\n"); | ||||
| 	} | ||||
|  | ||||
| 	if (!font->xfont) { | ||||
| 		free(font); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	font->ascent = font->xfont->ascent; | ||||
| 	font->descent = font->xfont->descent; | ||||
| 	font->h = font->ascent + font->descent; | ||||
| 	font = ecalloc(1, sizeof(Fnt)); | ||||
| 	font->xfont = xfont; | ||||
| 	font->pattern = pattern; | ||||
| 	font->h = xfont->ascent + xfont->descent; | ||||
| 	font->dpy = drw->dpy; | ||||
|  | ||||
| 	return font; | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_xfont_free(Fnt *font) { | ||||
| 	if(!font) | ||||
| static void | ||||
| xfont_free(Fnt *font) | ||||
| { | ||||
| 	if (!font) | ||||
| 		return; | ||||
| 	if(font->pattern) | ||||
| 	if (font->pattern) | ||||
| 		FcPatternDestroy(font->pattern); | ||||
| 	XftFontClose(font->dpy, font->xfont); | ||||
| 	free(font); | ||||
| } | ||||
|  | ||||
| Fnt* | ||||
| drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) { | ||||
| 	Fnt *ret = NULL; | ||||
| 	Fnt *cur = NULL; | ||||
| 	ssize_t i; | ||||
| 	for (i = fontcount - 1; i >= 0; i--) { | ||||
| 		if ((cur = drw_font_xcreate(drw, fonts[i], NULL))) { | ||||
| drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) | ||||
| { | ||||
| 	Fnt *cur, *ret = NULL; | ||||
| 	size_t i; | ||||
|  | ||||
| 	if (!drw || !fonts) | ||||
| 		return NULL; | ||||
|  | ||||
| 	for (i = 1; i <= fontcount; i++) { | ||||
| 		if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { | ||||
| 			cur->next = ret; | ||||
| 			ret = cur; | ||||
| 		} | ||||
| 	} | ||||
| 	return (drw->fonts = ret); | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_fontset_free(Fnt *font) | ||||
| { | ||||
| 	if (font) { | ||||
| 		drw_fontset_free(font->next); | ||||
| 		xfont_free(font); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_clr_create(Drw *drw, Clr *dest, const char *clrname) | ||||
| { | ||||
| 	if (!drw || !dest || !clrname) | ||||
| 		return; | ||||
|  | ||||
| 	if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), | ||||
| 	                       DefaultColormap(drw->dpy, drw->screen), | ||||
| 	                       clrname, dest)) | ||||
| 		die("error, cannot allocate color '%s'\n", clrname); | ||||
| } | ||||
|  | ||||
| /* Wrapper to create color schemes. The caller has to call free(3) on the | ||||
|  * returned color scheme when done using it. */ | ||||
| Clr * | ||||
| drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) | ||||
| { | ||||
| 	size_t i; | ||||
| 	Clr *ret; | ||||
|  | ||||
| 	/* need at least two colors for a scheme */ | ||||
| 	if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) | ||||
| 		return NULL; | ||||
|  | ||||
| 	for (i = 0; i < clrcount; i++) | ||||
| 		drw_clr_create(drw, &ret[i], clrnames[i]); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_fontset_free(Fnt *font) { | ||||
| 	Fnt *nf = font; | ||||
|  | ||||
| 	while ((font = nf)) { | ||||
| 		nf = font->next; | ||||
| 		drw_xfont_free(font); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| Scm * | ||||
| drw_scm_create(Drw *drw, const char *fgname, const char *bgname) { | ||||
| 	Scm *scm; | ||||
| 	Colormap cmap; | ||||
| 	Visual *vis; | ||||
|  | ||||
| 	if (!drw || !(scm = (Scm *)calloc(1, sizeof(Scm)))) | ||||
| 		return NULL; | ||||
|  | ||||
| 	cmap = DefaultColormap(drw->dpy, drw->screen); | ||||
| 	vis = DefaultVisual(drw->dpy, drw->screen); | ||||
| 	if (!XftColorAllocName(drw->dpy, vis, cmap, fgname, &scm->fg.rgb)) | ||||
| 		die("error, cannot allocate color '%s'\n", fgname); | ||||
| 	if (!XftColorAllocName(drw->dpy, vis, cmap, bgname, &scm->bg.rgb)) | ||||
| 		die("error, cannot allocate color '%s'\n", bgname); | ||||
| 	scm->fg.pix = scm->fg.rgb.pixel; | ||||
| 	scm->bg.pix = scm->bg.rgb.pixel; | ||||
| 	return scm; | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_scm_free(Scm *scm) { | ||||
| 	if (scm) | ||||
| 		free(scm); | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_setfontset(Drw *drw, Fnt *set) { | ||||
| drw_setfontset(Drw *drw, Fnt *set) | ||||
| { | ||||
| 	if (drw) | ||||
| 		drw->fonts = set; | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_setscheme(Drw *drw, Scm *scm) { | ||||
| 	if (drw && scm) | ||||
| drw_setscheme(Drw *drw, Clr *scm) | ||||
| { | ||||
| 	if (drw) | ||||
| 		drw->scheme = scm; | ||||
| } | ||||
|  | ||||
| @ -217,24 +227,23 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int | ||||
| { | ||||
| 	if (!drw || !drw->scheme) | ||||
| 		return; | ||||
| 	XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg.pix : drw->scheme->fg.pix); | ||||
| 	XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); | ||||
| 	if (filled) | ||||
| 		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); | ||||
| 	else | ||||
| 		XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); | ||||
| 		XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); | ||||
| } | ||||
|  | ||||
| int | ||||
| drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert) { | ||||
| drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) | ||||
| { | ||||
| 	char buf[1024]; | ||||
| 	int tx, ty, th; | ||||
| 	unsigned int ew = 0; | ||||
| 	Colormap cmap; | ||||
| 	Visual *vis; | ||||
| 	XftDraw *d; | ||||
| 	int ty; | ||||
| 	unsigned int ew; | ||||
| 	XftDraw *d = NULL; | ||||
| 	Fnt *usedfont, *curfont, *nextfont; | ||||
| 	size_t i, len; | ||||
| 	int utf8strlen, utf8charlen, render; | ||||
| 	int utf8strlen, utf8charlen, render = x || y || w || h; | ||||
| 	long utf8codepoint = 0; | ||||
| 	const char *utf8str; | ||||
| 	FcCharSet *fccharset; | ||||
| @ -243,23 +252,19 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex | ||||
| 	XftResult result; | ||||
| 	int charexists = 0; | ||||
|  | ||||
| 	if (!(render = x || y || w || h)) { | ||||
| 	if (!drw || (render && !drw->scheme) || !text || !drw->fonts) | ||||
| 		return 0; | ||||
|  | ||||
| 	if (!render) { | ||||
| 		w = ~w; | ||||
| 	} | ||||
|  | ||||
| 	if (!drw || !drw->scheme) { | ||||
| 		return 0; | ||||
| 	} else if (render) { | ||||
| 		XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->fg.pix : drw->scheme->bg.pix); | ||||
| 	} else { | ||||
| 		XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); | ||||
| 		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); | ||||
| 	} | ||||
|  | ||||
| 	if (!text || !drw->fonts) { | ||||
| 		return 0; | ||||
| 	} else if (render) { | ||||
| 		cmap = DefaultColormap(drw->dpy, drw->screen); | ||||
| 		vis = DefaultVisual(drw->dpy, drw->screen); | ||||
| 		d = XftDrawCreate(drw->dpy, drw->drawable, vis, cmap); | ||||
| 		d = XftDrawCreate(drw->dpy, drw->drawable, | ||||
| 		                  DefaultVisual(drw->dpy, drw->screen), | ||||
| 		                  DefaultColormap(drw->dpy, drw->screen)); | ||||
| 		x += lpad; | ||||
| 		w -= lpad; | ||||
| 	} | ||||
|  | ||||
| 	usedfont = drw->fonts; | ||||
| @ -282,32 +287,30 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if (!charexists || nextfont) { | ||||
| 			if (!charexists || nextfont) | ||||
| 				break; | ||||
| 			} else { | ||||
| 			else | ||||
| 				charexists = 0; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (utf8strlen) { | ||||
| 			drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); | ||||
| 			/* shorten text if necessary */ | ||||
| 			for(len = MIN(utf8strlen, (sizeof buf) - 1); len && (ew > w - drw->fonts->h || w < drw->fonts->h); len--) | ||||
| 			for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) | ||||
| 				drw_font_getexts(usedfont, utf8str, len, &ew, NULL); | ||||
|  | ||||
| 			if (len) { | ||||
| 				memcpy(buf, utf8str, len); | ||||
| 				buf[len] = '\0'; | ||||
| 				if(len < utf8strlen) | ||||
| 					for(i = len; i && i > len - 3; buf[--i] = '.'); | ||||
| 				if (len < utf8strlen) | ||||
| 					for (i = len; i && i > len - 3; buf[--i] = '.') | ||||
| 						; /* NOP */ | ||||
|  | ||||
| 				if (render) { | ||||
| 					th = usedfont->ascent + usedfont->descent; | ||||
| 					ty = y + (h / 2) - (th / 2) + usedfont->ascent; | ||||
| 					tx = x + (h / 2); | ||||
| 					XftDrawStringUtf8(d, invert ? &drw->scheme->bg.rgb : &drw->scheme->fg.rgb, usedfont->xfont, tx, ty, (XftChar8 *)buf, len); | ||||
| 					ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; | ||||
| 					XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], | ||||
| 					                  usedfont->xfont, x, ty, (XftChar8 *)buf, len); | ||||
| 				} | ||||
|  | ||||
| 				x += ew; | ||||
| 				w -= ew; | ||||
| 			} | ||||
| @ -320,18 +323,15 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex | ||||
| 			usedfont = nextfont; | ||||
| 		} else { | ||||
| 			/* Regardless of whether or not a fallback font is found, the | ||||
| 			 * character must be drawn. | ||||
| 			 */ | ||||
| 			 * character must be drawn. */ | ||||
| 			charexists = 1; | ||||
|  | ||||
| 			fccharset = FcCharSetCreate(); | ||||
| 			FcCharSetAddChar(fccharset, utf8codepoint); | ||||
|  | ||||
| 			if (!drw->fonts->pattern) { | ||||
| 				/* Refer to the comment in drw_font_xcreate for more | ||||
| 				 * information. | ||||
| 				 */ | ||||
| 				die("The first font in the cache must be loaded from a font string.\n"); | ||||
| 				/* Refer to the comment in xfont_create for more information. */ | ||||
| 				die("the first font in the cache must be loaded from a font string.\n"); | ||||
| 			} | ||||
|  | ||||
| 			fcpattern = FcPatternDuplicate(drw->fonts->pattern); | ||||
| @ -346,47 +346,50 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex | ||||
| 			FcPatternDestroy(fcpattern); | ||||
|  | ||||
| 			if (match) { | ||||
| 				usedfont = drw_font_xcreate(drw, NULL, match); | ||||
| 				usedfont = xfont_create(drw, NULL, match); | ||||
| 				if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { | ||||
| 					for (curfont = drw->fonts; curfont->next; curfont = curfont->next) | ||||
| 						; /* just find the end of the linked list */ | ||||
| 						; /* NOP */ | ||||
| 					curfont->next = usedfont; | ||||
| 				} else { | ||||
| 					drw_xfont_free(usedfont); | ||||
| 					xfont_free(usedfont); | ||||
| 					usedfont = drw->fonts; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (render) { | ||||
| 	if (d) | ||||
| 		XftDrawDestroy(d); | ||||
| 	} | ||||
|  | ||||
| 	return x; | ||||
| 	return x + (render ? w : 0); | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) { | ||||
| 	if(!drw) | ||||
| drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) | ||||
| { | ||||
| 	if (!drw) | ||||
| 		return; | ||||
|  | ||||
| 	XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); | ||||
| 	XSync(drw->dpy, False); | ||||
| } | ||||
|  | ||||
| unsigned int | ||||
| drw_fontset_getwidth(Drw *drw, const char *text) { | ||||
| drw_fontset_getwidth(Drw *drw, const char *text) | ||||
| { | ||||
| 	if (!drw || !drw->fonts || !text) | ||||
| 		return 0; | ||||
| 	return drw_text(drw, 0, 0, 0, 0, text, 0); | ||||
| 	return drw_text(drw, 0, 0, 0, 0, 0, text, 0); | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) { | ||||
| drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) | ||||
| { | ||||
| 	XGlyphInfo ext; | ||||
|  | ||||
| 	if(!font || !text) | ||||
| 	if (!font || !text) | ||||
| 		return; | ||||
|  | ||||
| 	XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); | ||||
| 	if (w) | ||||
| 		*w = ext.xOff; | ||||
| @ -395,19 +398,24 @@ drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, | ||||
| } | ||||
|  | ||||
| Cur * | ||||
| drw_cur_create(Drw *drw, int shape) { | ||||
| drw_cur_create(Drw *drw, int shape) | ||||
| { | ||||
| 	Cur *cur; | ||||
|  | ||||
| 	if(!drw || !(cur = (Cur *)calloc(1, sizeof(Cur)))) | ||||
| 	if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) | ||||
| 		return NULL; | ||||
|  | ||||
| 	cur->cursor = XCreateFontCursor(drw->dpy, shape); | ||||
|  | ||||
| 	return cur; | ||||
| } | ||||
|  | ||||
| void | ||||
| drw_cur_free(Drw *drw, Cur *cursor) { | ||||
| 	if(!drw || !cursor) | ||||
| drw_cur_free(Drw *drw, Cur *cursor) | ||||
| { | ||||
| 	if (!cursor) | ||||
| 		return; | ||||
|  | ||||
| 	XFreeCursor(drw->dpy, cursor->cursor); | ||||
| 	free(cursor); | ||||
| } | ||||
|  | ||||
							
								
								
									
										28
									
								
								drw.h
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								drw.h
									
									
									
									
									
								
							| @ -1,27 +1,19 @@ | ||||
| /* See LICENSE file for copyright and license details. */ | ||||
| #define DRW_FONT_CACHE_SIZE 32 | ||||
|  | ||||
| typedef struct { | ||||
| 	Cursor cursor; | ||||
| } Cur; | ||||
|  | ||||
| typedef struct Fnt Fnt; | ||||
| struct Fnt { | ||||
| typedef struct Fnt { | ||||
| 	Display *dpy; | ||||
| 	int ascent; | ||||
| 	int descent; | ||||
| 	unsigned int h; | ||||
| 	XftFont *xfont; | ||||
| 	FcPattern *pattern; | ||||
| 	Fnt *next; | ||||
| }; | ||||
| 	struct Fnt *next; | ||||
| } Fnt; | ||||
|  | ||||
| typedef struct { | ||||
| 	struct { | ||||
| 		unsigned long pix; | ||||
| 		XftColor rgb; | ||||
| 	} fg, bg; | ||||
| } Scm; | ||||
| enum { ColFg, ColBg }; /* Clr scheme index */ | ||||
| typedef XftColor Clr; | ||||
|  | ||||
| typedef struct { | ||||
| 	unsigned int w, h; | ||||
| @ -30,7 +22,7 @@ typedef struct { | ||||
| 	Window root; | ||||
| 	Drawable drawable; | ||||
| 	GC gc; | ||||
| 	Scm *scheme; | ||||
| 	Clr *scheme; | ||||
| 	Fnt *fonts; | ||||
| } Drw; | ||||
|  | ||||
| @ -46,8 +38,8 @@ unsigned int drw_fontset_getwidth(Drw *drw, const char *text); | ||||
| void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); | ||||
|  | ||||
| /* Colorscheme abstraction */ | ||||
| Scm *drw_scm_create(Drw *drw, const char *fgname, const char *bgname); | ||||
| void drw_scm_free(Scm *scm); | ||||
| void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); | ||||
| Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); | ||||
|  | ||||
| /* Cursor abstraction */ | ||||
| Cur *drw_cur_create(Drw *drw, int shape); | ||||
| @ -55,11 +47,11 @@ void drw_cur_free(Drw *drw, Cur *cursor); | ||||
|  | ||||
| /* Drawing context manipulation */ | ||||
| void drw_setfontset(Drw *drw, Fnt *set); | ||||
| void drw_setscheme(Drw *drw, Scm *scm); | ||||
| void drw_setscheme(Drw *drw, Clr *scm); | ||||
|  | ||||
| /* Drawing functions */ | ||||
| void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); | ||||
| int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert); | ||||
| int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); | ||||
|  | ||||
| /* Map functions */ | ||||
| void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); | ||||
|  | ||||
							
								
								
									
										85
									
								
								sent.c
									
									
									
									
									
								
							
							
						
						
									
										85
									
								
								sent.c
									
									
									
									
									
								
							| @ -20,6 +20,7 @@ | ||||
| #include <X11/Xft/Xft.h> | ||||
|  | ||||
| #include "arg.h" | ||||
| #include "util.h" | ||||
| #include "drw.h" | ||||
|  | ||||
| char *argv0; | ||||
| @ -96,7 +97,6 @@ static void ffdraw(Image *img); | ||||
|  | ||||
| static void getfontsize(Slide *s, unsigned int *width, unsigned int *height); | ||||
| static void cleanup(); | ||||
| static void die(const char *, ...); | ||||
| static void load(FILE *fp); | ||||
| static void advance(const Arg *arg); | ||||
| static void quit(const Arg *arg); | ||||
| @ -123,7 +123,7 @@ static int idx = 0; | ||||
| static int slidecount = 0; | ||||
| static XWindow xw; | ||||
| static Drw *d = NULL; | ||||
| static Scm *sc; | ||||
| static Clr *sc; | ||||
| static Fnt *fonts[NUMFONTSCALES]; | ||||
| static int running = 1; | ||||
|  | ||||
| @ -141,18 +141,18 @@ filter(int fd, const char *cmd) | ||||
| 	int fds[2]; | ||||
|  | ||||
| 	if (pipe(fds) < 0) | ||||
| 		die("Unable to create pipe:"); | ||||
| 		die("sent: Unable to create pipe:"); | ||||
|  | ||||
| 	switch (fork()) { | ||||
| 	case -1: | ||||
| 		die("Unable to fork:"); | ||||
| 		die("sent: Unable to fork:"); | ||||
| 	case 0: | ||||
| 		dup2(fd, 0); | ||||
| 		dup2(fds[1], 1); | ||||
| 		close(fds[0]); | ||||
| 		close(fds[1]); | ||||
| 		execlp("sh", "sh", "-c", cmd, (char *)0); | ||||
| 		die("execlp sh -c '%s':", cmd); | ||||
| 		die("sent: execlp sh -c '%s':", cmd); | ||||
| 	} | ||||
| 	close(fds[1]); | ||||
| 	return fds[0]; | ||||
| @ -182,13 +182,13 @@ ffopen(char *filename) | ||||
| 		return NULL; | ||||
|  | ||||
| 	if ((fd = open(filename, O_RDONLY)) < 0) { | ||||
| 		die("Unable to open file %s:", filename); | ||||
| 		die("sent: Unable to open file %s:", filename); | ||||
| 	} | ||||
|  | ||||
| 	tmpfd = fd; | ||||
| 	fd = filter(fd, bin); | ||||
| 	if (fd < 0) | ||||
| 		die("Unable to filter %s:", filename); | ||||
| 		die("sent: Unable to filter %s:", filename); | ||||
| 	close(tmpfd); | ||||
|  | ||||
| 	if (read(fd, hdr, 16) != 16) | ||||
| @ -231,26 +231,26 @@ ffread(Image *img) | ||||
| 		free(img->buf); | ||||
| 	/* internally the image is stored in 888 format */ | ||||
| 	if (!(img->buf = malloc(3 * img->bufwidth * img->bufheight))) | ||||
| 		die("Unable to malloc buffer for image."); | ||||
| 		die("sent: Unable to malloc buffer for image.\n"); | ||||
|  | ||||
| 	/* scratch buffer to read row by row */ | ||||
| 	rowlen = img->bufwidth * 2 * strlen("RGBA"); | ||||
| 	row = malloc(rowlen); | ||||
| 	if (!row) { | ||||
| 		die("Unable to malloc buffer for image row."); | ||||
| 		die("sent: Unable to malloc buffer for image row.\n"); | ||||
| 	} | ||||
|  | ||||
| 	/* extract window background color channels for transparency */ | ||||
| 	bg_r = (sc->bg.pix >> 16) % 256; | ||||
| 	bg_g = (sc->bg.pix >>  8) % 256; | ||||
| 	bg_b = (sc->bg.pix >>  0) % 256; | ||||
| 	bg_r = (sc[ColBg].pixel >> 16) % 256; | ||||
| 	bg_g = (sc[ColBg].pixel >>  8) % 256; | ||||
| 	bg_b = (sc[ColBg].pixel >>  0) % 256; | ||||
|  | ||||
| 	for (off = 0, y = 0; y < img->bufheight; y++) { | ||||
| 		nbytes = 0; | ||||
| 		while (nbytes < rowlen) { | ||||
| 			count = read(img->fd, (char *)row + nbytes, rowlen - nbytes); | ||||
| 			if (count < 0) | ||||
| 				die("Unable to read from pipe:"); | ||||
| 				die("sent: Unable to read from pipe:"); | ||||
| 			nbytes += count; | ||||
| 		} | ||||
| 		for (x = 0; x < rowlen / 2; x += 4) { | ||||
| @ -284,17 +284,17 @@ ffprepare(Image *img) | ||||
| 		height = img->bufheight * xw.uw / img->bufwidth; | ||||
|  | ||||
| 	if (depth < 24) | ||||
| 		die("Display depths <24 not supported."); | ||||
| 		die("sent: Display depths <24 not supported.\n"); | ||||
|  | ||||
| 	if (!(img->ximg = XCreateImage(xw.dpy, CopyFromParent, depth, ZPixmap, 0, | ||||
| 	                               NULL, width, height, 32, 0))) | ||||
| 		die("Unable to create XImage."); | ||||
| 		die("sent: Unable to create XImage.\n"); | ||||
|  | ||||
| 	if (!(img->ximg->data = malloc(img->ximg->bytes_per_line * height))) | ||||
| 		die("Unable to alloc data section for XImage."); | ||||
| 		die("sent: Unable to alloc data section for XImage.\n"); | ||||
|  | ||||
| 	if (!XInitImage(img->ximg)) | ||||
| 		die("Unable to init XImage."); | ||||
| 		die("sent: Unable to init XImage.\n"); | ||||
|  | ||||
| 	ffscale(img); | ||||
| 	img->state |= SCALED; | ||||
| @ -364,7 +364,6 @@ getfontsize(Slide *s, unsigned int *width, unsigned int *height) | ||||
| 			*width = curw; | ||||
| 	} | ||||
| 	*height = fonts[j]->h * lfac; | ||||
| 	*width += fonts[j]->h; | ||||
| } | ||||
|  | ||||
| void | ||||
| @ -374,7 +373,7 @@ cleanup() | ||||
|  | ||||
| 	for (i = 0; i < NUMFONTSCALES; i++) | ||||
| 		drw_fontset_free(fonts[i]); | ||||
| 	drw_scm_free(sc); | ||||
| 	free(sc); | ||||
| 	drw_free(d); | ||||
|  | ||||
| 	XDestroyWindow(xw.dpy, xw.win); | ||||
| @ -393,27 +392,6 @@ cleanup() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void | ||||
| die(const char *fmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
|  | ||||
| 	fputs("sent: ", stderr); | ||||
|  | ||||
| 	va_start(ap, fmt); | ||||
| 	vfprintf(stderr, fmt, ap); | ||||
| 	va_end(ap); | ||||
|  | ||||
| 	if (fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') { | ||||
| 		fputc(' ', stderr); | ||||
| 		perror(NULL); | ||||
| 	} else { | ||||
| 		fputc('\n', stderr); | ||||
| 	} | ||||
|  | ||||
| 	exit(1); | ||||
| } | ||||
|  | ||||
| void | ||||
| load(FILE *fp) | ||||
| { | ||||
| @ -433,7 +411,7 @@ load(FILE *fp) | ||||
|  | ||||
| 		if ((slidecount+1) * sizeof(*slides) >= size) | ||||
| 			if (!(slides = realloc(slides, (size += BUFSIZ)))) | ||||
| 				die("Unable to realloc %u bytes:", size); | ||||
| 				die("sent: Unable to realloc %u bytes:", size); | ||||
|  | ||||
| 		/* read one slide */ | ||||
| 		maxlines = 0; | ||||
| @ -446,12 +424,12 @@ load(FILE *fp) | ||||
| 			if (s->linecount >= maxlines) { | ||||
| 				maxlines = 2 * s->linecount + 1; | ||||
| 				if (!(s->lines = realloc(s->lines, maxlines * sizeof(s->lines[0])))) | ||||
| 					die("Unable to realloc %u bytes:", maxlines * sizeof(s->lines[0])); | ||||
| 					die("sent: Unable to realloc %u bytes:", maxlines * sizeof(s->lines[0])); | ||||
| 			} | ||||
|  | ||||
| 			blen = strlen(buf); | ||||
| 			if (!(s->lines[s->linecount] = strdup(buf))) | ||||
| 				die("Unable to strdup:"); | ||||
| 				die("sent: Unable to strdup:"); | ||||
| 			if (s->lines[s->linecount][blen-1] == '\n') | ||||
| 				s->lines[s->linecount][blen-1] = '\0'; | ||||
|  | ||||
| @ -543,6 +521,7 @@ xdraw() | ||||
| 			         (xw.h - height) / 2 + i * linespacing * d->fonts->h, | ||||
| 			         width, | ||||
| 			         d->fonts->h, | ||||
| 			         0, | ||||
| 			         slides[idx].lines[i], | ||||
| 			         0); | ||||
| 		drw_map(d, xw.win, 0, 0, xw.w, xw.h); | ||||
| @ -564,7 +543,7 @@ xhints() | ||||
| 	XSizeHints *sizeh = NULL; | ||||
|  | ||||
| 	if (!(sizeh = XAllocSizeHints())) | ||||
| 		die("Unable to alloc size hints."); | ||||
| 		die("sent: Unable to alloc size hints.\n"); | ||||
|  | ||||
| 	sizeh->flags = PSize; | ||||
| 	sizeh->height = xw.h; | ||||
| @ -580,7 +559,7 @@ xinit() | ||||
| 	XTextProperty prop; | ||||
|  | ||||
| 	if (!(xw.dpy = XOpenDisplay(NULL))) | ||||
| 		die("Unable to open display."); | ||||
| 		die("sent: Unable to open display.\n"); | ||||
| 	xw.scr = XDefaultScreen(xw.dpy); | ||||
| 	xw.vis = XDefaultVisual(xw.dpy, xw.scr); | ||||
| 	resize(DisplayWidth(xw.dpy, xw.scr), DisplayHeight(xw.dpy, xw.scr)); | ||||
| @ -599,10 +578,10 @@ xinit() | ||||
| 	XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); | ||||
|  | ||||
| 	if (!(d = drw_create(xw.dpy, xw.scr, xw.win, xw.w, xw.h))) | ||||
| 		die("Unable to create drawing context."); | ||||
| 	sc = drw_scm_create(d, fgcol, bgcol); | ||||
| 		die("sent: Unable to create drawing context.\n"); | ||||
| 	sc = drw_scm_create(d, colors, 2); | ||||
| 	drw_setscheme(d, sc); | ||||
| 	XSetWindowBackground(xw.dpy, xw.win, sc->bg.pix); | ||||
| 	XSetWindowBackground(xw.dpy, xw.win, sc[ColBg].pixel); | ||||
|  | ||||
| 	xloadfonts(); | ||||
|  | ||||
| @ -623,16 +602,16 @@ xloadfonts() | ||||
|  | ||||
| 	for (j = 0; j < LEN(fontfallbacks); j++) { | ||||
| 		if (!(fstrs[j] = malloc(MAXFONTSTRLEN))) | ||||
| 			die("Unable to malloc fstrs."); | ||||
| 			die("sent: Unable to malloc fstrs.\n"); | ||||
| 	} | ||||
|  | ||||
| 	for (i = 0; i < NUMFONTSCALES; i++) { | ||||
| 		for (j = 0; j < LEN(fontfallbacks); j++) { | ||||
| 			if (MAXFONTSTRLEN < snprintf(fstrs[j], MAXFONTSTRLEN, "%s:size=%d", fontfallbacks[j], FONTSZ(i))) | ||||
| 				die("Font string too long."); | ||||
| 				die("sent: Font string too long.\n"); | ||||
| 		} | ||||
| 		if (!(fonts[i] = drw_fontset_create(d, (const char**)fstrs, LEN(fstrs)))) | ||||
| 			die("Unable to load any font for size %d.", FONTSZ(i)); | ||||
| 			die("sent: Unable to load any font for size %d.\n", FONTSZ(i)); | ||||
| 	} | ||||
|  | ||||
| 	for (j = 0; j < LEN(fontfallbacks); j++) | ||||
| @ -689,7 +668,7 @@ void | ||||
| usage() | ||||
| { | ||||
| 	die("sent " VERSION " (c) 2014-2015 markus.teich@stusta.mhn.de\n" \ | ||||
| 	"usage: sent [FILE]", argv0); | ||||
| 	"usage: sent [FILE]\n", argv0); | ||||
| } | ||||
|  | ||||
| int | ||||
| @ -706,7 +685,7 @@ main(int argc, char *argv[]) | ||||
| 	if (!argv[0] || !strcmp(argv[0], "-")) | ||||
| 		fp = stdin; | ||||
| 	else if (!(fp = fopen(argv[0], "r"))) | ||||
| 		die("Unable to open '%s' for reading:", argv[0]); | ||||
| 		die("sent: Unable to open '%s' for reading:", argv[0]); | ||||
|  | ||||
| 	load(fp); | ||||
| 	fclose(fp); | ||||
|  | ||||
							
								
								
									
										30
									
								
								util.c
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								util.c
									
									
									
									
									
								
							| @ -2,16 +2,32 @@ | ||||
| #include <stdarg.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "util.h" | ||||
|  | ||||
| void | ||||
| die(const char *errstr, ...) { | ||||
| 	va_list ap; | ||||
| void * | ||||
| ecalloc(size_t nmemb, size_t size) | ||||
| { | ||||
| 	void *p; | ||||
|  | ||||
| 	va_start(ap, errstr); | ||||
| 	vfprintf(stderr, errstr, ap); | ||||
| 	va_end(ap); | ||||
| 	exit(1); | ||||
| 	if (!(p = calloc(nmemb, size))) | ||||
| 		perror(NULL); | ||||
| 	return p; | ||||
| } | ||||
|  | ||||
| void | ||||
| die(const char *fmt, ...) { | ||||
| 	va_list ap; | ||||
|  | ||||
| 	va_start(ap, fmt); | ||||
| 	vfprintf(stderr, fmt, ap); | ||||
| 	va_end(ap); | ||||
|  | ||||
| 	if (fmt[0] && fmt[strlen(fmt)-1] == ':') { | ||||
| 		fputc(' ', stderr); | ||||
| 		perror(NULL); | ||||
| 	} | ||||
|  | ||||
| 	exit(1); | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user