Merge branch 'userinfo'
This commit is contained in:
		
						commit
						aa6ccf42b8
					
				
							
								
								
									
										8
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								Makefile
									
									
									
									
									
								
							| @ -1,4 +1,4 @@ | |||||||
| VERSION = git-20130112 | VERSION = git-20130127 | ||||||
| 
 | 
 | ||||||
| PREFIX    = /usr/local | PREFIX    = /usr/local | ||||||
| MANPREFIX = $(PREFIX)/share/man | MANPREFIX = $(PREFIX)/share/man | ||||||
| @ -32,9 +32,13 @@ install: all | |||||||
| 	cp sxiv $(DESTDIR)$(PREFIX)/bin/ | 	cp sxiv $(DESTDIR)$(PREFIX)/bin/ | ||||||
| 	chmod 755 $(DESTDIR)$(PREFIX)/bin/sxiv | 	chmod 755 $(DESTDIR)$(PREFIX)/bin/sxiv | ||||||
| 	mkdir -p $(DESTDIR)$(MANPREFIX)/man1 | 	mkdir -p $(DESTDIR)$(MANPREFIX)/man1 | ||||||
| 	sed "s/VERSION/$(VERSION)/g" sxiv.1 > $(DESTDIR)$(MANPREFIX)/man1/sxiv.1 | 	sed "s!PREFIX!$(PREFIX)!g; s!VERSION!$(VERSION)!g" sxiv.1 > $(DESTDIR)$(MANPREFIX)/man1/sxiv.1 | ||||||
| 	chmod 644 $(DESTDIR)$(MANPREFIX)/man1/sxiv.1 | 	chmod 644 $(DESTDIR)$(MANPREFIX)/man1/sxiv.1 | ||||||
|  | 	mkdir -p $(DESTDIR)$(PREFIX)/share/sxiv/exec | ||||||
|  | 	cp image-info $(DESTDIR)$(PREFIX)/share/sxiv/exec/image-info | ||||||
|  | 	chmod 755 $(DESTDIR)$(PREFIX)/share/sxiv/exec/image-info | ||||||
| 
 | 
 | ||||||
| uninstall: | uninstall: | ||||||
| 	rm -f $(DESTDIR)$(PREFIX)/bin/sxiv | 	rm -f $(DESTDIR)$(PREFIX)/bin/sxiv | ||||||
| 	rm -f $(DESTDIR)$(MANPREFIX)/man1/sxiv.1 | 	rm -f $(DESTDIR)$(MANPREFIX)/man1/sxiv.1 | ||||||
|  | 	rm -rf $(DESTDIR)$(PREFIX)/share/sxiv | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| sxiv | sxiv | ||||||
| ==== | ==== | ||||||
| 
 | 
 | ||||||
| **Simple (or small or suckless) X Image Viewer** | **Simple X Image Viewer** | ||||||
| 
 | 
 | ||||||
| sxiv is an alternative to feh and qiv. Its only dependencies besides xlib are | sxiv is an alternative to feh and qiv. Its only dependencies besides xlib are | ||||||
| imlib2 and giflib. The primary goal for writing sxiv is to create an image | imlib2 and giflib. The primary goal for writing sxiv is to create an image | ||||||
| @ -20,7 +20,7 @@ Features | |||||||
| * Ability to cache thumbnails for fast re-loading | * Ability to cache thumbnails for fast re-loading | ||||||
| * Basic support for multi-frame images | * Basic support for multi-frame images | ||||||
| * Load all frames from GIF files and play GIF animations | * Load all frames from GIF files and play GIF animations | ||||||
| * Display image information in window title | * Display image information in status bar | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| Screenshots | Screenshots | ||||||
|  | |||||||
							
								
								
									
										17
									
								
								image-info
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								image-info
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | #!/bin/sh | ||||||
|  | 
 | ||||||
|  | # Example for ~/.sxiv/exec/image-info | ||||||
|  | # Called by sxiv(1) whenever an image gets loaded, | ||||||
|  | # with the name of the image file as its first argument. | ||||||
|  | # The output is displayed in sxiv's status bar. | ||||||
|  | 
 | ||||||
|  | filename=$(basename "$1") | ||||||
|  | filesize=$(du -h "$1" | cut -f 1) | ||||||
|  | 
 | ||||||
|  | geometry=$(identify -format '%wx%h' "$1") | ||||||
|  | 
 | ||||||
|  | tags=$(exiv2 -q pr -pi "$1" | awk '$1~"Keywords" { printf("%s,", $4); }') | ||||||
|  | tags=${tags:+|}${tags%,} | ||||||
|  | 
 | ||||||
|  | echo "[$filesize|$geometry$tags] $filename" | ||||||
|  | 
 | ||||||
							
								
								
									
										149
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										149
									
								
								main.c
									
									
									
									
									
								
							| @ -39,8 +39,10 @@ | |||||||
| #include "config.h" | #include "config.h" | ||||||
| 
 | 
 | ||||||
| enum { | enum { | ||||||
| 	INFO_STR_LEN = 256, | 	BAR_L_LEN    = 512, | ||||||
| 	FILENAME_CNT = 1024 | 	BAR_R_LEN    = 64, | ||||||
|  | 	FILENAME_CNT = 1024, | ||||||
|  | 	TITLE_LEN    = 256 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
| @ -63,15 +65,18 @@ win_t win; | |||||||
| fileinfo_t *files; | fileinfo_t *files; | ||||||
| int filecnt, fileidx; | int filecnt, fileidx; | ||||||
| int alternate; | int alternate; | ||||||
| size_t filesize; |  | ||||||
| 
 | 
 | ||||||
| int prefix; | int prefix; | ||||||
| 
 | 
 | ||||||
| bool resized = false; | bool resized = false; | ||||||
| 
 | 
 | ||||||
| char win_bar_l[INFO_STR_LEN]; | const char * const INFO_SCRIPT = ".sxiv/exec/image-info"; | ||||||
| char win_bar_r[INFO_STR_LEN]; | char *info_script; | ||||||
| char win_title[INFO_STR_LEN]; | 
 | ||||||
|  | struct { | ||||||
|  | 	char l[BAR_L_LEN]; | ||||||
|  | 	char r[BAR_R_LEN]; | ||||||
|  | } bar; | ||||||
| 
 | 
 | ||||||
| timeout_t timeouts[] = { | timeout_t timeouts[] = { | ||||||
| 	{ { 0, 0 }, false, redraw }, | 	{ { 0, 0 }, false, redraw }, | ||||||
| @ -202,9 +207,37 @@ bool check_timeouts(struct timeval *t) { | |||||||
| 	return tmin > 0; | 	return tmin > 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void load_image(int new) { | void read_info(void) { | ||||||
| 	struct stat fstats; | 	char cmd[4096]; | ||||||
|  | 	FILE *outp; | ||||||
|  | 	int c, i = 0, n = sizeof(bar.l) - 1; | ||||||
|  | 	bool lastsep = false; | ||||||
| 	 | 	 | ||||||
|  | 	if (info_script != NULL) { | ||||||
|  | 		snprintf(cmd, sizeof(cmd), "%s \"%s\"", info_script, files[fileidx].name); | ||||||
|  | 		outp = popen(cmd, "r"); | ||||||
|  | 		if (outp == NULL) | ||||||
|  | 			goto end; | ||||||
|  | 		while (i < n && (c = fgetc(outp)) != EOF) { | ||||||
|  | 			if (c == '\n') { | ||||||
|  | 				if (!lastsep) { | ||||||
|  | 					bar.l[i++] = ' '; | ||||||
|  | 					lastsep = true; | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				bar.l[i++] = c; | ||||||
|  | 				lastsep = false; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		pclose(outp); | ||||||
|  | 	} | ||||||
|  | end: | ||||||
|  | 	if (lastsep) | ||||||
|  | 		i--; | ||||||
|  | 	bar.l[i] = '\0'; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void load_image(int new) { | ||||||
| 	if (new < 0 || new >= filecnt) | 	if (new < 0 || new >= filecnt) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| @ -220,10 +253,8 @@ void load_image(int new) { | |||||||
| 	files[new].loaded = true; | 	files[new].loaded = true; | ||||||
| 	alternate = fileidx; | 	alternate = fileidx; | ||||||
| 	fileidx = new; | 	fileidx = new; | ||||||
| 	if (stat(files[new].path, &fstats) == 0) | 
 | ||||||
| 		filesize = fstats.st_size; | 	read_info(); | ||||||
| 	else |  | ||||||
| 		filesize = 0; |  | ||||||
| 
 | 
 | ||||||
| 	if (img.multi.cnt > 0 && img.multi.animate) | 	if (img.multi.cnt > 0 && img.multi.animate) | ||||||
| 		set_timeout(animate, img.multi.frames[img.multi.sel].delay, true); | 		set_timeout(animate, img.multi.frames[img.multi.sel].delay, true); | ||||||
| @ -232,60 +263,51 @@ void load_image(int new) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void update_info(void) { | void update_info(void) { | ||||||
| 	int i, fw, pw, fi, ln, rn; | 	unsigned int i, fn, fw, n, len = sizeof(bar.r); | ||||||
| 	char frame_info[16]; | 	int sel; | ||||||
| 	const char *size_unit; | 	char *t = bar.r, title[TITLE_LEN]; | ||||||
| 	float size = filesize; | 	bool ow_info; | ||||||
| 
 | 
 | ||||||
| 	pw = 0; | 	for (fw = 0, i = filecnt; i > 0; fw++, i /= 10); | ||||||
| 	for (i = filecnt; i > 0; i /= 10) | 	sel = mode == MODE_IMAGE ? fileidx : tns.sel; | ||||||
| 		pw++; |  | ||||||
| 
 | 
 | ||||||
| 	if (mode == MODE_THUMB) { | 	if (mode == MODE_THUMB) { | ||||||
| 		if (tns.cnt != filecnt) { |  | ||||||
| 			snprintf(win_bar_l, sizeof win_bar_l, "Loading... %0*d/%d", |  | ||||||
| 			         pw, tns.cnt, filecnt); |  | ||||||
| 		} else { |  | ||||||
| 			fi = snprintf(win_bar_l, sizeof win_bar_l, "%0*d/%d%s", |  | ||||||
| 			              pw, tns.sel + 1, filecnt, BAR_SEPARATOR); |  | ||||||
| 			ln = snprintf(win_bar_l + fi, sizeof win_bar_l - fi, "%s", |  | ||||||
| 			              files[tns.sel].name) + fi; |  | ||||||
| 			if (win_textwidth(win_bar_l, ln, true) > win.w) |  | ||||||
| 				snprintf(win_bar_l + fi, sizeof win_bar_l - fi, "%s", |  | ||||||
| 				         files[tns.sel].base); |  | ||||||
| 		} |  | ||||||
| 		win_set_title(&win, "sxiv"); | 		win_set_title(&win, "sxiv"); | ||||||
| 		win_set_bar_info(&win, win_bar_l, NULL); | 
 | ||||||
| 	} else { | 		if (tns.cnt == filecnt) { | ||||||
| 		size_readable(&size, &size_unit); | 			n = snprintf(t, len, "%0*d/%d", fw, sel + 1, filecnt); | ||||||
| 		if (img.multi.cnt > 0) { | 			ow_info = true; | ||||||
| 			fw = 0; |  | ||||||
| 			for (i = img.multi.cnt; i > 0; i /= 10) |  | ||||||
| 				fw++; |  | ||||||
| 			snprintf(frame_info, sizeof frame_info, "%s%0*d/%d", |  | ||||||
| 			         BAR_SEPARATOR, fw, img.multi.sel+1, img.multi.cnt); |  | ||||||
| 		} else { | 		} else { | ||||||
| 			frame_info[0] = '\0'; | 			snprintf(bar.l, sizeof(bar.l), "Loading... %0*d/%d", | ||||||
|  | 			         fw, tns.cnt, filecnt); | ||||||
|  | 			bar.r[0] = '\0'; | ||||||
|  | 			ow_info = false; | ||||||
| 		} | 		} | ||||||
| 		fi = snprintf(win_bar_l, sizeof win_bar_l, "%0*d/%d%s", | 	} else { | ||||||
| 		              pw, fileidx + 1, filecnt, BAR_SEPARATOR); | 		snprintf(title, sizeof(title), "sxiv - %s", files[sel].name); | ||||||
| 		ln = snprintf(win_bar_l + fi, sizeof win_bar_l - fi, "%s", | 		win_set_title(&win, title); | ||||||
| 		              files[fileidx].name) + fi; |  | ||||||
| 		rn = snprintf(win_bar_r, sizeof win_bar_r, "%.2f%s%s%dx%d%s%3d%%%s", |  | ||||||
| 		              size, size_unit, BAR_SEPARATOR, img.w, img.h, BAR_SEPARATOR, |  | ||||||
| 		              (int) (img.zoom * 100.0), frame_info); |  | ||||||
| 
 | 
 | ||||||
| 		if (win_textwidth(win_bar_l, ln, true) + | 		n = snprintf(t, len, "%3d%% ", (int) (img.zoom * 100.0)); | ||||||
| 		    win_textwidth(win_bar_r, rn, true) > win.w) | 		if (img.multi.cnt > 0) { | ||||||
| 		{ | 			for (fn = 0, i = img.multi.cnt; i > 0; fn++, i /= 10); | ||||||
| 			snprintf(win_bar_l + fi, sizeof win_bar_l - fi, "%s", | 			n += snprintf(t + n, len - n, "(%0*d/%d) ", | ||||||
| 			         files[fileidx].base); | 			              fn, img.multi.sel + 1, img.multi.cnt); | ||||||
| 		} | 		} | ||||||
| 		win_set_bar_info(&win, win_bar_l, win_bar_r); | 		n += snprintf(t + n, len - n, "%0*d/%d", fw, sel + 1, filecnt); | ||||||
| 
 | 		ow_info = bar.l[0] == '\0'; | ||||||
| 		snprintf(win_title, sizeof win_title, "sxiv - %s", files[fileidx].name); |  | ||||||
| 		win_set_title(&win, win_title); |  | ||||||
| 	} | 	} | ||||||
|  | 	if (ow_info) { | ||||||
|  | 		fn = strlen(files[sel].name); | ||||||
|  | 		if (fn < sizeof(bar.l) && | ||||||
|  | 		    win_textwidth(files[sel].name, fn, true) + | ||||||
|  | 		    win_textwidth(bar.r, n, true) < win.w) | ||||||
|  | 		{ | ||||||
|  | 			strncpy(bar.l, files[sel].name, sizeof(bar.l)); | ||||||
|  | 		} else { | ||||||
|  | 			strncpy(bar.l, files[sel].base, sizeof(bar.l)); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	win_set_bar_info(&win, bar.l, bar.r); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void redraw(void) { | void redraw(void) { | ||||||
| @ -519,6 +541,7 @@ int main(int argc, char **argv) { | |||||||
| 	size_t n; | 	size_t n; | ||||||
| 	ssize_t len; | 	ssize_t len; | ||||||
| 	char *filename; | 	char *filename; | ||||||
|  | 	const char *homedir; | ||||||
| 	struct stat fstats; | 	struct stat fstats; | ||||||
| 	r_dir_t dir; | 	r_dir_t dir; | ||||||
| 
 | 
 | ||||||
| @ -595,6 +618,18 @@ int main(int argc, char **argv) { | |||||||
| 	win_init(&win); | 	win_init(&win); | ||||||
| 	img_init(&img, &win); | 	img_init(&img, &win); | ||||||
| 
 | 
 | ||||||
|  | 	if ((homedir = getenv("HOME")) == NULL) { | ||||||
|  | 		warn("could not locate home directory"); | ||||||
|  | 	} else { | ||||||
|  | 		len = strlen(homedir) + strlen(INFO_SCRIPT) + 2; | ||||||
|  | 		info_script = (char*) s_malloc(len); | ||||||
|  | 		snprintf(info_script, len, "%s/%s", homedir, INFO_SCRIPT); | ||||||
|  | 		if (access(info_script, X_OK) != 0) { | ||||||
|  | 			free(info_script); | ||||||
|  | 			info_script = NULL; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if (options->thumb_mode) { | 	if (options->thumb_mode) { | ||||||
| 		mode = MODE_THUMB; | 		mode = MODE_THUMB; | ||||||
| 		tns_init(&tns, filecnt, &win); | 		tns_init(&tns, filecnt, &win); | ||||||
|  | |||||||
							
								
								
									
										30
									
								
								sxiv.1
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								sxiv.1
									
									
									
									
									
								
							| @ -1,6 +1,6 @@ | |||||||
| .TH SXIV 1 sxiv\-VERSION | .TH SXIV 1 sxiv\-VERSION | ||||||
| .SH NAME | .SH NAME | ||||||
| sxiv \- Simple (or small or suckless) X Image Viewer | sxiv \- Simple X Image Viewer | ||||||
| .SH SYNOPSIS | .SH SYNOPSIS | ||||||
| .B sxiv | .B sxiv | ||||||
| .RB [ \-bcdFfhpqrstvZ ] | .RB [ \-bcdFfhpqrstvZ ] | ||||||
| @ -306,9 +306,18 @@ Pan image left. | |||||||
| .TP | .TP | ||||||
| .B Shift+ScrollDown | .B Shift+ScrollDown | ||||||
| Pan image right. | Pan image right. | ||||||
|  | .SH STATUS BAR | ||||||
|  | The information displayed on the left side of the status bar can be replaced | ||||||
|  | with the output of a user-provided script, which is called by sxiv whenever an | ||||||
|  | image gets loaded. The path of this script is | ||||||
|  | .I ~/.sxiv/exec/image-info | ||||||
|  | and the first argument to this script is the path of the loaded image. | ||||||
|  | .P | ||||||
|  | There is also an example script installed together with sxiv as | ||||||
|  | .IR PREFIX/share/sxiv/exec/image-info . | ||||||
| .SH THUMBNAIL CACHING | .SH THUMBNAIL CACHING | ||||||
| To enable thumbnail caching, please make sure to create the directory | To enable thumbnail caching, please make sure to create the directory | ||||||
| .I ~/.sxiv/ | .I ~/.sxiv/cache/ | ||||||
| with write permissions. sxiv will then store all thumbnails inside this | with write permissions. sxiv will then store all thumbnails inside this | ||||||
| directory, but it will not create this directory by itself. It rather uses the | directory, but it will not create this directory by itself. It rather uses the | ||||||
| existance of this directory as an affirmation, that the user wants thumbnails | existance of this directory as an affirmation, that the user wants thumbnails | ||||||
| @ -321,30 +330,23 @@ Additionally, run the following command afterwards inside the cache directory | |||||||
| to remove empty subdirectories: | to remove empty subdirectories: | ||||||
| .P | .P | ||||||
| .RS | .RS | ||||||
| find \-type d \-empty \-delete |  | ||||||
| .RE |  | ||||||
| .P |  | ||||||
| If the version of |  | ||||||
| .I find |  | ||||||
| installed on your local system does not support the \-delete option, then you |  | ||||||
| can also try the following command: |  | ||||||
| .P |  | ||||||
| .RS |  | ||||||
| find . \-depth \-type d \-empty ! \-name '.' \-exec rmdir {} \\; | find . \-depth \-type d \-empty ! \-name '.' \-exec rmdir {} \\; | ||||||
| .RE | .RE | ||||||
| .SH AUTHOR | .SH AUTHOR | ||||||
| .EX | .EX | ||||||
| Bert Muennich   <ber.t at gmx.com> | Bert Muennich   <be.muennich @ gmail.com> | ||||||
| .EE | .EE | ||||||
| .SH CONTRIBUTORS | .SH CONTRIBUTORS | ||||||
| .EX | .EX | ||||||
| Bastien Dejean  <nihilhill at gmail.com> | Bastien Dejean  <nihilhill at gmail.com> | ||||||
| Dave Reisner    <d at falconindy.com> | Dave Reisner    <d at falconindy.com> | ||||||
| Fung SzeTat     <sthorde at gmail.com> | Fung SzeTat     <sthorde at gmail.com> | ||||||
| .EX | .EE | ||||||
| .SH HOMEPAGE | .SH HOMEPAGE | ||||||
| .TP | .EX | ||||||
|  | http://muennich.github.com/sxiv | ||||||
| https://github.com/muennich/sxiv | https://github.com/muennich/sxiv | ||||||
|  | .EE | ||||||
| .SH SEE ALSO | .SH SEE ALSO | ||||||
| .BR feh (1), | .BR feh (1), | ||||||
| .BR qiv (1) | .BR qiv (1) | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								thumbs.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								thumbs.c
									
									
									
									
									
								
							| @ -31,8 +31,10 @@ | |||||||
| #include "util.h" | #include "util.h" | ||||||
| #include "config.h" | #include "config.h" | ||||||
| 
 | 
 | ||||||
| const int thumb_dim = THUMB_SIZE + 10; | static const int thumb_dim = THUMB_SIZE + 10; | ||||||
| char *cache_dir = NULL; | 
 | ||||||
|  | static const char * const CACHE_DIR = ".sxiv/cache"; | ||||||
|  | static char *cache_dir = NULL; | ||||||
| 
 | 
 | ||||||
| bool tns_cache_enabled(void) { | bool tns_cache_enabled(void) { | ||||||
| 	struct stat stats; | 	struct stat stats; | ||||||
| @ -175,9 +177,9 @@ void tns_init(tns_t *tns, int cnt, win_t *win) { | |||||||
| 	if ((homedir = getenv("HOME")) != NULL) { | 	if ((homedir = getenv("HOME")) != NULL) { | ||||||
| 		if (cache_dir != NULL) | 		if (cache_dir != NULL) | ||||||
| 			free(cache_dir); | 			free(cache_dir); | ||||||
| 		len = strlen(homedir) + 10; | 		len = strlen(homedir) + strlen(CACHE_DIR) + 2; | ||||||
| 		cache_dir = (char*) s_malloc(len * sizeof(char)); | 		cache_dir = (char*) s_malloc(len); | ||||||
| 		snprintf(cache_dir, len, "%s/.sxiv", homedir); | 		snprintf(cache_dir, len, "%s/%s", homedir, CACHE_DIR); | ||||||
| 	} else { | 	} else { | ||||||
| 		warn("could not locate thumbnail cache directory"); | 		warn("could not locate thumbnail cache directory"); | ||||||
| 	} | 	} | ||||||
|  | |||||||
							
								
								
									
										141
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										141
									
								
								window.c
									
									
									
									
									
								
							| @ -42,13 +42,16 @@ static GC gc; | |||||||
| 
 | 
 | ||||||
| Atom wm_delete_win; | Atom wm_delete_win; | ||||||
| 
 | 
 | ||||||
| struct { | static struct { | ||||||
| 	int ascent; | 	int ascent; | ||||||
| 	int descent; | 	int descent; | ||||||
| 	XFontStruct *xfont; | 	XFontStruct *xfont; | ||||||
| 	XFontSet set; | 	XFontSet set; | ||||||
| } font; | } font; | ||||||
| 
 | 
 | ||||||
|  | static int fontheight; | ||||||
|  | static int barheight; | ||||||
|  | 
 | ||||||
| void win_init_font(Display *dpy, const char *fontstr) { | void win_init_font(Display *dpy, const char *fontstr) { | ||||||
| 	int n; | 	int n; | ||||||
| 	char *def, **missing; | 	char *def, **missing; | ||||||
| @ -77,6 +80,8 @@ void win_init_font(Display *dpy, const char *fontstr) { | |||||||
| 		font.ascent  = font.xfont->ascent; | 		font.ascent  = font.xfont->ascent; | ||||||
| 		font.descent = font.xfont->descent; | 		font.descent = font.xfont->descent; | ||||||
| 	} | 	} | ||||||
|  | 	fontheight = font.ascent + font.descent; | ||||||
|  | 	barheight = fontheight + 2 * V_TEXT_PAD; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| unsigned long win_alloc_color(win_t *win, const char *name) { | unsigned long win_alloc_color(win_t *win, const char *name) { | ||||||
| @ -85,8 +90,8 @@ unsigned long win_alloc_color(win_t *win, const char *name) { | |||||||
| 	if (win == NULL) | 	if (win == NULL) | ||||||
| 		return 0UL; | 		return 0UL; | ||||||
| 	if (XAllocNamedColor(win->env.dpy, | 	if (XAllocNamedColor(win->env.dpy, | ||||||
| 		                   DefaultColormap(win->env.dpy, win->env.scr), | 	                     DefaultColormap(win->env.dpy, win->env.scr), | ||||||
| 											 name, &col, &col) == 0) | 	                     name, &col, &col) == 0) | ||||||
| 	{ | 	{ | ||||||
| 		die("could not allocate color: %s", name); | 		die("could not allocate color: %s", name); | ||||||
| 	} | 	} | ||||||
| @ -99,6 +104,8 @@ void win_init(win_t *win) { | |||||||
| 	if (win == NULL) | 	if (win == NULL) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
|  | 	memset(win, 0, sizeof(win_t)); | ||||||
|  | 
 | ||||||
| 	e = &win->env; | 	e = &win->env; | ||||||
| 	if ((e->dpy = XOpenDisplay(NULL)) == NULL) | 	if ((e->dpy = XOpenDisplay(NULL)) == NULL) | ||||||
| 		die("could not open display"); | 		die("could not open display"); | ||||||
| @ -110,19 +117,12 @@ void win_init(win_t *win) { | |||||||
| 	e->cmap = DefaultColormap(e->dpy, e->scr); | 	e->cmap = DefaultColormap(e->dpy, e->scr); | ||||||
| 	e->depth = DefaultDepth(e->dpy, e->scr); | 	e->depth = DefaultDepth(e->dpy, e->scr); | ||||||
| 
 | 
 | ||||||
| 	win->white    = WhitePixel(e->dpy, e->scr); | 	win->white     = WhitePixel(e->dpy, e->scr); | ||||||
| 	win->bgcol    = win_alloc_color(win, WIN_BG_COLOR); | 	win->bgcol     = win_alloc_color(win, WIN_BG_COLOR); | ||||||
| 	win->fscol    = win_alloc_color(win, WIN_FS_COLOR); | 	win->fscol     = win_alloc_color(win, WIN_FS_COLOR); | ||||||
| 	win->selcol   = win_alloc_color(win, SEL_COLOR); | 	win->selcol    = win_alloc_color(win, SEL_COLOR); | ||||||
| 	win->barbgcol = win_alloc_color(win, BAR_BG_COLOR); | 	win->bar.bgcol = win_alloc_color(win, BAR_BG_COLOR); | ||||||
| 	win->barfgcol = win_alloc_color(win, BAR_FG_COLOR); | 	win->bar.fgcol = win_alloc_color(win, BAR_FG_COLOR); | ||||||
| 
 |  | ||||||
| 	win->xwin = 0; |  | ||||||
| 	win->pm = 0; |  | ||||||
| 	win->fullscreen = false; |  | ||||||
| 	win->barh = 0; |  | ||||||
| 	win->lbar = NULL; |  | ||||||
| 	win->rbar = NULL; |  | ||||||
| 
 | 
 | ||||||
| 	if (setlocale(LC_CTYPE, "") == NULL || XSupportsLocale() == 0) | 	if (setlocale(LC_CTYPE, "") == NULL || XSupportsLocale() == 0) | ||||||
| 		warn("no locale support"); | 		warn("no locale support"); | ||||||
| @ -141,8 +141,8 @@ void win_set_sizehints(win_t *win) { | |||||||
| 	sizehints.flags = PMinSize | PMaxSize; | 	sizehints.flags = PMinSize | PMaxSize; | ||||||
| 	sizehints.min_width = win->w; | 	sizehints.min_width = win->w; | ||||||
| 	sizehints.max_width = win->w; | 	sizehints.max_width = win->w; | ||||||
| 	sizehints.min_height = win->h + win->barh; | 	sizehints.min_height = win->h + win->bar.h; | ||||||
| 	sizehints.max_height = win->h + win->barh; | 	sizehints.max_height = win->h + win->bar.h; | ||||||
| 	XSetWMNormalHints(win->env.dpy, win->xwin, &sizehints); | 	XSetWMNormalHints(win->env.dpy, win->xwin, &sizehints); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -215,8 +215,8 @@ void win_open(win_t *win) { | |||||||
| 	XSetWMProtocols(e->dpy, win->xwin, &wm_delete_win, 1); | 	XSetWMProtocols(e->dpy, win->xwin, &wm_delete_win, 1); | ||||||
| 
 | 
 | ||||||
| 	if (!options->hide_bar) { | 	if (!options->hide_bar) { | ||||||
| 		win->barh = font.ascent + font.descent + 2 * V_TEXT_PAD; | 		win->bar.h = barheight; | ||||||
| 		win->h -= win->barh; | 		win->h -= win->bar.h; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (options->fixed_win) | 	if (options->fixed_win) | ||||||
| @ -250,7 +250,7 @@ bool win_configure(win_t *win, XConfigureEvent *c) { | |||||||
| 	if (win == NULL || c == NULL) | 	if (win == NULL || c == NULL) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	if ((changed = win->w != c->width || win->h + win->barh != c->height)) { | 	if ((changed = win->w != c->width || win->h + win->bar.h != c->height)) { | ||||||
| 		if (win->pm != None) { | 		if (win->pm != None) { | ||||||
| 			XFreePixmap(win->env.dpy, win->pm); | 			XFreePixmap(win->env.dpy, win->pm); | ||||||
| 			win->pm = None; | 			win->pm = None; | ||||||
| @ -260,7 +260,7 @@ bool win_configure(win_t *win, XConfigureEvent *c) { | |||||||
| 	win->x = c->x; | 	win->x = c->x; | ||||||
| 	win->y = c->y; | 	win->y = c->y; | ||||||
| 	win->w = c->width; | 	win->w = c->width; | ||||||
| 	win->h = c->height - win->barh; | 	win->h = c->height - win->bar.h; | ||||||
| 	win->bw = c->border_width; | 	win->bw = c->border_width; | ||||||
| 
 | 
 | ||||||
| 	return changed; | 	return changed; | ||||||
| @ -283,13 +283,13 @@ bool win_moveresize(win_t *win, int x, int y, unsigned int w, unsigned int h) { | |||||||
| 	w = MIN(w, win->env.scrw - 2 * win->bw); | 	w = MIN(w, win->env.scrw - 2 * win->bw); | ||||||
| 	h = MIN(h, win->env.scrh - 2 * win->bw); | 	h = MIN(h, win->env.scrh - 2 * win->bw); | ||||||
| 
 | 
 | ||||||
| 	if (win->x == x && win->y == y && win->w == w && win->h + win->barh == h) | 	if (win->x == x && win->y == y && win->w == w && win->h + win->bar.h == h) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	win->x = x; | 	win->x = x; | ||||||
| 	win->y = y; | 	win->y = y; | ||||||
| 	win->w = w; | 	win->w = w; | ||||||
| 	win->h = h - win->barh; | 	win->h = h - win->bar.h; | ||||||
| 
 | 
 | ||||||
| 	if (options->fixed_win) | 	if (options->fixed_win) | ||||||
| 		win_set_sizehints(win); | 		win_set_sizehints(win); | ||||||
| @ -327,12 +327,12 @@ void win_toggle_bar(win_t *win) { | |||||||
| 	if (win == NULL || win->xwin == None) | 	if (win == NULL || win->xwin == None) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	if (win->barh != 0) { | 	if (win->bar.h != 0) { | ||||||
| 		win->h += win->barh; | 		win->h += win->bar.h; | ||||||
| 		win->barh = 0; | 		win->bar.h = 0; | ||||||
| 	} else { | 	} else { | ||||||
| 		win->barh = font.ascent + font.descent + 2 * V_TEXT_PAD; | 		win->bar.h = barheight; | ||||||
| 		win->h -= win->barh; | 		win->h -= win->bar.h; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -343,7 +343,7 @@ void win_clear(win_t *win) { | |||||||
| 	if (win == NULL || win->xwin == None) | 	if (win == NULL || win->xwin == None) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	h = win->h + win->barh; | 	h = win->h + win->bar.h; | ||||||
| 	e = &win->env; | 	e = &win->env; | ||||||
| 
 | 
 | ||||||
| 	if (win->pm == None) | 	if (win->pm == None) | ||||||
| @ -354,53 +354,56 @@ void win_clear(win_t *win) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void win_draw_bar(win_t *win) { | void win_draw_bar(win_t *win) { | ||||||
|  | 	int len, olen, x, y, w, tw; | ||||||
|  | 	char rest[3]; | ||||||
|  | 	const char *dots = "..."; | ||||||
| 	win_env_t *e; | 	win_env_t *e; | ||||||
| 	int len, x, y, w, tw = 0, seplen; |  | ||||||
| 	const char *rt; |  | ||||||
| 
 | 
 | ||||||
| 	if (win == NULL || win->xwin == None || win->pm == None) | 	if (win == NULL || win->xwin == None || win->pm == None) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	e = &win->env; | 	e = &win->env; | ||||||
| 	x = H_TEXT_PAD; |  | ||||||
| 	y = win->h + font.ascent + V_TEXT_PAD; | 	y = win->h + font.ascent + V_TEXT_PAD; | ||||||
| 	w = win->w - 2 * H_TEXT_PAD; | 	w = win->w; | ||||||
| 
 | 
 | ||||||
| 	XSetForeground(e->dpy, gc, win->barbgcol); | 	XSetForeground(e->dpy, gc, win->bar.bgcol); | ||||||
| 	XFillRectangle(e->dpy, win->pm, gc, 0, win->h, win->w, win->barh); | 	XFillRectangle(e->dpy, win->pm, gc, 0, win->h, win->w, win->bar.h); | ||||||
| 
 | 
 | ||||||
| 	XSetForeground(e->dpy, gc, win->barfgcol); | 	XSetForeground(e->dpy, gc, win->bar.fgcol); | ||||||
| 	XSetBackground(e->dpy, gc, win->barbgcol); | 	XSetBackground(e->dpy, gc, win->bar.bgcol); | ||||||
| 
 | 
 | ||||||
| 	if (win->lbar != NULL) { | 	if (win->bar.r != NULL) { | ||||||
| 		len = strlen(win->lbar); | 		len = strlen(win->bar.r); | ||||||
| 		while (len > 0 && (tw = win_textwidth(win->lbar, len, false)) > w) |  | ||||||
| 			len--; |  | ||||||
| 		w -= tw + 2 * H_TEXT_PAD; |  | ||||||
| 		if (font.set) |  | ||||||
| 			XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, win->lbar, len); |  | ||||||
| 		else |  | ||||||
| 			XDrawString(e->dpy, win->pm, gc, x, y, win->lbar, len); |  | ||||||
| 	} |  | ||||||
| 	if (win->rbar != NULL) { |  | ||||||
| 		len = strlen(win->rbar); |  | ||||||
| 		seplen = strlen(BAR_SEPARATOR); |  | ||||||
| 		rt = win->rbar; |  | ||||||
| 		while (len > 0 && (tw = win_textwidth(rt, len, false)) > w) { |  | ||||||
| 			rt = strstr(rt, BAR_SEPARATOR); |  | ||||||
| 			if (rt != NULL) { |  | ||||||
| 				rt += seplen; |  | ||||||
| 				len = strlen(rt); |  | ||||||
| 			} else { |  | ||||||
| 				len = 0; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		if (len > 0) { | 		if (len > 0) { | ||||||
| 			x = win->w - tw - H_TEXT_PAD; | 			if ((tw = win_textwidth(win->bar.r, len, true)) > w) | ||||||
|  | 				return; | ||||||
|  | 			x = win->w - tw + H_TEXT_PAD; | ||||||
|  | 			w -= tw; | ||||||
| 			if (font.set) | 			if (font.set) | ||||||
| 				XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, rt, len); | 				XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, win->bar.r, len); | ||||||
| 			else | 			else | ||||||
| 				XDrawString(e->dpy, win->pm, gc, x, y, rt, len); | 				XDrawString(e->dpy, win->pm, gc, x, y, win->bar.r, len); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (win->bar.l != NULL) { | ||||||
|  | 		olen = len = strlen(win->bar.l); | ||||||
|  | 		while (len > 0 && (tw = win_textwidth(win->bar.l, len, true)) > w) | ||||||
|  | 			len--; | ||||||
|  | 		if (len > 0) { | ||||||
|  |       if (len != olen) { | ||||||
|  |         w = strlen(dots); | ||||||
|  |         if (len <= w) | ||||||
|  |           return; | ||||||
|  |         memcpy(rest, win->bar.l + len - w, w); | ||||||
|  |         memcpy(win->bar.l + len - w, dots, w); | ||||||
|  |       } | ||||||
|  | 			x = H_TEXT_PAD; | ||||||
|  | 			if (font.set) | ||||||
|  | 				XmbDrawString(e->dpy, win->pm, font.set, gc, x, y, win->bar.l, len); | ||||||
|  | 			else | ||||||
|  | 				XDrawString(e->dpy, win->pm, gc, x, y, win->bar.l, len); | ||||||
|  | 			if (len != olen) | ||||||
|  | 			  memcpy(win->bar.l + len - w, rest, w); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @ -409,11 +412,11 @@ void win_draw(win_t *win) { | |||||||
| 	if (win == NULL || win->xwin == None || win->pm == None) | 	if (win == NULL || win->xwin == None || win->pm == None) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	if (win->barh > 0) | 	if (win->bar.h > 0) | ||||||
| 		win_draw_bar(win); | 		win_draw_bar(win); | ||||||
| 
 | 
 | ||||||
| 	XCopyArea(win->env.dpy, win->pm, win->xwin, gc, | 	XCopyArea(win->env.dpy, win->pm, win->xwin, gc, | ||||||
| 	          0, 0, win->w, win->h + win->barh, 0, 0); | 	          0, 0, win->w, win->h + win->bar.h, 0, 0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void win_draw_rect(win_t *win, Pixmap pm, int x, int y, int w, int h, | void win_draw_rect(win_t *win, Pixmap pm, int x, int y, int w, int h, | ||||||
| @ -466,10 +469,10 @@ void win_set_title(win_t *win, const char *title) { | |||||||
| 	                PropModeReplace, (unsigned char *) title, strlen(title)); | 	                PropModeReplace, (unsigned char *) title, strlen(title)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void win_set_bar_info(win_t *win, const char *li, const char *ri) { | void win_set_bar_info(win_t *win, char *linfo, char *rinfo) { | ||||||
| 	if (win != NULL) { | 	if (win != NULL) { | ||||||
| 		win->lbar = li; | 		win->bar.l = linfo; | ||||||
| 		win->rbar = ri; | 		win->bar.r = rinfo; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										16
									
								
								window.h
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								window.h
									
									
									
									
									
								
							| @ -23,8 +23,6 @@ | |||||||
| 
 | 
 | ||||||
| #include "types.h" | #include "types.h" | ||||||
| 
 | 
 | ||||||
| #define BAR_SEPARATOR " | " |  | ||||||
| 
 |  | ||||||
| typedef struct { | typedef struct { | ||||||
| 	Display *dpy; | 	Display *dpy; | ||||||
| 	int scr; | 	int scr; | ||||||
| @ -42,21 +40,23 @@ typedef struct { | |||||||
| 	unsigned long bgcol; | 	unsigned long bgcol; | ||||||
| 	unsigned long fscol; | 	unsigned long fscol; | ||||||
| 	unsigned long selcol; | 	unsigned long selcol; | ||||||
| 	unsigned long barbgcol; |  | ||||||
| 	unsigned long barfgcol; |  | ||||||
| 	Pixmap pm; | 	Pixmap pm; | ||||||
| 
 | 
 | ||||||
| 	int x; | 	int x; | ||||||
| 	int y; | 	int y; | ||||||
| 	unsigned int w; | 	unsigned int w; | ||||||
| 	unsigned int h; /* = win height - bar height */ | 	unsigned int h; /* = win height - bar height */ | ||||||
| 	unsigned int barh; |  | ||||||
| 	unsigned int bw; | 	unsigned int bw; | ||||||
| 
 | 
 | ||||||
| 	bool fullscreen; | 	bool fullscreen; | ||||||
| 
 | 
 | ||||||
| 	const char *lbar; | 	struct { | ||||||
| 	const char *rbar; | 		unsigned int h; | ||||||
|  | 		char *l; | ||||||
|  | 		char *r; | ||||||
|  | 		unsigned long bgcol; | ||||||
|  | 		unsigned long fgcol; | ||||||
|  | 	} bar; | ||||||
| } win_t; | } win_t; | ||||||
| 
 | 
 | ||||||
| extern Atom wm_delete_win; | extern Atom wm_delete_win; | ||||||
| @ -80,7 +80,7 @@ void win_draw_rect(win_t*, Pixmap, int, int, int, int, bool, int, | |||||||
| int win_textwidth(const char*, unsigned int, bool); | int win_textwidth(const char*, unsigned int, bool); | ||||||
| 
 | 
 | ||||||
| void win_set_title(win_t*, const char*); | void win_set_title(win_t*, const char*); | ||||||
| void win_set_bar_info(win_t*, const char*, const char*); | void win_set_bar_info(win_t*, char*, char*); | ||||||
| void win_set_cursor(win_t*, cursor_t); | void win_set_cursor(win_t*, cursor_t); | ||||||
| 
 | 
 | ||||||
| #endif /* WINDOW_H */ | #endif /* WINDOW_H */ | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Bert Münnich
						Bert Münnich