diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | COPYING | 1 | ||||
-rw-r--r-- | ChangeLog | 64 | ||||
-rw-r--r-- | Makefile | 16 | ||||
-rw-r--r-- | README | 40 | ||||
-rw-r--r-- | TODO | 40 | ||||
-rw-r--r-- | config.mk | 38 | ||||
-rw-r--r-- | examples/keys | 45 | ||||
-rw-r--r-- | examples/themes (renamed from src/fehrc.raw) | 34 | ||||
-rw-r--r-- | man/Makefile | 3 | ||||
-rw-r--r-- | man/feh.pre | 581 | ||||
-rwxr-xr-x | scripts/checkkeys.pl | 91 | ||||
-rwxr-xr-x | scripts/lskeys.pl | 20 | ||||
-rw-r--r-- | share/fonts/black.style (renamed from data/fonts/black.style) | 0 | ||||
-rw-r--r-- | share/fonts/menu.style (renamed from data/fonts/menu.style) | 0 | ||||
-rw-r--r-- | share/fonts/yudit.ttf (renamed from data/fonts/yudit.ttf) | bin | 57708 -> 57708 bytes | |||
-rw-r--r-- | share/images/about.png (renamed from data/images/about.png) | bin | 61171 -> 61171 bytes | |||
-rw-r--r-- | share/images/logo.svg (renamed from data/images/logo.svg) | 0 | ||||
-rw-r--r-- | share/images/menubg_aluminium.png (renamed from data/images/menubg_aluminium.png) | bin | 1862 -> 1862 bytes | |||
-rw-r--r-- | share/images/menubg_aqua.png (renamed from data/images/menubg_aqua.png) | bin | 5325 -> 5325 bytes | |||
-rw-r--r-- | share/images/menubg_black.png (renamed from data/images/menubg_black.png) | bin | 1716 -> 1716 bytes | |||
-rw-r--r-- | share/images/menubg_brushed.png (renamed from data/images/menubg_brushed.png) | bin | 8649 -> 8649 bytes | |||
-rw-r--r-- | share/images/menubg_default.png (renamed from data/images/menubg_default.png) | bin | 209 -> 209 bytes | |||
-rw-r--r-- | share/images/menubg_sky.png (renamed from data/images/menubg_sky.png) | bin | 1928 -> 1928 bytes | |||
-rw-r--r-- | src/collage.c | 1 | ||||
-rw-r--r-- | src/debug.h | 1 | ||||
-rw-r--r-- | src/deps.mk | 41 | ||||
-rw-r--r-- | src/events.c | 21 | ||||
-rw-r--r-- | src/feh.h | 5 | ||||
-rw-r--r-- | src/feh_png.c | 6 | ||||
-rw-r--r-- | src/filelist.c | 1 | ||||
-rw-r--r-- | src/help.raw | 17 | ||||
-rw-r--r-- | src/imlib.c | 307 | ||||
-rw-r--r-- | src/index.c | 1 | ||||
-rw-r--r-- | src/keyevents.c | 635 | ||||
-rw-r--r-- | src/list.c | 1 | ||||
-rw-r--r-- | src/main.c | 5 | ||||
-rw-r--r-- | src/menu.c | 18 | ||||
-rw-r--r-- | src/menu.h | 1 | ||||
-rw-r--r-- | src/multiwindow.c | 4 | ||||
-rw-r--r-- | src/options.c | 189 | ||||
-rw-r--r-- | src/options.h | 69 | ||||
-rw-r--r-- | src/signals.c | 5 | ||||
-rw-r--r-- | src/slideshow.c | 42 | ||||
-rw-r--r-- | src/structs.h | 3 | ||||
-rw-r--r-- | src/support.c | 174 | ||||
-rw-r--r-- | src/support.h | 1 | ||||
-rw-r--r-- | src/thumbnail.c | 54 | ||||
-rw-r--r-- | src/thumbnail.h | 7 | ||||
-rw-r--r-- | src/timers.c | 1 | ||||
-rw-r--r-- | src/winwidget.c | 39 | ||||
-rw-r--r-- | src/winwidget.h | 6 | ||||
-rw-r--r-- | test/config/keys/feh/keys | 17 | ||||
-rw-r--r-- | test/config/themes/feh/themes | 5 | ||||
-rwxr-xr-x | test/feh-bg.i | 3 | ||||
-rwxr-xr-x | test/feh-scr.i | 2 | ||||
-rwxr-xr-x | test/feh.i | 112 | ||||
-rw-r--r-- | test/feh.t | 78 | ||||
-rw-r--r-- | test/list/filename_recursive | 6 | ||||
-rw-r--r-- | test/nx_action/loadable_action | 8 | ||||
-rw-r--r-- | test/nx_action/loadable_naction | 8 | ||||
-rw-r--r-- | test/nx_action/unloadable_action | 8 | ||||
-rw-r--r-- | test/nx_action/unloadable_naction | 8 | ||||
-rw-r--r-- | test/ok/recursive/png | bin | 0 -> 403 bytes | |||
-rw-r--r-- | test/scr/caption_done | bin | 9669 -> 9603 bytes | |||
-rw-r--r-- | test/scr/caption_new | bin | 19333 -> 19221 bytes | |||
-rw-r--r-- | test/scr/caption_while | bin | 21458 -> 21269 bytes | |||
-rw-r--r-- | test/scr/draw_action | bin | 8315 -> 8287 bytes | |||
-rw-r--r-- | test/scr/draw_all_multi | bin | 11416 -> 11334 bytes | |||
-rw-r--r-- | test/scr/draw_all_one | bin | 11113 -> 11045 bytes | |||
-rw-r--r-- | test/scr/draw_filename | bin | 7796 -> 7804 bytes | |||
-rw-r--r-- | test/scr/draw_filename_action | bin | 9549 -> 9525 bytes | |||
-rw-r--r-- | test/scr/feh_lhi_iir | bin | 15536 -> 15431 bytes | |||
-rw-r--r-- | test/scr/feh_lhi_iirr | bin | 15431 -> 15400 bytes | |||
-rw-r--r-- | test/scr/feh_lhi_iirri | bin | 64012 -> 63970 bytes | |||
-rw-r--r-- | test/scr/feh_lhi_iirrio | bin | 72552 -> 72012 bytes | |||
-rw-r--r-- | test/scr/feh_lhi_o | bin | 120797 -> 20132 bytes | |||
-rw-r--r-- | test/scr/feh_lhi_oo | bin | 131624 -> 32053 bytes | |||
-rw-r--r-- | test/scr/feh_lhi_ooo | bin | 141170 -> 136692 bytes | |||
-rw-r--r-- | test/scr/feh_lwi_scroll_r | bin | 19072 -> 19066 bytes | |||
-rw-r--r-- | test/scr/feh_lwi_scroll_rd | bin | 19081 -> 19075 bytes | |||
-rw-r--r-- | test/scr/feh_lwi_scroll_rdr | bin | 19075 -> 19188 bytes | |||
-rw-r--r-- | test/scr/feh_lwi_scroll_rdru | bin | 19066 -> 19143 bytes | |||
-rw-r--r-- | test/scr/feh_lwi_scroll_rdrul | bin | 19072 -> 19066 bytes | |||
-rw-r--r-- | test/scr/thumbnail_default | bin | 1712 -> 1712 bytes | |||
-rw-r--r-- | test/status | 419 |
86 files changed, 2352 insertions, 951 deletions
@@ -1,3 +1,4 @@ +/src/deps.mk /src/*.o /src/*.inc /src/feh @@ -1,4 +1,5 @@ Copyright (C) 1999,2000 Tom Gilbert. +Copyright (C) 2010,2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -1,9 +1,69 @@ git HEAD + * Only create caption directory when actually writing out a caption. + <http://github.com/derf/feh/issues/42> + * The --menu-bg option has been deprecated. It will be removed along with + --menu-style by the end of 2012. + <http://github.com/derf/feh/issues/27> + +Sat, 23 Apr 2011 22:00:27 +0200 Daniel Friesel <derf@finalrewind.org> + +* Release v1.13 + * Fix segfault upon unloadable images when image-related format specifiers + (e.g. %h) are used in --title + * Show images in current directory when invoked without file arguments + * Option to disable antialiasing, either global (--force-aliasing) or per + image (press 'A' to toggle, keybinding toggle_aliasing) + * Use SIGUSR1/SIGUSR2 to reload all images in multiwindow mode + * Fix Imlib2 caching bug in reload (only worked after the second try) + * The --bg options are now Xinerama-aware. That is, they set the image in + the respective mode (scale/fill/max/center) on each Xinerama screen. Use + --no-xinerama to disable this. + +Sat, 12 Mar 2011 22:49:53 +0100 Daniel Friesel <derf@finalrewind.org> + +* Release v1.12 + * Add --zoom fill as equivalent for --auto-zoom + * Add --zoom max (zooming like in --bg-max) + * --menu-style is now deprecated + * http images are now viewed using libcurl, not wget (thanks to talisein) + This adds libcurl as dependency, and removes the wget recommendation + * Slight build system change: make now has flags, e.g. + "make xinerama=0 debug=1". By default feh is compiled with xinerama and + libcurl support enabled, see README. + * Remove builtin http client (--builtin) + * Fix compilation issues with libpng 1.5.1 + +Wed, 09 Feb 2011 20:11:26 +0100 Daniel Friesel <derf@finalrewind.org> + +* Release v1.11.2 + * Use wget --no-clobber to prevent TOCTTOU-based hole allowing a + well-informed attacker to rewrite arbitrary user files with images. + The attacker needs to know feh's PID and the URL the user gave it. + It is still possible for an attacker to _create_ arbitrary files via the + same hole. + +Wed, 26 Jan 2011 21:07:19 +0100 Daniel Friesel <derf@finalrewind.org> + +* Release v1.11.1 + * Show correct image dimensions in for cached thumbnails + * Allow commandline options to override those set in a theme + * Remove support for FEH_OPTIONS (was deprecated >5 years ago) + * Restrict available modifiers to Control/Mod1/Mod4 + +Sat, 22 Jan 2011 11:48:33 +0100 Daniel Friesel <derf@finalrewind.org> + +* Release v1.11 * Patch by Pascal Bleser: Use getaddrinfo for builtin http client, this enables IPv6 support - -Fri, 03 Dec 2010 19:41:45 +0100 + * Fix zooming when --scale-down is used + * The themes are now read from ~/.config/feh/themes (BC for .fehrc exists) + * Key bindings can now be configured via ~/.config/feh/keys + * Removes --rcpath, use XDG_CONFIG_HOME instead + * Increase movement steps for Ctrl+Left etc. + * Make in/out zoom use equal zoom ratio + +Fri, 03 Dec 2010 19:41:45 +0100 Daniel Friesel <derf@finalrewind.org> * Release v1.10.1 * Partially fix --scale-down behaviour (zooming is still broken) @@ -9,13 +9,14 @@ build-man: @${MAKE} -C man test: all - @PACKAGE=${PACKAGE} VERSION=${VERSION} prove test + @PACKAGE=${PACKAGE} prove test test-x11: all test/run-interactive prove test/feh-bg.i install: install-man install-doc install-bin install-font install-img +install: install-examples install-man: @echo installing manuals to ${man_dir} @@ -40,15 +41,21 @@ install-bin: install-font: @echo installing fonts to ${font_dir} @mkdir -p ${font_dir} - @cp data/fonts/* ${font_dir} + @cp share/fonts/* ${font_dir} @chmod 644 ${font_dir}/* install-img: @echo installing images to ${image_dir} @mkdir -p ${image_dir} - @cp data/images/* ${image_dir} + @cp share/images/* ${image_dir} @chmod 644 ${image_dir}/* +install-examples: + @echo installing examples to ${example_dir} + @mkdir -p ${example_dir} + @cp examples/* ${example_dir} + @chmod 644 ${example_dir}/* + uninstall: rm -f ${man_dir}/man1/feh.1 ${man_dir}/man1/feh-cam.1 @@ -61,6 +68,7 @@ uninstall: dist: mkdir /tmp/feh-${VERSION} git --work-tree=/tmp/feh-${VERSION} checkout -f + cp src/deps.mk /tmp/feh-${VERSION}/src/deps.mk sed -i 's/^VERSION ?= .*$$/VERSION ?= ${VERSION}/' \ /tmp/feh-${VERSION}/config.mk tar -C /tmp -cjf ../feh-${VERSION}.tar.bz2 feh-${VERSION} @@ -79,4 +87,4 @@ clean: @${MAKE} -C man clean .PHONY: all test test-x11 install uninstall clean install-man install-doc \ - install-bin install-font install-img dist + install-bin install-font install-img install-examples dist @@ -1,30 +1,44 @@ feh - Imlib2 based image viewer +------------------------------- - * <https://derf.homelinux.org/p/feh/> + * <http://feh.finalrewind.org/> * <http://linuxbrit.co.uk/feh/> + * #feh on irc.oftc.net - -Dependencies: +Dependencies +------------ * giblib * Imlib2 + * libcurl (disable with make curl=0) * libpng * libX11 + * libXinerama (disable with make xinerama=0) - -Recommended: +Recommended +----------- * jpegtran (supplied by the jpeg library, for lossless image rotation) - * wget (for http/ftp support) - -Installation: +Installation +------------ $ make $ sudo make install -If compilation does not work or you want to customize stuff (like disable -Xinerama support), edit config.mk first. +Make flags +---------- + +Use "make flag=bool", e.g. "make xinerama=0 debug=1" to disable Xinerama +support and get a debug build. + +Available flags are: + + * curl (default 1) - use libcurl to view http:// and similar images + * debug (default 0) - debug build, enables --debug + * xinerama (default 1) - Support Xinerama multiscreen setups + +So, by default libcurl and Xinerama are enabled, while debug is disabled. Note: config.mk is designed so that in most cases, you can set environment variables instead of editing it. E.g.: @@ -32,7 +46,8 @@ CFLAGS='-g -Os' make export DESTDIR=/tmp/feh PREFIX=/usr; make && make install -Testing (non-X): +Testing (non-X) +--------------- $ make test @@ -40,7 +55,8 @@ Requires perl >= 5.10 with Test::Command. The tests are non-interactive and work without X, so they can safely be run even on a headless buildserver. -Testing (X): +Testing (X) +----------- Requires * import (usually supplied by imagemagick) @@ -1,39 +1 @@ -See also: <http://github.com/derf/feh/issues> - -key/option/signal/timeout to totally reload filelist (rescan directories etc) - -<keypad begin> antialieses the image, but doing that automatically upon -key release would be better. However, I couldn't find a way to do that so far. -Even when holding down a key, everytime the eventloop runs I get a -KeyRelease event. - ---thumb-title covers a very specific case, would be cool to make this more -general (usable in index mode, as image info in thumbnail mode, etc.) - ---reload-button might be useless (wtf is button 0) - -Control thumbnail mode (image selection, mainly) with keys. - -Xinerama doesn't really work when not on screen 0. -On screen 1, it will work if fullscreen is turned off, the window is rendered -and moved so that its top corner is only on screen 1, and then fullscreen is -turned on (after that, it'll work for all images in the slideshow). -Maybe I'll someday find out how to fix that :> - -The thumbnail mode draws an image which has to be re-rendered as new -thumbnails are created, becoming quite slow for large filelists. -A workaround (--thumb-redraw) exists, but at some point a rewrite with a -GUI-toolkit or similar (or maybe writing a completely new tool for that and -removing the feature from feh) would be due. - -Saving the filelist from thumbnail mode is not possible. I wonder if this -matters enough to be fixed. %u is borked there for the same reason. - -Maybe: Zoom mode like --bg-fill? - -Configurable key bindings - -Maybe remove some unneccessary stuff? - * Builtin HTTP client - * Support for custom menu backgrounds/themes - * output-dir (cd $dir; feh is good enough) +Please see <http://github.com/derf/feh/issues> @@ -11,23 +11,43 @@ bin_dir = ${main_dir}/bin doc_dir = ${main_dir}/share/doc/feh image_dir = ${main_dir}/share/feh/images font_dir = ${main_dir}/share/feh/fonts +example_dir = ${main_dir}/share/doc/feh/examples # default CFLAGS CFLAGS ?= -g -O2 CFLAGS += -Wall -Wextra -pedantic -# Comment these out if you don't have libxinerama -xinerama = -DHAVE_LIBXINERAMA -xinerama_ld = -lXinerama - -# Uncomment this for debug mode -# (Use feh -+ or feh --debug to see debug output) -#CFLAGS += -DDEBUG +curl ?= 1 +debug ?= 0 +xinerama ?= 1 + +ifeq (${curl},1) + CFLAGS += -DHAVE_LIBCURL + LDLIBS += -lcurl + MAN_CURL = enabled +else + MAN_CURL = disabled +endif + +ifeq (${debug},1) + CFLAGS += -DDEBUG + MAN_DEBUG = . This is a debug build. +else + MAN_DEBUG = +endif + +ifeq (${xinerama},1) + CFLAGS += -DHAVE_LIBXINERAMA + LDLIBS += -lXinerama + MAN_XINERAMA = enabled +else + MAN_XINERAMA = disabled +endif # Uncomment this to use dmalloc #CFLAGS += -DWITH_DMALLOC -CFLAGS += ${xinerama} -DPREFIX=\"${PREFIX}\" \ +CFLAGS += -DPREFIX=\"${PREFIX}\" \ -DPACKAGE=\"${PACKAGE}\" -DVERSION=\"${VERSION}\" -LDLIBS += -lm -lpng -lX11 -lImlib2 -lgiblib ${xinerama_ld} +LDLIBS += -lm -lpng -lX11 -lImlib2 -lgiblib diff --git a/examples/keys b/examples/keys new file mode 100644 index 0000000..d221d29 --- /dev/null +++ b/examples/keys @@ -0,0 +1,45 @@ +# feh key configuration. +# Comments start with a # sign, do not use them mid-line. +# Each line must be blank, a comment, or a key definition. +# +# key definition: <action name> <key1> [<key2> [<key3>]] +# +# Each <key> is an X11 keysym (as output by xev) with optional modifier. +# For instance, C-x would be Ctrl+X, or 4-space Mod4+Space + +# Examples for vim-like menu bindings on a qwerty keyboard: +menu_parent h Left +menu_child l Right +menu_down j Down +menu_up k Up +menu_select space Return + +# Same for image navigation ... +next_img j Right space +prev_img k Left BackSpace + +# and image movement +scroll_up J C-Up +scroll_down K C-Down +scroll_left H C-Left +scroll_right L C-Right + +# File deletion +remove d Delete +delete C-d C-Delete + +# remove now conflicts with toggle_filenames, so change that +toggle_filenames f + +# zooming +zoom_in C-Up f +zoom_out C-Down a +zoom_default d +zoom_fit s + +# I only hit these accidentaly +save_image +save_filelist + +# This leaves some conflicts with existing default bindings, but you should +# get the idea. And I'm not gonna fix the conflicts, I don't use qwerty ;-) diff --git a/src/fehrc.raw b/examples/themes index 154a6e1..c5fce79 100644 --- a/src/fehrc.raw +++ b/examples/themes @@ -1,8 +1,6 @@ -# Feh configuration file. -# Lines starting with # are comments. Don't use comments mid-line. - -# Feh expects to find this as ~/.fehrc or /etc/fehrc -# If both are available, ~/.fehrc will be used +# Feh themes configuration file. +# Lines starting with # are comments. Midline comments are not supported. +# Place this as either ~/.config/feh/themes or /etc/feh/themes # Options are defined in theme_name/options pairs. # Separate themename and options by whitespace. @@ -14,8 +12,8 @@ # mkindex theme. # Multiple options can of course be used. If they are too long for one line, -# you can (usually) use a \\ to make them continue on the next one: -# imagemap -rV --quiet -W 400 -H 300 \\ +# you can use a \ to make them continue on the next one, but not mid-option. +# imagemap -rV --quiet -W 400 -H 300 \ # --thumb-width 40 --thumb-height 30 # ==================== @@ -31,7 +29,7 @@ webcam --multiwindow --reload 20 mkindex -iVO index.jpg . # More ambitious version... -imgidx --index --output-only .fehindex.jpg --limit-width 1024 \\ +imgidx --index --output-only .fehindex.jpg --limit-width 1024 \ --thumb-width 128 --thumb-height 128 --verbose --quiet # Show a presentation @@ -43,32 +41,26 @@ booth --full-screen --hide-pointer --slideshow-delay 20 # Screw xscreensaver, use feh =) screensave --recursive --full-screen --randomize --slideshow-delay 10 --hide-pointer -# Add <img> tags to your html with ease :-) -newimg -q -L \"<img src=\\\"%f\\\" alt=\\\"%n\\\" border=\\\"0\\\" width=\\\"%w\\\" height=\\\"%h\\\">\" - # Different menus -brushed --menu-bg " PREFIX "/share/feh/images/menubg_brushed.png -aluminium --menu-bg " PREFIX "/share/feh/images/menubg_aluminium.png aqua --menu-bg " PREFIX "/share/feh/images/menubg_aqua.png sky --menu-bg " PREFIX "/share/feh/images/menubg_sky.png -black --menu-bg " PREFIX "/share/feh/images/menubg_black.png \\ - --menu-style " PREFIX "/share/feh/fonts/black.style +black --menu-bg " PREFIX "/share/feh/images/menubg_black.png # Some more examples, used by the feh developer rfs --full-screen --hide-pointer --auto-zoom --randomize fs --full-screen --hide-pointer --auto-zoom --sort filename -thumb_s --thumbnails --cache-thumbnails --thumb-width 128 --thumb-height 128 \\ - --limit-width 1024 --sort filename \\ +thumb_s --thumbnails --cache-thumbnails --thumb-width 128 --thumb-height 128 \ + --limit-width 1024 --sort filename \ --fontpath /usr/share/fonts/truetype/ttf-dejavu/ --font DejaVuSans/8 -thumb_b --thumbnails --cache-thumbnails --thumb-width 256 --thumb-height 256 \\ - --limit-width 1024 --sort filename \\ +thumb_b --thumbnails --cache-thumbnails --thumb-width 256 --thumb-height 256 \ + --limit-width 1024 --sort filename \ --fontpath /usr/share/fonts/truetype/ttf-dejavu/ --font DejaVuSans/8 -thumb_s_nt --thumbnails --cache-thumbnails --thumb-width 128 --thumb-height 128 \\ +thumb_s_nt --thumbnails --cache-thumbnails --thumb-width 128 --thumb-height 128 \ --limit-width 1024 --sort filename --index-name 0 -thumb_b_nt --thumbnails --cache-thumbnails --thumb-width 256 --thumb-height 256 \\ +thumb_b_nt --thumbnails --cache-thumbnails --thumb-width 256 --thumb-height 256 \ --limit-width 1024 --sort filename --index-name 0 diff --git a/man/Makefile b/man/Makefile index 293d2b7..f03b9d7 100644 --- a/man/Makefile +++ b/man/Makefile @@ -9,6 +9,9 @@ all: ${TARGETS} sed \ -e 's/\$$VERSION\$$/${VERSION}/g' \ -e 's/\$$DATE\$$/'"$$(date '+%B %d, %Y')"/g \ + -e 's/\$$MAN_CURL\$$/${MAN_CURL}/' \ + -e 's/\$$MAN_DEBUG\$$/${MAN_DEBUG}/' \ + -e 's/\$$MAN_XINERAMA\$$/${MAN_XINERAMA}/' \ < ${@:.1=.pre} > $@ clean: diff --git a/man/feh.pre b/man/feh.pre index 1c45f64..e2fda9f 100644 --- a/man/feh.pre +++ b/man/feh.pre @@ -4,91 +4,125 @@ . . .Sh NAME +. .Nm feh .Nd image viewer and cataloguer . . .Sh SYNOPSIS +. .Nm .Op Ar options .Ar files or directories ... . . .Sh VERSION +. This manual documents feh $VERSION$ . +.Pp +. +Compile-time switches: libcurl support $MAN_CURL$, Xinerama support +$MAN_XINERAMA$$MAN_DEBUG$ +. . .Sh DESCRIPTION +. .Nm is a mode-based image viewer. It is especially aimed at commandline users who need a fast image viewer without huge GUI dependencies, though it can also be started by .Pq graphical file managers to view an image. +. .Pp +. .Nm supports filelists, various image sorting modes, image captions and more. -Control happens via keyboard shortcuts; the mouse can also be used to control -it, but is only required for very few actions. +Configurable keyboard shortcuts are used to control it; the mouse is also +supported, but only required for very few actions. . . .Sh MODES +. .Nm is based on various modes, which are selected at startup by comandline options. +. .Pp +. Slideshow mode is the default. It opens one window and displays the first image in it, the keyboard and mouse can be used to change slides .Pq images . In slideshow mode, images can be deleted either from the filelist or from the disk, the new filelist can then be saved to the disk and reopened at a later time. +. .Pp +. Montage mode forms a montage from the filelist. The resulting image can be viewed or saved, and its size can be limited by height, width or both. +. .Pp +. Collage mode is very similar to montage mode, except the images are distributed randomly and may overlap each other. +. .Pp +. Index mode forms an index print from the filelist. Image thumbnails are shown along with the filename, filesize and pixel size, printed using a truetype font of your choice. The resulting image can be viewed or saved, and its size can be limited by height, width or both. +. .Pp +. Thumbnail mode is like index mode, but the mini-images are clickable and open the selected image in a new window. +. .Pp +. Multiwindow mode shows images in multiple windows, instead of as a slideshow in one window. Don't use with a large filelist ;) +. .Pp +. List mode doesn't display images. Outputs an .Cm ls - No style listing of the files in the filelist, including image info such as size, pixels, type, etc. Customlist mode will display whatever image info you want, in the format you choose. +. .Pp +. .Nm can also list either all the loadable files in a filelist or all the unloadable files. Useful for preening a directory. . . .Sh OPTIONS +. .Bl -tag -width indent . .It Cm -A , --action Oo Ar flag Oc Ns Ar action +. Specify a string as an action to perform on the image. In slideshow or multiwindow modes, the action will be run when the enter key is pressed, in list mode, the action will be run for each file listed. In loadables/unloadables mode, the action will be run for each loadable/unloadable file, respectively. +. .Pp +. If .Ar flag is .Qq \&; , .Nm will not switch to the next image after executing the action. +. .Pp +. The action will be executed by /bin/sh. Use format specifiers to refer to image info. See .Sx FORMAT SPECIFIERS @@ -98,25 +132,26 @@ In slideshow mode, the next image will be shown after running the action, in 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. . .It Cm -Z , --auto-zoom +. Zoom pictures to screen size in fullscreen .Pq affected by Cm --stretch No and Cm --ignore-aspect . . .It Cm -x , --borderless -Create borderless windows. . -.It Cm -Q , --builtin -Use builtin HTTP client to grab remote files instead of -.Xr wget 1 . +Create borderless windows. . .It Cm -P , --cache-thumbnails +. Enable (experimental) thumbnail caching in .Pa ~/.thumbnails . Only works with thumbnails <= 256x256 pixels. . .It Cm -K , --caption-path Ar path +. Path to directory containing image captions. This turns on caption viewing, and if captions are found in .Ar path , @@ -129,6 +164,7 @@ the caption will be looked for in .Qq images/captions/foo.jpg.txt . . .It Cm -c , --collage +. Enable collage mode. Collage mode is very similar to montage mode, except the images are distributed randomly. When using collage mode, you should also specify @@ -137,6 +173,7 @@ and .Cm --limit-height . . .It Cm -L , --customlist Ar format +. Use .Ar format .Pq printf-like string containing image info specifiers @@ -144,15 +181,19 @@ for list output. See .Sx FORMAT SPECIFIERS . . .It Cm --cycle-once +. Exit feh after one loop through the slideshow. . .It Cm -G , --draw-actions +. Draw the defined actions and what they do at the top-left of the image. . .It Cm -d , --draw-filename +. Draw the filename at the top-left of the image. . .It Cm -f , --filelist Ar file +. This option is similar to the playlists used by music software. If .Ar file exists, it will be read for a list of files to load, in the order they appear. @@ -172,24 +213,33 @@ exits. You can add files to filelists by specifying them on the commandline when also specifying the list. . .It Cm -e , --font Ar font +. Set global font. Should be a truetype font, resident in the current directory or the font directory, and should be defined in the form fontname/points, like .Qq myfont/12 . . .It Cm -C , --fontpath Ar path +. Specify .Ar path as extra directory in which to search for fonts; can be used multiple times to add multiple paths. . +.It Cm --force-aliasing +. +Disable antialiasing for zooming, background setting etc. +. .It Cm -I , --fullindex +. Same as Index mode, but you also get image size and dimensions printed below each thumbnail. . .It Cm -F , --fullscreen +. Make the window fullscreen. . .It Cm -g , --geometry Ar width No x Ar height +. Limit (and don't change) the window size. Takes an X-style geometry .Ar string like 640x480. @@ -197,32 +247,40 @@ Note that larger images will be zoomed out to fit but you can see them at 1:1 by clicking the zoom button. . .It Cm -h , --help +. display help output and exit. . .It Cm -Y , --hide-pointer +. Hide the pointer .Pq useful for slideshows etc . . .It Cm -B , --image-bg Ar style +. Use style as background for transparent image parts and the like. Accepted values: white, black, default. . .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 name beneath each thumbnail. Index mode enables certain other options, see .Sx INDEX MODE OPTIONS . . .It Cm --index-dim Ar bool +. Toggle showing image dimensions in thumbnail/index mode. . .It Cm --index-name Ar bool +. Toggle showing the filename in thumbnail/index mode. . .It Cm --index-size Ar bool +. Toggle showing the filesize in thumbnail/index mode. . .It Cm --info Ar commandline +. Execute .Ar commandline and display its output in the bottom left corner of the image. Can be used to @@ -230,6 +288,7 @@ display e.g. image dimensions or EXIF information. Supports .Sx FORMAT SPECIFIERS . . .It Cm -k , --keep-http +. When viewing files using HTTP, .Nm normally deletes the local copies after viewing, or, if caching, on exit. @@ -241,63 +300,64 @@ with in the name. . .It Cm -l , --list +. Don't display images. Analyse them and display an .Xr ls 1 - No style listing. Useful in scripts to hunt out images of a certain size/resolution/type etc. . .It Cm -U , --loadable +. Don't display images. Just print out their names if imlib2 can successfully load them. . -.It Cm -) , --menu-bg Ar file -Use -.Ar file -as background image in menus. -. .It Cm -M , --menu-font Ar font +. Use .Ar font .Pq truetype, with size, like Qq yudit/12 as menu font. . -.It Cm --menu-style Ar file -Read -.Ar file -to determine menu style. -. .It Cm -m , --montage +. Enable montage mode. Montage mode creates a new image consisting of a grid of thumbnails of the images in the filelist. When montage mode is selected, certain other options become available. See .Sx MONTAGE MODE OPTIONS . . .It Cm -w , --multiwindow +. Disable slideshow mode. With this setting, instead of opening multiple files in slideshow mode, multiple windows will be opened; one per file. . .It Cm --no-jump-on-resort +. Don't jump to the first image after resorting the filelist. . .It Cm -N , --no-menus +. Don't load or show any menus. . .It Cm --no-screen-clip +. By default, window sizes are limited to the screen size. With this option, windows will have the size of the image inside them. Note that they may become very large this way, making them unmanageable in certain window managers. . .It Cm --no-xinerama +. Disable Xinerama support. Only makes sense when you have Xinerama support compiled in. . .It Cm -j , --output-dir Ar directory +. Save files to .Ar directory .Pq only useful with -k . .It Cm -p , --preload +. Preload images. This doesn't mean hold them in RAM, it means run through them and eliminate unloadable images first. Otherwise they will be removed as you flick through. This also analyses the images to get data for use in @@ -305,39 +365,39 @@ sorting, such as pixel size, type etc. A preload run will be automatically performed if you specify one of these sort modes. . .It Cm -q , --quiet +. Don't report non-fatal errors for failed loads. Verbose and quiet modes are not mutually exclusive, the first controls informational messages, the second only errors. . .It Cm -z , --randomize +. When viewing multiple files in a slideshow, randomize the file list before displaying. . -.It Cm -_ , --rcfile Ar file -Use -.Ar file -to parse themes and options from, instead of the default -.Pa ~/.fehrc , /etc/fehrc -files. -. .It Cm -r , --recursive +. Recursively expand any directories in the commandline arguments to the content of those directories, all the way down to the bottom level. . .It Cm -R , --reload Ar int +. Reload images after .Ar int seconds. Mainly useful when viewing webcams via http. . .It Cm -n , --reverse +. Reverse the sort order. Use this to invert the order of the filelist. E.g. to sort in reverse width order, use .Cm -nSwidth . . .It Cm -. , --scale-down +. When not in fullscreen: Scale images to screen size if they are too big. . .It Cm -D , --slideshow-delay Ar float +. For slideshow mode, wait .Ar float seconds between automatically changing slides. Useful for presentations. @@ -346,26 +406,36 @@ Specify a negative number to set the delay but start feh in paused mode. . .It Cm -S , --sort Ar sort_type +. The file list may be sorted according to image parameters. Allowed sort types are: name, filename, width, height, pixels, size, format. For sort modes other than name or filename, a preload run will be necessary, causing a delay proportional to the number of images in the list. . .It Cm -| , --start-at Ar filename +. Start the filelist at .Ar filename . See .Sx USAGE EXAMPLES . . .It Cm -T , --theme Ar theme +. Load options from config file with name .Ar theme - see -.Sx CONFIG FILE SYNTAX -for more info. Note that options from the theme file always override -commandline options. +.Sx THEMES CONFIG SYNTAX +for more info. Note that commandline options always override theme options. +The theme can also be set via the program name +.Pq e.g. with symlinks , +so by default +.Nm +will look for a +.Qq Nm +theme. . .It Cm -t , --thumbnails +. Same as Index mode, but the thumbnails are clickable image launchers. Note that .Cm --fullscreen @@ -373,80 +443,108 @@ does not affect the thumbnail window. It does, however, work for the image windows launched from thumbnail mode. . .It Cm -~ , --thumb-title Ar string +. Set .Ar title for windows opened from thumbnail mode. See also .Sx FORMAT SPECIFIERS . . .It Cm -^ , --title Ar title +. Set window title. Applies to all windows except those opened from thumbnail mode. See .Sx FORMAT SPECIFIERS . .It Cm -u , --unloadable +. Don't display images. Just print out their names if imlib2 can NOT successfully load them. . .It Cm -V , --verbose +. output useful information, progress bars, etc. . .It Cm -v , --version +. output version information and exit. . -.It Cm --zoom Ar percent +.It Cm --zoom Ar percent No | Cm max No | Cm fill +. Zoom images by .Ar percent when in full screen mode or when window geometry is fixed. When combined with .Cm --auto-zoom , zooming will be limited to the specified .Ar percent . +Specifying +.Cm fill +is like setting +.Cm --auto-zoom , +using +.Cm max +makes feh zoom the image like the +.Cm --bg-max +mode. +. .El . . .Sh BUTTON OPTIONS +. .Bl -tag -width indent . .It Cm -0 , --reload-button Ar int +. Set button to reload the image .Pq default: 0 . . .It Cm -1 , --pan-button Ar int +. Set button to pan the image .Pq hold button down and move mouse to move the image . When the mouse is not moved, advances to the next image in slideshow mode. .Pq default: 1 , usually the left button . . .It Cm -2 , --zoom-button Ar int +. Set button to enable zoom mode .Pq default: 2 , usually the middle button . . .It Cm -3 , --menu-button Ar int +. Set button to activate the menu. .Pq default: 3 , usually the right button . . .It Cm --menu-ctrl-mask +. Require CTRL+Button for menu activation. . .It Cm -4 , --prev-button Ar int +. Set button to switch to the previous image in slideshow mode .Pq default: 4 , usually Aq mousewheel up . . .It Cm -5 , --next-button Ar int +. Set button to switch to the next image in slideshow mode .Pq default: 5 , usually Aq mousewheel down . . .It Cm -8 , --rotate-button Ar int +. Use CTRL+Button to rotate the current image .Pq default : 2 . . .It Cm --no-rotate-ctrl-mask +. Don't require CTRL+Button for rotation - just use the button. . .It Cm -9 , --blur-button Ar int +. Use CTRL+Button for blurring .Pq default : 1 . . .It Cm --no-blur-ctrl-mask +. Don't require CTRL+Button for blurring - just use the button. .El . @@ -459,11 +557,13 @@ thumbnail modes. .Bl -tag -width indent . .It Cm -a , --alpha Ar int +. When drawing thumbnails onto the background, set their transparency level to .Ar int .Pq 0 - 255 . . .It Cm -b , --bg Ar file No | Cm trans +. Use .Ar file as background for your montage. With this option specified, the montage size @@ -476,6 +576,7 @@ is the background will be made transparent. . .It Cm -X , --ignore-aspect +. By default, the montage thumbnails will retain their aspect ratios, while fitting into thumb-width/-height. This options forces them to be the size set by @@ -483,6 +584,7 @@ by This will prevent any empty space in the final montage. . .It Cm -H , --limit-height Ar pixels +. Limit the height of the montage. These options can be used together to define the image size exactly, or separately. If only one is specified, the other is calculated from the number of files specified and the size of the thumbnails. @@ -490,18 +592,22 @@ The default is to limit width to 800 pixels and calculate the height as necessary. . .It Cm -W , --limit-width Ar pixels +. Limit the width of the montage. . .It Cm -o , --output Ar file +. Save the created montage to .Ar file . . .It Cm -O , --output-only Ar file +. Just save the created montage to .Ar file without displaying it. . .It Cm -s , --stretch +. 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 @@ -509,12 +615,15 @@ the thumnail size. Aspect ratio will be maintained unles is specified. . .It Cm -E , --thumb-height Ar pixels +. Set thumbnail height. . .It Cm -y , --thumb-width Ar pixels +. Set thumbnail width. . .It Cm -J , --thumb-redraw Ar n +. Only relevant for .Cm --thumbnails : Redraw thumbnail window every @@ -532,17 +641,23 @@ default. Set to get the old behaviour, .Ar n No = 0 will only redraw once all thumbnails are loaded. +. .El . +. .Sh INDEX MODE OPTIONS +. .Bl -tag -width indent . .It Cm -@ , --title-font Ar font +. Set font to print a title on the index, if no font is specified, no title will be printed. .El . +. .Sh BACKGROUND SETTING +. .Nm can also be used as a background setter. It will store the command line necessary to set the background in @@ -551,31 +666,50 @@ so to have your background restored everytime you start X, you can add .Qq `cat ~/.fehbg` to your X startup script .Pq like Pa ~/.xinitrc . +. .Pp +. +Note that all options except +.Cm --bg-tile +support Xinerama. So, if you have multiple screens connected and use e.g. +.Cm --bg-center , +.Nm +will center the image on each screen. You can use +.Cm --no-xinerama +to treat the whole X display as one screen. +. +.Pp +. The following options control how exactly the background is set. Each of them takes exactly one file as argument. +. .Bl -tag -width indent . .It Cm --bg-center +. Center the file on the background. If it is too small, it will be surrounded by a black border . .It Cm --bg-fill +. Like .Cm --bg-scale , but preserves aspect ratio by zooming the image until it fits. Either a horizontal or a vertical part of the image will be cut off . .It Cm --bg-max +. Like .Cm --bg-fill , but scale the image to the maximum size that fits the screen with black borders on one side. . .It Cm --bg-scale +. Fit the file into the background without repeating it, cutting off stuff or using borders. But the aspect ratio is not preserved either . .It Cm --bg-tile +. Tile .Pq repeat the image in case it is too small for the screen @@ -584,46 +718,90 @@ the image in case it is too small for the screen . . .Sh FORMAT SPECIFIERS +. .Bl -tag -width indent +. .It %f +. Image path/filename +. .It %h +. Image height +. .It %l +. Total number of files in filelist +. .It %m +. Current mode +. .It %n +. Image name +. .It %p +. Number of image pixels +. .It \&%P +. .Nm +. .It %s +. Image size in bytes +. .It %t +. Image format +. .It %u +. Number of current file +. .It %w +. Image width +. .It %v +. .Nm version +. .El . -.Sh CONFIG FILE SYNTAX -The config file allows the naming of option groups, called themes. -If -.Pa ~/.fehrc No or Pa /etc/fehrc -exist, -.Nm -will look in them for name/options pairs. -If neither of them exist, +. +.Sh CONFIGURATION +. .Nm -will create a default one in -.Pa ~/.fehrc . +has two config files: +.Pa themes +for theme definitions and +.Pa keys +for key bindings. +It will try to read them from +.Pa $XDG_CONFIG_HOME/feh/ , +which +.Pq when XDG_CONFIG_HOME is unset +defaults to +.Pa ~/.config/feh/ . +If the files are not found in that directory, it will also try +.Pa /etc/feh/ . .Pp +All config files treat lines starting with a +.Qq # +character as comments. +Note that mid-line comments are not supported. +. +. +.Sh THEMES CONFIG SYNTAX +. +This file allows the naming of option groups, called themes. +. +.Pp +. It takes entries of the form .Qq Ar theme options ... , where @@ -631,10 +809,14 @@ where is the name of the entry and .Ar options are the options which will be applied when the theme is used. +. .Pp +. An example entry would be .Qq imagemap -rVq --thumb-width 40 --thumb-height 30 . +. .Pp +. You cane use this theme in two ways. Either call .Qo .Nm @@ -651,20 +833,75 @@ ln -s `which Now just run .Qq imagemap *.jpg to use these options. +. .Pp +. Note that you can split a theme over several lines by placing a backslash at the end of a line, like in the shell. +. .Pp -You can combine these themes with commandline options. An example .fehrc is +. +You can combine these themes with commandline options. An example fehrc is provided with a couple of cool example themes. . +. +.Sh KEYS CONFIG SYNTAX +. +This file defines the key bindings. It has entries of the form +.Qq Ar action Op Ar key1 Op Ar key2 Op Ar key3 . +. +.Pp +. +Each +.Ar key +is an X11 keysym name as shown by +.Xr xev 1 , +like +.Qq Delete . +It may optionally start with a modifier for things like Control, in which case +.Ar key +looks like +.Ar mod Ns No - Ns Ar keysym +.Pq for example Qo C-Delete Qc for Ctrl+Delete . +. +.Pp +. +Available modifiers are +.Ar C No for Control and +.Ar 1 , 4 No for Mod1 and Mod4 . +. +.Pp +. +Specifying an +.Ar action +without any keys unbinds it (i.e. the default bindings are removed). +. +.Pp +. +For a list of the +.Ar action +names, see +.Sx KEYS . +. +. .Sh KEYS -In an image window, the following keys may be used: +. +In an image window, the following keys may be used +.Pq The strings in Bo square brackets Bc are the config action names : +. .Bl -tag -width indent -.It a +. +.It a Bq toggle_actions +. Toggle actions display .Pq see Cm --draw-actions -.It c +. +.It A Bq toggle_aliasing +. +Enable/Disable anti-aliasing +. +.It c Bq toggle_caption +. Caption entry mode. If .Cm --caption-path has been specified, then this enables caption editing. The caption at the @@ -672,91 +909,192 @@ bottom of the screen will turn yellow and can be edited. Hit return to confirm and save the caption, or escape to cancel editing. Note that you can insert an actual newline into the caption using .Aq CTRL+return . -.It d +. +.It d Bq toggle_filenames +. Toggle filename display .Pq see Cm --draw-filename -.It f +. +.It f Bq save_filelist +. Save the current filelist to a unique filename -.It h +. +.It h Bq toggle_pause +. Pause/Continue the slideshow. When it is paused, it will not automatically change slides based on .Cm --slideshow-delay . -.It m +. +.It m Bq toggle_menu +. Show menu. Use the arrow keys and return to select items, .Aq escape to close the menu. -.It n , Ao Space Ac , Aq Right +. +.It n , Ao Space Ac , Ao Right Ac Bq next_img +. Show next image -.It o +. +.It o Bq toggle_pointer +. Toggle pointer visibility -.It p , Ao Backspace Ac , Aq Left +. +.It p , Ao Backspace Ac , Ao Left Ac Bq prev_img +. Show previous image -.It q +. +.It q , Ao Escape Ac Bq quit +. Quit feh -.It r +. +.It r Bq reload_image +. Reload current image. Useful for webcams -.It s +. +.It s Bq save_image +. Save the current image to a unique filename -.It v +. +.It v Bq toggle_fullscreen +. Toggle fullscreen -.It w +. +.It w Bq size_to_image +. Change window size to fit current image size -.It x +. +.It x Bq close +. Close current window -.It z +. +.It z Bq jump_random +. Jump to a random position in the current filelist -.It < , > +. +.It < , > Bq orient_3 , orient_1 +. In place editing - rotate the images 90 degrees (counter)clockwise. The rotation is lossless, but may create artifacts in some image corners when used with JPEG images. Rotating in the reverse direction will make them go away. See .Xr jpegtran 1 for more about lossless JPEG rotation. -.It 0 .. 9 +. +.It 0 .. 9 Bq action_0 .. action_9 +. Execute the corresponding action .Pq 0 = Cm --action , No 1 = Cm --action1 No etc. -.It Aq Return +. +.It Ao Return Ac Bq action_0 +. Run the command defined by .Cm --action -.It Aq home +. +.It Ao home Ac Bq jump_first +. Show first image -.It Aq end +. +.It Ao end Ac Bq jump_last +. Show last image -.It Aq page up +. +.It Ao page up Ac Bq jump_fwd +. Go forward ~5% of the filelist -.It Aq page down +. +.It Ao page down Ac Bq jump_back +. Go backward ~5% of the filelist -.It Aq escape -Quit the slideshow -.It + +. +.It + Bq reload_plus +. Increase reload delay -.It - +. +.It - Bq reload_minus +. Decrease reload delay -.It Aq delete +. +.It Ao delete Ac Bq remove +. Remove current file from filelist -.It Aq CTRL+delete +. +.It Ao CTRL+delete Ac Bq delete +. Remove current file from filelist and delete it -.It Ao keypad left Ac , Ao Ctrl+Left Ac +. +.It Ao keypad left Ac , Ao Ctrl+Left Ac Bq scroll_left +. Scroll to the left -.It Ao keypad right Ac , Ao Ctrl+Right Ac +. +.It Ao keypad right Ac , Ao Ctrl+Right Ac Bq scroll_right +. Scroll to the right -.It Ao keypad up Ac , Ao Ctrl+Up Ac +. +.It Ao keypad up Ac , Ao Ctrl+Up Ac Bq scroll_up +. Scroll up -.It Ao keypad down Ac , Ao Ctrl+Down Ac +. +.It Ao keypad down Ac , Ao Ctrl+Down Ac Bq scroll_down +. Scroll down -.It Aq keypad begin +. +.It Ao keypad begin Ac Bq render +. Antialias the image -.It Ao keypad + Ac , Ao Up Ac +. +.It Ao keypad + Ac , Ao Up Ac Bq zoom_in +. Zoom in -.It Ao keypad - Ac , Ao Down Ac +. +.It Ao keypad - Ac , Ao Down Ac Bq zoom_out +. Zoom out -.It Aq keypad * +. +.It Ao keypad * Ac Bq zoom_default +. Zoom to 100% -.It Aq keypad / +. +.It Ao keypad / Ac Bq zoom_fit +. Zoom to fit the window size +. +.El +. +.Ss MENU KEYS +. +The following keys bindings are used for the feh menu: +. +.Bl -tag -width indent +. +.It Ao Escape Ac Bq menu_close +. +Close the menu +. +.It Ao Up Ac Bq menu_up +. +Highlight previous menu item +. +.It Ao Down Ac Bq menu_down +. +Highlight next menu item +. +.It Ao Left Ac Bq menu_parent +. +Highlight parent menu item +. +.It Ao Right Ac Bq menu_child +. +Highlight child menu item +. +.It Ao Return Ac , Ao Space Ac Bq menu_select +. +Select highlighted menu item +. .El . +. .Sh MOUSE ACTIONS +. When viewing an image, by default mouse button 1 pans .Pq moves the image around or, when only clicked, moves to the next image @@ -766,17 +1104,23 @@ button 2 zooms to restore zoom to 100% .Pc ; and mouse button 3 opens the menu. +. .Pp +. CTRL+Button 1 blurs or sharpens the image .Pq drag left to blur, right to sharpen ; CTRL+Button 2 rotates the image around the center point. +. .Pp +. A note about pan and zoom modes: In pan mode, if you reach a window border but haven't yet panned to the end of the image, .Nm will warp your cursor to the opposite border so you can continue panning. +. .Pp +. When clicking the zoom button and immediately releasing it, the image will be back at 100% zoom. When clicking it and moving the mouse while holding the button down, the zoom will be continued at the previous zoom level. The zoom @@ -784,111 +1128,150 @@ will always happen so that the pixel on which you entered the zoom mode remains stationary. So, to enlarge a specific part of an image, click the zoom button on that part. . +. .Sh SIGNALS +. In slideshow mode, .Nm handles the following signals: +. .Bl -tag -width indent +. .It Dv SIGUSR1 +. Switch to next image +. .It Dv SIGUSR2 +. Switch to previous image +. .El . +. .Sh USAGE EXAMPLES +. Here are some examples of useful option combinations +. .Bl -tag -width indent . .It feh /opt/images +. Show all images in /opt/images . .It feh -r /opt/images +. Recursively show all images found in /opt/images and subdirectories . .It feh -rSfilename /opt/images +. Same as above, but sort by filename. By default, feh will show files in the order it finds them on the hard disk, which is usually somewhat random. . .It feh -t -Sfilename -E 128 -y 128 -W 1024 /opt/images +. Show 128x128 pixel thumbnails, limit window width to 1024 pixels. . .It feh -t -Sfilename -E 128 -y 128 -W 1024 -P -C /usr/share/fonts/truetype/ttf-dejavu/ -e DejaVuSans/8 /opt/images +. Same as above, but enable thumbnail caching in ~/.thumbnails and use a smaller font. . .It feh -irFarial/14 -O index.jpg /opt/images +. Make an index print of /opt/images and all directories below it, using 14 point Arial to write the image info under each thumbnail. Save the image as index.jpg and don't display it, just exit. Note that this even works without a running X server . .It feh --unloadable -r /opt/images +. Print all unloadable images in /opt/images, recursively . .It feh -w /opt/images/holidays +. Open each image in /opt/images/holidays in its own window . .It feh -FD5 -Sname /opt/images/presentation +. Show the images in .../presentation, sorted by name, in fullscreen, automatically change to the next image after 5 seconds . .It feh -rSwidth -A Qo mv '%f' ~/images/'%n' Qc /opt/images +. View all images in /opt/images and below, sorted by width, move an image to ~/image/image_name when enter is pressed . .It feh --start-at ./foo.jpg \&. +. View all images in the current directory, starting with foo.jpg. All other images are still in the slideshow and can be viewed normally . .It feh --start-at foo.jpg * +. Same as above . .It feh --info \&"exifgrep '\&(Model\&|DateTimeOriginal\&|FNumber\&|ISO\&|Flash\&)' '%f' \&| cut -d \&. -f 4-\&" \&. +. Show some EXIF information, extracted by exifprobe/exifgrep +. .El . . .Sh DEPENDENCIES +. .Nm requires the .Cm jpegtran binary .Pq usually distributed in Qo libjpeg-progs Qc or similar for lossless rotation. +. .Pp -To view images from URLs such as http://, you need to have -.Cm wget -available or use the builtin HTTP client -.Pq see Cm --builtin . +. +To view images from URLs such as http://, you need +.Nm +compiled with libcurl support (enabled by default). See the +.Sx VERSION +section. +. . .Sh BUGS -Xinerama support does not really work on Xinerama screens != 0. +. +Xinerama support does not really work on Xinerama screens != 0. Set +.Ev XINERAMA_SCREEN +to the correct number as a workaround. +. .Pp +. Thumbnail mode is somewhat inefficient, and because of that not nearly as fast as it could be. +. .Pp -.Cm --scale-down -does not support zooming. +. +There are still some zooming issues when using +.Cm --scale-down . . .Ss REPORTING BUGS +. If you find a bug, please report it to .Aq derf@finalrewind.org or via -.Aq http://github.com/derf/feh/issues +.Aq http://github.com/derf/feh/issues . +You are also welcome to direct any feh-related comments/questions/... to #feh +on irc.oftc.net. +. .Pp +. Please include the feh version .Aq the output of Qq feh --version , steps to reproduce the bug and (if necessary), images to reproduce it. . +. .Sh FUTURE PLANS -Plans for the following releases: -.Bl -bullet -compact . -.It -Switch to real config file from fehrc theme definitions +Plans for the following releases: . -.It -Add config options to rebind keys + proper mouse action rebinding +.Bl -bullet -compact . .It Make zoom options more intuitive @@ -897,32 +1280,48 @@ Make zoom options more intuitive . . .Sh LICENSE +. Copyright (C) 1999, 2000 by Tom Gilbert (and various contributors). Copyright (C) 2010 by Daniel Friesel (and even more contributors). +. .Pp +. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +. .Pp +. The above copyright notice and this permission notice shall be included in all copies of the Software and its documentation and acknowledgment shall be given in the documentation and software packages that this Software was used. +. .Pp +. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +. .Pp +. Current developer: Daniel Friesel .Aq derf@finalrewind.org +. .Pp +. Original author .Pq no longer developing : Tom Gilbert .Aq feh_sucks@linuxbrit.co.uk +. +.Pp +. +See also: +http://feh.finalrewind.org diff --git a/scripts/checkkeys.pl b/scripts/checkkeys.pl new file mode 100755 index 0000000..54978c5 --- /dev/null +++ b/scripts/checkkeys.pl @@ -0,0 +1,91 @@ +#!/usr/bin/env perl +## Copyright © 2011 by Daniel Friesel <derf@finalrewind.org> +## License: WTFPL: +## 0. You just DO WHAT THE FUCK YOU WANT TO. +use strict; +use warnings; +use 5.010; + +use autodie; + +my $fh; +my $keys; + +my $re_struct = qr{ + struct \s __fehkey \s (?<action> [^;]+ ) ; +}x; + +my $re_set = qr{ + feh_set_kb \( \& keys \. (?<action> [^ ,]+ ) \s* , + \s* (?<mod1> \d+ ) , + \s* (?<key1> [^ ,]+ ) \s* , + \s* (?<mod2> \d+ ) , + \s* (?<key2> [^ ,]+ ) \s* , + \s* (?<mod3> \d+ ) , + \s* (?<key3> [^ ,]+ ) \s* \) ; +}x; + +my $re_parse_action = qr{ + if \s \( \! strcmp \( action , \s " (?<action> [^"]+ ) " \) \) +}x; + +my $re_parse_conf = qr{ + cur_kb \s = \s \& keys \. (?<str> [^;]+ ) ; +}x; + +my $re_man = qr{ + ^ \. It \s (?<keys> .+ ) \s Bq \s (?<action> .+ ) $ +}x; + +my $re_skip = qr{ + ^ ( action | orient ) _ +}x; + +open($fh, '<', 'src/options.h'); +while (my $line = <$fh>) { + if ($line =~ $re_struct) { + $keys->{ $+{action} }->{struct} = 1; + } +} +close($fh); + +open($fh, '<', 'src/keyevents.c'); +while (my $line = <$fh>) { + if ($line =~ $re_set) { + $keys->{ $+{action} }->{default} + = [@+{'mod1', 'key1', 'mod2', 'key2', 'mod3', 'key3'}]; + } + elsif ($line =~ $re_parse_action) { + $keys->{ $+{action} }->{parse} = 1; + } +} +close($fh); + +open($fh, '<', 'man/feh.pre'); +while (my $line = <$fh>) { + if ($line =~ $re_man) { + $keys->{ $+{action} }->{man} = 1; + } +} +close($fh); + +for my $action (sort keys %{$keys}) { + my $k = $keys->{$action}; + + if ($action =~ $re_skip) { + next; + } + + if (not defined $k->{struct}) { + say "$action missing in struct"; + } + if (not defined $k->{default}) { + say "$action missing in defaults"; + } + if (not defined $k->{parse}) { + say "$action missing in parser"; + } + if (not defined $k->{man}) { + say "$action missing in manual"; + } +} diff --git a/scripts/lskeys.pl b/scripts/lskeys.pl new file mode 100755 index 0000000..530e38d --- /dev/null +++ b/scripts/lskeys.pl @@ -0,0 +1,20 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use 5.010; + +use autodie; + +my @keys; + +open(my $fh, '<', 'src/keyevents.c'); +while (my $line = <$fh>) { + chomp($line); + if ($line =~ qr{ + if \s \( \! strcmp \( action , \s " (?<key> [^"]+ ) " \)\) }x) { + push(@keys, $+{key}); + } +} +close($fh); + +say join("\n", sort @keys); diff --git a/data/fonts/black.style b/share/fonts/black.style index d2a86a9..d2a86a9 100644 --- a/data/fonts/black.style +++ b/share/fonts/black.style diff --git a/data/fonts/menu.style b/share/fonts/menu.style index 8557360..8557360 100644 --- a/data/fonts/menu.style +++ b/share/fonts/menu.style diff --git a/data/fonts/yudit.ttf b/share/fonts/yudit.ttf Binary files differindex 8099e63..8099e63 100644 --- a/data/fonts/yudit.ttf +++ b/share/fonts/yudit.ttf diff --git a/data/images/about.png b/share/images/about.png Binary files differindex 5aaaf17..5aaaf17 100644 --- a/data/images/about.png +++ b/share/images/about.png diff --git a/data/images/logo.svg b/share/images/logo.svg index e07b95d..e07b95d 100644 --- a/data/images/logo.svg +++ b/share/images/logo.svg diff --git a/data/images/menubg_aluminium.png b/share/images/menubg_aluminium.png Binary files differindex eed00f1..eed00f1 100644 --- a/data/images/menubg_aluminium.png +++ b/share/images/menubg_aluminium.png diff --git a/data/images/menubg_aqua.png b/share/images/menubg_aqua.png Binary files differindex 3a72590..3a72590 100644 --- a/data/images/menubg_aqua.png +++ b/share/images/menubg_aqua.png diff --git a/data/images/menubg_black.png b/share/images/menubg_black.png Binary files differindex 08b4c2b..08b4c2b 100644 --- a/data/images/menubg_black.png +++ b/share/images/menubg_black.png diff --git a/data/images/menubg_brushed.png b/share/images/menubg_brushed.png Binary files differindex 32fad47..32fad47 100644 --- a/data/images/menubg_brushed.png +++ b/share/images/menubg_brushed.png diff --git a/data/images/menubg_default.png b/share/images/menubg_default.png Binary files differindex dd21188..dd21188 100644 --- a/data/images/menubg_default.png +++ b/share/images/menubg_default.png diff --git a/data/images/menubg_sky.png b/share/images/menubg_sky.png Binary files differindex e0be8ca..e0be8ca 100644 --- a/data/images/menubg_sky.png +++ b/share/images/menubg_sky.png diff --git a/src/collage.c b/src/collage.c index 782d5f8..1f2fac4 100644 --- a/src/collage.c +++ b/src/collage.c @@ -1,6 +1,7 @@ /* collage.c Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to diff --git a/src/debug.h b/src/debug.h index 93cb6bf..eb929e3 100644 --- a/src/debug.h +++ b/src/debug.h @@ -1,6 +1,7 @@ /* debug.h Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to diff --git a/src/deps.mk b/src/deps.mk deleted file mode 100644 index 36b264f..0000000 --- a/src/deps.mk +++ /dev/null @@ -1,41 +0,0 @@ -collage.o: collage.c feh.h structs.h menu.h utils.h getopt.h debug.h \ - winwidget.h filelist.h options.h -events.o: events.c feh.h structs.h menu.h utils.h getopt.h debug.h \ - filelist.h winwidget.h timers.h options.h events.h thumbnail.h -feh_png.o: feh_png.c feh_png.h feh.h structs.h menu.h utils.h getopt.h \ - debug.h -filelist.o: filelist.c feh.h structs.h menu.h utils.h getopt.h debug.h \ - filelist.h options.h -getopt.o: getopt.c -getopt1.o: getopt1.c getopt.h -imlib.o: imlib.c feh.h structs.h menu.h utils.h getopt.h debug.h \ - filelist.h winwidget.h options.h -index.o: index.c feh.h structs.h menu.h utils.h getopt.h debug.h \ - filelist.h winwidget.h options.h -keyevents.o: keyevents.c feh.h structs.h menu.h utils.h getopt.h debug.h \ - thumbnail.h filelist.h winwidget.h options.h -list.o: list.c feh.h structs.h menu.h utils.h getopt.h debug.h filelist.h \ - options.h -main.o: main.c feh.h structs.h menu.h utils.h getopt.h debug.h filelist.h \ - winwidget.h timers.h options.h events.h support.h -md5.o: md5.c md5.h -menu.o: menu.c feh.h structs.h menu.h utils.h getopt.h debug.h support.h \ - thumbnail.h filelist.h winwidget.h options.h -multiwindow.o: multiwindow.c feh.h structs.h menu.h utils.h getopt.h \ - debug.h winwidget.h timers.h filelist.h options.h -options.o: options.c feh.h structs.h menu.h utils.h getopt.h debug.h \ - filelist.h options.h help.inc fehrc.inc -signals.o: signals.c feh.h structs.h menu.h utils.h getopt.h debug.h \ - winwidget.h -slideshow.o: slideshow.c feh.h structs.h menu.h utils.h getopt.h debug.h \ - filelist.h timers.h winwidget.h options.h signals.h -support.o: support.c feh.h structs.h menu.h utils.h getopt.h debug.h \ - filelist.h options.h support.h -thumbnail.o: thumbnail.c feh.h structs.h menu.h utils.h getopt.h debug.h \ - filelist.h winwidget.h options.h thumbnail.h md5.h feh_png.h -timers.o: timers.c feh.h structs.h menu.h utils.h getopt.h debug.h \ - options.h timers.h -utils.o: utils.c feh.h structs.h menu.h utils.h getopt.h debug.h \ - options.h -winwidget.o: winwidget.c feh.h structs.h menu.h utils.h getopt.h debug.h \ - filelist.h winwidget.h options.h diff --git a/src/events.c b/src/events.c index 36379b1..a850137 100644 --- a/src/events.c +++ b/src/events.c @@ -1,6 +1,7 @@ /* events.c Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -182,7 +183,7 @@ static void feh_event_handle_ButtonRelease(XEvent * ev) opt.mode = MODE_NORMAL; winwid->mode = MODE_NORMAL; winwidget_sanitise_offsets(winwid); - winwidget_render_image(winwid, 0, 1); + winwidget_render_image(winwid, 0, 0); } } else if (opt.mode == MODE_NEXT) { opt.mode = MODE_NORMAL; @@ -247,7 +248,7 @@ static void feh_event_handle_ButtonRelease(XEvent * ev) } else winwidget_sanitise_offsets(winwid); - winwidget_render_image(winwid, 0, 1); + winwidget_render_image(winwid, 0, 0); } } else if ((ev->xbutton.button == opt.blur_button) && ((opt.no_blur_ctrl_mask) @@ -280,7 +281,7 @@ static void feh_event_handle_ConfigureNotify(XEvent * ev) opt.geom_w = w->w; opt.geom_h = w->h; } - winwidget_render_image(w, 0, 1); + winwidget_render_image(w, 0, 0); } } } @@ -403,7 +404,7 @@ static void feh_event_handle_MotionNotify(XEvent * ev) winwid->im_y = winwid->click_offset_y - (winwid->im_click_offset_y * winwid->zoom); - winwidget_render_image(winwid, 0, 0); + winwidget_render_image(winwid, 0, 1); } } else if ((opt.mode == MODE_PAN) || (opt.mode == MODE_NEXT)) { int orig_x, orig_y; @@ -462,7 +463,7 @@ static void feh_event_handle_MotionNotify(XEvent * ev) if ((winwid->im_x != orig_x) || (winwid->im_y != orig_y)) - winwidget_render_image(winwid, 0, 0); + winwidget_render_image(winwid, 0, 1); } } else if (opt.mode == MODE_ROTATE) { while (XCheckTypedWindowEvent(disp, ev->xmotion.window, MotionNotify, ev)); @@ -482,7 +483,7 @@ static void feh_event_handle_MotionNotify(XEvent * ev) } winwid->im_angle = (ev->xmotion.x - winwid->w / 2) / ((double) winwid->w / 2) * 3.1415926535; D(("angle: %f\n", winwid->im_angle)); - winwidget_render_image(winwid, 0, 0); + winwidget_render_image(winwid, 0, 1); } } else if (opt.mode == MODE_BLUR) { while (XCheckTypedWindowEvent(disp, ev->xmotion.window, MotionNotify, ev)); @@ -502,7 +503,7 @@ static void feh_event_handle_MotionNotify(XEvent * ev) gib_imlib_image_blur(temp, 0 - blur_radius); ptr = winwid->im; winwid->im = temp; - winwidget_render_image(winwid, 0, 0); + winwidget_render_image(winwid, 0, 1); gib_imlib_free_image_and_decache(winwid->im); winwid->im = ptr; } @@ -521,7 +522,7 @@ static void feh_event_handle_MotionNotify(XEvent * ev) imlib_context_set_image(winwid->im); imlib_apply_filter("bump_map_point(x=[],y=[],map=" PREFIX "/share/feh/images/about.png);", &x, &y); - winwidget_render_image(winwid, 0, 1); + winwidget_render_image(winwid, 0, 0); gib_imlib_free_image_and_decache(winwid->im); winwid->im = orig_im; } else if (winwid->type == WIN_TYPE_THUMBNAIL) { @@ -552,11 +553,11 @@ static void feh_event_handle_MotionNotify(XEvent * ev) thumbnail->x + 2, thumbnail->y + 2, thumbnail->w - 4, thumbnail->h - 4, 255, 255, 255, 255); - winwidget_render_image(winwid, 0, 1); + winwidget_render_image(winwid, 0, 0); gib_imlib_free_image_and_decache(winwid->im); winwid->im = origwin; } else - winwidget_render_image(winwid, 0, 1); + winwidget_render_image(winwid, 0, 0); } last_thumb = thumbnail; } @@ -1,6 +1,7 @@ /* feh.h Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -120,6 +121,7 @@ void show_mini_usage(void); void slideshow_change_image(winwidget winwid, int change); void slideshow_pause_toggle(winwidget w); char *slideshow_create_name(feh_file * file); +void init_keyevents(void); void feh_event_handle_keypress(XEvent * ev); void feh_action_run(feh_file * file, char *action); char *feh_printf(char *str, feh_file * file); @@ -137,12 +139,11 @@ 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); -char *feh_strip_hostname(char *url); void slideshow_save_image(winwidget win); void feh_edit_inplace_orient(winwidget w, int orientation); void feh_edit_inplace_lossless_rotate(winwidget w, int orientation); gib_list *feh_wrap_string(char *text, int wrap_width, Imlib_Font fn, gib_style * style); -char *build_caption_filename(feh_file * file); +char *build_caption_filename(feh_file * file, short create_dir); gib_list *feh_list_jump(gib_list * root, gib_list * l, int direction, int num); /* Imlib stuff */ diff --git a/src/feh_png.c b/src/feh_png.c index e2842f8..f02aecb 100644 --- a/src/feh_png.c +++ b/src/feh_png.c @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <stdarg.h> #define FEH_PNG_COMPRESSION 3 -#define FEH_PNG_NUM_COMMENTS 2 /* only Thumb::URI and Thumb::MTime for now */ +#define FEH_PNG_NUM_COMMENTS 4 gib_hash *feh_png_read_comments(char *file) { @@ -66,7 +66,7 @@ gib_hash *feh_png_read_comments(char *file) return hash; } - if (setjmp(png_ptr->jmpbuf)) { + if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); return hash; @@ -124,7 +124,7 @@ int feh_png_write_png(Imlib_Image image, char *file, ...) return 0; } - if (setjmp(png_ptr->jmpbuf)) { + if (setjmp(png_jmpbuf(png_ptr))) { fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); png_destroy_info_struct(png_ptr, &info_ptr); diff --git a/src/filelist.c b/src/filelist.c index e1b4055..fa1735d 100644 --- a/src/filelist.c +++ b/src/filelist.c @@ -1,6 +1,7 @@ /* filelist.c Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to diff --git a/src/help.raw b/src/help.raw index e0ea432..bbe5e37 100644 --- a/src/help.raw +++ b/src/help.raw @@ -2,7 +2,7 @@ Usage : " PACKAGE " [options] <files or directories ...> - This is just a short option summary. Please consult the manual for details. + This is just a short option summary. Please see \"man " PACKAGE "\" for details. OPTIONS -h, --help Show help and exit @@ -10,7 +10,6 @@ OPTIONS -V, --verbose Show progress bars and other extra information -q, --quiet Hide non-fatal errors. May be used with --verbose -T, --theme THEME Load options with name THEME - -_, --rcfile FILE Use FILE to parse themes and options from -r, --recursive Recursively expand any directories in FILE to the content of those directories. (Take it easy) -z, --randomize Randomize the filelist @@ -36,7 +35,6 @@ OPTIONS -D, --slideshow-delay NUM Set delay between automatically changing slides --cycle-once Exit after one loop through the slideshow -R, --reload NUM Reload images after NUM seconds - -Q, --builtin Use builtin http client instead of wget -k, --keep-http Keep local copies when viewing HTTP/FTP files -K, --caption-path PATH Path to caption directory, enables caption display -j, --output-dir With -k: Output directory for saved files @@ -50,8 +48,8 @@ OPTIONS -A, --action ACTION Specify action to perform when pressing <return>. Executed by /bin/sh, may contain FORMAT SPECIFIERS --action[1-9] Extra actions triggered by pressing keys <1>to <9> - --action-hold-slide Do not change to next image after running an action -G, --draw-actions Show the defined actions in the image window + --force-aliasing Disable antialiasing -m, --montage Enable montage mode -c, --collage Montage mode with randomly distributed thumbnails -i, --index Create an index print of all images @@ -79,8 +77,6 @@ OPTIONS -C, --fontpath PATH Specify an extra directory to look in for fonts, can be used multiple times to add multiple paths. -M, --menu-font FONT Use FONT for the font in menus. - --menu-style FILE Use FILE as the style descriptor for menu text. - -), --menu-bg BG Use BG for the background image in menus. -B, --image-bg STYLE Set background for transparent images and the like. Accepted values: white, black, default -N, --no-menus Don't load or show any menus. @@ -148,7 +144,7 @@ FORMAT SPECIFIERS %l total number of files in the filelist %u current file number %% % - \\n newline + \\n newline KEYS p, <BACKSPACE>, <LEFT> Go to previous slide @@ -188,7 +184,8 @@ KEYS 1-9 Run action 1-9 specified by --action[1-9] options This program is free software, see the file COPYING for licensing info. -Copyright Tom Gilbert (and various contributors) 1999-2003 +Copyright Tom Gilbert (and various contributors) 1999-2003. +Copyright Daniel Friesel 2010-2011. -Homepage: https://derf.homelinux.org/p/feh -Email bugs to <derf@finalrewind.org> +Homepage: http://feh.finalrewind.org +Report bugs to <derf@finalrewind.org> or #feh on irc.oftc.net. diff --git a/src/imlib.c b/src/imlib.c index 89271bf..dcf3c5c 100644 --- a/src/imlib.c +++ b/src/imlib.c @@ -1,6 +1,7 @@ /* imlib.c Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -33,6 +34,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> +#include <curl/curl.h> Display *disp = NULL; Visual *vis = NULL; @@ -231,8 +233,16 @@ int feh_load_image(Imlib_Image * im, feh_file * file) return(1); } +#ifdef HAVE_LIBCURL + char *feh_http_load_image(char *url) { + CURL *curl; + CURLcode res; + char *sfn; + FILE *sfp; + int fd = -1; + char *ebuff; char *tmpname; char *basename; char *path = NULL; @@ -248,252 +258,64 @@ char *feh_http_load_image(char *url) basename = strrchr(url, '/') + 1; tmpname = feh_unique_filename(path, basename); - if (opt.builtin_http) { - /* state for HTTP header parser */ -#define SAW_NONE 1 -#define SAW_ONE_CM 2 -#define SAW_ONE_CJ 3 -#define SAW_TWO_CM 4 -#define IN_BODY 5 - -#define OUR_BUF_SIZE 1024 -#define EOL "\015\012" - - int sockno = 0; - int size; - int body = SAW_NONE; - struct addrinfo hints; - struct addrinfo *result, *rp; - char *hostname; - char *get_string; - char *host_string; - char *query_string; - char *get_url; - static char buf[OUR_BUF_SIZE]; - char ua_string[] = "User-Agent: feh image viewer"; - char accept_string[] = "Accept: image/*"; - FILE *fp; - - D(("using builtin http collection\n")); - fp = fopen(tmpname, "w"); - if (!fp) { - weprintf("couldn't write to file %s:", tmpname); - free(tmpname); - return(NULL); - } - - hostname = feh_strip_hostname(url); - if (!hostname) { - weprintf("couldn't work out hostname from %s:", url); - fclose(fp); - unlink(tmpname); - free(tmpname); - return(NULL); - } - - D(("trying hostname %s\n", hostname)); - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_NUMERICSERV; - hints.ai_protocol = 0; - if (getaddrinfo(hostname, "80", &hints, &result) != 0) { - weprintf("error resolving host %s:", hostname); - fclose(fp); - unlink(tmpname); - free(hostname); - free(tmpname); - return(NULL); - } - for (rp = result; rp != NULL; rp = rp->ai_next) { - sockno = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if (sockno == -1) { - continue; - } - if (connect(sockno, rp->ai_addr, rp->ai_addrlen) != -1) { - break; - } - close(sockno); - } - if (rp == NULL) { - weprintf("error connecting socket:"); - freeaddrinfo(result); - fclose(fp); - unlink(tmpname); - free(tmpname); - free(hostname); - return(NULL); - } - freeaddrinfo(result); - - get_url = strchr(url, '/') + 2; - get_url = strchr(get_url, '/'); - - get_string = estrjoin(" ", "GET", get_url, "HTTP/1.0", NULL); - host_string = estrjoin(" ", "Host:", hostname, NULL); - query_string = estrjoin(EOL, get_string, host_string, accept_string, ua_string, "", "", NULL); - /* At this point query_string looks something like - ** - ** GET /dir/foo.jpg?123456 HTTP/1.0^M^J - ** Host: www.example.com^M^J - ** Accept: image/ *^M^J - ** User-Agent: feh image viewer^M^J - ** ^M^J - ** - ** Host: is required by HTTP/1.1 and very important for some sites, - ** even with HTTP/1.0 - ** - ** -- BEG - */ - if ((send(sockno, query_string, strlen(query_string), 0)) == -1) { - free(get_string); - free(host_string); - free(query_string); - free(tmpname); - free(hostname); - weprintf("error sending over socket:"); - return(NULL); - } - free(get_string); - free(host_string); - free(query_string); - free(hostname); - - while ((size = read(sockno, &buf, OUR_BUF_SIZE))) { - if (body == IN_BODY) { - fwrite(buf, 1, size, fp); - } else { - int i; - - for (i = 0; i < size; i++) { - /* We are looking for ^M^J^M^J, but will accept - ** ^J^J from broken servers. Stray ^Ms will be - ** ignored. - ** - ** TODO: - ** Checking the headers for a - ** Content-Type: image/ * - ** header would help detect problems with results. - ** Maybe look at the response code too? But there is - ** no fundamental reason why a 4xx or 5xx response - ** could not return an image, it is just the 3xx - ** series we need to worry about. - ** - ** Also, grabbing the size from the Content-Length - ** header and killing the connection after that - ** many bytes where read would speed up closing the - ** socket. - ** -- BEG - */ - - switch (body) { - - case IN_BODY: - fwrite(buf + i, 1, size - i, fp); - i = size; - break; - - case SAW_ONE_CM: - if (buf[i] == '\012') { - body = SAW_ONE_CJ; - } else { - body = SAW_NONE; - } - break; - - case SAW_ONE_CJ: - if (buf[i] == '\015') { - body = SAW_TWO_CM; - } else { - if (buf[i] == '\012') { - body = IN_BODY; - } else { - body = SAW_NONE; - } - } - break; - - case SAW_TWO_CM: - if (buf[i] == '\012') { - body = IN_BODY; - } else { - body = SAW_NONE; - } - break; - - case SAW_NONE: - if (buf[i] == '\015') { - body = SAW_ONE_CM; - } else { - if (buf[i] == '\012') { - body = SAW_ONE_CJ; - } - } - break; - - } /* switch */ - } /* for i */ + curl = curl_easy_init(); + if (!curl) { + weprintf("open url: libcurl initialization failure"); + return NULL; + } + + sfn = estrjoin("_", tmpname, "XXXXXX", NULL); + free(tmpname); + fd = mkstemp(sfn); + if (fd != -1) { + sfp = fdopen(fd, "w+"); + if (sfp != NULL) { + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, sfp); + ebuff = emalloc(CURL_ERROR_SIZE); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, ebuff); + curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L); + + res = curl_easy_perform(curl); + curl_easy_cleanup(curl); + if (res != CURLE_OK) { + weprintf("open url: %s", ebuff); + unlink(sfn); + close(fd); + free(sfn); + sfn = NULL; } - } /* while read */ - close(sockno); - fclose(fp); - } else { - int pid; - int status; - - if ((pid = fork()) < 0) { - weprintf("open url: fork failed:"); - free(tmpname); - return(NULL); - } else if (pid == 0) { - char *quiet = NULL; - if (!opt.verbose) - quiet = estrdup("-q"); - - execlp("wget", "wget", "--cache=off", "-O", tmpname, url, quiet, NULL); - eprintf("url: Is 'wget' installed? Failed to exec wget:"); + free(ebuff); + fclose(sfp); + return sfn; } else { - waitpid(pid, &status, 0); - - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - weprintf("url: wget failed to load URL %s\n", url); - unlink(tmpname); - free(tmpname); - return(NULL); - } + weprintf("open url: fdopen failed:"); + free(sfn); + unlink(sfn); + close(fd); } + } else { + weprintf("open url: mkstemp failed:"); + free(sfn); } - - return(tmpname); + curl_easy_cleanup(curl); + return NULL; } -char *feh_strip_hostname(char *url) -{ - char *ret; - char *start; - char *finish; - int len; - - start = strchr(url, '/'); - if (!start) - return(NULL); - - start += 2; - - finish = strchr(start, '/'); - if (!finish) - return(NULL); +#else /* HAVE_LIBCURL */ - len = finish - start; - - ret = emalloc(len + 1); - strncpy(ret, start, len); - ret[len] = '\0'; - return(ret); +char *feh_http_load_image(char *url) +{ + weprintf( + "Cannot load image %s\n Please recompile with libcurl support", + url + ); + return NULL; } +#endif /* HAVE_LIBCURL */ + void feh_draw_zoom(winwidget w) { static Imlib_Font fn = NULL; @@ -683,7 +505,7 @@ void feh_draw_info(winwidget w) return; } -char *build_caption_filename(feh_file * file) +char *build_caption_filename(feh_file * file, short create_dir) { char *caption_filename; char *s, *dir, *caption_dir; @@ -702,6 +524,8 @@ char *build_caption_filename(feh_file * file) D(("dir %s, cp %s, cdir %s\n", dir, opt.caption_path, caption_dir)) if (stat(caption_dir, &cdir_stat) == -1) { + if (!create_dir) + return NULL; if (mkdir(caption_dir, 0755) == -1) eprintf("Failed to create caption directory %s:", caption_dir); } else if (!S_ISDIR(cdir_stat.st_mode)) @@ -737,9 +561,12 @@ void feh_draw_caption(winwidget w) if (!file->caption) { char *caption_filename; - caption_filename = build_caption_filename(file); - /* read caption from file */ - file->caption = ereadfile(caption_filename); + caption_filename = build_caption_filename(file, 0); + if (caption_filename) + /* read caption from file */ + file->caption = ereadfile(caption_filename); + else + file->caption = estrdup(""); free(caption_filename); } diff --git a/src/index.c b/src/index.c index 15dcea1..2829bad 100644 --- a/src/index.c +++ b/src/index.c @@ -1,6 +1,7 @@ /* index.c Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to diff --git a/src/keyevents.c b/src/keyevents.c index 7940973..e43ae33 100644 --- a/src/keyevents.c +++ b/src/keyevents.c @@ -1,6 +1,7 @@ /* keyevents.c Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -29,6 +30,276 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "winwidget.h" #include "options.h" +fehkb keys; + +static void feh_set_kb(fehkey *key, int s0, int y0, int s1, int y1, int s2, int y2) { + key->keystates[0] = s0; + key->keystates[1] = s1; + key->keystates[2] = s2; + key->keysyms[0] = y0; + key->keysyms[1] = y1; + key->keysyms[2] = y2; +} + +static void feh_set_parse_kb_partial(fehkey *key, int index, char *ks) { + char *cur = ks; + int mod = 0; + + if (!*ks) { + key->keysyms[index] = 0; + return; + } + + if (ks[1] == '-') { + switch (ks[0]) { + case 'C': + mod = ControlMask; + break; + case '1': + mod = Mod1Mask; + break; + case '4': + mod = Mod4Mask; + break; + default: + weprintf("keys: invalid modifier %c in %s", ks[0], ks); + break; + } + cur = ks + 2; + } + + key->keysyms[index] = XStringToKeysym(cur); + key->keystates[index] = mod; + + if (key->keysyms[index] == NoSymbol) + weprintf("keys: Invalid keysym: %s", cur); +} + +void init_keyevents(void) { + char *home = NULL; + char *confhome = NULL; + char *confpath = NULL; + char line[128]; + char action[32], k1[32], k2[32], k3[32]; + struct __fehkey *cur_kb = NULL; + FILE *conf = NULL; + int read = 0; + + memset(&keys, 0, sizeof(keys)); + + feh_set_kb(&keys.menu_close, 0, XK_Escape , 0, 0 , 0, 0); + feh_set_kb(&keys.menu_parent,0, XK_Left , 0, 0 , 0, 0); + feh_set_kb(&keys.menu_down , 0, XK_Down , 0, 0 , 0, 0); + feh_set_kb(&keys.menu_up , 0, XK_Up , 0, 0 , 0, 0); + feh_set_kb(&keys.menu_child, 0, XK_Right , 0, 0 , 0, 0); + feh_set_kb(&keys.menu_select,0, XK_Return , 0, XK_space , 0, 0); + feh_set_kb(&keys.scroll_left,0, XK_KP_Left , 4, XK_Left , 0, 0); + feh_set_kb(&keys.scroll_right,0,XK_KP_Right , 4, XK_Right , 0, 0); + feh_set_kb(&keys.scroll_down,0, XK_KP_Down , 4, XK_Down , 0, 0); + feh_set_kb(&keys.scroll_up , 0, XK_KP_Up , 4, XK_Up , 0, 0); + feh_set_kb(&keys.prev_img , 0, XK_Left , 0, XK_p , 0, XK_BackSpace); + feh_set_kb(&keys.next_img , 0, XK_Right , 0, XK_n , 0, XK_space); + feh_set_kb(&keys.jump_back , 0, XK_Page_Up , 0, XK_KP_Page_Up, 0, 0); + feh_set_kb(&keys.jump_fwd , 0, XK_Page_Down , 0, XK_KP_Page_Down,0,0); + feh_set_kb(&keys.jump_random,0, XK_z , 0, 0 , 0, 0); + feh_set_kb(&keys.quit , 0, XK_Escape , 0, XK_q , 0, 0); + feh_set_kb(&keys.close , 0, XK_x , 0, 0 , 0, 0); + feh_set_kb(&keys.remove , 0, XK_Delete , 0, 0 , 0, 0); + feh_set_kb(&keys.delete , 4, XK_Delete , 0, 0 , 0, 0); + feh_set_kb(&keys.jump_first, 0, XK_Home , 0, XK_KP_Home , 0, 0); + feh_set_kb(&keys.jump_last , 0, XK_End , 0, XK_KP_End , 0, 0); + feh_set_kb(&keys.action_0 , 0, XK_Return , 0, XK_0 , 0, XK_KP_0); + feh_set_kb(&keys.action_1 , 0, XK_1 , 0, XK_KP_1 , 0, 0); + feh_set_kb(&keys.action_2 , 0, XK_2 , 0, XK_KP_2 , 0, 0); + feh_set_kb(&keys.action_3 , 0, XK_3 , 0, XK_KP_3 , 0, 0); + feh_set_kb(&keys.action_4 , 0, XK_4 , 0, XK_KP_4 , 0, 0); + feh_set_kb(&keys.action_5 , 0, XK_5 , 0, XK_KP_5 , 0, 0); + feh_set_kb(&keys.action_6 , 0, XK_6 , 0, XK_KP_6 , 0, 0); + feh_set_kb(&keys.action_7 , 0, XK_7 , 0, XK_KP_7 , 0, 0); + feh_set_kb(&keys.action_8 , 0, XK_8 , 0, XK_KP_8 , 0, 0); + feh_set_kb(&keys.action_9 , 0, XK_9 , 0, XK_KP_9 , 0, 0); + feh_set_kb(&keys.zoom_in , 0, XK_Up , 0, XK_KP_Add , 0, 0); + feh_set_kb(&keys.zoom_out , 0, XK_Down , 0, XK_KP_Subtract,0, 0); + feh_set_kb(&keys.zoom_default, 0, XK_KP_Multiply, 0, 0 , 0, 0); + feh_set_kb(&keys.zoom_fit , 0, XK_KP_Divide , 0, 0 , 0, 0); + feh_set_kb(&keys.size_to_image, 0, XK_w , 0, 0 , 0, 0); + feh_set_kb(&keys.render , 0, XK_KP_Begin , 0, 0 , 0, 0); + feh_set_kb(&keys.toggle_actions, 0, XK_a, 0, 0, 0, 0); + feh_set_kb(&keys.toggle_aliasing, 0, XK_A, 0, 0, 0, 0); + feh_set_kb(&keys.toggle_filenames, 0, XK_d, 0, 0, 0, 0); + feh_set_kb(&keys.toggle_pointer, 0, XK_o, 0, 0, 0, 0); + feh_set_kb(&keys.toggle_caption, 0, XK_c, 0, 0, 0, 0); + feh_set_kb(&keys.toggle_pause, 0, XK_h, 0, 0, 0, 0); + feh_set_kb(&keys.toggle_menu, 0, XK_m, 0, 0, 0, 0); + feh_set_kb(&keys.toggle_fullscreen, 0, XK_v, 0, 0, 0, 0); + feh_set_kb(&keys.reload_image, 0, XK_r, 0, 0, 0, 0); + feh_set_kb(&keys.save_image, 0, XK_s, 0, 0, 0, 0); + feh_set_kb(&keys.save_filelist, 0, XK_f, 0, 0, 0, 0); + feh_set_kb(&keys.orient_1, 0, XK_greater, 0, 0, 0, 0); + feh_set_kb(&keys.orient_3, 0, XK_less, 0, 0, 0, 0); + feh_set_kb(&keys.reload_minus, 0, XK_minus, 0, 0, 0, 0); + feh_set_kb(&keys.reload_plus, 0, XK_plus, 0, 0, 0, 0); + + home = getenv("HOME"); + if (!home) + eprintf("No HOME in environment\n"); + + confhome = getenv("XDG_CONFIG_HOME"); + + if (confhome) + confpath = estrjoin("/", confhome, "feh/keys", NULL); + else + confpath = estrjoin("/", home, ".config/feh/keys", NULL); + + conf = fopen(confpath, "r"); + + free(confpath); + + if (!conf && ((conf = fopen("/etc/feh/keys", "r")) == NULL)) + return; + + while (fgets(line, sizeof(line), conf)) { + *action = '\0'; + *k1 = '\0'; + *k2 = '\0'; + *k3 = '\0'; + + read = sscanf(line, "%31s %31s %31s %31s\n", + (char *) &action, (char *) &k1, (char* ) &k2, (char *) &k3); + + if ((read == EOF) || (read == 0) || (line[0] == '#')) + continue; + + if (!strcmp(action, "menu_close")) + cur_kb = &keys.menu_close; + else if (!strcmp(action, "menu_parent")) + cur_kb = &keys.menu_parent; + else if (!strcmp(action, "menu_down")) + cur_kb = &keys.menu_down; + else if (!strcmp(action, "menu_up")) + cur_kb = &keys.menu_up; + else if (!strcmp(action, "menu_child")) + cur_kb = &keys.menu_child; + else if (!strcmp(action, "menu_select")) + cur_kb = &keys.menu_select; + else if (!strcmp(action, "scroll_right")) + cur_kb = &keys.scroll_right; + else if (!strcmp(action, "scroll_left")) + cur_kb = &keys.scroll_left; + else if (!strcmp(action, "scroll_up")) + cur_kb = &keys.scroll_up; + else if (!strcmp(action, "scroll_down")) + cur_kb = &keys.scroll_down; + else if (!strcmp(action, "prev_img")) + cur_kb = &keys.prev_img; + else if (!strcmp(action, "next_img")) + cur_kb = &keys.next_img; + else if (!strcmp(action, "jump_back")) + cur_kb = &keys.jump_back; + else if (!strcmp(action, "jump_fwd")) + cur_kb = &keys.jump_fwd; + else if (!strcmp(action, "jump_random")) + cur_kb = &keys.jump_random; + else if (!strcmp(action, "quit")) + cur_kb = &keys.quit; + else if (!strcmp(action, "close")) + cur_kb = &keys.close; + else if (!strcmp(action, "remove")) + cur_kb = &keys.remove; + else if (!strcmp(action, "delete")) + cur_kb = &keys.delete; + else if (!strcmp(action, "jump_first")) + cur_kb = &keys.jump_first; + else if (!strcmp(action, "jump_last")) + cur_kb = &keys.jump_last; + else if (!strcmp(action, "action_0")) + cur_kb = &keys.action_0; + else if (!strcmp(action, "action_1")) + cur_kb = &keys.action_1; + else if (!strcmp(action, "action_2")) + cur_kb = &keys.action_2; + else if (!strcmp(action, "action_3")) + cur_kb = &keys.action_3; + else if (!strcmp(action, "action_4")) + cur_kb = &keys.action_4; + else if (!strcmp(action, "action_5")) + cur_kb = &keys.action_5; + else if (!strcmp(action, "action_6")) + cur_kb = &keys.action_6; + else if (!strcmp(action, "action_7")) + cur_kb = &keys.action_7; + else if (!strcmp(action, "action_8")) + cur_kb = &keys.action_8; + else if (!strcmp(action, "action_9")) + cur_kb = &keys.action_9; + else if (!strcmp(action, "zoom_in")) + cur_kb = &keys.zoom_in; + else if (!strcmp(action, "zoom_out")) + cur_kb = &keys.zoom_out; + else if (!strcmp(action, "zoom_default")) + cur_kb = &keys.zoom_default; + else if (!strcmp(action, "zoom_fit")) + cur_kb = &keys.zoom_fit; + else if (!strcmp(action, "size_to_image")) + cur_kb = &keys.size_to_image; + else if (!strcmp(action, "render")) + cur_kb = &keys.render; + else if (!strcmp(action, "toggle_actions")) + cur_kb = &keys.toggle_actions; + else if (!strcmp(action, "toggle_aliasing")) + cur_kb = &keys.toggle_aliasing; + else if (!strcmp(action, "toggle_filenames")) + cur_kb = &keys.toggle_filenames; + else if (!strcmp(action, "toggle_pointer")) + cur_kb = &keys.toggle_pointer; + else if (!strcmp(action, "toggle_caption")) + cur_kb = &keys.toggle_caption; + else if (!strcmp(action, "toggle_pause")) + cur_kb = &keys.toggle_pause; + else if (!strcmp(action, "toggle_menu")) + cur_kb = &keys.toggle_menu; + else if (!strcmp(action, "toggle_fullscreen")) + cur_kb = &keys.toggle_fullscreen; + else if (!strcmp(action, "reload_image")) + cur_kb = &keys.reload_image; + else if (!strcmp(action, "save_image")) + cur_kb = &keys.save_image; + else if (!strcmp(action, "save_filelist")) + cur_kb = &keys.save_filelist; + else if (!strcmp(action, "orient_1")) + cur_kb = &keys.orient_1; + else if (!strcmp(action, "orient_3")) + cur_kb = &keys.orient_3; + else if (!strcmp(action, "reload_minus")) + cur_kb = &keys.reload_minus; + else if (!strcmp(action, "reload_plus")) + cur_kb = &keys.reload_plus; + else + weprintf("keys: Invalid action: %s", action); + + if (cur_kb) { + feh_set_parse_kb_partial(cur_kb, 0, k1); + feh_set_parse_kb_partial(cur_kb, 1, k2); + feh_set_parse_kb_partial(cur_kb, 2, k3); + } + } + fclose(conf); +} + +static short feh_is_kp(fehkey *key, int sym, int state) { + int i; + + for (i = 0; i < 3; i++) { + if ( + (key->keysyms[i] == sym) && + (key->keystates[i] == state)) + return 1; + else if (key->keysyms[i] == 0) + return 0; + } + return 0; +} + void feh_event_invoke_action(winwidget winwid, unsigned char action) { if (opt.actions[action]) { @@ -54,6 +325,7 @@ void feh_event_invoke_action(winwidget winwid, unsigned char action) void feh_event_handle_keypress(XEvent * ev) { int len; + int state; char kbuf[20]; KeySym keysym; XKeyEvent *kev; @@ -71,34 +343,23 @@ void feh_event_handle_keypress(XEvent * ev) kev = (XKeyEvent *) ev; len = XLookupString(&ev->xkey, (char *) kbuf, sizeof(kbuf), &keysym, NULL); + state = kev->state & (ControlMask | Mod1Mask | Mod4Mask); /* menus are showing, so this is a menu control keypress */ if (ev->xbutton.window == menu_cover) { selected_item = feh_menu_find_selected_r(menu_root, &selected_menu); - switch (keysym) { - case XK_Escape: + if (feh_is_kp(&keys.menu_close, keysym, state)) feh_menu_hide(menu_root, True); - break; - case XK_Left: + else if (feh_is_kp(&keys.menu_parent, keysym, state)) feh_menu_select_parent(selected_menu); - break; - case XK_Down: + else if (feh_is_kp(&keys.menu_down, keysym, state)) feh_menu_select_next(selected_menu, selected_item); - break; - case XK_Up: + else if (feh_is_kp(&keys.menu_up, keysym, state)) feh_menu_select_prev(selected_menu, selected_item); - break; - case XK_Right: + else if (feh_is_kp(&keys.menu_child, keysym, state)) feh_menu_select_submenu(selected_menu); - break; - case XK_Return: - case XK_space: + else if (feh_is_kp(&keys.menu_select, keysym, state)) feh_menu_item_activate(selected_menu, selected_item); - break; - default: - break; - } - return; } @@ -108,7 +369,7 @@ void feh_event_handle_keypress(XEvent * ev) if (winwid->caption_entry) { switch (keysym) { case XK_Return: - if (kev->state & ControlMask) { + if (state & ControlMask) { /* insert actual newline */ ESTRAPPEND(FEH_FILE(winwid->file->data)->caption, "\n"); winwidget_render_image_cached(winwid); @@ -116,14 +377,15 @@ void feh_event_handle_keypress(XEvent * ev) /* finish caption entry, write to captions file */ FILE *fp; char *caption_filename; - caption_filename = build_caption_filename(FEH_FILE(winwid->file->data)); + caption_filename = + build_caption_filename(FEH_FILE(winwid->file->data), 1); winwid->caption_entry = 0; winwidget_render_image_cached(winwid); XFreePixmap(disp, winwid->bg_pmap_cache); winwid->bg_pmap_cache = 0; fp = fopen(caption_filename, "w"); if (!fp) { - weprintf("couldn't write to captions file %s:", caption_filename); + eprintf("couldn't write to captions file %s:", caption_filename); return; } fprintf(fp, "%s", FEH_FILE(winwid->file->data)->caption); @@ -156,244 +418,179 @@ void feh_event_handle_keypress(XEvent * ev) return; } - switch (keysym) { - case XK_Left: - if (kev->state & ControlMask) { - winwid->im_x += 10; - winwidget_render_image(winwid, 0, 0); - } - else if (opt.slideshow) - slideshow_change_image(winwid, SLIDE_PREV); - break; - case XK_Right: - if (kev->state & ControlMask) { - winwid->im_x -= 10; - winwidget_render_image(winwid, 0, 0); - } - else if (opt.slideshow) + if (feh_is_kp(&keys.next_img, keysym, state)) { + if (opt.slideshow) slideshow_change_image(winwid, SLIDE_NEXT); - break; - case XK_Page_Up: - case XK_KP_Page_Up: + } + else if (feh_is_kp(&keys.prev_img, keysym, state)) { + if (opt.slideshow) + slideshow_change_image(winwid, SLIDE_PREV); + } + else if (feh_is_kp(&keys.scroll_right, keysym, state)) { + winwid->im_x -= 20; + winwidget_render_image(winwid, 0, 1); + } + else if (feh_is_kp(&keys.scroll_left, keysym, state)) { + winwid->im_x += 20; + winwidget_render_image(winwid, 0, 1); + } + else if (feh_is_kp(&keys.scroll_down, keysym, state)) { + winwid->im_y -= 20; + winwidget_render_image(winwid, 0, 1); + } + else if (feh_is_kp(&keys.scroll_up, keysym, state)) { + winwid->im_y += 20; + winwidget_render_image(winwid, 0, 1); + } + else if (feh_is_kp(&keys.jump_back, keysym, state)) { if (opt.slideshow) slideshow_change_image(winwid, SLIDE_JUMP_BACK); - break; - case XK_Escape: - winwidget_destroy_all(); - break; - case XK_Page_Down: - case XK_KP_Page_Down: + } + else if (feh_is_kp(&keys.jump_fwd, keysym, state)) { if (opt.slideshow) slideshow_change_image(winwid, SLIDE_JUMP_FWD); - break; - case XK_Delete: - /* Holding ctrl gets you a filesystem deletion and removal from the * - filelist. Just DEL gets you filelist removal only. */ - if (kev->state & ControlMask) { - if (winwid->type == WIN_TYPE_THUMBNAIL_VIEWER) - feh_thumbnail_mark_removed(FEH_FILE(winwid->file->data), 1); - feh_filelist_image_remove(winwid, 1); - } else { - if (winwid->type == WIN_TYPE_THUMBNAIL_VIEWER) - feh_thumbnail_mark_removed(FEH_FILE(winwid->file->data), 0); - feh_filelist_image_remove(winwid, 0); - } - break; - case XK_Home: - case XK_KP_Home: + } + else if (feh_is_kp(&keys.quit, keysym, state)) { + winwidget_destroy_all(); + } + else if (feh_is_kp(&keys.delete, keysym, state)) { + if (winwid->type == WIN_TYPE_THUMBNAIL_VIEWER) + feh_thumbnail_mark_removed(FEH_FILE(winwid->file->data), 1); + feh_filelist_image_remove(winwid, 1); + } + else if (feh_is_kp(&keys.remove, keysym, state)) { + if (winwid->type == WIN_TYPE_THUMBNAIL_VIEWER) + feh_thumbnail_mark_removed(FEH_FILE(winwid->file->data), 0); + feh_filelist_image_remove(winwid, 0); + } + else if (feh_is_kp(&keys.jump_first, keysym, state)) { if (opt.slideshow) slideshow_change_image(winwid, SLIDE_FIRST); - break; - case XK_End: - case XK_KP_End: + } + else if (feh_is_kp(&keys.jump_last, keysym, state)) { if (opt.slideshow) slideshow_change_image(winwid, SLIDE_LAST); - break; - case XK_Return: - case XK_KP_Enter: - case XK_0: - case XK_KP_0: + } + else if (feh_is_kp(&keys.action_0, keysym, state)) { feh_event_invoke_action(winwid, 0); - break; - case XK_1: - case XK_KP_1: + } + else if (feh_is_kp(&keys.action_1, keysym, state)) { feh_event_invoke_action(winwid, 1); - break; - case XK_2: - case XK_KP_2: + } + else if (feh_is_kp(&keys.action_2, keysym, state)) { feh_event_invoke_action(winwid, 2); - break; - case XK_3: - case XK_KP_3: + } + else if (feh_is_kp(&keys.action_3, keysym, state)) { feh_event_invoke_action(winwid, 3); - break; - case XK_4: - case XK_KP_4: + } + else if (feh_is_kp(&keys.action_4, keysym, state)) { feh_event_invoke_action(winwid, 4); - break; - case XK_5: - case XK_KP_5: + } + else if (feh_is_kp(&keys.action_5, keysym, state)) { feh_event_invoke_action(winwid, 5); - break; - case XK_6: - case XK_KP_6: + } + else if (feh_is_kp(&keys.action_6, keysym, state)) { feh_event_invoke_action(winwid, 6); - break; - case XK_7: - case XK_KP_7: + } + else if (feh_is_kp(&keys.action_7, keysym, state)) { feh_event_invoke_action(winwid, 7); - break; - case XK_8: - case XK_KP_8: + } + else if (feh_is_kp(&keys.action_8, keysym, state)) { feh_event_invoke_action(winwid, 8); - break; - case XK_9: - case XK_KP_9: + } + else if (feh_is_kp(&keys.action_9, keysym, state)) { feh_event_invoke_action(winwid, 9); - break; - case XK_KP_Left: - winwid->im_x += 10; - winwidget_render_image(winwid, 0, 0); - break; - case XK_KP_Right: - winwid->im_x -= 10; - winwidget_render_image(winwid, 0, 0); - break; - case XK_KP_Up: - winwid->im_y += 10; + } + else if (feh_is_kp(&keys.zoom_in, keysym, state)) { + winwid->old_zoom = winwid->zoom; + winwid->zoom = winwid->zoom * 1.25; + winwid->im_x = (winwid->w / 2) - (((winwid->w / 2) - winwid->im_x) / + winwid->old_zoom * winwid->zoom); + winwid->im_y = (winwid->h / 2) - (((winwid->h / 2) - winwid->im_y) / + winwid->old_zoom * winwid->zoom); + winwidget_sanitise_offsets(winwid); winwidget_render_image(winwid, 0, 0); - break; - case XK_KP_Down: - winwid->im_y -= 10; + } + else if (feh_is_kp(&keys.zoom_out, keysym, state)) { + winwid->old_zoom = winwid->zoom; + winwid->zoom = winwid->zoom * 0.80; + winwid->im_x = (winwid->w / 2) - (((winwid->w / 2) - winwid->im_x) / + winwid->old_zoom * winwid->zoom); + winwid->im_y = (winwid->h / 2) - (((winwid->h / 2) - winwid->im_y) / + winwid->old_zoom * winwid->zoom); + winwidget_sanitise_offsets(winwid); winwidget_render_image(winwid, 0, 0); - break; - case XK_KP_Add: - case XK_Up: - if (kev->state & ControlMask) { - winwid->im_y += 10; - winwidget_render_image(winwid, 0, 0); - } - else { - /* erroneously recognized as '+' in the *kbuf switch. Work around this. */ - len = 0; - winwid->old_zoom = winwid->zoom; - winwid->zoom = winwid->zoom * 1.25; - winwid->im_x = (winwid->w / 2) - (((winwid->w / 2) - winwid->im_x) / - winwid->old_zoom * winwid->zoom); - winwid->im_y = (winwid->h / 2) - (((winwid->h / 2) - winwid->im_y) / - winwid->old_zoom * winwid->zoom); - winwidget_sanitise_offsets(winwid); - winwidget_render_image(winwid, 0, 1); - } - break; - case XK_KP_Subtract: - case XK_Down: - if (kev->state & ControlMask) { - winwid->im_y -= 10; - winwidget_render_image(winwid, 0, 0); - } - else { - len = 0; - winwid->old_zoom = winwid->zoom; - winwid->zoom = winwid->zoom * 0.75; - winwid->im_x = (winwid->w / 2) - (((winwid->w / 2) - winwid->im_x) / - winwid->old_zoom * winwid->zoom); - winwid->im_y = (winwid->h / 2) - (((winwid->h / 2) - winwid->im_y) / - winwid->old_zoom * winwid->zoom); - winwidget_sanitise_offsets(winwid); - winwidget_render_image(winwid, 0, 1); - } - break; - case XK_KP_Multiply: - len = 0; + } + else if (feh_is_kp(&keys.zoom_default, keysym, state)) { winwid->zoom = 1; + winwid->old_zoom = 1.001; /* hack for --scale-down */ winwidget_center_image(winwid); winwidget_render_image(winwid, 0, 0); - break; - case XK_KP_Divide: - len = 0; + } + else if (feh_is_kp(&keys.zoom_fit, keysym, state)) { feh_calc_needed_zoom(&winwid->zoom, winwid->im_w, winwid->im_h, winwid->w, winwid->h); winwidget_center_image(winwid); - winwidget_render_image(winwid, 0, 1); - break; - case XK_KP_Begin: - winwidget_render_image(winwid, 0, 1); - break; - default: - break; + winwidget_render_image(winwid, 0, 0); } - - if (len <= 0 || len > (int) sizeof(kbuf)) - return; - kbuf[len] = '\0'; - - switch (*kbuf) { - case 'a': + else if (feh_is_kp(&keys.render, keysym, state)) { + winwidget_render_image(winwid, 0, 0); + } + else if (feh_is_kp(&keys.toggle_actions, keysym, state)) { opt.draw_actions = !opt.draw_actions; - winwidget_rerender_all(0, 1); - break; - case 'd': + winwidget_rerender_all(0); + } + else if (feh_is_kp(&keys.toggle_aliasing, keysym, state)) { + opt.force_aliasing = !opt.force_aliasing; + winwidget_rerender_all(0); + } + else if (feh_is_kp(&keys.toggle_filenames, keysym, state)) { opt.draw_filename = !opt.draw_filename; - winwidget_rerender_all(0, 1); - break; - case 'n': - case ' ': - if (opt.slideshow) - slideshow_change_image(winwid, SLIDE_NEXT); - break; - case 'o': + winwidget_rerender_all(0); + } + else if (feh_is_kp(&keys.toggle_pointer, keysym, state)) { winwidget_set_pointer(winwid, opt.hide_pointer); opt.hide_pointer = !opt.hide_pointer; - break; - case 'p': - case '\b': - if (opt.slideshow) - slideshow_change_image(winwid, SLIDE_PREV); - break; - case 'z': - if (opt.slideshow) - slideshow_change_image(winwid, SLIDE_RAND); - break; - case 'q': - winwidget_destroy_all(); - break; - case 'c': + } + else if (feh_is_kp(&keys.jump_random, keysym, state)) { + slideshow_change_image(winwid, SLIDE_RAND); + } + else if (feh_is_kp(&keys.toggle_caption, keysym, state)) { if (opt.caption_path) winwid->caption_entry = 1; - winwidget_render_image(winwid, 0, 1); - break; - case 'r': + winwidget_render_image(winwid, 0, 0); + } + else if (feh_is_kp(&keys.reload_image, keysym, state)) { feh_reload_image(winwid, 0, 0); - break; - case 'h': + } + else if (feh_is_kp(&keys.toggle_pause, keysym, state)) { slideshow_pause_toggle(winwid); - break; - case 's': + } + else if (feh_is_kp(&keys.save_image, keysym, state)) { slideshow_save_image(winwid); - break; - case 'f': + } + else if (feh_is_kp(&keys.save_filelist, keysym, state)) { if ((winwid->type == WIN_TYPE_THUMBNAIL) || (winwid->type == WIN_TYPE_THUMBNAIL_VIEWER)) weprintf("Filelist saving is not supported in thumbnail mode"); else feh_save_filelist(); - break; - case 'w': + } + else if (feh_is_kp(&keys.size_to_image, keysym, state)) { winwidget_size_to_image(winwid); - break; - case 'm': + } + else if (feh_is_kp(&keys.toggle_menu, keysym, state)) { winwidget_show_menu(winwid); - break; - case 'x': + } + else if (feh_is_kp(&keys.close, keysym, state)) { winwidget_destroy(winwid); - break; - case '>': + } + else if (feh_is_kp(&keys.orient_1, keysym, state)) { feh_edit_inplace_orient(winwid, 1); - break; - case '<': + } + else if (feh_is_kp(&keys.orient_3, keysym, state)) { feh_edit_inplace_orient(winwid, 3); - break; - case 'v': + } + else if (feh_is_kp(&keys.toggle_fullscreen, keysym, state)) { #ifdef HAVE_LIBXINERAMA if (opt.xinerama && xinerama_screens) { int i, rect[4]; @@ -425,7 +622,7 @@ void feh_event_handle_keypress(XEvent * ev) winwid->full_screen = !winwid->full_screen; winwidget_destroy_xwin(winwid); winwidget_create_window(winwid, winwid->im_w, winwid->im_h); - winwidget_render_image(winwid, 1, 1); + winwidget_render_image(winwid, 1, 0); winwidget_show(winwid); #ifdef HAVE_LIBXINERAMA /* if we have xinerama and we're using it, then full screen the window @@ -436,20 +633,18 @@ void feh_event_handle_keypress(XEvent * ev) xinerama_screens[curr_screen].x_org, xinerama_screens[curr_screen].y_org); } #endif /* HAVE_LIBXINERAMA */ - case '+': + } + else if (feh_is_kp(&keys.reload_plus, keysym, state)){ if (opt.reload < SLIDESHOW_RELOAD_MAX) opt.reload++; else if (opt.verbose) weprintf("Cannot set RELOAD higher than %d seconds.", opt.reload); - break; - case '-': + } + else if (feh_is_kp(&keys.reload_minus, keysym, state)) { if (opt.reload > 1) opt.reload--; else if (opt.verbose) weprintf("Cannot set RELOAD lower than 1 second."); - break; - default: - break; } return; } @@ -1,6 +1,7 @@ /* list.c Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -1,6 +1,7 @@ /* main.c Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -43,8 +44,10 @@ int main(int argc, char **argv) init_imlib_fonts(); - if (opt.display) + if (opt.display) { init_x_and_imlib(); + init_keyevents(); + } feh_event_init(); @@ -1,6 +1,7 @@ /* menu.c Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -1267,7 +1268,7 @@ void feh_menu_cb_opt_fullscreen(feh_menu * m, feh_menu_item * i) winwidget_destroy_xwin(m->fehwin); winwidget_create_window(m->fehwin, m->fehwin->im_w, m->fehwin->im_h); - winwidget_render_image(m->fehwin, 1, 1); + winwidget_render_image(m->fehwin, 1, 0); winwidget_show(m->fehwin); #ifdef HAVE_LIBXINERAMA @@ -1342,7 +1343,7 @@ void feh_menu_cb(feh_menu * m, feh_menu_item * i, int action, void *data) winwidget_resize(m->fehwin, m->fehwin->im_w, m->fehwin->im_h); } winwidget_reset_image(m->fehwin); - winwidget_render_image(m->fehwin, 1, 1); + winwidget_render_image(m->fehwin, 1, 0); break; case CB_RELOAD: feh_reload_image(m->fehwin, 0, 0); @@ -1403,7 +1404,7 @@ void feh_menu_cb(feh_menu * m, feh_menu_item * i, int action, void *data) opt.draw_filename = TRUE; else opt.draw_filename = FALSE; - winwidget_rerender_all(0, 1); + winwidget_rerender_all(0); break; case CB_OPT_DRAW_ACTIONS: MENU_ITEM_TOGGLE(i); @@ -1411,7 +1412,7 @@ void feh_menu_cb(feh_menu * m, feh_menu_item * i, int action, void *data) opt.draw_actions = TRUE; else opt.draw_actions = FALSE; - winwidget_rerender_all(0, 1); + winwidget_rerender_all(0); break; case CB_OPT_KEEP_HTTP: MENU_ITEM_TOGGLE(i); @@ -1435,8 +1436,11 @@ void feh_menu_cb(feh_menu * m, feh_menu_item * i, int action, void *data) break; case CB_OPT_AUTO_ZOOM: MENU_ITEM_TOGGLE(i); - opt.auto_zoom = MENU_ITEM_IS_ON(i) ? 1 : 0; - winwidget_rerender_all(1, 1); + if (MENU_ITEM_IS_ON(i)) + opt.zoom_mode = ZOOM_MODE_FILL; + else + opt.zoom_mode = 0; + winwidget_rerender_all(1); break; } return; @@ -1487,7 +1491,7 @@ static feh_menu *feh_menu_func_gen_options(feh_menu * m) mm = feh_menu_new(); mm->name = estrdup("OPTIONS"); mm->fehwin = m->fehwin; - feh_menu_add_toggle_entry(mm, "Auto-Zoom", NULL, NULL, CB_OPT_AUTO_ZOOM, NULL, NULL, opt.auto_zoom); + feh_menu_add_toggle_entry(mm, "Auto-Zoom", NULL, NULL, CB_OPT_AUTO_ZOOM, NULL, NULL, (opt.zoom_mode == ZOOM_MODE_FILL)); feh_menu_add_toggle_entry(mm, "Freeze Window Size", NULL, NULL, CB_OPT_FREEZE_WINDOW, NULL, NULL, opt.geom_flags); feh_menu_add_toggle_entry(mm, "Fullscreen", NULL, NULL, @@ -1,6 +1,7 @@ /* menu.h Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to diff --git a/src/multiwindow.c b/src/multiwindow.c index c46e453..1bd8a8a 100644 --- a/src/multiwindow.c +++ b/src/multiwindow.c @@ -28,6 +28,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "timers.h" #include "filelist.h" #include "options.h" +#include "signals.h" void init_multiwindow_mode(void) { @@ -63,5 +64,8 @@ void init_multiwindow_mode(void) } free(s); } + + setup_signal_handlers(); + return; } diff --git a/src/options.c b/src/options.c index 2206f3e..de72429 100644 --- a/src/options.c +++ b/src/options.c @@ -1,6 +1,7 @@ /* options.c Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -28,9 +29,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "options.h" static void check_options(void); -static void feh_create_default_config(char *rcfile); -static void feh_parse_option_array(int argc, char **argv); -static void feh_parse_environment_options(void); +static void feh_getopt_theme(int argc, char **argv); +static void feh_parse_option_array(int argc, char **argv, int finalrun); static void feh_check_theme_options(int arg, char **argv); static void feh_parse_options_from_string(char *opts); static void feh_load_options_for_theme(char *theme); @@ -80,8 +80,6 @@ void init_parse_options(int argc, char **argv) opt.start_list_at = NULL; opt.jump_on_resort = 1; - opt.builtin_http = 0; - opt.xinerama = 0; opt.screen_clip = 1; #ifdef HAVE_LIBXINERAMA @@ -89,17 +87,15 @@ void init_parse_options(int argc, char **argv) opt.xinerama = 1; #endif /* HAVE_LIBXINERAMA */ - D(("About to parse env options (if any)\n")); - /* Check for and parse any options in FEH_OPTIONS */ - feh_parse_environment_options(); - - D(("About to parse commandline options\n")); - /* Parse the cmdline args */ - feh_parse_option_array(argc, argv); + feh_getopt_theme(argc, argv); D(("About to check for theme configuration\n")); feh_check_theme_options(argc, argv); + D(("About to parse commandline options\n")); + /* Parse the cmdline args */ + feh_parse_option_array(argc, argv, 1); + /* If we have a filelist to read, do it now */ if (opt.filelistfile) { /* joining two reverse-sorted lists in this manner works nicely for us @@ -147,35 +143,38 @@ static void feh_check_theme_options(int arg, char **argv) static void feh_load_options_for_theme(char *theme) { FILE *fp = NULL; - char *home; + char *home = getenv("HOME"); char *rcpath = NULL; + char *oldrcpath = NULL; + char *confbase = getenv("XDG_CONFIG_HOME"); char s[1024], s1[1024], s2[1024]; int cont = 0; int bspos; - if (opt.rcfile) { - if ((fp = fopen(opt.rcfile, "r")) == NULL) { - weprintf("couldn't load the specified rcfile %s\n", opt.rcfile); - return; - } - } else { - home = getenv("HOME"); - if (!home) - eprintf("D'oh! Please define HOME in your environment! " - "It would really help me out...\n"); - rcpath = estrjoin("/", home, ".fehrc", NULL); - D(("Trying %s for config\n", rcpath)); - fp = fopen(rcpath, "r"); - - if (!fp && ((fp = fopen("/etc/fehrc", "r")) == NULL)) { - feh_create_default_config(rcpath); - - if ((fp = fopen(rcpath, "r")) == NULL) - return; - } + if (!home) + eprintf("You have no HOME, cannot read themes"); - free(rcpath); - } + oldrcpath = estrjoin("/", home, ".fehrc", NULL); + + if (confbase) + rcpath = estrjoin("/", confbase, "feh/themes", NULL); + else + rcpath = estrjoin("/", home, ".config/feh/themes", NULL); + + fp = fopen(rcpath, "r"); + + free(rcpath); + + if (!fp && ((fp = fopen(oldrcpath, "r")) != NULL)) + weprintf("The theme config file was moved from ~/.fehrc to " + "~/.config/feh/themes. Run\n" + " mkdir -p ~/.config/feh; mv ~/.fehrc ~/.config/feh/themes\n" + "to fix this."); + + free(oldrcpath); + + if (!fp && ((fp = fopen("/etc/feh/themes", "r")) == NULL)) + return; /* Oooh. We have an options file :) */ for (; fgets(s, sizeof(s), fp);) { @@ -221,22 +220,6 @@ static void feh_load_options_for_theme(char *theme) return; } -static void feh_parse_environment_options(void) -{ - char *opts; - - if ((opts = getenv("FEH_OPTIONS")) == NULL) - return; - - weprintf - ("The FEH_OPTIONS configuration method is depreciated and will soon die.\n" - "Use the .fehrc configuration file instead."); - - /* We definitely have some options to parse */ - feh_parse_options_from_string(opts); - return; -} - /* FIXME This function is a crufty bitch ;) */ static void feh_parse_options_from_string(char *opts) { @@ -275,7 +258,7 @@ static void feh_parse_options_from_string(char *opts) last = *t; } - feh_parse_option_array(num, list); + feh_parse_option_array(num, list, 0); for (i = 0; i < num; i++) if (list[i]) @@ -317,11 +300,31 @@ char *feh_string_normalize(char *str) return(estrdup(ret)); } -static void feh_parse_option_array(int argc, char **argv) +static void feh_getopt_theme(int argc, char **argv) +{ + static char stropts[] = "-T:"; + static struct option lopts[] = { + {"theme", 1, 0, 'T'}, + {0, 0, 0, 0} + }; + int optch = 0, cmdx = 0; + + opterr = 0; + + while ((optch = getopt_long(argc, argv, stropts, lopts, &cmdx)) != EOF) { + if (optch == 'T') + theme = estrdup(optarg); + } + + opterr = 1; + optind = 0; +} + +static void feh_parse_option_array(int argc, char **argv, int finalrun) { static char stropts[] = - "a:A:b:B:cC:dD:e:E:f:Fg:GhH:iIj:J:kK:lL:mM:nNo:O:pPqQrR:sS:tT:uUvVwW:xXy:YzZ" - "0:1:2:4:5:8:9:.@:^:~:):|:_:+:"; + "a:A:b:B:cC:dD:e:E:f:Fg:GhH:iIj:J:kK:lL:mM:nNo:O:pPqrR:sS:tT:uUvVwW:xXy:YzZ" + "0:1:2:4:5:8:9:.@:^:~:):|:+:"; /* (*name, has_arg, *flag, val) See: struct option in getopts.h */ static struct option lopts[] = { @@ -351,7 +354,6 @@ static void feh_parse_option_array(int argc, char **argv) {"preload" , 0, 0, 'p'}, {"reverse" , 0, 0, 'n'}, {"thumbnails" , 0, 0, 't'}, - {"builtin" , 0, 0, 'Q'}, {"scale-down" , 0, 0, '.'}, {"no-jump-on-resort", 0, 0, 220}, {"hide-pointer" , 0, 0, 'Y'}, @@ -396,7 +398,6 @@ static void feh_parse_option_array(int argc, char **argv) {"rotate-button" , 1, 0, '8'}, {"blur-button" , 1, 0, '9'}, {"start-at" , 1, 0, '|'}, - {"rcfile" , 1, 0, '_'}, {"debug" , 0, 0, '+'}, {"output-dir" , 1, 0, 'j'}, {"bg-tile" , 1, 0, 200}, @@ -422,11 +423,11 @@ static void feh_parse_option_array(int argc, char **argv) {"index-dim" , 1, 0, 232}, {"thumb-redraw" , 1, 0, 'J'}, {"info" , 1, 0, 234}, + {"force-aliasing", 0, 0, 235}, {0, 0, 0, 0} }; int optch = 0, cmdx = 0; - int i = 0; /* Now to pass some optionarinos */ while ((optch = getopt_long(argc, argv, stropts, lopts, &cmdx)) != EOF) { @@ -468,9 +469,6 @@ static void feh_parse_option_array(int argc, char **argv) opt.list = 1; opt.display = 0; break; - case 'Q': - opt.builtin_http = 1; - break; case 'L': opt.customlist = estrdup(optarg); opt.display = 0; @@ -522,7 +520,7 @@ static void feh_parse_option_array(int argc, char **argv) opt.full_screen = 1; break; case 'Z': - opt.auto_zoom = 1; + opt.zoom_mode = ZOOM_MODE_MAX; break; case 'U': opt.loadables = 1; @@ -591,9 +589,6 @@ static void feh_parse_option_array(int argc, char **argv) opt.bg = 1; opt.bg_file = estrdup(optarg); break; - case '_': - opt.rcfile = estrdup(optarg); - break; case 'A': opt.actions[0] = estrdup(optarg); break; @@ -612,6 +607,7 @@ static void feh_parse_option_array(int argc, char **argv) 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 'B': free(opt.image_bg); @@ -693,9 +689,15 @@ static void feh_parse_option_array(int argc, char **argv) case 204: free(opt.menu_style); opt.menu_style = estrdup(optarg); + weprintf("The --menu-style option is deprecated and will be removed by 2012"); break; case 205: - opt.default_zoom = atoi(optarg); + if (!strcmp("fill", optarg)) + opt.zoom_mode = ZOOM_MODE_FILL; + else if (!strcmp("max", optarg)) + opt.zoom_mode = ZOOM_MODE_MAX; + else + opt.default_zoom = atoi(optarg); break; case 206: opt.screen_clip = 0; @@ -772,6 +774,9 @@ static void feh_parse_option_array(int argc, char **argv) case 234: opt.info_cmd = estrdup(optarg); break; + case 235: + opt.force_aliasing = 1; + break; default: break; } @@ -785,13 +790,8 @@ static void feh_parse_option_array(int argc, char **argv) add_file_to_filelist_recursively(argv[optind++], FILELIST_FIRST); } } - - for (i = 0; i < 10; i++) { - if (opt.actions[i] && !opt.hold_actions[i] && (opt.actions[i][0] == ';')) { - opt.hold_actions[i] = 1; - opt.actions[i] = &opt.actions[i][1]; - } - } + else if (finalrun && !opt.filelistfile && !opt.bgmode) + add_file_to_filelist_recursively(".", FILELIST_FIRST); /* So that we can safely be called again */ optind = 1; @@ -800,6 +800,14 @@ static void feh_parse_option_array(int argc, char **argv) static void check_options(void) { + int i; + for (i = 0; i < 10; i++) { + if (opt.actions[i] && !opt.hold_actions[i] && (opt.actions[i][0] == ';')) { + opt.hold_actions[i] = 1; + opt.actions[i] = &opt.actions[i][1]; + } + } + if ((opt.index + opt.collage) > 1) { weprintf("you can't use collage mode and index mode together.\n" " I'm going with index"); @@ -843,7 +851,23 @@ static void check_options(void) static void show_version(void) { - printf(PACKAGE " version " VERSION "\n"); + puts(PACKAGE " version " VERSION); + puts("Compile-time switches: " + +#ifdef HAVE_LIBCURL + "curl " +#endif + +#ifdef DEBUG + "debug " +#endif + +#ifdef HAVE_LIBXINERAMA + "xinerama " +#endif + + ); + exit(0); } @@ -861,20 +885,3 @@ static void show_usage(void) , stdout); exit(0); } - -static void feh_create_default_config(char *rcfile) -{ - FILE *fp; - - if ((fp = fopen(rcfile, "w")) == NULL) { - weprintf("Unable to create default config file %s\n", rcfile); - return; - } - - fputs( -#include "fehrc.inc" - , fp); - fclose(fp); - - return; -} diff --git a/src/options.h b/src/options.h index e99c14c..431fdfc 100644 --- a/src/options.h +++ b/src/options.h @@ -1,6 +1,7 @@ /* options.h Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -26,6 +27,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifndef OPTIONS_H #define OPTIONS_H +#define ZOOM_MODE_FILL 1 +#define ZOOM_MODE_MAX 2 + struct __fehoptions { unsigned char multiwindow; unsigned char montage; @@ -50,7 +54,6 @@ struct __fehoptions { unsigned char randomize; unsigned char jump_on_resort; unsigned char full_screen; - unsigned char auto_zoom; unsigned char draw_filename; unsigned char list; unsigned char quiet; @@ -60,7 +63,6 @@ struct __fehoptions { unsigned char reverse; unsigned char no_menus; unsigned char scale_down; - unsigned char builtin_http; unsigned char bgmode; unsigned char xinerama; unsigned char screen_clip; @@ -84,7 +86,6 @@ struct __fehoptions { char *customlist; char *menu_bg; char *image_bg; - char *rcfile; char *menu_style; char *caption_path; char *start_list_at; @@ -106,6 +107,7 @@ struct __fehoptions { unsigned char no_blur_ctrl_mask; unsigned char no_pan_ctrl_mask; + int force_aliasing; int thumb_w; int thumb_h; int limit_w; @@ -120,6 +122,7 @@ struct __fehoptions { unsigned int geom_w; unsigned int geom_h; int default_zoom; + int zoom_mode; unsigned char adjust_reload; unsigned char mode; @@ -130,6 +133,66 @@ struct __fehoptions { Imlib_Font menu_fn; }; +struct __fehkey { + int keysyms[3]; + int keystates[3]; +}; + +struct __fehkb { + struct __fehkey menu_close; + struct __fehkey menu_parent; + struct __fehkey menu_down; + struct __fehkey menu_up; + struct __fehkey menu_child; + struct __fehkey menu_select; + struct __fehkey scroll_right; + struct __fehkey prev_img; + struct __fehkey scroll_left; + struct __fehkey next_img; + struct __fehkey scroll_up; + struct __fehkey scroll_down; + struct __fehkey jump_back; + struct __fehkey quit; + struct __fehkey jump_fwd; + struct __fehkey remove; + struct __fehkey delete; + struct __fehkey jump_first; + struct __fehkey jump_last; + struct __fehkey action_0; + struct __fehkey action_1; + struct __fehkey action_2; + struct __fehkey action_3; + struct __fehkey action_4; + struct __fehkey action_5; + struct __fehkey action_6; + struct __fehkey action_7; + struct __fehkey action_8; + struct __fehkey action_9; + struct __fehkey zoom_in; + struct __fehkey zoom_out; + struct __fehkey zoom_default; + struct __fehkey zoom_fit; + struct __fehkey render; + struct __fehkey toggle_actions; + struct __fehkey toggle_filenames; + struct __fehkey toggle_pointer; + struct __fehkey toggle_aliasing; + struct __fehkey jump_random; + struct __fehkey toggle_caption; + struct __fehkey toggle_pause; + struct __fehkey reload_image; + struct __fehkey save_image; + struct __fehkey save_filelist; + struct __fehkey size_to_image; + struct __fehkey toggle_menu; + struct __fehkey close; + struct __fehkey orient_1; + struct __fehkey orient_3; + struct __fehkey toggle_fullscreen; + struct __fehkey reload_minus; + struct __fehkey reload_plus; +}; + void init_parse_options(int argc, char **argv); char *feh_string_normalize(char *str); diff --git a/src/signals.c b/src/signals.c index b3e118a..956c861 100644 --- a/src/signals.c +++ b/src/signals.c @@ -25,6 +25,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "feh.h" #include "winwidget.h" +#include "options.h" void feh_handle_signal(int); @@ -60,12 +61,16 @@ void feh_handle_signal(int signo) { winwidget winwid = winwidget_get_first_window_of_type(WIN_TYPE_SLIDESHOW); + int i; if (winwid) { if (signo == SIGUSR1) slideshow_change_image(winwid, SLIDE_NEXT); else if (signo == SIGUSR2) slideshow_change_image(winwid, SLIDE_PREV); + } else if (opt.multiwindow) { + for (i = window_num - 1; i >= 0; i--) + feh_reload_image(windows[i], 0, 0); } return; diff --git a/src/slideshow.c b/src/slideshow.c index de10300..79b931f 100644 --- a/src/slideshow.c +++ b/src/slideshow.c @@ -1,6 +1,7 @@ /* slideshow.c Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -100,12 +101,15 @@ void feh_reload_image(winwidget w, int resize, int force_new) char *title, *new_title; int len; Imlib_Image tmp; + int old_w, old_h; if (!w->file) { weprintf("couldn't reload, this image has no file associated with it."); return; } + D(("resize %d, force_new %d\n", resize, force_new)); + free(FEH_FILE(w->file->data)->caption); FEH_FILE(w->file->data)->caption = NULL; @@ -115,10 +119,11 @@ void feh_reload_image(winwidget w, int resize, int force_new) title = estrdup(w->name); winwidget_rename(w, new_title); + old_w = gib_imlib_image_get_width(w->im); + old_h = gib_imlib_image_get_height(w->im); + /* force imlib2 not to cache */ - if (force_new) { - winwidget_free_image(w); - } + winwidget_free_image(w); /* if the image has changed in dimensions - we gotta resize */ if ((feh_load_image(&tmp, FEH_FILE(w->file->data))) == 0) { @@ -133,19 +138,13 @@ void feh_reload_image(winwidget w, int resize, int force_new) filelist = feh_file_remove_from_list(filelist, w->file); return; } - if (force_new) { - w->im = tmp; + + if (!resize && ((old_w != gib_imlib_image_get_width(tmp)) || + (old_h != gib_imlib_image_get_height(tmp)))) resize = 1; - winwidget_reset_image(w); - } else { - if ((gib_imlib_image_get_width(w->im) != gib_imlib_image_get_width(tmp)) - || (gib_imlib_image_get_height(w->im) != gib_imlib_image_get_height(tmp))) { - resize = 1; - winwidget_reset_image(w); - } - winwidget_free_image(w); - w->im = tmp; - } + + w->im = tmp; + winwidget_reset_image(w); w->mode = MODE_NORMAL; if ((w->im_w != gib_imlib_image_get_width(w->im)) @@ -162,7 +161,7 @@ void feh_reload_image(winwidget w, int resize, int force_new) w->im_w = gib_imlib_image_get_width(w->im); w->im_h = gib_imlib_image_get_height(w->im); } - winwidget_render_image(w, resize, 1); + winwidget_render_image(w, resize, 0); winwidget_rename(w, title); free(title); @@ -251,10 +250,6 @@ void slideshow_change_image(winwidget winwid, int change) filelist = feh_file_remove_from_list(filelist, last); last = NULL; } - s = slideshow_create_name(FEH_FILE(current_file->data)); - - winwidget_rename(winwid, s); - free(s); if ((winwidget_loadimage(winwid, FEH_FILE(current_file->data))) != 0) { @@ -267,7 +262,12 @@ void slideshow_change_image(winwidget winwid, int change) winwidget_reset_image(winwid); winwid->im_w = gib_imlib_image_get_width(winwid->im); winwid->im_h = gib_imlib_image_get_height(winwid->im); - winwidget_render_image(winwid, 1, 1); + winwidget_render_image(winwid, 1, 0); + + s = slideshow_create_name(FEH_FILE(current_file->data)); + winwidget_rename(winwid, s); + free(s); + break; } else last = current_file; diff --git a/src/structs.h b/src/structs.h index a2d3527..3942bc0 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1,6 +1,7 @@ /* structs.h Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -33,5 +34,7 @@ typedef struct __feh_file_info feh_file_info; typedef struct __winwidget _winwidget; typedef _winwidget *winwidget; typedef struct __fehoptions fehoptions; +typedef struct __fehkey fehkey; +typedef struct __fehkb fehkb; #endif diff --git a/src/support.c b/src/support.c index afb941b..e257271 100644 --- a/src/support.c +++ b/src/support.c @@ -1,6 +1,7 @@ /* support.c Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -130,7 +131,7 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled, enl_ipc_sync(); } else { Atom prop_root, prop_esetroot, type; - int format; + int format, i; unsigned long length, after; unsigned char *data_root, *data_esetroot; Pixmap pmap_d1, pmap_d2; @@ -138,6 +139,10 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled, char *fehbg = NULL; char *home; char filbuf[PATH_MAX]; + char fehbg_xinerama[] = "--no-xinerama"; + + if (opt.xinerama) + fehbg_xinerama[0] = '\0'; /* local display to set closedownmode on */ Display *disp2; @@ -162,21 +167,20 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled, filbuf[out++] = 0; if (scaled) { - w = scr->width; - h = scr->height; - -/* disable xinerama check for setting background */ -#if 0 -/* #ifdef HAVE_LIBXINERAMA */ - if (opt.xinerama && xinerama_screens) { - w = xinerama_screens[xinerama_screen].width; - h = xinerama_screens[xinerama_screen].height; - } -#endif /* HAVE_LIBXINERAMA */ - - pmap_d1 = XCreatePixmap(disp, root, w, h, depth); - gib_imlib_render_image_on_drawable_at_size(pmap_d1, im, 0, 0, w, h, 1, 0, 1); - fehbg = estrjoin(" ", "feh --bg-scale", filbuf, NULL); + pmap_d1 = XCreatePixmap(disp, root, scr->width, scr->height, depth); + +#ifdef HAVE_LIBXINERAMA + if (opt.xinerama && xinerama_screens) + for (i = 0; i < num_xinerama_screens; i++) + gib_imlib_render_image_on_drawable_at_size(pmap_d1, im, + xinerama_screens[i].x_org, xinerama_screens[i].y_org, + xinerama_screens[i].width, xinerama_screens[i].height, + 1, 0, !opt.force_aliasing); + else +#endif /* HAVE_LIBXINERAMA */ + gib_imlib_render_image_on_drawable_at_size(pmap_d1, im, 0, 0, + scr->width, scr->height, 1, 0, !opt.force_aliasing); + fehbg = estrjoin(" ", "feh", fehbg_xinerama, "--bg-scale", filbuf, NULL); } else if (centered) { XGCValues gcval; GC gc; @@ -185,25 +189,33 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled, D(("centering\n")); w = scr->width; h = scr->height; - -/* disable xinerama check for setting background */ -#if 0 -/* #ifdef HAVE_LIBXINERAMA */ - if (opt.xinerama && xinerama_screens) { - w = xinerama_screens[xinerama_screen].width; - h = xinerama_screens[xinerama_screen].height; - } -#endif /* HAVE_LIBXINERAMA */ + x = (w - gib_imlib_image_get_width(im)) >> 1; + y = (h - gib_imlib_image_get_height(im)) >> 1; pmap_d1 = XCreatePixmap(disp, root, w, h, depth); gcval.foreground = BlackPixel(disp, DefaultScreen(disp)); gc = XCreateGC(disp, root, GCForeground, &gcval); XFillRectangle(disp, pmap_d1, gc, 0, 0, w, h); - x = (w - gib_imlib_image_get_width(im)) >> 1; - y = (h - gib_imlib_image_get_height(im)) >> 1; - gib_imlib_render_image_on_drawable(pmap_d1, im, x, y, 1, 0, 0); + +#ifdef HAVE_LIBXINERAMA + if (opt.xinerama && xinerama_screens) + for (i = 0; i < num_xinerama_screens; i++) { + w = xinerama_screens[i].width; + h = xinerama_screens[i].height; + x = (w - gib_imlib_image_get_width(im)) >> 1; + y = (h - gib_imlib_image_get_height(im)) >> 1; + gib_imlib_render_image_part_on_drawable_at_size( + pmap_d1, im, + ((x < 0) ? -x : 0) , ((y < 0) ? -y : 0), w, h, + xinerama_screens[i].x_org + ((x > 0) ? x : 0), + xinerama_screens[i].y_org + ((y > 0) ? y : 0), + w, h, 1, 0, 0); + } + else +#endif /* HAVE_LIBXINERAMA */ + gib_imlib_render_image_on_drawable(pmap_d1, im, x, y, 1, 0, 0); XFreeGC(disp, gc); - fehbg = estrjoin(" ", "feh --bg-center", filbuf, NULL); + fehbg = estrjoin(" ", "feh", fehbg_xinerama, "--bg-center", filbuf, NULL); } else if (filled == 1) { int scr_w = scr->width; int scr_h = scr->height; @@ -211,20 +223,44 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled, int img_h = gib_imlib_image_get_height(im); int render_x = 0; int render_y = 0; + int cut_x = (((img_w * scr_h) > (img_h * scr_w)) ? 1 : 0); + w = (cut_x ? ((scr_h * img_w) / img_h) : scr_w); + h = (cut_x ? scr_h : ((scr_w * img_h) / img_w)); + + if (cut_x) + render_x = (scr_w - w) >> 1; + else + render_y = (scr_h - h) >> 1; - if ((img_w * scr_h) > (scr_w * img_h)) { - h = scr_h; - w = (scr_h * img_w) / img_h; - render_x = (scr_w - w) / 2; - } else { - h = (scr_w * img_h) / img_w; - w = scr_w; - render_y = (scr_h - h) / 2; - } pmap_d1 = XCreatePixmap(disp, root, w, h, depth); - gib_imlib_render_image_on_drawable_at_size(pmap_d1, im, - render_x, render_y, w, h, 1, 0, 1); - fehbg = estrjoin(" ", "feh --bg-fill", filbuf, NULL); + +#ifdef HAVE_LIBXINERAMA + if (opt.xinerama && xinerama_screens) + for (i = 0; i < num_xinerama_screens; i++) { + scr_w = xinerama_screens[i].width; + scr_h = xinerama_screens[i].height; + cut_x = (((img_w * scr_h) > (img_h * scr_w)) ? 1 : 0); + w = (cut_x ? ((img_h * scr_w) / scr_h) : img_w); + h = (cut_x ? img_h : ((img_w * scr_h) / scr_w)); + render_x = (cut_x ? ((img_w - w) >> 1) : 0); + render_y = (cut_x ? 0 : ((img_h - h) >> 1)); + + D(("cut_x %d w %5d h %5d x %5d y %5d\n", + cut_x, w, h, render_x, render_y)); + + gib_imlib_render_image_part_on_drawable_at_size( + pmap_d1, im, + render_x, render_y, + w, h, + xinerama_screens[i].x_org, + xinerama_screens[i].y_org, + scr_w, scr_h, 1, 0, !opt.force_aliasing); + } + else +#endif /* HAVE_LIBXINERAMA */ + gib_imlib_render_image_on_drawable_at_size(pmap_d1, im, + render_x, render_y, w, h, 1, 0, !opt.force_aliasing); + fehbg = estrjoin(" ", "feh", fehbg_xinerama, "--bg-fill", filbuf, NULL); } else if (filled == 2) { int scr_w = scr->width; int scr_h = scr->height; @@ -232,38 +268,48 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled, int img_h = gib_imlib_image_get_height(im); int render_x = 0; int render_y = 0; + int border_x = (((img_w * scr_h) > (img_h * scr_w)) ? 0 : 1); + w = (border_x ? ((scr_h * img_w) / img_h) : scr_w); + h = (border_x ? scr_h : ((scr_w * img_h) / img_w)); XGCValues gcval; - if (img_w > img_h) { - w = scr_w; - h = (((scr_w * 100) / img_w) * img_h) / 100; - render_y = (scr_h - h) / 2; - if (h > scr_h) { - w = (((scr_h * 100) / h) * w) / 100; - h = scr_h; - render_x = (scr_w - w) / 2; - render_y = 0; - } - } else { - h = scr_h; - w = (((scr_h * 100) / img_h) * img_w) / 100; - render_x = (scr_w - w) / 2; - if (w > scr_w) { - h = (((scr_w * 100) / w) * h) / 100; - w = scr_w; - render_x = 0; - render_y = (scr_h - h) / 2; - } - } + if (border_x) + render_x = (scr_w - w) >> 1; + else + render_y = (scr_h - h) >> 1; pmap_d1 = XCreatePixmap(disp, root, scr_w, scr_h, depth); gcval.foreground = BlackPixel(disp, DefaultScreen(disp)); gc = XCreateGC(disp, root, GCForeground, &gcval); XFillRectangle(disp, pmap_d1, gc, 0, 0, scr_w, scr_h); + +#ifdef HAVE_LIBXINERAMA + if (opt.xinerama && xinerama_screens) + for (i = 0; i < num_xinerama_screens; i++) { + scr_w = xinerama_screens[i].width; + scr_h = xinerama_screens[i].height; + border_x = (((img_w * scr_h) > (img_h * scr_w)) ? 0 : 1); + w = (border_x ? ((scr_h * img_w) / img_h) : scr_w); + h = (border_x ? scr_h : ((scr_w * img_h) / img_w)); + render_x = (border_x ? ((scr_w - w) >> 1) : 0); + render_y = (border_x ? 0 : ((scr_h - h) >> 1)); + + D(("border_x %d w %5d h %5d x %5d y %5d\n", + border_x, w, h, render_x, render_y)); + + gib_imlib_render_image_on_drawable_at_size( + pmap_d1, im, + xinerama_screens[i].x_org + render_x, + xinerama_screens[i].y_org + render_y, + w, h, + 1, 0, !opt.force_aliasing); + } + else +#endif /* HAVE_LIBXINERAMA */ gib_imlib_render_image_on_drawable_at_size(pmap_d1, im, - render_x, render_y, w, h, 1, 0, 1); + render_x, render_y, w, h, 1, 0, !opt.force_aliasing); XFreeGC(disp, gc); - fehbg = estrjoin(" ", "feh --bg-max", filbuf, NULL); + fehbg = estrjoin(" ", "feh", fehbg_xinerama, "--bg-max", filbuf, NULL); } else { w = gib_imlib_image_get_width(im); h = gib_imlib_image_get_height(im); diff --git a/src/support.h b/src/support.h index bb17082..3cd0fe1 100644 --- a/src/support.h +++ b/src/support.h @@ -1,6 +1,7 @@ /* support.h Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to diff --git a/src/thumbnail.c b/src/thumbnail.c index ed4e0fb..ca5c387 100644 --- a/src/thumbnail.c +++ b/src/thumbnail.c @@ -1,6 +1,7 @@ /* thumbnail.c Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -57,6 +58,7 @@ void init_thumbnail_mode(void) Imlib_Image im_temp; int ww = 0, hh = 0, www, hhh, xxx, yyy; + int orig_w, orig_h; int x = 0, y = 0; winwidget winwid = NULL; Imlib_Image im_thumb = NULL; @@ -204,7 +206,8 @@ void init_thumbnail_mode(void) } D(("About to load image %s\n", file->filename)); /* if (feh_load_image(&im_temp, file) != 0) */ - if (feh_thumbnail_get_thumbnail(&im_temp, file) != 0) { + if (feh_thumbnail_get_thumbnail(&im_temp, file, &orig_w, &orig_h) + != 0) { if (opt.verbose) feh_display_status('.'); D(("Successfully loaded %s\n", file->filename)); @@ -212,6 +215,12 @@ void init_thumbnail_mode(void) hhh = opt.thumb_h; ww = gib_imlib_image_get_width(im_temp); hh = gib_imlib_image_get_height(im_temp); + + if (!orig_w) { + orig_w = ww; + orig_h = hh; + } + thumbnailcount++; if (gib_imlib_image_has_alpha(im_temp)) imlib_context_set_blend(1); @@ -333,7 +342,7 @@ void init_thumbnail_mode(void) td.font_main, NULL, x + x_offset_dim, y + opt.thumb_h + (lines++ * (th + 2)) + 2, - create_index_dimension_string(ww, hh), + create_index_dimension_string(orig_w, orig_h), IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255); if (opt.index_show_size) gib_imlib_text_draw(td.im_main, @@ -355,7 +364,7 @@ void init_thumbnail_mode(void) if (opt.display) { /* thumb_counter is unsigned, so no need to catch overflows */ if (++thumb_counter == opt.thumb_redraw) { - winwidget_render_image(winwid, 0, 0); + winwidget_render_image(winwid, 0, 1); thumb_counter = 0; } if (!feh_main_iteration(0)) @@ -364,7 +373,7 @@ void init_thumbnail_mode(void) } if (thumb_counter != 0) - winwidget_render_image(winwid, 0, 0); + winwidget_render_image(winwid, 0, 1); if (opt.verbose) fprintf(stdout, "\n"); @@ -717,21 +726,27 @@ void feh_thumbnail_calculate_geometry(void) } } -int feh_thumbnail_get_thumbnail(Imlib_Image * image, feh_file * file) +int feh_thumbnail_get_thumbnail(Imlib_Image * image, feh_file * file, + int * orig_w, int * orig_h) { int status = 0; char *thumb_file = NULL, *uri = NULL; + *orig_w = 0; + *orig_h = 0; + if (!file || !file->filename) return (0); if (td.cache_thumbnails) { uri = feh_thumbnail_get_name_uri(file->filename); thumb_file = feh_thumbnail_get_name(uri); - status = feh_thumbnail_get_generated(image, file, thumb_file); + status = feh_thumbnail_get_generated(image, file, thumb_file, + orig_w, orig_h); if (!status) - status = feh_thumbnail_generate(image, file, thumb_file, uri); + status = feh_thumbnail_generate(image, file, thumb_file, uri, + orig_w, orig_h); D(("uri is %s, thumb_file is %s\n", uri, thumb_file)); free(uri); @@ -808,15 +823,16 @@ char *feh_thumbnail_get_name_md5(char *uri) } int feh_thumbnail_generate(Imlib_Image * image, feh_file * file, - char *thumb_file, char *uri) + char *thumb_file, char *uri, int * orig_w, int * orig_h) { int w, h, thumb_w, thumb_h; Imlib_Image im_temp; struct stat sb; + char c_width[8], c_height[8]; if (feh_load_image(&im_temp, file) != 0) { - w = gib_imlib_image_get_width(im_temp); - h = gib_imlib_image_get_height(im_temp); + *orig_w = w = gib_imlib_image_get_width(im_temp); + *orig_h = h = gib_imlib_image_get_height(im_temp); thumb_w = td.cache_dim; thumb_h = td.cache_dim; @@ -834,8 +850,12 @@ int feh_thumbnail_generate(Imlib_Image * image, feh_file * file, if (!stat(file->filename, &sb)) { char c_mtime[128]; sprintf(c_mtime, "%d", (int)sb.st_mtime); + snprintf(c_width, 8, "%d", w); + snprintf(c_height, 8, "%d", h); feh_png_write_png(*image, thumb_file, "Thumb::URI", uri, - "Thumb::MTime", c_mtime); + "Thumb::MTime", c_mtime, + "Thumb::Image::Width", c_width, + "Thumb::Image::Height", c_height); } gib_imlib_free_image_and_decache(im_temp); @@ -846,19 +866,27 @@ int feh_thumbnail_generate(Imlib_Image * image, feh_file * file, return (0); } -int feh_thumbnail_get_generated(Imlib_Image * image, feh_file * file, char *thumb_file) +int feh_thumbnail_get_generated(Imlib_Image * image, feh_file * file, + char *thumb_file, int * orig_w, int * orig_h) { struct stat sb; char *c_mtime; + char *c_width, *c_height; time_t mtime = 0; gib_hash *hash; if (!stat(file->filename, &sb)) { hash = feh_png_read_comments(thumb_file); if (hash != NULL) { - c_mtime = (char *) gib_hash_get(hash, "Thumb::MTime"); + c_mtime = (char *) gib_hash_get(hash, "Thumb::MTime"); + c_width = (char *) gib_hash_get(hash, "Thumb::Image::Width"); + c_height = (char *) gib_hash_get(hash, "Thumb::Image::Height"); if (c_mtime != NULL) mtime = (time_t) strtol(c_mtime, NULL, 10); + if (c_width != NULL) + *orig_w = atoi(c_width); + if (c_height != NULL) + *orig_h = atoi(c_height); gib_hash_free_and_data(hash); } diff --git a/src/thumbnail.h b/src/thumbnail.h index a384d11..6d2dc77 100644 --- a/src/thumbnail.h +++ b/src/thumbnail.h @@ -1,6 +1,7 @@ /* thumbnail.h Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -73,9 +74,9 @@ void feh_thumbnail_mark_removed(feh_file * file, int deleted); void feh_thumbnail_calculate_geometry(void); -int feh_thumbnail_get_thumbnail(Imlib_Image * image, feh_file * file); -int feh_thumbnail_generate(Imlib_Image * image, feh_file * file, char *thumb_file, char *uri); -int feh_thumbnail_get_generated(Imlib_Image * image, feh_file * file, char *thumb_file); +int feh_thumbnail_get_thumbnail(Imlib_Image * image, feh_file * file, int * orig_w, int * orig_h); +int feh_thumbnail_generate(Imlib_Image * image, feh_file * file, char *thumb_file, char *uri, int * orig_w, int * orig_h); +int feh_thumbnail_get_generated(Imlib_Image * image, feh_file * file, char * thumb_file, int * orig_w, int * orig_h); char *feh_thumbnail_get_name(char *uri); char *feh_thumbnail_get_name_uri(char *name); char *feh_thumbnail_get_name_md5(char *uri); diff --git a/src/timers.c b/src/timers.c index cba0716..4cb5251 100644 --- a/src/timers.c +++ b/src/timers.c @@ -1,6 +1,7 @@ /* timers.c Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to diff --git a/src/winwidget.c b/src/winwidget.c index 26a43e2..a39e8ef 100644 --- a/src/winwidget.c +++ b/src/winwidget.c @@ -1,6 +1,7 @@ /* winwidget.c Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -57,6 +58,7 @@ static winwidget winwidget_allocate(void) ret->type = WIN_TYPE_UNSET; ret->visible = 0; ret->caption_entry = 0; + ret->force_aliasing = opt.force_aliasing; /* Zoom stuff */ ret->mode = MODE_NORMAL; @@ -98,7 +100,7 @@ winwidget winwidget_create_from_image(Imlib_Image im, char *name, char type) if (opt.full_screen && (type != WIN_TYPE_THUMBNAIL)) ret->full_screen = True; winwidget_create_window(ret, ret->w, ret->h); - winwidget_render_image(ret, 1, 1); + winwidget_render_image(ret, 1, 0); return(ret); } @@ -131,7 +133,7 @@ winwidget winwidget_create_from_file(gib_list * list, char *name, char type) if (opt.full_screen) ret->full_screen = True; winwidget_create_window(ret, ret->w, ret->h); - winwidget_render_image(ret, 1, 1); + winwidget_render_image(ret, 1, 0); } return(ret); @@ -361,10 +363,11 @@ void winwidget_setup_pixmaps(winwidget winwid) return; } -void winwidget_render_image(winwidget winwid, int resize, int alias) +void winwidget_render_image(winwidget winwid, int resize, int force_alias) { int sx, sy, sw, sh, dx, dy, dw, dh; int calc_w, calc_h; + int antialias = 0; if (!winwid->full_screen && resize) { winwidget_resize(winwid, winwid->im_w, winwid->im_h); @@ -377,13 +380,14 @@ void winwidget_render_image(winwidget winwid, int resize, int alias) if (winwid->im_y > winwid->h) winwid->im_y = winwid->h; - D(("winwidget_render_image resize %d alias %d im %dx%d\n", - resize, alias, winwid->im_w, winwid->im_h)); + D(("winwidget_render_image resize %d force_alias %d im %dx%d\n", + resize, force_alias, winwid->im_w, winwid->im_h)); winwidget_setup_pixmaps(winwid); if (!winwid->full_screen && opt.scale_down && ((winwid->w < winwid->im_w) - || (winwid->h < winwid->im_h))) { + || (winwid->h < winwid->im_h)) && + (winwid->old_zoom == 1.0)) { D(("scaling down image %dx%d\n", winwid->w, winwid->h)); feh_calc_needed_zoom(&(winwid->zoom), winwid->im_w, winwid->im_h, winwid->w, winwid->h); @@ -424,7 +428,7 @@ void winwidget_render_image(winwidget winwid, int resize, int alias) smaller = ((winwid->im_w < max_w) && (winwid->im_h < max_h)); - if (!smaller || opt.auto_zoom) { + if (!smaller || opt.zoom_mode) { double ratio = 0.0; /* Image is larger than the screen (so wants shrinking), or it's @@ -522,17 +526,22 @@ void winwidget_render_image(winwidget winwid, int resize, int alias) D(("sx: %d sy: %d sw: %d sh: %d dx: %d dy: %d dw: %d dh: %d zoom: %f\n", sx, sy, sw, sh, dx, dy, dw, dh, winwid->zoom)); + if ((winwid->zoom != 1.0) && !force_alias && !winwid->force_aliasing) + antialias = 1; + D(("winwidget_render(): winwid->im_angle = %f\n", winwid->im_angle)); if (winwid->has_rotated) gib_imlib_render_image_part_on_drawable_at_size_with_rotation - (winwid->bg_pmap, winwid->im, sx, sy, sw, sh, dx, dy, dw, dh, winwid->im_angle, 1, 1, alias); + (winwid->bg_pmap, winwid->im, sx, sy, sw, sh, dx, dy, dw, dh, + winwid->im_angle, 1, 1, antialias); else gib_imlib_render_image_part_on_drawable_at_size(winwid->bg_pmap, winwid->im, sx, sy, sw, sh, dx, dy, dw, dh, 1, - gib_imlib_image_has_alpha(winwid->im), alias); + gib_imlib_image_has_alpha(winwid->im), + antialias); if (opt.mode == MODE_NORMAL) { if (opt.caption_path) @@ -543,7 +552,7 @@ void winwidget_render_image(winwidget winwid, int resize, int alias) feh_draw_actions(winwid); if (opt.info_cmd) feh_draw_info(winwid); - } else if ((opt.mode == MODE_ZOOM) && !alias) + } else if ((opt.mode == MODE_ZOOM) && !antialias) feh_draw_zoom(winwid); XSetWindowBackgroundPixmap(disp, winwid->win, winwid->bg_pmap); @@ -578,6 +587,9 @@ double feh_calc_needed_zoom(double *zoom, int orig_w, int orig_h, int dest_w, in ratio = ((double) orig_w / orig_h) / ((double) dest_w / dest_h); + if (opt.zoom_mode == ZOOM_MODE_FILL) + ratio = 1.0 / ratio; + if (ratio > 1.0) *zoom = ((double) dest_w / orig_w); else @@ -686,13 +698,13 @@ void winwidget_destroy_all(void) return; } -void winwidget_rerender_all(int resize, int alias) +void winwidget_rerender_all(int resize) { int i; /* Have to DESCEND the list here, 'cos of the way _unregister works */ for (i = window_num - 1; i >= 0; i--) - winwidget_render_image(windows[i], resize, alias); + winwidget_render_image(windows[i], resize, 0); return; } @@ -908,6 +920,7 @@ void feh_debug_print_winwid(winwidget w) void winwidget_reset_image(winwidget winwid) { winwid->zoom = 1.0; + winwid->old_zoom = 1.0; winwid->im_x = 0; winwid->im_y = 0; winwid->im_angle = 0.0; @@ -982,7 +995,7 @@ void winwidget_size_to_image(winwidget winwid) { winwidget_resize(winwid, winwid->im_w * winwid->zoom, winwid->im_h * winwid->zoom); winwid->im_x = winwid->im_y = 0; - winwidget_render_image(winwid, 0, 1); + winwidget_render_image(winwid, 0, 0); return; } diff --git a/src/winwidget.h b/src/winwidget.h index 012d78f..922ecf5 100644 --- a/src/winwidget.h +++ b/src/winwidget.h @@ -1,6 +1,7 @@ /* winwidget.h Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to @@ -81,6 +82,7 @@ struct __winwidget { int h; int im_w; int im_h; + int force_aliasing; double im_angle; enum win_type type; unsigned char had_resize, full_screen; @@ -122,14 +124,14 @@ void winwidget_hide(winwidget winwid); void winwidget_destroy_all(void); void winwidget_free_image(winwidget w); void winwidget_center_image(winwidget w); -void winwidget_render_image(winwidget winwid, int resize, int alias); +void winwidget_render_image(winwidget winwid, int resize, int force_alias); void winwidget_rotate_image(winwidget winid, double angle); void winwidget_move(winwidget winwid, int x, int y); void winwidget_resize(winwidget winwid, int w, int h); void winwidget_setup_pixmaps(winwidget winwid); void winwidget_update_title(winwidget ret); void winwidget_update_caption(winwidget winwid); -void winwidget_rerender_all(int resize, int alias); +void winwidget_rerender_all(int resize); void winwidget_destroy_xwin(winwidget winwid); void winwidget_set_pointer(winwidget winwid, int visible); diff --git a/test/config/keys/feh/keys b/test/config/keys/feh/keys new file mode 100644 index 0000000..7114ecc --- /dev/null +++ b/test/config/keys/feh/keys @@ -0,0 +1,17 @@ +action_1 x +action_2 X +action_3 C-x +action_4 C-X +action_5 1-x +action_6 +action_7 + +next_img a b c +prev_img d e f + +# conflict with next_img/prev_img +toggle_actions +toggle_caption +toggle_filenames +save_filelist +close diff --git a/test/config/themes/feh/themes b/test/config/themes/feh/themes new file mode 100644 index 0000000..d4b7f69 --- /dev/null +++ b/test/config/themes/feh/themes @@ -0,0 +1,5 @@ +test_general --action1 "touch a1" + +test_multiline --action1 "touch a1" \ +--action2 "touch a2" \ + --action3 "touch a3" diff --git a/test/feh-bg.i b/test/feh-bg.i index eeff836..3624f5c 100755 --- a/test/feh-bg.i +++ b/test/feh-bg.i @@ -10,6 +10,8 @@ use Time::HiRes qw/sleep/; my ($pid_xnest, $pid_twm); +$ENV{HOME} = 'test'; + sub set_bg { my ($mode, $file) = @_; @@ -74,3 +76,4 @@ kill(15, $pid_xnest); sleep(0.2); unlink("/tmp/feh_${$}.png"); +unlink('test/.fehbg'); diff --git a/test/feh-scr.i b/test/feh-scr.i index 098f1c0..9696c9e 100755 --- a/test/feh-scr.i +++ b/test/feh-scr.i @@ -16,6 +16,8 @@ my ($width, $height); my $pwd = getcwd(); my $test_id = 0; +$ENV{HOME} = 'test'; + sub waitfor(&) { my ($sub) = @_; my $out; @@ -4,7 +4,7 @@ use warnings; use 5.010; use Cwd; -use Test::More tests => 75; +use Test::More tests => 103; use Time::HiRes qw/sleep/; use X11::GUITest qw/:ALL/; @@ -12,6 +12,8 @@ my $win; my ($width, $height); my $pwd = getcwd(); +$ENV{HOME} = 'test'; + sub waitfor(&) { my ($sub) = @_; my $out; @@ -185,6 +187,108 @@ sleep(0.8); test_win_title($win, 'feh [2 of 3] - test/ok/gif'); feh_stop(); +$win = feh_start( + '--action3 ";echo foo" --action7 "echo foo" ' . + '--action8 ";touch feh_test_%u_%l" --action9 "rm feh_test_%u_%l"', + 'test/ok/png test/ok/gif test/ok/jpg' +); +test_win_title($win, 'feh [1 of 3] - test/ok/png'); +SendKeys('3'); +test_win_title($win, 'feh [1 of 3] - test/ok/png'); +SendKeys('7'); +test_win_title($win, 'feh [2 of 3] - test/ok/gif'); +SendKeys('8'); +test_win_title($win, 'feh [2 of 3] - test/ok/gif'); +ok(-e 'feh_test_2_3', 'feh action created file with correct format specifiers'); +SendKeys('9'); +ok(waitfor { not -e 'feh_test_2_3' }, 'feh action removed file'); +test_win_title($win, 'feh [3 of 3] - test/ok/jpg'); +feh_stop(); + + +# .config/feh/keys +# Action Unbinding + non-conflicting none/shift/control/meta modifiers + +$ENV{XDG_CONFIG_HOME} = 'test/config/keys'; + +$win = feh_start( + '--action1 "touch a1" --action2 "touch a2" ' . + '--action3 "touch a3" --action4 "touch a4" ' . + '--action5 "touch a5" --action6 "touch a6" ', + 'test/ok/png test/ok/jpg test/ok/pnm' +); +test_win_title($win, 'feh [1 of 3] - test/ok/png'); +SendKeys('6'); +test_win_title($win, 'feh [1 of 3] - test/ok/png'); +SendKeys('{RIG}'); +test_win_title($win, 'feh [1 of 3] - test/ok/png'); +SendKeys('a'); +test_win_title($win, 'feh [2 of 3] - test/ok/jpg'); +SendKeys('b'); +test_win_title($win, 'feh [3 of 3] - test/ok/pnm'); +SendKeys('c'); +test_win_title($win, 'feh [1 of 3] - test/ok/png'); +SendKeys('d'); +test_win_title($win, 'feh [3 of 3] - test/ok/pnm'); +SendKeys('e'); +test_win_title($win, 'feh [2 of 3] - test/ok/jpg'); +SendKeys('f'); +test_win_title($win, 'feh [1 of 3] - test/ok/png'); +SendKeys('1'); +test_win_title($win, 'feh [1 of 3] - test/ok/png'); +SendKeys('x'); +ok(waitfor { -e 'a1' }, 'action 1 = X ok'); +SendKeys('X'); +ok(waitfor { -e 'a2' }, 'action 2 = Shift+X ok'); +SendKeys('^(x)'); +ok(waitfor { -e 'a3' }, 'action 3 = Ctrl+X ok'); +SendKeys('^(X)'); +ok(waitfor { -e 'a4' }, 'action 4 = Ctrl+Shift+X ok'); +SendKeys('%(x)'); +ok(waitfor { -e 'a5' }, 'action 5 = Alt+X ok'); +for my $f (qw(a1 a2 a3 a4 a5)) { + unlink($f); +} +feh_stop(); + +$ENV{XDG_CONFIG_HOME} = 'test/config/themes'; + +$win = feh_start( + '-Ttest_general', + 'test/ok/png test/ok/jpg' +); +SendKeys('1'); +ok(waitfor { -e 'a1' }, 'theme: action 1 okay'); +unlink('a1'); +feh_stop(); + +$win = feh_start( + '-Ttest_general --action1 "touch c1"', + 'test/ok/png test/ok/jpg' +); +SendKeys('1'); +ok(waitfor { -e 'c1' }, 'theme: commandline overrides theme'); +unlink('c1'); +feh_stop(); + +$win = feh_start( + '-Ttest_multiline', + 'test/ok/png test/ok/jpg' +); +SendKeys('1'); +ok(waitfor { -e 'a1' }, 'multiline theme: first line ok'); +SendKeys('2'); +ok(waitfor { -e 'a2' }, 'multiline theme: second line ok'); +SendKeys('3'); +ok(waitfor { -e 'a3' }, 'multiline theme: last line ok'); +for my $f (qw(a1 a2 a3)) { + unlink($f); +} +feh_stop(); + +delete $ENV{XDG_CONFIG_HOME}; + + $win = feh_start(q{}, 'test/ok/png ' x 100); test_win_title($win, 'feh [1 of 100] - test/ok/png'); SendKeys('{PGD}'); @@ -341,3 +445,9 @@ ok(waitfor { }, 'disabled screen clip'); feh_stop(); + +# GH-35 "Custom window title crashes feh on unloadable files" +$win = feh_start('--title "feh %h"', 'test/ok/png test/fail/png test/ok/jpg'); +SendKeys('{RIG}'); +test_win_title($win, 'feh 16'); +feh_stop(); @@ -2,38 +2,33 @@ use strict; use warnings; use 5.010; -use Test::Command tests => 48; +use Test::Command tests => 59; -my $fehrc = "/tmp/.fehrc-$$"; -my $feh = "src/feh --rcfile $fehrc"; +$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 ($feh_name, $feh_version) = @ENV{'PACKAGE', 'VERSION'}; +my $feh_name = $ENV{'PACKAGE'}; # These tests are meant to run non-interactively and without X. # make sure they are capable of doing so. delete $ENV{'DISPLAY'}; -# Create empty fehrc so that feh does not create one in $HOME -# (mostly for build servers) -open(my $fh, '>', $fehrc) or die("Can't create $fehrc: $!"); -close($fh) or die("Can't close $fehrc: $!"); - my $err_no_env = <<'EOF'; -Unable to determine feh PACKAGE or VERSION. +Unable to determine feh PACKAGE. This is most likely because you ran 'prove test' or 'perl test/feh.t'. -Sinc this test uses make variables and is therefore designed to be run from +Since this test uses make variables and is therefore designed to be run from the Makefile only, use 'make test' instead. If you absolutely need to run it the other way, use - PACKAGE=feh VERSION=1.5 ${your_command} -(with the appropiate values, of course). + PACKAGE=feh ${your_command} EOF -if (length($feh_name) == 0 or length($feh_version) == 0) { +if (length($feh_name) == 0) { die($err_no_env); } @@ -43,20 +38,9 @@ my $re_loadable = qr{test/ok/...}; my $re_unloadable = qr{test/fail/...}; my $re_list_action = qr{test/ok/... 16x16 \(${feh_name}\)}; -my $cmd = Test::Command->new(cmd => $feh); - -# Insufficient Arguments -> Usage should return failure -$cmd->exit_is_num(1, 'missing arguments return 1'); -$cmd->stdout_is_eq('', 'missing arguments print usage (!stdout)'); -$cmd->stderr_is_eq(<<"EOF", 'missing arguments print usage (stderr)'); -${feh_name} - No loadable images specified. -Use ${feh_name} --help for detailed usage information -EOF - -$cmd = Test::Command->new(cmd => "$feh --version"); +my $cmd = Test::Command->new(cmd => "$feh --version"); $cmd->exit_is_num(0); -$cmd->stdout_is_eq("${feh_name} version ${feh_version}\n"); $cmd->stderr_is_eq(''); $cmd = Test::Command->new(cmd => "$feh --loadable $images"); @@ -65,6 +49,38 @@ $cmd->exit_is_num(0); $cmd->stdout_like($re_loadable); $cmd->stderr_is_eq(''); +$cmd = Test::Command->new( + cmd => "$feh --loadable --action 'echo touch %f' $images" +); + +$cmd->exit_is_num(0); +$cmd->stdout_is_file('test/nx_action/loadable_action'); +$cmd->stderr_is_eq(''); + +$cmd = Test::Command->new( + cmd => "$feh --loadable --action ';echo touch %f' $images" +); + +$cmd->exit_is_num(0); +$cmd->stdout_is_file('test/nx_action/loadable_naction'); +$cmd->stderr_is_eq(''); + +$cmd = Test::Command->new( + cmd => "$feh --unloadable --action 'echo rm %f' $images" +); + +$cmd->exit_is_num(0); +$cmd->stdout_is_file('test/nx_action/unloadable_action'); +$cmd->stderr_is_eq(''); + +$cmd = Test::Command->new( + cmd => "$feh --unloadable --action ';echo rm %f' $images" +); + +$cmd->exit_is_num(0); +$cmd->stdout_is_file('test/nx_action/unloadable_naction'); +$cmd->stderr_is_eq(''); + $cmd = Test::Command->new(cmd => "$feh --unloadable $images"); $cmd->exit_is_num(0); @@ -91,6 +107,14 @@ $cmd->exit_is_num(0); $cmd->stdout_is_file('test/list/format_reverse'); $cmd->stderr_like($re_warning); +$cmd = Test::Command->new( + cmd => "$feh --list --recursive --sort filename test/ok" +); + +$cmd->exit_is_num(0); +$cmd->stdout_is_file('test/list/filename_recursive'); +$cmd->stderr_is_eq(''); + $cmd = Test::Command->new(cmd => "$feh --customlist '%f; %h; %l; %m; %n; %p; " . "%s; %t; %u; %w' $images"); @@ -109,5 +133,3 @@ $cmd = Test::Command->new(cmd => $cmd->exit_is_num(0); $cmd->stdout_is_file('test/list/default'); $cmd->stderr_like($re_list_action); - -unlink($fehrc); diff --git a/test/list/filename_recursive b/test/list/filename_recursive new file mode 100644 index 0000000..5ffa63e --- /dev/null +++ b/test/list/filename_recursive @@ -0,0 +1,6 @@ +NUM FORMAT WIDTH HEIGHT PIXELS SIZE(bytes) ALPHA FILENAME +1 gif 16 16 256 953 - test/ok/gif +2 jpeg 16 16 256 354 - test/ok/jpg +3 png 16 16 256 403 X test/ok/png +4 pnm 16 16 256 269 - test/ok/pnm +5 png 16 16 256 403 X test/ok/recursive/png diff --git a/test/nx_action/loadable_action b/test/nx_action/loadable_action new file mode 100644 index 0000000..d173261 --- /dev/null +++ b/test/nx_action/loadable_action @@ -0,0 +1,8 @@ +touch test/ok/gif +touch test/ok/jpg +touch test/ok/png +touch test/ok/pnm +test/ok/gif +test/ok/jpg +test/ok/png +test/ok/pnm diff --git a/test/nx_action/loadable_naction b/test/nx_action/loadable_naction new file mode 100644 index 0000000..d173261 --- /dev/null +++ b/test/nx_action/loadable_naction @@ -0,0 +1,8 @@ +touch test/ok/gif +touch test/ok/jpg +touch test/ok/png +touch test/ok/pnm +test/ok/gif +test/ok/jpg +test/ok/png +test/ok/pnm diff --git a/test/nx_action/unloadable_action b/test/nx_action/unloadable_action new file mode 100644 index 0000000..c16572e --- /dev/null +++ b/test/nx_action/unloadable_action @@ -0,0 +1,8 @@ +rm test/fail/gif +rm test/fail/jpg +rm test/fail/png +rm test/fail/pnm +test/fail/gif +test/fail/jpg +test/fail/png +test/fail/pnm diff --git a/test/nx_action/unloadable_naction b/test/nx_action/unloadable_naction new file mode 100644 index 0000000..c16572e --- /dev/null +++ b/test/nx_action/unloadable_naction @@ -0,0 +1,8 @@ +rm test/fail/gif +rm test/fail/jpg +rm test/fail/png +rm test/fail/pnm +test/fail/gif +test/fail/jpg +test/fail/png +test/fail/pnm diff --git a/test/ok/recursive/png b/test/ok/recursive/png Binary files differnew file mode 100644 index 0000000..2f06506 --- /dev/null +++ b/test/ok/recursive/png diff --git a/test/scr/caption_done b/test/scr/caption_done Binary files differindex d178e7e..d873599 100644 --- a/test/scr/caption_done +++ b/test/scr/caption_done diff --git a/test/scr/caption_new b/test/scr/caption_new Binary files differindex fc438fd..54d48ac 100644 --- a/test/scr/caption_new +++ b/test/scr/caption_new diff --git a/test/scr/caption_while b/test/scr/caption_while Binary files differindex e9db559..313565a 100644 --- a/test/scr/caption_while +++ b/test/scr/caption_while diff --git a/test/scr/draw_action b/test/scr/draw_action Binary files differindex 4a2b06c..3c49ba1 100644 --- a/test/scr/draw_action +++ b/test/scr/draw_action diff --git a/test/scr/draw_all_multi b/test/scr/draw_all_multi Binary files differindex d105fbe..0153eb7 100644 --- a/test/scr/draw_all_multi +++ b/test/scr/draw_all_multi diff --git a/test/scr/draw_all_one b/test/scr/draw_all_one Binary files differindex 7a3b796..f33566c 100644 --- a/test/scr/draw_all_one +++ b/test/scr/draw_all_one diff --git a/test/scr/draw_filename b/test/scr/draw_filename Binary files differindex dc32356..eea7dab 100644 --- a/test/scr/draw_filename +++ b/test/scr/draw_filename diff --git a/test/scr/draw_filename_action b/test/scr/draw_filename_action Binary files differindex 6039def..73f9afd 100644 --- a/test/scr/draw_filename_action +++ b/test/scr/draw_filename_action diff --git a/test/scr/feh_lhi_iir b/test/scr/feh_lhi_iir Binary files differindex 396ee99..81748a3 100644 --- a/test/scr/feh_lhi_iir +++ b/test/scr/feh_lhi_iir diff --git a/test/scr/feh_lhi_iirr b/test/scr/feh_lhi_iirr Binary files differindex 81748a3..7a8079b 100644 --- a/test/scr/feh_lhi_iirr +++ b/test/scr/feh_lhi_iirr diff --git a/test/scr/feh_lhi_iirri b/test/scr/feh_lhi_iirri Binary files differindex 43b8fa1..31af36f 100644 --- a/test/scr/feh_lhi_iirri +++ b/test/scr/feh_lhi_iirri diff --git a/test/scr/feh_lhi_iirrio b/test/scr/feh_lhi_iirrio Binary files differindex c9e287b..3a5bdec 100644 --- a/test/scr/feh_lhi_iirrio +++ b/test/scr/feh_lhi_iirrio diff --git a/test/scr/feh_lhi_o b/test/scr/feh_lhi_o Binary files differindex ec48c01..72e79a0 100644 --- a/test/scr/feh_lhi_o +++ b/test/scr/feh_lhi_o diff --git a/test/scr/feh_lhi_oo b/test/scr/feh_lhi_oo Binary files differindex 784d7d7..c1806ff 100644 --- a/test/scr/feh_lhi_oo +++ b/test/scr/feh_lhi_oo diff --git a/test/scr/feh_lhi_ooo b/test/scr/feh_lhi_ooo Binary files differindex ad14384..1a6fbf1 100644 --- a/test/scr/feh_lhi_ooo +++ b/test/scr/feh_lhi_ooo diff --git a/test/scr/feh_lwi_scroll_r b/test/scr/feh_lwi_scroll_r Binary files differindex 5003a88..455a2c2 100644 --- a/test/scr/feh_lwi_scroll_r +++ b/test/scr/feh_lwi_scroll_r diff --git a/test/scr/feh_lwi_scroll_rd b/test/scr/feh_lwi_scroll_rd Binary files differindex 333b9e3..4ed9fec 100644 --- a/test/scr/feh_lwi_scroll_rd +++ b/test/scr/feh_lwi_scroll_rd diff --git a/test/scr/feh_lwi_scroll_rdr b/test/scr/feh_lwi_scroll_rdr Binary files differindex 1e921f1..b33270c 100644 --- a/test/scr/feh_lwi_scroll_rdr +++ b/test/scr/feh_lwi_scroll_rdr diff --git a/test/scr/feh_lwi_scroll_rdru b/test/scr/feh_lwi_scroll_rdru Binary files differindex 455a2c2..c854160 100644 --- a/test/scr/feh_lwi_scroll_rdru +++ b/test/scr/feh_lwi_scroll_rdru diff --git a/test/scr/feh_lwi_scroll_rdrul b/test/scr/feh_lwi_scroll_rdrul Binary files differindex 5003a88..455a2c2 100644 --- a/test/scr/feh_lwi_scroll_rdrul +++ b/test/scr/feh_lwi_scroll_rdrul diff --git a/test/scr/thumbnail_default b/test/scr/thumbnail_default Binary files differindex 2c52059..eade08b 100644 --- a/test/scr/thumbnail_default +++ b/test/scr/thumbnail_default diff --git a/test/status b/test/status new file mode 100644 index 0000000..81cf852 --- /dev/null +++ b/test/status @@ -0,0 +1,419 @@ +Overall test status, what's covered / missing + +# Features + +# Options + +--action +--action1 +--action2 +--action3 +--action4 +--action5 +--action6 +--action7 +--action8 +--action9 + + [x] correct command execution + [x] hold-action flag + [x] supports format specifiers + [x] with --list + [x] with --loadable + [x] with --unloadable + +--alpha +--auto-zoom + + [ ] zooms to fullscreen + [ ] with --stretch + [ ] with --ignore-aspect + + +--bg +--bg-center + + [x] sets centered wallpaper + + +--bg-fill + + [x] Sets wallpaper zoomed to fill + + +--bg-max + + [x] Sets wallpaper zoomed to max + + +--bg-scale + + [x] sets scaled wallpaper, ignoring aspect ratio + + +--bg-tile + + [x] sets tiled wallpaper + + +--blur-button +--borderless + + [ ] create borderless window (need test WM with borders first...) + + +--builtin + + [ ] View via builtin HTTP client + [ ] View via wget + + +--cache-thumbnails + + [ ] ./thumbnails/normal + [ ] .thumbnails/large + + +--caption-path + + [x] loads/saves captions + [x] autocreates caption dir + [x] caption newline support + [x] correct caption display + + +--collage + +--customlist + + [x] correct output + [x] format specifiers + + +--cycle-once + + [x] closes feh window at end of slideshow + [x] combination with --slideshow-delay + + +--draw-actions + + [x] lists correct actions + [x] Alignment with/without --draw-filename + + +--draw-filename + + [x] shows filename + [ ] shows filename and position in fullscreen + + +--filelist + + [x] saves filelist + [x] loads filelist + + +--font + + [ ] Sets different font + + +--fontpath + + [ ] Adds font path + + +--fullindex + + [ ] Shows correct image size + [ ] Shows correct image dimensions + [ ] With --cache-thumbnails + + +--fullscreen + + [x] uses full screen size + + +--geometry + + [x] correct window dimensions + + +--help + + [ ] Displays help + + +--hide-pointer + + [ ] Hides pointer visibility + + +--ignore-aspect +--image-bg + + [x] black + [x] white + [x] default + + +--index +--index-dim +--index-name +--index-size + +--info + + [x] executes commands + [x] correct output + [ ] format specifiers + + +--keep-http + + [ ] keeps local file copies + + +--limit-height + + [x] sets correct thumbnail window height + + +--limit-width + + [x] sets correct thumbnail window width + + +--list + + [x] correct output + + +--loadable + + [x] lists loadable images + + +--menu-bg + + to be deprecated + + +--menu-button +--menu-ctrl-mask +--menu-font + + [ ] changes menu font + + +--montage +--multiwindow + + [x] opens one window per image + + +--next-button +--no-blur-ctrl-mask +--no-jump-on-resort +--no-menus + + [ ] disables menu + + +--no-rotate-ctrl-mask +--no-screen-clip + + [x] creates huge window + + +--no-xinerama + + [ ] disables xinerama support + + +--output +--output-dir + + to be deprecated + + +--output-only +--pan-button +--preload + + [ ] weeds out unloadable images + + +--prev-button +--quiet + + [x] quiet output + + +--randomize + + [ ] random filelist order + + +--recursive + + [x] recurses into subdirectories + + +--reload + + [ ] automatically reloads image + + +--reload-button +--reverse + + [x] reverse sort order + + +--rotate-button +--scale-down + + [x] correct window size + [x] correct zoom level + [ ] correct zoom behaviour + + +--slideshow-delay + + [x] positive delay -> automatic window change + [x] negative delay -> starts paused + + +--sort + + [x] name + [x] filename + [x] width + [x] height + [x] pixels + [x] size + [x] format + + +--start-at + + [x] starts at correct image + + +--stretch +--theme + + [x] loads correct options + [x] commandline overrides theme + [x] multiline theme specifications + + +--thumb-height + + [ ] sets correct thumbnail height + + +--thumbnails + + [x] starts thumbnail mode + [ ] shows correct thumbnail dimensions (GH-29) + + +--thumb-redraw +--thumb-title + + [ ] sets title for windows opened from thumbnail mode + + +--thumb-width + + [ ] sets correct thumbnail width + + +--title + + [x] Sets correct window title + [x] Supports format specifiers + + +--title-font +--unloadable + + [x] lists unloadable images + + +--verbose + + [ ] outputs progress bars etc. + + +--version + + [x] correct output + + +--zoom + + [ ] percent + [ ] max + [ ] fill + + +--zoom-button + +# Keys + +action_0 +action_1 +action_2 +action_3 +action_4 +action_5 +action_6 +action_7 +action_8 +action_9 +[x] close +delete +[x] jump_back +[x] jump_first +[x] jump_fwd +[x] jump_last +jump_random +menu_child +menu_close +menu_down +menu_parent +menu_select +menu_up +[x] next_img +orient_1 +orient_3 +[x] prev_img +[x] quit +reload_image +reload_minus +reload_plus +[x] remove +render +save_filelist +save_image +[x] scroll_down +[x] scroll_left +[x] scroll_right +[x] scroll_up +[x] size_to_image +[x] toggle_actions +[x] toggle_caption +[x] toggle_filenames +toggle_fullscreen +toggle_menu +[x] toggle_pause +toggle_pointer +zoom_default +zoom_fit +[x] zoom_in +[x] zoom_out |