diff --git a/Makefile b/Makefile
index ed7a700..74235d9 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 all: sxiv
 
-VERSION = 0.9
+VERSION = git-20110818
 
 CC = gcc
 DESTDIR =
diff --git a/events.c b/events.c
index 618aa3a..805e1b0 100644
--- a/events.c
+++ b/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)
diff --git a/image.c b/image.c
index c9e53de..75fe989 100644
--- a/image.c
+++ b/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;
 	}
 
diff --git a/image.h b/image.h
index 2d14b7a..0907bcc 100644
--- a/image.h
+++ b/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*);
diff --git a/main.c b/main.c
index 1b98efd..d6564cb 100644
--- a/main.c
+++ b/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 {
diff --git a/thumbs.c b/thumbs.c
index bfd8794..c13fba5 100644
--- a/thumbs.c
+++ b/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(&times[0], &fstats.st_atim);
 				TIMESPEC_TO_TIMEVAL(&times[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;
 	}
 
diff --git a/thumbs.h b/thumbs.h
index 347c146..436f0bf 100644
--- a/thumbs.h
+++ b/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);
diff --git a/types.h b/types.h
index de6e04d..a2b9651 100644
--- a/types.h
+++ b/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 */
diff --git a/util.c b/util.c
index dee497d..e8bbdd9 100644
--- a/util.c
+++ b/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;
 
diff --git a/util.h b/util.h
index 9e08bac..0e75b4e 100644
--- a/util.h
+++ b/util.h
@@ -55,6 +55,7 @@ typedef struct {
 
 void* s_malloc(size_t);
 void* s_realloc(void*, size_t);
+char* s_strdup(char*);
 
 void warn(const char*, ...);
 void die(const char*, ...);