diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile | 1 | ||||
| -rw-r--r-- | src/collage.c | 208 | ||||
| -rw-r--r-- | src/feh.h | 1 | ||||
| -rw-r--r-- | src/filelist.c | 7 | ||||
| -rw-r--r-- | src/gib_imlib.c | 12 | ||||
| -rw-r--r-- | src/gib_imlib.h | 2 | ||||
| -rw-r--r-- | src/gib_list.c | 2 | ||||
| -rw-r--r-- | src/help.raw | 32 | ||||
| -rw-r--r-- | src/imlib.c | 74 | ||||
| -rw-r--r-- | src/keyevents.c | 6 | ||||
| -rw-r--r-- | src/main.c | 7 | ||||
| -rw-r--r-- | src/menu.c | 2 | ||||
| -rw-r--r-- | src/options.c | 68 | ||||
| -rw-r--r-- | src/options.h | 3 | ||||
| -rw-r--r-- | src/signals.c | 15 | ||||
| -rw-r--r-- | src/signals.h | 2 | ||||
| -rw-r--r-- | src/slideshow.c | 62 | ||||
| -rw-r--r-- | src/utils.c | 1 | ||||
| -rw-r--r-- | src/wallpaper.c | 21 | ||||
| -rw-r--r-- | src/winwidget.c | 3 | 
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; -} @@ -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);  	} @@ -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 @@ -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); | 
