| @@ -18,6 +18,8 @@ |
| 18 | 18 | | |
| 19 | 19 | | #include <stdlib.h> |
| 20 | 20 | | #include <stdio.h> |
| 21 | + | #include <string.h> |
| 22 | + | #include <dirent.h> |
| 21 | 23 | | #include <sys/select.h> |
| 22 | 24 | | #include <sys/stat.h> |
| 23 | 25 | | |
| @@ -39,7 +41,8 @@ void on_motionnotify(XEvent*); |
| 39 | 41 | | void on_configurenotify(XEvent*); |
| 40 | 42 | | |
| 41 | 43 | | void update_title(); |
| 42 | | − | void read_dir(const char*); |
| 44 | + | void check_append(const char*); |
| 45 | + | void read_dir_rec(const char*); |
| 43 | 46 | | |
| 44 | 47 | | static void (*handler[LASTEvent])(XEvent*) = { |
| 45 | 48 | | [KeyPress] = on_keypress, |
| @@ -118,16 +121,11 @@ int main(int argc, char **argv) { |
| 118 | 121 | | WARN("could not stat file: %s", filename); |
| 119 | 122 | | } else if (S_ISDIR(fstats.st_mode)) { |
| 120 | 123 | | if (options->recursive) |
| 121 | | − | read_dir(filename); |
| 124 | + | read_dir_rec(filename); |
| 122 | 125 | | else |
| 123 | 126 | | WARN("ignoring directory: %s", filename); |
| 124 | | − | } else if (img_check(filename)) { |
| 125 | | − | if (fileidx == filecnt) { |
| 126 | | − | filecnt *= 2; |
| 127 | | − | filenames = (const char**) s_realloc(filenames, |
| 128 | | − | filecnt * sizeof(const char*)); |
| 129 | | − | } |
| 130 | | − | filenames[fileidx++] = filename; |
| 127 | + | } else { |
| 128 | + | check_append(filename); |
| 131 | 129 | | } |
| 132 | 130 | | } |
| 133 | 131 | | |
| @@ -384,7 +382,68 @@ void update_title() { |
| 384 | 382 | | win_set_title(&win, win_title); |
| 385 | 383 | | } |
| 386 | 384 | | |
| 387 | | − | void read_dir(const char *dir) { |
| 385 | + | void check_append(const char *filename) { |
| 386 | + | if (!filename) |
| 387 | + | return; |
| 388 | + | |
| 389 | + | if (img_check(filename)) { |
| 390 | + | if (fileidx == filecnt) { |
| 391 | + | filecnt *= 2; |
| 392 | + | filenames = (const char**) s_realloc(filenames, |
| 393 | + | filecnt * sizeof(const char*)); |
| 394 | + | } |
| 395 | + | filenames[fileidx++] = filename; |
| 396 | + | } |
| 397 | + | } |
| 398 | + | |
| 399 | + | void read_dir_rec(const char *dirname) { |
| 400 | + | char *filename; |
| 401 | + | const char **dirnames; |
| 402 | + | int dircnt, diridx; |
| 403 | + | unsigned char first; |
| 404 | + | size_t len; |
| 405 | + | DIR *dir; |
| 406 | + | struct dirent *dentry; |
| 407 | + | struct stat fstats; |
| 408 | + | |
| 409 | + | if (!dirname) |
| 410 | + | return; |
| 411 | + | |
| 412 | + | dircnt = DNAME_CNT; |
| 413 | + | diridx = first = 1; |
| 414 | + | dirnames = (const char**) s_malloc(dircnt * sizeof(const char*)); |
| 415 | + | dirnames[0] = dirname; |
| 416 | + | |
| 417 | + | while (diridx > 0) { |
| 418 | + | dirname = dirnames[--diridx]; |
| 419 | + | if (!(dir = opendir(dirname))) |
| 420 | + | DIE("could not open directory: %s", dirname); |
| 421 | + | while ((dentry = readdir(dir))) { |
| 422 | + | if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, "..")) |
| 423 | + | continue; |
| 424 | + | len = strlen(dirname) + strlen(dentry->d_name) + 2; |
| 425 | + | filename = (char*) s_malloc(len * sizeof(char)); |
| 426 | + | snprintf(filename, len, "%s/%s", dirname, dentry->d_name); |
| 427 | + | if (stat(filename, &fstats)) { |
| 428 | + | WARN("could not stat file: %s", filename); |
| 429 | + | free(filename); |
| 430 | + | } else if (S_ISDIR(fstats.st_mode)) { |
| 431 | + | if (diridx == dircnt) { |
| 432 | + | dircnt *= 2; |
| 433 | + | dirnames = (const char**) s_realloc(dirnames, |
| 434 | + | dircnt * sizeof(const char*)); |
| 435 | + | } |
| 436 | + | dirnames[diridx++] = filename; |
| 437 | + | } else { |
| 438 | + | check_append(filename); |
| 439 | + | } |
| 440 | + | } |
| 441 | + | closedir(dir); |
| 442 | + | if (!first) |
| 443 | + | free((void*) dirname); |
| 444 | + | else |
| 445 | + | first = 0; |
| 446 | + | } |
| 388 | 447 | | } |
| 389 | 448 | | |
| 390 | 449 | | void* s_malloc(size_t size) { |