summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/c.yml6
-rw-r--r--.mailmap4
-rw-r--r--AUTHORS2
-rw-r--r--COPYING2
-rw-r--r--ChangeLog353
-rw-r--r--Makefile10
-rw-r--r--README.md121
-rw-r--r--config.mk16
-rw-r--r--examples/buttons2
-rw-r--r--examples/keys2
-rw-r--r--man/Makefile1
-rw-r--r--man/feh.pre189
-rwxr-xr-xscripts/checkkeys.pl2
-rwxr-xr-xscripts/checkopts.pl2
-rw-r--r--share/applications/feh.pre2
-rw-r--r--src/Makefile2
-rw-r--r--src/debug.h2
-rw-r--r--src/events.c35
-rw-r--r--src/exif.c577
-rw-r--r--src/exif.h17
-rw-r--r--src/exif_canon.c30
-rw-r--r--src/exif_canon.h3
-rw-r--r--src/exif_cfg.h85
-rw-r--r--src/exif_nikon.c796
-rw-r--r--src/exif_nikon.h3
-rw-r--r--src/feh.h20
-rw-r--r--src/feh_png.c5
-rw-r--r--src/filelist.c60
-rw-r--r--src/filelist.h3
-rw-r--r--src/getopt.c949
-rw-r--r--src/getopt.h130
-rw-r--r--src/getopt1.c173
-rw-r--r--src/gib_hash.c4
-rw-r--r--src/gib_hash.h2
-rw-r--r--src/gib_imlib.c5
-rw-r--r--src/gib_imlib.h2
-rw-r--r--src/gib_list.c2
-rw-r--r--src/help.raw7
-rw-r--r--src/imlib.c318
-rw-r--r--src/index.c6
-rw-r--r--src/index.h2
-rw-r--r--src/keyevents.c16
-rw-r--r--src/list.c2
-rw-r--r--src/main.c59
-rw-r--r--src/menu.c20
-rw-r--r--src/menu.h2
-rw-r--r--src/options.c445
-rw-r--r--src/options.h111
-rw-r--r--src/signals.c26
-rw-r--r--src/signals.h5
-rw-r--r--src/slideshow.c29
-rw-r--r--src/structs.h2
-rw-r--r--src/strverscmp.c6
-rw-r--r--src/thumbnail.c15
-rw-r--r--src/thumbnail.h6
-rw-r--r--src/timers.c2
-rw-r--r--src/utils.c2
-rw-r--r--src/wallpaper.c194
-rw-r--r--src/wallpaper.h5
-rw-r--r--src/winwidget.c61
-rw-r--r--src/winwidget.h2
-rw-r--r--test/feh.t11
-rw-r--r--test/tiny.pbm4
63 files changed, 2251 insertions, 2726 deletions
diff --git a/.github/workflows/c.yml b/.github/workflows/c.yml
index e7a4207..5477164 100644
--- a/.github/workflows/c.yml
+++ b/.github/workflows/c.yml
@@ -27,12 +27,12 @@ jobs:
run: sudo apt-get -y install build-essential libx11-dev libxt-dev libimlib2-dev libtest-command-perl libtest-simple-perl
- name: Install libcurl
if: matrix.curl
- run: sudo apt-get -y install libcurl4-openssl-dev
+ run: sudo apt-get -y install libcurl4-openssl-dev
- name: Install libexif
if: matrix.exif
- run: sudo apt-get -y install libexif-dev
+ run: sudo apt-get -y install libexif-dev
- name: Install Xinerama
if: matrix.xinerama
- run: sudo apt-get -y install libxinerama-dev
+ run: sudo apt-get -y install libxinerama-dev
- name: Build and Test
run: for inotify in 0 1; do for verscmp in 0 1; do make curl=${{ matrix.curl }} exif=${{ matrix.exif }} inotify=$inotify verscmp=$verscmp xinerama=${{ matrix.xinerama }} && make test && make clean; done; done
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 0000000..888b47c
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,4 @@
+Birte Kristina Friesel <derf@finalrewind.org>
+Birte Kristina Friesel <derf@chaosdorf.de>
+Birte Kristina Friesel <ghub@derf.homelinux.org>
+Birte Kristina Friesel <derf@derf.homelinux.org>
diff --git a/AUTHORS b/AUTHORS
index ede7d47..ad85f15 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -50,7 +50,7 @@ Yu-Jie Lin
Dennis Real
- patch for builtin exif support (exif=1)
-Daniel Friesel - derf (at) finalrewind (dot) org
+Birte Kristina Friesel - derf (at) finalrewind (dot) org
- Maintenance since 2010
Thanks to:
diff --git a/COPYING b/COPYING
index bac6a11..dc7abbd 100644
--- a/COPYING
+++ b/COPYING
@@ -1,5 +1,5 @@
Copyright (C) 1999,2000 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2023 Birte Kristina 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/ChangeLog b/ChangeLog
index c8caec4..a8f84c9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,128 @@
-Sat, 29 Aug 2020 08:49:08 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Mon, 04 Dec 2023 21:25:49 +0100 Birte Friesel <derf+feh@finalrewind.org>
+
+* Release v3.10.2
+ * Fix crash in right-click / menu rendering code on some distributions
+ (patch by Ametov Imil)
+
+Mon, 02 Oct 2023 04:27:56 +0200 Birte Friesel <derf+feh@finalrewind.org>
+
+* Release v3.10.1
+ * Do not call signal-unsafe functions within signal handlers
+
+Thu, 06 Apr 2023 16:19:16 +0200 Birte Friesel <derf+feh@finalrewind.org>
+
+* Release v3.10
+ * Add --sort=none option to un-set sort modes specified earlier
+ * Improve error messages for Imlib2 ≥ 1.8
+ * Fix build with clang 16. (Patch by orbea)
+ * Fix tests when building with magic=1
+
+Mon, 22 Aug 2022 17:49:11 +0200 Birte Friesel <derf+feh@finalrewind.org>
+
+* Release v3.9.1
+ * Set libcurl user agent to "feh/3.9.1". Previously, feh did not send a
+ user agent.
+
+Sun, 12 Jun 2022 13:12:00 +0200 Birte Friesel <derf+feh@finalrewind.org>
+
+* Release v3.9
+ * Fix compilation on macOS by defining _DARWIN_C_SOURCE for
+ mkdtemp and mkstemps. (Patch by Ryan Schmidt)
+ * Remove magic byte check before passing an image to Imlib2.
+ This check was introduced in feh 3.6 to work around an issue with
+ Imlib2 being slow to determine image loadability in some cases
+ <https://phab.enlightenment.org/T8739>. By now, an Imlib2 version without
+ this issue should be available in all recent distributions, so the check
+ in feh is no longer required. For a slight speed-up, or to use feh with
+ an affected Imlib2 version (1.6.x or 1.7.0), compile feh with 'magic=1'.
+ In this case, feh will use libmagic to determine whether a file is an
+ image, and only pass images to Imlib2. (Patch by Christian Hesse)
+ * Fix crash (segmentation fault due to null pointer dereference) when
+ toggling fullscreen mode while moving the cursor.
+ * Note that feh no longer supplies its own getopt_long function.
+ getopt_long is provided by a wide range of libc implementations, so
+ there is no need for feh to duplicate it. (Patch by Guilherme Janczak)
+
+Mon, 03 Jan 2022 11:29:03 +0100 Birte Friesel <derf+feh@finalrewind.org>
+
+* Release v3.8
+ * Add button ID "0" to cursor bindings. This pseudo-button is triggered
+ whenever feh observes a cursor movement. It does not have a default
+ binding.
+ * Support hexadecimal IDs in --window-id
+ * Disable --auto-rotate in feh builds compiled with Imlib2 1.7.5 or later.
+ Imlib2 1.7.5 introduces transparent EXIF-based image orientation
+ adjustment, so --auto-rotate is no longer needed (and would cause
+ mis-orientation of images, as Imlib2 has already adjusted the
+ orientation).
+
+Sat, 25 Sep 2021 09:21:25 +0200 Birte Friesel <derf+feh@finalrewind.org>
+
+* Release v3.7.2
+ * Fix crash when running feh without stdin file descriptor
+
+Sat, 24 Jul 2021 22:30:12 +0200 Birte Friesel <derf+feh@finalrewind.org>
+
+* Release v3.7.1
+ * Support JPEG XL files when using imlib2-jxl (patch by Alistair)
+ * Fix support for images smaller than 16 bytes (patch by David Buchanan)
+ * Fix some out of bounds reads (patches by Tobias Stoeckmann)
+
+Sun, 09 May 2021 11:31:55 +0200 Birte Friesel <derf+feh@finalrewind.org>
+
+* Release v3.7
+ * Use compact representation instead of key-value pairs for common EXIF data
+ (only applies when compiling feh with exif=1)
+ * Add --window-id <windowid> option (draw to an existing window)
+ * Add --zoom-step <percent> option (specify zoom step size)
+ * Pass gopher:// and gophers:// URLs to libcurl
+ * Fix --reload / --auto-reload reloading the wrong directory when
+ using --start-at and no file arguments or filelists have been
+ specified
+ * Fix Ctrl+key causing unintended behaviour when controlling feh via stdin
+ * Fix high CPU usage when closing stdin after starting feh from a terminal
+
+Mon, 25 Jan 2021 17:46:57 +0100 Birte Friesel <derf+feh@finalrewind.org>
+
+* Release v3.6.3
+ * Fix --start-at not handling URL-encoded file:/// paths properly. Notably,
+ this also fixes feh not displaying images with spaces or unicode
+ elements in their path when opened from a file manager.
+
+Sat, 09 Jan 2021 12:28:06 +0100 Birte Friesel <derf+feh@finalrewind.org>
+
+* Release v3.6.2
+ * Fix save_filelist not respecting --output-dir
+ * Fix file descriptor leak when attempting to load truncated image files.
+ The issue was introduced in v3.6.
+
+Sun, 06 Dec 2020 08:34:15 +0100 Birte Friesel <derf+feh@finalrewind.org>
+
+* Release v3.6.1
+ * Fix excessive memory consumption when showing long-running slideshows
+ with thousands to tens of thousands of images and feh has been compiled
+ with exif=1 (see https://github.com/derf/feh/issues/553)
+ * Fix memory leak when showing long-running slideshows with relatively few
+ images and feh has been compiled with exif=1 (ibid.)
+ * Fix memory leak when reloading an image and feh has been compiled with
+ exif=1
+ * Fix memory leak in --draw-exif
+ * Fix memory leak when reloading HTTP files with --no-conversion-cache
+
+Mon, 30 Nov 2020 19:44:47 +0100 Birte Friesel <derf+feh@finalrewind.org>
+
+* Release v3.6
+ * Add flip and rotate options to the menu
+ * Improve unloadable image detection time (e.g. for large video files) by
+ checking a file's header before passing it to Imlib2. For rarely used
+ image formats, there is a very small chance that an image which could be
+ loaded by feh 3.5 is reported as unloadable by feh 3.6 due to this
+ change. Set FEH_SKIP_MAGIC=1 to bypass the header check in this case. See
+ <https://phab.enlightenment.org/T8739> and
+ <https://github.com/derf/feh/issues/505> for details.
+
+
+Sat, 29 Aug 2020 08:49:08 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v3.5
* Enable --version-sort on systems without strverscmp support. This
@@ -8,13 +132,13 @@ Sat, 29 Aug 2020 08:49:08 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* Add %a format specifier (slideshow state: "playing" / "paused")
* Fix crashes when combining --reload and --multiwindow
-Fri, 29 May 2020 23:52:35 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Fri, 29 May 2020 23:52:35 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v3.4.1
* Fix lossless rotate not being lossless when using feh with Imlib2 v1.6
or later
-Sat, 11 Apr 2020 09:51:01 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Sat, 11 Apr 2020 09:51:01 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v3.4
* Images loaded via HTTPS/curl, ImageMagick, and dcraw are now cached
@@ -32,7 +156,7 @@ Sat, 11 Apr 2020 09:51:01 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* Fix a memory leak when repeatedly cycling through slideshows containing
images loaded via libcurl, ImageMagick or dcraw.
-Tue, 03 Dec 2019 17:27:46 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Tue, 03 Dec 2019 17:27:46 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v3.3
* New option --class allows setting the X11 class hint per feh instance
@@ -40,7 +164,7 @@ Tue, 03 Dec 2019 17:27:46 +0100 Daniel Friesel <derf+feh@finalrewind.org>
* Improve handling of NULL returns from Imlib2 calls (patch by Ben Boeckel)
* Fix compilation with libcurl < v7.32
-Mon, 22 Jul 2019 20:17:03 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Mon, 22 Jul 2019 20:17:03 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v3.2.1
* Use --no-fehbg option in ~/.fehbg. This fixes cases where an X11
@@ -51,7 +175,7 @@ Mon, 22 Jul 2019 20:17:03 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* Fix TOCTTOU when setting the file mode of ~/.fehbg
(patch by Tobias Stoeckmann)
-Wed, 10 Jul 2019 17:40:29 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Wed, 10 Jul 2019 17:40:29 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v3.2
* Build feh with inotify=1 to automatically reload changed files in
@@ -60,13 +184,13 @@ Wed, 10 Jul 2019 17:40:29 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* Reload current image(s) when receiving SIGUSR1 or SIGUSR2 in single-image
slideshows or in multiwindow mode
-Sun, 17 Feb 2019 08:41:53 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Sun, 17 Feb 2019 08:41:53 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Releasev v3.1.3
* Fix missing filename in ~/.fehbg when using --no-xinerama on a feh
binary compiled with xinerama=1. This issue was introduced in v3.1.2.
-Mon, 11 Feb 2019 17:24:13 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Mon, 11 Feb 2019 17:24:13 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v3.1.2
* Fix missing filenames in ~/.fehbg when using --bg-* on directories and/or
@@ -75,7 +199,7 @@ Mon, 11 Feb 2019 17:24:13 +0100 Daniel Friesel <derf+feh@finalrewind.org>
'start paused' flag
* Fix repeated --info option not properly overriding the 'draw info' flag
-Fri, 07 Dec 2018 22:51:15 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Fri, 07 Dec 2018 22:51:15 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v3.1.1
* Decrease libcurl timeout from indefinite to 30 minutes. This should
@@ -87,7 +211,7 @@ Fri, 07 Dec 2018 22:51:15 +0100 Daniel Friesel <derf+feh@finalrewind.org>
Previously, signals were ignored during a (possibly slow) libcurl
network transfer, which was not intended behaviour.
-Wed, 21 Nov 2018 19:37:34 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Wed, 21 Nov 2018 19:37:34 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v3.1
* Running "feh --start-at .../file.jpg" without specifying images,
@@ -103,7 +227,7 @@ Wed, 21 Nov 2018 19:37:34 +0100 Daniel Friesel <derf+feh@finalrewind.org>
error in previous versions.
* Respect -j / --output-dir when using save_image or save_filelist actions.
-Fri, 09 Nov 2018 17:17:15 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Fri, 09 Nov 2018 17:17:15 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v3.0
* Remove deprecated webcam scripts (feh-cam and gen-cam-menu)
@@ -120,7 +244,7 @@ Fri, 09 Nov 2018 17:17:15 +0100 Daniel Friesel <derf+feh@finalrewind.org>
file as well as the displayed image. This was the default behaviour in
feh 1.x and 2.x
-Sat, 27 Oct 2018 19:46:48 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Sat, 27 Oct 2018 19:46:48 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.28.1
* Do not ignore quit signals (SIGTERM, SIGINT, SIGQUIT) during preload
@@ -128,7 +252,7 @@ Sat, 27 Oct 2018 19:46:48 +0200 Daniel Friesel <derf+feh@finalrewind.org>
patch by Olof-Joachim Frahm)
* Improve randomness on non-glibc systems
-Mon, 17 Sep 2018 21:17:04 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Mon, 17 Sep 2018 21:17:04 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.28
* Decrease loading time for RAW images by utilizing dcraw to display the
@@ -142,7 +266,7 @@ Mon, 17 Sep 2018 21:17:04 +0200 Daniel Friesel <derf+feh@finalrewind.org>
<https://github.com/ulteq>), quit replaces --cycle-once (which is now
deprecated), and resume is the default (continue at the first image).
-Tue, 17 Jul 2018 17:33:10 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Tue, 17 Jul 2018 17:33:10 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.27.1
* Fix feh occasionally becoming unresponsive when asked to terminate
@@ -151,7 +275,7 @@ Tue, 17 Jul 2018 17:33:10 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* Fix --keep-zoom-vp issues introduced in 2.27
(patch by <https://github.com/ulteq>)
-Thu, 28 Jun 2018 17:26:54 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Thu, 28 Jun 2018 17:26:54 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.27
* Fix size_to_image ("w") command when both --scale-down and --keep-zoom-vp
@@ -168,17 +292,17 @@ Thu, 28 Jun 2018 17:26:54 +0200 Daniel Friesel <derf+feh@finalrewind.org>
is enabled
* All patches provided by <https://github.com/ulteq>. Thanks a lot!
-Tue, 26 Jun 2018 10:33:04 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Tue, 26 Jun 2018 10:33:04 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.26.4
* Correctly save --bg-max in ~/.fehbg (patch by Sebastian Bickerle)
-Fri, 18 May 2018 22:58:02 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Fri, 18 May 2018 22:58:02 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.26.3
* Properly escape --image-bg argument in ~/.fehbg (broken in 2.26.1)
-Sat, 12 May 2018 16:33:56 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Sat, 12 May 2018 16:33:56 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.26.2
* Show correct filelist position in windows opened from thumbnail mode.
@@ -186,7 +310,7 @@ Sat, 12 May 2018 16:33:56 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* Improve support for key input from stdin
* Do not push menus off the screen when hitting screen limits
-Fri, 11 May 2018 15:11:17 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Fri, 11 May 2018 15:11:17 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.26.1
* Restore pre-2.21 ~/.fehbg behaviour. This fixes nondeterministic
@@ -196,7 +320,7 @@ Fri, 11 May 2018 15:11:17 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* Fix /tmp being cluttered with temporary ImageMagick files when using
--magick-timeout and a conversion takes longer than allowed
-Thu, 19 Apr 2018 21:43:12 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Thu, 19 Apr 2018 21:43:12 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.26
* Save absolute file paths in ~/.fehbg, similar to the behaviour prior to
@@ -204,13 +328,13 @@ Thu, 19 Apr 2018 21:43:12 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* Add %g (window dimensions) and %Z (precise zoom level) format specifiers
* Improve -z/--randomize randomness
-Wed, 07 Mar 2018 17:49:52 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Wed, 07 Mar 2018 17:49:52 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.25.1
* Fix compilation issues when using CFLAGS=-m64 on some gcc versions
* Re-render current image when toggle_fixed_geometry is input
-Sun, 04 Mar 2018 08:53:50 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Sun, 04 Mar 2018 08:53:50 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.25
* Add --version-sort option to enable natural sorting of file and directory
@@ -225,7 +349,7 @@ Sun, 04 Mar 2018 08:53:50 +0100 Daniel Friesel <derf+feh@finalrewind.org>
* Fix filelists specified by -f/--filelist not being reloaded when using
--reload
-Mon, 26 Feb 2018 21:41:38 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Mon, 26 Feb 2018 21:41:38 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.24
* Improve performance when using --{max,min}-dimension in slideshow mode
@@ -234,12 +358,12 @@ Mon, 26 Feb 2018 21:41:38 +0100 Daniel Friesel <derf+feh@finalrewind.org>
(introduced in feh 2.23.1)
-Mon, 12 Feb 2018 22:11:55 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Mon, 12 Feb 2018 22:11:55 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.23.2
* Fix support for nested quotes in .confeg/feh/themes
-Wed, 31 Jan 2018 17:38:25 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Wed, 31 Jan 2018 17:38:25 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.23.1
* The Makefile no longer honors CPPFLAGS and instead consistently uses
@@ -248,7 +372,7 @@ Wed, 31 Jan 2018 17:38:25 +0100 Daniel Friesel <derf+feh@finalrewind.org>
* Minor performance improvements (patches by ulteq)
* Stability improvements when using --magick-timeout (patch by ulteq)
-Thu, 28 Dec 2017 19:26:29 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Thu, 28 Dec 2017 19:26:29 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.23
* Fix broken thumbnail/index windows when using --scale-down
@@ -256,18 +380,18 @@ Thu, 28 Dec 2017 19:26:29 +0100 Daniel Friesel <derf+feh@finalrewind.org>
for significant performance improvements especially in small slideshows
* Add --cache-size option to set Imlib2 image cache size
-Tue, 07 Nov 2017 17:36:26 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Tue, 07 Nov 2017 17:36:26 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.22.2
* Fix HTTPS certificate errors on some systems (broken in 2.22)
-Tue, 07 Nov 2017 07:51:48 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Tue, 07 Nov 2017 07:51:48 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.22.1
* Allow ~/.fehbg to be sourced (instead of executed) from other shell
scripts again (broken in 2.22)
-Sat, 04 Nov 2017 14:55:38 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Sat, 04 Nov 2017 14:55:38 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.22
* Add support for CURL_CA_BUNDLE environment variable when loading images
@@ -275,7 +399,7 @@ Sat, 04 Nov 2017 14:55:38 +0100 Daniel Friesel <derf+feh@finalrewind.org>
* Fix ~/.fehbg not being updated when setting a wallpaper via menu
(broken in 2.21)
-Sat, 07 Oct 2017 12:14:17 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Sat, 07 Oct 2017 12:14:17 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.21
* Add toggle_fixed_geometry ('g') key binding to toggle window auto-resize
@@ -284,7 +408,7 @@ Sat, 07 Oct 2017 12:14:17 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* Fix --force-aliasing (and possibly other options) missing from ~/.fehbg
when using them for background setting
-Thu, 07 Sep 2017 20:20:11 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Thu, 07 Sep 2017 20:20:11 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.20
* Fix clang/gcc warnings (Patches by orbea)
@@ -297,27 +421,27 @@ Thu, 07 Sep 2017 20:20:11 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* Remove images from the filelist if they were removed by executing a
user-defined action <https://github.com/derf/feh/issues/322>
-Mon, 21 Aug 2017 19:04:00 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Mon, 21 Aug 2017 19:04:00 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.19.3
* Save geometry data in .fehbg when setting a wallpaper with --geometry
* Fix Imlib2 developer warning and improve out-of-memory error message
when using --thumbnails / --index on large directories
-Sat, 12 Aug 2017 05:05:24 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Sat, 12 Aug 2017 05:05:24 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.19.2
* Show ImageMagick loader errors unless --quiet is specified
* Fix crash when handling certain media keys (introduced in 2.19.1)
-Tue, 25 Jul 2017 18:40:33 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Tue, 25 Jul 2017 18:40:33 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.19.1
* Fix Shift modifier not being recognized for tab, space and similar keys.
This lead to keybindings like Shift+Tab or Shift+Space being parsed as if
the Shift modifier had not been specified
-Tue, 06 Jun 2017 20:40:00 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Tue, 06 Jun 2017 20:40:00 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.19
* Follow the freedesktop.org Thumbnail Managing Standard by saving
@@ -327,7 +451,7 @@ Tue, 06 Jun 2017 20:40:00 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* Install app icons with the correct permissions of 644
* Documentation improvements
-Tue, 04 Apr 2017 21:22:16 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Tue, 04 Apr 2017 21:22:16 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.18.3
* Fix double-free/OOB-write in E17 IPC. This only affects the
@@ -344,19 +468,19 @@ Tue, 04 Apr 2017 21:22:16 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* Fix memory leak when saving a filelist or image whose target filename
already exists. (patch by Tobias Stoeckmann)
-Thu, 16 Feb 2017 23:05:39 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Thu, 16 Feb 2017 23:05:39 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.18.2
* Fix crash when using both --thumbnails and --title. This bug was
introduced in v2.18.1.
-Sun, 22 Jan 2017 19:11:32 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Sun, 22 Jan 2017 19:11:32 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.18.1
* Fix image-specific format specifiers not being updated correctly
(e.g. %z not displaying the correct zoom value after zooming in / out)
-Tue, 01 Nov 2016 10:55:04 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Tue, 01 Nov 2016 10:55:04 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.18
* Move README to README.md
@@ -365,13 +489,13 @@ Tue, 01 Nov 2016 10:55:04 +0100 Daniel Friesel <derf+feh@finalrewind.org>
* Only for builds with exif=1: Disable EXIF-based auto rotation by
default, add --auto-rotate option to enable it (Patch by Elliot Wolk)
-Wed, 31 Aug 2016 20:27:20 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Wed, 31 Aug 2016 20:27:20 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.17.1
* Fix compilation on systems where HOST_NAME_MAX is not defined, such as
FreeBSD (patch by Niclas Zeising)
-Sun, 28 Aug 2016 21:26:54 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Sun, 28 Aug 2016 21:26:54 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.17
* Install feh icon (both 48x48 and scalable SVG) to /usr/share/icons
@@ -387,20 +511,20 @@ Sun, 28 Aug 2016 21:26:54 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* feh now also sets the X11 _NET_WM_PID and WM_CLIENT_MACHINE window
properties
-Sun, 31 Jul 2016 16:59:07 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Sun, 31 Jul 2016 16:59:07 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.16.2
* Also support in-place editing for images loaded via libcurl or
imagemagick. Results will not be written back to disk in this case.
-Fri, 24 Jun 2016 00:31:56 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Fri, 24 Jun 2016 00:31:56 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.16.1
* Fix crash when trying to rotate a JPEG image without having
jpegtran / jpegexiforient installed
* Handle failing fork() calls gracefully
-Thu, 09 Jun 2016 08:59:35 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Thu, 09 Jun 2016 08:59:35 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.16
* Fix invalid key/button definitions mis-assigning keys/buttons to other
@@ -413,13 +537,13 @@ Thu, 09 Jun 2016 08:59:35 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* Add navigation keys next_dir (]) and prev_dir ([) to jump to the first
image of the nex/previous directory (Patch by Sung Pae)
-Fri, 27 May 2016 13:15:49 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Fri, 27 May 2016 13:15:49 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.15.4
* Fix toggle_filenames key displaying wrong file numbers in multiwindow
mode
-Thu, 28 Apr 2016 11:41:04 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Thu, 28 Apr 2016 11:41:04 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.15.3
* Rescale image when resizing a window and --scale-down or --geometry is
@@ -428,18 +552,18 @@ Thu, 28 Apr 2016 11:41:04 +0200 Daniel Friesel <derf+feh@finalrewind.org>
size which will not be updated when changing images (as was the case in
feh < 2.15). This may or may not be fixed in the future.
-Sat, 16 Apr 2016 18:32:38 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Sat, 16 Apr 2016 18:32:38 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.15.2
* Fix --keep-zoom-vp not keeping the viewport x/y offsets (broken by 2.15)
-Fri, 15 Apr 2016 10:18:37 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Fri, 15 Apr 2016 10:18:37 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.15.1
* Fix w (size_to_image) key not updating window size when --scale-down
or --geometry is active
-Sat, 09 Apr 2016 20:42:23 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Sat, 09 Apr 2016 20:42:23 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.15
* Patch by William Woodruff: Add --insecure option to disable HTTPS
@@ -458,7 +582,7 @@ Sat, 09 Apr 2016 20:42:23 +0200 Daniel Friesel <derf+feh@finalrewind.org>
start with a space. Titles starting with a space are treated as part of
of the command so that actions like '[ -L %F ] && foo' still work
-Thu, 18 Feb 2016 20:40:19 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Thu, 18 Feb 2016 20:40:19 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.14.2
* make test: Ignore results on arm and mips since they expose a bug in
@@ -471,7 +595,7 @@ Thu, 18 Feb 2016 20:40:19 +0100 Daniel Friesel <derf+feh@finalrewind.org>
* -f / --filelist: Fix bug in "-" / "/dev/stdin" handling affecting feh
running in ksh and possibly other environments
-Thu, 04 Feb 2016 20:31:38 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Thu, 04 Feb 2016 20:31:38 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.14.1
* Skip a small set of build tests on Debian and derivatives, since they
@@ -480,7 +604,7 @@ Thu, 04 Feb 2016 20:31:38 +0100 Daniel Friesel <derf+feh@finalrewind.org>
<https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=813729> for more
information
-Sun, 04 Oct 2015 10:01:20 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Sun, 04 Oct 2015 10:01:20 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.14
* Add --xinerama-index option for background setting
@@ -497,12 +621,12 @@ Sun, 04 Oct 2015 10:01:20 +0200 Daniel Friesel <derf+feh@finalrewind.org>
active xinerama screen by setting the XINERAMA_SCREEN environment
variable
-Sun, 24 May 2015 11:45:18 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Sun, 24 May 2015 11:45:18 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.13.1
* Fix --scale-down breaking image centering in fullscreen mode
-Sun, 17 May 2015 20:40:36 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Sun, 17 May 2015 20:40:36 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.13
* print --verbose output to stderr
@@ -515,14 +639,14 @@ Sun, 17 May 2015 20:40:36 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* Fix potential out of bounds array access in EXIF code
(when built with exif=1)
-Wed, 08 Apr 2015 11:18:41 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Wed, 08 Apr 2015 11:18:41 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.12.1
* Handle missing HOME in environment
* Fix memory leak when a slideshow contains many unloadable images
* Fix memory leak when --prelaod removes files from the filelist
-Thu, 15 May 2014 23:41:07 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Thu, 15 May 2014 23:41:07 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.12
* feh-cam and gen-cam-menu are no longer installed by default. Use
@@ -540,7 +664,7 @@ Thu, 15 May 2014 23:41:07 +0200 Daniel Friesel <derf+feh@finalrewind.org>
--thumb-title and --title)
* Update help (when built with help=1)
-Sun, 27 Apr 2014 20:28:02 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Sun, 27 Apr 2014 20:28:02 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.11
* Patch by Michael Vorburger: Fix erroneous free() in case of failed
@@ -556,7 +680,7 @@ Sun, 27 Apr 2014 20:28:02 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* Respect --image-bg=checks in fullscreen mode (default remains black)
(closes #156)
-Fri, 28 Feb 2014 18:20:25 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Fri, 28 Feb 2014 18:20:25 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.10
* Allow non-centered wallpapers using the --geometry option
@@ -572,7 +696,7 @@ Fri, 28 Feb 2014 18:20:25 +0100 Daniel Friesel <derf+feh@finalrewind.org>
(Patch by Brian Mattern)
* Always use absolute paths in .fehbg
-Tue, 11 Jun 2013 08:27:24 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Tue, 11 Jun 2013 08:27:24 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.9.3
* Patch by David Gowers: Add %L format code (temporary copy of filelist)
@@ -580,20 +704,20 @@ Tue, 11 Jun 2013 08:27:24 +0200 Daniel Friesel <derf+feh@finalrewind.org>
--customlist, --index-info, --info, --thumb-title, --title)
* Fix tests failing when compiled with help=1
-Fri, 03 May 2013 21:16:59 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Fri, 03 May 2013 21:16:59 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.9.2
* Fix -F --zoom 100 not working in Gnome+Unity when compiling feh with
gcc and enabled optimizations (not -O0)
* EXIF updates by Dennis Real
-Thu, 14 Feb 2013 12:52:02 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Thu, 14 Feb 2013 12:52:02 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.9.1
* Set correct window dimensions on any Xinerama screen, not just the
first one (active screen is determined by current pointer location)
-Wed, 13 Feb 2013 01:46:56 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Wed, 13 Feb 2013 01:46:56 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.9
* Add --keep-zoom-vp option to keep zoom and offsets when switching
@@ -605,7 +729,7 @@ Wed, 13 Feb 2013 01:46:56 +0100 Daniel Friesel <derf+feh@finalrewind.org>
error
* Add button bindings to zoom in / out (patch by sdaau)
-Mon, 24 Dec 2012 15:45:54 +0100 Daniel Friesel <derf+feh@finalrewind.org>
+Mon, 24 Dec 2012 15:45:54 +0100 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.8
* Do not apply --scale-down to the thumbnail window. It will be applied
@@ -626,19 +750,19 @@ Mon, 24 Dec 2012 15:45:54 +0100 Daniel Friesel <derf+feh@finalrewind.org>
* Make 'z' (jump_random) work in thumbnail mode as well, fix thumbnail
selection roll-over <https://github.com/derf/feh/issues/115>
-Tue, 16 Oct 2012 06:29:58 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Tue, 16 Oct 2012 06:29:58 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.7
* Add --min-dim and --max-dim options to only process images with certain
dimensions
-Thu, 27 Sep 2012 16:48:48 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Thu, 27 Sep 2012 16:48:48 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.6.3
* Fix segfault when doing lossless mirror/rotate and jpegexiforient is
not present <https://github.com/derf/feh/issues/100>
-Wed, 26 Sep 2012 17:06:50 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Wed, 26 Sep 2012 17:06:50 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.6.2
* Set EXIF orientation tag to 1 ("0,0 is top left" aka normal) after
@@ -648,7 +772,7 @@ Wed, 26 Sep 2012 17:06:50 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* Fix spelling in feh(1)
* Compile debug builds with -O0
-Thu, 13 Sep 2012 12:00:06 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Thu, 13 Sep 2012 12:00:06 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.6.1
* Fix freedesktop.org Thumbnail Managing Standard implementation:
@@ -660,7 +784,7 @@ Thu, 13 Sep 2012 12:00:06 +0200 Daniel Friesel <derf+feh@finalrewind.org>
* Show error message if load failed and magick is disabled (was broken
by feh 2.4)
-Tue, 28 Aug 2012 11:46:19 +0200 Daniel Friesel <derf+feh@finalrewind.org>
+Tue, 28 Aug 2012 11:46:19 +0200 Birte Friesel <derf+feh@finalrewind.org>
* Release v2.6
* Dennis Real: EXIF mode fixes, support for more camera models
@@ -681,7 +805,7 @@ Tue, 28 Aug 2012 11:46:19 +0200 Daniel Friesel <derf+feh@finalrewind.org>
less confusing. Set --magick-timeout to a non-negative value to enable
it (--magick-timeout 5 for feh-2.5 behaviour)
-Sun, 25 Mar 2012 13:13:26 +0200 Daniel Friesel <derf@finalrewind.org>
+Sun, 25 Mar 2012 13:13:26 +0200 Birte Friesel <derf@finalrewind.org>
* Release v2.5
* Add R, * and / bindings for <keypad begin>, <keypad *> and <keypad />
@@ -692,7 +816,7 @@ Sun, 25 Mar 2012 13:13:26 +0200 Daniel Friesel <derf@finalrewind.org>
* Do not scroll past image borders when using key bindings
* --loadable / --unloadable: indicate result in exit status
-Tue, 06 Mar 2012 13:13:35 +0100 Daniel Friesel <derf@finalrewind.org>
+Tue, 06 Mar 2012 13:13:35 +0100 Birte Friesel <derf@finalrewind.org>
* Release v2.4
* exif-support fixes by Dennis Real
@@ -704,7 +828,7 @@ Tue, 06 Mar 2012 13:13:35 +0100 Daniel Friesel <derf@finalrewind.org>
ignore out of memory errors
* Use ImageMagick (convert) as loader for unsupported file formats
-Thu, 02 Feb 2012 21:04:06 +0100 Daniel Friesel <derf@finalrewind.org>
+Thu, 02 Feb 2012 21:04:06 +0100 Birte Friesel <derf@finalrewind.org>
* Release v2.3
* Add %F and %N format specifiers, containing an escaped version of %f/%n.
@@ -721,7 +845,7 @@ Thu, 02 Feb 2012 21:04:06 +0100 Daniel Friesel <derf@finalrewind.org>
* Accept offset-only arguments for --geometry
<https://github.com/derf/feh/issues/73>
-Mon, 02 Jan 2012 11:54:01 +0100 Daniel Friesel <derf@finalrewind.org>
+Mon, 02 Jan 2012 11:54:01 +0100 Birte Friesel <derf@finalrewind.org>
* Release v2.2
* Add --no-fehbg option to disable ~/.fehbg creation (patch by Felix Crux)
@@ -733,7 +857,7 @@ Mon, 02 Jan 2012 11:54:01 +0100 Daniel Friesel <derf@finalrewind.org>
* Follow HTTP redirects
<http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=653689>
-Wed, 02 Nov 2011 10:56:10 +0100 Daniel Friesel <derf@finalrewind.org>
+Wed, 02 Nov 2011 10:56:10 +0100 Birte Friesel <derf@finalrewind.org>
* Release v2.1
* Experimental --scale-down and --auto-zoom tiling support
@@ -742,7 +866,7 @@ Wed, 02 Nov 2011 10:56:10 +0100 Daniel Friesel <derf@finalrewind.org>
* Fix http image load for long image names
<http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=646421>
-Mon, 10 Oct 2011 12:25:00 +0200 Daniel Friesel <derf@finalrewind.org>
+Mon, 10 Oct 2011 12:25:00 +0200 Birte Friesel <derf@finalrewind.org>
* Release v2.0
* The --bg-options now accept multiple filenames, one per Xinerama screen
@@ -758,7 +882,7 @@ Mon, 10 Oct 2011 12:25:00 +0200 Daniel Friesel <derf@finalrewind.org>
hosts if the local system is 32bit (for 32<->32 and 64<->64, this works
anyways)
-Mon, 26 Sep 2011 09:35:41 +0200 Daniel Friesel <derf@finalrewind.org>
+Mon, 26 Sep 2011 09:35:41 +0200 Birte Friesel <derf@finalrewind.org>
* Release v1.16.2
* Fix useless memory use when using feh --reload on HTTP URLs
@@ -768,13 +892,13 @@ Mon, 26 Sep 2011 09:35:41 +0200 Daniel Friesel <derf@finalrewind.org>
* Fix --title-font fallback behaviour
* Fix delayed title display when using --title-font
-Sun, 11 Sep 2011 12:46:50 +0200 Daniel Friesel <derf@finalrewind.org>
+Sun, 11 Sep 2011 12:46:50 +0200 Birte Friesel <derf@finalrewind.org>
* Release v1.16.1
* Fix reload after image rotation and similar (broken by 1.16)
<https://github.com/derf/feh/issues/63>
-Mon, 05 Sep 2011 10:56:58 +0200 Daniel Friesel <derf@finalrewind.org>
+Mon, 05 Sep 2011 10:56:58 +0200 Birte Friesel <derf@finalrewind.org>
* Release v1.16
* Reload image after executing an action with the hold-action flag set
@@ -797,14 +921,14 @@ Mon, 05 Sep 2011 10:56:58 +0200 Daniel Friesel <derf@finalrewind.org>
* When using --no-menus and clicking the menu button, feh will now ignore
it instead of quitting (which was undocumented behaviour anyways)
-Tue, 16 Aug 2011 22:48:06 +0200 Daniel Friesel <derf@finalrewind.org>
+Tue, 16 Aug 2011 22:48:06 +0200 Birte Friesel <derf@finalrewind.org>
* Release v1.15.1
* Fix segfault when selecting menu items (broken by 1.15)
<https://github.com/derf/feh/issues/58>,
<https://bugs.archlinux.org/task/25612>
-Mon, 15 Aug 2011 11:12:34 +0200 Daniel Friesel <derf@finalrewind.org>
+Mon, 15 Aug 2011 11:12:34 +0200 Birte Friesel <derf@finalrewind.org>
* Release v1.15
* Respect --image-bg option in full-screen mode
@@ -829,7 +953,7 @@ Mon, 15 Aug 2011 11:12:34 +0200 Daniel Friesel <derf@finalrewind.org>
* Add experimental reload functionality for directories
<https://github.com/derf/feh/issues/14>
-Mon, 04 Jul 2011 14:46:36 +0200 Daniel Friesel <derf@finalrewind.org>
+Mon, 04 Jul 2011 14:46:36 +0200 Birte Friesel <derf@finalrewind.org>
* Release v1.14.2
* Fix --draw-filename "x of y" being cut off by short filenames
@@ -841,13 +965,13 @@ Mon, 04 Jul 2011 14:46:36 +0200 Daniel Friesel <derf@finalrewind.org>
* Fix minor documentation bugs
* Fix minor memleak in the recursive file loader for directories
-Thu, 19 May 2011 22:32:42 +0200 Daniel Friesel <derf@finalrewind.org>
+Thu, 19 May 2011 22:32:42 +0200 Birte Friesel <derf@finalrewind.org>
* Release v1.14.1
* Fix compilation with curl=0
* Make zoom_default key work properly with --geometry
-Wed, 11 May 2011 11:37:32 +0200 Daniel Friesel <derf@finalrewind.org>
+Wed, 11 May 2011 11:37:32 +0200 Birte Friesel <derf@finalrewind.org>
* Release v1.14
* Only create caption directory when actually writing out a caption.
@@ -885,7 +1009,7 @@ Wed, 11 May 2011 11:37:32 +0200 Daniel Friesel <derf@finalrewind.org>
theme definition handling. Having a theme line with just one
option/value pair used to produce undefined behaviour
-Sat, 23 Apr 2011 22:00:27 +0200 Daniel Friesel <derf@finalrewind.org>
+Sat, 23 Apr 2011 22:00:27 +0200 Birte Friesel <derf@finalrewind.org>
* Release v1.13
* Fix segfault upon unloadable images when image-related format specifiers
@@ -899,7 +1023,7 @@ Sat, 23 Apr 2011 22:00:27 +0200 Daniel Friesel <derf@finalrewind.org>
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>
+Sat, 12 Mar 2011 22:49:53 +0100 Birte Friesel <derf@finalrewind.org>
* Release v1.12
* Add --zoom fill as equivalent for --auto-zoom
@@ -913,7 +1037,7 @@ Sat, 12 Mar 2011 22:49:53 +0100 Daniel Friesel <derf@finalrewind.org>
* 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>
+Wed, 09 Feb 2011 20:11:26 +0100 Birte Friesel <derf@finalrewind.org>
* Release v1.11.2
* Use wget --no-clobber to prevent TOCTTOU-based hole allowing a
@@ -922,7 +1046,7 @@ Wed, 09 Feb 2011 20:11:26 +0100 Daniel Friesel <derf@finalrewind.org>
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>
+Wed, 26 Jan 2011 21:07:19 +0100 Birte Friesel <derf@finalrewind.org>
* Release v1.11.1
* Show correct image dimensions in for cached thumbnails
@@ -930,7 +1054,7 @@ Wed, 26 Jan 2011 21:07:19 +0100 Daniel Friesel <derf@finalrewind.org>
* 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>
+Sat, 22 Jan 2011 11:48:33 +0100 Birte Friesel <derf@finalrewind.org>
* Release v1.11
* Patch by Pascal Bleser: Use getaddrinfo for builtin http client,
@@ -942,7 +1066,7 @@ Sat, 22 Jan 2011 11:48:33 +0100 Daniel Friesel <derf@finalrewind.org>
* 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>
+Fri, 03 Dec 2010 19:41:45 +0100 Birte Friesel <derf@finalrewind.org>
* Release v1.10.1
* Partially fix --scale-down behaviour (zooming is still broken)
@@ -950,7 +1074,7 @@ Fri, 03 Dec 2010 19:41:45 +0100 Daniel Friesel <derf@finalrewind.org>
* Fix segfaults after trying to load several unloadable images
* Fix fehrc created by feh (contined escape errors)
-Thu, 07 Oct 2010 20:15:12 +0200 Daniel Friesel <derf@finalrewind.org>
+Thu, 07 Oct 2010 20:15:12 +0200 Birte Friesel <derf@finalrewind.org>
* Release v1.10 (aka "2.0 will come real soon now")
* Patch by Stefan Mark: Add --bg-max (scaled with borders)
@@ -966,7 +1090,7 @@ Thu, 07 Oct 2010 20:15:12 +0200 Daniel Friesel <derf@finalrewind.org>
* Zoom button: Zoom to 100% on button release, not button click
* --draw-filename: Always show position in filelist
-Tue, 24 Aug 2010 19:23:36 +0200 Daniel Friesel <derf@chaosdorf.de>
+Tue, 24 Aug 2010 19:23:36 +0200 Birte Friesel <derf@chaosdorf.de>
* Release v1.9
* Add --fullscreen option, --full-screen is now deprecated
@@ -981,7 +1105,7 @@ Tue, 24 Aug 2010 19:23:36 +0200 Daniel Friesel <derf@chaosdorf.de>
* When zooming via keyboard: Always zoom around the center of the window
* The image can now be panned with Ctrl + arrow keys
-Fri, 25 Jun 2010 16:07:20 +0200 Daniel Friesel <derf@chaosdorf.de>
+Fri, 25 Jun 2010 16:07:20 +0200 Birte Friesel <derf@chaosdorf.de>
* Release v1.8
* support LDLIBS in Makefile/config.mk
@@ -1002,7 +1126,7 @@ Fri, 25 Jun 2010 16:07:20 +0200 Daniel Friesel <derf@chaosdorf.de>
* Don't add ?randomnumber to URLs when downloading them, it confuses some
servers and is not really necessary in general
-Thu Jun 10 12:12:04 CEST 2010 Daniel Friesel <derf@chaosdorf.de>
+Thu Jun 10 12:12:04 CEST 2010 Birte Friesel <derf@chaosdorf.de>
* Release v1.7
* Fix segfault in Thumbnail mode when trying to open a no longer
@@ -1020,14 +1144,14 @@ Thu Jun 10 12:12:04 CEST 2010 Daniel Friesel <derf@chaosdorf.de>
* caption mode: Automatically create caption directory if it doesn't exist
* Slideshow mode: SIGUSR1 = next image, SIGUSR2 = previous image
-Sat Jun 5 21:35:25 CEST 2010 Daniel Friesel <derf@chaosdorf.de
+Sat Jun 5 21:35:25 CEST 2010 Birte Friesel <derf@chaosdorf.de
* Release v1.6.1
* Fix omitted image borders at high zoom levels
* Re-add getopt_long files (possibly relevant for non-glibc systems)
* Do not require a running X server for -L, -u, -U options
-Tue Jun 1 10:21:19 CEST 2010 Daniel Friesel <derf@chaosdorf.de>
+Tue Jun 1 10:21:19 CEST 2010 Birte Friesel <derf@chaosdorf.de>
* Release v1.6
* Patch by aaptel: Support numpad keys for actions
@@ -1043,7 +1167,7 @@ Tue Jun 1 10:21:19 CEST 2010 Daniel Friesel <derf@chaosdorf.de>
* Fix "make uninstall". You do NOT want to call this for feh versions
1.4.2 to 1.5
-Thu May 6 08:34:39 CEST 2010 Daniel Friesel <derf@chaosdorf.de>
+Thu May 6 08:34:39 CEST 2010 Birte Friesel <derf@chaosdorf.de>
* Release v1.5
* Rewrite parts of the menu code & fix a memory leak while there
@@ -1051,7 +1175,7 @@ Thu May 6 08:34:39 CEST 2010 Daniel Friesel <derf@chaosdorf.de>
* Add keybinding to toggle pointer visibility (see --hide-pointer)
* Sort manual a bit
-Thu Apr 22 22:28:09 CEST 2010 Daniel Friesel <derf@chaosdorf.de>
+Thu Apr 22 22:28:09 CEST 2010 Birte Friesel <derf@chaosdorf.de>
* Release v1.4.3
* Warp the pointer when reaching a window border in pan mode
@@ -1061,7 +1185,7 @@ Thu Apr 22 22:28:09 CEST 2010 Daniel Friesel <derf@chaosdorf.de>
is. The zoom happen around at that pixel.
* Manpage review
-Fri Apr 2 16:20:55 CEST 2010 Daniel Friesel <derf@chaosdorf.de>
+Fri Apr 2 16:20:55 CEST 2010 Birte Friesel <derf@chaosdorf.de>
* Release v1.4.2
* Replace autoconf by config.mk
@@ -1070,7 +1194,7 @@ Fri Apr 2 16:20:55 CEST 2010 Daniel Friesel <derf@chaosdorf.de>
* patch by dylan: Remove temporary files if url opening fails
* Fix problems with unexpectedly empty filelists
-Tue Mar 16 07:56:36 CET 2010 Daniel Friesel <derf@chaosdorf.de>
+Tue Mar 16 07:56:36 CET 2010 Birte Friesel <derf@chaosdorf.de>
* Release v1.4.1
* Fix chrome theme in the default .fehrc
@@ -1078,7 +1202,7 @@ Tue Mar 16 07:56:36 CET 2010 Daniel Friesel <derf@chaosdorf.de>
* Add manual for feh-cam and gen-cam-menu (from Debian)
* Fix lossless rotate for filenames with spaces etc.
-Thu Mar 4 14:55:02 CET 2010 Daniel Friesel <derf@chaosdorf.de>
+Thu Mar 4 14:55:02 CET 2010 Birte Friesel <derf@chaosdorf.de>
* Release v1.4
* Lots of documentation fixes/improvements
@@ -1092,7 +1216,7 @@ Thu Mar 4 14:55:02 CET 2010 Daniel Friesel <derf@chaosdorf.de>
* Use jpegtran binary instead of libjpeg for lossless rotation
* Add --bg-fill option (patch by Anonymous)
-Mon Feb 8 21:47:56 CET 2010 Daniel Friesel <derf@chaosdorf.de>
+Mon Feb 8 21:47:56 CET 2010 Birte Friesel <derf@chaosdorf.de>
* Release v1.3.5
* Import various Debian patches
@@ -1172,8 +1296,8 @@ Mon Mar 07 23:56:03 GMT 2005 Tom Gilbert <tom@linuxbrit.co.uk>
> In short, it enables the user to use feh as an image viewer used by a
> file manager like ROX-Filer or Nautilus when invoked with the --fmmode
> option. The file manager passes the file that the user wants to view to
- > feh. My function then reads the directory in which the file resides and
- > first passes the current image, then alphabetically all the following
+ > feh. My function then reads the directory in which the file resides and
+ > first passes the current image, then alphabetically all the following
> images and at last the images that are alphabetically before the current
> file to the 'filelist'.
> Afaik that's the default behaviour of gqview and gthumb.
@@ -1219,7 +1343,7 @@ Fri Sep 03 13:40:48 BST 2004 Tom Gilbert <tom@linuxbrit.co.uk>
Sat Jul 24 14:52:19 BST 2004 Tom Gilbert <tom@linuxbrit.co.uk>
- * Various warning fixes from Claes Nasten <pekdon@pekdon.net>
+ * Various warning fixes from Claes Nasten <pekdon@pekdon.net>
Thu Jun 10 23:14:36 BST 2004 Tom Gilbert <tom@linuxbrit.co.uk>
@@ -1350,13 +1474,13 @@ Sun Oct 20 20:12:23 2002 EDT, Paul Duncan <pabs@pablotron.org>
* AUTHORS: added Jon Bernard
Sun Oct 20 14:49:46 2002 EDT, Paul Duncan <pabs@pablotron.org>
-
+
* New beveled, off-white background image for menus. I made it the
default after consulting with the boss (eg Sue Gilbert). Tom thinks
it's okay too.
Sun Oct 20 05:48:40 2002 EDT Paul Duncan <pabs@pablotron.org>
-
+
* Added Xinerama support. Currently defaults to fullscreen on the
first head (this can be fixed with a little work).
* Added winwidget_{move,get_geometry}();
@@ -1917,7 +2041,7 @@ Fri Jun 23 11:37:56 2000 Tom Gilbert <gilbertt@linuxbrit.co.uk>
Thu Jun 22 23:57:33 2000 Tom Gilbert <gilbertt@linuxbrit.co.uk>
* Optimisations to thumb hilites. Only show hilite when you can
- click to open an image, don't show when over emtpy space, and
+ click to open an image, don't show when over emtpy space, and
don't re-render if the selection hasn't changed from the last
mouseover. Speeds it up a lot.
@@ -2020,7 +2144,7 @@ Sun Jun 18 03:47:58 2000 Tom Gilbert <gilbertt@linuxbrit.co.uk>
Sun Jun 18 01:29:16 2000 Tom Gilbert <gilbertt@linuxbrit.co.uk>
- * The first part of some background setting code from richlowe
+ * The first part of some background setting code from richlowe
<richlowe@btinternet.com> - more to come, it'll be sweet.
* Doesn't work yet btw, so don't get excited ;)
@@ -2042,7 +2166,7 @@ Sat Jun 17 23:46:32 2000 Tom Gilbert <gilbertt@linuxbrit.co.uk>
bg. Same for --theme chrome.
Sat Jun 17 12:57:49 PDT 2000 Paul Duncan <pabs@pablotron.org>
-
+
* wget is now quiet by default (wget -q). it's verbose if the
-V or --verbose flag is passed to feh. Your terminal will
thank you.
@@ -2117,7 +2241,7 @@ Sun Jun 4 15:44:05 2000 Tom Gilbert <gilbertt@linuxbrit.co.uk>
the singleton context (accidentally leaving context_antialias on,
not blending when I should be etc), and to fix them I was adding
lines and lines of context_set this, context_set that. I've
- wrapped the imlib calls in an imlib1
+ wrapped the imlib calls in an imlib1
lots-of-params-per-function-call stylee, and now it's much more
readable and harder to break.
* In the process, made big speedups by not antialiasing when I
@@ -2456,7 +2580,7 @@ Fri Mar 24 19:22:51 2000 Tom Gilbert <gilbertt@linuxbrit.co.uk>
* If ~/.fehrc exists, or if not, but /etc/fehrc exists, feh will
look in it for name/options pairs. An example entry would be:
imagemap -rVq --thumb-width 40 --thumb-height 30
- * You can use the theme in two ways. Either
+ * You can use the theme in two ways. Either
feh -C themename [images]
or you can create a symbolic link to feh with the name of the
options you want it to use. So from the example above:
@@ -2469,7 +2593,7 @@ Fri Mar 24 19:22:51 2000 Tom Gilbert <gilbertt@linuxbrit.co.uk>
create an index.jpg in the current directory. I just run:
$ mkindex.
* An example.fehrc is provided with a couple of cool examples.
-
+
Fri Mar 24 19:17:27 2000 Tom Gilbert <gilbertt@linuxbrit.co.uk>
* Slightly increased the default index mode font size.
@@ -2705,11 +2829,11 @@ Fri Mar 3 22:44:25 PST 2000 Michael Jennings <mej@eterm.org>
tired right now to try to make sense out of gilbertt's callback
logic. :-) I'll try to fix it this weekend if he doesn't beat me
to it.
-
+
Wed Mar 1 15:13:04 PST 2000 Michael Jennings <mej@eterm.org>
* Math lib
-
+
Sun Feb 20 15:22:00 2000 Tom Gilbert <gilbertt@linuxbrit.co.uk>
* Remove some crufty duplication.
@@ -3012,7 +3136,7 @@ Sun Dec 19 22:06:43 1999 Tom Gilbert <gilbertt@linuxbrit.co.uk>
Sun Dec 19 20:29:33 1999 Tom Gilbert <gilbertt@linuxbrit.co.uk>
* Added a .spec file for feh. Contributed by Alistair Sutton
- <metallica@freenet.co.uk>, (who is obviously a metallica fan ;),
+ <metallica@freenet.co.uk>, (who is obviously a metallica fan ;),
and has written specs for me before ::) Thanks dude :)
* Urm. I haven't actually tested this yet :)
@@ -3122,4 +3246,3 @@ Thu Dec 16 22:58:21 1999 Tom Gilbert <gilbertt@linuxbrit.co.uk>
Thu Dec 16 22:10:50 1999 Tom Gilbert <gilbertt@linuxbrit.co.uk>
* Initial import. Feh is currently at 0.5.0 release level.
-
diff --git a/Makefile b/Makefile
index 552ae4d..1e7e4e5 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,7 @@ build-applications:
@${MAKE} -C share/applications
test: all
- @if ! uname -m | fgrep -q -e arm -e mips; then \
+ @if ! uname -m | grep -q -e arm -e mips; then \
PACKAGE=${PACKAGE} prove test/feh.t test/mandoc.t; \
else \
PACKAGE=${PACKAGE} prove test/feh.t test/mandoc.t || cat test/imlib2-bug-notice; \
@@ -25,20 +25,20 @@ test-x11: all
install: install-man install-doc install-bin install-font install-img
install: install-icon install-examples install-applications
-install-man:
+install-man: man/feh.1
@echo installing manuals to ${man_dir}
@mkdir -p ${man_dir}/man1
@cp man/feh.1 ${man_dir}/man1
@chmod 644 ${man_dir}/man1/feh.1
-install-doc:
+install-doc: AUTHORS ChangeLog README.md TODO
@echo installing docs to ${doc_dir}
@mkdir -p ${doc_dir}
@cp AUTHORS ChangeLog README.md TODO ${doc_dir}
@chmod 644 ${doc_dir}/AUTHORS ${doc_dir}/ChangeLog ${doc_dir}/README.md \
${doc_dir}/TODO
-install-bin:
+install-bin: src/feh
@echo installing executables to ${bin_dir}
@mkdir -p ${bin_dir}
@cp src/feh ${bin_dir}/feh.tmp
@@ -78,7 +78,7 @@ install-examples:
@cp examples/* ${example_dir}
@chmod 644 ${example_dir}/*
-install-applications:
+install-applications: share/applications/feh.desktop
@echo installing desktop file to ${desktop_dir}
@mkdir -p ${desktop_dir}
@cp share/applications/feh.desktop ${desktop_dir}
diff --git a/README.md b/README.md
index 2cedc53..cbd2150 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,6 @@
-[![build status](https://travis-ci.org/derf/feh.svg?branch=master)](https://travis-ci.org/derf/feh)
+# feh - Image Viewer and Cataloguer
-Feh – Image viewer and Cataloguer
----
-
-feh is a light-weight, configurable and versatile image viewer.
+**feh** is a light-weight, configurable and versatile image viewer.
It is aimed at command line users, but can also be started from graphical file
managers. Apart from viewing images, it can compile text and thumbnail
listings, show (un)loadable files, set X11 backgrounds, and more.
@@ -13,70 +10,54 @@ and image captions. feh can be controlled by configurable keyboard and mouse
shortcuts, terminal input and signals. When no file arguments or filelists are
specified, feh displays all files in the current directory.
-For more information, please refer to the [feh
-website](https://feh.finalrewind.org/) or read the [feh
-manual](https://man.finalrewind.org/1/feh/).
+This README focuses on installation and contribution instructions. See the
+[feh homepage](https://feh.finalrewind.org/) and the
+[feh(1) manual](https://man.finalrewind.org/1/feh/) for other details.
-Dependencies
----
+## Dependencies
* Imlib2
- * libcurl (disable with make curl=0)
+ * libcurl (disable with `curl=0`)
* libpng
* libX11
- * libXinerama (disable with make xinerama=0)
+ * libXt
+ * libXinerama (disable with `xinerama=0`)
-If built with exif=1:
+Only when building with `exif=1`:
* libexif-dev
* libexif12
-Recommended Binaries
----
+Only when building with `magic=1`:
- * convert (supplied by ImageMagick, can be used to load image formats not supported by Imlib2)
+ * libmagic
-Installation
----
+## Build Process
-**For end users:**
-```bash
-$ make
-$ sudo make install app=1
-```
+feh has been packaged for a variety of distributions, including
+[Arch Linux](https://archlinux.org/packages/extra/x86_64/feh/),
+[Debian](https://packages.debian.org/search?keywords=feh&exact=1),
+[FreeBSD](https://www.freshports.org/graphics/feh), and
+[Ubuntu](https://packages.ubuntu.com/search?keywords=feh&exact=1).
+You can configure, compile and install a custom version as follows.
-**For package maintainers and users who do not want feh to install its
-icons into /usr/share:**
-```bash
-$ make
-$ sudo make install
-```
-
-**Explanation:** feh ships some icons and an X11 desktop entry, which allow it to
-be used from file managers, desktop menus and similar. However, installing
-icons to /usr/local/share/... does not seem to work reliably.
-Because of this, when using "make install app=1", feh will install its icons
-to /usr/share/..., even though they technically belong into /usr/local.
-
-[ZSH completion for
-feh](https://git.finalrewind.org/zsh/plain/etc/completions/_feh) is also
-available.
-
-Make flags
-----------
+### Configuration
feh's build process uses make flags to enable/disable optional features and
-fine-tune the build and installation process. They can be passed as **make**
-arguments or set as environment variables, like so:
+fine-tune the build and installation process. It uses (hopefully) reasonable
+defaults, so you can skip this section if you like.
+
+Make flags can be passed as **make** arguments or set as environment variables,
+like so:
```bash
-make flag=bool
-make install flag=bool
+$ make flag=bool
+$ make install flag=bool
```
or
```bash
-export flag=bool
-make && make install
+$ export flag=bool
+$ make && make install
```
The following flags are respected by the makefile. A default value of **1**
@@ -91,13 +72,16 @@ indicates that the corresponding feature is enabled by default.
| help | 0 | include help text (refers to the manpage otherwise) |
| inotify | 0 | enable inotify, needed for `--auto-reload` |
| stat64 | 0 | Support CIFS shares from 64bit hosts on 32bit machines |
+| magic | 0 | Use libmagic to filter unsupported file formats |
+| mkstemps | 1 | Whether your libc provides `mkstemps()`. If set to 0, feh will be unable to load gif images via libcurl |
| verscmp | 1 | Whether your libc provides `strvercmp()`. If set to 0, feh will use an internal implementation. |
| xinerama | 1 | Support Xinerama/XRandR multiscreen setups |
For example, `make xinerama=0 debug=1` will disable Xinerama support and
produce a debug build; libcurl and natural sorting support will remain enabled.
-Additionally, the standard variables `PREFIX` and `DESTDIR` are supported.
+Additionally, it supports the standard variables `CFLAGS`, `LDLIBS`, `PREFIX`,
+and `DESTDIR`.
**PREFIX _(default: /usr/local)_** controls where the application and its data files
will be installed. It must be set both during `make` and `make install`.
@@ -109,18 +93,43 @@ is mostly useful for package maintainers.
cases, you can set environment variables instead of editing it. E.g.:
```bash
-CFLAGS='-g -Os' make
+$ CFLAGS='-g -Os' make
```
```bash
-export DESTDIR=/tmp/feh PREFIX=/usr
-make && make install
+$ export DESTDIR=/tmp/feh PREFIX=/usr
+$ make && make install
```
Builtin EXIF support is maintained by Dennis Real, [here](https://github.com/reald/feh).
+### Installation
-Testing (non-X)
----------------
+Add your own make flags to the following examples as needed.
+
+**For end users:**
+```bash
+$ make
+$ sudo make install app=1
+```
+
+**For package maintainers and users who do not want feh to install its
+icons into /usr/share:**
+```bash
+$ make
+$ sudo make install
+```
+
+**Explanation:** feh ships some icons and an X11 desktop entry, which allow it to
+be used from file managers, desktop menus and similar. However, installing
+icons to /usr/local/share/... does not seem to work reliably.
+Because of this, when using "make install app=1", feh will install its icons
+to /usr/share/..., even though they technically belong into /usr/local.
+
+[ZSH completion for
+feh](https://git.finalrewind.org/zsh/plain/etc/completions/_feh) is also
+available.
+
+## Testing (non-X11)
The non-X11 parts of feh can be automatically tested by running
@@ -131,9 +140,7 @@ This requires **perl >= 5.10** and the perl module `Test::Command`. Tests are
non-interactive and do not require a running X11, so they can safely be run on
a headless buildserver.
-
-Contributing
----
+## Contributing
Bugfixes are always welcome, just open a pull request :)
diff --git a/config.mk b/config.mk
index 5dfd7d3..5cad703 100644
--- a/config.mk
+++ b/config.mk
@@ -6,6 +6,8 @@ curl ?= 1
debug ?= 0
exif ?= 0
help ?= 0
+magic ?= 0
+mkstemps ?= 1
verscmp ?= 1
xinerama ?= 1
@@ -38,7 +40,7 @@ CFLAGS ?= -g -O2
CFLAGS += -Wall -Wextra -pedantic
# Settings for glibc >= 2.19 - may need to be adjusted for other systems
-CFLAGS += -std=c11 -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700
+CFLAGS += -std=c11 -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -D_DARWIN_C_SOURCE
ifeq (${curl},1)
CFLAGS += -DHAVE_LIBCURL
@@ -63,6 +65,18 @@ ifeq (${stat64},1)
CFLAGS += -D_FILE_OFFSET_BITS=64
endif
+ifeq (${mkstemps},1)
+ CFLAGS += -DHAVE_MKSTEMPS
+endif
+
+ifeq (${magic},1)
+ CFLAGS += -DHAVE_LIBMAGIC
+ LDLIBS += -lmagic
+ MAN_MAGIC = enabled
+else
+ MAN_MAGIC = disabled
+endif
+
ifeq (${verscmp},1)
CFLAGS += -DHAVE_STRVERSCMP
endif
diff --git a/examples/buttons b/examples/buttons
index 3c79413..be6ce39 100644
--- a/examples/buttons
+++ b/examples/buttons
@@ -14,4 +14,4 @@ zoom 3
# make scroll wheel (mousewheel up and down) zoom, instead of flipping images
zoom_in 4
-zoom_out 5 \ No newline at end of file
+zoom_out 5
diff --git a/examples/keys b/examples/keys
index d221d29..c1bb091 100644
--- a/examples/keys
+++ b/examples/keys
@@ -37,7 +37,7 @@ zoom_out C-Down a
zoom_default d
zoom_fit s
-# I only hit these accidentaly
+# I only hit these accidentally
save_image
save_filelist
diff --git a/man/Makefile b/man/Makefile
index 3be07e3..8fe2cbd 100644
--- a/man/Makefile
+++ b/man/Makefile
@@ -13,6 +13,7 @@ all: ${TARGETS}
-e 's/\$$MAN_DEBUG\$$/${MAN_DEBUG}/' \
-e 's/\$$MAN_EXIF\$$/${MAN_EXIF}/' \
-e 's/\$$MAN_INOTIFY\$$/${MAN_INOTIFY}/' \
+ -e 's/\$$MAN_MAGIC\$$/${MAN_MAGIC}/' \
-e 's/\$$MAN_XINERAMA\$$/${MAN_XINERAMA}/' \
< ${@:.1=.pre} > $@
diff --git a/man/feh.pre b/man/feh.pre
index 7f7ef6b..cd65b83 100644
--- a/man/feh.pre
+++ b/man/feh.pre
@@ -13,6 +13,7 @@
.
.Nm
.Op Ar options
+.Op Cm --
.Op Ar files | Ar directories | Ar URLs ...
.
.
@@ -40,6 +41,9 @@ libexif builtin EXIF reader $MAN_EXIF$
.It
inotify-based auto-reload of changed files $MAN_INOTIFY$
.
+.It
+libmagic $MAN_MAGIC$
+.
.El
.
$MAN_DEBUG$
@@ -150,34 +154,41 @@ pnm, tiff, and bmp.
The gif format is also supported, but only for static images.
In case of animations, only the first frame will be shown.
.
-If the convert binary
-.Pq supplied by ImageMagick
-is available, it also has limited support for many other file types, such as
-svg, xcf and otf.
-If dcraw is available,
-.Nm
-also supports RAW files provided by cameras and will display the embedded
-thumbnails.
-Use
+.Pp
+.
+When invoked with
.Cm --conversion-timeout Ar timeout
-with a non-negative value to enable support for these formats.
+.Po
+and a non-negative
+.Ar timeout
+value
+.Pc ,
+.Nm
+also has limited support for various other file types by means of external
+conversion programs.
+If the dcraw binary is available,
+.Nm
+will use it to display the thumbnails embedded into RAW files provided by
+digital cameras and similar.
+If the ImageMagick convert binary is available,
+.Nm
+will use it to load file types such as svg, xcf, and otf.
.
.Pp
.
-As Imlib2 may take several seconds to determine whether it can load a file or
-not
-.Pq e.g. when attempting to open a large video ,
+.Pq optional feature, $MAN_MAGIC$ in this build
+.Nm
+can use libmagic to only pass image files to Imlib2.
+When using
.Nm
-checks each file's header before loading it.
-If it looks like an image, it is passed on to Imlib2, otherwise, it is
-assumed to be unloadable.
-This greatly improves performance when working in directories with mixed files
-.Pq i.e., directories which do not exclusively contain image files .
+with lots of non-image files
+.Pq especially with Imlib2 version 1.6.x or 1.7.0 ,
+this can speed up the detection of non-image files significantly.
If you think that Imlib2 can load a file which
.Nm
has determined to be likely not an image, set the environment variable
.Qq FEH_SKIP_MAGIC
-to pass all files directly to Imlib2, bypassing the header check.
+to pass all files directly to Imlib2, bypassing this check.
The environment variable's value does not matter, it just needs to be set.
.
.Sh OPTIONS
@@ -260,9 +271,16 @@ Automatic reload is not supported in montage, index, or thumbnail mode.
.It Cm --auto-rotate
.
.Pq optional feature, $MAN_EXIF$ in this build
+.Pq deprecated in favor of Imlib2's auto-orientation support
Automatically rotate images based on EXIF data.
Does not alter the image files.
.
+.Pp
+.
+Note that Imlib2 version 1.7.5+ performs auto-rotation by itself, so this option is obsolete on systems with Imlib2 version 1.7.5 or later.
+.Nm
+currently cannot detect this at runtime.
+.
.It Cm -Z , --auto-zoom
.
Zoom pictures to screen size in fullscreen / fixed geometry mode.
@@ -408,8 +426,9 @@ will read the filelist from its standard input.
.
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 .
+directory, and should be defined in the form fontname/size, like
+.Qq yudit/12
+.Pq which is the default .
.
.It Cm -C , --fontpath Ar path
.
@@ -556,6 +575,9 @@ Useful in scripts to hunt out images of a certain size/resolution/type etc.
Don't display images.
Just print out their names if imlib2 can successfully load them.
Returns false if at least one image failed to load.
+When combined with
+.Cm --action ,
+the specified action will be run for each loadable image.
.
.It Cm --max-dimension Ar width No x Ar height
.
@@ -652,7 +674,10 @@ and next image.
.Cm quit
will cause
.Nm
-to quit when trying to advance past the last image in the slide show.
+to quit when trying to advance past the last image in the slide show. This is
+the behavior of the obsolete
+.Cm --cycle-once
+option.
.
.Pp
.
@@ -671,7 +696,7 @@ Save files to
.Ar directory
when using
.Cm --keep-http
-or the save_image command.
+or the save_image or save_filelist command.
By default, files are saved in the current working directory.
.
.It Cm -p , --preload
@@ -780,9 +805,9 @@ in paused mode.
.
Sort file list according to image parameters.
Allowed sort types are:
-.Cm name , filename , dirname , mtime , width , height , pixels , size , format .
+.Cm name , none , filename , dirname , mtime , width , height , pixels , size , format .
For sort modes other than
-.Cm name , filename , dirname ,
+.Cm name , none , filename , dirname ,
or
.Cm mtime ,
a preload run is
@@ -810,6 +835,11 @@ you can use
.Cm --version-sort
to sort numbers naturally, so that e.g. 10.jpg comes after 2.jpg.
.
+.Pp
+.
+.Cm none
+is the default; you can specify it explicitly to discard a sort mode that has
+been specified at an earlier point in the command line arguments.
.It Cm -| , --start-at Ar filename
.
Start the filelist at
@@ -896,6 +926,9 @@ See
Don't display images.
Just print out their names if imlib2 can NOT successfully load them.
Returns false if at least one image was loadable.
+When combined with
+.Cm --action ,
+the specified action will be run for each unloadable file.
.
.It Cm -V , --verbose
.
@@ -919,26 +952,38 @@ comes before
Note that this option only has an effect when a sort mode is set using
.Cm --sort .
.
-.It Cm --xinerama-index Ar screen
+.It Cm --window-id Ar windowid
+.
+Draw to an existing X11 window by its ID
+.Ar windowid .
+This option is intended for use with software such as xcreensaver or
+xsecurelock, which provide a window for other applications to draw into.
+Unexpected things will happen if you specify a window belonging to software
+which does not expect
+.Nm
+to draw into it or attempt to use options or keybindings which affect window
+attributes, such as full-screen mode.
+.
+.It Cm --xinerama-index Ar monitor
.
.Pq optional feature, $MAN_XINERAMA$ in this build
Override
.Nm Ns No 's
-idea of the active Xinerama screen.
+idea of the active Xinerama monitor.
May be useful in certain circumstances where the window manager places the feh
-window on Xinerama screen A while
+window on Xinerama monitor A while
.Nm
-assumes that it will be placed on screen B.
+assumes that it will be placed on monitor B.
.
.Pp
.
In background setting mode: When used with any option other than
.Cm --bg-tile :
Only set wallpaper on
-.Ar screen .
-All other screens will be filled black/white.
+.Ar monitor .
+All other monitors will be filled black/white.
.
-This is most useful in a Xinerama configuration with overlapping screens.
+This is most useful in a Xinerama configuration with overlapping monitors.
For instance, assume you have two overlapping displays (index 0 and 1),
where index 0 is smaller.
To center a background on the display with index 0 and fill the extra space
@@ -946,6 +991,13 @@ on index 1 black/white, use
.Qq --xinerama-index 0
when setting the wallpaper.
.
+.Pp
+.
+Use
+.Cm xrandr --listmonitors
+to determine how Xinerama monitor IDs map to screens/monitors in your setup.
+.
+.
.It Cm --zoom Ar percent | Cm max | Cm fill
.
Zoom images by
@@ -967,8 +1019,14 @@ zoom the image like the
.Cm --bg-fill
mode.
.
-.El
+.It Cm --zoom-step Ar percent
+.
+Zoom images in and out by
+.Ar percent
+.Pq default: 25
+when using the zoom keys and buttons.
.
+.El
.
.Sh MONTAGE MODE OPTIONS
.
@@ -1147,7 +1205,7 @@ and
.Cm --bg-max ,
you can use
.Cm --geometry
-to specify an offset from one side of the screen instead of centering the image.
+to specify an offset from one side of the monitor instead of centering the image.
Positive values will offset from the left/top side, negative values from the
bottom/right.
+0 and -0 are both valid and distinct values.
@@ -1157,23 +1215,26 @@ bottom/right.
Note that all options except
.Cm --bg-tile
support Xinerama.
-For instance, if you have multiple screens connected and use e.g.
+For instance, if you have multiple monitors connected and use e.g.
.Cm --bg-center ,
.Nm
-will center or appropriately offset the image on each screen.
+will center or appropriately offset the image on each monitor.
You may even specify more than one file, in that case, the first file is set
-on screen 0, the second on screen 1, and so on.
+on monitor 0, the second on monitor 1, and so on.
+Use
+.Cm xrandr --listmonitor
+to determine how Xinerama monitor IDs map to screens / monitors in your setup.
.
.Pp
.
Use
.Cm --no-xinerama
-to treat the whole X display as one screen when setting wallpapers.
+to treat the whole X display as one monitor when setting wallpapers.
You may also use
.Cm --xinerama-index
to use
.Nm
-as a background setter for a specific screen.
+as a background setter for a specific monitor.
.
.Bl -tag -width indent
.
@@ -1305,6 +1366,14 @@ Number of current file
.
Image width
.
+.\" .It %W
+.\" .
+.\" Window dimensions and offset as WxH+x+y
+.\" .Pq X11 geometry format .
+.\" Note that this is currently only properly updated when changing images;
+.\" offsets for the first image after starting feh and after changing window
+.\" geometry may be bogus.
+.
.It %v
.
.Nm
@@ -1576,7 +1645,10 @@ will keep zoom and X, Y offset when switching images.
.It L Bq save_filelist
.
Save the current filelist as
-.Qq feh_PID_ID_filelist
+.Qq feh_PID_ID_filelist .
+It is saved in the directory specified by
+.Cm --output-dir ,
+if set, and in the current working directory otherwise.
.
.It m Bq toggle_menu
.
@@ -1612,7 +1684,10 @@ Useful for webcams
.It s Bq save_image
.
Save the current image as
-.Qq feh_PID_ID_FILENAME
+.Qq feh_PID_ID_FILENAME .
+It is saved in the directory specified by
+.Cm --output-dir ,
+if set, and in the current working directory otherwise.
.
.It w Bq size_to_image
.
@@ -1869,6 +1944,13 @@ section can also be bound to a button.
.
Reload current image
.
+.It 0 Ao cursor movement while not panning, zooming, or similar Ac
+.
+Does not have a default binding.
+By binding it to
+.Cm quit ,
+you can turn feh into a simple screensaver.
+.
.It 1 Ao left mouse button Ac Bq pan
.
pan the current image
@@ -2087,6 +2169,22 @@ It is $MAN_CURL$ in this build
.
.Sh KNOWN BUGS
.
+Imlib2 releases prior to 1.7.4 are unable to load gif, tiff, and webp images
+if the filename does not end with gif, tiff, or webp, respectively.
+Notably, this means that feh is unable to show gif, tiff, and webp images from
+stdin or network URLs on systems using an Imlib2 version older than 1.7.4.
+.
+.Pp
+.
+Imlib2 releases 1.7.5+ automatically rotate images based on their EXIF tags.
+When combined with the
+.Cm --auto-rotate
+option, this causes images to be rotated twice and end up in an incorrect orientation.
+As a workaround, do not use
+.Cm --auto-rotate
+on systems with Imlib2 version 1.7.5 or later.
+.Pp
+.
On systems with giflib 5.1.2,
.Nm
may be unable to load gif images.
@@ -2126,21 +2224,22 @@ If you find a bug, please report it to
.Aq derf+feh@finalrewind.org
or via
.Aq https://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.
+Note that
+.Nm
+is a hobby project, so bug reports may be addressed with significant delays.
.
.
.Sh LICENSE
.
Copyright (C) 1999, 2000 by Paul Duncan.
Copyright (C) 1999, 2000 by Tom Gilbert and contributors.
-Copyright (C) 2010-2020 by Daniel Friesel and contributors.
+Copyright (C) 2010-2023 by Birte Kristina Friesel and contributors.
.
.Pp
.
@@ -2170,7 +2269,7 @@ SOFTWARE.
.
.Pp
.
-Current developer: Daniel Friesel
+Current developer: Birte Friesel
.Aq derf@finalrewind.org
.
.Pp
diff --git a/scripts/checkkeys.pl b/scripts/checkkeys.pl
index 54978c5..ecf01e0 100755
--- a/scripts/checkkeys.pl
+++ b/scripts/checkkeys.pl
@@ -1,5 +1,5 @@
#!/usr/bin/env perl
-## Copyright © 2011 by Daniel Friesel <derf@finalrewind.org>
+## Copyright © 2011 by Birte Kristina Friesel <derf@finalrewind.org>
## License: WTFPL:
## 0. You just DO WHAT THE FUCK YOU WANT TO.
use strict;
diff --git a/scripts/checkopts.pl b/scripts/checkopts.pl
index 3a4b884..e5779ca 100755
--- a/scripts/checkopts.pl
+++ b/scripts/checkopts.pl
@@ -1,5 +1,5 @@
#!/usr/bin/env perl
-## Copyright © 2010 by Daniel Friesel <derf@finalrewind.org>
+## Copyright © 2010 by Birte Kristina Friesel <derf@finalrewind.org>
## License: WTFPL <http://sam.zoy.org/wtfpl>
use strict;
use warnings;
diff --git a/share/applications/feh.pre b/share/applications/feh.pre
index fe23468..8007630 100644
--- a/share/applications/feh.pre
+++ b/share/applications/feh.pre
@@ -9,5 +9,5 @@ Terminal=false
Type=Application
Icon=feh
Categories=Graphics;2DGraphics;Viewer;
-MimeType=image/bmp;image/gif;image/jpeg;image/jpg;image/pjpeg;image/png;image/tiff;image/webp;image/x-bmp;image/x-pcx;image/x-png;image/x-portable-anymap;image/x-portable-bitmap;image/x-portable-graymap;image/x-portable-pixmap;image/x-tga;image/x-xbitmap;
+MimeType=image/bmp;image/gif;image/jpeg;image/jpg;image/pjpeg;image/png;image/tiff;image/webp;image/x-bmp;image/x-pcx;image/x-png;image/x-portable-anymap;image/x-portable-bitmap;image/x-portable-graymap;image/x-portable-pixmap;image/x-tga;image/x-xbitmap;image/heic;
NoDisplay=true
diff --git a/src/Makefile b/src/Makefile
index 10e33eb..2968671 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -4,8 +4,6 @@ TARGETS = \
events.c \
feh_png.c \
filelist.c \
- getopt.c \
- getopt1.c \
gib_hash.c \
gib_imlib.c \
gib_list.c \
diff --git a/src/debug.h b/src/debug.h
index 569637e..0ff1447 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -1,7 +1,7 @@
/* debug.h
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina 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/events.c b/src/events.c
index c44ebf4..de9e7b3 100644
--- a/src/events.c
+++ b/src/events.c
@@ -1,7 +1,7 @@
/* events.c
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -85,6 +85,15 @@ static void feh_set_parse_bb_partial(fehkey *button, char *binding)
button->button = atoi(cur);
button->state = mod;
+
+ if (button->button == 0) {
+ /*
+ * Mod3 is unused on today's keyboards. If Mod3 is unset and button==0,
+ * we are dealing with an uninitialized or unset binding. If Mod3 is set
+ * and button==0, it refers to mouse movement.
+ */
+ button->state |= Mod3Mask;
+ }
}
/*
@@ -255,7 +264,7 @@ static void feh_event_handle_ButtonPress(XEvent * ev)
- winwid->im_y) / winwid->old_zoom;
/* copied from zoom_in, keyevents.c */
- winwid->zoom = winwid->zoom * 1.25;
+ winwid->zoom = winwid->zoom * opt.zoom_rate;
if (winwid->zoom > ZOOM_MAX)
winwid->zoom = ZOOM_MAX;
@@ -283,7 +292,7 @@ static void feh_event_handle_ButtonPress(XEvent * ev)
- winwid->im_y) / winwid->old_zoom;
/* copied from zoom_out, keyevents.c */
- winwid->zoom = winwid->zoom * 0.80;
+ winwid->zoom = winwid->zoom / opt.zoom_rate;
if (winwid->zoom < ZOOM_MIN)
winwid->zoom = ZOOM_MIN;
@@ -672,14 +681,18 @@ static void feh_event_handle_MotionNotify(XEvent * ev)
} else {
while (XCheckTypedWindowEvent(disp, ev->xmotion.window, MotionNotify, ev));
winwid = winwidget_get_from_window(ev->xmotion.window);
- if ((winwid != NULL) && (winwid->type == WIN_TYPE_THUMBNAIL)) {
- feh_thumbnail *thumbnail;
- int x, y;
-
- x = (ev->xbutton.x - winwid->im_x) / winwid->zoom;
- y = (ev->xbutton.y - winwid->im_y) / winwid->zoom;
- thumbnail = feh_thumbnail_get_thumbnail_from_coords(x, y);
- feh_thumbnail_select(winwid, thumbnail);
+ if (winwid != NULL) {
+ if (winwid->type == WIN_TYPE_THUMBNAIL) {
+ feh_thumbnail *thumbnail;
+ int x, y;
+
+ x = (ev->xbutton.x - winwid->im_x) / winwid->zoom;
+ y = (ev->xbutton.y - winwid->im_y) / winwid->zoom;
+ thumbnail = feh_thumbnail_get_thumbnail_from_coords(x, y);
+ feh_thumbnail_select(winwid, thumbnail);
+ } else {
+ feh_event_handle_generic(winwid, ev->xmotion.state | Mod3Mask, NoSymbol, 0);
+ }
}
}
return;
diff --git a/src/exif.c b/src/exif.c
index 9ad9dae..6b0719d 100644
--- a/src/exif.c
+++ b/src/exif.c
@@ -1,6 +1,7 @@
/* exif.c
Copyright (C) 2012 Dennis Real.
+Copyright (C) 2021 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -42,199 +43,302 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/* remove all spaces on the right end of a string */
void exif_trim_spaces(char *str)
{
- char *end;
-
- for (end = str; *str!='\0'; str++)
- {
- if (*str != ' ')
- {
- end = str + 1;
- }
- }
- *end = '\0';
+ char *end;
+
+ for (end = str; *str != '\0'; str++) {
+ if (*str != ' ') {
+ end = str + 1;
+ }
+ }
+ *end = '\0';
}
/* show given exif tag content with tag name */
-void exif_get_tag(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize)
+void exif_get_tag(ExifData * d, ExifIfd ifd, ExifTag tag, char *buffer,
+ unsigned int maxsize)
{
- char s[EXIF_MAX_DATA];
- ExifEntry *entry = NULL;
-
- if ( (d != NULL) && (buffer != NULL) && (maxsize > 0) )
- {
- entry = exif_content_get_entry(d->ifd[ifd], tag);
- if (entry != NULL)
- {
- /* Get the contents of the tag in human-readable form */
- exif_entry_get_value(entry, s, EXIF_MAX_DATA);
-
- /* Don't bother printing it if it's entirely blank */
- exif_trim_spaces(s);
- if (*s != '\0')
- {
- D(("%s: %s\n", exif_tag_get_name_in_ifd(tag,ifd), s));
- snprintf(buffer, (size_t)maxsize, "%s: %s\n", exif_tag_get_name_in_ifd(tag,ifd), s);
- }
- }
- }
+ char s[EXIF_MAX_DATA];
+ ExifEntry *entry = NULL;
+
+ if ((d != NULL) && (buffer != NULL) && (maxsize > 0)) {
+ entry = exif_content_get_entry(d->ifd[ifd], tag);
+ if (entry != NULL) {
+ /* Get the contents of the tag in human-readable form */
+ exif_entry_get_value(entry, s, EXIF_MAX_DATA);
+
+ /* Don't bother printing it if it's entirely blank */
+ exif_trim_spaces(s);
+ if (*s != '\0') {
+ D(("%s: %s\n",
+ exif_tag_get_name_in_ifd(tag, ifd), s));
+ snprintf(buffer, (size_t) maxsize,
+ "%s: %s\n",
+ exif_tag_get_name_in_ifd(tag,
+ ifd), s);
+ }
+ }
+ }
}
/* show given exif tag content without tag name */
-void exif_get_tag_content(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize)
+void exif_get_tag_content(ExifData * d, ExifIfd ifd, ExifTag tag,
+ char *buffer, unsigned int maxsize)
{
- char s[EXIF_MAX_DATA];
- ExifEntry *entry = NULL;
-
- if ( (d != NULL) && (buffer != NULL) && (maxsize > 0) )
- {
- entry = exif_content_get_entry(d->ifd[ifd], tag);
- if (entry != NULL)
- {
- /* Get the contents of the tag in human-readable form */
- exif_entry_get_value(entry, s, EXIF_MAX_DATA);
-
- /* Don't bother printing it if it's entirely blank */
- exif_trim_spaces(s);
- if (*s != '\0')
- {
- D(("%s - %s\n", exif_tag_get_name_in_ifd(tag,ifd), s));
- snprintf(buffer, (size_t)maxsize, "%s", s);
- }
- }
- }
+ char s[EXIF_MAX_DATA];
+ ExifEntry *entry = NULL;
+
+ if ((d != NULL) && (buffer != NULL) && (maxsize > 0)) {
+ entry = exif_content_get_entry(d->ifd[ifd], tag);
+ if (entry != NULL) {
+ /* Get the contents of the tag in human-readable form */
+ exif_entry_get_value(entry, s, EXIF_MAX_DATA);
+
+ /* Don't bother printing it if it's entirely blank */
+ exif_trim_spaces(s);
+ if (*s != '\0') {
+ D(("%s - %s\n",
+ exif_tag_get_name_in_ifd(tag, ifd), s));
+ snprintf(buffer, (size_t) maxsize, "%s",
+ s);
+ }
+ }
+ }
}
/* Show the given MakerNote tag if it exists */
-void exif_get_mnote_tag(ExifData *d, unsigned int tag, char* buffer, unsigned int maxsize)
+void exif_get_mnote_tag(ExifData * d, unsigned int tag, char *buffer,
+ unsigned int maxsize)
{
- ExifMnoteData *mn = NULL;
- int i, num;
- char buf[1024];
-
- if ( (d!=NULL) && (buffer!=NULL) && (maxsize > 0) )
- {
- mn = exif_data_get_mnote_data(d);
- }
- else
- {
- return;
- }
-
- if ( mn != NULL )
- {
- num = exif_mnote_data_count(mn);
-
- /* Loop through all MakerNote tags, searching for the desired one */
- for (i=0; i < num; ++i)
- {
- D(("%d/%d %d 0x%2x %s; %s\n", i, num, exif_mnote_data_get_id(mn, i),
- exif_mnote_data_get_id(mn, i),
- exif_mnote_data_get_name(mn,i),
- exif_mnote_data_get_title(mn, i) ));
-
- if (exif_mnote_data_get_id(mn, i) == tag)
- {
- if (exif_mnote_data_get_value(mn, i, buf, sizeof(buf)))
- {
- /* Don't bother printing it if it's entirely blank */
- exif_trim_spaces(buf);
- if (*buf != '\0')
- {
- D(("%s\n", buf));
- snprintf(buffer, (size_t)maxsize, "%s: %s\n", exif_mnote_data_get_title(mn, i), buf);
- }
- }
- }
- }
- }
+ ExifMnoteData *mn = NULL;
+ int i, num;
+ char buf[1024];
+
+ if ((d != NULL) && (buffer != NULL) && (maxsize > 0)) {
+ mn = exif_data_get_mnote_data(d);
+ } else {
+ return;
+ }
+
+ if (mn != NULL) {
+ num = exif_mnote_data_count(mn);
+
+ /* Loop through all MakerNote tags, searching for the desired one */
+ for (i = 0; i < num; ++i) {
+ D(("%d/%d %d 0x%2x %s; %s\n", i, num,
+ exif_mnote_data_get_id(mn, i),
+ exif_mnote_data_get_id(mn, i),
+ exif_mnote_data_get_name(mn, i),
+ exif_mnote_data_get_title(mn, i)));
+
+ if (exif_mnote_data_get_id(mn, i) == tag) {
+ if (exif_mnote_data_get_value
+ (mn, i, buf, sizeof(buf))) {
+ /* Don't bother printing it if it's entirely blank */
+ exif_trim_spaces(buf);
+ if (*buf != '\0') {
+ D(("%s\n", buf));
+ snprintf(buffer,
+ (size_t) maxsize,
+ "%s: %s\n",
+ exif_mnote_data_get_title
+ (mn, i), buf);
+ }
+ }
+ }
+ }
+ }
}
+void exif_get_make_model_lens(ExifData * ed, char *buffer, unsigned int maxsize)
+{
+ char make[EXIF_STD_BUF_LEN];
+ char model[EXIF_STD_BUF_LEN];
+ char lens[EXIF_STD_BUF_LEN];
+ unsigned int offset = 0;
+
+ make[0] = model[0] = lens[0] = '\0';
+
+ exif_get_tag_content(ed, EXIF_IFD_0, EXIF_TAG_MAKE, make, sizeof(make));
+ exif_get_tag_content(ed, EXIF_IFD_0, EXIF_TAG_MODEL, model, sizeof(model));
+ exif_get_tag_content(ed, EXIF_IFD_EXIF, 0xa434, lens, sizeof(lens));
+
+ if (make[0] && strncmp(make, model, strlen(make)) != 0) {
+ offset += snprintf(buffer, maxsize, "%s ", make);
+ }
+ if (model[0]) {
+ offset += snprintf(buffer + offset, maxsize - offset, "%s", model);
+ }
+ if (lens[0]) {
+ offset += snprintf(buffer + offset, maxsize - offset, " + %s", lens);
+ }
+ snprintf(buffer + offset, maxsize - offset, "\n");
+}
+
+void exif_get_exposure(ExifData * ed, char *buffer, unsigned int maxsize)
+{
+ char fnumber[EXIF_STD_BUF_LEN];
+ char exposure[EXIF_STD_BUF_LEN];
+ char iso[EXIF_STD_BUF_LEN];
+ char focus[EXIF_STD_BUF_LEN];
+ char focus35[EXIF_STD_BUF_LEN];
+ unsigned int offset = 0;
+
+ fnumber[0] = exposure[0] = iso[0] = '\0';
+ focus[0] = focus35[0] = '\0';
+
+ exif_get_tag_content(ed, EXIF_IFD_EXIF, EXIF_TAG_FNUMBER, fnumber, sizeof(fnumber));
+ exif_get_tag_content(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_TIME, exposure, sizeof(exposure));
+ exif_get_tag_content(ed, EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS, iso, sizeof(iso));
+ exif_get_tag_content(ed, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH, focus, sizeof(focus));
+ exif_get_tag_content(ed, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM, focus35, sizeof(focus35));
+
+ if (fnumber[0] || exposure[0]) {
+ offset += snprintf(buffer, maxsize, "%s %s ", fnumber, exposure);
+ }
+ if (iso[0]) {
+ offset += snprintf(buffer + offset, maxsize - offset, "ISO%s ", iso);
+ }
+ if (focus[0] && focus35[0]) {
+ snprintf(buffer + offset, maxsize - offset, "%s (%s mm)\n", focus, focus35);
+ } else if (focus[0]) {
+ snprintf(buffer + offset, maxsize - offset, "%s\n", focus);
+ }
+}
+
+void exif_get_flash(ExifData * ed, char *buffer, unsigned int maxsize)
+{
+ char flash[EXIF_STD_BUF_LEN];
+
+ flash[0] = '\0';
+
+ exif_get_tag_content(ed, EXIF_IFD_EXIF, EXIF_TAG_FLASH, flash, sizeof(flash));
+
+ if (flash[0]) {
+ snprintf(buffer, maxsize, "%s\n", flash);
+ }
+}
+
+void exif_get_mode(ExifData * ed, char *buffer, unsigned int maxsize)
+{
+ char mode[EXIF_STD_BUF_LEN];
+ char program[EXIF_STD_BUF_LEN];
+
+ mode[0] = program[0] = '\0';
+
+ exif_get_tag_content(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_MODE, mode, sizeof(mode));
+ exif_get_tag_content(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_PROGRAM, program, sizeof(program));
+
+ if (mode[0] || program[0]) {
+ snprintf(buffer, maxsize, "%s (%s)\n", mode, program);
+ }
+}
+
+void exif_get_datetime(ExifData * ed, char *buffer, unsigned int maxsize)
+{
+ char datetime[EXIF_STD_BUF_LEN];
+
+ datetime[0] = '\0';
+
+ exif_get_tag_content(ed, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_ORIGINAL, datetime, sizeof(datetime));
+
+ if (datetime[0]) {
+ snprintf(buffer, maxsize, "%s\n", datetime);
+ }
+}
+
+void exif_get_description(ExifData * ed, char *buffer, unsigned int maxsize)
+{
+ char description[EXIF_STD_BUF_LEN];
+
+ description[0] = '\0';
+
+ exif_get_tag_content(ed, EXIF_IFD_0, EXIF_TAG_IMAGE_DESCRIPTION, description, sizeof(description));
+
+ if (description[0]) {
+ snprintf(buffer, maxsize, "\"%s\"\n", description);
+ }
+}
/* get gps coordinates if available */
void exif_get_gps_coords(ExifData * ed, char *buffer, unsigned int maxsize)
{
- char buf[EXIF_STD_BUF_LEN];
-
- buf[0] = '\0';
- exif_get_tag_content(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE_REF, buf, sizeof(buf));
- if ( buf[0] != '\0' )
- {
- snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), "GPS: %s ", buf);
- }
- else
- {
- return;
- }
-
- buf[0] = '\0';
- exif_get_tag_content(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE, buf, sizeof(buf));
- if ( buf[0] != '\0' )
- {
- snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), "%s ", buf);
- }
- else
- {
- return;
- }
-
- buf[0] = '\0';
- exif_get_tag_content(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE_REF, buf, sizeof(buf));
- if ( buf[0] != '\0' )
- {
- snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), ", %s ", buf);
- }
- else
- {
- return;
- }
-
- buf[0] = '\0';
- exif_get_tag_content(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE, buf, sizeof(buf));
- if ( buf[0] != '\0' )
- {
- snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), "%s ", buf);
- }
- else
- {
- return;
- }
-
- buf[0] = '\0';
- exif_get_tag_content(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_MAP_DATUM, buf, sizeof(buf));
- if ( buf[0] != '\0' )
- {
- snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), "(%s)\n", buf);
- }
- else
- {
- return;
- }
+ char buf[EXIF_STD_BUF_LEN];
+
+ buf[0] = '\0';
+ exif_get_tag_content(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE_REF,
+ buf, sizeof(buf));
+ if (buf[0] != '\0') {
+ snprintf(buffer + strlen(buffer), maxsize - strlen(buffer),
+ "GPS: %s ", buf);
+ } else {
+ return;
+ }
+
+ buf[0] = '\0';
+ exif_get_tag_content(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE, buf,
+ sizeof(buf));
+ if (buf[0] != '\0') {
+ snprintf(buffer + strlen(buffer), maxsize - strlen(buffer),
+ "%s ", buf);
+ } else {
+ return;
+ }
+
+ buf[0] = '\0';
+ exif_get_tag_content(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE_REF,
+ buf, sizeof(buf));
+ if (buf[0] != '\0') {
+ snprintf(buffer + strlen(buffer), maxsize - strlen(buffer),
+ ", %s ", buf);
+ } else {
+ return;
+ }
+
+ buf[0] = '\0';
+ exif_get_tag_content(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE, buf,
+ sizeof(buf));
+ if (buf[0] != '\0') {
+ snprintf(buffer + strlen(buffer), maxsize - strlen(buffer),
+ "%s ", buf);
+ } else {
+ return;
+ }
+
+ buf[0] = '\0';
+ exif_get_tag_content(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_MAP_DATUM, buf,
+ sizeof(buf));
+ if (buf[0] != '\0') {
+ snprintf(buffer + strlen(buffer), maxsize - strlen(buffer),
+ "(%s)\n", buf);
+ } else {
+ return;
+ }
}
/* return data structure with exif data if available */
-ExifData * exif_get_data(char *path)
+ExifData *exif_get_data(char *path)
{
- ExifData *ed = NULL;
+ ExifData *ed = NULL;
- /* Load an ExifData object from an EXIF file */
- ed = exif_data_new_from_file(path);
- if (ed == NULL)
- {
- D(("File not readable or no Exif data present in %s\n", path));
- }
+ /* Load an ExifData object from an EXIF file */
+ ed = exif_data_new_from_file(path);
+ if (ed == NULL) {
+ D(("File not readable or no Exif data present in %s\n",
+ path));
+ }
- return(ed);
+ return (ed);
}
@@ -243,76 +347,93 @@ ExifData * exif_get_data(char *path)
/* get all exif data in readable form */
void exif_get_info(ExifData * ed, char *buffer, unsigned int maxsize)
{
- ExifEntry *entry = NULL;
- char buf[EXIF_STD_BUF_LEN];
- unsigned short int i = 0;
-
- if ( (buffer == NULL) || (maxsize == 0) )
- {
- return;
- }
- else if (ed == NULL)
- {
- snprintf(buffer, (size_t)maxsize, "%s\n", "No Exif data in file.");
- return;
- }
- else
- {
- /* show normal exif tags. list must be defined in exif_cfg.h */
- while ( (i < USHRT_MAX) && (Exif_tag_list[i].ifd != EXIF_IFD_COUNT) )
- {
- exif_get_tag(ed, Exif_tag_list[i].ifd, Exif_tag_list[i].tag, buffer + strlen(buffer), maxsize - strlen(buffer));
- i++;
- }
-
- /* show vendor specific makernote tags */
- entry = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE);
- if (entry != NULL)
- {
-
- if (exif_entry_get_value(entry, buf, sizeof(buf)))
- {
- exif_trim_spaces(buf);
-
- if ( (strcmp(buf, "NIKON CORPORATION") == 0)
- || (strcmp(buf, "Nikon") == 0)
- || (strcmp(buf, "NIKON") == 0)
- )
- {
- /* show nikon makernote exif tags. list must be defined in exif_cfg.h */
- i=0;
- while ( (i < USHRT_MAX) && (Exif_makernote_nikon_tag_list[i] != EXIF_NIKON_MAKERNOTE_END) )
- {
- exn_get_mnote_nikon_tags(ed, Exif_makernote_nikon_tag_list[i],
- buffer + strlen(buffer), maxsize - strlen(buffer));
- i++;
- }
-
- }
- else if ( (strcmp(buf, "Canon") == 0) )
- {
- /* show canon makernote exif tags. list must be defined in exif_cfg.h */
- i=0;
- while ( (i < USHRT_MAX) && (Exif_makernote_canon_tag_list[i] != EXIF_CANON_MAKERNOTE_END) )
- {
- exc_get_mnote_canon_tags(ed, Exif_makernote_canon_tag_list[i],
- buffer + strlen(buffer), maxsize - strlen(buffer));
- i++;
- }
-
- }
- else
- {
- }
- }
-
- }
-
- /* show gps coordinates */
- exif_get_gps_coords(ed, buffer + strlen(buffer), maxsize - strlen(buffer));
-
- }
-
+ ExifEntry *entry = NULL;
+ char buf[EXIF_STD_BUF_LEN];
+ unsigned short int i = 0;
+
+ if ((buffer == NULL) || (maxsize == 0)) {
+ return;
+ } else if (ed == NULL) {
+ snprintf(buffer, (size_t) maxsize, "%s\n",
+ "No Exif data in file.");
+ return;
+ }
+
+ exif_get_description(ed, buffer + strlen(buffer),
+ maxsize - strlen(buffer));
+ exif_get_make_model_lens(ed, buffer + strlen(buffer),
+ maxsize - strlen(buffer));
+ exif_get_exposure(ed, buffer + strlen(buffer),
+ maxsize - strlen(buffer));
+ exif_get_mode(ed, buffer + strlen(buffer),
+ maxsize - strlen(buffer));
+ exif_get_flash(ed, buffer + strlen(buffer),
+ maxsize - strlen(buffer));
+ exif_get_datetime(ed, buffer + strlen(buffer),
+ maxsize - strlen(buffer));
+
+ /* show vendor specific makernote tags */
+ entry =
+ exif_content_get_entry(ed->ifd[EXIF_IFD_0],
+ EXIF_TAG_MAKE);
+ if (entry != NULL) {
+
+ if (exif_entry_get_value(entry, buf, sizeof(buf))) {
+ exif_trim_spaces(buf);
+
+ if ((strcmp(buf, "NIKON CORPORATION") == 0)
+ || (strcmp(buf, "Nikon") == 0)
+ || (strcmp(buf, "NIKON") == 0)
+ ) {
+ /* show nikon makernote exif tags. list must be defined in exif_cfg.h */
+ i = 0;
+ while ((i < USHRT_MAX)
+ &&
+ (Exif_makernote_nikon_tag_list
+ [i] !=
+ EXIF_NIKON_MAKERNOTE_END))
+ {
+ exn_get_mnote_nikon_tags
+ (ed,
+ Exif_makernote_nikon_tag_list
+ [i],
+ buffer +
+ strlen(buffer),
+ maxsize -
+ strlen(buffer));
+ i++;
+ }
+
+ } else if ((strcmp(buf, "Canon") == 0)) {
+ /* show canon makernote exif tags. list must be defined in exif_cfg.h */
+ i = 0;
+ while ((i < USHRT_MAX)
+ &&
+ (Exif_makernote_canon_tag_list
+ [i] !=
+ EXIF_CANON_MAKERNOTE_END))
+ {
+ exc_get_mnote_canon_tags
+ (ed,
+ Exif_makernote_canon_tag_list
+ [i],
+ buffer +
+ strlen(buffer),
+ maxsize -
+ strlen(buffer));
+ i++;
+ }
+
+ } else {
+ }
+ }
+
+ }
+
+ /* show gps coordinates */
+ exif_get_gps_coords(ed, buffer + strlen(buffer),
+ maxsize - strlen(buffer));
+
}
#endif
diff --git a/src/exif.h b/src/exif.h
index 79187f4..41769c0 100644
--- a/src/exif.h
+++ b/src/exif.h
@@ -32,11 +32,16 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define EXIF_STD_BUF_LEN 128
extern void exif_trim_spaces(char *str);
-extern void exif_get_tag(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize);
-extern void exif_get_tag_content(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize);
-extern void exif_get_mnote_tag(ExifData *d, unsigned int tag, char* buffer, unsigned int maxsize);
-extern void exif_get_gps_coords(ExifData * ed, char *buffer, unsigned int maxsize);
-extern ExifData * exif_get_data(char *path);
-extern void exif_get_info(ExifData * ed, char *buffer, unsigned int maxsize);
+extern void exif_get_tag(ExifData * d, ExifIfd ifd, ExifTag tag,
+ char *buffer, unsigned int maxsize);
+extern void exif_get_tag_content(ExifData * d, ExifIfd ifd, ExifTag tag,
+ char *buffer, unsigned int maxsize);
+extern void exif_get_mnote_tag(ExifData * d, unsigned int tag,
+ char *buffer, unsigned int maxsize);
+extern void exif_get_gps_coords(ExifData * ed, char *buffer,
+ unsigned int maxsize);
+extern ExifData *exif_get_data(char *path);
+extern void exif_get_info(ExifData * ed, char *buffer,
+ unsigned int maxsize);
#endif
diff --git a/src/exif_canon.c b/src/exif_canon.c
index 8801899..ee72164 100644
--- a/src/exif_canon.c
+++ b/src/exif_canon.c
@@ -36,26 +36,26 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/* get interesting canon maker note tags in readable form */
-void exc_get_mnote_canon_tags(ExifData *ed, unsigned int tag, char * buffer, unsigned int maxsize)
+void exc_get_mnote_canon_tags(ExifData * ed, unsigned int tag,
+ char *buffer, unsigned int maxsize)
{
- /* char buf[EXIF_STD_BUF_LEN];
+ /* char buf[EXIF_STD_BUF_LEN];
- buf[0] = '\0';
- exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_FLASH, buf, sizeof(buf));
- exif_trim_spaces(buf); */
+ buf[0] = '\0';
+ exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_FLASH, buf, sizeof(buf));
+ exif_trim_spaces(buf); */
- switch(tag)
- {
- default:
- {
- /* normal makernote tags without special treatment */
- exif_get_mnote_tag(ed, tag, buffer, maxsize);
- }
- break;
- }
+ switch (tag) {
+ default:
+ {
+ /* normal makernote tags without special treatment */
+ exif_get_mnote_tag(ed, tag, buffer, maxsize);
+ }
+ break;
+ }
- return;
+ return;
}
#endif
diff --git a/src/exif_canon.h b/src/exif_canon.h
index d8682c3..58ecc0e 100644
--- a/src/exif_canon.h
+++ b/src/exif_canon.h
@@ -28,6 +28,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <libexif/exif-data.h>
-extern void exc_get_mnote_canon_tags(ExifData *ed, unsigned int tag, char * buffer, unsigned int maxsize);
+extern void exc_get_mnote_canon_tags(ExifData * ed, unsigned int tag,
+ char *buffer, unsigned int maxsize);
#endif
diff --git a/src/exif_cfg.h b/src/exif_cfg.h
index a961147..0a13fa3 100644
--- a/src/exif_cfg.h
+++ b/src/exif_cfg.h
@@ -28,78 +28,43 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <libexif/exif-data.h>
-typedef struct
-{
- ExifIfd ifd; /* section */
- ExifTag tag; /* tag */
-} t_EXIF_INFO;
-
-
-/* show these standard tags. section must be given first, than the tag itself */
-/* definition: http://libexif.sourceforge.net/api/exif-tag_8h.html */
-const t_EXIF_INFO Exif_tag_list [] =
-{
- {EXIF_IFD_0, EXIF_TAG_MAKE},
- {EXIF_IFD_0, EXIF_TAG_MODEL},
- {EXIF_IFD_0, EXIF_TAG_IMAGE_DESCRIPTION},
- {EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_ORIGINAL},
- {EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_TIME},
- {EXIF_IFD_EXIF, EXIF_TAG_SHUTTER_SPEED_VALUE},
- {EXIF_IFD_EXIF, EXIF_TAG_FNUMBER},
- {EXIF_IFD_EXIF, EXIF_TAG_APERTURE_VALUE},
- {EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_BIAS_VALUE},
- {EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS},
- {EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH},
- {EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM},
- {EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_MODE},
- {EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_PROGRAM},
- {EXIF_IFD_EXIF, EXIF_TAG_SCENE_CAPTURE_TYPE},
- {EXIF_IFD_EXIF, EXIF_TAG_FLASH},
-
- {EXIF_IFD_COUNT, 0} /* end marker */
-};
+/* Nikon */
+#define EXIF_NIKON_MAKERNOTE_END 0 /* end marker: if 0 used as a tag we must find something else */
+/* show these nikon makernote tags */
+const unsigned int Exif_makernote_nikon_tag_list[] = {
-/* Nikon */
+ 6,
+ 8, /* Flash Setting */
+ 9, /* Flash Mode */
+ 135, /* Flash used */
+ 18, /* Flash Exposure Comp */
+ 168, /* Flash info: control mode */
-#define EXIF_NIKON_MAKERNOTE_END 0 /* end marker: if 0 used as a tag we must find something else */
+ 2, /* ISO. Has some more info than EXIF_TAG_ISO_SPEED_RATINGS but also fails on Lo.1 */
+ 5, /* White Balance */
+ 132, /* Lens */
+ 171, /* Digital Vari-Program */
+ 34, /* Active D-Lighting */
-/* show these nikon makernote tags */
-const unsigned int Exif_makernote_nikon_tag_list [] =
-{
-
- 6,
- 8, /* Flash Setting */
- 9, /* Flash Mode */
- 135, /* Flash used */
- 18, /* Flash Exposure Comp */
- 168, /* Flash info: control mode */
-
- 2, /* ISO. Has some more info than EXIF_TAG_ISO_SPEED_RATINGS but also fails on Lo.1 */
- 5, /* White Balance */
- 132, /* Lens */
- 171, /* Digital Vari-Program */
- 34, /* Active D-Lighting */
-
- 35, /* PictureControlData */
- 183, /* AFInfo2 */
-
- EXIF_NIKON_MAKERNOTE_END /* end marker */
+ 35, /* PictureControlData */
+ 183, /* AFInfo2 */
+
+ EXIF_NIKON_MAKERNOTE_END /* end marker */
};
/* Canon */
-#define EXIF_CANON_MAKERNOTE_END 0xFFFF /* end marker: if this is used as a tag we must find something else */
+#define EXIF_CANON_MAKERNOTE_END 0xFFFF /* end marker: if this is used as a tag we must find something else */
/* show these canon makernote tags */
-const unsigned int Exif_makernote_canon_tag_list [] =
-{
- 8, /* Image Number */
- 9, /* Owner Name */
-
- EXIF_CANON_MAKERNOTE_END /* end marker */
+const unsigned int Exif_makernote_canon_tag_list[] = {
+ 8, /* Image Number */
+ 9, /* Owner Name */
+
+ EXIF_CANON_MAKERNOTE_END /* end marker */
};
diff --git a/src/exif_nikon.c b/src/exif_nikon.c
index c058d8c..a81f290 100644
--- a/src/exif_nikon.c
+++ b/src/exif_nikon.c
@@ -37,12 +37,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/* Flash control mode */
/* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#FlashControlMode */
#define EXN_FLASH_CONTROL_MODES_MAX 9
-char *EXN_NikonFlashControlModeValues[EXN_FLASH_CONTROL_MODES_MAX] = {"Off",
- "iTTL-BL", "iTTL", "Auto Aperture",
- "Automatic", "GN (distance priority)",
- "Manual", "Repeating Flash",
- "N/A" /* "N/A" is not a nikon setting */
- };
+char *EXN_NikonFlashControlModeValues[EXN_FLASH_CONTROL_MODES_MAX] =
+ { "Off",
+ "iTTL-BL", "iTTL", "Auto Aperture",
+ "Automatic", "GN (distance priority)",
+ "Manual", "Repeating Flash",
+ "N/A" /* "N/A" is not a nikon setting */
+};
#define EXN_FLASH_CONTROL_MODE_MASK 0x7F
@@ -50,280 +51,302 @@ char *EXN_NikonFlashControlModeValues[EXN_FLASH_CONTROL_MODES_MAX] = {"Off",
/* AFInfo2 */
/* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#AFInfo2 */
#define EXN_CONTRAST_DETECT_AF_MAX 2
-char *EXN_NikonContrastDetectAF[EXN_CONTRAST_DETECT_AF_MAX] = {"Off", "On"};
+char *EXN_NikonContrastDetectAF[EXN_CONTRAST_DETECT_AF_MAX] =
+ { "Off", "On" };
/* AFArea Mode for ContrastDetectAF Off */
#define EXN_AF_AREA_MODE_P_MAX 13
char *EXN_NikonAFAreaModePhase[EXN_AF_AREA_MODE_P_MAX] = {
- "Single Area", "Dynamic Area", "Dynamic Area (closest subject)",
- "Group Dynamic ", "Dynamic Area (9 points) ", "Dynamic Area (21 points)",
- "Dynamic Area (51 points) ", "Dynamic Area (51 points, 3D-tracking)",
- "Auto-area", "Dynamic Area (3D-tracking)", "Single Area (wide)",
- "Dynamic Area (wide)", "Dynamic Area (wide, 3D-tracking)"};
+ "Single Area", "Dynamic Area", "Dynamic Area (closest subject)",
+ "Group Dynamic ", "Dynamic Area (9 points) ",
+ "Dynamic Area (21 points)",
+ "Dynamic Area (51 points) ",
+ "Dynamic Area (51 points, 3D-tracking)",
+ "Auto-area", "Dynamic Area (3D-tracking)", "Single Area (wide)",
+ "Dynamic Area (wide)", "Dynamic Area (wide, 3D-tracking)"
+};
/* AFArea Mode for ContrastDetectAF On */
#define EXN_AF_AREA_MODE_C_MAX 5
char *EXN_NikonAFAreaModeContr[EXN_AF_AREA_MODE_C_MAX] = {
- "Contrast-detect",
- "Contrast-detect (normal area)",
- "Contrast-detect (wide area)",
- "Contrast-detect (face priority)",
- "Contrast-detect (subject tracking)"};
+ "Contrast-detect",
+ "Contrast-detect (normal area)",
+ "Contrast-detect (wide area)",
+ "Contrast-detect (face priority)",
+ "Contrast-detect (subject tracking)"
+};
#define EXN_PHASE_DETECT_AF_MAX 4
-char *EXN_NikonPhaseDetectAF[EXN_PHASE_DETECT_AF_MAX] = {"Off", "On (51-point)",
- "On (11-point)", "On (39-point)"};
+char *EXN_NikonPhaseDetectAF[EXN_PHASE_DETECT_AF_MAX] =
+ { "Off", "On (51-point)",
+ "On (11-point)", "On (39-point)"
+};
/* PrimaryAFPoint and AFPointsUsed only valid with PhaseDetectAF == On */
#define EXN_PRIM_AF_PT_51_MAX 52
-char * EXN_Prim_AF_Pt_51[EXN_PRIM_AF_PT_51_MAX] = {"(none)", "C6 (Center)", "B6", "A5",
- "D6", "E5", "C7", "B7", "A6", "D7", "E6", "C5", "B5", "A4", "D5", "E4", "C8", "B8",
- "A7", "D8", "E7", "C9", "B9", "A8", "D9", "E8", "C10", "B10", "A9", "D10", "E9",
- "C11", "B11", "D11", "C4", "B4", "A3", "D4", "E3", "C3", "B3", "A2", "D3", "E2",
- "C2", "B2", "A1", "D2", "E1", "C1", "B1", "D1"};
-
+char *EXN_Prim_AF_Pt_51[EXN_PRIM_AF_PT_51_MAX] =
+ { "(none)", "C6 (Center)", "B6", "A5",
+ "D6", "E5", "C7", "B7", "A6", "D7", "E6", "C5", "B5", "A4", "D5",
+ "E4", "C8", "B8",
+ "A7", "D8", "E7", "C9", "B9", "A8", "D9", "E8", "C10", "B10", "A9",
+ "D10", "E9",
+ "C11", "B11", "D11", "C4", "B4", "A3", "D4", "E3", "C3", "B3",
+ "A2", "D3", "E2",
+ "C2", "B2", "A1", "D2", "E1", "C1", "B1", "D1"
+};
+
#define EXN_PRIM_AF_PT_11_MAX 12
-char * EXN_Prim_AF_Pt_11[EXN_PRIM_AF_PT_11_MAX] = {"(none)", "Center", "Top", "Bottom",
- "Mid-left", "Upper-left", "Lower-left", "Far Left", "Mid-right", "Upper-right",
- "Lower-right", "Far Right"};
+char *EXN_Prim_AF_Pt_11[EXN_PRIM_AF_PT_11_MAX] =
+ { "(none)", "Center", "Top", "Bottom",
+ "Mid-left", "Upper-left", "Lower-left", "Far Left", "Mid-right",
+ "Upper-right",
+ "Lower-right", "Far Right"
+};
#define EXN_PRIM_AF_PT_39_MAX 40
-char * EXN_Prim_AF_Pt_39[EXN_PRIM_AF_PT_39_MAX] = {"(none)", "C6 (Center)", "B6", "A2",
- "D6", "E2", "C7", "B7", "A3", "D7", "E3", "C5", "B5", "A1", "D5", "E1", "C8", "B8",
- "D8", "C9", "B9", "D9", "C10", "B10", "D10", "C11", "B11", "D11", "C4", "B4", "D4",
- "C3", "B3", "D3", "C2", "B2", "D2", "C1", "B1", "D1"};
+char *EXN_Prim_AF_Pt_39[EXN_PRIM_AF_PT_39_MAX] =
+ { "(none)", "C6 (Center)", "B6", "A2",
+ "D6", "E2", "C7", "B7", "A3", "D7", "E3", "C5", "B5", "A1", "D5",
+ "E1", "C8", "B8",
+ "D8", "C9", "B9", "D9", "C10", "B10", "D10", "C11", "B11", "D11",
+ "C4", "B4", "D4",
+ "C3", "B3", "D3", "C2", "B2", "D2", "C1", "B1", "D1"
+};
#define EXN_PIC_CTRL_ADJ_MAX 3
-char * EXN_Pic_Ctrl_Adj[EXN_PIC_CTRL_ADJ_MAX] = {"Default Settings",
- "Quick Adjust",
- "Full Control"};
+char *EXN_Pic_Ctrl_Adj[EXN_PIC_CTRL_ADJ_MAX] = { "Default Settings",
+ "Quick Adjust",
+ "Full Control"
+};
static void exn_get_prim_af_pt(unsigned int phasedetectaf,
- unsigned int primafpt,
- char * buffer,
- unsigned int maxsize);
-static void exn_get_flash_output(unsigned int flashoutput, char * buffer, unsigned int maxsize);
-static void exn_get_mnote_nikon_18(ExifData *ed, char * buffer, unsigned int maxsize);
-static void exn_get_mnote_nikon_34(ExifData *ed, char * buffer, unsigned int maxsize);
-static void exn_get_mnote_nikon_35(ExifData *ed, char * buffer, unsigned int maxsize);
-static void exn_get_mnote_nikon_168(ExifData *ed, char * buffer, unsigned int maxsize);
-static void exn_get_mnote_nikon_183(ExifData *ed, char * buffer, unsigned int maxsize);
+ unsigned int primafpt,
+ char *buffer, unsigned int maxsize);
+static void exn_get_flash_output(unsigned int flashoutput, char *buffer,
+ unsigned int maxsize);
+static void exn_get_mnote_nikon_18(ExifData * ed, char *buffer,
+ unsigned int maxsize);
+static void exn_get_mnote_nikon_34(ExifData * ed, char *buffer,
+ unsigned int maxsize);
+static void exn_get_mnote_nikon_35(ExifData * ed, char *buffer,
+ unsigned int maxsize);
+static void exn_get_mnote_nikon_168(ExifData * ed, char *buffer,
+ unsigned int maxsize);
+static void exn_get_mnote_nikon_183(ExifData * ed, char *buffer,
+ unsigned int maxsize);
/* get primary AF point */
static void exn_get_prim_af_pt(unsigned int phasedetectaf,
- unsigned int primafpt,
- char * buffer,
- unsigned int maxsize)
+ unsigned int primafpt,
+ char *buffer, unsigned int maxsize)
{
-
- switch(phasedetectaf)
- {
- case 0:
- {
- /* phasedetect not used. should not happen */
- snprintf(buffer, maxsize, "FAIL");
- return;
- }
- break;
- case 1:
- {
- /* 51 pt */
- if ( primafpt < EXN_PRIM_AF_PT_51_MAX )
- {
- snprintf(buffer, maxsize, "%s", EXN_Prim_AF_Pt_51[primafpt]);
- }
- return;
- }
- break;
- case 2:
- {
- /* 11 pt */
- if ( primafpt < EXN_PRIM_AF_PT_11_MAX )
- {
- snprintf(buffer, maxsize, "%s", EXN_Prim_AF_Pt_11[primafpt]);
- }
- return;
- }
- break;
- case 3:
- {
- /* 39 pt */
- if ( primafpt < EXN_PRIM_AF_PT_39_MAX )
- {
- snprintf(buffer, maxsize, "%s", EXN_Prim_AF_Pt_39[primafpt]);
- }
- return;
- }
- break;
- default:
- {
- snprintf(buffer, maxsize, "?");
- return;
- }
- break;
-
- }
-
+
+ switch (phasedetectaf) {
+ case 0:
+ {
+ /* phasedetect not used. should not happen */
+ snprintf(buffer, maxsize, "FAIL");
+ return;
+ }
+ break;
+ case 1:
+ {
+ /* 51 pt */
+ if (primafpt < EXN_PRIM_AF_PT_51_MAX) {
+ snprintf(buffer, maxsize, "%s",
+ EXN_Prim_AF_Pt_51[primafpt]);
+ }
+ return;
+ }
+ break;
+ case 2:
+ {
+ /* 11 pt */
+ if (primafpt < EXN_PRIM_AF_PT_11_MAX) {
+ snprintf(buffer, maxsize, "%s",
+ EXN_Prim_AF_Pt_11[primafpt]);
+ }
+ return;
+ }
+ break;
+ case 3:
+ {
+ /* 39 pt */
+ if (primafpt < EXN_PRIM_AF_PT_39_MAX) {
+ snprintf(buffer, maxsize, "%s",
+ EXN_Prim_AF_Pt_39[primafpt]);
+ }
+ return;
+ }
+ break;
+ default:
+ {
+ snprintf(buffer, maxsize, "?");
+ return;
+ }
+ break;
+
+ }
+
}
/* get flash output power (for FlashInfo010x) */
-static void exn_get_flash_output(unsigned int flashoutput, char * buffer, unsigned int maxsize)
+static void exn_get_flash_output(unsigned int flashoutput, char *buffer,
+ unsigned int maxsize)
{
-
- if ( flashoutput == 0 )
- {
- /* full power */
- snprintf(buffer, maxsize, "Full");
- }
- else
- {
- if ( (flashoutput % 6) == 0 )
- {
- /* value is a power of 2 */
- snprintf(buffer, maxsize, "1/%d", 1<<(flashoutput/6));
- }
- else
- {
- /* something uneven...ugly. maybe introduce pow() function from libm later */
- snprintf(buffer, maxsize, "1/2^(%f)", ((float)flashoutput)/6.0);
- }
- }
+
+ if (flashoutput == 0) {
+ /* full power */
+ snprintf(buffer, maxsize, "Full");
+ } else {
+ if ((flashoutput % 6) == 0) {
+ /* value is a power of 2 */
+ snprintf(buffer, maxsize, "1/%d",
+ 1 << (flashoutput / 6));
+ } else {
+ /* something uneven...ugly. maybe introduce pow() function from libm later */
+ snprintf(buffer, maxsize, "1/2^(%f)",
+ ((float) flashoutput) / 6.0);
+ }
+ }
}
/* get ActiveD-Lighting (18) info */
-static void exn_get_mnote_nikon_18(ExifData *ed, char * buffer, unsigned int maxsize)
+static void exn_get_mnote_nikon_18(ExifData * ed, char *buffer,
+ unsigned int maxsize)
{
- char buf[EXIF_STD_BUF_LEN];
- float data = 0;
+ char buf[EXIF_STD_BUF_LEN];
+ float data = 0;
- buf[0] = '\0';
- exif_get_mnote_tag(ed, 18, buf, sizeof(buf));
+ buf[0] = '\0';
+ exif_get_mnote_tag(ed, 18, buf, sizeof(buf));
- sscanf(buf, "Flash Exposure Compensation: %f", &data); /* libexif buggy here. fix conversion */
+ sscanf(buf, "Flash Exposure Compensation: %f", &data); /* libexif buggy here. fix conversion */
- snprintf(buffer, maxsize, "FlashExposureCompensation: %+.1f EV\n", ((float)((signed char)round(data*6.0))) / 6.0 );
+ snprintf(buffer, maxsize, "FlashExposureCompensation: %+.1f EV\n",
+ ((float) ((signed char) round(data * 6.0))) / 6.0);
}
/* get ActiveD-Lighting (34) info */
-static void exn_get_mnote_nikon_34(ExifData *ed, char * buffer, unsigned int maxsize)
+static void exn_get_mnote_nikon_34(ExifData * ed, char *buffer,
+ unsigned int maxsize)
{
- char buf[EXIF_STD_BUF_LEN];
- unsigned int data = 0;
- char *answer;
-
- buf[0] = '\0';
- exif_get_mnote_tag(ed, 34, buf, sizeof(buf));
- sscanf(buf, "(null): %u", &data); /* not directly supported by libexif yet */
-
- switch(data)
- {
- case 0:
- {
- answer = "Off";
- }
- break;
- case 1:
- {
- answer = "Low";
- }
- break;
- case 3:
- {
- answer = "Normal";
- }
- break;
- case 5:
- {
- answer = "High";
- }
- break;
- case 7:
- {
- answer = "Extra High";
- }
- break;
- case 65535:
- {
- answer = "Auto";
- }
- break;
- default:
- {
- answer = "N/A"; /* this is not a nikon value */
- }
-
- }
-
- snprintf(buffer, maxsize, "Active D-Lightning: %s\n", answer);
-
+ char buf[EXIF_STD_BUF_LEN];
+ unsigned int data = 0;
+ char *answer;
+
+ buf[0] = '\0';
+ exif_get_mnote_tag(ed, 34, buf, sizeof(buf));
+ sscanf(buf, "(null): %u", &data); /* not directly supported by libexif yet */
+
+ switch (data) {
+ case 0:
+ {
+ answer = "Off";
+ }
+ break;
+ case 1:
+ {
+ answer = "Low";
+ }
+ break;
+ case 3:
+ {
+ answer = "Normal";
+ }
+ break;
+ case 5:
+ {
+ answer = "High";
+ }
+ break;
+ case 7:
+ {
+ answer = "Extra High";
+ }
+ break;
+ case 65535:
+ {
+ answer = "Auto";
+ }
+ break;
+ default:
+ {
+ answer = "N/A"; /* this is not a nikon value */
+ }
+
+ }
+
+ snprintf(buffer, maxsize, "Active D-Lightning: %s\n", answer);
+
}
/* get nikon PictureControlData (35) info */
-static void exn_get_mnote_nikon_35(ExifData *ed, char * buffer, unsigned int maxsize)
+static void exn_get_mnote_nikon_35(ExifData * ed, char *buffer,
+ unsigned int maxsize)
{
- char buf[EXIF_STD_BUF_LEN];
- char picturecontrolname[EXIF_STD_BUF_LEN];
- char picturecontrolbase[EXIF_STD_BUF_LEN];
- unsigned int version = 0;
- unsigned int length = 0;
- unsigned int piccontroladj = 0;
- unsigned int piccontrolquickadj = 0;
- unsigned int sharpness = 0;
- unsigned int contrast = 0;
- unsigned int brightness = 0;
- unsigned int saturation = 0;
- unsigned int hueadjustment = 0;
- unsigned int i, j;
-
- /* libexif does not support PictureControlData 35 yet. so we have to parse the debug data :-( */
- buf[0] = '\0';
- exif_get_mnote_tag(ed, 35, buf, sizeof(buf));
-
- sscanf(buf, "(null): %u bytes unknown data: 303130%02X%40s%40s%*8s%02X%02X%02X%02X%02X%02X%02X",
- &length, &version, &picturecontrolname[0], &picturecontrolbase[0],
- &piccontroladj, &piccontrolquickadj,
- &sharpness, &contrast, &brightness, &saturation, &hueadjustment
- );
-
- /* printf("--%s %d-%d-\n", buf, version, piccontroladj); */
-
- for ( i=0; i<40; i++ )
- {
- sscanf(&picturecontrolname[2*i], "%2X", &j);
- picturecontrolname[i] = j;
- sscanf(&picturecontrolbase[2*i], "%2X", &j);
- picturecontrolbase[i] = j;
-
- }
- exif_trim_spaces(picturecontrolname);
- exif_trim_spaces(picturecontrolbase);
-
- if ( ((length == 58) && (version == '0'))
- && (piccontroladj < EXN_PIC_CTRL_ADJ_MAX)
-
- )
- {
- snprintf(buffer, maxsize,
- "PictCtrlData: Name: %s; Base: %s; CtrlAdj: %s; Quick: %d; Shrp: %d; Contr: %d; Brght: %d; Sat: %d; Hue: %d\n",
- picturecontrolname, picturecontrolbase,
- EXN_Pic_Ctrl_Adj[piccontroladj], piccontrolquickadj,
- sharpness, contrast, brightness, saturation, hueadjustment);
- }
+ char buf[EXIF_STD_BUF_LEN];
+ char picturecontrolname[EXIF_STD_BUF_LEN];
+ char picturecontrolbase[EXIF_STD_BUF_LEN];
+ unsigned int version = 0;
+ unsigned int length = 0;
+ unsigned int piccontroladj = 0;
+ unsigned int piccontrolquickadj = 0;
+ unsigned int sharpness = 0;
+ unsigned int contrast = 0;
+ unsigned int brightness = 0;
+ unsigned int saturation = 0;
+ unsigned int hueadjustment = 0;
+ unsigned int i, j;
+
+ /* libexif does not support PictureControlData 35 yet. so we have to parse the debug data :-( */
+ buf[0] = '\0';
+ exif_get_mnote_tag(ed, 35, buf, sizeof(buf));
+
+ sscanf(buf,
+ "(null): %u bytes unknown data: 303130%02X%40s%40s%*8s%02X%02X%02X%02X%02X%02X%02X",
+ &length, &version, &picturecontrolname[0],
+ &picturecontrolbase[0], &piccontroladj, &piccontrolquickadj,
+ &sharpness, &contrast, &brightness, &saturation,
+ &hueadjustment);
+
+ /* printf("--%s %d-%d-\n", buf, version, piccontroladj); */
+
+ for (i = 0; i < 40; i++) {
+ sscanf(&picturecontrolname[2 * i], "%2X", &j);
+ picturecontrolname[i] = j;
+ sscanf(&picturecontrolbase[2 * i], "%2X", &j);
+ picturecontrolbase[i] = j;
+
+ }
+ exif_trim_spaces(picturecontrolname);
+ exif_trim_spaces(picturecontrolbase);
+
+ if (((length == 58) && (version == '0'))
+ && (piccontroladj < EXN_PIC_CTRL_ADJ_MAX)
+ ) {
+ snprintf(buffer, maxsize,
+ "PictCtrlData: Name: %s; Base: %s; CtrlAdj: %s; Quick: %d; Shrp: %d; Contr: %d; Brght: %d; Sat: %d; Hue: %d\n",
+ picturecontrolname, picturecontrolbase,
+ EXN_Pic_Ctrl_Adj[piccontroladj],
+ piccontrolquickadj, sharpness, contrast,
+ brightness, saturation, hueadjustment);
+ }
}
@@ -331,180 +354,189 @@ static void exn_get_mnote_nikon_35(ExifData *ed, char * buffer, unsigned int max
/* get nikon Flash info: control mode (168) info */
-static void exn_get_mnote_nikon_168(ExifData *ed, char * buffer, unsigned int maxsize)
+static void exn_get_mnote_nikon_168(ExifData * ed, char *buffer,
+ unsigned int maxsize)
{
- char buf[EXIF_STD_BUF_LEN];
- unsigned int version = 0;
- unsigned int length = 0;
- unsigned int exn_fcm = (EXN_FLASH_CONTROL_MODES_MAX-1); /* default to N/A */
- unsigned int flashoutput = 0;
- unsigned int externalflashflags = 0;
- unsigned int flashcompensation = 0;
-
- /* libexif does not support flash info 168 yet. so we have to parse the debug data :-( */
- buf[0] = '\0';
- exif_get_mnote_tag(ed, 168, buf, sizeof(buf));
- sscanf(buf, "(null): %u bytes unknown data: 303130%02X%*8s%02X%02X%02X%02X", &length, &version, &externalflashflags, &exn_fcm, &flashoutput, &flashcompensation);
- exn_fcm = exn_fcm & EXN_FLASH_CONTROL_MODE_MASK;
-
- /* printf("%s - %d %d %d %d\n", buf, externalflashflags, exn_fcm, flashoutput, (signed char)flashcompensation); */
-
- if ( (exn_fcm < EXN_FLASH_CONTROL_MODES_MAX)
- && ( ((length == 22) && (version == '3')) /* Nikon FlashInfo0103 */
- || ((length == 22) && (version == '4')) /* Nikon FlashInfo0104 */
- || ((length == 21) && (version == '2')) /* Nikon FlashInfo0102 */
- || ((length == 19) && (version == '0')) /* Nikon FlashInfo0100 */
- )
- )
- {
-
- buf[0] = '\0';
- exn_get_flash_output(flashoutput, buf, EXIF_STD_BUF_LEN);
- snprintf(buffer, maxsize, "NikonFlashControlMode: %s (Power: %s)\n", EXN_NikonFlashControlModeValues[exn_fcm], buf);
-
- /* External Flash Flags. Not as useful as expected. Not used (yet). */
- /* if ( (externalflashflags & (1<<2)) ) -> Bounce Flash */
- /* if ( (externalflashflags & (1<<4)) ) -> Wide Flash Adapter */
- /* if ( (externalflashflags & (1<<5)) ) -> Dome Diffusor */
-
- }
+ char buf[EXIF_STD_BUF_LEN];
+ unsigned int version = 0;
+ unsigned int length = 0;
+ unsigned int exn_fcm = (EXN_FLASH_CONTROL_MODES_MAX - 1); /* default to N/A */
+ unsigned int flashoutput = 0;
+ unsigned int externalflashflags = 0;
+ unsigned int flashcompensation = 0;
+
+ /* libexif does not support flash info 168 yet. so we have to parse the debug data :-( */
+ buf[0] = '\0';
+ exif_get_mnote_tag(ed, 168, buf, sizeof(buf));
+ sscanf(buf,
+ "(null): %u bytes unknown data: 303130%02X%*8s%02X%02X%02X%02X",
+ &length, &version, &externalflashflags, &exn_fcm,
+ &flashoutput, &flashcompensation);
+ exn_fcm = exn_fcm & EXN_FLASH_CONTROL_MODE_MASK;
+
+ /* printf("%s - %d %d %d %d\n", buf, externalflashflags, exn_fcm, flashoutput, (signed char)flashcompensation); */
+
+ if ((exn_fcm < EXN_FLASH_CONTROL_MODES_MAX)
+ && (((length == 22) && (version == '3')) /* Nikon FlashInfo0103 */
+ ||((length == 22) && (version == '4')) /* Nikon FlashInfo0104 */
+ ||((length == 21) && (version == '2')) /* Nikon FlashInfo0102 */
+ ||((length == 19) && (version == '0')) /* Nikon FlashInfo0100 */
+ )
+ ) {
+
+ buf[0] = '\0';
+ exn_get_flash_output(flashoutput, buf, EXIF_STD_BUF_LEN);
+ snprintf(buffer, maxsize,
+ "NikonFlashControlMode: %s (Power: %s)\n",
+ EXN_NikonFlashControlModeValues[exn_fcm], buf);
+
+ /* External Flash Flags. Not as useful as expected. Not used (yet). */
+ /* if ( (externalflashflags & (1<<2)) ) -> Bounce Flash */
+ /* if ( (externalflashflags & (1<<4)) ) -> Wide Flash Adapter */
+ /* if ( (externalflashflags & (1<<5)) ) -> Dome Diffusor */
+
+ }
}
/* get nikon AFInfo2 (183) info */
-static void exn_get_mnote_nikon_183(ExifData *ed, char * buffer, unsigned int maxsize)
+static void exn_get_mnote_nikon_183(ExifData * ed, char *buffer,
+ unsigned int maxsize)
{
- char buf[EXIF_STD_BUF_LEN];
- unsigned int contrastdetectaf = 0;
- unsigned int afareamode = 0;
- unsigned int phasedetectaf = 0;
- unsigned int primaryafpoint = 0;
- unsigned int version = 0;
- unsigned int length = 0;
-
- /* AFInfo2 */
- /* libexif does not support AFInfo2 183 yet. so we have to parse the debug data :-( */
- buf[0] = '\0';
- exif_get_mnote_tag(ed, 183, buf, sizeof(buf));
- sscanf(buf, "(null): %u bytes unknown data: 303130%02X%02X%02X%02X%02X", &length, &version,
- &contrastdetectaf,
- &afareamode,
- &phasedetectaf,
- &primaryafpoint
- );
-
-
- if ( ((length == 30) && (version == '0'))
- && (contrastdetectaf < EXN_CONTRAST_DETECT_AF_MAX)
- && (phasedetectaf < EXN_PHASE_DETECT_AF_MAX)
- )
- {
- if ( (contrastdetectaf != 0) && (afareamode < EXN_AF_AREA_MODE_C_MAX) )
- {
- /* Contrast AF (live view) */
- snprintf(buffer, maxsize,
- "ContrastDetectAF: %s; AFAreaMode: %s\n",
- EXN_NikonContrastDetectAF[contrastdetectaf],
- EXN_NikonAFAreaModeContr[afareamode]);
-
- }
- else if ( (phasedetectaf != 0) && (afareamode < EXN_AF_AREA_MODE_P_MAX) )
- {
- /* Phase AF */
- buf[0] = '\0';
- exn_get_prim_af_pt(phasedetectaf, primaryafpoint, buf, EXIF_STD_BUF_LEN);
-
- snprintf(buffer, maxsize,
- "PhaseDetectAF: %s; AreaMode: %s; PrimaryAFPoint: %s\n",
- EXN_NikonPhaseDetectAF[phasedetectaf],
- EXN_NikonAFAreaModePhase[afareamode],
- buf
- );
- }
-
- }
+ char buf[EXIF_STD_BUF_LEN];
+ unsigned int contrastdetectaf = 0;
+ unsigned int afareamode = 0;
+ unsigned int phasedetectaf = 0;
+ unsigned int primaryafpoint = 0;
+ unsigned int version = 0;
+ unsigned int length = 0;
+
+ /* AFInfo2 */
+ /* libexif does not support AFInfo2 183 yet. so we have to parse the debug data :-( */
+ buf[0] = '\0';
+ exif_get_mnote_tag(ed, 183, buf, sizeof(buf));
+ sscanf(buf,
+ "(null): %u bytes unknown data: 303130%02X%02X%02X%02X%02X",
+ &length, &version, &contrastdetectaf, &afareamode,
+ &phasedetectaf, &primaryafpoint);
+
+
+ if (((length == 30) && (version == '0'))
+ && (contrastdetectaf < EXN_CONTRAST_DETECT_AF_MAX)
+ && (phasedetectaf < EXN_PHASE_DETECT_AF_MAX)
+ ) {
+ if ((contrastdetectaf != 0)
+ && (afareamode < EXN_AF_AREA_MODE_C_MAX)) {
+ /* Contrast AF (live view) */
+ snprintf(buffer, maxsize,
+ "ContrastDetectAF: %s; AFAreaMode: %s\n",
+ EXN_NikonContrastDetectAF
+ [contrastdetectaf],
+ EXN_NikonAFAreaModeContr[afareamode]);
+
+ } else if ((phasedetectaf != 0)
+ && (afareamode < EXN_AF_AREA_MODE_P_MAX)) {
+ /* Phase AF */
+ buf[0] = '\0';
+ exn_get_prim_af_pt(phasedetectaf, primaryafpoint,
+ buf, EXIF_STD_BUF_LEN);
+
+ snprintf(buffer, maxsize,
+ "PhaseDetectAF: %s; AreaMode: %s; PrimaryAFPoint: %s\n",
+ EXN_NikonPhaseDetectAF[phasedetectaf],
+ EXN_NikonAFAreaModePhase[afareamode],
+ buf);
+ }
+
+ }
}
/* get interesting nikon maker note tags in readable form */
-void exn_get_mnote_nikon_tags(ExifData *ed, unsigned int tag, char * buffer, unsigned int maxsize)
+void exn_get_mnote_nikon_tags(ExifData * ed, unsigned int tag,
+ char *buffer, unsigned int maxsize)
{
- char buf[EXIF_STD_BUF_LEN];
-
- buf[0] = '\0';
- exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_FLASH, buf, sizeof(buf));
- exif_trim_spaces(buf);
-
- switch(tag)
- {
- /* show only if flash was used */
- case 8: /* Flash Setting */
- case 9: /* Flash Mode */
- case 135: /* Flash used */
- {
- if ( !(strcmp("Flash: Flash did not fire\n", buf) == 0) )
- {
- /* show extended flash info only if flash was fired */
- exif_get_mnote_tag(ed, tag, buffer, maxsize);
- }
- }
- break;
-
- case 18: /* FlashExposureComp */
- {
- if ( !(strcmp("Flash: Flash did not fire\n", buf) == 0) )
- {
- /* show only if flash was fired */
- exn_get_mnote_nikon_18(ed, buffer, maxsize);
- }
- }
- break;
-
- case 34:
- {
- /* ActiveD-Lighting */
- exn_get_mnote_nikon_34(ed, buffer, maxsize);
- }
- break;
-
- case 35:
- {
- /* PictureControlData */
- exn_get_mnote_nikon_35(ed, buffer, maxsize);
- }
- break;
-
- case 168:
- {
- /* Flash info: control mode */
- if ( !(strcmp("Flash: Flash did not fire\n", buf) == 0) )
- {
- /* show extended flash info only if flash was fired */
- exn_get_mnote_nikon_168(ed, buffer, maxsize);
- }
- }
- break;
-
- case 183:
- {
- /* AFInfo 2 */
- exn_get_mnote_nikon_183(ed, buffer, maxsize);
- }
- break;
-
- default:
- {
- /* normal makernote tags without special treatment */
- exif_get_mnote_tag(ed, tag, buffer, maxsize);
- }
- break;
- }
-
-
- return;
+ char buf[EXIF_STD_BUF_LEN];
+
+ buf[0] = '\0';
+ exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_FLASH, buf, sizeof(buf));
+ exif_trim_spaces(buf);
+
+ switch (tag) {
+ /* show only if flash was used */
+ case 8: /* Flash Setting */
+ case 9: /* Flash Mode */
+ case 135: /* Flash used */
+ {
+ if (!
+ (strcmp("Flash: Flash did not fire\n", buf) ==
+ 0)) {
+ /* show extended flash info only if flash was fired */
+ exif_get_mnote_tag(ed, tag, buffer,
+ maxsize);
+ }
+ }
+ break;
+
+ case 18: /* FlashExposureComp */
+ {
+ if (!
+ (strcmp("Flash: Flash did not fire\n", buf) ==
+ 0)) {
+ /* show only if flash was fired */
+ exn_get_mnote_nikon_18(ed, buffer,
+ maxsize);
+ }
+ }
+ break;
+
+ case 34:
+ {
+ /* ActiveD-Lighting */
+ exn_get_mnote_nikon_34(ed, buffer, maxsize);
+ }
+ break;
+
+ case 35:
+ {
+ /* PictureControlData */
+ exn_get_mnote_nikon_35(ed, buffer, maxsize);
+ }
+ break;
+
+ case 168:
+ {
+ /* Flash info: control mode */
+ if (!
+ (strcmp("Flash: Flash did not fire\n", buf) ==
+ 0)) {
+ /* show extended flash info only if flash was fired */
+ exn_get_mnote_nikon_168(ed, buffer,
+ maxsize);
+ }
+ }
+ break;
+
+ case 183:
+ {
+ /* AFInfo 2 */
+ exn_get_mnote_nikon_183(ed, buffer, maxsize);
+ }
+ break;
+
+ default:
+ {
+ /* normal makernote tags without special treatment */
+ exif_get_mnote_tag(ed, tag, buffer, maxsize);
+ }
+ break;
+ }
+
+
+ return;
}
#endif
diff --git a/src/exif_nikon.h b/src/exif_nikon.h
index 16e8fb9..49d14b6 100644
--- a/src/exif_nikon.h
+++ b/src/exif_nikon.h
@@ -28,6 +28,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <libexif/exif-data.h>
-extern void exn_get_mnote_nikon_tags(ExifData *ed, unsigned int tag, char * buffer, unsigned int maxsize);
+extern void exn_get_mnote_nikon_tags(ExifData * ed, unsigned int tag,
+ char *buffer, unsigned int maxsize);
#endif
diff --git a/src/feh.h b/src/feh.h
index e735871..54e78ea 100644
--- a/src/feh.h
+++ b/src/feh.h
@@ -1,7 +1,7 @@
/* feh.h
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -63,6 +63,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <signal.h>
#include <sys/wait.h>
#include <math.h>
+#include <getopt.h>
#include <Imlib2.h>
#include "gib_hash.h"
@@ -74,7 +75,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "menu.h"
#include "utils.h"
-#include "getopt.h"
#include "debug.h"
@@ -115,6 +115,14 @@ enum slide_change { SLIDE_NEXT, SLIDE_PREV, SLIDE_RAND, SLIDE_FIRST, SLIDE_LAST,
SLIDE_JUMP_PREV_DIR
};
+enum feh_load_error {
+ LOAD_ERROR_IMLIB = 0,
+ LOAD_ERROR_IMAGEMAGICK,
+ LOAD_ERROR_CURL,
+ LOAD_ERROR_DCRAW,
+ LOAD_ERROR_MAGICBYTES
+};
+
#define INPLACE_EDIT_FLIP -1
#define INPLACE_EDIT_MIRROR -2
@@ -137,6 +145,10 @@ void init_slideshow_mode(void);
void init_list_mode(void);
void init_loadables_mode(void);
void init_unloadables_mode(void);
+#ifdef HAVE_LIBMAGIC
+void uninit_magic(void);
+void init_magic(void);
+#endif
void feh_clean_exit(void);
int feh_should_ignore_image(Imlib_Image * im);
int feh_load_image(Imlib_Image * im, feh_file * file);
@@ -148,7 +160,7 @@ void init_buttonbindings(void);
void setup_stdin(void);
void restore_stdin(void);
void feh_event_handle_keypress(XEvent * ev);
-void feh_event_handle_stdin();
+void feh_event_handle_stdin(void);
void feh_event_handle_generic(winwidget winwid, unsigned int state, KeySym keysym, unsigned int button);
fehkey *feh_str_to_kb(char * action);
void feh_action_run(feh_file * file, char *action, winwidget winwid);
@@ -172,7 +184,7 @@ void feh_display_status(char stat);
void real_loadables_mode(int loadable);
void feh_reload_image(winwidget w, int resize, int force_new);
void feh_filelist_image_remove(winwidget winwid, char do_delete);
-void feh_imlib_print_load_error(char *file, winwidget w, Imlib_Load_Error err);
+void feh_print_load_error(char *file, winwidget w, Imlib_Load_Error err, enum feh_load_error feh_err);
void slideshow_save_image(winwidget win);
void feh_edit_inplace(winwidget w, int orientation);
void feh_edit_inplace_lossless(winwidget w, int orientation);
diff --git a/src/feh_png.c b/src/feh_png.c
index d0c1c8a..8f5b94d 100644
--- a/src/feh_png.c
+++ b/src/feh_png.c
@@ -197,7 +197,10 @@ int feh_png_file_is_png(FILE * fp)
{
unsigned char buf[8];
- fread(buf, 1, 8, fp);
+ if (fread(buf, 1, 8, fp) != 8) {
+ return 0;
+ }
+
if (png_sig_cmp(buf, 0, 8)) {
return 0;
}
diff --git a/src/filelist.c b/src/filelist.c
index 361ac19..f1e820c 100644
--- a/src/filelist.c
+++ b/src/filelist.c
@@ -1,7 +1,7 @@
/* filelist.c
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -24,20 +24,19 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifdef HAVE_LIBEXIF
-#include <libexif/exif-data.h>
-#endif
-
#include "feh.h"
#include "filelist.h"
#include "signals.h"
#include "options.h"
+#ifdef HAVE_LIBCURL
+#include <curl/curl.h>
+#endif
+
gib_list *filelist = NULL;
gib_list *original_file_items = NULL; /* original file items from argv */
int filelist_len = 0;
gib_list *current_file = NULL;
-extern int errno;
static gib_list *rm_filelist = NULL;
@@ -156,7 +155,7 @@ static void feh_print_stat_error(char *path)
}
}
-static void add_stdin_to_filelist()
+static void add_stdin_to_filelist(void)
{
char buf[1024];
size_t readsize;
@@ -181,6 +180,7 @@ static void add_stdin_to_filelist()
while ((readsize = fread(buf, sizeof(char), sizeof(buf), stdin)) > 0) {
if (fwrite(buf, sizeof(char), readsize, outfile) < readsize) {
free(sfn);
+ fclose(outfile);
return;
}
}
@@ -198,7 +198,7 @@ void add_file_to_filelist_recursively(char *origpath, unsigned char level)
struct stat st;
char *path;
- if (!origpath)
+ if (!origpath || *origpath == '\0')
return;
path = estrdup(origpath);
@@ -398,7 +398,7 @@ void feh_file_dirname(char *dst, feh_file * f, int maxlen)
return;
}
- strncpy(dst, f->filename, n);
+ memcpy(dst, f->filename, n);
dst[n] = '\0';
}
@@ -641,12 +641,13 @@ char *feh_absolute_path(char *path)
filelist file can be saved anywhere and feh will still find the
images */
D(("Need to convert %s to an absolute form\n", path));
- /* I SHOULD be able to just use a simple realpath() here, but dumb *
+ /* I SHOULD be able to just use a simple realpath() here, but dumb *
old Solaris's realpath doesn't return an absolute path if the
path you give it is relative. Linux and BSD get this right... */
if (getcwd(cwd, sizeof(cwd)) == NULL)
eprintf("Cannot determine working directory:");
- snprintf(temp, sizeof(temp), "%s/%s", cwd, path);
+ if ((size_t) snprintf(temp, sizeof(temp), "%s/%s", cwd, path) >= sizeof(temp))
+ eprintf("Absolute path for working directory was truncated");
if (realpath(temp, fullpath) != NULL) {
ret = estrdup(fullpath);
} else {
@@ -656,11 +657,20 @@ char *feh_absolute_path(char *path)
return(ret);
}
-void feh_save_filelist()
+void feh_save_filelist(void)
{
char *tmpname;
+ char *base_dir = "";
- tmpname = feh_unique_filename("", "filelist");
+ if (opt.output_dir) {
+ base_dir = estrjoin("", opt.output_dir, "/", NULL);
+ }
+
+ tmpname = feh_unique_filename(base_dir, "filelist");
+
+ if (opt.output_dir) {
+ free(base_dir);
+ }
if (opt.verbose)
fprintf(stderr, "saving filelist to filename '%s'\n", tmpname);
@@ -669,3 +679,27 @@ void feh_save_filelist()
free(tmpname);
return;
}
+
+#ifdef HAVE_LIBCURL
+
+char *feh_http_unescape(char *url)
+{
+ CURL *curl = curl_easy_init();
+ if (!curl) {
+ return NULL;
+ }
+ char *tmp_url = curl_easy_unescape(curl, url, 0, NULL);
+ char *new_url = estrdup(tmp_url);
+ curl_free(tmp_url);
+ curl_easy_cleanup(curl);
+ return new_url;
+}
+
+#else
+
+char *feh_http_unescape(char *url)
+{
+ return NULL;
+}
+
+#endif
diff --git a/src/filelist.h b/src/filelist.h
index e24a6a6..7f263dc 100644
--- a/src/filelist.h
+++ b/src/filelist.h
@@ -96,7 +96,8 @@ int feh_write_filelist(gib_list * list, char *filename);
gib_list *feh_read_filelist(char *filename);
char *feh_absolute_path(char *path);
gib_list *feh_file_remove_from_list(gib_list * list, gib_list * l);
-void feh_save_filelist();
+void feh_save_filelist(void);
+char *feh_http_unescape(char * url);
int feh_cmp_name(void *file1, void *file2);
int feh_cmp_dirname(void *file1, void *file2);
diff --git a/src/getopt.c b/src/getopt.c
deleted file mode 100644
index d212b3a..0000000
--- a/src/getopt.c
+++ /dev/null
@@ -1,949 +0,0 @@
-/* Getopt for GNU.
- NOTE: getopt is now part of the C library, so if you don't know what
- "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
- before changing it!
-
- Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97
- Free Software Foundation, Inc.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
- Ditto for AIX 3.2 and <stdlib.h>. */
-#ifndef _NO_PROTO
-#define _NO_PROTO
-#endif
-
-#if !defined (__STDC__) || !__STDC__
-/* This is a separate conditional since some stdc systems
- reject `defined (const)'. */
-#ifndef const
-#define const
-#endif
-#endif
-
-#include <stdio.h>
-
-/* Comment out all this code if we are using the GNU C Library, and are not
- actually compiling the library itself. This code is part of the GNU C
- Library, but also included in many other GNU distributions. Compiling
- and linking in this code is a waste when using the GNU C library
- (especially if it is a shared library). Rather than having every GNU
- program understand `configure --with-gnu-libc' and omit the object files,
- it is simpler to just do this in the source for each such file. */
-
-#define GETOPT_INTERFACE_VERSION 2
-#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
-#include <gnu-versions.h>
-#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
-#define ELIDE_CODE
-#endif
-#endif
-
-#ifndef ELIDE_CODE
-
-/* This needs to come after some library #include
- to get __GNU_LIBRARY__ defined. */
-#ifdef __GNU_LIBRARY__
-/* Don't include stdlib.h for non-GNU C libraries because some of them
- contain conflicting prototypes for getopt. */
-#include <stdlib.h>
-#include <unistd.h>
-#endif /* GNU C library. */
-
-#ifdef VMS
-#include <unixlib.h>
-#if HAVE_STRING_H - 0
-#include <string.h>
-#endif
-#endif
-
-#ifndef _
-/* This is for other GNU distributions with internationalized messages.
- When compiling libc, the _ macro is predefined. */
-#ifdef HAVE_LIBINTL_H
-# include <libintl.h>
-# define _(msgid) gettext (msgid)
-#else
-# define _(msgid) (msgid)
-#endif
-#endif
-
-/* This version of `getopt' appears to the caller like standard Unix `getopt'
- but it behaves differently for the user, since it allows the user
- to intersperse the options with the other arguments.
-
- As `getopt' works, it permutes the elements of ARGV so that,
- when it is done, all the options precede everything else. Thus
- all application programs are extended to handle flexible argument order.
-
- Setting the environment variable POSIXLY_CORRECT disables permutation.
- Then the behavior is completely standard.
-
- GNU application programs can use a third alternative mode in which
- they can distinguish the relative order of options and other arguments. */
-
-#include "getopt.h"
-
-/* For communication from `getopt' to the caller.
- When `getopt' finds an option that takes an argument,
- the argument value is returned here.
- Also, when `ordering' is RETURN_IN_ORDER,
- each non-option ARGV-element is returned here. */
-
-char *optarg = NULL;
-
-/* Index in ARGV of the next element to be scanned.
- This is used for communication to and from the caller
- and for communication between successive calls to `getopt'.
-
- On entry to `getopt', zero means this is the first call; initialize.
-
- When `getopt' returns -1, this is the index of the first of the
- non-option elements that the caller should itself scan.
-
- Otherwise, `optind' communicates from one call to the next
- how much of ARGV has been scanned so far. */
-
-/* 1003.2 says this must be 1 before any call. */
-int optind = 1;
-
-/* Formerly, initialization of getopt depended on optind==0, which
- causes problems with re-calling getopt as programs generally don't
- know that. */
-
-int __getopt_initialized = 0;
-
-/* The next char to be scanned in the option-element
- in which the last option character we returned was found.
- This allows us to pick up the scan where we left off.
-
- If this is zero, or a null string, it means resume the scan
- by advancing to the next ARGV-element. */
-
-static char *nextchar;
-
-/* Callers store zero here to inhibit the error message
- for unrecognized options. */
-
-int opterr = 1;
-
-/* Set to an option character which was unrecognized.
- This must be initialized on some systems to avoid linking in the
- system's own getopt implementation. */
-
-int optopt = '?';
-
-/* Describe how to deal with options that follow non-option ARGV-elements.
-
- If the caller did not specify anything,
- the default is REQUIRE_ORDER if the environment variable
- POSIXLY_CORRECT is defined, PERMUTE otherwise.
-
- REQUIRE_ORDER means don't recognize them as options;
- stop option processing when the first non-option is seen.
- This is what Unix does.
- This mode of operation is selected by either setting the environment
- variable POSIXLY_CORRECT, or using `+' as the first character
- of the list of option characters.
-
- PERMUTE is the default. We permute the contents of ARGV as we scan,
- so that eventually all the non-options are at the end. This allows options
- to be given in any order, even with programs that were not written to
- expect this.
-
- RETURN_IN_ORDER is an option available to programs that were written
- to expect options and other ARGV-elements in any order and that care about
- the ordering of the two. We describe each non-option ARGV-element
- as if it were the argument of an option with character code 1.
- Using `-' as the first character of the list of option characters
- selects this mode of operation.
-
- The special argument `--' forces an end of option-scanning regardless
- of the value of `ordering'. In the case of RETURN_IN_ORDER, only
- `--' can cause `getopt' to return -1 with `optind' != ARGC. */
-
-static enum {
- REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
-} ordering;
-
-/* Value of POSIXLY_CORRECT environment variable. */
-static char *posixly_correct;
-
-#ifdef __GNU_LIBRARY__
-/* We want to avoid inclusion of string.h with non-GNU libraries
- because there are many ways it can cause trouble.
- On some systems, it contains special magic macros that don't work
- in GCC. */
-#include <string.h>
-#define my_index strchr
-#else
-
-/* Avoid depending on library functions or files
- whose names are inconsistent. */
-
-char *getenv();
-
-static char *my_index(str, chr)
-const char *str;
-int chr;
-{
- while (*str) {
- if (*str == chr)
- return (char *) str;
- str++;
- }
- return 0;
-}
-
-/* If using GCC, we can safely declare strlen this way.
- If not using GCC, it is ok not to declare it. */
-#ifdef __GNUC__
-/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
- That was relevant to code that was here before. */
-#if !defined (__STDC__) || !__STDC__
-/* gcc with -traditional declares the built-in strlen to return int,
- and has done so at least since version 2.4.5. -- rms. */
-extern int strlen(const char *);
-#endif /* not __STDC__ */
-#endif /* __GNUC__ */
-
-#endif /* not __GNU_LIBRARY__ */
-
-/* Handle permutation of arguments. */
-
-/* Describe the part of ARGV that contains non-options that have
- been skipped. `first_nonopt' is the index in ARGV of the first of them;
- `last_nonopt' is the index after the last of them. */
-
-static int first_nonopt;
-static int last_nonopt;
-
-#ifdef _LIBC
-/* Bash 2.0 gives us an environment variable containing flags
- indicating ARGV elements that should not be considered arguments. */
-
-/* Defined in getopt_init.c */
-extern char *__getopt_nonoption_flags;
-
-static int nonoption_flags_max_len;
-static int nonoption_flags_len;
-
-static int original_argc;
-static char *const *original_argv;
-
-/* Make sure the environment variable bash 2.0 puts in the environment
- is valid for the getopt call we must make sure that the ARGV passed
- to getopt is that one passed to the process. */
-static void
- __attribute__ ((unused)) store_args_and_env(int argc, char *const *argv)
-{
- /* XXX This is no good solution. We should rather copy the args so that
- we can compare them later. But we must not use malloc(3). */
- original_argc = argc;
- original_argv = argv;
-}
-
-# ifdef text_set_element
-text_set_element(__libc_subinit, store_args_and_env);
-# endif /* text_set_element */
-
-# define SWAP_FLAGS(ch1, ch2) \
- if (nonoption_flags_len > 0) \
- { \
- char __tmp = __getopt_nonoption_flags[ch1]; \
- __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
- __getopt_nonoption_flags[ch2] = __tmp; \
- }
-#else /* !_LIBC */
-# define SWAP_FLAGS(ch1, ch2)
-#endif /* _LIBC */
-
-/* Exchange two adjacent subsequences of ARGV.
- One subsequence is elements [first_nonopt,last_nonopt)
- which contains all the non-options that have been skipped so far.
- The other is elements [last_nonopt,optind), which contains all
- the options processed since those non-options were skipped.
-
- `first_nonopt' and `last_nonopt' are relocated so that they describe
- the new indices of the non-options in ARGV after they are moved. */
-
-#if defined (__STDC__) && __STDC__
-static void exchange(char **);
-#endif
-
-static void exchange(argv)
-char **argv;
-{
- int bottom = first_nonopt;
- int middle = last_nonopt;
- int top = optind;
- char *tem;
-
- /* Exchange the shorter segment with the far end of the longer segment.
- That puts the shorter segment into the right place. It leaves the
- longer segment in the right place overall, but it consists of two parts
- that need to be swapped next. */
-
-#ifdef _LIBC
- /* First make sure the handling of the `__getopt_nonoption_flags' string
- can work normally. Our top argument must be in the range of the
- string. */
- if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) {
- /* We must extend the array. The user plays games with us and presents
- new arguments. */
- char *new_str = malloc(top + 1);
-
- if (new_str == NULL)
- nonoption_flags_len = nonoption_flags_max_len = 0;
- else {
- memset(__mempcpy
- (new_str, __getopt_nonoption_flags,
- nonoption_flags_max_len), '\0', top + 1 - nonoption_flags_max_len);
- nonoption_flags_max_len = top + 1;
- __getopt_nonoption_flags = new_str;
- }
- }
-#endif
-
- while (top > middle && middle > bottom) {
- if (top - middle > middle - bottom) {
- /* Bottom segment is the short one. */
- int len = middle - bottom;
- register int i;
-
- /* Swap it with the top part of the top segment. */
- for (i = 0; i < len; i++) {
- tem = argv[bottom + i];
- argv[bottom + i] = argv[top - (middle - bottom) + i];
- argv[top - (middle - bottom) + i] = tem;
- SWAP_FLAGS(bottom + i, top - (middle - bottom) + i);
- }
- /* Exclude the moved bottom segment from further swapping. */
- top -= len;
- } else {
- /* Top segment is the short one. */
- int len = top - middle;
- register int i;
-
- /* Swap it with the bottom part of the bottom segment. */
- for (i = 0; i < len; i++) {
- tem = argv[bottom + i];
- argv[bottom + i] = argv[middle + i];
- argv[middle + i] = tem;
- SWAP_FLAGS(bottom + i, middle + i);
- }
- /* Exclude the moved top segment from further swapping. */
- bottom += len;
- }
- }
-
- /* Update records for the slots the non-options now occupy. */
-
- first_nonopt += (optind - last_nonopt);
- last_nonopt = optind;
-}
-
-/* Initialize the internal data when the first call is made. */
-
-#if defined (__STDC__) && __STDC__
-static const char *_getopt_initialize(int, char *const *, const char *);
-#endif
-static const char *_getopt_initialize(argc, argv, optstring)
-int argc;
-char *const *argv;
-const char *optstring;
-{
- /* Start processing options with ARGV-element 1 (since ARGV-element 0 is
- the program name); the sequence of previously skipped non-option
- ARGV-elements is empty. */
-
- first_nonopt = last_nonopt = optind;
-
- nextchar = NULL;
-
- posixly_correct = getenv("POSIXLY_CORRECT");
-
- /* Determine how to handle the ordering of options and nonoptions. */
-
- if (optstring[0] == '-') {
- ordering = RETURN_IN_ORDER;
- ++optstring;
- } else if (optstring[0] == '+') {
- ordering = REQUIRE_ORDER;
- ++optstring;
- } else if (posixly_correct != NULL)
- ordering = REQUIRE_ORDER;
- else
- ordering = PERMUTE;
-
-#ifdef _LIBC
- if (posixly_correct == NULL && argc == original_argc && argv == original_argv) {
- if (nonoption_flags_max_len == 0) {
- if (__getopt_nonoption_flags == NULL || __getopt_nonoption_flags[0] == '\0')
- nonoption_flags_max_len = -1;
- else {
- const char *orig_str = __getopt_nonoption_flags;
- int len = nonoption_flags_max_len = strlen(orig_str);
-
- if (nonoption_flags_max_len < argc)
- nonoption_flags_max_len = argc;
- __getopt_nonoption_flags = (char *)
- malloc(nonoption_flags_max_len);
- if (__getopt_nonoption_flags == NULL)
- nonoption_flags_max_len = -1;
- else
- memset(__mempcpy
- (__getopt_nonoption_flags,
- orig_str, len), '\0', nonoption_flags_max_len - len);
- }
- }
- nonoption_flags_len = nonoption_flags_max_len;
- } else
- nonoption_flags_len = 0;
-#endif
-
- return optstring;
-}
-
-/* Scan elements of ARGV (whose length is ARGC) for option characters
- given in OPTSTRING.
-
- If an element of ARGV starts with '-', and is not exactly "-" or "--",
- then it is an option element. The characters of this element
- (aside from the initial '-') are option characters. If `getopt'
- is called repeatedly, it returns successively each of the option characters
- from each of the option elements.
-
- If `getopt' finds another option character, it returns that character,
- updating `optind' and `nextchar' so that the next call to `getopt' can
- resume the scan with the following option character or ARGV-element.
-
- If there are no more option characters, `getopt' returns -1.
- Then `optind' is the index in ARGV of the first ARGV-element
- that is not an option. (The ARGV-elements have been permuted
- so that those that are not options now come last.)
-
- OPTSTRING is a string containing the legitimate option characters.
- If an option character is seen that is not listed in OPTSTRING,
- return '?' after printing an error message. If you set `opterr' to
- zero, the error message is suppressed but we still return '?'.
-
- If a char in OPTSTRING is followed by a colon, that means it wants an arg,
- so the following text in the same ARGV-element, or the text of the following
- ARGV-element, is returned in `optarg'. Two colons mean an option that
- wants an optional arg; if there is text in the current ARGV-element,
- it is returned in `optarg', otherwise `optarg' is set to zero.
-
- If OPTSTRING starts with `-' or `+', it requests different methods of
- handling the non-option ARGV-elements.
- See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
-
- Long-named options begin with `--' instead of `-'.
- Their names may be abbreviated as long as the abbreviation is unique
- or is an exact match for some defined option. If they have an
- argument, it follows the option name in the same ARGV-element, separated
- from the option name by a `=', or else the in next ARGV-element.
- When `getopt' finds a long-named option, it returns 0 if that option's
- `flag' field is nonzero, the value of the option's `val' field
- if the `flag' field is zero.
-
- The elements of ARGV aren't really const, because we permute them.
- But we pretend they're const in the prototype to be compatible
- with other systems.
-
- LONGOPTS is a vector of `struct option' terminated by an
- element containing a name which is zero.
-
- LONGIND returns the index in LONGOPT of the long-named option found.
- It is only valid when a long-named option has been found by the most
- recent call.
-
- If LONG_ONLY is nonzero, '-' as well as '--' can introduce
- long-named options. */
-
-int _getopt_internal(argc, argv, optstring, longopts, longind, long_only)
-int argc;
-char *const *argv;
-const char *optstring;
-const struct option *longopts;
-int *longind;
-int long_only;
-{
- optarg = NULL;
-
- if (optind == 0 || !__getopt_initialized) {
- if (optind == 0)
- optind = 1; /* Don't scan ARGV[0], the
- program name. */
- optstring = _getopt_initialize(argc, argv, optstring);
- __getopt_initialized = 1;
- }
-
- /* Test whether ARGV[optind] points to a non-option argument. Either it
- does not have option syntax, or there is an environment flag from the
- shell indicating it is not an option. The later information is only
- used when the used in the GNU libc. */
-#ifdef _LIBC
-#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
- || (optind < nonoption_flags_len \
- && __getopt_nonoption_flags[optind] == '1'))
-#else
-#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
-#endif
-
- if (nextchar == NULL || *nextchar == '\0') {
- /* Advance to the next ARGV-element. */
-
- /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
- moved back by the user (who may also have changed the arguments). */
- if (last_nonopt > optind)
- last_nonopt = optind;
- if (first_nonopt > optind)
- first_nonopt = optind;
-
- if (ordering == PERMUTE) {
- /* If we have just processed some options following some
- non-options, exchange them so that the options come first. */
-
- if (first_nonopt != last_nonopt && last_nonopt != optind)
- exchange((char **) argv);
- else if (last_nonopt != optind)
- first_nonopt = optind;
-
- /* Skip any additional non-options and extend the range of
- non-options previously skipped. */
-
- while (optind < argc && NONOPTION_P)
- optind++;
- last_nonopt = optind;
- }
-
- /* The special ARGV-element `--' means premature end of options. Skip
- it like a null option, then exchange with previous non-options as if
- it were an option, then skip everything else like a non-option. */
-
- if (optind != argc && !strcmp(argv[optind], "--")) {
- optind++;
-
- if (first_nonopt != last_nonopt && last_nonopt != optind)
- exchange((char **) argv);
- else if (first_nonopt == last_nonopt)
- first_nonopt = optind;
- last_nonopt = argc;
-
- optind = argc;
- }
-
- /* If we have done all the ARGV-elements, stop the scan and back over
- any non-options that we skipped and permuted. */
-
- if (optind == argc) {
- /* Set the next-arg-index to point at the non-options that we
- previously skipped, so the caller will digest them. */
- if (first_nonopt != last_nonopt)
- optind = first_nonopt;
- return -1;
- }
-
- /* If we have come to a non-option and did not permute it, either stop
- the scan or describe it to the caller and pass it by. */
-
- if (NONOPTION_P) {
- if (ordering == REQUIRE_ORDER)
- return -1;
- optarg = argv[optind++];
- return 1;
- }
-
- /* We have found another option-ARGV-element. Skip the initial
- punctuation. */
-
- nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-'));
- }
-
- /* Decode the current option-ARGV-element. */
-
- /* Check whether the ARGV-element is a long option.
-
- If long_only and the ARGV-element has the form "-f", where f is a valid
- short option, don't consider it an abbreviated form of a long option
- that starts with f. Otherwise there would be no way to give the -f
- short option.
-
- On the other hand, if there's a long option "fubar" and the
- ARGV-element is "-fu", do consider that an abbreviation of the long
- option, just like "--fu", and not "-f" with arg "u".
-
- This distinction seems to be the most useful approach. */
-
- if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2]
- || !my_index(optstring, argv[optind]
- [1]))))) {
- char *nameend;
- const struct option *p;
- const struct option *pfound = NULL;
- int exact = 0;
- int ambig = 0;
- int indfound = -1;
- int option_index;
-
- for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
- /* Do nothing. */ ;
-
- /* Test all long options for either exact match or abbreviated matches.
- */
- for (p = longopts, option_index = 0; p->name; p++, option_index++)
- if (!strncmp(p->name, nextchar, nameend - nextchar)) {
- if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen(p->name)) {
- /* Exact match found. */
- pfound = p;
- indfound = option_index;
- exact = 1;
- break;
- } else if (pfound == NULL) {
- /* First nonexact match found. */
- pfound = p;
- indfound = option_index;
- } else
- /* Second or later nonexact match found. */
- ambig = 1;
- }
-
- if (ambig && !exact) {
- if (opterr)
- fprintf(stderr, _("%s: option `%s' is ambiguous\n"), argv[0], argv[optind]);
- nextchar += strlen(nextchar);
- optind++;
- optopt = 0;
- return '?';
- }
-
- if (pfound != NULL) {
- option_index = indfound;
- optind++;
- if (*nameend) {
- /* Don't test has_arg with >, because some C compilers don't
- allow it to be used on enums. */
- if (pfound->has_arg)
- optarg = nameend + 1;
- else {
- if (opterr) {
- if (argv[optind - 1][1] == '-')
- /* --option */
- fprintf(stderr,
- _
- ("%s: option `--%s' doesn't allow an argument\n"),
- argv[0], pfound->name);
- else
- /* +option or -option */
- fprintf(stderr,
- _
- ("%s: option `%c%s' doesn't allow an argument\n"),
- argv[0], argv[optind - 1][0], pfound->name);
- }
-
- nextchar += strlen(nextchar);
-
- optopt = pfound->val;
- return '?';
- }
- } else if (pfound->has_arg == 1) {
- if (optind < argc)
- optarg = argv[optind++];
- else {
- if (opterr)
- fprintf(stderr,
- _
- ("%s: option `%s' requires an argument\n"),
- argv[0], argv[optind - 1]);
- nextchar += strlen(nextchar);
- optopt = pfound->val;
- return optstring[0] == ':' ? ':' : '?';
- }
- }
- nextchar += strlen(nextchar);
- if (longind != NULL)
- *longind = option_index;
- if (pfound->flag) {
- *(pfound->flag) = pfound->val;
- return 0;
- }
- return pfound->val;
- }
-
- /* Can't find it as a long option. If this is not getopt_long_only, or
- the option starts with '--' or is not a valid short option, then
- it's an error. Otherwise interpret it as a short option. */
- if (!long_only || argv[optind][1] == '-' || my_index(optstring, *nextchar) == NULL) {
- if (opterr) {
- if (argv[optind][1] == '-')
- /* --option */
- fprintf(stderr, _("%s: unrecognized option `--%s'\n"), argv[0], nextchar);
- else
- /* +option or -option */
- fprintf(stderr,
- _
- ("%s: unrecognized option `%c%s'\n"),
- argv[0], argv[optind][0], nextchar);
- }
- nextchar = (char *) "";
- optind++;
- optopt = 0;
- return '?';
- }
- }
-
- /* Look at and handle the next short option-character. */
-
- {
- char c = *nextchar++;
- char *temp = my_index(optstring, c);
-
- /* Increment `optind' when we start to process its last character. */
- if (*nextchar == '\0')
- ++optind;
-
- if (temp == NULL || c == ':') {
- if (opterr) {
- if (posixly_correct)
- /* 1003.2 specifies the format of this message. */
- fprintf(stderr, _("%s: illegal option -- %c\n"), argv[0], c);
- else
- fprintf(stderr, _("%s: invalid option -- %c\n"), argv[0], c);
- }
- optopt = c;
- return '?';
- }
- /* Convenience. Treat POSIX -W foo same as long option --foo */
- if (temp[0] == 'W' && temp[1] == ';') {
- char *nameend;
- const struct option *p;
- const struct option *pfound = NULL;
- int exact = 0;
- int ambig = 0;
- int indfound = 0;
- int option_index;
-
- /* This is an option that requires an argument. */
- if (*nextchar != '\0') {
- optarg = nextchar;
- /* If we end this ARGV-element by taking the rest as an arg, we
- must advance to the next element now. */
- optind++;
- } else if (optind == argc) {
- if (opterr) {
- /* 1003.2 specifies the format of this message. */
- fprintf(stderr, _("%s: option requires an argument -- %c\n"), argv[0], c);
- }
- optopt = c;
- if (optstring[0] == ':')
- c = ':';
- else
- c = '?';
- return c;
- } else
- /* We already incremented `optind' once; increment it again when
- taking next ARGV-elt as argument. */
- optarg = argv[optind++];
-
- /* optarg is now the argument, see if it's in the table of longopts.
- */
-
- for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
- /* Do nothing. */ ;
-
- /* Test all long options for either exact match or abbreviated
- matches. */
- for (p = longopts, option_index = 0; p->name; p++, option_index++)
- if (!strncmp(p->name, nextchar, nameend - nextchar)) {
- if ((unsigned int) (nameend - nextchar) == strlen(p->name)) {
- /* Exact match found. */
- pfound = p;
- indfound = option_index;
- exact = 1;
- break;
- } else if (pfound == NULL) {
- /* First nonexact match found. */
- pfound = p;
- indfound = option_index;
- } else
- /* Second or later nonexact match found. */
- ambig = 1;
- }
- if (ambig && !exact) {
- if (opterr)
- fprintf(stderr, _("%s: option `-W %s' is ambiguous\n"), argv[0], argv[optind]);
- nextchar += strlen(nextchar);
- optind++;
- return '?';
- }
- if (pfound != NULL) {
- option_index = indfound;
- if (*nameend) {
- /* Don't test has_arg with >, because some C compilers don't
- allow it to be used on enums. */
- if (pfound->has_arg)
- optarg = nameend + 1;
- else {
- if (opterr)
- fprintf(stderr, _("\
-%s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name);
-
- nextchar += strlen(nextchar);
- return '?';
- }
- } else if (pfound->has_arg == 1) {
- if (optind < argc)
- optarg = argv[optind++];
- else {
- if (opterr)
- fprintf(stderr,
- _
- ("%s: option `%s' requires an argument\n"),
- argv[0], argv[optind - 1]);
- nextchar += strlen(nextchar);
- return optstring[0] == ':' ? ':' : '?';
- }
- }
- nextchar += strlen(nextchar);
- if (longind != NULL)
- *longind = option_index;
- if (pfound->flag) {
- *(pfound->flag) = pfound->val;
- return 0;
- }
- return pfound->val;
- }
- nextchar = NULL;
- return 'W'; /* Let the application handle it.
- */
- }
- if (temp[1] == ':') {
- if (temp[2] == ':') {
- /* This is an option that accepts an argument optionally. */
- if (*nextchar != '\0') {
- optarg = nextchar;
- optind++;
- } else
- optarg = NULL;
- nextchar = NULL;
- } else {
- /* This is an option that requires an argument. */
- if (*nextchar != '\0') {
- optarg = nextchar;
- /* If we end this ARGV-element by taking the rest as an arg,
- we must advance to the next element now. */
- optind++;
- } else if (optind == argc) {
- if (opterr) {
- /* 1003.2 specifies the format of this message. */
- fprintf(stderr,
- _("%s: option requires an argument -- %c\n"), argv[0], c);
- }
- optopt = c;
- if (optstring[0] == ':')
- c = ':';
- else
- c = '?';
- } else
- /* We already incremented `optind' once; increment it again
- when taking next ARGV-elt as argument. */
- optarg = argv[optind++];
- nextchar = NULL;
- }
- }
- return c;
- }
-}
-
-int getopt(argc, argv, optstring)
-int argc;
-char *const *argv;
-const char *optstring;
-{
- return _getopt_internal(argc, argv, optstring, (const struct option *) 0, (int *) 0, 0);
-}
-
-#endif /* Not ELIDE_CODE. */
-
-#ifdef TEST
-
-/* Compile with -DTEST to make an executable for use in testing
- the above definition of `getopt'. */
-
-int main(argc, argv)
-int argc;
-char **argv;
-{
- int c;
- int digit_optind = 0;
-
- while (1) {
- int this_option_optind = optind ? optind : 1;
-
- c = getopt(argc, argv, "abc:d:0123456789");
- if (c == -1)
- break;
-
- switch (c) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (digit_optind != 0 && digit_optind != this_option_optind)
- printf("digits occur in two different argv-elements.\n");
- digit_optind = this_option_optind;
- printf("option %c\n", c);
- break;
-
- case 'a':
- printf("option a\n");
- break;
-
- case 'b':
- printf("option b\n");
- break;
-
- case 'c':
- printf("option c with value `%s'\n", optarg);
- break;
-
- case '?':
- break;
-
- default:
- printf("?? getopt returned character code 0%o ??\n", c);
- }
- }
-
- if (optind < argc) {
- printf("non-option ARGV-elements: ");
- while (optind < argc)
- printf("%s ", argv[optind++]);
- printf("\n");
- }
-
- exit(0);
-}
-
-#endif /* TEST */
diff --git a/src/getopt.h b/src/getopt.h
deleted file mode 100644
index 0a985b0..0000000
--- a/src/getopt.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/* Declarations for getopt.
- Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-#ifndef _GETOPT_H
-#define _GETOPT_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* For communication from `getopt' to the caller.
- When `getopt' finds an option that takes an argument,
- the argument value is returned here.
- Also, when `ordering' is RETURN_IN_ORDER,
- each non-option ARGV-element is returned here. */
-
- extern char *optarg;
-
-/* Index in ARGV of the next element to be scanned.
- This is used for communication to and from the caller
- and for communication between successive calls to `getopt'.
-
- On entry to `getopt', zero means this is the first call; initialize.
-
- When `getopt' returns -1, this is the index of the first of the
- non-option elements that the caller should itself scan.
-
- Otherwise, `optind' communicates from one call to the next
- how much of ARGV has been scanned so far. */
-
- extern int optind;
-
-/* Callers store zero here to inhibit the error message `getopt' prints
- for unrecognized options. */
-
- extern int opterr;
-
-/* Set to an option character which was unrecognized. */
-
- extern int optopt;
-
-/* Describe the long-named options requested by the application.
- The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
- of `struct option' terminated by an element containing a name which is
- zero.
-
- The field `has_arg' is:
- no_argument (or 0) if the option does not take an argument,
- required_argument (or 1) if the option requires an argument,
- optional_argument (or 2) if the option takes an optional argument.
-
- If the field `flag' is not NULL, it points to a variable that is set
- to the value given in the field `val' when the option is found, but
- left unchanged if the option is not found.
-
- To have a long-named option do something other than set an `int' to
- a compiled-in constant, such as set a value from `optarg', set the
- option's `flag' field to zero and its `val' field to a nonzero
- value (the equivalent single-letter option character, if there is
- one). For long options that have a zero `flag' field, `getopt'
- returns the contents of the `val' field. */
-
- struct option {
-#if defined (__STDC__) && __STDC__
- const char *name;
-#else
- char *name;
-#endif
- /* has_arg can't be an enum because some compilers complain about type
- mismatches in all the code that assumes it is an int. */
- int has_arg;
- int *flag;
- int val;
- };
-
-/* Names for the values of the `has_arg' field of `struct option'. */
-
-#define no_argument 0
-#define required_argument 1
-#define optional_argument 2
-
-#if defined (__STDC__) && __STDC__
-#ifdef __GNU_LIBRARY__
-/* Many other libraries have conflicting prototypes for getopt, with
- differences in the consts, in stdlib.h. To avoid compilation
- errors, only prototype getopt for the GNU C library. */
- extern int getopt(int argc, char *const *argv, const char *shortopts);
-#else /* not __GNU_LIBRARY__ */
-#ifndef __cplusplus
-/* C++ is more pedantic, and demands a full prototype, not this.
- Hope that stdlib.h has a prototype for `getopt'. */
- extern int getopt();
-#endif /* __cplusplus */
-#endif /* __GNU_LIBRARY__ */
- extern int getopt_long(int argc, char *const *argv,
- const char *shortopts, const struct option *longopts, int *longind);
- extern int getopt_long_only(int argc, char *const *argv,
- const char *shortopts, const struct option *longopts, int *longind);
-
-/* Internal only. Users should not call this directly. */
- extern int _getopt_internal(int argc, char *const *argv,
- const char *shortopts, const struct option *longopts, int *longind, int long_only);
-#else /* not __STDC__ */
- extern int getopt();
- extern int getopt_long();
- extern int getopt_long_only();
-
- extern int _getopt_internal();
-#endif /* __STDC__ */
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* getopt.h */
diff --git a/src/getopt1.c b/src/getopt1.c
deleted file mode 100644
index 5a5c483..0000000
--- a/src/getopt1.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/* getopt_long and getopt_long_only entry points for GNU getopt.
- Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-#include "getopt.h"
-
-#if !defined (__STDC__) || !__STDC__
-/* This is a separate conditional since some stdc systems
- reject `defined (const)'. */
-#ifndef const
-#define const
-#endif
-#endif
-
-#include <stdio.h>
-
-/* Comment out all this code if we are using the GNU C Library, and are not
- actually compiling the library itself. This code is part of the GNU C
- Library, but also included in many other GNU distributions. Compiling
- and linking in this code is a waste when using the GNU C library
- (especially if it is a shared library). Rather than having every GNU
- program understand `configure --with-gnu-libc' and omit the object files,
- it is simpler to just do this in the source for each such file. */
-
-#define GETOPT_INTERFACE_VERSION 2
-#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
-#include <gnu-versions.h>
-#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
-#define ELIDE_CODE
-#endif
-#endif
-
-#ifndef ELIDE_CODE
-
-/* This needs to come after some library #include
- to get __GNU_LIBRARY__ defined. */
-#ifdef __GNU_LIBRARY__
-#include <stdlib.h>
-#endif
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-int getopt_long(argc, argv, options, long_options, opt_index)
-int argc;
-char *const *argv;
-const char *options;
-const struct option *long_options;
-int *opt_index;
-{
- return _getopt_internal(argc, argv, options, long_options, opt_index, 0);
-}
-
-/* Like getopt_long, but '-' as well as '--' can indicate a long option.
- If an option that starts with '-' (not '--') doesn't match a long option,
- but does match a short option, it is parsed as a short option
- instead. */
-
-int getopt_long_only(argc, argv, options, long_options, opt_index)
-int argc;
-char *const *argv;
-const char *options;
-const struct option *long_options;
-int *opt_index;
-{
- return _getopt_internal(argc, argv, options, long_options, opt_index, 1);
-}
-
-#endif /* Not ELIDE_CODE. */
-
-#ifdef TEST
-
-#include <stdio.h>
-
-int main(argc, argv)
-int argc;
-char **argv;
-{
- int c;
- int digit_optind = 0;
-
- while (1) {
- int this_option_optind = optind ? optind : 1;
- int option_index = 0;
- static struct option long_options[] = {
- {"add", 1, 0, 0},
- {"append", 0, 0, 0},
- {"delete", 1, 0, 0},
- {"verbose", 0, 0, 0},
- {"create", 0, 0, 0},
- {"file", 1, 0, 0},
- {0, 0, 0, 0}
- };
-
- c = getopt_long(argc, argv, "abc:d:0123456789", long_options, &option_index);
- if (c == -1)
- break;
-
- switch (c) {
- case 0:
- printf("option %s", long_options[option_index].name);
- if (optarg)
- printf(" with arg %s", optarg);
- printf("\n");
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (digit_optind != 0 && digit_optind != this_option_optind)
- printf("digits occur in two different argv-elements.\n");
- digit_optind = this_option_optind;
- printf("option %c\n", c);
- break;
-
- case 'a':
- printf("option a\n");
- break;
-
- case 'b':
- printf("option b\n");
- break;
-
- case 'c':
- printf("option c with value `%s'\n", optarg);
- break;
-
- case 'd':
- printf("option d with value `%s'\n", optarg);
- break;
-
- case '?':
- break;
-
- default:
- printf("?? getopt returned character code 0%o ??\n", c);
- }
- }
-
- if (optind < argc) {
- printf("non-option ARGV-elements: ");
- while (optind < argc)
- printf("%s ", argv[optind++]);
- printf("\n");
- }
-
- exit(0);
-}
-
-#endif /* TEST */
diff --git a/src/gib_hash.c b/src/gib_hash.c
index 0d6a226..9497d04 100644
--- a/src/gib_hash.c
+++ b/src/gib_hash.c
@@ -53,7 +53,7 @@ void gib_hash_node_free_and_data(gib_hash_node *node)
return;
}
-gib_hash *gib_hash_new()
+gib_hash *gib_hash_new(void)
{
gib_hash *hash = emalloc(sizeof(gib_hash));
hash->base = gib_hash_node_new("__gib_hash_new",NULL);
@@ -89,7 +89,7 @@ static unsigned char gib_hash_find_callback(gib_list *list, void *data)
gib_hash_node *node = GIB_HASH_NODE(list);
char *key = (char*) data;
- /* strncasecmp causes simliar keys like key1 and key11 clobber eachother */
+ /* strncasecmp causes similar keys like key1 and key11 clobber each other */
return !strcasecmp(node->key, key);
}
diff --git a/src/gib_hash.h b/src/gib_hash.h
index 58506c8..125e280 100644
--- a/src/gib_hash.h
+++ b/src/gib_hash.h
@@ -55,7 +55,7 @@ gib_hash_node *gib_hash_node_new(char *key, void *data);
void gib_hash_node_free(gib_hash_node *node);
void gib_hash_node_free_and_data(gib_hash_node *node);
-gib_hash *gib_hash_new();
+gib_hash *gib_hash_new(void);
void gib_hash_free(gib_hash *hash);
void gib_hash_free_and_data(gib_hash *hash);
diff --git a/src/gib_imlib.c b/src/gib_imlib.c
index 7858cb7..39d0081 100644
--- a/src/gib_imlib.c
+++ b/src/gib_imlib.c
@@ -27,6 +27,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "utils.h"
#include "debug.h"
+/*
int
gib_imlib_load_image(Imlib_Image * im, char *filename)
{
@@ -38,7 +39,6 @@ gib_imlib_load_image(Imlib_Image * im, char *filename)
*im = imlib_load_image_with_error_return(filename, &err);
if ((err) || (!im))
{
- /* Check error code */
switch (err)
{
case IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST:
@@ -91,6 +91,7 @@ gib_imlib_load_image(Imlib_Image * im, char *filename)
}
return (1);
}
+*/
int
gib_imlib_image_get_width(Imlib_Image im)
@@ -322,7 +323,7 @@ gib_imlib_text_draw(Imlib_Image im, Imlib_Font fn, gib_style * s, int x,
gib_style_bit *bb;
gib_list *l;
- /* here we shift the draw to accomodate bits with negative offsets,
+ /* here we shift the draw to accommodate bits with negative offsets,
* which would be drawn at negative coords otherwise */
l = s->bits;
while (l)
diff --git a/src/gib_imlib.h b/src/gib_imlib.h
index 07daabe..6a35e7e 100644
--- a/src/gib_imlib.h
+++ b/src/gib_imlib.h
@@ -47,7 +47,9 @@ extern "C"
{
#endif
+/*
int gib_imlib_load_image(Imlib_Image * im, char *filename);
+*/
int gib_imlib_image_get_width(Imlib_Image im);
int gib_imlib_image_get_height(Imlib_Image im);
int gib_imlib_image_has_alpha(Imlib_Image im);
diff --git a/src/gib_list.c b/src/gib_list.c
index a8ba1dd..e7710bc 100644
--- a/src/gib_list.c
+++ b/src/gib_list.c
@@ -520,7 +520,7 @@ gib_list_find(gib_list *root, unsigned char (*find_func)(gib_list *node, void *d
for (i=root; i; i=i->next)
if (find_func(i,data))
return i;
-
+
return NULL;
}
diff --git a/src/help.raw b/src/help.raw
index e0fb62a..e218e78 100644
--- a/src/help.raw
+++ b/src/help.raw
@@ -29,6 +29,8 @@ OPTIONS
mode or when window geometry is fixed. If combined
with --auto-zoom, zooming will be limited to the
the size. Also support \"max\" and \"fill\"
+ --zoom-step PERCENT Zoom images in and out by PERCENT (default: 25)
+ when using the zoom keys / buttons
--keep-zoom-vp Keep viewport zoom and settings while changing images
-w, --multiwindow Open all files at once, one window per image
-x, --borderless Create borderless windows
@@ -39,7 +41,7 @@ OPTIONS
--auto-rotate Rotate images according to Exif info (if compiled with exif=1)
-^, --title TITLE Set window title (see FORMAT SPECIFIERS)
-D, --slideshow-delay NUM Set delay between automatically changing slides
- --on-last-slide quit Exit after one loop through the slide show
+ --on-last-slide quit Exit after one loop through the slide show (old --cycle-once)
--on-last-slide hold Stop at both ends of the filelist
-R, --reload NUM Reload images after NUM seconds
-k, --keep-http Keep local copies when viewing HTTP/FTP files
@@ -100,6 +102,7 @@ OPTIONS
--scroll-step COUNT scroll COUNT pixels when movement key is pressed
--cache-size NUM imlib cache size in mebibytes (0 .. 2048)
--auto-reload automatically reload shown image if file was changed
+ --window-id ID Draw to an existing X11 window by its ID
MONTAGE MODE OPTIONS
-X, --ignore-aspect Set thumbnail to specified width/height without
@@ -201,7 +204,7 @@ DEFAULT KEYS
This program is free software, see the file COPYING for licensing info.
Copyright Tom Gilbert (and various contributors) 1999-2003.
-Copyright Daniel Friesel (and various contributors) 2010-2020.
+Copyright Birte Kristina Friesel (and various contributors) 2010-2020.
Homepage: http://feh.finalrewind.org
Report bugs to <derf+feh@finalrewind.org> or #feh on irc.oftc.net.
diff --git a/src/imlib.c b/src/imlib.c
index 4e8e790..143807d 100644
--- a/src/imlib.c
+++ b/src/imlib.c
@@ -1,7 +1,7 @@
/* imlib.c
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -44,6 +44,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "exif.h"
#endif
+#ifdef HAVE_LIBMAGIC
+#include <magic.h>
+
+magic_t magic = NULL;
+#endif
+
Display *disp = NULL;
Visual *vis = NULL;
Screen *scr = NULL;
@@ -164,11 +170,31 @@ int feh_load_image_char(Imlib_Image * im, char *filename)
return(i);
}
-void feh_imlib_print_load_error(char *file, winwidget w, Imlib_Load_Error err)
+void feh_print_load_error(char *file, winwidget w, Imlib_Load_Error err, enum feh_load_error feh_err)
{
if (err == IMLIB_LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS)
eprintf("%s - Out of file descriptors while loading", file);
else if (!opt.quiet || w) {
+ switch (feh_err) {
+ case LOAD_ERROR_IMLIB:
+ // handled in the next switch/case statement
+ break;
+ case LOAD_ERROR_IMAGEMAGICK:
+ im_weprintf(w, "%s - No ImageMagick loader for that file format", file);
+ break;
+ case LOAD_ERROR_CURL:
+ im_weprintf(w, "%s - libcurl was unable to retrieve the file", file);
+ break;
+ case LOAD_ERROR_DCRAW:
+ im_weprintf(w, "%s - Unable to open preview via dcraw", file);
+ break;
+ case LOAD_ERROR_MAGICBYTES:
+ im_weprintf(w, "%s - Does not look like an image (magic bytes missing)", file);
+ break;
+ }
+ if (feh_err != LOAD_ERROR_IMLIB) {
+ return;
+ }
switch (err) {
case IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST:
im_weprintf(w, "%s - File does not exist", file);
@@ -181,11 +207,7 @@ void feh_imlib_print_load_error(char *file, winwidget w, Imlib_Load_Error err)
break;
case IMLIB_LOAD_ERROR_UNKNOWN:
case IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT:
- if (getenv("FEH_SKIP_MAGIC")) {
- im_weprintf(w, "%s - No Imlib2 loader for that file format", file);
- } else {
- im_weprintf(w, "%s - Does not look like an image (magic bytes missing)", file);
- }
+ im_weprintf(w, "%s - No Imlib2 loader for that file format", file);
break;
case IMLIB_LOAD_ERROR_PATH_TOO_LONG:
im_weprintf(w, "%s - Path specified is too long", file);
@@ -211,6 +233,14 @@ void feh_imlib_print_load_error(char *file, winwidget w, Imlib_Load_Error err)
case IMLIB_LOAD_ERROR_OUT_OF_DISK_SPACE:
im_weprintf(w, "%s - Cannot write - out of disk space", file);
break;
+#if defined(IMLIB2_VERSION_MAJOR) && defined(IMLIB2_VERSION_MINOR) && (IMLIB2_VERSION_MAJOR > 1 || IMLIB2_VERSION_MINOR > 7)
+ case IMLIB_LOAD_ERROR_IMAGE_READ:
+ im_weprintf(w, "%s - Invalid image file", file);
+ break;
+ case IMLIB_LOAD_ERROR_IMAGE_FRAME:
+ im_weprintf(w, "%s - Requested frame not in image", file);
+ break;
+#endif
default:
im_weprintf(w, "While loading %s - Unknown error (%d)",
file, err);
@@ -219,6 +249,33 @@ void feh_imlib_print_load_error(char *file, winwidget w, Imlib_Load_Error err)
}
}
+#ifdef HAVE_LIBMAGIC
+void uninit_magic(void)
+{
+ if (!magic) {
+ return;
+ }
+
+ magic_close(magic);
+ magic = NULL;
+}
+void init_magic(void)
+{
+ if (getenv("FEH_SKIP_MAGIC")) {
+ return;
+ }
+
+ if (!(magic = magic_open(MAGIC_NONE))) {
+ weprintf("unable to initialize magic library\n");
+ return;
+ }
+
+ if (magic_load(magic, NULL) != 0) {
+ weprintf("cannot load magic database: %s\n", magic_error(magic));
+ uninit_magic();
+ }
+}
+
/*
* This is a workaround for an Imlib2 regression, causing unloadable image
* detection to be excessively slow (and, thus, causing feh to hang for a while
@@ -226,90 +283,53 @@ void feh_imlib_print_load_error(char *file, winwidget w, Imlib_Load_Error err)
* avoid calling Imlib2 for files it probably cannot handle. See
* <https://phab.enlightenment.org/T8739> and
* <https://github.com/derf/feh/issues/505>.
- *
- * Note that this drops support for bz2-compressed files, unless
- * FEH_SKIP_MAGIC is set
*/
-int feh_is_image(feh_file * file)
+int feh_is_image(feh_file * file, int magic_flags)
{
- unsigned char buf[16];
- FILE *fh = fopen(file->filename, "r");
- if (!fh) {
- return 0;
- }
- if (fread(buf, 1, 16, fh) != 16) {
- return 0;
- }
- fclose(fh);
+ const char * mime_type = NULL;
- if (buf[0] == 0xff && buf[1] == 0xd8) {
- // JPEG
- return 1;
- }
- if (!memcmp(buf, "\x89PNG\x0d\x0a\x1a\x0a", 8)) {
- // PNG
- return 1;
- }
- if (buf[0] == 'A' && buf[1] == 'R' && buf[2] == 'G' && buf[3] == 'B') {
- // ARGB
- return 1;
- }
- if (buf[0] == 'B' && buf[1] == 'M') {
- // BMP
- return 1;
- }
- if (!memcmp(buf, "farbfeld", 8)) {
- // farbfeld
- return 1;
- }
- if (buf[0] == 'G' && buf[1] == 'I' && buf[2] == 'F') {
- // GIF
+ if (!magic) {
return 1;
}
- if (buf[0] == 0x00 && buf[1] == 0x00 && buf[2] <= 0x02 && buf[3] == 0x00) {
- // ICO
- return 1;
- }
- if (!memcmp(buf, "FORM", 4)) {
- // Amiga IFF ILBM
- return 1;
- }
- if (buf[0] == 'P' && buf[1] >= '1' && buf[1] <= '7') {
- // PNM et al.
- return 1;
- }
- if (strstr(file->filename, ".tga")) {
- // TGA
- return 1;
- }
- if (!memcmp(buf, "II\x2a\x00", 4) || !memcmp(buf, "MM\x00\x2a", 4)) {
- // TIFF
- return 1;
- }
- if (!memcmp(buf, "RIFF", 4)) {
- // might be webp
- return 1;
+
+ magic_setflags(magic, MAGIC_MIME_TYPE | MAGIC_SYMLINK | magic_flags);
+ mime_type = magic_file(magic, file->filename);
+
+ if (!mime_type) {
+ return 0;
}
- buf[15] = 0;
- if (strstr((char *)buf, "XPM")) {
- // XPM
+
+ D(("file %s has mime type: %s\n", file->filename, mime_type));
+
+ if (strncmp(mime_type, "image/", 6) == 0) {
return 1;
}
- if (strstr(file->filename, ".bz2") || strstr(file->filename, ".gz")) {
- // Imlib2 supports compressed images. It relies on the filename to
- // determine the appropriate loader and does not use magic bytes here.
- return 1;
+
+ /* no infinite loop on compressed content, please */
+ if (magic_flags) {
+ return 0;
}
- // moved to the end as this variable won't be set in most cases
- if (getenv("FEH_SKIP_MAGIC")) {
- return 1;
+
+ /* imlib2 supports loading compressed images, let's have a look inside */
+ if (strcmp(mime_type, "application/gzip") == 0 ||
+ strcmp(mime_type, "application/x-bzip2") == 0 ||
+ strcmp(mime_type, "application/x-xz") == 0) {
+ return feh_is_image(file, MAGIC_COMPRESS);
}
+
return 0;
}
+#else
+int feh_is_image(__attribute__((unused)) feh_file * file, __attribute__((unused)) int magic_flags)
+{
+ return 1;
+}
+#endif
int feh_load_image(Imlib_Image * im, feh_file * file)
{
Imlib_Load_Error err = IMLIB_LOAD_ERROR_NONE;
+ enum feh_load_error feh_err = LOAD_ERROR_IMLIB;
enum { SRC_IMLIB, SRC_HTTP, SRC_MAGICK, SRC_DCRAW } image_source = SRC_IMLIB;
char *tmpname = NULL;
char *real_filename = NULL;
@@ -322,19 +342,16 @@ int feh_load_image(Imlib_Image * im, feh_file * file)
if (path_is_url(file->filename)) {
image_source = SRC_HTTP;
- if ((tmpname = feh_http_load_image(file->filename)) == NULL)
+ if ((tmpname = feh_http_load_image(file->filename)) == NULL) {
+ feh_err = LOAD_ERROR_CURL;
err = IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST;
- }
- else if (opt.conversion_timeout >= 0 && feh_file_is_raw(file->filename)) {
- image_source = SRC_DCRAW;
- tmpname = feh_dcraw_load_image(file->filename);
- if (!tmpname)
- err = IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT;
+ }
}
else {
- if (feh_is_image(file)) {
+ if (feh_is_image(file, 0)) {
*im = imlib_load_image_with_error_return(file->filename, &err);
} else {
+ feh_err = LOAD_ERROR_MAGICBYTES;
err = IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT;
}
}
@@ -342,8 +359,20 @@ int feh_load_image(Imlib_Image * im, feh_file * file)
if (opt.conversion_timeout >= 0 && (
(err == IMLIB_LOAD_ERROR_UNKNOWN) ||
(err == IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT))) {
- image_source = SRC_MAGICK;
- tmpname = feh_magick_load_image(file->filename);
+ if (feh_file_is_raw(file->filename)) {
+ image_source = SRC_DCRAW;
+ tmpname = feh_dcraw_load_image(file->filename);
+ if (!tmpname) {
+ feh_err = LOAD_ERROR_DCRAW;
+ }
+ } else {
+ image_source = SRC_MAGICK;
+ feh_err = LOAD_ERROR_IMLIB;
+ tmpname = feh_magick_load_image(file->filename);
+ if (!tmpname) {
+ feh_err = LOAD_ERROR_IMAGEMAGICK;
+ }
+ }
}
if (tmpname) {
@@ -366,7 +395,14 @@ int feh_load_image(Imlib_Image * im, feh_file * file)
file->filename = real_filename;
#ifdef HAVE_LIBEXIF
- file->ed = exif_get_data(tmpname);
+ /*
+ * if we're called from within feh_reload_image, file->ed is already
+ * populated.
+ */
+ if (file->ed) {
+ exif_data_unref(file->ed);
+ }
+ file->ed = exif_data_new_from_file(tmpname);
#endif
}
if (!opt.use_conversion_cache && ((image_source != SRC_HTTP) || !opt.keep_http))
@@ -376,8 +412,19 @@ int feh_load_image(Imlib_Image * im, feh_file * file)
// add_file_to_rm_filelist duplicates tmpname
add_file_to_rm_filelist(tmpname);
- if (image_source != SRC_HTTP && !opt.use_conversion_cache)
+ if (!opt.use_conversion_cache)
free(tmpname);
+ } else if (im) {
+#ifdef HAVE_LIBEXIF
+ /*
+ * if we're called from within feh_reload_image, file->ed is already
+ * populated.
+ */
+ if (file->ed) {
+ exif_data_unref(file->ed);
+ }
+ file->ed = exif_data_new_from_file(file->filename);
+#endif
}
if ((err) || (!im)) {
@@ -385,7 +432,7 @@ int feh_load_image(Imlib_Image * im, feh_file * file)
fputs("\n", stderr);
reset_output = 1;
}
- feh_imlib_print_load_error(file->filename, NULL, err);
+ feh_print_load_error(file->filename, NULL, err, feh_err);
D(("Load *failed*\n"));
return(0);
}
@@ -402,14 +449,13 @@ int feh_load_image(Imlib_Image * im, feh_file * file)
#ifdef HAVE_LIBEXIF
int orientation = 0;
- ExifData *exifData = exif_data_new_from_file(file->filename);
- if (exifData) {
- ExifByteOrder byteOrder = exif_data_get_byte_order(exifData);
- ExifEntry *exifEntry = exif_data_get_entry(exifData, EXIF_TAG_ORIENTATION);
- if (exifEntry && opt.auto_rotate)
+ if (file->ed) {
+ ExifByteOrder byteOrder = exif_data_get_byte_order(file->ed);
+ ExifEntry *exifEntry = exif_data_get_entry(file->ed, EXIF_TAG_ORIENTATION);
+ if (exifEntry && opt.auto_rotate) {
orientation = exif_get_short(exifEntry->data, byteOrder);
+ }
}
- file->ed = exifData;
if (orientation == 2)
gib_imlib_image_flip_horizontal(*im);
@@ -527,11 +573,9 @@ static int feh_file_is_raw(char *filename)
}
if (childpid == 0) {
- if (opt.quiet) {
- int devnull = open("/dev/null", O_WRONLY);
- dup2(devnull, 1);
- dup2(devnull, 2);
- }
+ int devnull = open("/dev/null", O_WRONLY);
+ dup2(devnull, 1);
+ dup2(devnull, 2);
execlp("dcraw", "dcraw", "-i", filename, NULL);
_exit(1);
} else {
@@ -591,9 +635,7 @@ static char *feh_dcraw_load_image(char *filename)
close(fd);
return NULL;
} else if (childpid == 0) {
-
- close(1);
- dup(fd);
+ dup2(fd, STDOUT_FILENO);
close(fd);
alarm(opt.conversion_timeout);
@@ -818,15 +860,32 @@ static char *feh_http_load_image(char *url)
}
basename = strrchr(url, '/') + 1;
- tmpname = feh_unique_filename(path, basename);
- if (strlen(tmpname) > (NAME_MAX-6))
- tmpname[NAME_MAX-7] = '\0';
+#ifdef HAVE_MKSTEMPS
+ tmpname = estrjoin("_", "feh_curl_XXXXXX", basename, NULL);
- sfn = estrjoin("_", tmpname, "XXXXXX", NULL);
+ if (strlen(tmpname) > NAME_MAX) {
+ tmpname[NAME_MAX] = '\0';
+ }
+#else
+ if (strlen(basename) > NAME_MAX-7) {
+ tmpname = estrdup("feh_curl_XXXXXX");
+ } else {
+ tmpname = estrjoin("_", "feh_curl", basename, "XXXXXX", NULL);
+ }
+#endif
+
+ sfn = estrjoin("", path, tmpname, NULL);
free(tmpname);
+ D(("sfn is %s\n", sfn))
+
+#ifdef HAVE_MKSTEMPS
+ fd = mkstemps(sfn, strlen(basename) + 1);
+#else
fd = mkstemp(sfn);
+#endif
+
if (fd != -1) {
sfp = fdopen(fd, "w+");
if (sfp != NULL) {
@@ -835,8 +894,8 @@ static char *feh_http_load_image(char *url)
#endif
/*
* Do not allow requests to take longer than 30 minutes.
- * This should be sufficiently high to accomodate use cases with
- * unusually high latencies, while at the sime time avoiding
+ * This should be sufficiently high to accommodate use cases with
+ * unusually high latencies, while at the same time avoiding
* feh hanging indefinitely in unattended slideshows.
*/
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1800);
@@ -844,6 +903,7 @@ static char *feh_http_load_image(char *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_USERAGENT, PACKAGE "/" VERSION);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
#if LIBCURL_VERSION_NUM >= 0x072000 /* 07.32.0 */
@@ -885,7 +945,11 @@ static char *feh_http_load_image(char *url)
close(fd);
}
} else {
+#ifdef HAVE_MKSTEMPS
+ weprintf("open url: mkstemps failed:");
+#else
weprintf("open url: mkstemp failed:");
+#endif
free(sfn);
}
curl_easy_cleanup(curl);
@@ -1115,7 +1179,7 @@ void feh_draw_exif(winwidget w)
if (buffer[0] == '\0')
{
- snprintf(buffer, EXIF_MAX_DATA, "%s", estrdup("Failed to run exif command"));
+ snprintf(buffer, EXIF_MAX_DATA, "%s", "Failed to run exif command");
gib_imlib_get_text_size(fn, buffer, NULL, &width, &height, IMLIB_TEXT_TO_RIGHT);
info_buf[no_lines] = estrdup(buffer);
no_lines++;
@@ -1127,29 +1191,28 @@ void feh_draw_exif(winwidget w)
{
/* max 128 lines */
pos2 = 0;
- while ( pos2 < 256 ) /* max 256 chars per line */
+ while ( pos2 < 255 ) /* max 255 chars + 1 null byte per line */
{
if ( (buffer[pos] != '\n')
&& (buffer[pos] != '\0') )
{
- info_line[pos2] = buffer[pos];
- }
- else if ( buffer[pos] == '\0' )
- {
- pos = EXIF_MAX_DATA; /* all data seen */
- info_line[pos2] = '\0';
+ info_line[pos2] = buffer[pos];
+ }
+ else if ( buffer[pos] == '\0' )
+ {
+ pos = EXIF_MAX_DATA; /* all data seen */
+ break;
+ }
+ else
+ {
+ pos++; /* line finished, continue with next line*/
+ break;
}
- else
- {
- info_line[pos2] = '\0'; /* line finished, continue with next line*/
-
- pos++;
- break;
- }
- pos++;
- pos2++;
+ pos++;
+ pos2++;
}
+ info_line[pos2] = '\0';
gib_imlib_get_text_size(fn, info_line, NULL, &line_width,
&line_height, IMLIB_TEXT_TO_RIGHT);
@@ -1184,6 +1247,7 @@ void feh_draw_exif(winwidget w)
info_buf[i], IMLIB_TEXT_TO_RIGHT, 0, 0, 0, 255);
gib_imlib_text_draw(im, fn, NULL, 1, (i * line_height) + 1,
info_buf[i], IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255);
+ free(info_buf[i]);
}
@@ -1514,8 +1578,8 @@ void feh_edit_inplace(winwidget w, int op)
FEH_FILE(w->file->data)->filename, &err);
gib_imlib_free_image(old);
if (err)
- feh_imlib_print_load_error(FEH_FILE(w->file->data)->filename,
- w, err);
+ feh_print_load_error(FEH_FILE(w->file->data)->filename,
+ w, err, LOAD_ERROR_IMLIB);
feh_reload_image(w, 1, 1);
} else {
/*
diff --git a/src/index.c b/src/index.c
index 3633c96..b0b6923 100644
--- a/src/index.c
+++ b/src/index.c
@@ -1,7 +1,7 @@
/* index.c
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -131,7 +131,7 @@ void init_index_mode(void)
weprintf(
"The image size you specified (%dx%d) is not large\n"
"enough to hold all %d thumbnails. To fit all the thumbnails,\n"
- "either decrease their size, choos e asmaller font,\n"
+ "either decrease their size, choose a smaller font,\n"
"or use a larger image (like %dx%d)",
opt.limit_w, opt.limit_h, filelist_len, w, h);
h = opt.limit_h;
@@ -332,7 +332,7 @@ void init_index_mode(void)
gib_imlib_save_image_with_error_return(im_main, output_buf, &err);
if (err) {
- feh_imlib_print_load_error(output_buf, im_main, err);
+ feh_print_load_error(output_buf, im_main, err, LOAD_ERROR_IMLIB);
}
else if (opt.verbose) {
int tw, th;
diff --git a/src/index.h b/src/index.h
index b022f1a..b805cc0 100644
--- a/src/index.h
+++ b/src/index.h
@@ -1,6 +1,6 @@
/* index.h
-Copyright (C) 2018 Daniel Friesel.
+Copyright (C) 2018 Birte Kristina 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 a5526a2..2f9b1d6 100644
--- a/src/keyevents.c
+++ b/src/keyevents.c
@@ -1,7 +1,7 @@
/* keyevents.c
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -35,7 +35,7 @@ struct __fehkey keys[EVENT_LIST_END];
struct termios old_term_settings;
unsigned char control_via_stdin = 0;
-void setup_stdin() {
+void setup_stdin(void) {
struct termios ctrl;
control_via_stdin = 1;
@@ -55,7 +55,7 @@ void setup_stdin() {
eprintf("tcsetattr failed");
}
-void restore_stdin() {
+void restore_stdin(void) {
if (tcsetattr(STDIN_FILENO, TCSANOW, &old_term_settings) == -1)
eprintf("tcsetattr failed");
}
@@ -314,12 +314,12 @@ void feh_event_invoke_action(winwidget winwid, unsigned char action)
return;
}
-void feh_event_handle_stdin()
+void feh_event_handle_stdin(void)
{
char stdin_buf[2];
static char is_esc = 0;
KeySym keysym = NoSymbol;
- if (read(STDIN_FILENO, &stdin_buf, 1) == -1) {
+ if (read(STDIN_FILENO, &stdin_buf, 1) <= 0) {
control_via_stdin = 0;
if (isatty(STDIN_FILENO) && getpgrp() == (tcgetpgrp(STDIN_FILENO))) {
weprintf("reading a command from stdin failed - disabling control via stdin");
@@ -359,7 +359,7 @@ void feh_event_handle_stdin()
else
keysym = XStringToKeysym(stdin_buf);
- if (window_num)
+ if (window_num && keysym)
feh_event_handle_generic(windows[0], is_esc * Mod1Mask, keysym, 0);
is_esc = 0;
@@ -603,7 +603,7 @@ void feh_event_handle_generic(winwidget winwid, unsigned int state, KeySym keysy
}
else if (feh_is_kp(EVENT_zoom_in, state, keysym, button)) {
winwid->old_zoom = winwid->zoom;
- winwid->zoom = winwid->zoom * 1.25;
+ winwid->zoom = winwid->zoom * opt.zoom_rate;
if (winwid->zoom > ZOOM_MAX)
winwid->zoom = ZOOM_MAX;
@@ -617,7 +617,7 @@ void feh_event_handle_generic(winwidget winwid, unsigned int state, KeySym keysy
}
else if (feh_is_kp(EVENT_zoom_out, state, keysym, button)) {
winwid->old_zoom = winwid->zoom;
- winwid->zoom = winwid->zoom * 0.80;
+ winwid->zoom = winwid->zoom / opt.zoom_rate;
if (winwid->zoom < ZOOM_MIN)
winwid->zoom = ZOOM_MIN;
diff --git a/src/list.c b/src/list.c
index 83df407..f293af3 100644
--- a/src/list.c
+++ b/src/list.c
@@ -1,7 +1,7 @@
/* list.c
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina 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/main.c b/src/main.c
index 1497be2..78ee616 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,7 +1,7 @@
/* main.c
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -49,6 +49,11 @@ int main(int argc, char **argv)
srandom(getpid() * time(NULL) % ((unsigned int) -1));
setup_signal_handlers();
+
+#ifdef HAVE_LIBMAGIC
+ init_magic();
+#endif
+
init_parse_options(argc, argv);
init_imlib_fonts();
@@ -102,6 +107,28 @@ int main(int argc, char **argv)
return(sig_exit);
}
+static void feh_process_signal(void)
+{
+ winwidget winwid = winwidget_get_first_window_of_type(WIN_TYPE_SLIDESHOW);
+ int i;
+ int signo = sig_received;
+ sig_received = 0;
+
+ if (winwid) {
+ if (filelist_len > 1) {
+ if (signo == SIGUSR1)
+ slideshow_change_image(winwid, SLIDE_NEXT, 1);
+ else if (signo == SIGUSR2)
+ slideshow_change_image(winwid, SLIDE_PREV, 1);
+ } else {
+ feh_reload_image(winwid, 0, 0);
+ }
+ } else if (opt.multiwindow) {
+ for (i = window_num - 1; i >= 0; i--)
+ feh_reload_image(windows[i], 0, 0);
+ }
+}
+
/* Return 0 to stop iterating, 1 if ok to continue. */
int feh_main_iteration(int block)
{
@@ -119,6 +146,10 @@ int feh_main_iteration(int block)
if (window_num == 0 || sig_exit != 0)
return(0);
+ if (sig_received) {
+ feh_process_signal();
+ }
+
if (first) {
/* Only need to set these up the first time */
xfd = ConnectionNumber(disp);
@@ -151,6 +182,10 @@ int feh_main_iteration(int block)
if (window_num == 0 || sig_exit != 0)
return(0);
+
+ if (sig_received) {
+ feh_process_signal();
+ }
}
XFlush(disp);
@@ -158,8 +193,9 @@ int feh_main_iteration(int block)
FD_ZERO(&fdset);
FD_SET(xfd, &fdset);
- if (control_via_stdin)
+ if (control_via_stdin) {
FD_SET(STDIN_FILENO, &fdset);
+ }
#ifdef HAVE_INOTIFY
if (opt.auto_reload) {
FD_SET(opt.inotify_fd, &fdset);
@@ -210,7 +246,12 @@ int feh_main_iteration(int block)
in that */
feh_handle_timer();
}
- else if ((count > 0) && (FD_ISSET(0, &fdset)))
+ /*
+ * Beware: If stdin is not connected, we may end up with xfd == 0.
+ * However, STDIN_FILENO == 0 holds as well in most cases. So we must
+ * check control_via_stdin to avoid mistaking an X11 event for stdin.
+ */
+ else if ((count > 0) && control_via_stdin && (FD_ISSET(STDIN_FILENO, &fdset)))
feh_event_handle_stdin();
#ifdef HAVE_INOTIFY
else if ((count > 0) && (FD_ISSET(opt.inotify_fd, &fdset)))
@@ -227,7 +268,7 @@ int feh_main_iteration(int block)
&& ((errno == ENOMEM) || (errno == EINVAL)
|| (errno == EBADF)))
eprintf("Connection to X display lost");
- else if ((count > 0) && (FD_ISSET(0, &fdset)))
+ else if ((count > 0) && control_via_stdin && (FD_ISSET(STDIN_FILENO, &fdset)))
feh_event_handle_stdin();
#ifdef HAVE_INOTIFY
else if ((count > 0) && (FD_ISSET(opt.inotify_fd, &fdset)))
@@ -237,7 +278,11 @@ int feh_main_iteration(int block)
}
if (window_num == 0 || sig_exit != 0)
return(0);
-
+
+ if (sig_received) {
+ feh_process_signal();
+ }
+
return(1);
}
@@ -256,6 +301,10 @@ void feh_clean_exit(void)
if(disp)
XCloseDisplay(disp);
+#ifdef HAVE_LIBMAGIC
+ uninit_magic();
+#endif
+
/*
* Only restore the old terminal settings if
* - we changed them in the first place
diff --git a/src/menu.c b/src/menu.c
index b1deedb..b1ef61d 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -1,7 +1,7 @@
/* menu.c
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -825,21 +825,17 @@ void feh_menu_draw_toggle_at(int x, int y, int w, int h, Imlib_Image dst, int ox
void feh_menu_draw_submenu_at(int x, int y, Imlib_Image dst, int ox, int oy)
{
- ImlibPolygon poly;
-
- x -= ox;
+ // Draw filled triangle
+ x -= ox;
y -= oy;
imlib_context_set_image(dst);
-
- poly = imlib_polygon_new();
- imlib_polygon_add_point(poly, x, y + 3);
- imlib_polygon_add_point(poly, x + 3, y + 6);
- imlib_polygon_add_point(poly, x, y + 9);
imlib_context_set_color(0, 0, 0, 255);
- imlib_image_fill_polygon(poly);
- imlib_polygon_free(poly);
+ for (int i= 0; i <= 3; i++) {
+ imlib_image_draw_line(x+i, y+3+i, x+i, y+9-i, 0);
+ }
+
return;
}
@@ -936,7 +932,7 @@ void feh_menu_init_main(void)
return;
}
-void feh_menu_init_common()
+void feh_menu_init_common(void)
{
int num_desks, i;
char buf[30];
diff --git a/src/menu.h b/src/menu.h
index 3ab29bc..5bad00c 100644
--- a/src/menu.h
+++ b/src/menu.h
@@ -1,7 +1,7 @@
/* menu.h
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina 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/options.c b/src/options.c
index 04f02c5..0fc656d 100644
--- a/src/options.c
+++ b/src/options.c
@@ -1,7 +1,7 @@
/* options.c
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -63,6 +63,8 @@ void init_parse_options(int argc, char **argv)
opt.font = NULL;
opt.max_height = opt.max_width = UINT_MAX;
+ opt.zoom_rate = 1.25;
+
opt.start_list_at = NULL;
opt.jump_on_resort = 1;
@@ -330,109 +332,111 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
/* (*name, has_arg, *flag, val) See: struct option in getopts.h */
static struct option lopts[] = {
- {"debug" , 0, 0, '+'},
- {"scale-down" , 0, 0, '.'},
- {"max-dimension" , 1, 0, '<'},
- {"min-dimension" , 1, 0, '>'},
- {"title-font" , 1, 0, '@'},
- {"action" , 1, 0, 'A'},
- {"image-bg" , 1, 0, 'B'},
- {"fontpath" , 1, 0, 'C'},
- {"slideshow-delay",1, 0, 'D'},
- {"thumb-height" , 1, 0, 'E'},
- {"full-screen" , 0, 0, 'F'}, /* deprecated */
- {"fullscreen" , 0, 0, 'F'},
- {"draw-actions" , 0, 0, 'G'},
- {"limit-height" , 1, 0, 'H'},
- {"fullindex" , 0, 0, 'I'},
- {"thumb-redraw" , 1, 0, 'J'},
- {"caption-path" , 1, 0, 'K'},
- {"customlist" , 1, 0, 'L'},
- {"menu-font" , 1, 0, 'M'},
- {"no-menus" , 0, 0, 'N'},
- {"output-only" , 1, 0, 'O'},
- {"cache-thumbnails", 0, 0, 'P'},
- {"reload" , 1, 0, 'R'},
- {"sort" , 1, 0, 'S'},
- {"theme" , 1, 0, 'T'},
- {"loadable" , 0, 0, 'U'},
- {"verbose" , 0, 0, 'V'},
- {"limit-width" , 1, 0, 'W'},
- {"ignore-aspect" , 0, 0, 'X'},
- {"hide-pointer" , 0, 0, 'Y'},
- {"auto-zoom" , 0, 0, 'Z'},
- {"title" , 1, 0, '^'},
- {"alpha" , 1, 0, 'a'},
- {"bg" , 1, 0, 'b'},
- {"draw-filename" , 0, 0, 'd'},
- {"font" , 1, 0, 'e'},
- {"filelist" , 1, 0, 'f'},
- {"geometry" , 1, 0, 'g'},
- {"help" , 0, 0, 'h'},
- {"index" , 0, 0, 'i'},
- {"output-dir" , 1, 0, 'j'},
- {"keep-http" , 0, 0, 'k'},
- {"list" , 0, 0, 'l'},
- {"montage" , 0, 0, 'm'},
- {"reverse" , 0, 0, 'n'},
- {"output" , 1, 0, 'o'},
- {"preload" , 0, 0, 'p'},
- {"quiet" , 0, 0, 'q'},
- {"recursive" , 0, 0, 'r'},
- {"stretch" , 0, 0, 's'},
- {"thumbnails" , 0, 0, 't'},
- {"unloadable" , 0, 0, 'u'},
- {"version" , 0, 0, 'v'},
- {"multiwindow" , 0, 0, 'w'},
- {"borderless" , 0, 0, 'x'},
- {"thumb-width" , 1, 0, 'y'},
- {"randomize" , 0, 0, 'z'},
- {"start-at" , 1, 0, '|'},
- {"thumb-title" , 1, 0, '~'},
- {"bg-tile" , 0, 0, 200},
- {"bg-center" , 0, 0, 201},
- {"bg-scale" , 0, 0, 202},
- {"zoom" , 1, 0, 205},
- {"no-screen-clip", 0, 0, 206},
- {"index-info" , 1, 0, 207},
- {"magick-timeout", 1, 0, 208},
- {"action1" , 1, 0, 209},
- {"action2" , 1, 0, 210},
- {"action3" , 1, 0, 211},
- {"action4" , 1, 0, 212},
- {"action5" , 1, 0, 213},
- {"action6" , 1, 0, 214},
- {"action7" , 1, 0, 215},
- {"action8" , 1, 0, 216},
- {"action9" , 1, 0, 217},
- {"bg-fill" , 0, 0, 218},
- {"bg-max" , 0, 0, 219},
- {"no-jump-on-resort", 0, 0, 220},
- {"edit" , 0, 0, 221},
+ {"debug" , 0, 0, OPTION_debug},
+ {"scale-down" , 0, 0, OPTION_scale_down},
+ {"max-dimension" , 1, 0, OPTION_max_dimension},
+ {"min-dimension" , 1, 0, OPTION_min_dimension},
+ {"title-font" , 1, 0, OPTION_title_font},
+ {"action" , 1, 0, OPTION_action},
+ {"image-bg" , 1, 0, OPTION_image_bg},
+ {"fontpath" , 1, 0, OPTION_fontpath},
+ {"slideshow-delay",1, 0, OPTION_slideshow_delay},
+ {"thumb-height" , 1, 0, OPTION_thumb_height},
+ {"full-screen" , 0, 0, OPTION_fullscreen}, /* deprecated */
+ {"fullscreen" , 0, 0, OPTION_fullscreen},
+ {"draw-actions" , 0, 0, OPTION_draw_actions},
+ {"limit-height" , 1, 0, OPTION_limit_height},
+ {"fullindex" , 0, 0, OPTION_fullindex},
+ {"thumb-redraw" , 1, 0, OPTION_thumb_redraw},
+ {"caption-path" , 1, 0, OPTION_caption_path},
+ {"customlist" , 1, 0, OPTION_customlist},
+ {"menu-font" , 1, 0, OPTION_menu_font},
+ {"no-menus" , 0, 0, OPTION_no_menus},
+ {"output-only" , 1, 0, OPTION_output_only},
+ {"cache-thumbnails", 0, 0, OPTION_cache_thumbnails},
+ {"reload" , 1, 0, OPTION_reload},
+ {"sort" , 1, 0, OPTION_sort},
+ {"theme" , 1, 0, OPTION_theme},
+ {"loadable" , 0, 0, OPTION_loadable},
+ {"verbose" , 0, 0, OPTION_verbose},
+ {"limit-width" , 1, 0, OPTION_limit_width},
+ {"ignore-aspect" , 0, 0, OPTION_ignore_aspect},
+ {"hide-pointer" , 0, 0, OPTION_hide_pointer},
+ {"auto-zoom" , 0, 0, OPTION_auto_zoom},
+ {"title" , 1, 0, OPTION_title},
+ {"alpha" , 1, 0, OPTION_alpha},
+ {"bg" , 1, 0, OPTION_bg},
+ {"draw-filename" , 0, 0, OPTION_draw_filename},
+ {"font" , 1, 0, OPTION_font},
+ {"filelist" , 1, 0, OPTION_filelist},
+ {"geometry" , 1, 0, OPTION_geometry},
+ {"help" , 0, 0, OPTION_help},
+ {"index" , 0, 0, OPTION_index},
+ {"output-dir" , 1, 0, OPTION_output_dir},
+ {"keep-http" , 0, 0, OPTION_keep_http},
+ {"list" , 0, 0, OPTION_list},
+ {"montage" , 0, 0, OPTION_montage},
+ {"reverse" , 0, 0, OPTION_reverse},
+ {"output" , 1, 0, OPTION_output},
+ {"preload" , 0, 0, OPTION_preload},
+ {"quiet" , 0, 0, OPTION_quiet},
+ {"recursive" , 0, 0, OPTION_recursive},
+ {"stretch" , 0, 0, OPTION_stretch},
+ {"thumbnails" , 0, 0, OPTION_thumbnails},
+ {"unloadable" , 0, 0, OPTION_unloadable},
+ {"version" , 0, 0, OPTION_version},
+ {"multiwindow" , 0, 0, OPTION_multiwindow},
+ {"borderless" , 0, 0, OPTION_borderless},
+ {"thumb-width" , 1, 0, OPTION_thumb_width},
+ {"randomize" , 0, 0, OPTION_randomize},
+ {"start-at" , 1, 0, OPTION_start_at},
+ {"thumb-title" , 1, 0, OPTION_thumb_title},
+ {"bg-tile" , 0, 0, OPTION_bg_title},
+ {"bg-center" , 0, 0, OPTION_bg_center},
+ {"bg-scale" , 0, 0, OPTION_bg_scale},
+ {"zoom" , 1, 0, OPTION_zoom},
+ {"zoom-step" , 1, 0, OPTION_zoom_step},
+ {"no-screen-clip", 0, 0, OPTION_no_screen_clip},
+ {"index-info" , 1, 0, OPTION_index_info},
+ {"magick-timeout", 1, 0, OPTION_magick_timeout},
+ {"action1" , 1, 0, OPTION_action1},
+ {"action2" , 1, 0, OPTION_action2},
+ {"action3" , 1, 0, OPTION_action3},
+ {"action4" , 1, 0, OPTION_action4},
+ {"action5" , 1, 0, OPTION_action5},
+ {"action6" , 1, 0, OPTION_action6},
+ {"action7" , 1, 0, OPTION_action7},
+ {"action8" , 1, 0, OPTION_action8},
+ {"action9" , 1, 0, OPTION_action9},
+ {"bg-fill" , 0, 0, OPTION_bg_fill},
+ {"bg-max" , 0, 0, OPTION_bg_max},
+ {"no-jump-on-resort", 0, 0, OPTION_no_jump_on_resort},
+ {"edit" , 0, 0, OPTION_edit},
#ifdef HAVE_LIBEXIF
- {"draw-exif" , 0, 0, 223},
- {"auto-rotate" , 0, 0, 242},
+ {"draw-exif" , 0, 0, OPTION_draw_exif},
+ {"auto-rotate" , 0, 0, OPTION_auto_rotate},
#endif
- {"no-xinerama" , 0, 0, 225},
- {"draw-tinted" , 0, 0, 229},
- {"info" , 1, 0, 234},
- {"force-aliasing", 0, 0, 235},
- {"no-fehbg" , 0, 0, 236},
- {"keep-zoom-vp" , 0, 0, 237},
- {"scroll-step" , 1, 0, 238},
- {"xinerama-index", 1, 0, 239},
- {"insecure" , 0, 0, 240},
- {"no-recursive" , 0, 0, 241},
- {"cache-size" , 1, 0, 243},
- {"on-last-slide" , 1, 0, 244},
- {"conversion-timeout" , 1, 0, 245},
- {"version-sort" , 0, 0, 246},
- {"offset" , 1, 0, 247},
+ {"no-xinerama" , 0, 0, OPTION_no_xinerama},
+ {"draw-tinted" , 0, 0, OPTION_draw_tinted},
+ {"info" , 1, 0, OPTION_info},
+ {"force-aliasing", 0, 0, OPTION_force_aliasing},
+ {"no-fehbg" , 0, 0, OPTION_no_fehbg},
+ {"keep-zoom-vp" , 0, 0, OPTION_keep_zoom_vp},
+ {"scroll-step" , 1, 0, OPTION_scroll_step},
+ {"xinerama-index", 1, 0, OPTION_xinerama_index},
+ {"insecure" , 0, 0, OPTION_insecure},
+ {"no-recursive" , 0, 0, OPTION_recursive},
+ {"cache-size" , 1, 0, OPTION_cache_size},
+ {"on-last-slide" , 1, 0, OPTION_on_last_slide},
+ {"conversion-timeout" , 1, 0, OPTION_conversion_timeout},
+ {"version-sort" , 0, 0, OPTION_version_sort},
+ {"offset" , 1, 0, OPTION_offset},
#ifdef HAVE_INOTIFY
- {"auto-reload" , 0, 0, 248},
+ {"auto-reload" , 0, 0, OPTION_auto_reload},
#endif
- {"class" , 1, 0, 249},
- {"no-conversion-cache", 0, 0, 250},
+ {"class" , 1, 0, OPTION_class},
+ {"no-conversion-cache", 0, 0, OPTION_no_conversion_cache},
+ {"window-id", 1, 0, OPTION_window_id},
{0, 0, 0, 0}
};
int optch = 0, cmdx = 0;
@@ -442,10 +446,10 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
switch (optch) {
case 0:
break;
- case '+':
+ case OPTION_debug:
opt.debug = 1;
break;
- case '<':
+ case OPTION_max_dimension:
opt.filter_by_dimensions = 1;
XParseGeometry(optarg, &discard, &discard, &opt.max_width, &opt.max_height);
if (opt.max_width == 0)
@@ -453,27 +457,27 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
if (opt.max_height == 0)
opt.max_height = UINT_MAX;
break;
- case '>':
+ case OPTION_min_dimension:
opt.filter_by_dimensions = 1;
XParseGeometry(optarg, &discard, &discard, &opt.min_width, &opt.min_height);
break;
- case '.':
+ case OPTION_scale_down:
opt.scale_down = 1;
break;
- case '@':
+ case OPTION_title_font:
opt.title_font = estrdup(optarg);
break;
- case 'A':
+ case OPTION_action:
opt.actions[0] = estrdup(optarg);
break;
- case 'B':
+ case OPTION_image_bg:
opt.image_bg = estrdup(optarg);
break;
- case 'C':
+ case OPTION_fontpath:
D(("adding fontpath %s\n", optarg));
imlib_add_path_to_font_path(optarg);
break;
- case 'D':
+ case OPTION_slideshow_delay:
opt.slideshow_delay = atof(optarg);
if (opt.slideshow_delay < 0.0) {
opt.slideshow_delay *= (-1);
@@ -482,57 +486,59 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
opt.paused = 0;
}
break;
- case 'E':
+ case OPTION_thumb_height:
opt.thumb_h = atoi(optarg);
break;
- case 'F':
+ case OPTION_fullscreen:
opt.full_screen = 1;
break;
- case 'G':
+ case OPTION_draw_actions:
opt.draw_actions = 1;
break;
- case 'H':
+ case OPTION_limit_height:
opt.limit_h = atoi(optarg);
break;
- case 'I':
+ case OPTION_fullindex:
opt.index = 1;
opt.index_info = estrdup("%n\n%S\n%wx%h");
break;
- case 'J':
+ case OPTION_thumb_redraw:
opt.thumb_redraw = atoi(optarg);
break;
- case 'K':
+ case OPTION_caption_path:
opt.caption_path = estrdup(optarg);
break;
- case 'L':
+ case OPTION_customlist:
opt.customlist = estrdup(optarg);
opt.display = 0;
break;
- case 'M':
+ case OPTION_menu_font:
free(opt.menu_font);
opt.menu_font = estrdup(optarg);
break;
- case 'N':
+ case OPTION_no_menus:
opt.no_menus = 1;
break;
- case 'O':
+ case OPTION_output_only:
opt.output = 1;
opt.output_file = estrdup(optarg);
opt.display = 0;
break;
- case 'P':
+ case OPTION_cache_thumbnails:
opt.cache_thumbnails = 1;
break;
- case 'R':
+ case OPTION_reload:
opt.reload = atof(optarg);
opt.use_conversion_cache = 0;
#ifdef HAVE_INOTIFY
opt.auto_reload = 0;
#endif
break;
- case 'S':
+ case OPTION_sort:
if (!strcasecmp(optarg, "name"))
opt.sort = SORT_NAME;
+ else if (!strcasecmp(optarg, "none"))
+ opt.sort = SORT_NONE;
else if (!strcasecmp(optarg, "filename"))
opt.sort = SORT_FILENAME;
else if (!strcasecmp(optarg, "dirname"))
@@ -560,116 +566,116 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
opt.randomize = 0;
}
break;
- case 'T':
+ case OPTION_theme:
theme = estrdup(optarg);
break;
- case 'U':
+ case OPTION_loadable:
opt.loadables = 1;
opt.display = 0;
break;
- case 'V':
+ case OPTION_verbose:
opt.verbose = 1;
break;
- case 'W':
+ case OPTION_limit_width:
opt.limit_w = atoi(optarg);
break;
- case 'X':
+ case OPTION_ignore_aspect:
opt.aspect = 0;
break;
- case 'Y':
+ case OPTION_hide_pointer:
opt.hide_pointer = 1;
break;
- case 'Z':
+ case OPTION_auto_zoom:
opt.zoom_mode = ZOOM_MODE_MAX;
break;
- case '^':
+ case OPTION_title:
opt.title = estrdup(optarg);
break;
- case 'a':
+ case OPTION_alpha:
opt.alpha = 1;
opt.alpha_level = 255 - atoi(optarg);
break;
- case 'b':
+ case OPTION_bg:
opt.bg = 1;
opt.bg_file = estrdup(optarg);
break;
- case 'd':
+ case OPTION_draw_filename:
opt.draw_filename = 1;
break;
- case 'e':
+ case OPTION_font:
opt.font = estrdup(optarg);
break;
- case 'f':
+ case OPTION_filelist:
if (!strcmp(optarg, "-"))
opt.filelistfile = estrdup("/dev/stdin");
else
opt.filelistfile = estrdup(optarg);
break;
- case 'g':
+ case OPTION_geometry:
opt.geom_enabled = 1;
opt.geom_flags = XParseGeometry(optarg, &opt.geom_x,
&opt.geom_y, &opt.geom_w, &opt.geom_h);
break;
- case 'h':
+ case OPTION_help:
show_usage();
break;
- case 'i':
+ case OPTION_index:
opt.index = 1;
opt.index_info = estrdup("%n");
break;
- case 'j':
+ case OPTION_output_dir:
opt.output_dir = estrdup(optarg);
break;
- case 'k':
+ case OPTION_keep_http:
opt.keep_http = 1;
break;
- case 'l':
+ case OPTION_list:
opt.list = 1;
opt.display = 0;
break;
- case 'm':
+ case OPTION_montage:
opt.index = 1;
break;
- case 'n':
+ case OPTION_reverse:
opt.reverse = 1;
break;
- case 'o':
+ case OPTION_output:
opt.output = 1;
opt.output_file = estrdup(optarg);
break;
- case 'p':
+ case OPTION_preload:
opt.preload = 1;
break;
- case 'q':
+ case OPTION_quiet:
opt.quiet = 1;
break;
- case 'r':
+ case OPTION_recursive:
opt.recursive = 1;
break;
- case 's':
+ case OPTION_stretch:
opt.stretch = 1;
break;
- case 't':
+ case OPTION_thumbnails:
opt.thumbs = 1;
opt.index_info = estrdup("%n");
break;
- case 'u':
+ case OPTION_unloadable:
opt.unloadables = 1;
opt.display = 0;
break;
- case 'v':
+ case OPTION_version:
show_version();
break;
- case 'w':
+ case OPTION_multiwindow:
opt.multiwindow = 1;
break;
- case 'x':
+ case OPTION_borderless:
opt.borderless = 1;
break;
- case 'y':
+ case OPTION_thumb_width:
opt.thumb_w = atoi(optarg);
break;
- case 'z':
+ case OPTION_randomize:
opt.randomize = 1;
if (opt.sort != SORT_NONE) {
weprintf("commandline contains --sort and --randomize. "
@@ -677,22 +683,22 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
opt.sort = SORT_NONE;
}
break;
- case '|':
+ case OPTION_start_at:
opt.start_list_at = estrdup(optarg);
break;
- case '~':
+ case OPTION_thumb_title:
opt.thumb_title = estrdup(optarg);
break;
- case 200:
+ case OPTION_bg_title:
opt.bgmode = BG_MODE_TILE;
break;
- case 201:
+ case OPTION_bg_center:
opt.bgmode = BG_MODE_CENTER;
break;
- case 202:
+ case OPTION_bg_scale:
opt.bgmode = BG_MODE_SCALE;
break;
- case 205:
+ case OPTION_zoom:
if (!strcmp("fill", optarg))
opt.zoom_mode = ZOOM_MODE_FILL;
else if (!strcmp("max", optarg))
@@ -700,70 +706,75 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
else
opt.default_zoom = atoi(optarg);
break;
- case 206:
+ case OPTION_no_screen_clip:
opt.screen_clip = 0;
break;
- case 207:
+ case OPTION_index_info:
opt.index_info = estrdup(optarg);
break;
- case 208:
+ case OPTION_magick_timeout:
weprintf("--magick-timeout is deprecated, please use --conversion-timeout instead");
opt.conversion_timeout = atoi(optarg);
break;
- case 209:
+ case OPTION_action1:
opt.actions[1] = estrdup(optarg);
break;
- case 210:
+ case OPTION_action2:
opt.actions[2] = estrdup(optarg);
break;
- case 211:
+ case OPTION_action3:
opt.actions[3] = estrdup(optarg);
break;
- case 212:
+ case OPTION_action4:
opt.actions[4] = estrdup(optarg);
break;
- case 213:
+ case OPTION_action5:
opt.actions[5] = estrdup(optarg);
break;
- case 214:
+ case OPTION_action6:
opt.actions[6] = estrdup(optarg);
break;
- case 215:
+ case OPTION_action7:
opt.actions[7] = estrdup(optarg);
break;
- case 216:
+ case OPTION_action8:
opt.actions[8] = estrdup(optarg);
break;
- case 217:
+ case OPTION_action9:
opt.actions[9] = estrdup(optarg);
break;
- case 218:
+ case OPTION_bg_fill:
opt.bgmode = BG_MODE_FILL;
break;
- case 219:
+ case OPTION_bg_max:
opt.bgmode = BG_MODE_MAX;
break;
- case 220:
+ case OPTION_no_jump_on_resort:
opt.jump_on_resort = 0;
break;
- case 221:
+ case OPTION_edit:
opt.edit = 1;
break;
#ifdef HAVE_LIBEXIF
- case 223:
+ case OPTION_draw_exif:
opt.draw_exif = 1;
break;
- case 242:
+ case OPTION_auto_rotate:
+#if defined(IMLIB2_VERSION_MAJOR) && defined(IMLIB2_VERSION_MINOR) && defined(IMLIB2_VERSION_MICRO) && (IMLIB2_VERSION_MAJOR > 1 || IMLIB2_VERSION_MINOR > 7 || IMLIB2_VERSION_MICRO >= 5)
+ weprintf("This feh release was built with Imlib2 version %d.%d.%d, which transparently adjusts for image orientation according to EXIF data.", IMLIB2_VERSION_MAJOR, IMLIB2_VERSION_MINOR, IMLIB2_VERSION_MICRO);
+ weprintf("--auto-rotate would rotate an already correctly oriented image, resulting in incorrect orientation. It has been disabled in this build. Rebuild feh with Imlib2 <1.7.5 to enable --auto-rotate.");
+#else
opt.auto_rotate = 1;
+#endif
break;
#endif
- case 225:
+ case OPTION_no_xinerama:
opt.xinerama = 0;
break;
- case 229:
+ case OPTION_draw_tinted:
opt.text_bg = TEXT_BG_TINTED;
break;
- case 234:
+ case OPTION_info:
opt.info_cmd = estrdup(optarg);
if (opt.info_cmd[0] == ';') {
opt.draw_info = 0;
@@ -772,35 +783,35 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
opt.draw_info = 1;
}
break;
- case 235:
+ case OPTION_force_aliasing:
opt.force_aliasing = 1;
break;
- case 236:
+ case OPTION_no_fehbg:
opt.no_fehbg = 1;
break;
- case 237:
+ case OPTION_keep_zoom_vp:
opt.keep_zoom_vp = 1;
break;
- case 238:
+ case OPTION_scroll_step:
opt.scroll_step = atoi(optarg);
break;
- case 239:
+ case OPTION_xinerama_index:
opt.xinerama_index = atoi(optarg);
break;
- case 240:
+ case OPTION_insecure:
opt.insecure_ssl = 1;
break;
- case 241:
+ case OPTION_no_recursive:
opt.recursive = 0;
break;
- case 243:
+ case OPTION_cache_size:
opt.cache_size = atoi(optarg);
if (opt.cache_size < 0)
opt.cache_size = 0;
if (opt.cache_size > 2048)
opt.cache_size = 2048;
break;
- case 244:
+ case OPTION_on_last_slide:
if (!strcmp(optarg, "quit")) {
opt.on_last_slide = ON_LAST_SLIDE_QUIT;
} else if (!strcmp(optarg, "hold")) {
@@ -812,27 +823,39 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
"Supported actions: hold, resume, quit\n", optarg);
}
break;
- case 245:
+ case OPTION_conversion_timeout:
opt.conversion_timeout = atoi(optarg);
break;
- case 246:
+ case OPTION_version_sort:
opt.version_sort = 1;
break;
- case 247:
+ case OPTION_offset:
opt.offset_flags = XParseGeometry(optarg, &opt.offset_x,
&opt.offset_y, (unsigned int *)&discard, (unsigned int *)&discard);
break;
#ifdef HAVE_INOTIFY
- case 248:
+ case OPTION_auto_reload:
opt.auto_reload = 1;
break;
#endif
- case 249:
+ case OPTION_class:
opt.x11_class = estrdup(optarg);
break;
- case 250:
+ case OPTION_no_conversion_cache:
opt.use_conversion_cache = 0;
break;
+ case OPTION_window_id:
+ opt.x11_windowid = strtol(optarg, NULL, 0);
+ break;
+ case OPTION_zoom_step:
+ opt.zoom_rate = atof(optarg);
+ if ((opt.zoom_rate <= 0)) {
+ weprintf("Zooming disabled due to --zoom-step=%f", opt.zoom_rate);
+ opt.zoom_rate = 1.0;
+ } else {
+ opt.zoom_rate = 1 + ((float)opt.zoom_rate / 100);
+ }
+ break;
default:
break;
}
@@ -855,11 +878,26 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
*/
if (opt.start_list_at && path_is_url(opt.start_list_at) && (strlen(opt.start_list_at) <= 8 || strncmp(opt.start_list_at, "file:///", 8) != 0)) {
add_file_to_filelist_recursively(opt.start_list_at, FILELIST_FIRST);
+ /*
+ * Otherwise, make "feh --start-at dir/file.jpg" behave like
+ * "feh --start-at dir/file.jpg dir".
+ */
} else if (opt.start_list_at && strrchr(opt.start_list_at, '/')) {
+ /*
+ * feh can't candle urlencoded path components ("some%20dir" etc).
+ * Use libcurl to unescape them if --start-at is file://...
+ */
if (strlen(opt.start_list_at) > 8 && strncmp(opt.start_list_at, "file:///", 8) == 0) {
- char *start_at_path = estrdup(opt.start_list_at + 7);
- free(opt.start_list_at);
- opt.start_list_at = start_at_path;
+ char *unescaped_path = feh_http_unescape(opt.start_list_at);
+ if (unescaped_path != NULL) {
+ free(opt.start_list_at);
+ opt.start_list_at = estrdup(unescaped_path + 7);
+ free(unescaped_path);
+ } else {
+ char *new_path = estrdup(opt.start_list_at + 7);
+ free(opt.start_list_at);
+ opt.start_list_at = new_path;
+ }
}
char *target_directory = estrdup(opt.start_list_at);
char *filename_start = strrchr(target_directory, '/');
@@ -867,6 +905,7 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
*filename_start = '\0';
}
add_file_to_filelist_recursively(target_directory, FILELIST_FIRST);
+ original_file_items = gib_list_add_front(original_file_items, estrdup(target_directory));
free(target_directory);
} else {
add_file_to_filelist_recursively(".", FILELIST_FIRST);
@@ -939,6 +978,10 @@ static void show_version(void)
"help "
#endif
+#ifdef HAVE_LIBMAGIC
+ "magic "
+#endif
+
#if _FILE_OFFSET_BITS == 64
"stat64 "
#endif
diff --git a/src/options.h b/src/options.h
index 4906004..aa3cd91 100644
--- a/src/options.h
+++ b/src/options.h
@@ -1,7 +1,7 @@
/* options.h
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -127,9 +127,11 @@ struct __fehoptions {
int offset_y;
int default_zoom;
int zoom_mode;
+ double zoom_rate;
unsigned char adjust_reload;
int xinerama_index;
char *x11_class;
+ unsigned long int x11_windowid;
/* signed in case someone wants to invert scrolling real quick */
int scroll_step;
@@ -149,6 +151,113 @@ struct __fehoptions {
Imlib_Font menu_fn;
};
+enum __feh_option {
+OPTION_debug = '+',
+OPTION_scale_down = '.',
+OPTION_max_dimension = '<',
+OPTION_min_dimension = '>',
+OPTION_title_font = '@',
+OPTION_action = 'A',
+OPTION_image_bg = 'B',
+OPTION_fontpath = 'C',
+OPTION_slideshow_delay = 'D',
+OPTION_thumb_height = 'E',
+OPTION_fullscreen = 'F',
+OPTION_draw_actions = 'G',
+OPTION_limit_height = 'H',
+OPTION_fullindex = 'I',
+OPTION_thumb_redraw = 'J',
+OPTION_caption_path = 'K',
+OPTION_customlist = 'L',
+OPTION_menu_font = 'M',
+OPTION_no_menus = 'N',
+OPTION_output_only = 'O',
+OPTION_cache_thumbnails = 'P',
+OPTION_reload = 'R',
+OPTION_sort = 'S',
+OPTION_theme = 'T',
+OPTION_loadable = 'U',
+OPTION_verbose = 'V',
+OPTION_limit_width = 'W',
+OPTION_ignore_aspect = 'X',
+OPTION_hide_pointer = 'Y',
+OPTION_auto_zoom = 'Z',
+OPTION_title = '^',
+OPTION_alpha = 'a',
+OPTION_bg = 'b',
+OPTION_draw_filename = 'd',
+OPTION_font = 'e',
+OPTION_filelist = 'f',
+OPTION_geometry = 'g',
+OPTION_help = 'h',
+OPTION_index = 'i',
+OPTION_output_dir = 'j',
+OPTION_keep_http = 'k',
+OPTION_list = 'l',
+OPTION_montage = 'm',
+OPTION_reverse = 'n',
+OPTION_output = 'o',
+OPTION_preload = 'p',
+OPTION_quiet = 'q',
+OPTION_recursive = 'r',
+OPTION_stretch = 's',
+OPTION_thumbnails = 't',
+OPTION_unloadable = 'u',
+OPTION_version = 'v',
+OPTION_multiwindow = 'w',
+OPTION_borderless = 'x',
+OPTION_thumb_width = 'y',
+OPTION_randomize = 'z',
+OPTION_start_at = '|',
+OPTION_thumb_title = '~',
+OPTION_bg_title,
+OPTION_bg_center,
+OPTION_bg_scale,
+OPTION_bg_fill,
+OPTION_bg_max,
+OPTION_zoom,
+OPTION_zoom_step,
+OPTION_zoom_in_rate,
+OPTION_zoom_out_rate,
+OPTION_keep_zoom_vp,
+OPTION_no_screen_clip,
+OPTION_index_info,
+OPTION_magick_timeout,
+OPTION_action1,
+OPTION_action2,
+OPTION_action3,
+OPTION_action4,
+OPTION_action5,
+OPTION_action6,
+OPTION_action7,
+OPTION_action8,
+OPTION_action9,
+OPTION_no_jump_on_resort,
+OPTION_edit,
+OPTION_draw_exif,
+OPTION_auto_rotate,
+OPTION_no_xinerama,
+OPTION_draw_tinted,
+OPTION_info,
+OPTION_force_aliasing,
+OPTION_no_fehbg,
+OPTION_scroll_step,
+OPTION_xinerama_index,
+OPTION_insecure,
+OPTION_no_recursive,
+OPTION_cache_size,
+OPTION_on_last_slide,
+OPTION_conversion_timeout,
+OPTION_version_sort,
+OPTION_offset,
+OPTION_auto_reload,
+OPTION_class,
+OPTION_no_conversion_cache,
+OPTION_window_id,
+};
+
+//typedef enum __fehoption fehoption;
+
struct __fehkey {
unsigned int keysyms[3];
unsigned int keystates[3];
diff --git a/src/signals.c b/src/signals.c
index a64f935..5a64883 100644
--- a/src/signals.c
+++ b/src/signals.c
@@ -1,6 +1,6 @@
/* signals.c
-Copyright (C) 2010-2020 by Daniel Friesel
+Copyright (C) 2010-2020 by Birte Kristina 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,9 +29,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "options.h"
void feh_handle_signal(int);
+volatile int sig_received = 0;
volatile int sig_exit = 0;
-void setup_signal_handlers()
+void setup_signal_handlers(void)
{
struct sigaction feh_sh;
sigset_t feh_ss;
@@ -71,9 +72,6 @@ void setup_signal_handlers()
void feh_handle_signal(int signo)
{
- winwidget winwid;
- int i;
-
switch (signo) {
case SIGALRM:
if (childpid)
@@ -92,21 +90,5 @@ void feh_handle_signal(int signo)
return;
}
- winwid = winwidget_get_first_window_of_type(WIN_TYPE_SLIDESHOW);
-
- if (winwid) {
- if (filelist_len > 1) {
- if (signo == SIGUSR1)
- slideshow_change_image(winwid, SLIDE_NEXT, 1);
- else if (signo == SIGUSR2)
- slideshow_change_image(winwid, SLIDE_PREV, 1);
- } else {
- feh_reload_image(winwid, 0, 0);
- }
- } else if (opt.multiwindow) {
- for (i = window_num - 1; i >= 0; i--)
- feh_reload_image(windows[i], 0, 0);
- }
-
- return;
+ sig_received = signo;
}
diff --git a/src/signals.h b/src/signals.h
index bff737e..505a071 100644
--- a/src/signals.h
+++ b/src/signals.h
@@ -1,6 +1,6 @@
/* signals.h
-Copyright (C) 2010 by Daniel Friesel
+Copyright (C) 2010 by Birte Kristina 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 +26,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SIGNALS_H
#define SIGNALS_H
-void setup_signal_handlers();
+void setup_signal_handlers(void);
extern volatile int sig_exit;
+extern volatile int sig_received;
#endif
diff --git a/src/slideshow.c b/src/slideshow.c
index 07a1e94..a53749e 100644
--- a/src/slideshow.c
+++ b/src/slideshow.c
@@ -1,7 +1,7 @@
/* slideshow.c
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina 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 +57,7 @@ void init_slideshow_mode(void)
// Try finding an exact filename match first
for (; l && opt.start_list_at; l = l->next) {
if (!strcmp(opt.start_list_at, FEH_FILE(l->data)->filename)) {
+ free(opt.start_list_at);
opt.start_list_at = NULL;
break;
}
@@ -83,6 +84,7 @@ void init_slideshow_mode(void)
current_filename = FEH_FILE(l->data)->filename;
}
if (!strcmp(start_at_filename, current_filename)) {
+ free(opt.start_list_at);
opt.start_list_at = NULL;
break;
}
@@ -163,7 +165,7 @@ void cb_reload_timer(void *data)
if (opt.filelistfile) {
filelist = gib_list_cat(filelist, feh_read_filelist(opt.filelistfile));
}
-
+
if (!(filelist_len = gib_list_length(filelist))) {
eprintf("No files found to reload.");
}
@@ -225,6 +227,18 @@ void slideshow_change_image(winwidget winwid, int change, int render)
/* The for loop prevents us looping infinitely */
for (i = 0; i < our_filelist_len; i++) {
winwidget_free_image(winwid);
+#ifdef HAVE_LIBEXIF
+ /*
+ * An EXIF data chunk requires up to 50 kB of space. For large and
+ * long-running slideshows, this would acculumate gigabytes of
+ * EXIF data after a few days. We therefore do not cache EXIF data
+ * in slideshows.
+ */
+ if (FEH_FILE(winwid->file->data)->ed) {
+ exif_data_unref(FEH_FILE(winwid->file->data)->ed);
+ FEH_FILE(winwid->file->data)->ed = NULL;
+ }
+#endif
switch (change) {
case SLIDE_NEXT:
current_file = feh_list_jump(filelist, current_file, FORWARD, 1);
@@ -371,7 +385,8 @@ void feh_action_run(feh_file * file, char *action, winwidget winwid)
if (opt.verbose && !opt.list && !opt.customlist)
fprintf(stderr, "Running action -->%s<--\n", sys);
- system(sys);
+ if (system(sys) == -1)
+ perror("running action via system() failed");
}
return;
}
@@ -514,6 +529,12 @@ char *feh_printf(char *str, feh_file * file, winwidget winwid)
strncat(ret, buf, sizeof(ret) - strlen(ret) - 1);
}
break;
+ case 'W':
+ if (winwid) {
+ snprintf(buf, sizeof(buf), "%dx%d+%d+%d", winwid->w, winwid->h, winwid->x, winwid->y);
+ strncat(ret, buf, sizeof(ret) - strlen(ret) - 1);
+ }
+ break;
case 'z':
if (winwid) {
snprintf(buf, sizeof(buf), "%.2f", winwid->zoom);
@@ -626,7 +647,7 @@ void slideshow_save_image(winwidget win)
gib_imlib_save_image_with_error_return(win->im, tmpname, &err);
if (err)
- feh_imlib_print_load_error(tmpname, win, err);
+ feh_print_load_error(tmpname, win, err, LOAD_ERROR_IMLIB);
free(tmpname);
return;
diff --git a/src/structs.h b/src/structs.h
index 3e2a1aa..8438930 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -1,7 +1,7 @@
/* structs.h
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina 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/strverscmp.c b/src/strverscmp.c
index 92cd877..ddc6b6d 100644
--- a/src/strverscmp.c
+++ b/src/strverscmp.c
@@ -41,9 +41,9 @@ int strverscmp(const char *l0, const char *r0)
else if (c!='0') z=0;
}
- if (l[dp]!='0' && r[dp]!='0') {
- /* If we're not looking at a digit sequence that began
- * with a zero, longest digit string is greater. */
+ if (l[dp]-'1'<9U && r[dp]-'1'<9U) {
+ /* If we're looking at non-degenerate digit sequences starting
+ * with nonzero digits, longest digit string is greater. */
for (j=i; isdigit(l[j]); j++)
if (!isdigit(r[j])) return 1;
if (isdigit(r[j])) return -1;
diff --git a/src/thumbnail.c b/src/thumbnail.c
index 41bd1a0..77c0acd 100644
--- a/src/thumbnail.c
+++ b/src/thumbnail.c
@@ -1,7 +1,7 @@
/* thumbnail.c
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -392,7 +392,7 @@ void init_thumbnail_mode(void)
}
gib_imlib_save_image_with_error_return(td.im_main, output_buf, &err);
if (err) {
- feh_imlib_print_load_error(output_buf, td.im_main, err);
+ feh_print_load_error(output_buf, td.im_main, err, LOAD_ERROR_IMLIB);
}
else if (opt.verbose) {
int tw, th;
@@ -411,6 +411,7 @@ void init_thumbnail_mode(void)
else if (opt.start_list_at) {
for (l = thumbnails; l; l = l->next) {
if (!strcmp(opt.start_list_at, FEH_THUMB(l->data)->file->filename)) {
+ free(opt.start_list_at);
opt.start_list_at = NULL;
feh_thumbnail_select(winwid, FEH_THUMB(l->data));
break;
@@ -592,7 +593,7 @@ int feh_thumbnail_get_thumbnail(Imlib_Image * image, feh_file * file,
return status;
}
-static char *feh_thumbnail_get_prefix()
+static char *feh_thumbnail_get_prefix(void)
{
char *dir = NULL, *home, *xdg_cache_home;
@@ -635,9 +636,9 @@ char *feh_thumbnail_get_name_uri(char *name)
/* FIXME: what happens with http, https, and ftp? MTime etc */
if (!path_is_url(name)) {
- /* make sure it's an absoulte path */
+ /* make sure it's an absolute path */
/* FIXME: add support for ~, need to investigate if it's expanded
- somewhere else before adding (unecessary) code */
+ somewhere else before adding (unnecessary) code */
if (name[0] != '/') {
/* work around /some/path/./image.ext */
if ((strncmp(name, "./", 2)) == 0)
@@ -881,13 +882,13 @@ void feh_thumbnail_select_prev(winwidget winwid, int jump)
}
}
-void feh_thumbnail_show_selected()
+void feh_thumbnail_show_selected(void)
{
if (td.selected && td.selected->file)
feh_thumbnail_show_fullsize(td.selected->file);
}
-feh_file* feh_thumbnail_get_selected_file()
+feh_file* feh_thumbnail_get_selected_file(void)
{
if (td.selected)
return td.selected->file;
diff --git a/src/thumbnail.h b/src/thumbnail.h
index 61d3053..e69759f 100644
--- a/src/thumbnail.h
+++ b/src/thumbnail.h
@@ -1,7 +1,7 @@
/* thumbnail.h
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -83,8 +83,8 @@ void feh_thumbnail_show_fullsize(feh_file *thumbfile);
void feh_thumbnail_select(winwidget winwid, feh_thumbnail *thumbnail);
void feh_thumbnail_select_next(winwidget winwid, int jump);
void feh_thumbnail_select_prev(winwidget winwid, int jump);
-void feh_thumbnail_show_selected();
-feh_file *feh_thumbnail_get_selected_file();
+void feh_thumbnail_show_selected(void);
+feh_file *feh_thumbnail_get_selected_file(void);
int feh_thumbnail_setup_thumbnail_dir(void);
diff --git a/src/timers.c b/src/timers.c
index b2cdbc7..8e42050 100644
--- a/src/timers.c
+++ b/src/timers.c
@@ -1,7 +1,7 @@
/* timers.c
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina 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/utils.c b/src/utils.c
index 087e7f6..eb128a2 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -146,6 +146,8 @@ char *estrjoin(const char *separator, ...)
char path_is_url(char *path) {
if ((!strncmp(path, "http://", 7))
|| (!strncmp(path, "https://", 8))
+ || (!strncmp(path, "gopher://", 9))
+ || (!strncmp(path, "gophers://", 10))
|| (!strncmp(path, "ftp://", 6))
|| (!strncmp(path, "file://", 7)))
return 1;
diff --git a/src/wallpaper.c b/src/wallpaper.c
index 37b5a1d..e2fa67e 100644
--- a/src/wallpaper.c
+++ b/src/wallpaper.c
@@ -1,7 +1,7 @@
/* wallpaper.c
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -245,6 +245,106 @@ static void feh_wm_set_bg_maxed(Pixmap pmap, Imlib_Image im, int use_filelist,
return;
}
+/*
+** Creates a script that can be used to create the same background
+** as the last time the program was called.
+*/
+void feh_wm_gen_bg_script(char* fil, int centered, int scaled, int filled, int use_filelist) {
+ char * home = getenv("HOME");
+
+ if (!home)
+ return;
+
+ FILE *fp;
+ int fd;
+ char *path;
+ char *exec_method;
+ char *absolute_path;
+ struct stat s;
+ gib_list *filelist_pos = filelist;
+
+ if (strchr(cmdargv[0], '/'))
+ exec_method = feh_absolute_path(cmdargv[0]);
+ else
+ exec_method = cmdargv[0];
+
+ path = estrjoin("/", home, ".fehbg", NULL);
+
+ if ((fp = fopen(path, "w")) == NULL) {
+ weprintf("Can't write to %s", path);
+ } else {
+ fputs("#!/bin/sh\n", fp);
+ fputs(exec_method, fp);
+ fputs(" --no-fehbg --bg-", fp);
+ if (centered)
+ fputs("center", fp);
+ else if (scaled)
+ fputs("scale", fp);
+ else if (filled == 1)
+ fputs("fill", fp);
+ else if (filled == 2)
+ fputs("max", fp);
+ else
+ fputs("tile", fp);
+ if (opt.image_bg) {
+ fputs(" --image-bg ", fp);
+ fputs(shell_escape(opt.image_bg), fp);
+ }
+#ifdef HAVE_LIBXINERAMA
+ if (opt.xinerama) {
+ if (opt.xinerama_index >= 0) {
+ fprintf(fp, " --xinerama-index %d", opt.xinerama_index);
+ }
+ }
+ else {
+ fputs(" --no-xinerama", fp);
+ }
+#endif /* HAVE_LIBXINERAMA */
+ if (opt.geom_flags & XValue) {
+ fprintf(fp, " --geometry %c%d",
+ opt.geom_flags & XNegative ? '-' : '+',
+ opt.geom_flags & XNegative ? abs(opt.geom_x) : opt.geom_x);
+ if (opt.geom_flags & YValue) {
+ fprintf(fp, "%c%d",
+ opt.geom_flags & YNegative ? '-' : '+',
+ opt.geom_flags & YNegative ? abs(opt.geom_y) : opt.geom_y);
+ }
+ }
+ if (opt.force_aliasing) {
+ fputs(" --force-aliasing", fp);
+ }
+ fputc(' ', fp);
+ if (use_filelist) {
+#ifdef HAVE_LIBXINERAMA
+ for (int i = 0; (i < opt.xinerama ? num_xinerama_screens : 1) && filelist_pos; i++)
+#else
+ for (int i = 0; (i < 1 ) && filelist_pos; i++)
+#endif
+ {
+ absolute_path = feh_absolute_path(FEH_FILE(filelist_pos->data)->filename);
+ fputs(shell_escape(absolute_path), fp);
+ filelist_pos = filelist_pos->next;
+ free(absolute_path);
+ fputc(' ', fp);
+ }
+ } else if (fil) {
+ absolute_path = feh_absolute_path(fil);
+ fputs(shell_escape(absolute_path), fp);
+ free(absolute_path);
+ }
+ fputc('\n', fp);
+ fd = fileno(fp);
+ if (fstat(fd, &s) != 0 || fchmod(fd, s.st_mode | S_IXUSR | S_IXGRP) != 0) {
+ weprintf("Can't set %s as executable", path);
+ }
+ fclose(fp);
+ }
+ free(path);
+
+ if(exec_method != cmdargv[0])
+ free(exec_method);
+}
+
void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled,
int filled, int desktop, int use_filelist)
{
@@ -282,7 +382,10 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled,
feh_wm_load_next(&im);
fil = FEH_FILE(filelist->data)->filename;
}
- snprintf(sendbuf, sizeof(sendbuf), "background %s bg.file %s", bgname, fil);
+ if ((size_t) snprintf(sendbuf, sizeof(sendbuf), "background %s bg.file %s", bgname, fil) >= sizeof(sendbuf)) {
+ weprintf("Writing to IPC send buffer was truncated");
+ return;
+ }
enl_ipc_send(sendbuf);
if (scaled) {
@@ -322,8 +425,6 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled,
unsigned char *data_root = NULL, *data_esetroot = NULL;
Pixmap pmap_d1, pmap_d2;
- char *home;
-
/* local display to set closedownmode on */
Display *disp2;
Window root2;
@@ -448,87 +549,8 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled,
gib_imlib_render_image_on_drawable(pmap_d1, im, 0, 0, 1, 1, 0);
}
- if (!opt.no_fehbg) {
- home = getenv("HOME");
- if (home) {
- FILE *fp;
- int fd;
- char *path;
- char *absolute_path;
- struct stat s;
- gib_list *filelist_pos = filelist;
- path = estrjoin("/", home, ".fehbg", NULL);
- if ((fp = fopen(path, "w")) == NULL) {
- weprintf("Can't write to %s", path);
- } else {
- fputs("#!/bin/sh\n", fp);
- fputs(cmdargv[0], fp);
- fputs(" --no-fehbg --bg-", fp);
- if (centered)
- fputs("center", fp);
- else if (scaled)
- fputs("scale", fp);
- else if (filled == 1)
- fputs("fill", fp);
- else if (filled == 2)
- fputs("max", fp);
- else
- fputs("tile", fp);
- if (opt.image_bg) {
- fputs(" --image-bg ", fp);
- fputs(shell_escape(opt.image_bg), fp);
- }
-#ifdef HAVE_LIBXINERAMA
- if (opt.xinerama) {
- if (opt.xinerama_index >= 0) {
- fprintf(fp, " --xinerama-index %d", opt.xinerama_index);
- }
- }
- else {
- fputs(" --no-xinerama", fp);
- }
-#endif /* HAVE_LIBXINERAMA */
- if (opt.geom_flags & XValue) {
- fprintf(fp, " --geometry %c%d",
- opt.geom_flags & XNegative ? '-' : '+',
- opt.geom_flags & XNegative ? abs(opt.geom_x) : opt.geom_x);
- if (opt.geom_flags & YValue) {
- fprintf(fp, "%c%d",
- opt.geom_flags & YNegative ? '-' : '+',
- opt.geom_flags & YNegative ? abs(opt.geom_y) : opt.geom_y);
- }
- }
- if (opt.force_aliasing) {
- fputs(" --force-aliasing", fp);
- }
- fputc(' ', fp);
- if (use_filelist) {
-#ifdef HAVE_LIBXINERAMA
- for (int i = 0; (i < opt.xinerama ? num_xinerama_screens : 1) && filelist_pos; i++) {
-#else
- for (int i = 0; (i < 1 ) && filelist_pos; i++) {
-#endif
- absolute_path = feh_absolute_path(FEH_FILE(filelist_pos->data)->filename);
- fputs(shell_escape(absolute_path), fp);
- filelist_pos = filelist_pos->next;
- free(absolute_path);
- fputc(' ', fp);
- }
- } else if (fil) {
- absolute_path = feh_absolute_path(fil);
- fputs(shell_escape(absolute_path), fp);
- free(absolute_path);
- }
- fputc('\n', fp);
- fd = fileno(fp);
- if (fstat(fd, &s) != 0 || fchmod(fd, s.st_mode | S_IXUSR | S_IXGRP) != 0) {
- weprintf("Can't set %s as executable", path);
- }
- fclose(fp);
- }
- free(path);
- }
- }
+ if (!opt.no_fehbg)
+ feh_wm_gen_bg_script(fil, centered, scaled, filled, use_filelist);
/* create new display, copy pixmap to new display */
disp2 = XOpenDisplay(NULL);
@@ -569,7 +591,7 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled,
if (data_root)
XFree(data_root);
-
+
if (data_esetroot)
XFree(data_esetroot);
diff --git a/src/wallpaper.h b/src/wallpaper.h
index cf52d2d..c836c0f 100644
--- a/src/wallpaper.h
+++ b/src/wallpaper.h
@@ -1,7 +1,7 @@
/* wallpaper.h
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
extern Window ipc_win;
extern Atom ipc_atom;
-_XFUNCPROTOBEGIN extern Window enl_ipc_get_win(void);
+extern Window enl_ipc_get_win(void);
extern void enl_ipc_send(char *);
extern char *enl_wait_for_reply(void);
extern char *enl_ipc_get(const char *);
@@ -53,5 +53,4 @@ extern int feh_wm_get_num_desks(void);
extern signed char feh_wm_get_wm_is_e(void);
void feh_wm_set_bg_filelist(unsigned char bgmode);
-_XFUNCPROTOEND
#endif
diff --git a/src/winwidget.c b/src/winwidget.c
index bfd987d..b98cbef 100644
--- a/src/winwidget.c
+++ b/src/winwidget.c
@@ -1,7 +1,7 @@
/* winwidget.c
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -104,8 +104,13 @@ winwidget winwidget_create_from_image(Imlib_Image im, char type)
ret->w = ret->im_w = gib_imlib_image_get_width(ret->im);
ret->h = ret->im_h = gib_imlib_image_get_height(ret->im);
- if (opt.full_screen && (type != WIN_TYPE_THUMBNAIL))
+ if (opt.full_screen && (type != WIN_TYPE_THUMBNAIL)) {
ret->full_screen = True;
+ } else if (opt.default_zoom) {
+ ret->zoom = 0.01 * opt.default_zoom;
+ ret->w *= ret->zoom;
+ ret->h *= ret->zoom;
+ }
winwidget_create_window(ret, ret->w, ret->h);
winwidget_render_image(ret, 1, 0);
@@ -133,8 +138,13 @@ winwidget winwidget_create_from_file(gib_list * list, char type)
ret->w = ret->im_w = gib_imlib_image_get_width(ret->im);
ret->h = ret->im_h = gib_imlib_image_get_height(ret->im);
D(("image is %dx%d pixels, format %s\n", ret->w, ret->h, gib_imlib_image_format(ret->im)));
- if (opt.full_screen)
+ if (opt.full_screen) {
ret->full_screen = True;
+ } else if (opt.default_zoom) {
+ ret->zoom = 0.01 * opt.default_zoom;
+ ret->w *= ret->zoom;
+ ret->h *= ret->zoom;
+ }
winwidget_create_window(ret, ret->w, ret->h);
winwidget_render_image(ret, 1, 0);
}
@@ -144,6 +154,7 @@ winwidget winwidget_create_from_file(gib_list * list, char type)
void winwidget_create_window(winwidget ret, int w, int h)
{
+ XWindowAttributes window_attr;
XSetWindowAttributes attr;
XEvent ev;
XClassHint *xch;
@@ -250,11 +261,31 @@ void winwidget_create_window(winwidget ret, int w, int h)
}
}
- ret->win =
- XCreateWindow(disp, DefaultRootWindow(disp), x, y, w, h, 0,
- depth, InputOutput, vis,
- CWOverrideRedirect | CWSaveUnder | CWBackingStore
- | CWColormap | CWBackPixel | CWBorderPixel | CWEventMask, &attr);
+ if (opt.x11_windowid == 0) {
+ ret->win =
+ XCreateWindow(disp, DefaultRootWindow(disp), x, y, w, h, 0,
+ depth, InputOutput, vis,
+ CWOverrideRedirect | CWSaveUnder | CWBackingStore
+ | CWColormap | CWBackPixel | CWBorderPixel | CWEventMask,
+ &attr);
+ } else {
+ /* x11_windowid is a pointer to the window */
+ ret->win = (Window) opt.x11_windowid;
+
+ /* set our attributes on the window */
+ XChangeWindowAttributes(disp, ret->win,
+ CWOverrideRedirect | CWSaveUnder | CWBackingStore
+ | CWColormap | CWBackPixel | CWBorderPixel
+ | CWEventMask, &attr);
+
+ /* determine the size and visibility of the window */
+ XGetWindowAttributes(disp, ret->win, &window_attr);
+ ret->visible = (window_attr.map_state == IsViewable);
+ ret->x = window_attr.x;
+ ret->y = window_attr.y;
+ ret->w = window_attr.width;
+ ret->h = window_attr.height;
+ }
if (mwmhints.flags) {
XChangeProperty(disp, ret->win, prop, prop, 32,
@@ -433,7 +464,12 @@ void winwidget_render_image(winwidget winwid, int resize, int force_alias)
int antialias = 0;
if (!winwid->full_screen && resize) {
- winwidget_resize(winwid, winwid->im_w, winwid->im_h, 0);
+ if (opt.default_zoom) {
+ winwid->zoom = 0.01 * opt.default_zoom;
+ winwidget_resize(winwid, winwid->im_w * winwid->zoom, winwid->im_h * winwid->zoom, 0);
+ } else {
+ winwidget_resize(winwid, winwid->im_w, winwid->im_h, 0);
+ }
winwidget_reset_image(winwid);
}
@@ -703,7 +739,7 @@ void winwidget_inotify_remove(winwidget winwid)
#ifdef HAVE_INOTIFY
void winwidget_inotify_add(winwidget winwid, feh_file * file)
{
- if (opt.auto_reload) {
+ if (opt.auto_reload && !path_is_url(file->filename)) {
D(("Adding inotify watch for %s\n", file->filename));
char dir[PATH_MAX];
feh_file_dirname(dir, file, PATH_MAX);
@@ -742,7 +778,7 @@ void feh_event_handle_inotify(void)
for (int j = 0; j < window_num; j++) {
if(windows[j]->inotify_wd == event->wd) {
if (event->mask & IN_IGNORED) {
- D(("inotify watch was implicitely removed\n"));
+ D(("inotify watch was implicitly removed\n"));
windows[j]->inotify_wd = -1;
} else if (event->mask & (IN_CLOSE_WRITE | IN_MOVED_TO)) {
if (strcmp(event->name, FEH_FILE(windows[j]->file->data)->name) == 0) {
@@ -1014,8 +1050,9 @@ void winwidget_rename(winwidget winwid, char *newname)
void winwidget_free_image(winwidget w)
{
- if (w->im)
+ if (w->im) {
gib_imlib_free_image(w->im);
+ }
w->im = NULL;
w->im_w = 0;
w->im_h = 0;
diff --git a/src/winwidget.h b/src/winwidget.h
index 9d74286..0894b5a 100644
--- a/src/winwidget.h
+++ b/src/winwidget.h
@@ -1,7 +1,7 @@
/* winwidget.h
Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2020 Daniel Friesel.
+Copyright (C) 2010-2020 Birte Kristina 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/test/feh.t b/test/feh.t
index 44f705f..b9025b4 100644
--- a/test/feh.t
+++ b/test/feh.t
@@ -2,7 +2,7 @@
use strict;
use warnings;
use 5.010;
-use Test::Command tests => 71;
+use Test::Command tests => 73;
$ENV{HOME} = 'test';
@@ -46,8 +46,11 @@ if ( $version =~ m{ Compile-time \s switches : \s .* help }ox ) {
$has_help = 1;
}
+# Imlib2 1.8+ returns "Invalid image file" rather than "No Imlib2 loader".
+# feh compiled with magic=1 returns "Does not look like an image (magic bytes missing)"
+# Here, we accept all three.
my $re_warning
- = qr{${feh_name} WARNING: test/fail/... \- Does not look like an image \(magic bytes missing\)\n};
+ = qr{${feh_name} WARNING: test/fail/... \- (Invalid image file|No Imlib2 loader for that file format|Does not look like an image \(magic bytes missing\))\n};
my $re_loadable = qr{test/ok/...};
my $re_unloadable = qr{test/fail/...};
my $re_list_action = qr{test/ok/... 16x16};
@@ -186,3 +189,7 @@ $cmd
$cmd->exit_is_num(0);
$cmd->stdout_is_file("test/${list_dir}/default");
$cmd->stderr_is_eq('');
+
+$cmd = Test::Command->new( cmd => "$feh --list test/tiny.pbm" );
+$cmd->exit_is_num(0);
+$cmd->stderr_is_eq('');
diff --git a/test/tiny.pbm b/test/tiny.pbm
new file mode 100644
index 0000000..3fb3e4e
--- /dev/null
+++ b/test/tiny.pbm
@@ -0,0 +1,4 @@
+P4
+1 1
+
+