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(×[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; } 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*, ...);