Revised handling of file names & paths
This commit is contained in:
		
							parent
							
								
									2a3a9657d3
								
							
						
					
					
						commit
						ff013dd009
					
				
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @ -1,6 +1,6 @@ | ||||
| all: sxiv | ||||
| 
 | ||||
| VERSION = 0.9 | ||||
| VERSION = git-20110818 | ||||
| 
 | ||||
| CC = gcc | ||||
| DESTDIR = | ||||
|  | ||||
							
								
								
									
										30
									
								
								events.c
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								events.c
									
									
									
									
									
								
							| @ -52,7 +52,7 @@ extern img_t img; | ||||
| extern tns_t tns; | ||||
| extern win_t win; | ||||
| 
 | ||||
| extern char **filenames; | ||||
| extern fileinfo_t *files; | ||||
| extern int filecnt, fileidx; | ||||
| 
 | ||||
| int timo_cursor; | ||||
| @ -163,7 +163,7 @@ void run() { | ||||
| 			gettimeofday(&t0, 0); | ||||
| 
 | ||||
| 			while (tns.cnt < filecnt && !XPending(win.env.dpy)) { | ||||
| 				if (tns_load(&tns, tns.cnt, filenames[tns.cnt], 0)) | ||||
| 				if (tns_load(&tns, tns.cnt, &files[tns.cnt], 0)) | ||||
| 					tns.cnt++; | ||||
| 				else | ||||
| 					remove_file(tns.cnt, 0); | ||||
| @ -513,7 +513,7 @@ int open_with(arg_t a) { | ||||
| 
 | ||||
| 	if((pid = fork()) == 0) { | ||||
| 		execlp(prog, prog, | ||||
| 		       filenames[mode == MODE_NORMAL ? fileidx : tns.sel], NULL); | ||||
| 		       files[mode == MODE_NORMAL ? fileidx : tns.sel].path, NULL); | ||||
| 		warn("could not exec: %s", prog); | ||||
| 		exit(1); | ||||
| 	} else if (pid < 0) { | ||||
| @ -526,30 +526,30 @@ int open_with(arg_t a) { | ||||
| int run_command(arg_t a) { | ||||
| 	const char *cline = (const char*) a; | ||||
| 	char *cn, *cmdline; | ||||
| 	const char *co, *fname; | ||||
| 	int fncnt, fnlen, status; | ||||
| 	const char *co, *fpath; | ||||
| 	int fpcnt, fplen, status; | ||||
| 	pid_t pid; | ||||
| 
 | ||||
| 	if (!cline || !*cline) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/* build command line: */ | ||||
| 	fncnt = 0; | ||||
| 	fpcnt = 0; | ||||
| 	co = cline - 1; | ||||
| 	while ((co = strchr(co + 1, '#'))) | ||||
| 		fncnt++; | ||||
| 	if (!fncnt) | ||||
| 		fpcnt++; | ||||
| 	if (!fpcnt) | ||||
| 		return 0; | ||||
| 	fname = filenames[mode == MODE_NORMAL ? fileidx : tns.sel]; | ||||
| 	fnlen = strlen(fname); | ||||
| 	cn = cmdline = (char*) s_malloc((strlen(cline) + fncnt * (fnlen + 2)) * | ||||
| 	fpath = files[mode == MODE_NORMAL ? fileidx : tns.sel].path; | ||||
| 	fplen = strlen(fpath); | ||||
| 	cn = cmdline = (char*) s_malloc((strlen(cline) + fpcnt * (fplen + 2)) * | ||||
| 	                                sizeof(char)); | ||||
| 	/* replace all '#' with filename: */ | ||||
| 	for (co = cline; *co; co++) { | ||||
| 		if (*co == '#') { | ||||
| 			*cn++ = '"'; | ||||
| 			strcpy(cn, fname); | ||||
| 			cn += fnlen; | ||||
| 			strcpy(cn, fpath); | ||||
| 			cn += fplen; | ||||
| 			*cn++ = '"'; | ||||
| 		} else { | ||||
| 			*cn++ = *co; | ||||
| @ -575,11 +575,11 @@ int run_command(arg_t a) { | ||||
| 	 | ||||
| 	if (mode == MODE_NORMAL) { | ||||
| 		if (fileidx < tns.cnt) | ||||
| 			tns_load(&tns, fileidx, filenames[fileidx], 1); | ||||
| 			tns_load(&tns, fileidx, &files[fileidx], 1); | ||||
| 		img_close(&img, 1); | ||||
| 		load_image(fileidx); | ||||
| 	} else { | ||||
| 		if (!tns_load(&tns, tns.sel, filenames[tns.sel], 0)) { | ||||
| 		if (!tns_load(&tns, tns.sel, &files[tns.sel], 0)) { | ||||
| 			remove_file(tns.sel, 0); | ||||
| 			tns.dirty = 1; | ||||
| 			if (tns.sel >= tns.cnt) | ||||
|  | ||||
							
								
								
									
										8
									
								
								image.c
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								image.c
									
									
									
									
									
								
							| @ -50,12 +50,12 @@ void img_init(img_t *img, win_t *win) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int img_load(img_t *img, const char *filename) { | ||||
| 	if (!img || !filename) | ||||
| int img_load(img_t *img, const fileinfo_t *file) { | ||||
| 	if (!img || !file || !file->name || !file->path) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	if (access(filename, R_OK) || !(img->im = imlib_load_image(filename))) { | ||||
| 		warn("could not open image: %s", filename); | ||||
| 	if (access(file->path, R_OK) || !(img->im = imlib_load_image(file->path))) { | ||||
| 		warn("could not open image: %s", file->name); | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										2
									
								
								image.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								image.h
									
									
									
									
									
								
							| @ -43,7 +43,7 @@ typedef struct { | ||||
| 
 | ||||
| void img_init(img_t*, win_t*); | ||||
| 
 | ||||
| int img_load(img_t*, const char*); | ||||
| int img_load(img_t*, const fileinfo_t*); | ||||
| void img_close(img_t*, int); | ||||
| 
 | ||||
| void img_render(img_t*, win_t*); | ||||
|  | ||||
							
								
								
									
										71
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										71
									
								
								main.c
									
									
									
									
									
								
							| @ -25,6 +25,7 @@ | ||||
| #include "image.h" | ||||
| #include "options.h" | ||||
| #include "thumbs.h" | ||||
| #include "types.h" | ||||
| #include "util.h" | ||||
| #include "window.h" | ||||
| 
 | ||||
| @ -38,7 +39,7 @@ img_t img; | ||||
| tns_t tns; | ||||
| win_t win; | ||||
| 
 | ||||
| char **filenames; | ||||
| fileinfo_t *files; | ||||
| int filecnt, fileidx; | ||||
| size_t filesize; | ||||
| 
 | ||||
| @ -54,21 +55,30 @@ void cleanup() { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int check_add_file(char *filename) { | ||||
| 	if (!filename) | ||||
| 		return 0; | ||||
| void check_add_file(char *filename) { | ||||
| 	if (!filename || !*filename) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (access(filename, R_OK)) { | ||||
| 		warn("could not open file: %s", filename); | ||||
| 		return 0; | ||||
| 	} else { | ||||
| 		if (fileidx == filecnt) { | ||||
| 			filecnt *= 2; | ||||
| 			filenames = (char**) s_realloc(filenames, filecnt * sizeof(char*)); | ||||
| 		} | ||||
| 		filenames[fileidx++] = filename; | ||||
| 		return 1; | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	if (fileidx == filecnt) { | ||||
| 		filecnt *= 2; | ||||
| 		files = (fileinfo_t*) s_realloc(files, filecnt * sizeof(fileinfo_t)); | ||||
| 	} | ||||
| 	if (*filename != '/') { | ||||
| 		files[fileidx].path = absolute_path(filename); | ||||
| 		if (!files[fileidx].path) { | ||||
| 			warn("could not get absolute path of file: %s\n", filename); | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 	files[fileidx].name = s_strdup(filename); | ||||
| 	if (*filename == '/') | ||||
| 		files[fileidx].path = files[fileidx].name; | ||||
| 	fileidx++; | ||||
| } | ||||
| 
 | ||||
| void remove_file(int n, unsigned char silent) { | ||||
| @ -82,9 +92,12 @@ void remove_file(int n, unsigned char silent) { | ||||
| 		exit(!silent); | ||||
| 	} | ||||
| 
 | ||||
| 	if (n + 1 < filecnt) | ||||
| 		memmove(filenames + n, filenames + n + 1, (filecnt - n - 1) * | ||||
| 		        sizeof(char*)); | ||||
| 	if (n + 1 < filecnt) { | ||||
| 		if (files[n].path != files[n].name) | ||||
| 			free((void*) files[n].path); | ||||
| 		free((void*) files[n].name); | ||||
| 		memmove(files + n, files + n + 1, (filecnt - n - 1) * sizeof(fileinfo_t)); | ||||
| 	} | ||||
| 	if (n + 1 < tns.cnt) { | ||||
| 		memmove(tns.thumbs + n, tns.thumbs + n + 1, (tns.cnt - n - 1) * | ||||
| 		        sizeof(thumb_t)); | ||||
| @ -106,14 +119,14 @@ void load_image(int new) { | ||||
| 	win_set_cursor(&win, CURSOR_WATCH); | ||||
| 	img_close(&img, 0); | ||||
| 		 | ||||
| 	while (!img_load(&img, filenames[new])) { | ||||
| 	while (!img_load(&img, &files[new])) { | ||||
| 		remove_file(new, 0); | ||||
| 		if (new >= filecnt) | ||||
| 			new = filecnt - 1; | ||||
| 	} | ||||
| 
 | ||||
| 	fileidx = new; | ||||
| 	if (!stat(filenames[new], &fstats)) | ||||
| 	if (!stat(files[new].path, &fstats)) | ||||
| 		filesize = fstats.st_size; | ||||
| 	else | ||||
| 		filesize = 0; | ||||
| @ -127,14 +140,14 @@ void update_title() { | ||||
| 	if (mode == MODE_THUMBS) { | ||||
| 		n = snprintf(win_title, TITLE_LEN, "sxiv: [%d/%d] %s", | ||||
| 		             tns.cnt ? tns.sel + 1 : 0, tns.cnt, | ||||
| 		             tns.cnt ? filenames[tns.sel] : ""); | ||||
| 		             tns.cnt ? files[tns.sel].name : ""); | ||||
| 	} else { | ||||
| 		size = filesize; | ||||
| 		size_readable(&size, &unit); | ||||
| 		n = snprintf(win_title, TITLE_LEN, | ||||
| 		             "sxiv: [%d/%d] <%d%%> <%dx%d> (%.2f%s) %s", | ||||
| 		             fileidx + 1, filecnt, (int) (img.zoom * 100.0), img.w, img.h, | ||||
| 		             size, unit, filenames[fileidx]); | ||||
| 		             size, unit, files[fileidx].name); | ||||
| 	} | ||||
| 
 | ||||
| 	if (n >= TITLE_LEN) { | ||||
| @ -146,13 +159,13 @@ void update_title() { | ||||
| } | ||||
| 
 | ||||
| int fncmp(const void *a, const void *b) { | ||||
| 	return strcoll(*((char* const*) a), *((char* const*) b)); | ||||
| 	return strcoll(((fileinfo_t*) a)->name, ((fileinfo_t*) b)->name); | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char **argv) { | ||||
| 	int i, len, start; | ||||
| 	size_t n; | ||||
| 	char *filename = NULL; | ||||
| 	char *filename; | ||||
| 	struct stat fstats; | ||||
| 	r_dir_t dir; | ||||
| 
 | ||||
| @ -174,17 +187,16 @@ int main(int argc, char **argv) { | ||||
| 	else | ||||
| 		filecnt = options->filecnt; | ||||
| 
 | ||||
| 	filenames = (char**) s_malloc(filecnt * sizeof(char*)); | ||||
| 	files = (fileinfo_t*) s_malloc(filecnt * sizeof(fileinfo_t)); | ||||
| 	fileidx = 0; | ||||
| 
 | ||||
| 	/* build file list: */ | ||||
| 	if (options->from_stdin) { | ||||
| 		filename = NULL; | ||||
| 		while ((len = getline(&filename, &n, stdin)) > 0) { | ||||
| 			if (filename[len-1] == '\n') | ||||
| 				filename[len-1] = '\0'; | ||||
| 			if (!*filename || !check_add_file(filename)) | ||||
| 				free(filename); | ||||
| 			filename = NULL; | ||||
| 			check_add_file(filename); | ||||
| 		} | ||||
| 	} else { | ||||
| 		for (i = 0; i < options->filecnt; i++) { | ||||
| @ -202,13 +214,14 @@ int main(int argc, char **argv) { | ||||
| 					continue; | ||||
| 				} | ||||
| 				start = fileidx; | ||||
| 				printf("reading dir: %s\n", filename); | ||||
| 				while ((filename = r_readdir(&dir))) { | ||||
| 					if (!check_add_file(filename)) | ||||
| 						free((void*) filename); | ||||
| 					check_add_file(filename); | ||||
| 					free((void*) filename); | ||||
| 				} | ||||
| 				r_closedir(&dir); | ||||
| 				if (fileidx - start > 1) | ||||
| 					qsort(filenames + start, fileidx - start, sizeof(char*), fncmp); | ||||
| 					qsort(files + start, fileidx - start, sizeof(fileinfo_t), fncmp); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| @ -227,7 +240,7 @@ int main(int argc, char **argv) { | ||||
| 	if (options->thumbnails) { | ||||
| 		mode = MODE_THUMBS; | ||||
| 		tns_init(&tns, filecnt); | ||||
| 		while (!tns_load(&tns, 0, filenames[0], 0)) | ||||
| 		while (!tns_load(&tns, 0, &files[0], 0)) | ||||
| 			remove_file(0, 0); | ||||
| 		tns.cnt = 1; | ||||
| 	} else { | ||||
|  | ||||
							
								
								
									
										49
									
								
								thumbs.c
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								thumbs.c
									
									
									
									
									
								
							| @ -44,45 +44,34 @@ int tns_cache_enabled() { | ||||
| 	       !access(cache_dir, W_OK); | ||||
| } | ||||
| 
 | ||||
| char* tns_cache_filename(const char *filename) { | ||||
| char* tns_cache_filepath(const char *filepath) { | ||||
| 	size_t len; | ||||
| 	char *cfile = NULL; | ||||
| 	const char *abspath; | ||||
| 
 | ||||
| 	if (!cache_dir || !filename) | ||||
| 	if (!cache_dir || !filepath || *filepath != '/') | ||||
| 		return NULL; | ||||
| 	 | ||||
| 	if (*filename != '/') { | ||||
| 		if (!(abspath = absolute_path(filename))) | ||||
| 			return NULL; | ||||
| 	} else { | ||||
| 		abspath = filename; | ||||
| 	} | ||||
| 
 | ||||
| 	if (strncmp(abspath, cache_dir, strlen(cache_dir))) { | ||||
| 		len = strlen(cache_dir) + strlen(abspath) + 6; | ||||
| 	if (strncmp(filepath, cache_dir, strlen(cache_dir))) { | ||||
| 		len = strlen(cache_dir) + strlen(filepath) + 6; | ||||
| 		cfile = (char*) s_malloc(len); | ||||
| 		snprintf(cfile, len, "%s/%s.png", cache_dir, abspath + 1); | ||||
| 		snprintf(cfile, len, "%s/%s.png", cache_dir, filepath + 1); | ||||
| 	} | ||||
| 	 | ||||
| 	if (abspath != filename) | ||||
| 		free((void*) abspath); | ||||
| 
 | ||||
| 	return cfile; | ||||
| } | ||||
| 
 | ||||
| Imlib_Image* tns_cache_load(const char *filename) { | ||||
| Imlib_Image* tns_cache_load(const char *filepath) { | ||||
| 	char *cfile; | ||||
| 	struct stat cstats, fstats; | ||||
| 	Imlib_Image *im = NULL; | ||||
| 
 | ||||
| 	if (!filename) | ||||
| 	if (!filepath) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	if (stat(filename, &fstats)) | ||||
| 	if (stat(filepath, &fstats)) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	if ((cfile = tns_cache_filename(filename))) { | ||||
| 	if ((cfile = tns_cache_filepath(filepath))) { | ||||
| 		if (!stat(cfile, &cstats) && | ||||
| 		    cstats.st_mtim.tv_sec == fstats.st_mtim.tv_sec && | ||||
| 		    cstats.st_mtim.tv_nsec / 1000 == fstats.st_mtim.tv_nsec / 1000) | ||||
| @ -101,13 +90,13 @@ void tns_cache_write(thumb_t *t, Bool force) { | ||||
| 	struct timeval times[2]; | ||||
| 	Imlib_Load_Error err = 0; | ||||
| 
 | ||||
| 	if (!t || !t->im || !t->filename) | ||||
| 	if (!t || !t->im || !t->file || !t->file->name || !t->file->path) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (stat(t->filename, &fstats)) | ||||
| 	if (stat(t->file->path, &fstats)) | ||||
| 		return; | ||||
| 
 | ||||
| 	if ((cfile = tns_cache_filename(t->filename))) { | ||||
| 	if ((cfile = tns_cache_filepath(t->file->path))) { | ||||
| 		if (force || stat(cfile, &cstats) || | ||||
| 		    cstats.st_mtim.tv_sec != fstats.st_mtim.tv_sec || | ||||
| 		    cstats.st_mtim.tv_nsec / 1000 != fstats.st_mtim.tv_nsec / 1000) | ||||
| @ -125,7 +114,7 @@ void tns_cache_write(thumb_t *t, Bool force) { | ||||
| 			} | ||||
| 
 | ||||
| 			if (err) { | ||||
| 				warn("could not cache thumbnail: %s", t->filename); | ||||
| 				warn("could not cache thumbnail: %s", t->file->name); | ||||
| 			} else { | ||||
| 				TIMESPEC_TO_TIMEVAL(×[0], &fstats.st_atim); | ||||
| 				TIMESPEC_TO_TIMEVAL(×[1], &fstats.st_mtim); | ||||
| @ -223,21 +212,21 @@ void tns_free(tns_t *tns) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int tns_load(tns_t *tns, int n, const char *filename, unsigned char silent) { | ||||
| int tns_load(tns_t *tns, int n, const fileinfo_t *file, unsigned char silent) { | ||||
| 	int w, h; | ||||
| 	int use_cache, cached = 0; | ||||
| 	float z, zw, zh; | ||||
| 	thumb_t *t; | ||||
| 	Imlib_Image *im; | ||||
| 
 | ||||
| 	if (!tns || !tns->thumbs || !filename) | ||||
| 	if (!tns || !tns->thumbs || !file || !file->name || !file->path) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	if (n < 0 || n >= tns->cap) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	t = &tns->thumbs[n]; | ||||
| 	t->filename = filename; | ||||
| 	t->file = file; | ||||
| 
 | ||||
| 	if (t->im) { | ||||
| 		imlib_context_set_image(t->im); | ||||
| @ -245,15 +234,15 @@ int tns_load(tns_t *tns, int n, const char *filename, unsigned char silent) { | ||||
| 	} | ||||
| 
 | ||||
| 	if ((use_cache = tns_cache_enabled())) { | ||||
| 		if ((im = tns_cache_load(filename))) | ||||
| 		if ((im = tns_cache_load(file->path))) | ||||
| 			cached = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!cached && | ||||
| 	    (access(filename, R_OK) || !(im = imlib_load_image(filename)))) | ||||
| 	    (access(file->path, R_OK) || !(im = imlib_load_image(file->path)))) | ||||
| 	{ | ||||
| 		if (!silent) | ||||
| 			warn("could not open image: %s", filename); | ||||
| 			warn("could not open image: %s", file->name); | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										4
									
								
								thumbs.h
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								thumbs.h
									
									
									
									
									
								
							| @ -26,7 +26,7 @@ | ||||
| 
 | ||||
| typedef struct { | ||||
| 	Imlib_Image *im; | ||||
| 	const char *filename; | ||||
| 	const fileinfo_t *file; | ||||
| 	int x; | ||||
| 	int y; | ||||
| 	int w; | ||||
| @ -51,7 +51,7 @@ void tns_clean_cache(tns_t*); | ||||
| void tns_init(tns_t*, int); | ||||
| void tns_free(tns_t*); | ||||
| 
 | ||||
| int tns_load(tns_t*, int, const char*, unsigned char); | ||||
| int tns_load(tns_t*, int, const fileinfo_t*, unsigned char); | ||||
| 
 | ||||
| void tns_render(tns_t*, win_t*); | ||||
| void tns_highlight(tns_t*, win_t*, int, Bool); | ||||
|  | ||||
							
								
								
									
										5
									
								
								types.h
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								types.h
									
									
									
									
									
								
							| @ -26,4 +26,9 @@ typedef enum { | ||||
| 	CURSOR_WATCH | ||||
| } cursor_t; | ||||
| 
 | ||||
| typedef struct { | ||||
| 	const char *name; | ||||
| 	const char *path; | ||||
| } fileinfo_t; | ||||
| 
 | ||||
| #endif /* TYPES_H */ | ||||
|  | ||||
							
								
								
									
										11
									
								
								util.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								util.c
									
									
									
									
									
								
							| @ -47,6 +47,17 @@ void* s_realloc(void *ptr, size_t size) { | ||||
| 	return ptr; | ||||
| } | ||||
| 
 | ||||
| char* s_strdup(char *s) { | ||||
| 	char *d = NULL; | ||||
| 
 | ||||
| 	if (s) { | ||||
| 		if (!(d = malloc(strlen(s) + 1))) | ||||
| 			die("could not allocate memory"); | ||||
| 		strcpy(d, s); | ||||
| 	} | ||||
| 	return d; | ||||
| } | ||||
| 
 | ||||
| void warn(const char* fmt, ...) { | ||||
| 	va_list args; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Bert
						Bert