diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/collage.c | 1 | ||||
| -rw-r--r-- | src/debug.h | 1 | ||||
| -rw-r--r-- | src/deps.mk | 41 | ||||
| -rw-r--r-- | src/events.c | 21 | ||||
| -rw-r--r-- | src/feh.h | 5 | ||||
| -rw-r--r-- | src/feh_png.c | 6 | ||||
| -rw-r--r-- | src/fehrc.raw | 74 | ||||
| -rw-r--r-- | src/filelist.c | 1 | ||||
| -rw-r--r-- | src/help.raw | 17 | ||||
| -rw-r--r-- | src/imlib.c | 307 | ||||
| -rw-r--r-- | src/index.c | 1 | ||||
| -rw-r--r-- | src/keyevents.c | 635 | ||||
| -rw-r--r-- | src/list.c | 1 | ||||
| -rw-r--r-- | src/main.c | 5 | ||||
| -rw-r--r-- | src/menu.c | 18 | ||||
| -rw-r--r-- | src/menu.h | 1 | ||||
| -rw-r--r-- | src/multiwindow.c | 4 | ||||
| -rw-r--r-- | src/options.c | 189 | ||||
| -rw-r--r-- | src/options.h | 69 | ||||
| -rw-r--r-- | src/signals.c | 5 | ||||
| -rw-r--r-- | src/slideshow.c | 42 | ||||
| -rw-r--r-- | src/structs.h | 3 | ||||
| -rw-r--r-- | src/support.c | 174 | ||||
| -rw-r--r-- | src/support.h | 1 | ||||
| -rw-r--r-- | src/thumbnail.c | 54 | ||||
| -rw-r--r-- | src/thumbnail.h | 7 | ||||
| -rw-r--r-- | src/timers.c | 1 | ||||
| -rw-r--r-- | src/winwidget.c | 39 | ||||
| -rw-r--r-- | src/winwidget.h | 6 | 
29 files changed, 911 insertions, 818 deletions
| diff --git a/src/collage.c b/src/collage.c index 782d5f8..1f2fac4 100644 --- a/src/collage.c +++ b/src/collage.c @@ -1,6 +1,7 @@  /* collage.c  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to diff --git a/src/debug.h b/src/debug.h index 93cb6bf..eb929e3 100644 --- a/src/debug.h +++ b/src/debug.h @@ -1,6 +1,7 @@  /* debug.h  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to diff --git a/src/deps.mk b/src/deps.mk deleted file mode 100644 index 36b264f..0000000 --- a/src/deps.mk +++ /dev/null @@ -1,41 +0,0 @@ -collage.o: collage.c feh.h structs.h menu.h utils.h getopt.h debug.h \ -  winwidget.h filelist.h options.h -events.o: events.c feh.h structs.h menu.h utils.h getopt.h debug.h \ -  filelist.h winwidget.h timers.h options.h events.h thumbnail.h -feh_png.o: feh_png.c feh_png.h feh.h structs.h menu.h utils.h getopt.h \ -  debug.h -filelist.o: filelist.c feh.h structs.h menu.h utils.h getopt.h debug.h \ -  filelist.h options.h -getopt.o: getopt.c -getopt1.o: getopt1.c getopt.h -imlib.o: imlib.c feh.h structs.h menu.h utils.h getopt.h debug.h \ -  filelist.h winwidget.h options.h -index.o: index.c feh.h structs.h menu.h utils.h getopt.h debug.h \ -  filelist.h winwidget.h options.h -keyevents.o: keyevents.c feh.h structs.h menu.h utils.h getopt.h debug.h \ -  thumbnail.h filelist.h winwidget.h options.h -list.o: list.c feh.h structs.h menu.h utils.h getopt.h debug.h filelist.h \ -  options.h -main.o: main.c feh.h structs.h menu.h utils.h getopt.h debug.h filelist.h \ -  winwidget.h timers.h options.h events.h support.h -md5.o: md5.c md5.h -menu.o: menu.c feh.h structs.h menu.h utils.h getopt.h debug.h support.h \ -  thumbnail.h filelist.h winwidget.h options.h -multiwindow.o: multiwindow.c feh.h structs.h menu.h utils.h getopt.h \ -  debug.h winwidget.h timers.h filelist.h options.h -options.o: options.c feh.h structs.h menu.h utils.h getopt.h debug.h \ -  filelist.h options.h help.inc fehrc.inc -signals.o: signals.c feh.h structs.h menu.h utils.h getopt.h debug.h \ -  winwidget.h -slideshow.o: slideshow.c feh.h structs.h menu.h utils.h getopt.h debug.h \ -  filelist.h timers.h winwidget.h options.h signals.h -support.o: support.c feh.h structs.h menu.h utils.h getopt.h debug.h \ -  filelist.h options.h support.h -thumbnail.o: thumbnail.c feh.h structs.h menu.h utils.h getopt.h debug.h \ -  filelist.h winwidget.h options.h thumbnail.h md5.h feh_png.h -timers.o: timers.c feh.h structs.h menu.h utils.h getopt.h debug.h \ -  options.h timers.h -utils.o: utils.c feh.h structs.h menu.h utils.h getopt.h debug.h \ -  options.h -winwidget.o: winwidget.c feh.h structs.h menu.h utils.h getopt.h debug.h \ -  filelist.h winwidget.h options.h diff --git a/src/events.c b/src/events.c index 36379b1..a850137 100644 --- a/src/events.c +++ b/src/events.c @@ -1,6 +1,7 @@  /* events.c  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to @@ -182,7 +183,7 @@ static void feh_event_handle_ButtonRelease(XEvent * ev)  				opt.mode = MODE_NORMAL;  				winwid->mode = MODE_NORMAL;  				winwidget_sanitise_offsets(winwid); -				winwidget_render_image(winwid, 0, 1); +				winwidget_render_image(winwid, 0, 0);  			}  		} else if (opt.mode == MODE_NEXT) {  			opt.mode = MODE_NORMAL; @@ -247,7 +248,7 @@ static void feh_event_handle_ButtonRelease(XEvent * ev)  			} else  				winwidget_sanitise_offsets(winwid); -			winwidget_render_image(winwid, 0, 1); +			winwidget_render_image(winwid, 0, 0);  		}  	} else if ((ev->xbutton.button == opt.blur_button)  			&& ((opt.no_blur_ctrl_mask) @@ -280,7 +281,7 @@ static void feh_event_handle_ConfigureNotify(XEvent * ev)  					opt.geom_w = w->w;  					opt.geom_h = w->h;  				} -				winwidget_render_image(w, 0, 1); +				winwidget_render_image(w, 0, 0);  			}  		}  	} @@ -403,7 +404,7 @@ static void feh_event_handle_MotionNotify(XEvent * ev)  			winwid->im_y = winwid->click_offset_y  					- (winwid->im_click_offset_y * winwid->zoom); -			winwidget_render_image(winwid, 0, 0); +			winwidget_render_image(winwid, 0, 1);  		}  	} else if ((opt.mode == MODE_PAN) || (opt.mode == MODE_NEXT)) {  		int orig_x, orig_y; @@ -462,7 +463,7 @@ static void feh_event_handle_MotionNotify(XEvent * ev)  			if ((winwid->im_x != orig_x)  					|| (winwid->im_y != orig_y)) -				winwidget_render_image(winwid, 0, 0); +				winwidget_render_image(winwid, 0, 1);  		}  	} else if (opt.mode == MODE_ROTATE) {  		while (XCheckTypedWindowEvent(disp, ev->xmotion.window, MotionNotify, ev)); @@ -482,7 +483,7 @@ static void feh_event_handle_MotionNotify(XEvent * ev)  			}  			winwid->im_angle = (ev->xmotion.x - winwid->w / 2) / ((double) winwid->w / 2) * 3.1415926535;  			D(("angle: %f\n", winwid->im_angle)); -			winwidget_render_image(winwid, 0, 0); +			winwidget_render_image(winwid, 0, 1);  		}  	} else if (opt.mode == MODE_BLUR) {  		while (XCheckTypedWindowEvent(disp, ev->xmotion.window, MotionNotify, ev)); @@ -502,7 +503,7 @@ static void feh_event_handle_MotionNotify(XEvent * ev)  				gib_imlib_image_blur(temp, 0 - blur_radius);  			ptr = winwid->im;  			winwid->im = temp; -			winwidget_render_image(winwid, 0, 0); +			winwidget_render_image(winwid, 0, 1);  			gib_imlib_free_image_and_decache(winwid->im);  			winwid->im = ptr;  		} @@ -521,7 +522,7 @@ static void feh_event_handle_MotionNotify(XEvent * ev)  				imlib_context_set_image(winwid->im);  				imlib_apply_filter("bump_map_point(x=[],y=[],map="  						PREFIX "/share/feh/images/about.png);", &x, &y); -				winwidget_render_image(winwid, 0, 1); +				winwidget_render_image(winwid, 0, 0);  				gib_imlib_free_image_and_decache(winwid->im);  				winwid->im = orig_im;  			} else if (winwid->type == WIN_TYPE_THUMBNAIL) { @@ -552,11 +553,11 @@ static void feh_event_handle_MotionNotify(XEvent * ev)  								thumbnail->x + 2, thumbnail->y + 2,  								thumbnail->w - 4, thumbnail->h - 4,  								255, 255, 255, 255); -						winwidget_render_image(winwid, 0, 1); +						winwidget_render_image(winwid, 0, 0);  						gib_imlib_free_image_and_decache(winwid->im);  						winwid->im = origwin;  					} else -						winwidget_render_image(winwid, 0, 1); +						winwidget_render_image(winwid, 0, 0);  				}  				last_thumb = thumbnail;  			} @@ -1,6 +1,7 @@  /* feh.h  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to @@ -120,6 +121,7 @@ void show_mini_usage(void);  void slideshow_change_image(winwidget winwid, int change);  void slideshow_pause_toggle(winwidget w);  char *slideshow_create_name(feh_file * file); +void init_keyevents(void);  void feh_event_handle_keypress(XEvent * ev);  void feh_action_run(feh_file * file, char *action);  char *feh_printf(char *str, feh_file * file); @@ -137,12 +139,11 @@ void feh_display_status(char stat);  void real_loadables_mode(int loadable);  void feh_reload_image(winwidget w, int resize, int force_new);  void feh_filelist_image_remove(winwidget winwid, char do_delete); -char *feh_strip_hostname(char *url);  void slideshow_save_image(winwidget win);  void feh_edit_inplace_orient(winwidget w, int orientation);  void feh_edit_inplace_lossless_rotate(winwidget w, int orientation);  gib_list *feh_wrap_string(char *text, int wrap_width, Imlib_Font fn, gib_style * style); -char *build_caption_filename(feh_file * file); +char *build_caption_filename(feh_file * file, short create_dir);  gib_list *feh_list_jump(gib_list * root, gib_list * l, int direction, int num);  /* Imlib stuff */ diff --git a/src/feh_png.c b/src/feh_png.c index e2842f8..f02aecb 100644 --- a/src/feh_png.c +++ b/src/feh_png.c @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  #include <stdarg.h>  #define FEH_PNG_COMPRESSION 3 -#define FEH_PNG_NUM_COMMENTS 2	/* only Thumb::URI and Thumb::MTime for now */ +#define FEH_PNG_NUM_COMMENTS 4  gib_hash *feh_png_read_comments(char *file)  { @@ -66,7 +66,7 @@ gib_hash *feh_png_read_comments(char *file)  		return hash;  	} -	if (setjmp(png_ptr->jmpbuf)) { +	if (setjmp(png_jmpbuf(png_ptr))) {  		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);  		fclose(fp);  		return hash; @@ -124,7 +124,7 @@ int feh_png_write_png(Imlib_Image image, char *file, ...)  		return 0;  	} -	if (setjmp(png_ptr->jmpbuf)) { +	if (setjmp(png_jmpbuf(png_ptr))) {  		fclose(fp);  		png_destroy_write_struct(&png_ptr, &info_ptr);  		png_destroy_info_struct(png_ptr, &info_ptr); diff --git a/src/fehrc.raw b/src/fehrc.raw deleted file mode 100644 index 154a6e1..0000000 --- a/src/fehrc.raw +++ /dev/null @@ -1,74 +0,0 @@ -# Feh configuration file. -# Lines starting with # are comments. Don't use comments mid-line. - -# Feh expects to find this as ~/.fehrc or /etc/fehrc -# If both are available, ~/.fehrc will be used - -# Options are defined in theme_name/options pairs. -# Separate themename and options by whitespace. - -# There are two ways of specifying the theme. Either use feh -Tthemename, -# or use a symbolic link to feh with the name of the theme. eg -# ln -s `which feh` ~/bin/mkindex -# Now when you run 'mkindex', feh will load the config specified for the -# mkindex theme. - -# Multiple options can of course be used. If they are too long for one line, -# you can (usually) use a \\ to make them continue on the next one: -# imagemap -rV --quiet -W 400 -H 300 \\ -#          --thumb-width 40 --thumb-height 30 - -# ==================== -# A few default themes -# ==================== - -# Webcam mode, simply specify the url(s). -# e.g. feh -Twebcam http://cam1 http://cam2 -webcam --multiwindow --reload 20 - -# Create an index of the current directory. This version uses . as the -# current dir, so you don't even need any commandline arguments. -mkindex -iVO index.jpg . - -# More ambitious version... -imgidx --index --output-only .fehindex.jpg --limit-width 1024 \\ -       --thumb-width 128 --thumb-height 128 --verbose --quiet - -# Show a presentation -present --full-screen --sort name --hide-pointer - -# Booth mode ;-) -booth --full-screen --hide-pointer --slideshow-delay 20 - -# Screw xscreensaver, use feh =) -screensave --recursive --full-screen --randomize --slideshow-delay 10 --hide-pointer - -# Add <img> tags to your html with ease :-) -newimg -q -L \"<img src=\\\"%f\\\" alt=\\\"%n\\\" border=\\\"0\\\" width=\\\"%w\\\" height=\\\"%h\\\">\" - -# Different menus -brushed --menu-bg " PREFIX "/share/feh/images/menubg_brushed.png -aluminium --menu-bg " PREFIX "/share/feh/images/menubg_aluminium.png -aqua --menu-bg " PREFIX "/share/feh/images/menubg_aqua.png -sky --menu-bg " PREFIX "/share/feh/images/menubg_sky.png -black --menu-bg " PREFIX "/share/feh/images/menubg_black.png \\ -      --menu-style " PREFIX "/share/feh/fonts/black.style - -# Some more examples, used by the feh developer - -rfs --full-screen --hide-pointer --auto-zoom --randomize -fs  --full-screen --hide-pointer --auto-zoom --sort filename - -thumb_s  --thumbnails --cache-thumbnails --thumb-width 128 --thumb-height 128 \\ -         --limit-width 1024 --sort filename \\ -         --fontpath /usr/share/fonts/truetype/ttf-dejavu/ --font DejaVuSans/8 - -thumb_b  --thumbnails --cache-thumbnails --thumb-width 256 --thumb-height 256 \\ -         --limit-width 1024 --sort filename \\ -         --fontpath /usr/share/fonts/truetype/ttf-dejavu/ --font DejaVuSans/8 - -thumb_s_nt --thumbnails --cache-thumbnails --thumb-width 128 --thumb-height 128 \\ -           --limit-width 1024 --sort filename --index-name 0 - -thumb_b_nt --thumbnails --cache-thumbnails --thumb-width 256 --thumb-height 256 \\ -           --limit-width 1024 --sort filename --index-name 0 diff --git a/src/filelist.c b/src/filelist.c index e1b4055..fa1735d 100644 --- a/src/filelist.c +++ b/src/filelist.c @@ -1,6 +1,7 @@  /* filelist.c  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to diff --git a/src/help.raw b/src/help.raw index e0ea432..bbe5e37 100644 --- a/src/help.raw +++ b/src/help.raw @@ -2,7 +2,7 @@  Usage : " PACKAGE " [options] <files or directories ...> - This is just a short option summary.  Please consult the manual for details. + This is just a short option summary.  Please see \"man " PACKAGE "\" for details.  OPTIONS   -h, --help                Show help and exit @@ -10,7 +10,6 @@ OPTIONS   -V, --verbose             Show progress bars and other extra information   -q, --quiet               Hide non-fatal errors. May be used with --verbose   -T, --theme THEME         Load options with name THEME - -_, --rcfile FILE         Use FILE to parse themes and options from   -r, --recursive           Recursively expand any directories in FILE to                             the content of those directories. (Take it easy)   -z, --randomize           Randomize the filelist @@ -36,7 +35,6 @@ OPTIONS   -D, --slideshow-delay NUM Set delay between automatically changing slides       --cycle-once          Exit after one loop through the slideshow   -R, --reload NUM          Reload images after NUM seconds - -Q, --builtin             Use builtin http client instead of wget   -k, --keep-http           Keep local copies when viewing HTTP/FTP files   -K, --caption-path PATH   Path to caption directory, enables caption display   -j, --output-dir          With -k: Output directory for saved files @@ -50,8 +48,8 @@ OPTIONS   -A, --action ACTION       Specify action to perform when pressing <return>.                             Executed by /bin/sh, may contain FORMAT SPECIFIERS       --action[1-9]         Extra actions triggered by pressing keys <1>to <9> -     --action-hold-slide   Do not change to next image after running an action   -G, --draw-actions        Show the defined actions in the image window +     --force-aliasing      Disable antialiasing   -m, --montage             Enable montage mode   -c, --collage             Montage mode with randomly distributed thumbnails   -i, --index               Create an index print of all images @@ -79,8 +77,6 @@ OPTIONS   -C, --fontpath PATH       Specify an extra directory to look in for fonts,                             can be used multiple times to add multiple paths.   -M, --menu-font FONT      Use FONT for the font in menus. -     --menu-style FILE     Use FILE as the style descriptor for menu text. - -), --menu-bg BG          Use BG for the background image in menus.   -B, --image-bg STYLE      Set background for transparent images and the like.                             Accepted values: white, black, default   -N, --no-menus            Don't load or show any menus. @@ -148,7 +144,7 @@ FORMAT SPECIFIERS   %l     total number of files in the filelist   %u     current file number   %%     % - \\n    newline + \\n     newline  KEYS   p, <BACKSPACE>, <LEFT>  Go to previous slide @@ -188,7 +184,8 @@ KEYS   1-9                     Run action 1-9 specified by --action[1-9] options  This program is free software, see the file COPYING for licensing info. -Copyright Tom Gilbert (and various contributors) 1999-2003 +Copyright Tom Gilbert (and various contributors) 1999-2003. +Copyright Daniel Friesel 2010-2011. -Homepage: https://derf.homelinux.org/p/feh -Email bugs to <derf@finalrewind.org> +Homepage: http://feh.finalrewind.org +Report bugs to <derf@finalrewind.org> or #feh on irc.oftc.net. diff --git a/src/imlib.c b/src/imlib.c index 89271bf..dcf3c5c 100644 --- a/src/imlib.c +++ b/src/imlib.c @@ -1,6 +1,7 @@  /* imlib.c  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to @@ -33,6 +34,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  #include <netinet/in.h>  #include <arpa/inet.h>  #include <netdb.h> +#include <curl/curl.h>  Display *disp = NULL;  Visual *vis = NULL; @@ -231,8 +233,16 @@ int feh_load_image(Imlib_Image * im, feh_file * file)  	return(1);  } +#ifdef HAVE_LIBCURL +  char *feh_http_load_image(char *url)  { +	CURL *curl; +	CURLcode res; +	char *sfn; +	FILE *sfp; +	int fd = -1; +	char *ebuff;  	char *tmpname;  	char *basename;  	char *path = NULL; @@ -248,252 +258,64 @@ char *feh_http_load_image(char *url)  	basename = strrchr(url, '/') + 1;  	tmpname = feh_unique_filename(path, basename); -	if (opt.builtin_http) { -		/* state for HTTP header parser */ -#define SAW_NONE    1 -#define SAW_ONE_CM  2 -#define SAW_ONE_CJ  3 -#define SAW_TWO_CM  4 -#define IN_BODY     5 - -#define OUR_BUF_SIZE 1024 -#define EOL "\015\012" - -		int sockno = 0; -		int size; -		int body = SAW_NONE; -		struct addrinfo hints; -		struct addrinfo *result, *rp; -		char *hostname; -		char *get_string; -		char *host_string; -		char *query_string; -		char *get_url; -		static char buf[OUR_BUF_SIZE]; -		char ua_string[] = "User-Agent: feh image viewer"; -		char accept_string[] = "Accept: image/*"; -		FILE *fp; - -		D(("using builtin http collection\n")); -		fp = fopen(tmpname, "w"); -		if (!fp) { -			weprintf("couldn't write to file %s:", tmpname); -			free(tmpname); -			return(NULL); -		} - -		hostname = feh_strip_hostname(url); -		if (!hostname) { -			weprintf("couldn't work out hostname from %s:", url); -			fclose(fp); -			unlink(tmpname); -			free(tmpname); -			return(NULL); -		} - -		D(("trying hostname %s\n", hostname)); - -		memset(&hints, 0, sizeof(struct addrinfo)); -		hints.ai_family = AF_UNSPEC; -		hints.ai_socktype = SOCK_STREAM; -		hints.ai_flags = AI_NUMERICSERV; -		hints.ai_protocol = 0; -		if (getaddrinfo(hostname, "80", &hints, &result) != 0) { -			weprintf("error resolving host %s:", hostname); -			fclose(fp); -			unlink(tmpname); -			free(hostname); -			free(tmpname); -			return(NULL); -		} -		for (rp = result; rp != NULL; rp = rp->ai_next) { -			sockno = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); -			if (sockno == -1) { -				continue; -			} -			if (connect(sockno, rp->ai_addr, rp->ai_addrlen) != -1) { -				break; -			} -			close(sockno); -		} -		if (rp == NULL) { -			weprintf("error connecting socket:"); -			freeaddrinfo(result); -			fclose(fp); -			unlink(tmpname); -			free(tmpname); -			free(hostname); -			return(NULL); -		} -		freeaddrinfo(result); - -		get_url = strchr(url, '/') + 2; -		get_url = strchr(get_url, '/'); - -		get_string = estrjoin(" ", "GET", get_url, "HTTP/1.0", NULL); -		host_string = estrjoin(" ", "Host:", hostname, NULL); -		query_string = estrjoin(EOL, get_string, host_string, accept_string, ua_string, "", "", NULL); -		/* At this point query_string looks something like -		 ** -		 **    GET /dir/foo.jpg?123456 HTTP/1.0^M^J -		 **    Host: www.example.com^M^J -		 **    Accept: image/ *^M^J -		 **    User-Agent: feh image viewer^M^J -		 **    ^M^J -		 ** -		 ** Host: is required by HTTP/1.1 and very important for some sites, -		 ** even with HTTP/1.0 -		 ** -		 ** -- BEG -		 */ -		if ((send(sockno, query_string, strlen(query_string), 0)) == -1) { -			free(get_string); -			free(host_string); -			free(query_string); -			free(tmpname); -			free(hostname); -			weprintf("error sending over socket:"); -			return(NULL); -		} -		free(get_string); -		free(host_string); -		free(query_string); -		free(hostname); - -		while ((size = read(sockno, &buf, OUR_BUF_SIZE))) { -			if (body == IN_BODY) { -				fwrite(buf, 1, size, fp); -			} else { -				int i; - -				for (i = 0; i < size; i++) { -					/* We are looking for ^M^J^M^J, but will accept -					 ** ^J^J from broken servers. Stray ^Ms will be -					 ** ignored. -					 ** -					 ** TODO: -					 ** Checking the headers for a -					 **    Content-Type: image/ * -					 ** header would help detect problems with results. -					 ** Maybe look at the response code too? But there is -					 ** no fundamental reason why a 4xx or 5xx response -					 ** could not return an image, it is just the 3xx -					 ** series we need to worry about. -					 ** -					 ** Also, grabbing the size from the Content-Length -					 ** header and killing the connection after that -					 ** many bytes where read would speed up closing the -					 ** socket. -					 ** -- BEG -					 */ - -					switch (body) { - -					case IN_BODY: -						fwrite(buf + i, 1, size - i, fp); -						i = size; -						break; - -					case SAW_ONE_CM: -						if (buf[i] == '\012') { -							body = SAW_ONE_CJ; -						} else { -							body = SAW_NONE; -						} -						break; - -					case SAW_ONE_CJ: -						if (buf[i] == '\015') { -							body = SAW_TWO_CM; -						} else { -							if (buf[i] == '\012') { -								body = IN_BODY; -							} else { -								body = SAW_NONE; -							} -						} -						break; - -					case SAW_TWO_CM: -						if (buf[i] == '\012') { -							body = IN_BODY; -						} else { -							body = SAW_NONE; -						} -						break; - -					case SAW_NONE: -						if (buf[i] == '\015') { -							body = SAW_ONE_CM; -						} else { -							if (buf[i] == '\012') { -								body = SAW_ONE_CJ; -							} -						} -						break; - -					}	/* switch */ -				}	/* for i */ +	curl = curl_easy_init(); +	if (!curl) { +		weprintf("open url: libcurl initialization failure"); +		return NULL; +	} +	 +	sfn = estrjoin("_", tmpname, "XXXXXX", NULL); +	free(tmpname); +	fd = mkstemp(sfn); +	if (fd != -1) { +		sfp = fdopen(fd, "w+"); +		if (sfp != NULL) { +			curl_easy_setopt(curl, CURLOPT_URL, url); +			curl_easy_setopt(curl, CURLOPT_WRITEDATA, sfp); +			ebuff = emalloc(CURL_ERROR_SIZE); +			curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, ebuff); +			curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L); + +			res = curl_easy_perform(curl); +			curl_easy_cleanup(curl); +			if (res != CURLE_OK) { +				weprintf("open url: %s", ebuff); +				unlink(sfn); +				close(fd); +				free(sfn); +				sfn = NULL;  			} -		}		/* while read */ -		close(sockno); -		fclose(fp); -	} else { -		int pid; -		int status; - -		if ((pid = fork()) < 0) { -			weprintf("open url: fork failed:"); -			free(tmpname); -			return(NULL); -		} else if (pid == 0) { -			char *quiet = NULL; -			if (!opt.verbose) -				quiet = estrdup("-q"); - -			execlp("wget", "wget", "--cache=off", "-O", tmpname, url, quiet, NULL); -			eprintf("url: Is 'wget' installed? Failed to exec wget:"); +			free(ebuff); +			fclose(sfp); +			return sfn;  		} else { -			waitpid(pid, &status, 0); - -			if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { -				weprintf("url: wget failed to load URL %s\n", url); -				unlink(tmpname); -				free(tmpname); -				return(NULL); -			} +			weprintf("open url: fdopen failed:"); +			free(sfn); +			unlink(sfn); +			close(fd);  		} +	} else { +		weprintf("open url: mkstemp failed:"); +		free(sfn);  	} - -	return(tmpname); +	curl_easy_cleanup(curl); +	return NULL;  } -char *feh_strip_hostname(char *url) -{ -	char *ret; -	char *start; -	char *finish; -	int len; - -	start = strchr(url, '/'); -	if (!start) -		return(NULL); - -	start += 2; - -	finish = strchr(start, '/'); -	if (!finish) -		return(NULL); +#else				/* HAVE_LIBCURL */ -	len = finish - start; - -	ret = emalloc(len + 1); -	strncpy(ret, start, len); -	ret[len] = '\0'; -	return(ret); +char *feh_http_load_image(char *url) +{ +	weprintf( +		"Cannot load image %s\n Please recompile with libcurl support", +		url +	); +	return NULL;  } +#endif				/* HAVE_LIBCURL */ +  void feh_draw_zoom(winwidget w)  {  	static Imlib_Font fn = NULL; @@ -683,7 +505,7 @@ void feh_draw_info(winwidget w)  	return;  } -char *build_caption_filename(feh_file * file) +char *build_caption_filename(feh_file * file, short create_dir)  {  	char *caption_filename;  	char *s, *dir, *caption_dir; @@ -702,6 +524,8 @@ char *build_caption_filename(feh_file * file)  	D(("dir %s, cp %s, cdir %s\n", dir, opt.caption_path, caption_dir))  	if (stat(caption_dir, &cdir_stat) == -1) { +		if (!create_dir) +			return NULL;  		if (mkdir(caption_dir, 0755) == -1)  			eprintf("Failed to create caption directory %s:", caption_dir);  	} else if (!S_ISDIR(cdir_stat.st_mode)) @@ -737,9 +561,12 @@ void feh_draw_caption(winwidget w)  	if (!file->caption) {  		char *caption_filename; -		caption_filename = build_caption_filename(file); -		/* read caption from file */ -		file->caption = ereadfile(caption_filename); +		caption_filename = build_caption_filename(file, 0); +		if (caption_filename) +			/* read caption from file */ +			file->caption = ereadfile(caption_filename); +		else +			file->caption = estrdup("");  		free(caption_filename);  	} diff --git a/src/index.c b/src/index.c index 15dcea1..2829bad 100644 --- a/src/index.c +++ b/src/index.c @@ -1,6 +1,7 @@  /* index.c  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to diff --git a/src/keyevents.c b/src/keyevents.c index 7940973..e43ae33 100644 --- a/src/keyevents.c +++ b/src/keyevents.c @@ -1,6 +1,7 @@  /* keyevents.c  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to @@ -29,6 +30,276 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  #include "winwidget.h"  #include "options.h" +fehkb keys; + +static void feh_set_kb(fehkey *key, int s0, int y0, int s1, int y1, int s2, int y2) { +	key->keystates[0] = s0; +	key->keystates[1] = s1; +	key->keystates[2] = s2; +	key->keysyms[0] = y0; +	key->keysyms[1] = y1; +	key->keysyms[2] = y2; +} + +static void feh_set_parse_kb_partial(fehkey *key, int index, char *ks) { +	char *cur = ks; +	int mod = 0; + +	if (!*ks) { +		key->keysyms[index] = 0; +		return; +	} + +	if (ks[1] == '-') { +		switch (ks[0]) { +			case 'C': +				mod = ControlMask; +				break; +			case '1': +				mod = Mod1Mask; +				break; +			case '4': +				mod = Mod4Mask; +				break; +			default: +				weprintf("keys: invalid modifier %c in %s", ks[0], ks); +				break; +		} +		cur = ks + 2; +	} + +	key->keysyms[index] = XStringToKeysym(cur); +	key->keystates[index] = mod; + +	if (key->keysyms[index] == NoSymbol) +		weprintf("keys: Invalid keysym: %s", cur); +} + +void init_keyevents(void) { +	char *home = NULL; +	char *confhome = NULL; +	char *confpath = NULL; +	char line[128]; +	char action[32], k1[32], k2[32], k3[32]; +	struct __fehkey *cur_kb = NULL; +	FILE *conf = NULL; +	int read = 0; + +	memset(&keys, 0, sizeof(keys)); + +	feh_set_kb(&keys.menu_close, 0, XK_Escape    , 0, 0            , 0, 0); +	feh_set_kb(&keys.menu_parent,0, XK_Left      , 0, 0            , 0, 0); +	feh_set_kb(&keys.menu_down , 0, XK_Down      , 0, 0            , 0, 0); +	feh_set_kb(&keys.menu_up   , 0, XK_Up        , 0, 0            , 0, 0); +	feh_set_kb(&keys.menu_child, 0, XK_Right     , 0, 0            , 0, 0); +	feh_set_kb(&keys.menu_select,0, XK_Return    , 0, XK_space     , 0, 0); +	feh_set_kb(&keys.scroll_left,0, XK_KP_Left   , 4, XK_Left      , 0, 0); +	feh_set_kb(&keys.scroll_right,0,XK_KP_Right  , 4, XK_Right     , 0, 0); +	feh_set_kb(&keys.scroll_down,0, XK_KP_Down   , 4, XK_Down      , 0, 0); +	feh_set_kb(&keys.scroll_up , 0, XK_KP_Up     , 4, XK_Up        , 0, 0); +	feh_set_kb(&keys.prev_img  , 0, XK_Left      , 0, XK_p         , 0, XK_BackSpace); +	feh_set_kb(&keys.next_img  , 0, XK_Right     , 0, XK_n         , 0, XK_space); +	feh_set_kb(&keys.jump_back , 0, XK_Page_Up   , 0, XK_KP_Page_Up, 0, 0); +	feh_set_kb(&keys.jump_fwd  , 0, XK_Page_Down , 0, XK_KP_Page_Down,0,0); +	feh_set_kb(&keys.jump_random,0, XK_z         , 0, 0            , 0, 0); +	feh_set_kb(&keys.quit      , 0, XK_Escape    , 0, XK_q         , 0, 0); +	feh_set_kb(&keys.close     , 0, XK_x         , 0, 0            , 0, 0); +	feh_set_kb(&keys.remove    , 0, XK_Delete    , 0, 0            , 0, 0); +	feh_set_kb(&keys.delete    , 4, XK_Delete    , 0, 0            , 0, 0); +	feh_set_kb(&keys.jump_first, 0, XK_Home      , 0, XK_KP_Home   , 0, 0); +	feh_set_kb(&keys.jump_last , 0, XK_End       , 0, XK_KP_End    , 0, 0); +	feh_set_kb(&keys.action_0  , 0, XK_Return    , 0, XK_0         , 0, XK_KP_0); +	feh_set_kb(&keys.action_1  , 0, XK_1         , 0, XK_KP_1      , 0, 0); +	feh_set_kb(&keys.action_2  , 0, XK_2         , 0, XK_KP_2      , 0, 0); +	feh_set_kb(&keys.action_3  , 0, XK_3         , 0, XK_KP_3      , 0, 0); +	feh_set_kb(&keys.action_4  , 0, XK_4         , 0, XK_KP_4      , 0, 0); +	feh_set_kb(&keys.action_5  , 0, XK_5         , 0, XK_KP_5      , 0, 0); +	feh_set_kb(&keys.action_6  , 0, XK_6         , 0, XK_KP_6      , 0, 0); +	feh_set_kb(&keys.action_7  , 0, XK_7         , 0, XK_KP_7      , 0, 0); +	feh_set_kb(&keys.action_8  , 0, XK_8         , 0, XK_KP_8      , 0, 0); +	feh_set_kb(&keys.action_9  , 0, XK_9         , 0, XK_KP_9      , 0, 0); +	feh_set_kb(&keys.zoom_in   , 0, XK_Up        , 0, XK_KP_Add    , 0, 0); +	feh_set_kb(&keys.zoom_out  , 0, XK_Down      , 0, XK_KP_Subtract,0, 0); +	feh_set_kb(&keys.zoom_default, 0, XK_KP_Multiply, 0, 0         , 0, 0); +	feh_set_kb(&keys.zoom_fit  , 0, XK_KP_Divide , 0, 0            , 0, 0); +	feh_set_kb(&keys.size_to_image, 0, XK_w      , 0, 0            , 0, 0); +	feh_set_kb(&keys.render    , 0, XK_KP_Begin  , 0, 0            , 0, 0); +	feh_set_kb(&keys.toggle_actions, 0, XK_a, 0, 0, 0, 0); +	feh_set_kb(&keys.toggle_aliasing, 0, XK_A, 0, 0, 0, 0); +	feh_set_kb(&keys.toggle_filenames, 0, XK_d, 0, 0, 0, 0); +	feh_set_kb(&keys.toggle_pointer, 0, XK_o, 0, 0, 0, 0); +	feh_set_kb(&keys.toggle_caption, 0, XK_c, 0, 0, 0, 0); +	feh_set_kb(&keys.toggle_pause, 0, XK_h, 0, 0, 0, 0); +	feh_set_kb(&keys.toggle_menu, 0, XK_m, 0, 0, 0, 0); +	feh_set_kb(&keys.toggle_fullscreen, 0, XK_v, 0, 0, 0, 0); +	feh_set_kb(&keys.reload_image, 0, XK_r, 0, 0, 0, 0); +	feh_set_kb(&keys.save_image, 0, XK_s, 0, 0, 0, 0); +	feh_set_kb(&keys.save_filelist, 0, XK_f, 0, 0, 0, 0); +	feh_set_kb(&keys.orient_1, 0, XK_greater, 0, 0, 0, 0); +	feh_set_kb(&keys.orient_3, 0, XK_less, 0, 0, 0, 0); +	feh_set_kb(&keys.reload_minus, 0, XK_minus, 0, 0, 0, 0); +	feh_set_kb(&keys.reload_plus, 0, XK_plus, 0, 0, 0, 0); + +	home = getenv("HOME"); +	if (!home) +		eprintf("No HOME in environment\n"); + +	confhome = getenv("XDG_CONFIG_HOME"); + +	if (confhome) +		confpath = estrjoin("/", confhome, "feh/keys", NULL); +	else +		confpath = estrjoin("/", home, ".config/feh/keys", NULL); + +	conf = fopen(confpath, "r"); + +	free(confpath); + +	if (!conf && ((conf = fopen("/etc/feh/keys", "r")) == NULL)) +		return; + +	while (fgets(line, sizeof(line), conf)) { +		*action = '\0'; +		*k1 = '\0'; +		*k2 = '\0'; +		*k3 = '\0'; + +		read = sscanf(line, "%31s %31s %31s %31s\n", +			(char *) &action, (char *) &k1, (char* ) &k2, (char *) &k3); + +		if ((read == EOF) || (read == 0) || (line[0] == '#')) +			continue; + +		if (!strcmp(action, "menu_close")) +			cur_kb = &keys.menu_close; +		else if (!strcmp(action, "menu_parent")) +			cur_kb = &keys.menu_parent; +		else if (!strcmp(action, "menu_down")) +			cur_kb = &keys.menu_down; +		else if (!strcmp(action, "menu_up")) +			cur_kb = &keys.menu_up; +		else if (!strcmp(action, "menu_child")) +			cur_kb = &keys.menu_child; +		else if (!strcmp(action, "menu_select")) +			cur_kb = &keys.menu_select; +		else if (!strcmp(action, "scroll_right")) +			cur_kb = &keys.scroll_right; +		else if (!strcmp(action, "scroll_left")) +			cur_kb = &keys.scroll_left; +		else if (!strcmp(action, "scroll_up")) +			cur_kb = &keys.scroll_up; +		else if (!strcmp(action, "scroll_down")) +			cur_kb = &keys.scroll_down; +		else if (!strcmp(action, "prev_img")) +			cur_kb = &keys.prev_img; +		else if (!strcmp(action, "next_img")) +			cur_kb = &keys.next_img; +		else if (!strcmp(action, "jump_back")) +			cur_kb = &keys.jump_back; +		else if (!strcmp(action, "jump_fwd")) +			cur_kb = &keys.jump_fwd; +		else if (!strcmp(action, "jump_random")) +			cur_kb = &keys.jump_random; +		else if (!strcmp(action, "quit")) +			cur_kb = &keys.quit; +		else if (!strcmp(action, "close")) +			cur_kb = &keys.close; +		else if (!strcmp(action, "remove")) +			cur_kb = &keys.remove; +		else if (!strcmp(action, "delete")) +			cur_kb = &keys.delete; +		else if (!strcmp(action, "jump_first")) +			cur_kb = &keys.jump_first; +		else if (!strcmp(action, "jump_last")) +			cur_kb = &keys.jump_last; +		else if (!strcmp(action, "action_0")) +			cur_kb = &keys.action_0; +		else if (!strcmp(action, "action_1")) +			cur_kb = &keys.action_1; +		else if (!strcmp(action, "action_2")) +			cur_kb = &keys.action_2; +		else if (!strcmp(action, "action_3")) +			cur_kb = &keys.action_3; +		else if (!strcmp(action, "action_4")) +			cur_kb = &keys.action_4; +		else if (!strcmp(action, "action_5")) +			cur_kb = &keys.action_5; +		else if (!strcmp(action, "action_6")) +			cur_kb = &keys.action_6; +		else if (!strcmp(action, "action_7")) +			cur_kb = &keys.action_7; +		else if (!strcmp(action, "action_8")) +			cur_kb = &keys.action_8; +		else if (!strcmp(action, "action_9")) +			cur_kb = &keys.action_9; +		else if (!strcmp(action, "zoom_in")) +			cur_kb = &keys.zoom_in; +		else if (!strcmp(action, "zoom_out")) +			cur_kb = &keys.zoom_out; +		else if (!strcmp(action, "zoom_default")) +			cur_kb = &keys.zoom_default; +		else if (!strcmp(action, "zoom_fit")) +			cur_kb = &keys.zoom_fit; +		else if (!strcmp(action, "size_to_image")) +			cur_kb = &keys.size_to_image; +		else if (!strcmp(action, "render")) +			cur_kb = &keys.render; +		else if (!strcmp(action, "toggle_actions")) +			cur_kb = &keys.toggle_actions; +		else if (!strcmp(action, "toggle_aliasing")) +			cur_kb = &keys.toggle_aliasing; +		else if (!strcmp(action, "toggle_filenames")) +			cur_kb = &keys.toggle_filenames; +		else if (!strcmp(action, "toggle_pointer")) +			cur_kb = &keys.toggle_pointer; +		else if (!strcmp(action, "toggle_caption")) +			cur_kb = &keys.toggle_caption; +		else if (!strcmp(action, "toggle_pause")) +			cur_kb = &keys.toggle_pause; +		else if (!strcmp(action, "toggle_menu")) +			cur_kb = &keys.toggle_menu; +		else if (!strcmp(action, "toggle_fullscreen")) +			cur_kb = &keys.toggle_fullscreen; +		else if (!strcmp(action, "reload_image")) +			cur_kb = &keys.reload_image; +		else if (!strcmp(action, "save_image")) +			cur_kb = &keys.save_image; +		else if (!strcmp(action, "save_filelist")) +			cur_kb = &keys.save_filelist; +		else if (!strcmp(action, "orient_1")) +			cur_kb = &keys.orient_1; +		else if (!strcmp(action, "orient_3")) +			cur_kb = &keys.orient_3; +		else if (!strcmp(action, "reload_minus")) +			cur_kb = &keys.reload_minus; +		else if (!strcmp(action, "reload_plus")) +			cur_kb = &keys.reload_plus; +		else +			weprintf("keys: Invalid action: %s", action); + +		if (cur_kb) { +			feh_set_parse_kb_partial(cur_kb, 0, k1); +			feh_set_parse_kb_partial(cur_kb, 1, k2); +			feh_set_parse_kb_partial(cur_kb, 2, k3); +		} +	} +	fclose(conf); +} + +static short feh_is_kp(fehkey *key, int sym, int state) { +	int i; + +	for (i = 0; i < 3; i++) { +		if ( +				(key->keysyms[i] == sym) && +				(key->keystates[i] == state)) +			return 1; +		else if (key->keysyms[i] == 0) +			return 0; +	} +	return 0; +} +  void feh_event_invoke_action(winwidget winwid, unsigned char action)  {  	if (opt.actions[action]) { @@ -54,6 +325,7 @@ void feh_event_invoke_action(winwidget winwid, unsigned char action)  void feh_event_handle_keypress(XEvent * ev)  {  	int len; +	int state;  	char kbuf[20];  	KeySym keysym;  	XKeyEvent *kev; @@ -71,34 +343,23 @@ void feh_event_handle_keypress(XEvent * ev)  	kev = (XKeyEvent *) ev;  	len = XLookupString(&ev->xkey, (char *) kbuf, sizeof(kbuf), &keysym, NULL); +	state = kev->state & (ControlMask | Mod1Mask | Mod4Mask);  	/* menus are showing, so this is a menu control keypress */  	if (ev->xbutton.window == menu_cover) {  		selected_item = feh_menu_find_selected_r(menu_root, &selected_menu); -		switch (keysym) { -		case XK_Escape: +		if (feh_is_kp(&keys.menu_close, keysym, state))  			feh_menu_hide(menu_root, True); -			break; -		case XK_Left: +		else if (feh_is_kp(&keys.menu_parent, keysym, state))  			feh_menu_select_parent(selected_menu); -			break; -		case XK_Down: +		else if (feh_is_kp(&keys.menu_down, keysym, state))  			feh_menu_select_next(selected_menu, selected_item); -			break; -		case XK_Up: +		else if (feh_is_kp(&keys.menu_up, keysym, state))  			feh_menu_select_prev(selected_menu, selected_item); -			break; -		case XK_Right: +		else if (feh_is_kp(&keys.menu_child, keysym, state))  			feh_menu_select_submenu(selected_menu); -			break; -		case XK_Return: -		case XK_space: +		else if (feh_is_kp(&keys.menu_select, keysym, state))  			feh_menu_item_activate(selected_menu, selected_item); -			break; -		default: -			break; -		} -  		return;  	} @@ -108,7 +369,7 @@ void feh_event_handle_keypress(XEvent * ev)  	if (winwid->caption_entry) {  		switch (keysym) {  		case XK_Return: -			if (kev->state & ControlMask) { +			if (state & ControlMask) {  				/* insert actual newline */  				ESTRAPPEND(FEH_FILE(winwid->file->data)->caption, "\n");  				winwidget_render_image_cached(winwid); @@ -116,14 +377,15 @@ void feh_event_handle_keypress(XEvent * ev)  				/* finish caption entry, write to captions file */  				FILE *fp;  				char *caption_filename; -				caption_filename = build_caption_filename(FEH_FILE(winwid->file->data)); +				caption_filename = +					build_caption_filename(FEH_FILE(winwid->file->data), 1);  				winwid->caption_entry = 0;  				winwidget_render_image_cached(winwid);  				XFreePixmap(disp, winwid->bg_pmap_cache);  				winwid->bg_pmap_cache = 0;  				fp = fopen(caption_filename, "w");  				if (!fp) { -					weprintf("couldn't write to captions file %s:", caption_filename); +					eprintf("couldn't write to captions file %s:", caption_filename);  					return;  				}  				fprintf(fp, "%s", FEH_FILE(winwid->file->data)->caption); @@ -156,244 +418,179 @@ void feh_event_handle_keypress(XEvent * ev)  		return;  	} -	switch (keysym) { -	case XK_Left: -		if (kev->state & ControlMask) { -			winwid->im_x += 10; -			winwidget_render_image(winwid, 0, 0); -		} -		else if (opt.slideshow) -			slideshow_change_image(winwid, SLIDE_PREV); -		break; -	case XK_Right: -		if (kev->state & ControlMask) { -			winwid->im_x -= 10; -			winwidget_render_image(winwid, 0, 0); -		} -		else if (opt.slideshow) +	if (feh_is_kp(&keys.next_img, keysym, state)) { +		if (opt.slideshow)  			slideshow_change_image(winwid, SLIDE_NEXT); -		break; -	case XK_Page_Up: -	case XK_KP_Page_Up: +	} +	else if (feh_is_kp(&keys.prev_img, keysym, state)) { +		if (opt.slideshow) +			slideshow_change_image(winwid, SLIDE_PREV); +	} +	else if (feh_is_kp(&keys.scroll_right, keysym, state)) { +		winwid->im_x -= 20; +		winwidget_render_image(winwid, 0, 1); +	} +	else if (feh_is_kp(&keys.scroll_left, keysym, state)) { +		winwid->im_x += 20; +		winwidget_render_image(winwid, 0, 1); +	} +	else if (feh_is_kp(&keys.scroll_down, keysym, state)) { +		winwid->im_y -= 20; +		winwidget_render_image(winwid, 0, 1); +	} +	else if (feh_is_kp(&keys.scroll_up, keysym, state)) { +		winwid->im_y += 20; +		winwidget_render_image(winwid, 0, 1); +	} +	else if (feh_is_kp(&keys.jump_back, keysym, state)) {  		if (opt.slideshow)  			slideshow_change_image(winwid, SLIDE_JUMP_BACK); -		break; -	case XK_Escape: -		winwidget_destroy_all(); -		break; -	case XK_Page_Down: -	case XK_KP_Page_Down: +	} +	else if (feh_is_kp(&keys.jump_fwd, keysym, state)) {  		if (opt.slideshow)  			slideshow_change_image(winwid, SLIDE_JUMP_FWD); -		break; -	case XK_Delete: -		/* Holding ctrl gets you a filesystem deletion and removal from the *  -		   filelist. Just DEL gets you filelist removal only. */ -		if (kev->state & ControlMask) { -			if (winwid->type == WIN_TYPE_THUMBNAIL_VIEWER) -				feh_thumbnail_mark_removed(FEH_FILE(winwid->file->data), 1); -			feh_filelist_image_remove(winwid, 1); -		} else { -			if (winwid->type == WIN_TYPE_THUMBNAIL_VIEWER) -				feh_thumbnail_mark_removed(FEH_FILE(winwid->file->data), 0); -			feh_filelist_image_remove(winwid, 0); -		} -		break; -	case XK_Home: -	case XK_KP_Home: +	} +	else if (feh_is_kp(&keys.quit, keysym, state)) { +		winwidget_destroy_all(); +	} +	else if (feh_is_kp(&keys.delete, keysym, state)) { +		if (winwid->type == WIN_TYPE_THUMBNAIL_VIEWER) +			feh_thumbnail_mark_removed(FEH_FILE(winwid->file->data), 1); +		feh_filelist_image_remove(winwid, 1); +	} +	else if (feh_is_kp(&keys.remove, keysym, state)) { +		if (winwid->type == WIN_TYPE_THUMBNAIL_VIEWER) +			feh_thumbnail_mark_removed(FEH_FILE(winwid->file->data), 0); +		feh_filelist_image_remove(winwid, 0); +	} +	else if (feh_is_kp(&keys.jump_first, keysym, state)) {  		if (opt.slideshow)  			slideshow_change_image(winwid, SLIDE_FIRST); -		break; -	case XK_End: -	case XK_KP_End: +	} +	else if (feh_is_kp(&keys.jump_last, keysym, state)) {  		if (opt.slideshow)  			slideshow_change_image(winwid, SLIDE_LAST); -		break; -	case XK_Return: -	case XK_KP_Enter: -	case XK_0: -	case XK_KP_0: +	} +	else if (feh_is_kp(&keys.action_0, keysym, state)) {  		feh_event_invoke_action(winwid, 0); -		break; -	case XK_1: -	case XK_KP_1: +	} +	else if (feh_is_kp(&keys.action_1, keysym, state)) {  		feh_event_invoke_action(winwid, 1); -		break; -	case XK_2: -	case XK_KP_2: +	} +	else if (feh_is_kp(&keys.action_2, keysym, state)) {  		feh_event_invoke_action(winwid, 2); -		break; -	case XK_3: -	case XK_KP_3: +	} +	else if (feh_is_kp(&keys.action_3, keysym, state)) {  		feh_event_invoke_action(winwid, 3); -		break; -	case XK_4: -	case XK_KP_4: +	} +	else if (feh_is_kp(&keys.action_4, keysym, state)) {  		feh_event_invoke_action(winwid, 4); -		break; -	case XK_5: -	case XK_KP_5: +	} +	else if (feh_is_kp(&keys.action_5, keysym, state)) {  		feh_event_invoke_action(winwid, 5); -		break; -	case XK_6: -	case XK_KP_6: +	} +	else if (feh_is_kp(&keys.action_6, keysym, state)) {  		feh_event_invoke_action(winwid, 6); -		break; -	case XK_7: -	case XK_KP_7: +	} +	else if (feh_is_kp(&keys.action_7, keysym, state)) {  		feh_event_invoke_action(winwid, 7); -		break; -	case XK_8: -	case XK_KP_8: +	} +	else if (feh_is_kp(&keys.action_8, keysym, state)) {  		feh_event_invoke_action(winwid, 8); -		break; -	case XK_9: -	case XK_KP_9: +	} +	else if (feh_is_kp(&keys.action_9, keysym, state)) {  		feh_event_invoke_action(winwid, 9); -		break; -	case XK_KP_Left: -		winwid->im_x += 10; -		winwidget_render_image(winwid, 0, 0); -		break; -	case XK_KP_Right: -		winwid->im_x -= 10; -		winwidget_render_image(winwid, 0, 0); -		break; -	case XK_KP_Up: -		winwid->im_y += 10; +	} +	else if (feh_is_kp(&keys.zoom_in, keysym, state)) { +		winwid->old_zoom = winwid->zoom; +		winwid->zoom = winwid->zoom * 1.25; +		winwid->im_x = (winwid->w / 2) - (((winwid->w / 2) - winwid->im_x) / +			winwid->old_zoom * winwid->zoom); +		winwid->im_y = (winwid->h / 2) - (((winwid->h / 2) - winwid->im_y) / +			winwid->old_zoom * winwid->zoom); +		winwidget_sanitise_offsets(winwid);  		winwidget_render_image(winwid, 0, 0); -		break; -	case XK_KP_Down: -		winwid->im_y -= 10; +	} +	else if (feh_is_kp(&keys.zoom_out, keysym, state)) { +		winwid->old_zoom = winwid->zoom; +		winwid->zoom = winwid->zoom * 0.80; +		winwid->im_x = (winwid->w / 2) - (((winwid->w / 2) - winwid->im_x) / +			winwid->old_zoom * winwid->zoom); +		winwid->im_y = (winwid->h / 2) - (((winwid->h / 2) - winwid->im_y) / +			winwid->old_zoom * winwid->zoom); +		winwidget_sanitise_offsets(winwid);  		winwidget_render_image(winwid, 0, 0); -		break; -	case XK_KP_Add: -	case XK_Up: -		if (kev->state & ControlMask) { -			winwid->im_y += 10; -			winwidget_render_image(winwid, 0, 0); -		} -		else { -			/* erroneously recognized as '+' in the *kbuf switch. Work around this. */ -			len = 0; -			winwid->old_zoom = winwid->zoom; -			winwid->zoom = winwid->zoom * 1.25; -			winwid->im_x = (winwid->w / 2) - (((winwid->w / 2) - winwid->im_x) / -				winwid->old_zoom * winwid->zoom); -			winwid->im_y = (winwid->h / 2) - (((winwid->h / 2) - winwid->im_y) / -				winwid->old_zoom * winwid->zoom); -			winwidget_sanitise_offsets(winwid); -			winwidget_render_image(winwid, 0, 1); -		} -		break; -	case XK_KP_Subtract: -	case XK_Down: -		if (kev->state & ControlMask) { -			winwid->im_y -= 10; -			winwidget_render_image(winwid, 0, 0); -		} -		else { -			len = 0; -			winwid->old_zoom = winwid->zoom; -			winwid->zoom = winwid->zoom * 0.75; -			winwid->im_x = (winwid->w / 2) - (((winwid->w / 2) - winwid->im_x) / -				winwid->old_zoom * winwid->zoom); -			winwid->im_y = (winwid->h / 2) - (((winwid->h / 2) - winwid->im_y) / -				winwid->old_zoom * winwid->zoom); -			winwidget_sanitise_offsets(winwid); -			winwidget_render_image(winwid, 0, 1); -		} -		break; -	case XK_KP_Multiply: -		len = 0; +	} +	else if (feh_is_kp(&keys.zoom_default, keysym, state)) {  		winwid->zoom = 1; +		winwid->old_zoom = 1.001; /* hack for --scale-down */  		winwidget_center_image(winwid);  		winwidget_render_image(winwid, 0, 0); -		break; -	case XK_KP_Divide: -		len = 0; +	} +	else if (feh_is_kp(&keys.zoom_fit, keysym, state)) {  		feh_calc_needed_zoom(&winwid->zoom, winwid->im_w, winwid->im_h, winwid->w, winwid->h);  		winwidget_center_image(winwid); -		winwidget_render_image(winwid, 0, 1); -		break; -	case XK_KP_Begin: -		winwidget_render_image(winwid, 0, 1); -		break; -	default: -		break; +		winwidget_render_image(winwid, 0, 0);  	} - -	if (len <= 0 || len > (int) sizeof(kbuf)) -		return; -	kbuf[len] = '\0'; - -	switch (*kbuf) { -	case 'a': +	else if (feh_is_kp(&keys.render, keysym, state)) { +		winwidget_render_image(winwid, 0, 0); +	} +	else if (feh_is_kp(&keys.toggle_actions, keysym, state)) {  		opt.draw_actions = !opt.draw_actions; -		winwidget_rerender_all(0, 1); -		break; -	case 'd': +		winwidget_rerender_all(0); +	} +	else if (feh_is_kp(&keys.toggle_aliasing, keysym, state)) { +		opt.force_aliasing = !opt.force_aliasing; +		winwidget_rerender_all(0); +	} +	else if (feh_is_kp(&keys.toggle_filenames, keysym, state)) {  		opt.draw_filename = !opt.draw_filename; -		winwidget_rerender_all(0, 1); -		break; -	case 'n': -	case ' ': -		if (opt.slideshow) -			slideshow_change_image(winwid, SLIDE_NEXT); -		break; -	case 'o': +		winwidget_rerender_all(0); +	} +	else if (feh_is_kp(&keys.toggle_pointer, keysym, state)) {  		winwidget_set_pointer(winwid, opt.hide_pointer);  		opt.hide_pointer = !opt.hide_pointer; -		break; -	case 'p': -	case '\b': -		if (opt.slideshow) -			slideshow_change_image(winwid, SLIDE_PREV); -		break; -	case 'z': -		if (opt.slideshow) -			slideshow_change_image(winwid, SLIDE_RAND); -		break; -	case 'q': -		winwidget_destroy_all(); -		break; -	case 'c': +	} +	else if (feh_is_kp(&keys.jump_random, keysym, state)) { +		slideshow_change_image(winwid, SLIDE_RAND); +	} +	else if (feh_is_kp(&keys.toggle_caption, keysym, state)) {  		if (opt.caption_path)  			winwid->caption_entry = 1; -		winwidget_render_image(winwid, 0, 1); -		break; -	case 'r': +		winwidget_render_image(winwid, 0, 0); +	} +	else if (feh_is_kp(&keys.reload_image, keysym, state)) {  		feh_reload_image(winwid, 0, 0); -		break; -	case 'h': +	} +	else if (feh_is_kp(&keys.toggle_pause, keysym, state)) {  		slideshow_pause_toggle(winwid); -		break; -	case 's': +	} +	else if (feh_is_kp(&keys.save_image, keysym, state)) {  		slideshow_save_image(winwid); -		break; -	case 'f': +	} +	else if (feh_is_kp(&keys.save_filelist, keysym, state)) {  		if ((winwid->type == WIN_TYPE_THUMBNAIL)  				|| (winwid->type == WIN_TYPE_THUMBNAIL_VIEWER))  			weprintf("Filelist saving is not supported in thumbnail mode");  		else  			feh_save_filelist(); -		break; -	case 'w': +	} +	else if (feh_is_kp(&keys.size_to_image, keysym, state)) {  		winwidget_size_to_image(winwid); -		break; -	case 'm': +	} +	else if (feh_is_kp(&keys.toggle_menu, keysym, state)) {  		winwidget_show_menu(winwid); -		break; -	case 'x': +	} +	else if (feh_is_kp(&keys.close, keysym, state)) {  		winwidget_destroy(winwid); -		break; -	case '>': +	} +	else if (feh_is_kp(&keys.orient_1, keysym, state)) {  		feh_edit_inplace_orient(winwid, 1); -		break; -	case '<': +	} +	else if (feh_is_kp(&keys.orient_3, keysym, state)) {  		feh_edit_inplace_orient(winwid, 3); -		break; -	case 'v': +	} +	else if (feh_is_kp(&keys.toggle_fullscreen, keysym, state)) {  #ifdef HAVE_LIBXINERAMA  		if (opt.xinerama && xinerama_screens) {  			int i, rect[4]; @@ -425,7 +622,7 @@ void feh_event_handle_keypress(XEvent * ev)  		winwid->full_screen = !winwid->full_screen;  		winwidget_destroy_xwin(winwid);  		winwidget_create_window(winwid, winwid->im_w, winwid->im_h); -		winwidget_render_image(winwid, 1, 1); +		winwidget_render_image(winwid, 1, 0);  		winwidget_show(winwid);  #ifdef HAVE_LIBXINERAMA  		/* if we have xinerama and we're using it, then full screen the window @@ -436,20 +633,18 @@ void feh_event_handle_keypress(XEvent * ev)  					xinerama_screens[curr_screen].x_org, xinerama_screens[curr_screen].y_org);  		}  #endif				/* HAVE_LIBXINERAMA */ -	case '+': +	} +	else if (feh_is_kp(&keys.reload_plus, keysym, state)){   		if (opt.reload < SLIDESHOW_RELOAD_MAX)  			opt.reload++;  		else if (opt.verbose)  			weprintf("Cannot set RELOAD higher than %d seconds.", opt.reload); -		break; -	case '-': +	} +	else if (feh_is_kp(&keys.reload_minus, keysym, state)) {  		if (opt.reload > 1)  			opt.reload--;  		else if (opt.verbose)  			weprintf("Cannot set RELOAD lower than 1 second."); -		break; -	default: -		break;  	}  	return;  } @@ -1,6 +1,7 @@  /* list.c  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to @@ -1,6 +1,7 @@  /* main.c  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to @@ -43,8 +44,10 @@ int main(int argc, char **argv)  	init_imlib_fonts(); -	if (opt.display) +	if (opt.display) {  		init_x_and_imlib(); +		init_keyevents(); +	}  	feh_event_init(); @@ -1,6 +1,7 @@  /* menu.c  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to @@ -1267,7 +1268,7 @@ void feh_menu_cb_opt_fullscreen(feh_menu * m, feh_menu_item * i)  	winwidget_destroy_xwin(m->fehwin);  	winwidget_create_window(m->fehwin, m->fehwin->im_w, m->fehwin->im_h); -	winwidget_render_image(m->fehwin, 1, 1); +	winwidget_render_image(m->fehwin, 1, 0);  	winwidget_show(m->fehwin);  #ifdef HAVE_LIBXINERAMA @@ -1342,7 +1343,7 @@ void feh_menu_cb(feh_menu * m, feh_menu_item * i, int action, void *data)  				winwidget_resize(m->fehwin, m->fehwin->im_w, m->fehwin->im_h);  			}  			winwidget_reset_image(m->fehwin); -			winwidget_render_image(m->fehwin, 1, 1); +			winwidget_render_image(m->fehwin, 1, 0);  			break;  		case CB_RELOAD:  			feh_reload_image(m->fehwin, 0, 0); @@ -1403,7 +1404,7 @@ void feh_menu_cb(feh_menu * m, feh_menu_item * i, int action, void *data)  				opt.draw_filename = TRUE;  			else  				opt.draw_filename = FALSE; -			winwidget_rerender_all(0, 1); +			winwidget_rerender_all(0);  			break;  		case CB_OPT_DRAW_ACTIONS:  			MENU_ITEM_TOGGLE(i); @@ -1411,7 +1412,7 @@ void feh_menu_cb(feh_menu * m, feh_menu_item * i, int action, void *data)  				opt.draw_actions = TRUE;  			else  				opt.draw_actions = FALSE; -			winwidget_rerender_all(0, 1); +			winwidget_rerender_all(0);  			break;  		case CB_OPT_KEEP_HTTP:  			MENU_ITEM_TOGGLE(i); @@ -1435,8 +1436,11 @@ void feh_menu_cb(feh_menu * m, feh_menu_item * i, int action, void *data)  			break;  		case CB_OPT_AUTO_ZOOM:  			MENU_ITEM_TOGGLE(i); -			opt.auto_zoom = MENU_ITEM_IS_ON(i) ? 1 : 0; -			winwidget_rerender_all(1, 1); +			if (MENU_ITEM_IS_ON(i)) +				opt.zoom_mode = ZOOM_MODE_FILL; +			else +				opt.zoom_mode = 0; +			winwidget_rerender_all(1);  			break;  	}  	return; @@ -1487,7 +1491,7 @@ static feh_menu *feh_menu_func_gen_options(feh_menu * m)  	mm = feh_menu_new();  	mm->name = estrdup("OPTIONS");  	mm->fehwin = m->fehwin; -	feh_menu_add_toggle_entry(mm, "Auto-Zoom", NULL, NULL, CB_OPT_AUTO_ZOOM, NULL, NULL, opt.auto_zoom); +	feh_menu_add_toggle_entry(mm, "Auto-Zoom", NULL, NULL, CB_OPT_AUTO_ZOOM, NULL, NULL, (opt.zoom_mode == ZOOM_MODE_FILL));  	feh_menu_add_toggle_entry(mm, "Freeze Window Size", NULL, NULL,  				CB_OPT_FREEZE_WINDOW, NULL, NULL, opt.geom_flags);  	feh_menu_add_toggle_entry(mm, "Fullscreen", NULL, NULL, @@ -1,6 +1,7 @@  /* menu.h  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to diff --git a/src/multiwindow.c b/src/multiwindow.c index c46e453..1bd8a8a 100644 --- a/src/multiwindow.c +++ b/src/multiwindow.c @@ -28,6 +28,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  #include "timers.h"  #include "filelist.h"  #include "options.h" +#include "signals.h"  void init_multiwindow_mode(void)  { @@ -63,5 +64,8 @@ void init_multiwindow_mode(void)  		}  		free(s);  	} + +	setup_signal_handlers(); +  	return;  } diff --git a/src/options.c b/src/options.c index 2206f3e..de72429 100644 --- a/src/options.c +++ b/src/options.c @@ -1,6 +1,7 @@  /* options.c  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to @@ -28,9 +29,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  #include "options.h"  static void check_options(void); -static void feh_create_default_config(char *rcfile); -static void feh_parse_option_array(int argc, char **argv); -static void feh_parse_environment_options(void); +static void feh_getopt_theme(int argc, char **argv); +static void feh_parse_option_array(int argc, char **argv, int finalrun);  static void feh_check_theme_options(int arg, char **argv);  static void feh_parse_options_from_string(char *opts);  static void feh_load_options_for_theme(char *theme); @@ -80,8 +80,6 @@ void init_parse_options(int argc, char **argv)  	opt.start_list_at = NULL;  	opt.jump_on_resort = 1; -	opt.builtin_http = 0; -  	opt.xinerama = 0;  	opt.screen_clip = 1;  #ifdef HAVE_LIBXINERAMA @@ -89,17 +87,15 @@ void init_parse_options(int argc, char **argv)  	opt.xinerama = 1;  #endif				/* HAVE_LIBXINERAMA */ -	D(("About to parse env options (if any)\n")); -	/* Check for and parse any options in FEH_OPTIONS */ -	feh_parse_environment_options(); - -	D(("About to parse commandline options\n")); -	/* Parse the cmdline args */ -	feh_parse_option_array(argc, argv); +	feh_getopt_theme(argc, argv);  	D(("About to check for theme configuration\n"));  	feh_check_theme_options(argc, argv); +	D(("About to parse commandline options\n")); +	/* Parse the cmdline args */ +	feh_parse_option_array(argc, argv, 1); +  	/* If we have a filelist to read, do it now */  	if (opt.filelistfile) {  		/* joining two reverse-sorted lists in this manner works nicely for us @@ -147,35 +143,38 @@ static void feh_check_theme_options(int arg, char **argv)  static void feh_load_options_for_theme(char *theme)  {  	FILE *fp = NULL; -	char *home; +	char *home = getenv("HOME");  	char *rcpath = NULL; +	char *oldrcpath = NULL; +	char *confbase = getenv("XDG_CONFIG_HOME");  	char s[1024], s1[1024], s2[1024];  	int cont = 0;  	int bspos; -	if (opt.rcfile) { -		if ((fp = fopen(opt.rcfile, "r")) == NULL) { -			weprintf("couldn't load the specified rcfile %s\n", opt.rcfile); -			return; -		} -	} else { -		home = getenv("HOME"); -		if (!home) -			eprintf("D'oh! Please define HOME in your environment! " -					"It would really help me out...\n"); -		rcpath = estrjoin("/", home, ".fehrc", NULL); -		D(("Trying %s for config\n", rcpath)); -		fp = fopen(rcpath, "r"); - -		if (!fp && ((fp = fopen("/etc/fehrc", "r")) == NULL)) { -			feh_create_default_config(rcpath); - -			if ((fp = fopen(rcpath, "r")) == NULL) -				return; -		} +	if (!home) +		eprintf("You have no HOME, cannot read themes"); -		free(rcpath); -	} +	oldrcpath = estrjoin("/", home, ".fehrc", NULL); + +	if (confbase) +		rcpath = estrjoin("/", confbase, "feh/themes", NULL); +	else +		rcpath = estrjoin("/", home, ".config/feh/themes", NULL); + +	fp = fopen(rcpath, "r"); + +	free(rcpath); + +	if (!fp && ((fp = fopen(oldrcpath, "r")) != NULL)) +		weprintf("The theme config file was moved from ~/.fehrc to " +			"~/.config/feh/themes. Run\n" +			"    mkdir -p ~/.config/feh; mv ~/.fehrc ~/.config/feh/themes\n" +			"to fix this."); + +	free(oldrcpath); + +	if (!fp && ((fp = fopen("/etc/feh/themes", "r")) == NULL)) +		return;  	/* Oooh. We have an options file :) */  	for (; fgets(s, sizeof(s), fp);) { @@ -221,22 +220,6 @@ static void feh_load_options_for_theme(char *theme)  	return;  } -static void feh_parse_environment_options(void) -{ -	char *opts; - -	if ((opts = getenv("FEH_OPTIONS")) == NULL) -		return; - -	weprintf -	    ("The FEH_OPTIONS configuration method is depreciated and will soon die.\n" -	     "Use the .fehrc configuration file instead."); - -	/* We definitely have some options to parse */ -	feh_parse_options_from_string(opts); -	return; -} -  /* FIXME This function is a crufty bitch ;) */  static void feh_parse_options_from_string(char *opts)  { @@ -275,7 +258,7 @@ static void feh_parse_options_from_string(char *opts)  		last = *t;  	} -	feh_parse_option_array(num, list); +	feh_parse_option_array(num, list, 0);  	for (i = 0; i < num; i++)  		if (list[i]) @@ -317,11 +300,31 @@ char *feh_string_normalize(char *str)  	return(estrdup(ret));  } -static void feh_parse_option_array(int argc, char **argv) +static void feh_getopt_theme(int argc, char **argv) +{ +	static char stropts[] = "-T:"; +	static struct option lopts[] = { +		{"theme", 1, 0, 'T'}, +		{0, 0, 0, 0} +	}; +	int optch = 0, cmdx = 0; + +	opterr = 0; + +	while ((optch = getopt_long(argc, argv, stropts, lopts, &cmdx)) != EOF) { +		if (optch == 'T') +			theme = estrdup(optarg); +	} + +	opterr = 1; +	optind = 0; +} + +static void feh_parse_option_array(int argc, char **argv, int finalrun)  {  	static char stropts[] = -		"a:A:b:B:cC:dD:e:E:f:Fg:GhH:iIj:J:kK:lL:mM:nNo:O:pPqQrR:sS:tT:uUvVwW:xXy:YzZ" -		"0:1:2:4:5:8:9:.@:^:~:):|:_:+:"; +		"a:A:b:B:cC:dD:e:E:f:Fg:GhH:iIj:J:kK:lL:mM:nNo:O:pPqrR:sS:tT:uUvVwW:xXy:YzZ" +		"0:1:2:4:5:8:9:.@:^:~:):|:+:";  	/* (*name, has_arg, *flag, val) See: struct option in getopts.h */  	static struct option lopts[] = { @@ -351,7 +354,6 @@ static void feh_parse_option_array(int argc, char **argv)  		{"preload"       , 0, 0, 'p'},  		{"reverse"       , 0, 0, 'n'},  		{"thumbnails"    , 0, 0, 't'}, -		{"builtin"       , 0, 0, 'Q'},  		{"scale-down"    , 0, 0, '.'},  		{"no-jump-on-resort", 0, 0, 220},  		{"hide-pointer"  , 0, 0, 'Y'}, @@ -396,7 +398,6 @@ static void feh_parse_option_array(int argc, char **argv)  		{"rotate-button" , 1, 0, '8'},  		{"blur-button"   , 1, 0, '9'},  		{"start-at"      , 1, 0, '|'}, -		{"rcfile"        , 1, 0, '_'},  		{"debug"         , 0, 0, '+'},  		{"output-dir"    , 1, 0, 'j'},  		{"bg-tile"       , 1, 0, 200}, @@ -422,11 +423,11 @@ static void feh_parse_option_array(int argc, char **argv)  		{"index-dim"     , 1, 0, 232},  		{"thumb-redraw"  , 1, 0, 'J'},  		{"info"          , 1, 0, 234}, +		{"force-aliasing", 0, 0, 235},  		{0, 0, 0, 0}  	};  	int optch = 0, cmdx = 0; -	int i = 0;  	/* Now to pass some optionarinos */  	while ((optch = getopt_long(argc, argv, stropts, lopts, &cmdx)) != EOF) { @@ -468,9 +469,6 @@ static void feh_parse_option_array(int argc, char **argv)  			opt.list = 1;  			opt.display = 0;  			break; -		case 'Q': -			opt.builtin_http = 1; -			break;  		case 'L':  			opt.customlist = estrdup(optarg);  			opt.display = 0; @@ -522,7 +520,7 @@ static void feh_parse_option_array(int argc, char **argv)  			opt.full_screen = 1;  			break;  		case 'Z': -			opt.auto_zoom = 1; +			opt.zoom_mode = ZOOM_MODE_MAX;  			break;  		case 'U':  			opt.loadables = 1; @@ -591,9 +589,6 @@ static void feh_parse_option_array(int argc, char **argv)  			opt.bg = 1;  			opt.bg_file = estrdup(optarg);  			break; -		case '_': -			opt.rcfile = estrdup(optarg); -			break;  		case 'A':  			opt.actions[0] = estrdup(optarg);  			break; @@ -612,6 +607,7 @@ static void feh_parse_option_array(int argc, char **argv)  		case ')':  			free(opt.menu_bg);  			opt.menu_bg = estrdup(optarg); +			weprintf("The --menu-bg option is deprecated and will be removed by 2012");  			break;  		case 'B':  			free(opt.image_bg); @@ -693,9 +689,15 @@ static void feh_parse_option_array(int argc, char **argv)  		case 204:  			free(opt.menu_style);  			opt.menu_style = estrdup(optarg); +			weprintf("The --menu-style option is deprecated and will be removed by 2012");  			break;  		case 205: -			opt.default_zoom = atoi(optarg); +			if (!strcmp("fill", optarg)) +				opt.zoom_mode = ZOOM_MODE_FILL; +			else if (!strcmp("max", optarg)) +				opt.zoom_mode = ZOOM_MODE_MAX; +			else +				opt.default_zoom = atoi(optarg);  			break;  		case 206:  			opt.screen_clip = 0; @@ -772,6 +774,9 @@ static void feh_parse_option_array(int argc, char **argv)  		case 234:  			opt.info_cmd = estrdup(optarg);  			break; +		case 235: +			opt.force_aliasing = 1; +			break;  		default:  			break;  		} @@ -785,13 +790,8 @@ static void feh_parse_option_array(int argc, char **argv)  			add_file_to_filelist_recursively(argv[optind++], FILELIST_FIRST);  		}  	} - -	for (i = 0; i < 10; i++) { -		if (opt.actions[i] && !opt.hold_actions[i] && (opt.actions[i][0] == ';')) { -			opt.hold_actions[i] = 1; -			opt.actions[i] = &opt.actions[i][1]; -		} -	} +	else if (finalrun && !opt.filelistfile && !opt.bgmode) +		add_file_to_filelist_recursively(".", FILELIST_FIRST);  	/* So that we can safely be called again */  	optind = 1; @@ -800,6 +800,14 @@ static void feh_parse_option_array(int argc, char **argv)  static void check_options(void)  { +	int i; +	for (i = 0; i < 10; i++) { +		if (opt.actions[i] && !opt.hold_actions[i] && (opt.actions[i][0] == ';')) { +			opt.hold_actions[i] = 1; +			opt.actions[i] = &opt.actions[i][1]; +		} +	} +  	if ((opt.index + opt.collage) > 1) {  		weprintf("you can't use collage mode and index mode together.\n"  				"   I'm going with index"); @@ -843,7 +851,23 @@ static void check_options(void)  static void show_version(void)  { -	printf(PACKAGE " version " VERSION "\n"); +	puts(PACKAGE " version " VERSION); +	puts("Compile-time switches: " + +#ifdef HAVE_LIBCURL +		"curl " +#endif + +#ifdef DEBUG +		"debug " +#endif + +#ifdef HAVE_LIBXINERAMA +		"xinerama " +#endif + +	); +  	exit(0);  } @@ -861,20 +885,3 @@ static void show_usage(void)  	, stdout);  	exit(0);  } - -static void feh_create_default_config(char *rcfile) -{ -	FILE *fp; - -	if ((fp = fopen(rcfile, "w")) == NULL) { -		weprintf("Unable to create default config file %s\n", rcfile); -		return; -	} - -	fputs( -#include "fehrc.inc" -	, fp); -	fclose(fp); - -	return; -} diff --git a/src/options.h b/src/options.h index e99c14c..431fdfc 100644 --- a/src/options.h +++ b/src/options.h @@ -1,6 +1,7 @@  /* options.h  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to @@ -26,6 +27,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  #ifndef OPTIONS_H  #define OPTIONS_H +#define ZOOM_MODE_FILL 1 +#define ZOOM_MODE_MAX  2 +  struct __fehoptions {  	unsigned char multiwindow;  	unsigned char montage; @@ -50,7 +54,6 @@ struct __fehoptions {  	unsigned char randomize;  	unsigned char jump_on_resort;  	unsigned char full_screen; -	unsigned char auto_zoom;  	unsigned char draw_filename;  	unsigned char list;  	unsigned char quiet; @@ -60,7 +63,6 @@ struct __fehoptions {  	unsigned char reverse;  	unsigned char no_menus;  	unsigned char scale_down; -	unsigned char builtin_http;  	unsigned char bgmode;  	unsigned char xinerama;  	unsigned char screen_clip; @@ -84,7 +86,6 @@ struct __fehoptions {  	char *customlist;  	char *menu_bg;  	char *image_bg; -	char *rcfile;  	char *menu_style;  	char *caption_path;  	char *start_list_at; @@ -106,6 +107,7 @@ struct __fehoptions {  	unsigned char no_blur_ctrl_mask;  	unsigned char no_pan_ctrl_mask; +	int force_aliasing;  	int thumb_w;  	int thumb_h;  	int limit_w; @@ -120,6 +122,7 @@ struct __fehoptions {  	unsigned int geom_w;  	unsigned int geom_h;  	int default_zoom; +	int zoom_mode;  	unsigned char adjust_reload;  	unsigned char mode; @@ -130,6 +133,66 @@ struct __fehoptions {  	Imlib_Font menu_fn;  }; +struct __fehkey { +	int keysyms[3]; +	int keystates[3]; +}; + +struct __fehkb { +	struct __fehkey menu_close; +	struct __fehkey menu_parent; +	struct __fehkey menu_down; +	struct __fehkey menu_up; +	struct __fehkey menu_child; +	struct __fehkey menu_select; +	struct __fehkey scroll_right; +	struct __fehkey prev_img; +	struct __fehkey scroll_left; +	struct __fehkey next_img; +	struct __fehkey scroll_up; +	struct __fehkey scroll_down; +	struct __fehkey jump_back; +	struct __fehkey quit; +	struct __fehkey jump_fwd; +	struct __fehkey remove; +	struct __fehkey delete; +	struct __fehkey jump_first; +	struct __fehkey jump_last; +	struct __fehkey action_0; +	struct __fehkey action_1; +	struct __fehkey action_2; +	struct __fehkey action_3; +	struct __fehkey action_4; +	struct __fehkey action_5; +	struct __fehkey action_6; +	struct __fehkey action_7; +	struct __fehkey action_8; +	struct __fehkey action_9; +	struct __fehkey zoom_in; +	struct __fehkey zoom_out; +	struct __fehkey zoom_default; +	struct __fehkey zoom_fit; +	struct __fehkey render; +	struct __fehkey toggle_actions; +	struct __fehkey toggle_filenames; +	struct __fehkey toggle_pointer; +	struct __fehkey toggle_aliasing; +	struct __fehkey jump_random; +	struct __fehkey toggle_caption; +	struct __fehkey toggle_pause; +	struct __fehkey reload_image; +	struct __fehkey save_image; +	struct __fehkey save_filelist; +	struct __fehkey size_to_image; +	struct __fehkey toggle_menu; +	struct __fehkey close; +	struct __fehkey orient_1; +	struct __fehkey orient_3; +	struct __fehkey toggle_fullscreen; +	struct __fehkey reload_minus; +	struct __fehkey reload_plus; +}; +  void init_parse_options(int argc, char **argv);  char *feh_string_normalize(char *str); diff --git a/src/signals.c b/src/signals.c index b3e118a..956c861 100644 --- a/src/signals.c +++ b/src/signals.c @@ -25,6 +25,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  #include "feh.h"  #include "winwidget.h" +#include "options.h"  void feh_handle_signal(int); @@ -60,12 +61,16 @@ void feh_handle_signal(int signo)  {  	winwidget winwid  		= winwidget_get_first_window_of_type(WIN_TYPE_SLIDESHOW); +	int i;  	if (winwid) {  		if (signo == SIGUSR1)  			slideshow_change_image(winwid, SLIDE_NEXT);  		else if (signo == SIGUSR2)  			slideshow_change_image(winwid, SLIDE_PREV); +	} else if (opt.multiwindow) { +		for (i = window_num - 1; i >= 0; i--) +			feh_reload_image(windows[i], 0, 0);  	}  	return; diff --git a/src/slideshow.c b/src/slideshow.c index de10300..79b931f 100644 --- a/src/slideshow.c +++ b/src/slideshow.c @@ -1,6 +1,7 @@  /* slideshow.c  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to @@ -100,12 +101,15 @@ void feh_reload_image(winwidget w, int resize, int force_new)  	char *title, *new_title;  	int len;  	Imlib_Image tmp; +	int old_w, old_h;  	if (!w->file) {  		weprintf("couldn't reload, this image has no file associated with it.");  		return;  	} +	D(("resize %d, force_new %d\n", resize, force_new)); +  	free(FEH_FILE(w->file->data)->caption);  	FEH_FILE(w->file->data)->caption = NULL; @@ -115,10 +119,11 @@ void feh_reload_image(winwidget w, int resize, int force_new)  	title = estrdup(w->name);  	winwidget_rename(w, new_title); +	old_w = gib_imlib_image_get_width(w->im); +	old_h = gib_imlib_image_get_height(w->im); +  	/* force imlib2 not to cache */ -	if (force_new) { -		winwidget_free_image(w); -	} +	winwidget_free_image(w);  	/* if the image has changed in dimensions - we gotta resize */  	if ((feh_load_image(&tmp, FEH_FILE(w->file->data))) == 0) { @@ -133,19 +138,13 @@ void feh_reload_image(winwidget w, int resize, int force_new)  		filelist = feh_file_remove_from_list(filelist, w->file);  		return;  	} -	if (force_new) { -		w->im = tmp; + +	if (!resize && ((old_w != gib_imlib_image_get_width(tmp)) || +			(old_h != gib_imlib_image_get_height(tmp))))  		resize = 1; -		winwidget_reset_image(w); -	} else { -		if ((gib_imlib_image_get_width(w->im) != gib_imlib_image_get_width(tmp)) -		    || (gib_imlib_image_get_height(w->im) != gib_imlib_image_get_height(tmp))) { -			resize = 1; -			winwidget_reset_image(w); -		} -		winwidget_free_image(w); -		w->im = tmp; -	} + +	w->im = tmp; +	winwidget_reset_image(w);  	w->mode = MODE_NORMAL;  	if ((w->im_w != gib_imlib_image_get_width(w->im)) @@ -162,7 +161,7 @@ void feh_reload_image(winwidget w, int resize, int force_new)  		w->im_w = gib_imlib_image_get_width(w->im);  		w->im_h = gib_imlib_image_get_height(w->im);  	} -	winwidget_render_image(w, resize, 1); +	winwidget_render_image(w, resize, 0);  	winwidget_rename(w, title);  	free(title); @@ -251,10 +250,6 @@ void slideshow_change_image(winwidget winwid, int change)  			filelist = feh_file_remove_from_list(filelist, last);  			last = NULL;  		} -		s = slideshow_create_name(FEH_FILE(current_file->data)); - -		winwidget_rename(winwid, s); -		free(s);  		if ((winwidget_loadimage(winwid, FEH_FILE(current_file->data)))  		    != 0) { @@ -267,7 +262,12 @@ void slideshow_change_image(winwidget winwid, int change)  			winwidget_reset_image(winwid);  			winwid->im_w = gib_imlib_image_get_width(winwid->im);  			winwid->im_h = gib_imlib_image_get_height(winwid->im); -			winwidget_render_image(winwid, 1, 1); +			winwidget_render_image(winwid, 1, 0); + +			s = slideshow_create_name(FEH_FILE(current_file->data)); +			winwidget_rename(winwid, s); +			free(s); +  			break;  		} else  			last = current_file; diff --git a/src/structs.h b/src/structs.h index a2d3527..3942bc0 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1,6 +1,7 @@  /* structs.h  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to @@ -33,5 +34,7 @@ typedef struct __feh_file_info feh_file_info;  typedef struct __winwidget _winwidget;  typedef _winwidget *winwidget;  typedef struct __fehoptions fehoptions; +typedef struct __fehkey fehkey; +typedef struct __fehkb fehkb;  #endif diff --git a/src/support.c b/src/support.c index afb941b..e257271 100644 --- a/src/support.c +++ b/src/support.c @@ -1,6 +1,7 @@  /* support.c  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to @@ -130,7 +131,7 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled,  		enl_ipc_sync();  	} else {  		Atom prop_root, prop_esetroot, type; -		int format; +		int format, i;  		unsigned long length, after;  		unsigned char *data_root, *data_esetroot;  		Pixmap pmap_d1, pmap_d2; @@ -138,6 +139,10 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled,  		char *fehbg = NULL;  		char *home;  		char filbuf[PATH_MAX]; +		char fehbg_xinerama[] = "--no-xinerama"; + +		if (opt.xinerama) +			fehbg_xinerama[0] = '\0';  		/* local display to set closedownmode on */  		Display *disp2; @@ -162,21 +167,20 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled,  		filbuf[out++] = 0;  		if (scaled) { -			w = scr->width; -			h = scr->height; - -/* disable xinerama check for setting background */ -#if 0 -/* #ifdef HAVE_LIBXINERAMA */ -			if (opt.xinerama && xinerama_screens) { -				w = xinerama_screens[xinerama_screen].width; -				h = xinerama_screens[xinerama_screen].height; -			} -#endif				/* HAVE_LIBXINERAMA */ - -			pmap_d1 = XCreatePixmap(disp, root, w, h, depth); -			gib_imlib_render_image_on_drawable_at_size(pmap_d1, im, 0, 0, w, h, 1, 0, 1); -			fehbg = estrjoin(" ", "feh --bg-scale", filbuf, NULL); +			pmap_d1 = XCreatePixmap(disp, root, scr->width, scr->height, depth); + +#ifdef HAVE_LIBXINERAMA +			if (opt.xinerama && xinerama_screens) +				for (i = 0; i < num_xinerama_screens; i++) +					gib_imlib_render_image_on_drawable_at_size(pmap_d1, im, +						xinerama_screens[i].x_org, xinerama_screens[i].y_org, +						xinerama_screens[i].width, xinerama_screens[i].height, +						1, 0, !opt.force_aliasing); +			else +#endif			/* HAVE_LIBXINERAMA */ +				gib_imlib_render_image_on_drawable_at_size(pmap_d1, im, 0, 0, +					scr->width, scr->height, 1, 0, !opt.force_aliasing); +			fehbg = estrjoin(" ", "feh", fehbg_xinerama, "--bg-scale", filbuf, NULL);  		} else if (centered) {  			XGCValues gcval;  			GC gc; @@ -185,25 +189,33 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled,  			D(("centering\n"));  			w = scr->width;  			h = scr->height; - -/* disable xinerama check for setting background */ -#if 0 -/* #ifdef HAVE_LIBXINERAMA */ -			if (opt.xinerama && xinerama_screens) { -				w = xinerama_screens[xinerama_screen].width; -				h = xinerama_screens[xinerama_screen].height; -			} -#endif				/* HAVE_LIBXINERAMA */ +			x = (w - gib_imlib_image_get_width(im)) >> 1; +			y = (h - gib_imlib_image_get_height(im)) >> 1;  			pmap_d1 = XCreatePixmap(disp, root, w, h, depth);  			gcval.foreground = BlackPixel(disp, DefaultScreen(disp));  			gc = XCreateGC(disp, root, GCForeground, &gcval);  			XFillRectangle(disp, pmap_d1, gc, 0, 0, w, h); -			x = (w - gib_imlib_image_get_width(im)) >> 1; -			y = (h - gib_imlib_image_get_height(im)) >> 1; -			gib_imlib_render_image_on_drawable(pmap_d1, im, x, y, 1, 0, 0); + +#ifdef HAVE_LIBXINERAMA +			if (opt.xinerama && xinerama_screens) +				for (i = 0; i < num_xinerama_screens; i++) { +					w = xinerama_screens[i].width; +					h = xinerama_screens[i].height; +					x = (w - gib_imlib_image_get_width(im)) >> 1; +					y = (h - gib_imlib_image_get_height(im)) >> 1; +					gib_imlib_render_image_part_on_drawable_at_size( +						pmap_d1, im, +						((x < 0) ? -x : 0) , ((y < 0) ? -y : 0), w, h, +						xinerama_screens[i].x_org + ((x > 0) ? x : 0), +						xinerama_screens[i].y_org + ((y > 0) ? y : 0), +						w, h, 1, 0, 0); +				} +			else +#endif				/* HAVE_LIBXINERAMA */ +				gib_imlib_render_image_on_drawable(pmap_d1, im, x, y, 1, 0, 0);  			XFreeGC(disp, gc); -			fehbg = estrjoin(" ", "feh --bg-center", filbuf, NULL); +			fehbg = estrjoin(" ", "feh", fehbg_xinerama, "--bg-center", filbuf, NULL);  		} else if (filled == 1) {  			int scr_w = scr->width;  			int scr_h = scr->height; @@ -211,20 +223,44 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled,  			int img_h = gib_imlib_image_get_height(im);  			int render_x = 0;  			int render_y = 0; +			int cut_x = (((img_w * scr_h) > (img_h * scr_w)) ? 1 : 0); +			w = (cut_x ? ((scr_h * img_w) / img_h) : scr_w); +			h = (cut_x ? scr_h : ((scr_w * img_h) / img_w)); + +			if (cut_x) +				render_x = (scr_w - w) >> 1; +			else +				render_y = (scr_h - h) >> 1; -			if ((img_w * scr_h) > (scr_w * img_h)) { -				h = scr_h; -				w = (scr_h * img_w) / img_h; -				render_x = (scr_w - w) / 2; -			} else { -				h = (scr_w * img_h) / img_w; -				w = scr_w; -				render_y = (scr_h - h) / 2; -			}  			pmap_d1 = XCreatePixmap(disp, root, w, h, depth); -			gib_imlib_render_image_on_drawable_at_size(pmap_d1, im, -					render_x, render_y, w, h, 1, 0, 1); -			fehbg = estrjoin(" ", "feh --bg-fill", filbuf, NULL); + +#ifdef HAVE_LIBXINERAMA +			if (opt.xinerama && xinerama_screens) +				for (i = 0; i < num_xinerama_screens; i++) { +					scr_w = xinerama_screens[i].width; +					scr_h = xinerama_screens[i].height; +					cut_x = (((img_w * scr_h) > (img_h * scr_w)) ? 1 : 0); +					w = (cut_x ? ((img_h * scr_w) / scr_h) : img_w); +					h = (cut_x ? img_h : ((img_w * scr_h) / scr_w)); +					render_x = (cut_x ? ((img_w - w) >> 1) : 0); +					render_y = (cut_x ? 0 : ((img_h - h) >> 1)); + +					D(("cut_x %d w %5d h %5d x %5d y %5d\n", +							cut_x, w, h, render_x, render_y)); + +					gib_imlib_render_image_part_on_drawable_at_size( +						pmap_d1, im, +						render_x, render_y, +						w, h, +						xinerama_screens[i].x_org, +						xinerama_screens[i].y_org, +						scr_w, scr_h, 1, 0, !opt.force_aliasing); +				} +			else +#endif				/* HAVE_LIBXINERAMA */ +				gib_imlib_render_image_on_drawable_at_size(pmap_d1, im, +						render_x, render_y, w, h, 1, 0, !opt.force_aliasing); +			fehbg = estrjoin(" ", "feh", fehbg_xinerama, "--bg-fill", filbuf, NULL);  		} else if (filled == 2) {  			int scr_w = scr->width;  			int scr_h = scr->height; @@ -232,38 +268,48 @@ void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled,  			int img_h = gib_imlib_image_get_height(im);  			int render_x = 0;  			int render_y = 0; +			int border_x = (((img_w * scr_h) > (img_h * scr_w)) ? 0 : 1); +			w = (border_x ? ((scr_h * img_w) / img_h) : scr_w); +			h = (border_x ? scr_h : ((scr_w * img_h) / img_w));  			XGCValues gcval; -			if (img_w > img_h) { -				w = scr_w; -				h = (((scr_w * 100) / img_w) * img_h) / 100; -				render_y = (scr_h - h) / 2; -				if (h > scr_h) { -					w = (((scr_h * 100) / h) * w) / 100; -					h = scr_h; -					render_x = (scr_w - w) / 2; -					render_y = 0; -				} -			} else { -				h = scr_h; -				w = (((scr_h * 100) / img_h) * img_w) / 100; -				render_x = (scr_w - w) / 2; -				if (w > scr_w) { -					h = (((scr_w * 100) / w) * h) / 100; -					w = scr_w; -					render_x = 0; -					render_y = (scr_h - h) / 2; -				} -			} +			if (border_x) +				render_x = (scr_w - w) >> 1; +			else +				render_y = (scr_h - h) >> 1;  			pmap_d1 = XCreatePixmap(disp, root, scr_w, scr_h, depth);  			gcval.foreground = BlackPixel(disp, DefaultScreen(disp));  			gc = XCreateGC(disp, root, GCForeground, &gcval);  			XFillRectangle(disp, pmap_d1, gc, 0, 0, scr_w, scr_h); + +#ifdef HAVE_LIBXINERAMA +			if (opt.xinerama && xinerama_screens) +				for (i = 0; i < num_xinerama_screens; i++) { +					scr_w = xinerama_screens[i].width; +					scr_h = xinerama_screens[i].height; +					border_x = (((img_w * scr_h) > (img_h * scr_w)) ? 0 : 1); +					w = (border_x ? ((scr_h * img_w) / img_h) : scr_w); +					h = (border_x ? scr_h : ((scr_w * img_h) / img_w)); +					render_x = (border_x ? ((scr_w - w) >> 1) : 0); +					render_y = (border_x ? 0 : ((scr_h - h) >> 1)); + +					D(("border_x %d w %5d h %5d x %5d y %5d\n", +							border_x, w, h, render_x, render_y)); + +					gib_imlib_render_image_on_drawable_at_size( +						pmap_d1, im, +						xinerama_screens[i].x_org + render_x, +						xinerama_screens[i].y_org + render_y, +						w, h, +						1, 0, !opt.force_aliasing); +				} +			else +#endif				/* HAVE_LIBXINERAMA */  			gib_imlib_render_image_on_drawable_at_size(pmap_d1, im, -					render_x, render_y, w, h, 1, 0, 1); +					render_x, render_y, w, h, 1, 0, !opt.force_aliasing);  			XFreeGC(disp, gc); -			fehbg = estrjoin(" ", "feh --bg-max", filbuf, NULL); +			fehbg = estrjoin(" ", "feh", fehbg_xinerama, "--bg-max", filbuf, NULL);  		} else {  			w = gib_imlib_image_get_width(im);  			h = gib_imlib_image_get_height(im); diff --git a/src/support.h b/src/support.h index bb17082..3cd0fe1 100644 --- a/src/support.h +++ b/src/support.h @@ -1,6 +1,7 @@  /* support.h  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to diff --git a/src/thumbnail.c b/src/thumbnail.c index ed4e0fb..ca5c387 100644 --- a/src/thumbnail.c +++ b/src/thumbnail.c @@ -1,6 +1,7 @@  /* thumbnail.c  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to @@ -57,6 +58,7 @@ void init_thumbnail_mode(void)  	Imlib_Image im_temp;  	int ww = 0, hh = 0, www, hhh, xxx, yyy; +	int orig_w, orig_h;  	int x = 0, y = 0;  	winwidget winwid = NULL;  	Imlib_Image im_thumb = NULL; @@ -204,7 +206,8 @@ void init_thumbnail_mode(void)  		}  		D(("About to load image %s\n", file->filename));  		/*      if (feh_load_image(&im_temp, file) != 0) */ -		if (feh_thumbnail_get_thumbnail(&im_temp, file) != 0) { +		if (feh_thumbnail_get_thumbnail(&im_temp, file, &orig_w, &orig_h) +				!= 0) {  			if (opt.verbose)  				feh_display_status('.');  			D(("Successfully loaded %s\n", file->filename)); @@ -212,6 +215,12 @@ void init_thumbnail_mode(void)  			hhh = opt.thumb_h;  			ww = gib_imlib_image_get_width(im_temp);  			hh = gib_imlib_image_get_height(im_temp); + +			if (!orig_w) { +				orig_w = ww; +				orig_h = hh; +			} +  			thumbnailcount++;  			if (gib_imlib_image_has_alpha(im_temp))  				imlib_context_set_blend(1); @@ -333,7 +342,7 @@ void init_thumbnail_mode(void)  						td.font_main, NULL,  						x + x_offset_dim,  						y + opt.thumb_h + (lines++ * (th + 2)) + 2, -						create_index_dimension_string(ww, hh), +						create_index_dimension_string(orig_w, orig_h),  						IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255);  			if (opt.index_show_size)  				gib_imlib_text_draw(td.im_main, @@ -355,7 +364,7 @@ void init_thumbnail_mode(void)  		if (opt.display) {  			/* thumb_counter is unsigned, so no need to catch overflows */  			if (++thumb_counter == opt.thumb_redraw) { -				winwidget_render_image(winwid, 0, 0); +				winwidget_render_image(winwid, 0, 1);  				thumb_counter = 0;  			}  			if (!feh_main_iteration(0)) @@ -364,7 +373,7 @@ void init_thumbnail_mode(void)  	}  	if (thumb_counter != 0) -		winwidget_render_image(winwid, 0, 0); +		winwidget_render_image(winwid, 0, 1);  	if (opt.verbose)  		fprintf(stdout, "\n"); @@ -717,21 +726,27 @@ void feh_thumbnail_calculate_geometry(void)  	}  } -int feh_thumbnail_get_thumbnail(Imlib_Image * image, feh_file * file) +int feh_thumbnail_get_thumbnail(Imlib_Image * image, feh_file * file, +	int * orig_w, int * orig_h)  {  	int status = 0;  	char *thumb_file = NULL, *uri = NULL; +	*orig_w = 0; +	*orig_h = 0; +  	if (!file || !file->filename)  		return (0);  	if (td.cache_thumbnails) {  		uri = feh_thumbnail_get_name_uri(file->filename);  		thumb_file = feh_thumbnail_get_name(uri); -		status = feh_thumbnail_get_generated(image, file, thumb_file); +		status = feh_thumbnail_get_generated(image, file, thumb_file, +			orig_w, orig_h);  		if (!status) -			status = feh_thumbnail_generate(image, file, thumb_file, uri); +			status = feh_thumbnail_generate(image, file, thumb_file, uri, +				orig_w, orig_h);  		D(("uri is %s, thumb_file is %s\n", uri, thumb_file));  		free(uri); @@ -808,15 +823,16 @@ char *feh_thumbnail_get_name_md5(char *uri)  }  int feh_thumbnail_generate(Imlib_Image * image, feh_file * file, -		char *thumb_file, char *uri) +		char *thumb_file, char *uri, int * orig_w, int * orig_h)  {  	int w, h, thumb_w, thumb_h;  	Imlib_Image im_temp;  	struct stat sb; +	char c_width[8], c_height[8];  	if (feh_load_image(&im_temp, file) != 0) { -		w = gib_imlib_image_get_width(im_temp); -		h = gib_imlib_image_get_height(im_temp); +		*orig_w = w = gib_imlib_image_get_width(im_temp); +		*orig_h = h = gib_imlib_image_get_height(im_temp);  		thumb_w = td.cache_dim;  		thumb_h = td.cache_dim; @@ -834,8 +850,12 @@ int feh_thumbnail_generate(Imlib_Image * image, feh_file * file,  		if (!stat(file->filename, &sb)) {  			char c_mtime[128];  			sprintf(c_mtime, "%d", (int)sb.st_mtime); +			snprintf(c_width, 8, "%d", w); +			snprintf(c_height, 8, "%d", h);  			feh_png_write_png(*image, thumb_file, "Thumb::URI", uri, -					"Thumb::MTime", c_mtime); +					"Thumb::MTime", c_mtime, +					"Thumb::Image::Width", c_width, +					"Thumb::Image::Height", c_height);  		}  		gib_imlib_free_image_and_decache(im_temp); @@ -846,19 +866,27 @@ int feh_thumbnail_generate(Imlib_Image * image, feh_file * file,  	return (0);  } -int feh_thumbnail_get_generated(Imlib_Image * image, feh_file * file, char *thumb_file) +int feh_thumbnail_get_generated(Imlib_Image * image, feh_file * file, +	char *thumb_file, int * orig_w, int * orig_h)  {  	struct stat sb;  	char *c_mtime; +	char *c_width, *c_height;  	time_t mtime = 0;  	gib_hash *hash;  	if (!stat(file->filename, &sb)) {  		hash = feh_png_read_comments(thumb_file);  		if (hash != NULL) { -			c_mtime = (char *) gib_hash_get(hash, "Thumb::MTime"); +			c_mtime  = (char *) gib_hash_get(hash, "Thumb::MTime"); +			c_width  = (char *) gib_hash_get(hash, "Thumb::Image::Width"); +			c_height = (char *) gib_hash_get(hash, "Thumb::Image::Height");  			if (c_mtime != NULL)  				mtime = (time_t) strtol(c_mtime, NULL, 10); +			if (c_width != NULL) +				*orig_w = atoi(c_width); +			if (c_height != NULL) +				*orig_h = atoi(c_height);  			gib_hash_free_and_data(hash);  		} diff --git a/src/thumbnail.h b/src/thumbnail.h index a384d11..6d2dc77 100644 --- a/src/thumbnail.h +++ b/src/thumbnail.h @@ -1,6 +1,7 @@  /* thumbnail.h  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to @@ -73,9 +74,9 @@ void feh_thumbnail_mark_removed(feh_file * file, int deleted);  void feh_thumbnail_calculate_geometry(void); -int feh_thumbnail_get_thumbnail(Imlib_Image * image, feh_file * file); -int feh_thumbnail_generate(Imlib_Image * image, feh_file * file, char *thumb_file, char *uri); -int feh_thumbnail_get_generated(Imlib_Image * image, feh_file * file, char *thumb_file); +int feh_thumbnail_get_thumbnail(Imlib_Image * image, feh_file * file, int * orig_w, int * orig_h); +int feh_thumbnail_generate(Imlib_Image * image, feh_file * file, char *thumb_file, char *uri, int * orig_w, int * orig_h); +int feh_thumbnail_get_generated(Imlib_Image * image, feh_file * file, char * thumb_file, int * orig_w, int * orig_h);  char *feh_thumbnail_get_name(char *uri);  char *feh_thumbnail_get_name_uri(char *name);  char *feh_thumbnail_get_name_md5(char *uri); diff --git a/src/timers.c b/src/timers.c index cba0716..4cb5251 100644 --- a/src/timers.c +++ b/src/timers.c @@ -1,6 +1,7 @@  /* timers.c  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to diff --git a/src/winwidget.c b/src/winwidget.c index 26a43e2..a39e8ef 100644 --- a/src/winwidget.c +++ b/src/winwidget.c @@ -1,6 +1,7 @@  /* winwidget.c  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to @@ -57,6 +58,7 @@ static winwidget winwidget_allocate(void)  	ret->type = WIN_TYPE_UNSET;  	ret->visible = 0;  	ret->caption_entry = 0; +	ret->force_aliasing = opt.force_aliasing;  	/* Zoom stuff */  	ret->mode = MODE_NORMAL; @@ -98,7 +100,7 @@ winwidget winwidget_create_from_image(Imlib_Image im, char *name, char type)  	if (opt.full_screen && (type != WIN_TYPE_THUMBNAIL))  		ret->full_screen = True;  	winwidget_create_window(ret, ret->w, ret->h); -	winwidget_render_image(ret, 1, 1); +	winwidget_render_image(ret, 1, 0);  	return(ret);  } @@ -131,7 +133,7 @@ winwidget winwidget_create_from_file(gib_list * list, char *name, char type)  		if (opt.full_screen)  			ret->full_screen = True;  		winwidget_create_window(ret, ret->w, ret->h); -		winwidget_render_image(ret, 1, 1); +		winwidget_render_image(ret, 1, 0);  	}  	return(ret); @@ -361,10 +363,11 @@ void winwidget_setup_pixmaps(winwidget winwid)  	return;  } -void winwidget_render_image(winwidget winwid, int resize, int alias) +void winwidget_render_image(winwidget winwid, int resize, int force_alias)  {  	int sx, sy, sw, sh, dx, dy, dw, dh;  	int calc_w, calc_h; +	int antialias = 0;  	if (!winwid->full_screen && resize) {  		winwidget_resize(winwid, winwid->im_w, winwid->im_h); @@ -377,13 +380,14 @@ void winwidget_render_image(winwidget winwid, int resize, int alias)  	if (winwid->im_y > winwid->h)  		winwid->im_y = winwid->h; -	D(("winwidget_render_image resize %d alias %d im %dx%d\n", -	      resize, alias, winwid->im_w, winwid->im_h)); +	D(("winwidget_render_image resize %d force_alias %d im %dx%d\n", +	      resize, force_alias, winwid->im_w, winwid->im_h));  	winwidget_setup_pixmaps(winwid);  	if (!winwid->full_screen && opt.scale_down && ((winwid->w < winwid->im_w) -						       || (winwid->h < winwid->im_h))) { +						       || (winwid->h < winwid->im_h)) && +							  (winwid->old_zoom == 1.0)) {  		D(("scaling down image %dx%d\n", winwid->w, winwid->h));  		feh_calc_needed_zoom(&(winwid->zoom), winwid->im_w, winwid->im_h, winwid->w, winwid->h); @@ -424,7 +428,7 @@ void winwidget_render_image(winwidget winwid, int resize, int alias)  		smaller = ((winwid->im_w < max_w)  			   && (winwid->im_h < max_h)); -		if (!smaller || opt.auto_zoom) { +		if (!smaller || opt.zoom_mode) {  			double ratio = 0.0;  			/* Image is larger than the screen (so wants shrinking), or it's @@ -522,17 +526,22 @@ void winwidget_render_image(winwidget winwid, int resize, int alias)  	D(("sx: %d sy: %d sw: %d sh: %d dx: %d dy: %d dw: %d dh: %d zoom: %f\n",  	   sx, sy, sw, sh, dx, dy, dw, dh, winwid->zoom)); +	if ((winwid->zoom != 1.0) && !force_alias && !winwid->force_aliasing) +		antialias = 1; +  	D(("winwidget_render(): winwid->im_angle = %f\n", winwid->im_angle));  	if (winwid->has_rotated)  		gib_imlib_render_image_part_on_drawable_at_size_with_rotation -		    (winwid->bg_pmap, winwid->im, sx, sy, sw, sh, dx, dy, dw, dh, winwid->im_angle, 1, 1, alias); +			(winwid->bg_pmap, winwid->im, sx, sy, sw, sh, dx, dy, dw, dh, +			winwid->im_angle, 1, 1, antialias);  	else  		gib_imlib_render_image_part_on_drawable_at_size(winwid->bg_pmap,  								winwid->im,  								sx, sy, sw,  								sh, dx, dy,  								dw, dh, 1, -								gib_imlib_image_has_alpha(winwid->im), alias); +								gib_imlib_image_has_alpha(winwid->im), +								antialias);  	if (opt.mode == MODE_NORMAL) {  		if (opt.caption_path) @@ -543,7 +552,7 @@ void winwidget_render_image(winwidget winwid, int resize, int alias)  			feh_draw_actions(winwid);  		if (opt.info_cmd)  			feh_draw_info(winwid); -	} else if ((opt.mode == MODE_ZOOM) && !alias) +	} else if ((opt.mode == MODE_ZOOM) && !antialias)  		feh_draw_zoom(winwid);  	XSetWindowBackgroundPixmap(disp, winwid->win, winwid->bg_pmap); @@ -578,6 +587,9 @@ double feh_calc_needed_zoom(double *zoom, int orig_w, int orig_h, int dest_w, in  	ratio = ((double) orig_w / orig_h) / ((double) dest_w / dest_h); +	if (opt.zoom_mode == ZOOM_MODE_FILL) +		ratio = 1.0 / ratio; +  	if (ratio > 1.0)  		*zoom = ((double) dest_w / orig_w);  	else @@ -686,13 +698,13 @@ void winwidget_destroy_all(void)  	return;  } -void winwidget_rerender_all(int resize, int alias) +void winwidget_rerender_all(int resize)  {  	int i;  	/* Have to DESCEND the list here, 'cos of the way _unregister works */  	for (i = window_num - 1; i >= 0; i--) -		winwidget_render_image(windows[i], resize, alias); +		winwidget_render_image(windows[i], resize, 0);  	return;  } @@ -908,6 +920,7 @@ void feh_debug_print_winwid(winwidget w)  void winwidget_reset_image(winwidget winwid)  {  	winwid->zoom = 1.0; +	winwid->old_zoom = 1.0;  	winwid->im_x = 0;  	winwid->im_y = 0;  	winwid->im_angle = 0.0; @@ -982,7 +995,7 @@ void winwidget_size_to_image(winwidget winwid)  {  	winwidget_resize(winwid, winwid->im_w * winwid->zoom, winwid->im_h * winwid->zoom);  	winwid->im_x = winwid->im_y = 0; -	winwidget_render_image(winwid, 0, 1); +	winwidget_render_image(winwid, 0, 0);  	return;  } diff --git a/src/winwidget.h b/src/winwidget.h index 012d78f..922ecf5 100644 --- a/src/winwidget.h +++ b/src/winwidget.h @@ -1,6 +1,7 @@  /* winwidget.h  Copyright (C) 1999-2003 Tom Gilbert. +Copyright (C) 2010-2011 Daniel Friesel.  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to @@ -81,6 +82,7 @@ struct __winwidget {  	int h;  	int im_w;  	int im_h; +	int force_aliasing;  	double im_angle;  	enum win_type type;  	unsigned char had_resize, full_screen; @@ -122,14 +124,14 @@ void winwidget_hide(winwidget winwid);  void winwidget_destroy_all(void);  void winwidget_free_image(winwidget w);  void winwidget_center_image(winwidget w); -void winwidget_render_image(winwidget winwid, int resize, int alias); +void winwidget_render_image(winwidget winwid, int resize, int force_alias);  void winwidget_rotate_image(winwidget winid, double angle);  void winwidget_move(winwidget winwid, int x, int y);  void winwidget_resize(winwidget winwid, int w, int h);  void winwidget_setup_pixmaps(winwidget winwid);  void winwidget_update_title(winwidget ret);  void winwidget_update_caption(winwidget winwid); -void winwidget_rerender_all(int resize, int alias); +void winwidget_rerender_all(int resize);  void winwidget_destroy_xwin(winwidget winwid);  void winwidget_set_pointer(winwidget winwid, int visible); | 
