summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSven Willner <sven.willner@gmail.com>2019-04-01 13:58:50 +0200
committerSven Willner <sven.willner@gmail.com>2019-04-01 13:58:50 +0200
commita9ffd5d2234433bc3f3829713b0968a1d6c13b94 (patch)
tree78a78930edbf7c187e0803f367529f2aabc90627 /src
parent1d3d1259590c8a600c3d800942ab5566802d3499 (diff)
parent18dd1c5ea218c1b86e305d3ee0052335b1e22fc8 (diff)
Merge remote-tracking branch 'original/master'
Diffstat (limited to 'src')
-rw-r--r--src/Makefile1
-rw-r--r--src/collage.c208
-rw-r--r--src/feh.h1
-rw-r--r--src/filelist.c7
-rw-r--r--src/gib_imlib.c12
-rw-r--r--src/gib_imlib.h2
-rw-r--r--src/gib_list.c2
-rw-r--r--src/help.raw32
-rw-r--r--src/imlib.c74
-rw-r--r--src/keyevents.c6
-rw-r--r--src/main.c7
-rw-r--r--src/menu.c2
-rw-r--r--src/options.c68
-rw-r--r--src/options.h3
-rw-r--r--src/signals.c15
-rw-r--r--src/signals.h2
-rw-r--r--src/slideshow.c62
-rw-r--r--src/utils.c1
-rw-r--r--src/wallpaper.c21
-rw-r--r--src/winwidget.c3
20 files changed, 238 insertions, 291 deletions
diff --git a/src/Makefile b/src/Makefile
index 8a9f97e..ac4d2fe 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,7 +1,6 @@
include ../config.mk
TARGETS = \
- collage.c \
events.c \
feh_png.c \
filelist.c \
diff --git a/src/collage.c b/src/collage.c
deleted file mode 100644
index 2a4d9f9..0000000
--- a/src/collage.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/* collage.c
-
-Copyright (C) 1999-2003 Tom Gilbert.
-Copyright (C) 2010-2018 Daniel Friesel.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to
-deal in the Software without restriction, including without limitation the
-rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies of the Software and its documentation and acknowledgment shall be
-given in the documentation and software packages that this Software was
-used.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-*/
-
-#include "feh.h"
-#include "winwidget.h"
-#include "filelist.h"
-#include "options.h"
-
-void init_collage_mode(void)
-{
- Imlib_Image im_main;
- Imlib_Image im_temp;
- int ww, hh, www, hhh, xxx, yyy;
- int w = 800, h = 600;
- int bg_w = 0, bg_h = 0;
- winwidget winwid = NULL;
- Imlib_Image bg_im = NULL, im_thumb = NULL;
- feh_file *file = NULL;
- unsigned char trans_bg = 0;
- gib_list *l, *last = NULL;
-
- mode = "collage";
-
- weprintf("the --collage option (aka collage mode) is deprecated\n"
- "and will be removed soon\n");
-
- /* Use bg image dimensions for default size */
- if (opt.bg && opt.bg_file) {
- if (!strcmp(opt.bg_file, "trans"))
- trans_bg = 1;
- else {
-
- D(("Time to apply a background to blend onto\n"));
- if (feh_load_image_char(&bg_im, opt.bg_file) != 0) {
- bg_w = gib_imlib_image_get_width(bg_im);
- bg_h = gib_imlib_image_get_height(bg_im);
- }
- }
- }
-
- if (!opt.limit_w || !opt.limit_h) {
- if (bg_im) {
- if (opt.verbose)
- fputs(PACKAGE
- ": No size restriction specified for collage.\n"
- " You did specify a background however, so the\n"
- " collage size has defaulted to the size of the image\n",
- stderr);
- opt.limit_w = bg_w;
- opt.limit_h = bg_h;
- } else {
- if (opt.verbose)
- fputs(PACKAGE
- ": No size restriction specified for collage.\n"
- " - For collage mode, you need to specify width and height.\n"
- " Using defaults (width 800, height 600)\n",
- stderr);
- opt.limit_w = 800;
- opt.limit_h = 600;
- }
- }
-
- w = opt.limit_w;
- h = opt.limit_h;
- D(("Limiting width to %d and height to %d\n", w, h));
-
- im_main = imlib_create_image(w, h);
-
- if (!im_main)
- eprintf("Imlib error creating image");
-
- if (bg_im)
- gib_imlib_blend_image_onto_image(im_main, bg_im,
- gib_imlib_image_has_alpha(bg_im), 0, 0,
- bg_w, bg_h, 0, 0, w, h, 1, 0, 0);
- else if (trans_bg) {
- gib_imlib_image_fill_rectangle(im_main, 0, 0, w, h, 0, 0, 0, 0);
- gib_imlib_image_set_has_alpha(im_main, 1);
- } else {
- /* Colour the background */
- gib_imlib_image_fill_rectangle(im_main, 0, 0, w, h, 0, 0, 0, 255);
- }
-
- if (opt.display) {
- winwid = winwidget_create_from_image(im_main, WIN_TYPE_SINGLE);
- winwidget_rename(winwid, PACKAGE " [collage mode]");
- winwidget_show(winwid);
- }
-
- for (l = filelist; l; l = l->next) {
- file = FEH_FILE(l->data);
- if (last) {
- filelist = feh_file_remove_from_list(filelist, last);
- last = NULL;
- }
- D(("About to load image %s\n", file->filename));
- if (feh_load_image(&im_temp, file) != 0) {
- D(("Successfully loaded %s\n", file->filename));
- if (opt.verbose)
- feh_display_status('.');
- www = opt.thumb_w;
- hhh = opt.thumb_h;
- ww = gib_imlib_image_get_width(im_temp);
- hh = gib_imlib_image_get_height(im_temp);
-
- if (opt.aspect) {
- double ratio = 0.0;
-
- /* Keep the aspect ratio for the thumbnail */
- ratio = ((double) ww / hh) / ((double) www / hhh);
-
- if (ratio > 1.0)
- hhh = opt.thumb_h / ratio;
- else if (ratio != 1.0)
- www = opt.thumb_w * ratio;
- }
-
- if ((!opt.stretch) && ((www > ww) || (hhh > hh))) {
- /* Don't make the image larger unless stretch is specified */
- www = ww;
- hhh = hh;
- }
-
- /* pick random coords for thumbnail */
- xxx = ((w - www) * ((double) rand() / RAND_MAX));
- yyy = ((h - hhh) * ((double) rand() / RAND_MAX));
- D(("image going on at x=%d, y=%d\n", xxx, yyy));
-
- im_thumb = gib_imlib_create_cropped_scaled_image(im_temp,
- 0, 0, ww, hh, www, hhh, 1);
- gib_imlib_free_image_and_decache(im_temp);
-
- if (opt.alpha) {
- DATA8 atab[256];
-
- D(("Applying alpha options\n"));
- gib_imlib_image_set_has_alpha(im_thumb, 1);
- memset(atab, opt.alpha_level, sizeof(atab));
- gib_imlib_apply_color_modifier_to_rectangle(im_thumb,
- 0, 0, www, hhh, NULL, NULL, NULL, atab);
- }
- gib_imlib_blend_image_onto_image(im_main, im_thumb,
- gib_imlib_image_has_alpha(im_thumb), 0, 0, www, hhh, xxx,
- yyy,www, hhh, 1, gib_imlib_image_has_alpha(im_thumb), 0);
- gib_imlib_free_image_and_decache(im_thumb);
- } else {
- last = l;
- if (opt.verbose)
- feh_display_status('x');
- }
- if (opt.display) {
- winwidget_render_image(winwid, 0, 0);
- if (!feh_main_iteration(0))
- exit(0);
- }
- }
- if (opt.verbose)
- fputs("\n", stderr);
-
- if (opt.output && opt.output_file) {
- char output_buf[1024];
- if (opt.output_dir)
- snprintf(output_buf, 1024, "%s/%s", opt.output_dir, opt.output_file);
- else {
- strncpy(output_buf, opt.output_file, 1023);
- output_buf[1023] = '\0';
- }
- gib_imlib_save_image(im_main, output_buf);
- if (opt.verbose) {
- int tw, th;
-
- tw = gib_imlib_image_get_width(im_main);
- th = gib_imlib_image_get_height(im_main);
- fprintf(stderr, PACKAGE ": File saved as %s\n", output_buf);
- fprintf(stderr,
- " - Image is %dx%d pixels and contains %d thumbnails\n",
- tw, th, (tw / opt.thumb_w) * (th / opt.thumb_h));
- }
- }
-
- if (!opt.display)
- gib_imlib_free_image_and_decache(im_main);
-
- return;
-}
diff --git a/src/feh.h b/src/feh.h
index 614ccef..c97ece6 100644
--- a/src/feh.h
+++ b/src/feh.h
@@ -132,7 +132,6 @@ void init_xinerama(void);
#endif /* HAVE_LIBXINERAMA */
void init_multiwindow_mode(void);
void init_thumbnail_mode(void);
-void init_collage_mode(void);
void init_index_mode(void);
void init_slideshow_mode(void);
void init_list_mode(void);
diff --git a/src/filelist.c b/src/filelist.c
index 870e463..e3ae020 100644
--- a/src/filelist.c
+++ b/src/filelist.c
@@ -30,6 +30,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "feh.h"
#include "filelist.h"
+#include "signals.h"
#include "options.h"
gib_list *filelist = NULL;
@@ -327,6 +328,10 @@ gib_list *feh_file_info_preload(gib_list * list)
feh_display_status('s');
} else if (opt.verbose)
feh_display_status('.');
+ if (sig_exit) {
+ feh_display_status(0);
+ exit(sig_exit);
+ }
}
if (opt.verbose)
feh_display_status(0);
@@ -486,7 +491,7 @@ void feh_prepare_filelist(void)
* we can create a properly sized thumbnail list.
*/
if (opt.list || opt.preload || opt.customlist || (opt.sort > SORT_MTIME)
- || (opt.filter_by_dimensions && (opt.index || opt.collage || opt.thumbs || opt.bgmode))) {
+ || (opt.filter_by_dimensions && (opt.index || opt.thumbs || opt.bgmode))) {
/* For these sort options, we have to preload images */
filelist = feh_file_info_preload(filelist);
if (!gib_list_length(filelist))
diff --git a/src/gib_imlib.c b/src/gib_imlib.c
index 8f401aa..7858cb7 100644
--- a/src/gib_imlib.c
+++ b/src/gib_imlib.c
@@ -717,3 +717,15 @@ void gib_imlib_image_orientate(Imlib_Image im, int orientation)
imlib_context_set_image(im);
imlib_image_orientate(orientation);
}
+
+void gib_imlib_image_flip_horizontal(Imlib_Image im)
+{
+ imlib_context_set_image(im);
+ imlib_image_flip_horizontal();
+}
+
+void gib_imlib_image_flip_vertical(Imlib_Image im)
+{
+ imlib_context_set_image(im);
+ imlib_image_flip_vertical();
+}
diff --git a/src/gib_imlib.h b/src/gib_imlib.h
index 6a16a0c..07daabe 100644
--- a/src/gib_imlib.h
+++ b/src/gib_imlib.h
@@ -181,6 +181,8 @@ void gib_imlib_parse_color(char *col, int *r, int *g, int *b, int *a);
void gib_imlib_parse_fontpath(char *path);
Imlib_Font gib_imlib_load_font(char *name);
void gib_imlib_image_orientate(Imlib_Image im, int orientation);
+void gib_imlib_image_flip_horizontal(Imlib_Image im);
+void gib_imlib_image_flip_vertical(Imlib_Image im);
#ifdef __cplusplus
}
diff --git a/src/gib_list.c b/src/gib_list.c
index 5384d98..a8ba1dd 100644
--- a/src/gib_list.c
+++ b/src/gib_list.c
@@ -362,7 +362,7 @@ gib_list_randomize(gib_list * list)
}
for (i = 0; i < len - 1; i++)
{
- r = i + rand() / (RAND_MAX / (len - i) + 1 );
+ r = i + random() / (RAND_MAX / (len - i) + 1 );
t = farray[r];
farray[r] = farray[i];
farray[i] = t;
diff --git a/src/help.raw b/src/help.raw
index 2532325..7a9a658 100644
--- a/src/help.raw
+++ b/src/help.raw
@@ -35,6 +35,7 @@ OPTIONS
-d, --draw-filename Show the filename in the image window
--draw-tinted Show overlay texts on semi-transparent background
--draw-exif Show some Exif information (if compiled with exif=1)
+ --edit Make flip/rotation keys flip/rotate the underlying file
--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
@@ -87,12 +88,13 @@ OPTIONS
-M, --menu-font FONT Use FONT for the font in menus.
-B, --image-bg STYLE Set background for transparent images and the like.
Accepted values: default, checks, or a XColor (eg. #428bdd)
+ --xinerama-index I Assumee that I is the active xinerama screen
-N, --no-menus Don't load or show any menus.
--no-xinerama Disable Xinerama support
--no-screen-clip Do not limit window size to screen size
-Y, --hide-pointer Hide the pointer
- --magick-timeout INT Load unknown files with ImageMagick, timeout after
- INT seconds (0: no timeout)
+ --conversion-timeout INT Load unknown files with dcraw or ImageMagick,
+ timeout after INT seconds (0: no timeout)
--min-dimension WxH Only show images with width >= W and height >= H
--max-dimension WxH Only show images with width <= W and height <= H
--scroll-step COUNT scroll COUNT pixels when movement key is pressed
@@ -124,13 +126,14 @@ INDEX MODE OPTIONS
FORMAT SPECIFIERS
%f image path/filename
%F image path/filename (shell-escaped)
+ %g window dimensions (\"width,height\") in pixels
%h image height
%l total number of files in the filelist
%L path to temporary copy of filelist
%m current mode (slideshow, multiwindow...)
%n image name
%N image name (shell-escaped)
- %o x,y offset of top-left image corner to window in pixels
+ %o offset of top-left image corner to window (\"x,y\") in pixels
%p image pixel size
%P image pixel size in kilo-/megapixels
%r image rotation. half right turn == 3.1415 (pi)
@@ -141,34 +144,39 @@ FORMAT SPECIFIERS
%w image width
%v " PACKAGE " version
%V process ID
- %z current image zoom
+ %z current image zoom, rounded to two decimal places
+ %Z current image zoom, high precision
%% %
\\n newline
-KEYS
+DEFAULT KEYS
a Toggle action display (--draw-actions)
A Toggle anti-aliasing
c Enable caption entry mode
d Toggle filename display (--draw-filename)
e Toggle exif tag display (if compiled with exif=1)
- f Save current filelist to unique filename
+ f Toggle fullscreen
+ g Toggle fixed geometry mode
h pause/continue slideshow
i Toggle --info display
k Toggle zoom/viewport freeze when switching images
- m Show menu
+ L Save current filelist to unique filename
+ m Show/hide menu
n, <SPACE>, <RIGHT> Go to next image
o Toggle pointer visibility
p, <BACKSPACE>, <LEFT> Go to previous image
q, <ESCAPE> Quit
r Reload image
+ R Render/anti-alias image
s Save current image to unique filename
- v Toggle fullscreen
w Resize window to current image dimensions
x Close current window
z Jump to a random position in the current filelist
- <, > In place editing, rotate 90 degrees right/left
- _ In place editing, vertical flip
- | In place editing, horizontal flip
+ Z Toggle auto-zoom
+ [, ] Jump to previous/next directory
+ <, > Rotate 90 degrees right/left
+ _ Vertical flip
+ | Horizontal flip
0, <ENTER> Run action specified by --action option
1-9 Run action 1-9 specified by --action[1-9] options
<HOME> Go to first slide
@@ -192,7 +200,7 @@ 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-2016.
+Copyright Daniel Friesel (and various contributors) 2010-2018.
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 f41cdcd..4d2f2fa 100644
--- a/src/imlib.c
+++ b/src/imlib.c
@@ -26,6 +26,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "feh.h"
#include "filelist.h"
+#include "signals.h"
#include "winwidget.h"
#include "options.h"
@@ -294,10 +295,22 @@ int feh_load_image(Imlib_Image * im, feh_file * file)
}
file->ed = exifData;
- if (orientation == 3)
+ if (orientation == 2)
+ gib_imlib_image_flip_horizontal(*im);
+ else if (orientation == 3)
gib_imlib_image_orientate(*im, 2);
+ else if (orientation == 4)
+ gib_imlib_image_flip_vertical(*im);
+ else if (orientation == 5) {
+ gib_imlib_image_orientate(*im, 3);
+ gib_imlib_image_flip_vertical(*im);
+ }
else if (orientation == 6)
gib_imlib_image_orientate(*im, 1);
+ else if (orientation == 7) {
+ gib_imlib_image_orientate(*im, 3);
+ gib_imlib_image_flip_horizontal(*im);
+ }
else if (orientation == 8)
gib_imlib_image_orientate(*im, 3);
#endif
@@ -529,6 +542,24 @@ static char *feh_magick_load_image(char *filename)
#ifdef HAVE_LIBCURL
+static int curl_quit_function(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
+{
+ // ignore "unused parameter" warnings
+ (void)clientp;
+ (void)dltotal;
+ (void)dlnow;
+ (void)ultotal;
+ (void)ulnow;
+ if (sig_exit) {
+ /*
+ * The user wants to quit feh. Tell libcurl to abort the transfer and
+ * return control to the main loop, where we can quit gracefully.
+ */
+ return 1;
+ }
+ return 0;
+}
+
static char *feh_http_load_image(char *url)
{
CURL *curl;
@@ -571,12 +602,21 @@ static char *feh_http_load_image(char *url)
#ifdef DEBUG
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
#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
+ * feh hanging indefinitely in unattended slideshows.
+ */
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1800);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, sfp);
ebuff = emalloc(CURL_ERROR_SIZE);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, ebuff);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
+ curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, curl_quit_function);
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
if (opt.insecure_ssl) {
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
@@ -589,7 +629,9 @@ static char *feh_http_load_image(char *url)
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if (res != CURLE_OK) {
- weprintf("open url: %s", ebuff);
+ if (res != CURLE_ABORTED_BY_CALLBACK) {
+ weprintf("open url: %s", ebuff);
+ }
unlink(sfn);
close(fd);
free(sfn);
@@ -1192,6 +1234,26 @@ void feh_edit_inplace(winwidget w, int op)
if (!w->file || !w->file->data || !FEH_FILE(w->file->data)->filename)
return;
+ if (!opt.edit) {
+ imlib_context_set_image(w->im);
+ if (op == INPLACE_EDIT_FLIP)
+ imlib_image_flip_vertical();
+ else if (op == INPLACE_EDIT_MIRROR)
+ imlib_image_flip_horizontal();
+ else {
+ imlib_image_orientate(op);
+ tmp = w->im_w;
+ w->im_w = w->im_h;
+ w->im_h = tmp;
+ if (FEH_FILE(w->file->data)->info) {
+ FEH_FILE(w->file->data)->info->width = w->im_w;
+ FEH_FILE(w->file->data)->info->height = w->im_h;
+ }
+ }
+ winwidget_render_image(w, 1, 0);
+ return;
+ }
+
if (!strcmp(gib_imlib_image_format(w->im), "jpeg") &&
!path_is_url(FEH_FILE(w->file->data)->filename)) {
feh_edit_inplace_lossless(w, op);
@@ -1229,8 +1291,12 @@ void feh_edit_inplace(winwidget w, int op)
else {
imlib_image_orientate(op);
tmp = w->im_w;
- FEH_FILE(w->file->data)->info->width = w->im_w = w->im_h;
- FEH_FILE(w->file->data)->info->height = w->im_h = tmp;
+ w->im_w = w->im_h;
+ w->im_h = tmp;
+ if (FEH_FILE(w->file->data)->info) {
+ FEH_FILE(w->file->data)->info->width = w->im_w;
+ FEH_FILE(w->file->data)->info->height = w->im_h;
+ }
}
im_weprintf(w, "unable to edit in place. Changes have not been saved.");
winwidget_render_image(w, 1, 0);
diff --git a/src/keyevents.c b/src/keyevents.c
index 689aebd..6c2f06e 100644
--- a/src/keyevents.c
+++ b/src/keyevents.c
@@ -195,10 +195,10 @@ void init_keyevents(void) {
feh_set_kb("toggle_caption" , 0, XK_c, 0, 0, 0, 0);
feh_set_kb("toggle_pause" , 0, XK_h, 0, 0, 0, 0);
feh_set_kb("toggle_menu" , 0, XK_m, 0, 0, 0, 0);
- feh_set_kb("toggle_fullscreen" , 0, XK_v, 0, 0, 0, 0);
+ feh_set_kb("toggle_fullscreen" , 0, XK_f, 0, 0, 0, 0);
feh_set_kb("reload_image" , 0, XK_r, 0, 0, 0, 0);
feh_set_kb("save_image" , 0, XK_s, 0, 0, 0, 0);
- feh_set_kb("save_filelist" , 0, XK_f, 0, 0, 0, 0);
+ feh_set_kb("save_filelist" , 0, XK_L, 0, 0, 0, 0);
feh_set_kb("orient_1" , 0, XK_greater, 0, 0, 0, 0);
feh_set_kb("orient_3" , 0, XK_less, 0, 0, 0, 0);
feh_set_kb("flip" , 0, XK_underscore, 0, 0, 0, 0);
@@ -686,7 +686,7 @@ void feh_event_handle_generic(winwidget winwid, unsigned int state, KeySym keysy
}
else if (feh_is_kp(EVENT_jump_random, state, keysym, button)) {
if (winwid->type == WIN_TYPE_THUMBNAIL)
- feh_thumbnail_select_next(winwid, rand() % (filelist_len - 1));
+ feh_thumbnail_select_next(winwid, random() % (filelist_len - 1));
else
slideshow_change_image(winwid, SLIDE_RAND, 1);
}
diff --git a/src/main.c b/src/main.c
index d839a93..58a18cf 100644
--- a/src/main.c
+++ b/src/main.c
@@ -46,7 +46,7 @@ int main(int argc, char **argv)
{
atexit(feh_clean_exit);
- srand(getpid() * time(NULL) % ((unsigned int) -1));
+ srandom(getpid() * time(NULL) % ((unsigned int) -1));
setup_signal_handlers();
init_parse_options(argc, argv);
@@ -72,8 +72,6 @@ int main(int argc, char **argv)
if (opt.index)
init_index_mode();
- else if (opt.collage)
- init_collage_mode();
else if (opt.multiwindow)
init_multiwindow_mode();
else if (opt.list || opt.customlist)
@@ -205,7 +203,7 @@ int feh_main_iteration(int block)
&& ((errno == ENOMEM) || (errno == EINVAL)
|| (errno == EBADF)))
eprintf("Connection to X display lost");
- if ((ft) && (count == 0)) {
+ if (count == 0) {
/* This means the timer is due to be executed. If count was > 0,
that would mean an X event had woken us, we're not interested
in that */
@@ -246,7 +244,6 @@ void feh_clean_exit(void)
{
delete_rm_files();
- free(opt.menu_bg);
free(opt.menu_font);
#ifdef HAVE_INOTIFY
diff --git a/src/menu.c b/src/menu.c
index 2f8875d..fcbb490 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -134,7 +134,7 @@ feh_menu *feh_menu_new(void)
menus = l;
if (!bg) {
- feh_load_image_char(&bg, opt.menu_bg);
+ feh_load_image_char(&bg, PREFIX "/share/feh/images/menubg_default.png");
if (bg) {
border.left = border.right = border.top = border.bottom
= 4;
diff --git a/src/options.c b/src/options.c
index 364fb42..2a5aae8 100644
--- a/src/options.c
+++ b/src/options.c
@@ -61,7 +61,6 @@ void init_parse_options(int argc, char **argv)
opt.scroll_step = 20;
opt.menu_font = estrdup(DEFAULT_MENU_FONT);
opt.font = NULL;
- opt.menu_bg = estrdup(PREFIX "/share/feh/images/menubg_default.png");
opt.max_height = opt.max_width = UINT_MAX;
opt.start_list_at = NULL;
@@ -131,6 +130,7 @@ static void feh_load_options_for_theme(char *theme)
char *rcpath = NULL;
char *oldrcpath = NULL;
char *confbase = getenv("XDG_CONFIG_HOME");
+ // s, s1 and s2 must always have identical size
char s[1024], s1[1024], s2[1024];
int cont = 0;
int bspos;
@@ -167,11 +167,19 @@ static void feh_load_options_for_theme(char *theme)
s2[0] = '\0';
if (cont) {
+ /*
+ * fgets ensures that s contains no more than 1023 characters
+ * (+ 1 null byte)
+ */
sscanf(s, " %[^\n]\n", (char *) &s2);
if (!*s2)
break;
D(("Got continued options %s\n", s2));
} else {
+ /*
+ * fgets ensures that s contains no more than 1023 characters
+ * (+ 1 null byte)
+ */
sscanf(s, "%s %[^\n]\n", (char *) &s1, (char *) &s2);
if (!(*s1) || (!*s2) || (*s1 == '\n') || (*s1 == '#')) {
cont = 0;
@@ -313,12 +321,11 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
{
int discard;
static char stropts[] =
- "a:A:b:B:cC:dD:e:E:f:Fg:GhH:iIj:J:kK:lL:mM:nNo:O:pPqrR:sS:tT:uUvVwW:xXy:YzZ"
- ".@:^:~:):|:+:<:>:";
+ "a:A:b:B:C:dD:e:E:f:Fg:GhH:iIj:J:kK:lL:mM:nNo:O:pPqrR:sS:tT:uUvVwW:xXy:YzZ"
+ ".@:^:~:|:+:<:>:";
/* (*name, has_arg, *flag, val) See: struct option in getopts.h */
static struct option lopts[] = {
- {"menu-bg" , 1, 0, ')'},
{"debug" , 0, 0, '+'},
{"scale-down" , 0, 0, '.'},
{"max-dimension" , 1, 0, '<'},
@@ -353,7 +360,6 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
{"title" , 1, 0, '^'},
{"alpha" , 1, 0, 'a'},
{"bg" , 1, 0, 'b'},
- {"collage" , 0, 0, 'c'},
{"draw-filename" , 0, 0, 'd'},
{"font" , 1, 0, 'e'},
{"filelist" , 1, 0, 'f'},
@@ -398,11 +404,11 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
{"bg-fill" , 0, 0, 218},
{"bg-max" , 0, 0, 219},
{"no-jump-on-resort", 0, 0, 220},
+ {"edit" , 0, 0, 221},
#ifdef HAVE_LIBEXIF
{"draw-exif" , 0, 0, 223},
{"auto-rotate" , 0, 0, 242},
#endif
- {"cycle-once" , 0, 0, 224},
{"no-xinerama" , 0, 0, 225},
{"draw-tinted" , 0, 0, 229},
{"info" , 1, 0, 234},
@@ -430,11 +436,6 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
switch (optch) {
case 0:
break;
- case ')':
- free(opt.menu_bg);
- opt.menu_bg = estrdup(optarg);
- weprintf("The --menu-bg option is deprecated and will be removed by 2012");
- break;
case '+':
opt.debug = 1;
break;
@@ -471,6 +472,8 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
if (opt.slideshow_delay < 0.0) {
opt.slideshow_delay *= (-1);
opt.paused = 1;
+ } else {
+ opt.paused = 0;
}
break;
case 'E':
@@ -580,9 +583,6 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
opt.bg = 1;
opt.bg_file = estrdup(optarg);
break;
- case 'c':
- opt.collage = 1;
- break;
case 'd':
opt.draw_filename = 1;
break;
@@ -736,6 +736,9 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
case 220:
opt.jump_on_resort = 0;
break;
+ case 221:
+ opt.edit = 1;
+ break;
#ifdef HAVE_LIBEXIF
case 223:
opt.draw_exif = 1;
@@ -744,10 +747,6 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
opt.auto_rotate = 1;
break;
#endif
- case 224:
- weprintf("--cycle-once is deprecated, please use --on-last-slide=quit instead");
- opt.on_last_slide = ON_LAST_SLIDE_QUIT;
- break;
case 225:
opt.xinerama = 0;
break;
@@ -756,10 +755,12 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
break;
case 234:
opt.info_cmd = estrdup(optarg);
- if (opt.info_cmd[0] == ';')
+ if (opt.info_cmd[0] == ';') {
+ opt.draw_info = 0;
opt.info_cmd++;
- else
+ } else {
opt.draw_info = 1;
+ }
break;
case 235:
opt.force_aliasing = 1;
@@ -831,8 +832,19 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)
add_file_to_filelist_recursively(argv[optind++], FILELIST_FIRST);
}
}
- else if (finalrun && !opt.filelistfile && !opt.bgmode)
- add_file_to_filelist_recursively(".", FILELIST_FIRST);
+ else if (finalrun && !opt.filelistfile && !opt.bgmode) {
+ if (opt.start_list_at && !path_is_url(opt.start_list_at) && strrchr(opt.start_list_at, '/')) {
+ char *target_directory = estrdup(opt.start_list_at);
+ char *filename_start = strrchr(target_directory, '/');
+ if (filename_start) {
+ *filename_start = '\0';
+ }
+ add_file_to_filelist_recursively(target_directory, FILELIST_FIRST);
+ free(target_directory);
+ } else {
+ add_file_to_filelist_recursively(".", FILELIST_FIRST);
+ }
+ }
/* So that we can safely be called again */
optind = 0;
@@ -860,17 +872,11 @@ static void check_options(void)
}
}
- if ((opt.index + opt.collage) > 1) {
- weprintf("you can't use collage mode and index mode together.\n"
- " I'm going with index");
- opt.collage = 0;
- }
-
if (opt.full_screen && opt.multiwindow) {
eprintf("You cannot combine --fullscreen with --multiwindow");
}
- if (opt.list && (opt.multiwindow || opt.index || opt.collage)) {
+ if (opt.list && (opt.multiwindow || opt.index)) {
eprintf("You cannot combine --list with other modes");
}
@@ -910,6 +916,10 @@ static void show_version(void)
"stat64 "
#endif
+#ifdef HAVE_VERSCMP
+ "verscmp "
+#endif
+
#ifdef HAVE_LIBXINERAMA
"xinerama "
#endif
diff --git a/src/options.h b/src/options.h
index cae04ec..883c8e2 100644
--- a/src/options.h
+++ b/src/options.h
@@ -36,7 +36,6 @@ enum on_last_slide_action {
struct __fehoptions {
unsigned char multiwindow;
unsigned char montage;
- unsigned char collage;
unsigned char index;
unsigned char thumbs;
unsigned char slideshow;
@@ -85,6 +84,7 @@ struct __fehoptions {
unsigned char keep_zoom_vp;
unsigned char insecure_ssl;
unsigned char filter_by_dimensions;
+ unsigned char edit;
char *output_file;
char *output_dir;
@@ -100,7 +100,6 @@ struct __fehoptions {
char *filelistfile;
char *menu_font;
char *customlist;
- char *menu_bg;
char *caption_path;
char *start_list_at;
char *info_cmd;
diff --git a/src/signals.c b/src/signals.c
index aeaf889..85d81bc 100644
--- a/src/signals.c
+++ b/src/signals.c
@@ -24,11 +24,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "feh.h"
+#include "filelist.h"
#include "winwidget.h"
#include "options.h"
void feh_handle_signal(int);
-int sig_exit = 0;
+volatile int sig_exit = 0;
void setup_signal_handlers()
{
@@ -94,10 +95,14 @@ void feh_handle_signal(int signo)
winwid = winwidget_get_first_window_of_type(WIN_TYPE_SLIDESHOW);
if (winwid) {
- if (signo == SIGUSR1)
- slideshow_change_image(winwid, SLIDE_NEXT, 1);
- else if (signo == SIGUSR2)
- slideshow_change_image(winwid, SLIDE_PREV, 1);
+ 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);
diff --git a/src/signals.h b/src/signals.h
index 090ab0b..bff737e 100644
--- a/src/signals.h
+++ b/src/signals.h
@@ -27,5 +27,5 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define SIGNALS_H
void setup_signal_handlers();
-extern int sig_exit;
+extern volatile int sig_exit;
#endif
diff --git a/src/slideshow.c b/src/slideshow.c
index 3770677..145ced1 100644
--- a/src/slideshow.c
+++ b/src/slideshow.c
@@ -37,6 +37,24 @@ void init_slideshow_mode(void)
int success = 0;
gib_list *l = filelist, *last = NULL;
+ /*
+ * In theory, --start-at FILENAME is simple: Look for a file called
+ * FILENAME, start the filelist there, done.
+ *
+ * In practice, there are cases where this isn't sufficient. For instance,
+ * a user running 'feh --start-at hello.jpg /tmp' will expect feh to start
+ * at /tmp/hello.jpg, as if they had used
+ * 'feh --start-at /tmp/hello.jpg /tmp'. Similarly, XDG Desktop files
+ * may lead to the invocation 'feh --start-at /tmp/hello.jpg .' in /tmp,
+ * expecting the behaviour of 'feh --start-at ./hello.jpg .'.
+ *
+ * Since a good user experience is not about being technically correct, but
+ * about delivering the expected behaviour, we do some fuzzy matching
+ * here. In the worst case, this will cause --start-at to start at the
+ * wrong file.
+ */
+
+ // 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)) {
opt.start_list_at = NULL;
@@ -44,6 +62,34 @@ void init_slideshow_mode(void)
}
}
+ /*
+ * If it didn't work (opt.start_list_at is still set): Fall back to
+ * comparing just the filenames without directory prefixes. This may lead
+ * to false positives, but for now that's just the way it is.
+ */
+ if (opt.start_list_at) {
+ char *current_filename;
+ char *start_at_filename = strrchr(opt.start_list_at, '/');
+ if (start_at_filename) {
+ start_at_filename++; // We only care about the part after the '/'
+ } else {
+ start_at_filename = opt.start_list_at;
+ }
+ for (l = filelist; l && opt.start_list_at; l = l->next) {
+ current_filename = strrchr(FEH_FILE(l->data)->filename, '/');
+ if (current_filename) {
+ current_filename++; // We only care about the part after the '/'
+ } else {
+ current_filename = FEH_FILE(l->data)->filename;
+ }
+ if (!strcmp(start_at_filename, current_filename)) {
+ opt.start_list_at = NULL;
+ break;
+ }
+ }
+ }
+
+ // If that didn't work either, we're out of luck.
if (opt.start_list_at)
eprintf("--start-at %s: File not found in filelist",
opt.start_list_at);
@@ -258,7 +304,7 @@ void slideshow_change_image(winwidget winwid, int change, int render)
case SLIDE_RAND:
if (filelist_len > 1) {
current_file = feh_list_jump(filelist, current_file, FORWARD,
- (rand() % (filelist_len - 1)) + 1);
+ (random() % (filelist_len - 1)) + 1);
change = SLIDE_NEXT;
}
break;
@@ -615,16 +661,24 @@ void slideshow_save_image(winwidget win)
{
char *tmpname;
Imlib_Load_Error err;
+ char *base_dir = "";
+ if (opt.output_dir) {
+ base_dir = estrjoin("", opt.output_dir, "/", NULL);
+ }
if (win->file) {
- tmpname = feh_unique_filename("", FEH_FILE(win->file->data)->name);
+ tmpname = feh_unique_filename(base_dir, FEH_FILE(win->file->data)->name);
} else if (mode) {
char *tmp;
tmp = estrjoin(".", mode, "png", NULL);
- tmpname = feh_unique_filename("", tmp);
+ tmpname = feh_unique_filename(base_dir, tmp);
free(tmp);
} else {
- tmpname = feh_unique_filename("", "noname.png");
+ tmpname = feh_unique_filename(base_dir, "noname.png");
+ }
+
+ if (opt.output_dir) {
+ free(base_dir);
}
if (opt.verbose)
diff --git a/src/utils.c b/src/utils.c
index ec30d4a..087e7f6 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -152,6 +152,7 @@ char path_is_url(char *path) {
return 0;
}
+/* Note: path must end with a trailing / or be an empty string */
/* free the result please */
char *feh_unique_filename(char *path, char *basename)
{
diff --git a/src/wallpaper.c b/src/wallpaper.c
index db14a8c..9df259f 100644
--- a/src/wallpaper.c
+++ b/src/wallpaper.c
@@ -252,7 +252,7 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled,
XGCValues gcval;
GC gc;
char bgname[20];
- int num = (int) rand();
+ int num = (int) random();
char bgfil[4096];
char sendbuf[4096];
@@ -502,15 +502,16 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled,
}
fputc(' ', fp);
if (use_filelist) {
- for (int i = 0; i < cmdargc; i++) {
- if (filelist_pos && !strcmp(FEH_FILE(filelist_pos->data)->filename, cmdargv[i])) {
- /* argument is a file */
- absolute_path = feh_absolute_path(cmdargv[i]);
- fputs(shell_escape(absolute_path), fp);
- filelist_pos = filelist_pos->next;
- free(absolute_path);
- fputc(' ', fp);
- }
+#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);
diff --git a/src/winwidget.c b/src/winwidget.c
index 4993fb6..020ee5b 100644
--- a/src/winwidget.c
+++ b/src/winwidget.c
@@ -211,7 +211,6 @@ void winwidget_create_window(winwidget ret, int w, int h)
}
if (opt.paused) {
- printf("name %s\n", ret->name);
tmpname = estrjoin(" ", ret->name, "[Paused]", NULL);
free(ret->name);
ret->name = tmpname;
@@ -821,8 +820,6 @@ void winwidget_show(winwidget winwid)
void winwidget_move(winwidget winwid, int x, int y)
{
if (winwid && ((winwid->x != x) || (winwid->y != y))) {
- winwid->x = x;
- winwid->y = y;
winwid->x = (x > scr->width) ? scr->width : x;
winwid->y = (y > scr->height) ? scr->height : y;
XMoveWindow(disp, winwid->win, winwid->x, winwid->y);