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