diff options
-rw-r--r-- | ChangeLog | 40 | ||||
-rw-r--r-- | config.mk | 2 | ||||
-rw-r--r-- | man/feh.pre | 64 | ||||
-rw-r--r-- | src/feh.h | 3 | ||||
-rw-r--r-- | src/filelist.c | 10 | ||||
-rw-r--r-- | src/imlib.c | 171 | ||||
-rw-r--r-- | src/index.c | 8 | ||||
-rw-r--r-- | src/options.c | 421 | ||||
-rw-r--r-- | src/options.h | 2 | ||||
-rw-r--r-- | src/slideshow.c | 10 | ||||
-rw-r--r-- | src/thumbnail.c | 11 | ||||
-rw-r--r-- | src/wallpaper.c | 15 | ||||
-rw-r--r-- | src/winwidget.c | 4 | ||||
-rw-r--r-- | test/feh.t | 33 | ||||
-rw-r--r-- | test/no-loadable-files | 2 |
15 files changed, 497 insertions, 299 deletions
@@ -1,3 +1,43 @@ +git HEAD + + * Do not apply --scale-down to the thumbnail window. It will be applied + to windows opened from this, though. + * Patch by Rob Cornish: Respect --image-bg when setting a wallpaper + +Tue, 16 Oct 2012 06:29:58 +0200 Daniel Friesel <derf+feh@finalrewind.org> + +* Release v2.7 + * Add --min-dim and --max-dim options to only process images with certain + dimensions + +Thu, 27 Sep 2012 16:48:48 +0200 Daniel Friesel <derf+feh@finalrewind.org> + +* Release v2.6.3 + * Fix segfault when doing lossless mirror/rotate and jpegexiforient is + not present <https://github.com/derf/feh/issues/100> + +Wed, 26 Sep 2012 17:06:50 +0200 Daniel Friesel <derf+feh@finalrewind.org> + +* Release v2.6.2 + * Set EXIF orientation tag to 1 ("0,0 is top left" aka normal) after + running jpegtran. Previously, when doing a lossless rotate, the image + was rotated but the corresponding EXIF tag not updated, resulting in + wrong image display in programs aware of this EXIF tag. + * Fix spelling in feh(1) + * Compile debug builds with -O0 + +Thu, 13 Sep 2012 12:00:06 +0200 Daniel Friesel <derf+feh@finalrewind.org> + +* Release v2.6.1 + * Fix freedesktop.org Thumbnail Managing Standard implementation: + when running feh on the current working directory, '/path/to/./image.png' + was used for thumbnail name generation. Now it is always + '/path/to/image.png' + * Show error message if lossless rotate / flip failed on non-JPEG image + * Show error message if -O / -o failed to save image + * Show error message if load failed and magick is disabled (was broken + by feh 2.4) + Tue, 28 Aug 2012 11:46:19 +0200 Daniel Friesel <derf+feh@finalrewind.org> * Release v2.6 @@ -32,7 +32,7 @@ else endif ifeq (${debug},1) - CFLAGS += -DDEBUG + CFLAGS += -DDEBUG -O0 MAN_DEBUG = . This is a debug build. else MAN_DEBUG = diff --git a/man/feh.pre b/man/feh.pre index e047286..c60e15a 100644 --- a/man/feh.pre +++ b/man/feh.pre @@ -31,7 +31,7 @@ $MAN_XINERAMA$, builtin EXIF support $MAN_EXIF$$MAN_DEBUG$ .Sh DESCRIPTION . .Nm -is a mode-based image viewer. It is especially aimed at commandline users who +is a mode-based image viewer. It is especially aimed at command line users who need a fast image viewer without huge GUI dependencies, though it can also be started by .Pq graphical @@ -61,7 +61,7 @@ However, if you compile feh with exif=1, you can also display it directly. .Sh MODES . .Nm -is based on various modes, which are selected at startup by comandline +is based on various modes, which are selected at startup by command line options. . .Pp @@ -158,7 +158,7 @@ multiwindow mode, the window will be closed. . .It Cm --action1 No .. Cm --action9 . -Extra actions which can be set and triggered using the appropiate number key. +Extra actions which can be set and triggered using the appropriate number key. . .It Cm -Z , --auto-zoom . @@ -192,7 +192,7 @@ the caption will be looked for in Don't display images, print image info according to .Ar format instead. See -.Sx FORMAT SPECIFIEDRS . +.Sx FORMAT SPECIFIERS . . .It Cm --cycle-once . @@ -246,7 +246,7 @@ will be saved to .Ar file when .Nm -exits. You can add files to filelists by specifying them on the commandline +exits. You can add files to filelists by specifying them on the command line when also specifying the list. . .Pp @@ -287,7 +287,7 @@ Enables . Note: This option needs to load all images to calculate the dimensions of the .Nm -window, so when using it with many files it will ake a while before a +window, so when using it with many files it will take a while before a .Nm window is visible. Use .Cm --preload @@ -329,7 +329,7 @@ Accepted values: checks (default), white, black. .It Cm -i , --index . Enable Index mode. Index mode is similar to montage mode, and accepts the -same options. It creates an index print of thumbails, printing the image +same options. It creates an index print of thumbnails, printing the image name beneath each thumbnail. Index mode enables certain other options, see .Sx INDEX MODE OPTIONS and @@ -377,7 +377,7 @@ in the name. . .It Cm -l , --list . -Don't display images. Analyse them and display an +Don't display images. Analyze them and display an .Xr ls 1 - No style listing. Useful in scripts to hunt out images of a certain size/resolution/type etc. @@ -397,6 +397,15 @@ of zero causes .Nm to try indefinitely. By default, magick support is disabled. . +.It Cm --max-dimension Ar width No x Ar height +. +Only show images with width <= +.Ar width +and height <= +.Ar height . +If you only care about one parameter, set the other to either something large +or -1. +. .It Cm -M , --menu-font Ar font . Use @@ -404,6 +413,14 @@ Use .Pq truetype, with size, like Qq yudit/12 as menu font. . +.It Cm --min-dimension Ar width No x Ar height +. +Only show images with width >= +.Ar width +and height >= +.Ar height . +If you only care about one parameter, set the other to 0. +. .It Cm -m , --montage . Enable montage mode. Montage mode creates a new image consisting of a grid of @@ -541,8 +558,10 @@ theme. Same as Index mode, but the thumbnails are clickable image launchers. Note that .Cm --fullscreen -does not affect the thumbnail window. It does, however, work for the image -windows launched from thumbnail mode. +and +.Cm --scale-down +do not affect the thumbnail window. They do, however, work for image windows +launched from thumbnail mode. Also supports .Sx MONTAGE MODE OPTIONS . . @@ -662,7 +681,7 @@ without displaying it. . Normally, if an image is smaller than the specified thumbnail size, it will not be enlarged. If this option is set, the image will be scaled up to fit -the thumnail size. Aspect ratio will be maintained unles +the thumbnail size. Aspect ratio will be maintained unless .Cm --ignore-aspect is specified. . @@ -715,7 +734,7 @@ can also be used as a background setter. Unless you pass the .Cm --no-fehbg option, it will store the command line necessary to set the background in .Pa ~/.fehbg , -so to have your background restored everytime you start X, you can add +so to have your background restored every time you start X, you can add .Qq eval $(cat ~/.fehbg) to your X startup script .Pq like Pa ~/.xinitrc . @@ -821,7 +840,7 @@ Number of image pixels . .It \&%P . -Numbor of image pixels +Number of image pixels .Pq kilopixels / megapixels . .It %r @@ -1106,6 +1125,16 @@ away. See .Xr jpegtran 1 for more about lossless JPEG rotation. . +.Em Note: +jpegtran does not update EXIF orientation tags. However, +.Nm +assumes that you use the feature to normalize image orientation and want it to +be displayed this way everywhere. After every rotation, it will unconditionally +set the EXIF orientation to 1 +.Pq Qq 0,0 is top left . +Should you need to reverse this, see +.Xr jpegexiforient 1 . +. .It _ Bq flip . In place editing - vertical flip @@ -1453,6 +1482,11 @@ Same as above . Show some EXIF information, extracted by exifprobe/exifgrep . +.It feh --action 'rm %F' -rl --max-dim 1000x800 +. +Resursively remove all images with dimensions below or equal to 1000x800 pixels +from the current directory. +. .El . . @@ -1487,7 +1521,9 @@ but without the flickering. .Nm requires the .Cm jpegtran -binary +and +.Cm jpegexiforient +binaries .Pq usually distributed in Qo libjpeg-progs Qc or similar for lossless rotation. . @@ -157,7 +157,10 @@ void feh_display_status(char stat); void real_loadables_mode(int loadable); void feh_reload_image(winwidget w, int resize, int force_new); void feh_filelist_image_remove(winwidget winwid, char do_delete); +void feh_imlib_print_load_error(char *file, winwidget w, Imlib_Load_Error err); void slideshow_save_image(winwidget win); +void ungib_imlib_save_image_with_error_return(Imlib_Image im, char *file, + Imlib_Load_Error * error_return); void feh_edit_inplace(winwidget w, int orientation); void feh_edit_inplace_lossless(winwidget w, int orientation); gib_list *feh_wrap_string(char *text, int wrap_width, Imlib_Font fn, gib_style * style); diff --git a/src/filelist.c b/src/filelist.c index 920a5ef..542dbdf 100644 --- a/src/filelist.c +++ b/src/filelist.c @@ -281,6 +281,13 @@ gib_list *feh_file_info_preload(gib_list * list) remove_list = gib_list_add_front(remove_list, l); if (opt.verbose) feh_display_status('x'); + } else if (((unsigned int)file->info->width < opt.min_width) + || ((unsigned int)file->info->width > opt.max_width) + || ((unsigned int)file->info->height < opt.min_height) + || ((unsigned int)file->info->height > opt.max_height)) { + remove_list = gib_list_add_front(remove_list, l); + if (opt.verbose) + feh_display_status('s'); } else if (opt.verbose) feh_display_status('.'); } @@ -375,7 +382,8 @@ int feh_cmp_format(void *file1, void *file2) void feh_prepare_filelist(void) { if (opt.list || opt.customlist || (opt.sort > SORT_FILENAME) - || opt.preload) { + || opt.preload || opt.min_width || opt.min_height + || (opt.max_width != UINT_MAX) || (opt.max_height != UINT_MAX)) { /* For these sort options, we have to preload images */ filelist = feh_file_info_preload(filelist); if (!gib_list_length(filelist)) diff --git a/src/imlib.c b/src/imlib.c index af7acdd..e9f92ad 100644 --- a/src/imlib.c +++ b/src/imlib.c @@ -129,6 +129,83 @@ int feh_load_image_char(Imlib_Image * im, char *filename) return(i); } +/* + * XXX gib_imlib_save_image_with_error_return breaks with *.END and + * similar because it tries to set the image format, which only works + * with .end . + * So we leave that part out. + */ +void ungib_imlib_save_image_with_error_return(Imlib_Image im, char *file, + Imlib_Load_Error * error_return) +{ + char *tmp; + imlib_context_set_image(im); + tmp = strrchr(file, '.'); + if (tmp) { + char *p, *pp; + p = gib_estrdup(tmp + 1); + pp = p; + while(*pp) { + *pp = tolower(*pp); + pp++; + } + imlib_image_set_format(p); + gib_efree(p); + } + imlib_save_image_with_error_return(file, error_return); +} + +void feh_imlib_print_load_error(char *file, winwidget w, Imlib_Load_Error err) +{ + if (err == IMLIB_LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS) + eprintf("%s - Out of file descriptors while loading", file); + else if (!opt.quiet || w) { + switch (err) { + case IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST: + im_weprintf(w, "%s - File does not exist", file); + break; + case IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY: + im_weprintf(w, "%s - Directory specified for image filename", file); + break; + case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_READ: + im_weprintf(w, "%s - No read access", file); + break; + case IMLIB_LOAD_ERROR_UNKNOWN: + case IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT: + im_weprintf(w, "%s - No Imlib2 loader for that file format", file); + break; + case IMLIB_LOAD_ERROR_PATH_TOO_LONG: + im_weprintf(w, "%s - Path specified is too long", file); + break; + case IMLIB_LOAD_ERROR_PATH_COMPONENT_NON_EXISTANT: + im_weprintf(w, "%s - Path component does not exist", file); + break; + case IMLIB_LOAD_ERROR_PATH_COMPONENT_NOT_DIRECTORY: + im_weprintf(w, "%s - Path component is not a directory", file); + break; + case IMLIB_LOAD_ERROR_PATH_POINTS_OUTSIDE_ADDRESS_SPACE: + im_weprintf(w, "%s - Path points outside address space", file); + break; + case IMLIB_LOAD_ERROR_TOO_MANY_SYMBOLIC_LINKS: + im_weprintf(w, "%s - Too many levels of symbolic links", file); + break; + case IMLIB_LOAD_ERROR_OUT_OF_MEMORY: + im_weprintf(w, "While loading %s - Out of memory", file); + break; + case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_WRITE: + im_weprintf(w, "%s - Cannot write to directory", file); + break; + case IMLIB_LOAD_ERROR_OUT_OF_DISK_SPACE: + im_weprintf(w, "%s - Cannot write - out of disk space", file); + break; + default: + im_weprintf(w, "While loading %s - Unknown error (%d)", + file, err); + break; + } + } +} + int feh_load_image(Imlib_Image * im, feh_file * file) { Imlib_Load_Error err; @@ -157,10 +234,7 @@ int feh_load_image(Imlib_Image * im, feh_file * file) tmpname = feh_magick_load_image(file->filename); } - if (image_source != SRC_IMLIB) { - if (tmpname == NULL) - return 0; - + if ((image_source != SRC_IMLIB) && tmpname) { *im = imlib_load_image_with_error_return(tmpname, &err); if (im) { real_filename = file->filename; @@ -182,53 +256,7 @@ int feh_load_image(Imlib_Image * im, feh_file * file) fputs("\n", stdout); reset_output = 1; } - if (err == IMLIB_LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS) - eprintf("%s - Out of file descriptors while loading", file->filename); - else if (!opt.quiet) { - switch (err) { - case IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST: - weprintf("%s - File does not exist", file->filename); - break; - case IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY: - weprintf("%s - Directory specified for image filename", file->filename); - break; - case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_READ: - weprintf("%s - No read access", file->filename); - break; - case IMLIB_LOAD_ERROR_UNKNOWN: - case IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT: - weprintf("%s - No Imlib2 loader for that file format", file->filename); - break; - case IMLIB_LOAD_ERROR_PATH_TOO_LONG: - weprintf("%s - Path specified is too long", file->filename); - break; - case IMLIB_LOAD_ERROR_PATH_COMPONENT_NON_EXISTANT: - weprintf("%s - Path component does not exist", file->filename); - break; - case IMLIB_LOAD_ERROR_PATH_COMPONENT_NOT_DIRECTORY: - weprintf("%s - Path component is not a directory", file->filename); - break; - case IMLIB_LOAD_ERROR_PATH_POINTS_OUTSIDE_ADDRESS_SPACE: - weprintf("%s - Path points outside address space", file->filename); - break; - case IMLIB_LOAD_ERROR_TOO_MANY_SYMBOLIC_LINKS: - weprintf("%s - Too many levels of symbolic links", file->filename); - break; - case IMLIB_LOAD_ERROR_OUT_OF_MEMORY: - weprintf("While loading %s - Out of memory", file->filename); - break; - case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_WRITE: - weprintf("%s - Cannot write to directory", file->filename); - break; - case IMLIB_LOAD_ERROR_OUT_OF_DISK_SPACE: - weprintf("%s - Cannot write - out of disk space", file->filename); - break; - default: - weprintf("While loading %s - Unknown error (%d)", - file->filename, err); - break; - } - } + feh_imlib_print_load_error(file->filename, NULL, err); D(("Load *failed*\n")); return(0); } @@ -305,9 +333,6 @@ static char *feh_magick_load_image(char *filename) if (WIFSIGNALED(status)) weprintf("%s - Conversion took too long, skipping", filename); - else - weprintf("%s - No loader for that file format", - filename); } /* @@ -974,6 +999,7 @@ void feh_edit_inplace(winwidget w, int op) { int ret; Imlib_Image old; + Imlib_Load_Error err; if (!w->file || !w->file->data || !FEH_FILE(w->file->data)->filename) return; @@ -993,8 +1019,12 @@ void feh_edit_inplace(winwidget w, int op) imlib_image_flip_horizontal(); } else gib_imlib_image_orientate(old, op); - gib_imlib_save_image(old, FEH_FILE(w->file->data)->filename); + ungib_imlib_save_image_with_error_return(old, + FEH_FILE(w->file->data)->filename, &err); gib_imlib_free_image(old); + if (err) + feh_imlib_print_load_error(FEH_FILE(w->file->data)->filename, + w, err); feh_reload_image(w, 1, 1); } else { im_weprintf(w, "failed to load image from disk to edit it in place"); @@ -1107,6 +1137,7 @@ void feh_edit_inplace_lossless(winwidget w, int op) int len = strlen(filename) + 1; char *file_str = emalloc(len); int pid, status; + int devnull = -1; char op_name[] = "rotate"; /* message */ char op_op[] = "-rotate"; /* jpegtran option */ char op_value[] = "horizontal"; /* jpegtran option's value */ @@ -1126,14 +1157,16 @@ void feh_edit_inplace_lossless(winwidget w, int op) if ((pid = fork()) < 0) { im_weprintf(w, "lossless %s: fork failed:", op_name); exit(1); - } else if (pid == 0) { + } + else if (pid == 0) { execlp("jpegtran", "jpegtran", "-copy", "all", op_op, op_value, "-outfile", file_str, file_str, NULL); im_weprintf(w, "lossless %s: Is 'jpegtran' installed? Failed to exec:", op_name); exit(1); - } else { + } + else { waitpid(pid, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { @@ -1146,6 +1179,30 @@ void feh_edit_inplace_lossless(winwidget w, int op) return; } } + if ((pid = fork()) < 0) { + im_weprintf(w, "lossless %s: cannot fix rotation: fork:", op_name); + exit(1); + } + else if (pid == 0) { + + /* discard normal output */ + devnull = open("/dev/null", O_WRONLY); + dup2(devnull, 1); + + execlp("jpegexiforient", "jpegexiforient", "-1", file_str, NULL); + im_weprintf(w, "lossless %s: Failed to exec jpegexiforient:", op_name); + exit(1); + } + else { + waitpid(pid, &status, 0); + + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + im_weprintf(w, + "lossless %s: Failed to update EXIF orientation tag:" + " jpegexiforient returned %d", + op_name, status >> 8); + } + } free(file_str); } diff --git a/src/index.c b/src/index.c index 023cba0..5d4ed39 100644 --- a/src/index.c +++ b/src/index.c @@ -35,6 +35,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* TODO s/bit/lot */ void init_index_mode(void) { + Imlib_Load_Error err; Imlib_Image im_main; Imlib_Image im_temp; int w = 800, h = 600, ww = 0, hh = 0, www, hhh, xxx, yyy; @@ -326,8 +327,11 @@ void init_index_mode(void) else strncpy(output_buf, opt.output_file, 1024); - gib_imlib_save_image(im_main, output_buf); - if (opt.verbose) { + ungib_imlib_save_image_with_error_return(im_main, output_buf, &err); + if (err) { + feh_imlib_print_load_error(output_buf, im_main, err); + } + else if (opt.verbose) { int tw, th; tw = gib_imlib_image_get_width(im_main); diff --git a/src/options.c b/src/options.c index 09ae5cc..240b0d6 100644 --- a/src/options.c +++ b/src/options.c @@ -60,6 +60,7 @@ void init_parse_options(int argc, char **argv) opt.menu_font = estrdup(DEFAULT_MENU_FONT); opt.font = NULL; opt.menu_bg = estrdup(PREFIX "/share/feh/images/menubg_default.png"); + opt.max_height = opt.max_width = UINT_MAX; opt.start_list_at = NULL; opt.jump_on_resort = 1; @@ -300,77 +301,74 @@ static void feh_getopt_theme(int argc, char **argv) static void feh_parse_option_array(int argc, char **argv, int finalrun) { + int discard; static char stropts[] = "a:A:b:B:cC:dD:e:E:f:Fg:GhH:iIj:J:kK:lL:mM:nNo:O:pPqrR:sS:tT:uUvVwW:xXy:YzZ" - ".@:^:~:):|:+:"; + ".@:^:~:):|:+:<:>:"; /* (*name, has_arg, *flag, val) See: struct option in getopts.h */ static struct option lopts[] = { - {"help" , 0, 0, 'h'}, - {"version" , 0, 0, 'v'}, - {"montage" , 0, 0, 'm'}, - {"collage" , 0, 0, 'c'}, - {"index" , 0, 0, 'i'}, - {"fullindex" , 0, 0, 'I'}, - {"verbose" , 0, 0, 'V'}, - {"borderless" , 0, 0, 'x'}, - {"keep-http" , 0, 0, 'k'}, - {"stretch" , 0, 0, 's'}, - {"multiwindow" , 0, 0, 'w'}, - {"recursive" , 0, 0, 'r'}, - {"randomize" , 0, 0, 'z'}, - {"list" , 0, 0, 'l'}, - {"quiet" , 0, 0, 'q'}, - {"loadable" , 0, 0, 'U'}, - {"unloadable" , 0, 0, 'u'}, - {"no-menus" , 0, 0, 'N'}, + {"menu-bg" , 1, 0, ')'}, + {"debug" , 0, 0, '+'}, + {"scale-down" , 0, 0, '.'}, + {"max-dimension" , 1, 0, '<'}, + {"min-dimension" , 1, 0, '>'}, + {"title-font" , 1, 0, '@'}, + {"action" , 1, 0, 'A'}, + {"image-bg" , 1, 0, 'B'}, + {"fontpath" , 1, 0, 'C'}, + {"slideshow-delay",1, 0, 'D'}, + {"thumb-height" , 1, 0, 'E'}, {"full-screen" , 0, 0, 'F'}, /* deprecated */ {"fullscreen" , 0, 0, 'F'}, - {"auto-zoom" , 0, 0, 'Z'}, - {"ignore-aspect" , 0, 0, 'X'}, - {"draw-filename" , 0, 0, 'd'}, - {"preload" , 0, 0, 'p'}, - {"reverse" , 0, 0, 'n'}, - {"thumbnails" , 0, 0, 't'}, - {"scale-down" , 0, 0, '.'}, - {"no-jump-on-resort", 0, 0, 220}, - {"hide-pointer" , 0, 0, 'Y'}, {"draw-actions" , 0, 0, 'G'}, - {"cache-thumbnails", 0, 0, 'P'}, - {"cycle-once" , 0, 0, 224}, - {"no-xinerama" , 0, 0, 225}, - {"draw-tinted" , 0, 0, 229}, -#ifdef HAVE_LIBEXIF - {"draw-exif" , 0, 0, 223}, -#endif - - {"output" , 1, 0, 'o'}, - {"output-only" , 1, 0, 'O'}, - {"action" , 1, 0, 'A'}, - {"limit-width" , 1, 0, 'W'}, {"limit-height" , 1, 0, 'H'}, + {"fullindex" , 0, 0, 'I'}, + {"thumb-redraw" , 1, 0, 'J'}, + {"caption-path" , 1, 0, 'K'}, + {"customlist" , 1, 0, 'L'}, + {"menu-font" , 1, 0, 'M'}, + {"no-menus" , 0, 0, 'N'}, + {"output-only" , 1, 0, 'O'}, + {"cache-thumbnails", 0, 0, 'P'}, {"reload" , 1, 0, 'R'}, - {"alpha" , 1, 0, 'a'}, {"sort" , 1, 0, 'S'}, {"theme" , 1, 0, 'T'}, + {"loadable" , 0, 0, 'U'}, + {"verbose" , 0, 0, 'V'}, + {"limit-width" , 1, 0, 'W'}, + {"ignore-aspect" , 0, 0, 'X'}, + {"hide-pointer" , 0, 0, 'Y'}, + {"auto-zoom" , 0, 0, 'Z'}, + {"title" , 1, 0, '^'}, + {"alpha" , 1, 0, 'a'}, + {"bg" , 1, 0, 'b'}, + {"collage" , 0, 0, 'c'}, + {"draw-filename" , 0, 0, 'd'}, + {"font" , 1, 0, 'e'}, {"filelist" , 1, 0, 'f'}, - {"customlist" , 1, 0, 'L'}, {"geometry" , 1, 0, 'g'}, - {"menu-font" , 1, 0, 'M'}, + {"help" , 0, 0, 'h'}, + {"index" , 0, 0, 'i'}, + {"output-dir" , 1, 0, 'j'}, + {"keep-http" , 0, 0, 'k'}, + {"list" , 0, 0, 'l'}, + {"montage" , 0, 0, 'm'}, + {"reverse" , 0, 0, 'n'}, + {"output" , 1, 0, 'o'}, + {"preload" , 0, 0, 'p'}, + {"quiet" , 0, 0, 'q'}, + {"recursive" , 0, 0, 'r'}, + {"stretch" , 0, 0, 's'}, + {"thumbnails" , 0, 0, 't'}, + {"unloadable" , 0, 0, 'u'}, + {"version" , 0, 0, 'v'}, + {"multiwindow" , 0, 0, 'w'}, + {"borderless" , 0, 0, 'x'}, {"thumb-width" , 1, 0, 'y'}, - {"thumb-height" , 1, 0, 'E'}, - {"slideshow-delay",1, 0, 'D'}, - {"font" , 1, 0, 'e'}, - {"title-font" , 1, 0, '@'}, - {"title" , 1, 0, '^'}, - {"thumb-title" , 1, 0, '~'}, - {"bg" , 1, 0, 'b'}, - {"fontpath" , 1, 0, 'C'}, - {"menu-bg" , 1, 0, ')'}, - {"image-bg" , 1, 0, 'B'}, + {"randomize" , 0, 0, 'z'}, {"start-at" , 1, 0, '|'}, - {"debug" , 0, 0, '+'}, - {"output-dir" , 1, 0, 'j'}, + {"thumb-title" , 1, 0, '~'}, {"bg-tile" , 0, 0, 200}, {"bg-center" , 0, 0, 201}, {"bg-scale" , 0, 0, 202}, @@ -378,7 +376,6 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun) {"no-screen-clip", 0, 0, 206}, {"index-info" , 1, 0, 207}, {"magick-timeout", 1, 0, 208}, - {"caption-path" , 1, 0, 'K'}, {"action1" , 1, 0, 209}, {"action2" , 1, 0, 210}, {"action3" , 1, 0, 211}, @@ -390,7 +387,13 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun) {"action9" , 1, 0, 217}, {"bg-fill" , 0, 0, 218}, {"bg-max" , 0, 0, 219}, - {"thumb-redraw" , 1, 0, 'J'}, + {"no-jump-on-resort", 0, 0, 220}, +#ifdef HAVE_LIBEXIF + {"draw-exif" , 0, 0, 223}, +#endif + {"cycle-once" , 0, 0, 224}, + {"no-xinerama" , 0, 0, 225}, + {"draw-tinted" , 0, 0, 229}, {"info" , 1, 0, 234}, {"force-aliasing", 0, 0, 235}, {"no-fehbg" , 0, 0, 236}, @@ -399,38 +402,76 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun) }; int optch = 0, cmdx = 0; - /* Now to pass some optionarinos */ while ((optch = getopt_long(argc, argv, stropts, lopts, &cmdx)) != EOF) { D(("Got option, getopt calls it %d, or %c\n", optch, optch)); switch (optch) { case 0: break; - case 'h': - show_usage(); + case ')': + free(opt.menu_bg); + opt.menu_bg = estrdup(optarg); + weprintf("The --menu-bg option is deprecated and will be removed by 2012"); break; - case 'v': - show_version(); + case '+': + opt.debug = 1; break; - case 'm': - opt.index = 1; + case '<': + XParseGeometry(optarg, &discard, &discard, &opt.max_width, &opt.max_height); break; - case 'c': - opt.collage = 1; - break; - case 'i': - opt.index = 1; - opt.index_info = estrdup("%n"); + case '>': + XParseGeometry(optarg, &discard, &discard, &opt.min_width, &opt.min_height); break; case '.': opt.scale_down = 1; break; + case '@': + opt.title_font = estrdup(optarg); + break; + case 'A': + opt.actions[0] = estrdup(optarg); + break; + case 'B': + if (!strcmp(optarg, "checks")) + opt.image_bg = IMAGE_BG_CHECKS; + else if (!strcmp(optarg, "white")) + opt.image_bg = IMAGE_BG_WHITE; + else if (!strcmp(optarg, "black")) + opt.image_bg = IMAGE_BG_BLACK; + else + weprintf("Unknown argument to --image-bg: %s", optarg); + break; + case 'C': + D(("adding fontpath %s\n", optarg)); + imlib_add_path_to_font_path(optarg); + break; + case 'D': + opt.slideshow_delay = atof(optarg); + if (opt.slideshow_delay < 0.0) { + opt.slideshow_delay *= (-1); + opt.paused = 1; + } + break; + case 'E': + opt.thumb_h = atoi(optarg); + break; + case 'F': + opt.full_screen = 1; + break; + case 'G': + opt.draw_actions = 1; + break; + case 'H': + opt.limit_h = atoi(optarg); + break; case 'I': opt.index = 1; opt.index_info = estrdup("%n\n%S\n%wx%h"); break; - case 'l': - opt.list = 1; - opt.display = 0; + case 'J': + opt.thumb_redraw = atoi(optarg); + break; + case 'K': + opt.caption_path = estrdup(optarg); break; case 'L': opt.customlist = estrdup(optarg); @@ -440,64 +481,19 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun) free(opt.menu_font); opt.menu_font = estrdup(optarg); break; - case '+': - opt.debug = 1; - break; - case 'n': - opt.reverse = 1; - break; - case 'g': - opt.geom_flags = XParseGeometry(optarg, &opt.geom_x, &opt.geom_y, &opt.geom_w, &opt.geom_h); - break; case 'N': opt.no_menus = 1; break; - case 'V': - opt.verbose = 1; - break; - case 'q': - opt.quiet = 1; - break; - case 'x': - opt.borderless = 1; - break; - case 'k': - opt.keep_http = 1; - break; - case 's': - opt.stretch = 1; - break; - case 'w': - opt.multiwindow = 1; - break; - case 'r': - opt.recursive = 1; - break; - case 'z': - opt.randomize = 1; - break; - case 'd': - opt.draw_filename = 1; - break; - case 'F': - opt.full_screen = 1; - break; - case 'Z': - opt.zoom_mode = ZOOM_MODE_MAX; - break; - case 'U': - opt.loadables = 1; - opt.display = 0; - break; - case 'u': - opt.unloadables = 1; + case 'O': + opt.output = 1; + opt.output_file = estrdup(optarg); opt.display = 0; break; - case 'p': - opt.preload = 1; + case 'P': + opt.cache_thumbnails = 1; break; - case 'X': - opt.aspect = 0; + case 'R': + opt.reload = atof(optarg); break; case 'S': if (!strcasecmp(optarg, "name")) @@ -520,97 +516,125 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun) opt.sort = SORT_FILENAME; } break; - case 'o': - opt.output = 1; - opt.output_file = estrdup(optarg); + case 'T': + theme = estrdup(optarg); break; - case 'O': - opt.output = 1; - opt.output_file = estrdup(optarg); + case 'U': + opt.loadables = 1; opt.display = 0; break; - case 'T': - theme = estrdup(optarg); + case 'V': + opt.verbose = 1; break; - case 'C': - D(("adding fontpath %s\n", optarg)); - imlib_add_path_to_font_path(optarg); + case 'W': + opt.limit_w = atoi(optarg); break; - case 'e': - opt.font = estrdup(optarg); + case 'X': + opt.aspect = 0; break; - case '@': - opt.title_font = estrdup(optarg); + case 'Y': + opt.hide_pointer = 1; + break; + case 'Z': + opt.zoom_mode = ZOOM_MODE_MAX; break; case '^': opt.title = estrdup(optarg); break; - case '~': - opt.thumb_title = estrdup(optarg); + case 'a': + opt.alpha = 1; + opt.alpha_level = 255 - atoi(optarg); break; case 'b': opt.bg = 1; opt.bg_file = estrdup(optarg); break; - case 'A': - opt.actions[0] = estrdup(optarg); + case 'c': + opt.collage = 1; break; - case 'W': - opt.limit_w = atoi(optarg); + case 'd': + opt.draw_filename = 1; break; - case 'H': - opt.limit_h = atoi(optarg); + case 'e': + opt.font = estrdup(optarg); break; - case 'y': - opt.thumb_w = atoi(optarg); + case 'f': + if (!strcmp(optarg, "-")) + opt.filelistfile = estrdup("/dev/stdin"); + else + opt.filelistfile = estrdup(optarg); break; - case 'E': - opt.thumb_h = atoi(optarg); + case 'g': + opt.geom_flags = XParseGeometry(optarg, &opt.geom_x, + &opt.geom_y, &opt.geom_w, &opt.geom_h); break; - case ')': - free(opt.menu_bg); - opt.menu_bg = estrdup(optarg); - weprintf("The --menu-bg option is deprecated and will be removed by 2012"); + case 'h': + show_usage(); break; - case 'B': - if (!strcmp(optarg, "checks")) - opt.image_bg = IMAGE_BG_CHECKS; - else if (!strcmp(optarg, "white")) - opt.image_bg = IMAGE_BG_WHITE; - else if (!strcmp(optarg, "black")) - opt.image_bg = IMAGE_BG_BLACK; - else - weprintf("Unknown argument to --image-bg: %s", optarg); + case 'i': + opt.index = 1; + opt.index_info = estrdup("%n"); break; - case 'D': - opt.slideshow_delay = atof(optarg); - if (opt.slideshow_delay < 0.0) { - opt.slideshow_delay *= (-1); - opt.paused = 1; - } + case 'j': + opt.output_dir = estrdup(optarg); break; - case 'R': - opt.reload = atof(optarg); + case 'k': + opt.keep_http = 1; break; - case 'a': - opt.alpha = 1; - opt.alpha_level = 255 - atoi(optarg); + case 'l': + opt.list = 1; + opt.display = 0; break; - case 'f': - if (!strcmp(optarg, "-")) - opt.filelistfile = estrdup("/dev/stdin"); - else - opt.filelistfile = estrdup(optarg); + case 'm': + opt.index = 1; break; - case '|': - opt.start_list_at = estrdup(optarg); + case 'n': + opt.reverse = 1; + break; + case 'o': + opt.output = 1; + opt.output_file = estrdup(optarg); + break; + case 'p': + opt.preload = 1; + break; + case 'q': + opt.quiet = 1; + break; + case 'r': + opt.recursive = 1; + break; + case 's': + opt.stretch = 1; break; case 't': opt.thumbs = 1; opt.index_info = estrdup("%n"); break; - case 'j': - opt.output_dir = estrdup(optarg); + case 'u': + opt.unloadables = 1; + opt.display = 0; + break; + case 'v': + show_version(); + break; + case 'w': + opt.multiwindow = 1; + break; + case 'x': + opt.borderless = 1; + break; + case 'y': + opt.thumb_w = atoi(optarg); + break; + case 'z': + opt.randomize = 1; + break; + case '|': + opt.start_list_at = estrdup(optarg); + break; + case '~': + opt.thumb_title = estrdup(optarg); break; case 200: opt.bgmode = BG_MODE_TILE; @@ -621,12 +645,6 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun) case 202: opt.bgmode = BG_MODE_SCALE; break; - case 218: - opt.bgmode = BG_MODE_FILL; - break; - case 219: - opt.bgmode = BG_MODE_MAX; - break; case 205: if (!strcmp("fill", optarg)) opt.zoom_mode = ZOOM_MODE_FILL; @@ -644,9 +662,6 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun) case 208: opt.magick_timeout = atoi(optarg); break; - case 'K': - opt.caption_path = estrdup(optarg); - break; case 209: opt.actions[1] = estrdup(optarg); break; @@ -674,17 +689,14 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun) case 217: opt.actions[9] = estrdup(optarg); break; - case 220: - opt.jump_on_resort = 0; - break; - case 'Y': - opt.hide_pointer = 1; + case 218: + opt.bgmode = BG_MODE_FILL; break; - case 'G': - opt.draw_actions = 1; + case 219: + opt.bgmode = BG_MODE_MAX; break; - case 'P': - opt.cache_thumbnails = 1; + case 220: + opt.jump_on_resort = 0; break; #ifdef HAVE_LIBEXIF case 223: @@ -700,9 +712,6 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun) case 229: opt.text_bg = TEXT_BG_TINTED; break; - case 'J': - opt.thumb_redraw = atoi(optarg); - break; case 234: opt.info_cmd = estrdup(optarg); opt.draw_info = 1; diff --git a/src/options.h b/src/options.h index a763642..d30c396 100644 --- a/src/options.h +++ b/src/options.h @@ -109,6 +109,8 @@ struct __fehoptions { int zoom_mode; unsigned char adjust_reload; + unsigned int min_width, min_height, max_width, max_height; + unsigned char mode; unsigned char paused; diff --git a/src/slideshow.c b/src/slideshow.c index cec146c..60bd99c 100644 --- a/src/slideshow.c +++ b/src/slideshow.c @@ -594,16 +594,10 @@ void slideshow_save_image(winwidget win) if (opt.verbose) printf("saving image to filename '%s'\n", tmpname); - /* XXX gib_imlib_save_image_with_error_return breaks with *.XXX and - * similar because it tries to set the image format, which only works - * with .xxx . - * So we leave that part out. - */ - imlib_context_set_image(win->im); - imlib_save_image_with_error_return(tmpname, &err); + ungib_imlib_save_image_with_error_return(win->im, tmpname, &err); if (err) - im_weprintf(win, "Can't save image %s:", tmpname); + feh_imlib_print_load_error(tmpname, win, err); free(tmpname); return; diff --git a/src/thumbnail.c b/src/thumbnail.c index b26dc7f..fbe2ce0 100644 --- a/src/thumbnail.c +++ b/src/thumbnail.c @@ -55,6 +55,7 @@ void init_thumbnail_mode(void) int max_column_w = 0; */ + Imlib_Load_Error err; Imlib_Image im_temp; int ww = 0, hh = 0, www, hhh, xxx, yyy; int orig_w, orig_h; @@ -381,8 +382,11 @@ void init_thumbnail_mode(void) snprintf(output_buf, 1024, "%s/%s", opt.output_dir, opt.output_file); else strncpy(output_buf, opt.output_file, 1024); - gib_imlib_save_image(td.im_main, output_buf); - if (opt.verbose) { + ungib_imlib_save_image_with_error_return(td.im_main, output_buf, &err); + if (err) { + feh_imlib_print_load_error(output_buf, td.im_main, err); + } + else if (opt.verbose) { int tw, th; tw = gib_imlib_image_get_width(td.im_main); @@ -596,6 +600,9 @@ char *feh_thumbnail_get_name_uri(char *name) /* FIXME: add support for ~, need to investigate if it's expanded somewhere else before adding (unecessary) code */ if (name[0] != '/') { + /* work around /some/path/./image.ext */ + if ((strncmp(name, "./", 2)) == 0) + name += 2; cwd = getcwd(NULL, 0); uri = estrjoin("/", "file:/", cwd, name, NULL); free(cwd); diff --git a/src/wallpaper.c b/src/wallpaper.c index 8a4cafb..df78303 100644 --- a/src/wallpaper.c +++ b/src/wallpaper.c @@ -257,6 +257,8 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled, char *home; char filbuf[4096]; char fehbg_xinerama[] = "--no-xinerama"; + char *bgfill = NULL; + bgfill = opt.image_bg == IMAGE_BG_WHITE ? "--image-bg white" : "--image-bg black" ; /* local display to set closedownmode on */ Display *disp2; @@ -326,7 +328,10 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled, D(("centering\n")); pmap_d1 = XCreatePixmap(disp, root, scr->width, scr->height, depth); - gcval.foreground = BlackPixel(disp, DefaultScreen(disp)); + if (opt.image_bg == IMAGE_BG_WHITE) + gcval.foreground = WhitePixel(disp, DefaultScreen(disp)); + else + gcval.foreground = BlackPixel(disp, DefaultScreen(disp)); gc = XCreateGC(disp, root, GCForeground, &gcval); XFillRectangle(disp, pmap_d1, gc, 0, 0, scr->width, scr->height); @@ -343,7 +348,7 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled, XFreeGC(disp, gc); - fehbg = estrjoin(" ", "feh", fehbg_xinerama, "--bg-center", filbuf, NULL); + fehbg = estrjoin(" ", "feh", fehbg_xinerama, bgfill, "--bg-center", filbuf, NULL); } else if (filled == 1) { @@ -366,6 +371,10 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled, XGCValues gcval; pmap_d1 = XCreatePixmap(disp, root, scr->width, scr->height, depth); + if (opt.image_bg == IMAGE_BG_WHITE) + gcval.foreground = WhitePixel(disp, DefaultScreen(disp)); + else + gcval.foreground = BlackPixel(disp, DefaultScreen(disp)); gcval.foreground = BlackPixel(disp, DefaultScreen(disp)); gc = XCreateGC(disp, root, GCForeground, &gcval); XFillRectangle(disp, pmap_d1, gc, 0, 0, scr->width, scr->height); @@ -383,7 +392,7 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled, XFreeGC(disp, gc); - fehbg = estrjoin(" ", "feh", fehbg_xinerama, "--bg-max", filbuf, NULL); + fehbg = estrjoin(" ", "feh", fehbg_xinerama, bgfill, "--bg-max", filbuf, NULL); } else { if (use_filelist) diff --git a/src/winwidget.c b/src/winwidget.c index 0a9adc8..2f543df 100644 --- a/src/winwidget.c +++ b/src/winwidget.c @@ -402,6 +402,7 @@ void winwidget_render_image(winwidget winwid, int resize, int force_alias) if (!winwid->full_screen && opt.scale_down && ((winwid->w < winwid->im_w) || (winwid->h < winwid->im_h)) && + (winwid->type != WIN_TYPE_THUMBNAIL) && (winwid->old_zoom == 1.0)) { D(("scaling down image %dx%d\n", winwid->w, winwid->h)); @@ -512,7 +513,8 @@ void winwidget_render_image(winwidget winwid, int resize, int force_alias) winwid->im_y = (int) (max_h - (winwid->im_h * winwid->zoom)) >> 1; } } - else if (need_center && !winwid->full_screen && opt.scale_down) { + else if (need_center && !winwid->full_screen && opt.scale_down + && (winwid->type != WIN_TYPE_THUMBNAIL)) { winwid->im_x = (int) (winwid->w - (winwid->im_w * winwid->zoom)) >> 1; winwid->im_y = (int) (winwid->h - (winwid->im_h * winwid->zoom)) >> 1; } @@ -2,13 +2,14 @@ use strict; use warnings; use 5.010; -use Test::Command tests => 59; +use Test::Command tests => 71; $ENV{HOME} = 'test'; my $feh = "src/feh"; -my $images = 'test/ok/gif test/ok/jpg test/ok/png test/ok/pnm ' - . 'test/fail/gif test/fail/jpg test/fail/png test/fail/pnm'; +my $images_ok = 'test/ok/gif test/ok/jpg test/ok/png test/ok/pnm'; +my $images_fail = 'test/fail/gif test/fail/jpg test/fail/png test/fail/pnm'; +my $images = "${images_ok} ${images_fail}"; my $feh_name = $ENV{'PACKAGE'}; @@ -33,7 +34,7 @@ if (length($feh_name) == 0) { } my $re_warning = - qr{${feh_name} WARNING: test/fail/... \- No loader for that file format\n}; + qr{${feh_name} WARNING: test/fail/... \- No Imlib2 loader for that file format\n}; my $re_loadable = qr{test/ok/...}; my $re_unloadable = qr{test/fail/...}; my $re_list_action = qr{test/ok/... 16x16}; @@ -133,3 +134,27 @@ $cmd = Test::Command->new(cmd => $cmd->exit_is_num(0); $cmd->stdout_is_file('test/list/default'); $cmd->stderr_like($re_list_action); + +$cmd = Test::Command->new(cmd => "$feh --list --min-dimension 20x20 $images_ok"); + +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(''); +$cmd->stderr_is_file('test/no-loadable-files'); + +$cmd = Test::Command->new(cmd => "$feh --list --max-dimension 10x10 $images_ok"); + +$cmd->exit_is_num(1); +$cmd->stdout_is_eq(''); +$cmd->stderr_is_file('test/no-loadable-files'); + +$cmd = Test::Command->new(cmd => "$feh --list --min-dimension 16x16 $images_ok"); + +$cmd->exit_is_num(0); +$cmd->stdout_is_file('test/list/default'); +$cmd->stderr_is_eq(''); + +$cmd = Test::Command->new(cmd => "$feh --list --max-dimension 16x16 $images_ok"); + +$cmd->exit_is_num(0); +$cmd->stdout_is_file('test/list/default'); +$cmd->stderr_is_eq(''); diff --git a/test/no-loadable-files b/test/no-loadable-files new file mode 100644 index 0000000..bc5871d --- /dev/null +++ b/test/no-loadable-files @@ -0,0 +1,2 @@ +feh: No loadable images specified. +See 'man feh' for detailed usage information |