diff --git a/README.md b/README.md index 346b66f..07238e5 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ sxiv supports the following command-line options: (see section GEOMETRY SPECIFICATIONS of X(7)) -p Pixelize, i.e. turn off image anti-aliasing -q Be quiet, disable warnings + -r Search given directories recursively for images -s Scale all images to fit into window -v Print version information and exit -Z Same as `-z 100' diff --git a/TODO b/TODO index e01f2a7..47f1994 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,2 @@ - key mappings for fit image to window and vice versa - update filelist if image is removed or renamed while running -- view all images in directories (recursive mode) diff --git a/main.c b/main.c index 766312d..5ab7efa 100644 --- a/main.c +++ b/main.c @@ -18,6 +18,8 @@ #include #include +#include +#include #include #include @@ -39,7 +41,8 @@ void on_motionnotify(XEvent*); void on_configurenotify(XEvent*); void update_title(); -void read_dir(const char*); +void check_append(const char*); +void read_dir_rec(const char*); static void (*handler[LASTEvent])(XEvent*) = { [KeyPress] = on_keypress, @@ -118,16 +121,11 @@ int main(int argc, char **argv) { WARN("could not stat file: %s", filename); } else if (S_ISDIR(fstats.st_mode)) { if (options->recursive) - read_dir(filename); + read_dir_rec(filename); else WARN("ignoring directory: %s", filename); - } else if (img_check(filename)) { - if (fileidx == filecnt) { - filecnt *= 2; - filenames = (const char**) s_realloc(filenames, - filecnt * sizeof(const char*)); - } - filenames[fileidx++] = filename; + } else { + check_append(filename); } } @@ -384,7 +382,68 @@ void update_title() { win_set_title(&win, win_title); } -void read_dir(const char *dir) { +void check_append(const char *filename) { + if (!filename) + return; + + if (img_check(filename)) { + if (fileidx == filecnt) { + filecnt *= 2; + filenames = (const char**) s_realloc(filenames, + filecnt * sizeof(const char*)); + } + filenames[fileidx++] = filename; + } +} + +void read_dir_rec(const char *dirname) { + char *filename; + const char **dirnames; + int dircnt, diridx; + unsigned char first; + size_t len; + DIR *dir; + struct dirent *dentry; + struct stat fstats; + + if (!dirname) + return; + + dircnt = DNAME_CNT; + diridx = first = 1; + dirnames = (const char**) s_malloc(dircnt * sizeof(const char*)); + dirnames[0] = dirname; + + while (diridx > 0) { + dirname = dirnames[--diridx]; + if (!(dir = opendir(dirname))) + DIE("could not open directory: %s", dirname); + while ((dentry = readdir(dir))) { + if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, "..")) + continue; + len = strlen(dirname) + strlen(dentry->d_name) + 2; + filename = (char*) s_malloc(len * sizeof(char)); + snprintf(filename, len, "%s/%s", dirname, dentry->d_name); + if (stat(filename, &fstats)) { + WARN("could not stat file: %s", filename); + free(filename); + } else if (S_ISDIR(fstats.st_mode)) { + if (diridx == dircnt) { + dircnt *= 2; + dirnames = (const char**) s_realloc(dirnames, + dircnt * sizeof(const char*)); + } + dirnames[diridx++] = filename; + } else { + check_append(filename); + } + } + closedir(dir); + if (!first) + free((void*) dirname); + else + first = 0; + } } void* s_malloc(size_t size) { diff --git a/options.c b/options.c index bb608e5..74daf5b 100644 --- a/options.c +++ b/options.c @@ -29,7 +29,7 @@ options_t _options; const options_t *options = (const options_t*) &_options; void print_usage() { - printf("usage: sxiv [-dFfhpqsvZ] [-g GEOMETRY] [-z ZOOM] FILES...\n"); + printf("usage: sxiv [-dFfhpqrsvZ] [-g GEOMETRY] [-z ZOOM] FILES...\n"); } void print_version() { @@ -52,7 +52,7 @@ void parse_options(int argc, char **argv) { _options.quiet = 0; _options.recursive = 0; - while ((opt = getopt(argc, argv, "dFfg:hpqsvZz:")) != -1) { + while ((opt = getopt(argc, argv, "dFfg:hpqrsvZz:")) != -1) { switch (opt) { case '?': print_usage(); @@ -78,6 +78,9 @@ void parse_options(int argc, char **argv) { case 'q': _options.quiet = 1; break; + case 'r': + _options.recursive = 1; + break; case 's': _options.scalemode = SCALE_FIT; break; diff --git a/sxiv.1 b/sxiv.1 index a7daf29..56173ba 100644 --- a/sxiv.1 +++ b/sxiv.1 @@ -3,7 +3,7 @@ sxiv \- Simple (or small or suckless) X Image Viewer .SH SYNOPSIS .B sxiv -.RB [ \-dFfhpqsvZ ] +.RB [ \-dFfhpqrsvZ ] .RB [ \-g .IR GEOMETRY ] .RB [ \-z @@ -41,6 +41,9 @@ Pixelize images, i.e. turn off anti-aliasing. .B \-q Be quiet, disable warnings to standard error stream. .TP +.B \-r +Search the given directories recursively for images to view. +.TP .B \-s Scale all images to fit into window. .TP