From 21c4996c71d76b01a4333ef9905589b3fffa687d Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Fri, 5 Feb 2010 17:52:34 +0100 Subject: Initial commit (upstream 1.3.4) --- AUTHORS | 58 + COPYING | 21 + ChangeLog | 2007 ++++++++++++++++++++ Makefile.am | 26 + Makefile.in | 454 +++++ README | 17 + TODO | 20 + acinclude.m4 | 136 ++ aclocal.m4 | 1448 ++++++++++++++ cam/ChangeLog | 14 + cam/Makefile.am | 11 + cam/Makefile.in | 214 +++ cam/README | 45 + cam/cam | 192 ++ cam/cam_bookmarks | 24 + cam/gen_cam_menu.sh | 41 + config.guess | 1465 +++++++++++++++ config.sub | 1569 ++++++++++++++++ configure | 4700 ++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 68 + configure.in | 65 + feh.1 | 631 +++++++ feh.spec | 43 + feh.spec.in | 43 + install-sh | 251 +++ missing | 198 ++ mkinstalldirs | 40 + src/Makefile.am | 43 + src/Makefile.in | 496 +++++ src/about.png | Bin 0 -> 61171 bytes src/collage.c | 240 +++ src/config.h.in | 37 + src/debug.h | 115 ++ src/events.c | 688 +++++++ src/events.h | 37 + src/feh.h | 178 ++ src/feh_png.c | 214 +++ src/feh_png.h | 39 + src/filelist.c | 611 ++++++ src/filelist.h | 89 + src/getopt.c | 1045 +++++++++++ src/getopt.h | 136 ++ src/getopt1.c | 187 ++ src/imlib.c | 1292 +++++++++++++ src/index.c | 611 ++++++ src/ipc.c | 94 + src/ipc.h | 57 + src/jpegint.h | 392 ++++ src/keyevents.c | 445 +++++ src/list.c | 116 ++ src/main.c | 219 +++ src/md5.c | 392 ++++ src/md5.h | 94 + src/menu.c | 2144 +++++++++++++++++++++ src/menu.h | 192 ++ src/menubg_aluminium.png | Bin 0 -> 1862 bytes src/menubg_aqua.png | Bin 0 -> 5325 bytes src/menubg_black.png | Bin 0 -> 1716 bytes src/menubg_britney.png | Bin 0 -> 34250 bytes src/menubg_brushed.png | Bin 0 -> 8649 bytes src/menubg_chrome.png | Bin 0 -> 10995 bytes src/menubg_default.png | Bin 0 -> 209 bytes src/menubg_pastel.png | Bin 0 -> 3676 bytes src/menubg_sky.png | Bin 0 -> 1928 bytes src/menubg_wood.png | Bin 0 -> 7873 bytes src/multiwindow.c | 78 + src/options.c | 1203 ++++++++++++ src/options.h | 137 ++ src/slideshow.c | 582 ++++++ src/stamp-h.in | 1 + src/structs.h | 37 + src/support.c | 658 +++++++ src/support.h | 56 + src/thumbnail.c | 992 ++++++++++ src/thumbnail.h | 86 + src/timers.c | 172 ++ src/timers.h | 49 + src/transupp.c | 1233 ++++++++++++ src/transupp.h | 135 ++ src/ttfonts/Makefile.am | 13 + src/ttfonts/Makefile.in | 216 +++ src/ttfonts/black.style | 4 + src/ttfonts/menu.style | 4 + src/ttfonts/yudit.ttf | Bin 0 -> 57708 bytes src/utils.c | 248 +++ src/utils.h | 90 + src/winwidget.c | 1058 +++++++++++ src/winwidget.h | 158 ++ 88 files changed, 31214 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 README create mode 100644 TODO create mode 100644 acinclude.m4 create mode 100644 aclocal.m4 create mode 100644 cam/ChangeLog create mode 100644 cam/Makefile.am create mode 100644 cam/Makefile.in create mode 100644 cam/README create mode 100755 cam/cam create mode 100644 cam/cam_bookmarks create mode 100755 cam/gen_cam_menu.sh create mode 100755 config.guess create mode 100755 config.sub create mode 100755 configure create mode 100644 configure.ac create mode 100644 configure.in create mode 100644 feh.1 create mode 100644 feh.spec create mode 100644 feh.spec.in create mode 100755 install-sh create mode 100755 missing create mode 100755 mkinstalldirs create mode 100644 src/Makefile.am create mode 100644 src/Makefile.in create mode 100644 src/about.png create mode 100644 src/collage.c create mode 100644 src/config.h.in create mode 100644 src/debug.h create mode 100644 src/events.c create mode 100644 src/events.h create mode 100644 src/feh.h create mode 100644 src/feh_png.c create mode 100644 src/feh_png.h create mode 100644 src/filelist.c create mode 100644 src/filelist.h create mode 100644 src/getopt.c create mode 100644 src/getopt.h create mode 100644 src/getopt1.c create mode 100644 src/imlib.c create mode 100644 src/index.c create mode 100644 src/ipc.c create mode 100644 src/ipc.h create mode 100644 src/jpegint.h create mode 100644 src/keyevents.c create mode 100644 src/list.c create mode 100644 src/main.c create mode 100644 src/md5.c create mode 100644 src/md5.h create mode 100644 src/menu.c create mode 100644 src/menu.h create mode 100644 src/menubg_aluminium.png create mode 100644 src/menubg_aqua.png create mode 100644 src/menubg_black.png create mode 100644 src/menubg_britney.png create mode 100644 src/menubg_brushed.png create mode 100644 src/menubg_chrome.png create mode 100644 src/menubg_default.png create mode 100644 src/menubg_pastel.png create mode 100644 src/menubg_sky.png create mode 100644 src/menubg_wood.png create mode 100644 src/multiwindow.c create mode 100644 src/options.c create mode 100644 src/options.h create mode 100644 src/slideshow.c create mode 100644 src/stamp-h.in create mode 100644 src/structs.h create mode 100644 src/support.c create mode 100644 src/support.h create mode 100644 src/thumbnail.c create mode 100644 src/thumbnail.h create mode 100644 src/timers.c create mode 100644 src/timers.h create mode 100644 src/transupp.c create mode 100644 src/transupp.h create mode 100644 src/ttfonts/Makefile.am create mode 100644 src/ttfonts/Makefile.in create mode 100644 src/ttfonts/black.style create mode 100644 src/ttfonts/menu.style create mode 100644 src/ttfonts/yudit.ttf create mode 100644 src/utils.c create mode 100644 src/utils.h create mode 100644 src/winwidget.c create mode 100644 src/winwidget.h diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..0ffd352 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,58 @@ +Principle author. +Tom Gilbert (gilbrit, giblet, grubby) + +Paul Duncan (pabs) + - cam, wget fixups, mouse-button swapping options, rotation, + xinerama support, menu backgrounds, and more. + +Richard Lowe (richlowe) + - background setting code, thumbnail patches. + +Benjamin Elijah Griffin + - made builtin http work. + +Mrinal Kalakrishnan + - auto-zoom mode. + +Phil Morris (marmot) + - about.png. + +Carlos Puchol + - configure.in fix for nonstandard imlib2 locations. + +Eric Dorland + - the --title option. + +Omar Harriott + - fix filelist handling for filenames with spaces. + +Panagiotis Issaris + - keypad buttonpresses + +Jon Bernard + - xinerama bugfix + +Maciej Kalisiak + - large image/zoom bugfix + +Claes Nasten + - Thumbnail caching, fixes + +JC + - multiple --action* options + +Ulrich Spoerlein + - fullscreen image count display + +Thanks to: +Michael Jennings + - Makefile Fixes, moral support +Alistair Sutton + - rpm spec file for redhat. +Laurence J. Lane + - debian assimilation. +The Rasterman + - Imlib2, initial zooming code example. Enlightenment. +Stephen Levine + - Great help debugging under E17 + diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..de24d95 --- /dev/null +++ b/COPYING @@ -0,0 +1,21 @@ +Copyright (C) 1999,2000 Tom Gilbert. + +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. + diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..5544659 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,2007 @@ +Sat Jul 23 00:30:09 BST 2005 Tom Gilbert + + * Include the necessary jpegint header to get lossless rotation working in + the short term. + +Wed Jun 22 21:29:20 EDT 2005 Richard Lowe + * (support.c): Better fix for debiag bug#292020 + +Wed Jun 22 02:41:06 EDT 2005 Richard Lowe + * (support.c): Ugly change to deal with the New (and guaranteed) + way E17 tells us it's IPC window is a phony. + * (support.h): Support for the above. + +Wed Jun 22 01:04:20 EDT 2005 Richard Lowe + * (support.c): Check for E17 via the presence of the + ENLIGHTENMENT_VERSION atom, which right now is only there + on E16. I asked for this on E17, and two ints showing + MAJOR and MINOR. Let's see what happens (I'll fix the + check if it comes). + +Tue Jun 21 23:34:17 EDT 2005 Richard Lowe + * (support.c): Change references to Eterm to reference feh. + * (support.c): Fix Debian bug#292020 'feh crashes when it + can't create ~/.fehbg file'. + +Wed Jun 01 12:29:40 BST 2005 Tom Gilbert + + * fix transupp.c - ditching JPEG_INTERNALS broke exif tag preservation + * releasing as 1.3.3 + +Fri May 06 20:23:39 BST 2005 Tom Gilbert + + * back out fmmode (buggy, unportable) for now + +Sun May 01 00:15:11 BST 2005 Tom Gilbert + + * Releasing 1.3.1 + +Sun May 01 00:05:43 BST 2005 Tom Gilbert + + * Patch from From: Mathias Gumz + When setting a tiled background, tile the image into a root-sized + pixmap, rather than letting X do the tiling... + * fix a bug with --action's and thumbnail mode + * disable thumbnail caching by default :/ The spec doesn't support + user-specified thumbnail sizes at the moment, and feh does. + Use --cache-thumbnails to enable caching for now. + * New option --cycle-once to exit a slideshow after one loop through it. + +Mon Mar 07 23:56:03 GMT 2005 Tom Gilbert + + * Patch from Falko Schmidt + Adds --fmmode. I quote: + > In short, it enables the user to use feh as an image viewer used by a + > file manager like ROX-Filer or Nautilus when invoked with the --fmmode + > option. The file manager passes the file that the user wants to view to + > feh. My function then reads the directory in which the file resides and + > first passes the current image, then alphabetically all the following + > images and at last the images that are alphabetically before the current + > file to the 'filelist'. + > Afaik that's the default behaviour of gqview and gthumb. + +Mon Jan 24 15:34:53 GMT 2005 Tom Gilbert + + * Patch from Ulrich Spoerlein + * Displays image num/total when in fullscreen + +Tue Jan 04 23:50:08 GMT 2005 Tom Gilbert + + * Added option to hide the mouse pointer in full screen: --hide-pointer + * released 1.3.0 (1.2.[89]) were minor, feature-specific releases. + +Sat Sep 04 15:51:14 BST 2004 Tom Gilbert + + * Require giblib 1.2.4 now. + * Preparing for release of 1.2.7 + +Sat Sep 04 15:43:22 BST 2004 Tom Gilbert + + * Applied large patch from Claes Nasten + * Several tweaks to thumbnail.c including support for the "Thumbnail + Managing Standard" described at freedesktop.org. Thumbnails are cached in + a way which makes them accessible to other programs, under ~/.thumbnails + using md5sum filenames. + * He had to invoke libpng directly to write out the comments/tags required + by the spec, but that seems to be a trend with feh now so what the hell :p + +Sat Sep 04 12:35:46 BST 2004 Tom Gilbert + + * Nice patch from JC + * Alongside the original --action option, adds --action1 through --action9, + allowing you to define multiple actions which can be run using the number + keys. Lets you set up a list of commands for organising images. + +Fri Sep 03 13:40:48 BST 2004 Tom Gilbert + + * Moved to subversion, previous CVS history lost... + * New method for rotating jpegs - does a lossless jpeg rotation (thanks, + IJG) and preserves EXIF data, as requested by many users :) + * Fix minor documentation omissions (debian bug reports) + +Sat Jul 24 14:52:19 BST 2004 Tom Gilbert + + * Various warning fixes from Claes Nasten + +Thu Jun 10 23:14:36 BST 2004 Tom Gilbert + + * Support full X geometry flags + +Sat Jan 03 19:04:11 EST 2004 Paul Duncan , + + * removed extraneous XFlush + * switched to global file list length (avoid recalculating it + constantly) + +Tue May 27 14:55:02 BST 2003 Tom Gilbert + + * Released 1.2.6 + +Fri May 23 14:23:49 BST 2003 Tom Gilbert + + * Fix debian bug #193964. segv on 'm' followed by cursor movement. + +Fri Apr 11 11:46:55 BST 2003 Tom Gilbert + + * Patch from Eric Dorland + * Set icon name as well as title on change. + +Fri Apr 11 11:34:41 BST 2003 Tom Gilbert + + * Patch from Rami Lehti + * New option not to jump to start of filelist when it's re-sorted. + +Tue Mar 18 19:07:17 GMT 2003 Tom Gilbert + + * Fix bug reloading http images that fail to download on subsequent + attempts. + +Sun Feb 23 16:23:00 GMT 2003 Tom Gilbert + + * Released 1.2.5, for small bugfix below. + +Sun Feb 23 16:19:15 GMT 2003 Tom Gilbert + + * Fix http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=169911 + * Start of IPC code, not used yet. + +Mon Dec 23 01:19:17 GMT 2002 Tom Gilbert + + * Experimental speedup for caption editing. Caches the bg pixmap for the + image (which doesn't change when you're just editing a caption) so only + the overlay needs to be re-rendered on each change to the caption. + Definitely makes a difference when editing captions on a large, fullscreen + image. + +Sun Dec 22 22:59:31 GMT 2002 Tom Gilbert + + * Tweak event handling - don't nuke queued keyevents when we're accepting + input for caption entry. + +Sun Dec 22 13:50:16 GMT 2002 Tom Gilbert + + * Fixed wrapping for long lines with no spaces + * Caption editing, also requested by David Blackman + Hit 'c', edit caption, enter to confirm the changes or Escape to revert. + (Only when --captions-path has been specified). + * Spotted a couple of minor bugs as I went through stuff, fixed those two. + +Sat Dec 21 20:32:40 GMT 2002 Tom Gilbert + + * New option --captions-path. Specify a path (relative to each image) to a + directory with captions in and feh will overlay them on the image. It even + does text wrapping and centering! + Example, run feh --captions-path captions testimages + for image testimages/donna1.jpg, feh will look for a caption in + testimages/captions/donna1.jpg.txt + * This feature was requested by David Blackman + +Thu Dec 19 23:09:19 GMT 2002 Tom Gilbert + + * Fixed bug - segv when last image in slideshow is deleted. + +Thu Dec 05 16:04:24 GMT 2002 Tom Gilbert + + * Released 1.2.3 + +Thu Dec 05 03:32:29 GMT 2002 Tom Gilbert + + * Got rid of black background for the "draw filename" and zoom display + texts. Added a dropshadow to aid visibility when there's no contrast + against the background. + +Thu Dec 05 01:28:44 GMT 2002 Tom Gilbert + + * Keyboard control for menus :) + * Press 'm' to open the menu, escape to close it, arrow keys (or hjkl) to + navigate and space or enter to activate. + +Wed Dec 04 23:12:44 GMT 2002 Tom Gilbert + + * Changed the way the menus work - you don't have to hold the mouse button + down to keep them open any more. I prefer the old way but that way doesn't + allow keyboard menu control. + +Wed Dec 04 21:30:29 GMT 2002 Tom Gilbert + + * Found a couple of case statements without breaks in options.c + * New default menu, tweaked the menus a little, added code to specify the + menu bg image border and let the user tweak it. + +Sun Nov 24 22:47:43 GMT 2002 Tom Gilbert + + * Patch from Daniel Ashbrook to bind a key (v) to + switching between window and fullscreen mode + +Sun Oct 20 22:45:01 2002 EDT, Paul Duncan + + * added requested screen-clip option (allows you to disable window size + clipping based on screen geometry; ie, you can make pathologically large + windows, assuming you have the images to do so) + * disabled xinerama geometry check when using feh to set the background. + * cleaned up spelling and capitalization in menus + +Sun Oct 20 20:12:23 2002 EDT, Paul Duncan + + * src/support.c: xinerama bugfix from Jon Bernard + * src/options.c: added 'Use Xinerama' toggle to option menu + * src/options.c: changed 'Keep http files' to 'Keep HTTP Files' + (pet peeve ;P) + * src/options.c: added 'Auto-Zoom' toggle to option menu + * feh.1: added info about --xinerama flag + * AUTHORS: added Jon Bernard + +Sun Oct 20 14:49:46 2002 EDT, Paul Duncan + + * New beveled, off-white background image for menus. I made it the + default after consulting with the boss (eg Sue Gilbert). Tom thinks + it's okay too. + +Sun Oct 20 05:48:40 2002 EDT Paul Duncan + + * Added Xinerama support. Currently defaults to fullscreen on the + first head (this can be fixed with a little work). + * Added winwidget_{move,get_geometry}(); + +Wed Sep 11 19:53:31 BST 2002 Tom Gilbert + + * REALLY release 1.2.1 + +Wed Sep 11 19:52:24 BST 2002 Tom Gilbert + + * autoconf fixes + * throw out the damn non-free "public domain" fonts. + * stick in yudit.ttf. it's not as pretty, but it is, apparently, DFSG + compliant etc. + +Wed Sep 11 19:44:25 BST 2002 Tom Gilbert + + * Release 1.2.1 + +Wed Sep 11 19:43:24 BST 2002 Tom Gilbert + + * Patch from Panagiotis Issaris + - adds support for using the numeric keypad to scroll and zoom the image. + +Wed Jul 31 22:31:21 BST 2002 Tom Gilbert + + * Fixed --draw-filename (was --draw_filename but not documented as such - + oops, that's been broken a terribly long time :)) + +Tue Apr 16 19:19:11 BST 2002 Tom Gilbert + + * Release 1.2.0 + +Fri Mar 08 21:04:07 GMT 2002 Tom Gilbert + + * Patch from Omar Harriott + * fix filelist handling for filenames with spaces. + +Fri Feb 08 21:52:48 GMT 2002 Tom Gilbert + + * Don't segv on save if win->file is NULL, use the mode + .png for the + filename, or noname.png as a last resort. Reported by mousey. + +Sun Feb 03 19:28:19 GMT 2002 Tom Gilbert + + * Erp. s/wprintf/weprintf - I didn't notice the typo because wprintf is a + wide character printf. Luckily someone compiled feh on PPC and noticed the + bug. + +Wed Jan 30 13:54:29 GMT 2002 Tom Gilbert + + * New menu colour/style - "feh -Tblack src/testimages" + +Wed Jan 30 13:29:21 GMT 2002 Tom Gilbert + + * Patch from Jens Laas + * Adds --zoom option. Here's what he said about it: + > What it does: + > zooms images by a fixed amount but never larger than the screen. + > Why: + > This is nice if you got a collection of images where some are small and + > can stand a small zoom. Large images are unaffected. + > When does it work, and how? + > You have to be in fullscreen mode _and_ have auto-zoom turned on. + > "feh -FZ --zoom 130 imagefile" will do the trick. + > -zoom percent -- is the new switch. + > 100 = orignal size, + > 130 is 30% larger. + * I tweaked it abit to allow it to work (differently) without -Z. + feh -F --zoom 200 will zoom each image to 200%, regardless of the + resulting size. feh -FZ --zoom 200 will zoom each image up to a maximum + of 200%, but without generating an image larger than the screen. + +Sat Jan 26 16:20:43 GMT 2002 Tom Gilbert + + * Use giblib fontstyles for menus, instead of hardcoding the shadow. + * Let users choose menu style with --menu-style. Standard giblib + semantics. + +Sat Jan 26 15:34:26 GMT 2002 Tom Gilbert + + * make sure fullscreen windows are really fullscreen. + * Haha! feh uses giblib now, pointless me maintaining two list + implementations and two imlib2 wrappers. Plus now I can add fontstyles :) + +Sat Jan 26 14:10:54 GMT 2002 Tom Gilbert + + * Goodbye, non-free fonts, hello, free font. Turns out the guy who made + those "public domain" fonts doesn't actually want to release them under a + free license, so they gotta go. + +Mon Jan 14 19:51:18 2002 Tom Gilbert + + * Fixed --bg-seamless from the commandline. + * When you set a bg with feh, it now stores the necessary + commandline to restore that bg in ~/.fehbg. So for non-E + windowmanagers, that don't remember the bg, you can put "eval `cat + $HOME/.fehbg" in your .xsession, and your setting are remembered + when you restart X. + +Sun Jan 13 21:12:42 2002 Tom Gilbert + + * Gah. imlib_image_set_format("JPG") does not work, yet jpg + does. I think that's dumb :( This work around makes saving work + with uppercase filenames. + +Sat Jan 12 03:01:59 2002 Tom Gilbert + + * Stopped the bg code uselessly creating temp images when not + needed. + +Sun Jan 6 01:37:40 2002 Tom Gilbert + + * Use < or > keys to do in place edit rotations, 90 degrees left + or right. + +Sun Jan 6 01:16:04 2002 Tom Gilbert + + * Fix unlikely but naughty segv. + +Sun Jan 6 00:49:35 2002 Tom Gilbert + + * Some basic in place editing. Feh is not an editor, but when + viewing images I just grabbed from the digicam, it's really useful + to fix up the ones needing rotation. + +Tue Sep 4 23:47:42 2001 Tom Gilbert + + * --loadable and --unloadable modes should run --action on + matching files, fixed. + +Sun Aug 26 18:06:51 2001 Tom Gilbert + + * Slightly tweaked menu sliding behaviour. + * About to release 1.1.0. + +Sat Aug 25 21:58:31 2001 Tom Gilbert + + * Show zoom and new image size when zooming. + +Sat Aug 25 18:36:30 2001 Tom Gilbert + + * No need for cam to use -w as it spawns multiple feh processes. + * Can use options menu to switch between fullscreen and window + modes. + * Some fullscreen code cleanups. Now a per-window option. + * Menu code cleanups. + +Sat Aug 25 17:46:35 2001 Tom Gilbert + + * Fixed --geometry mode. When you resized the window it would still + center/size to the size you specified in --geometry. I think + --geometry should just say "don't change the window size", but the + user should still be able to :) + * Added a new menu option for freezing/unfreezing the window size. + +Sat Aug 25 02:49:54 2001 Tom Gilbert + + * okay. feh menus now support toggleable items. + * I was gonna use ellipses for the toggle state, but I found that + I had broken ellipses in imlib2 a while back (at least I think it + was me). So it's rectangles. I fixed imlib2 now, but there won't + be a release for a while. + * A couple of options can now be configured through the menus, + will add more in time. + * some other stuff I forget, I'm tired :) + +Fri Aug 24 08:44:46 2001 Tom Gilbert + + * Even better, you can copy a pixmap between displays :) This is + much faster than Xput/get. Cheers raster. + +Thu Aug 23 19:04:57 2001 Tom Gilbert + + * Okay. So you can't copy a pixmap between two displays using + XCopyArea :) Fair enough, back to blechy XPut/XGetImage. It works + now with or without E, and Eterm is happy. Managed to avoid + leaking data into X through imlib2 or my own cached GCs, which is + nice :) + * Tested commandline too, works great with E or without. Finally. + * Also fixed a bug with the non-E centering code, it would only + have really worked for square images before ;-) + +Wed Aug 22 22:44:13 2001 Tom Gilbert + + * Okay, setting the pixmap and atoms works now, bar an imlib2 bug + we need to fix. So right now, rather than dump core, I leak X + connections whenever you set a BG. No big hit unless you do + thousands, and it's only temporary until we fix imlib2. + * This is mainly for raster to check out right now. + +Wed Aug 22 17:01:08 2001 Tom Gilbert + + * Okay, setting bg from cmdline when not running E was broken, + basically because we didn't XFlush before exiting. My bad. + * Ugh. I'm trying to emulate Esetroot, by setting the atoms needed to + tell Eterm where the bg pixmap is. Of course, when feh exits, the + pixmap is cleaned up by X, unless I do an XSetCloseDownMode(disp, + RetainPermanent); However, this means all my crap hangs around, I want + it to be cleaned up. So anyone know how I can make the pixmap stick + around in X, without leaving windows and other pixmaps there too? + (Esetroot lets it all hang out basically, but it's non graphical and + can afford to. It always exits after doing it's job and the next time + you run it, it frees the last pixmap it made). + +Mon Aug 20 20:58:47 2001 Tom Gilbert + + * If you specify a font that can't be loaded, feh attempts to fall + back to 'fixed', then '*'. + +Sat Aug 18 19:15:22 2001 Tom Gilber + + * Added, 'w, W' and a menu option to resize the window to the + current image dimensions. + +Thu Aug 16 23:07:33 2001 Tom Gilbert + + * Added 'x' to close a window but not exit everything. + +Thu Aug 16 00:23:26 2001 Tom Gilbert + + * Fook. Broke backgrounding in E for 1.0, enlightenment IPC does + NOT support "filename with a space" at all. You can't do + it. ARGH. Okay, so back that out. + * Add setting bg from commandline, quite useful because it'll use + E if it's there or fallback to X, i.e. it should always do the + right thing (hopes). + * FYI, it's --bg-scale, --bg-center, --bg-seamless, --bg-tile. + +Mon Aug 13 22:21:44 2001 Tom Gilbert + + * Fixed bug when using -g to reduce image proportionally, + calculated zoom was incorrect because I am a dick. + +Sun Aug 12 18:13:39 2001 Till Adam + + * slide menus to the left and/or up if they are off the screen and the + cursor is close to the right and/or bottom edge of the screen + +Sun Aug 12 00:24:38 2001 Tom Gilbert + + * Uh that's not all I changed in the last commit. + * Panning is different now. It used to be ctrl+button 3, but this + was redefinable using cmdline/theme options. Now, instead, it's + combined with the next image button. + * ie. by default a single click of button 1 will change images, if + there is more than one image in the slideshow. Clicking and + dragging button 1 will pan, if the image is bigger than its + window. I find this more convenient, but let me know. + +Sun Aug 12 00:15:06 2001 Tom Gilbert + + * Oops. Fixed bug with zooming out larger images when -g is used. + * Other fixes. + +Sat Aug 11 23:29:32 2001 Tom Gilbert + + * Fixed annoying bug where feh would limit window size to desktop + size only on the first image. + +Sat Aug 11 23:20:09 2001 Tom Gilbert + + * Added -g, --geometry setting to fix feh's geometry. Stops + repeated resizing when browsing lots of pics. Please test this for + me as I want to get 1.0 out soon :)p + +Sat Aug 11 01:41:21 2001 Tom Gilbert + + * Add image and filelist saving to context menus. + * Tidy menus. + +Sat Aug 11 01:25:15 2001 Tom Gilbert + + * Fixed missing break; in keyevent handler + * Changed the slideshow pause key from "s,S" to "h,H" + * New slideshow key "s,S" to save the current image to a unique + filename (generated in the same way as saved webcam images). + * New slideshow key "f,F" to save the current filelist, also to a + unique filename. + * Little cleanups. + +Thu Aug 9 23:57:41 2001 Tom Gilbert + + * Oops. Went back to getopt_long. getopt_long_only is cool if you + only have a few cmdline options, but feh has a bunch and most + short option combos were coming up as "ambiguous". i.e. feh -Vw + actually ignores the -w. Fixed. + +Thu Aug 9 23:39:02 2001 Tom Gilbert + + * Remembered some things I changed a while back and didn't put in + here, but they need to be in here or I'll forget forever. + * Fixed a race with multiple webcam-viewing feh instances by + adding feh PID to the tmp filename used to cache the downloaded + images. Other fixups to the remote-getting code. + +Thu Aug 9 23:16:58 2001 Tom Gilbert + + * Load menu font just once and keep it around. + * New menu backgrounds. + * Fix detection of bad fonts. + * Allow use of --fontpath multiple times to add many paths + to the fontpath. + +Thu Aug 9 22:45:05 2001 Tom Gilbert + + * Progressive loading is gone. It's useless in imlib2 because + imlib2 can't load from filehandles, it's real application is + gone. Plus people say without seeing the image load it "feels" + faster. This also simplifies a bunch of code and I feel cleaner + without it. + * Less pointless redraws, should be faster switching images now. + * Other bits. + +Thu Feb 15 11:25:45 2001 Tom Gilbert + + * A patch from labisso (David LaBissoniere ) + to allow pausing of slideshows. Handy. + +Sun Jan 28 13:20:45 2001 Tom Gilbert + + * cam was using -Cwebcam, should be -Twebcam + * default generated ~/.fehrc used --keep-http in webcam mode, this + is probably not what most people want for the default, so I + removed it. Either blow away your ~/.fehrc or make this change + yourself to get it.... + * Maybe fixed a memleak. I hope so, but it will take 3 days of + running cam to find out :-) + * After an idea and partial patch from KainX, added -G, + --wget-timestamp to use wget timestamping when downloading http + images. Useful when watching webcams, the idea is that wget only + downloads the webcam if it has changed since the last time. Nice + bandwidth saver. However, there is currently a bug in wget that + prevents this from working. KainX found it and I think he reported + it, so the next version should contain a fix. + +Wed Jan 17 20:33:31 2001 Tom Gilbert + + * Reverted to using wget by default - the builtin stuff isn't + quite so tolerant about hangups and stuff, it kinda just blocks a + lot. Needs more work before replacing use of wget, which "just + works". + +Mon Dec 11 19:25:10 2000 Tom Gilbert + + * Added a super-sweet patch from Benjamin Elijah Griffin + to actually implement the builtin http + collection I started ages ago. I screwed with it only slightly, + it's a great patch. So now we can grab http images without + spawning a subprocess, and I have to say here it seems a little + faster too ;-) + * Added -Q, --wget option to use wget to grab http data just in + case you need to use a proxy, or something else stops the builtin + stuff from working... + * Misc tidyups etc.. + + +Tue Nov 28 00:45:38 2000 Tom Gilbert + + * Added support for --slideshow-delay as a float. -D0.25 for + example. + +Sat Oct 28 23:32:11 2000 Tom Gilbert + + * Better check for imlib2. + * Only create files in current dir if keeping http images. Ones + that will be deleted on exit go in /tmp. + +Sun Oct 22 02:01:33 2000 Tom Gilbert + + * Swapped the default right mouse button config. You now hold + ctrl to pan, or don't to get menus. + * Changed --no-menu-ctrl-mask to --menu-ctrl-mask + * Added --no-pan-ctrl-mask + * Use the options feh --no-pan-ctrl-mask --menu-ctrl-mask to + simulate the old behaviour, or add that line to ~/.fehrc to keep + it. + * Need to change all the --*-ctrl-mask options to booleans so it + is properly configurable, I think. + +Sat Oct 21 23:22:09 2000 Tom Gilbert + + * Fixed the -k option (to save files viewed by http). It now saves + the files into the *current* directory, with better filenames, eg + feh_000001_image.jpg for a file called image.jpg. + * Removed the use of the evil mkstemp function, not needed any + more. + +Fri Aug 25 16:41:29 2000 Tom Gilbert + + * rotation wasn't reset when image changed in fullscreen mode + +Sat Aug 19 16:07:29 2000 Paul Duncan + + * added multiple key loading to cam. also updated the + documentation and chnaged the version number to 0.3. + +Fri Aug 4 12:09:29 2000 Tom Gilbert + + * Sweet patch from Eric, changes window title to "Reloading: + " when reloading an image. Neato :) + +Thu Aug 3 23:11:23 2000 Tom Gilbert + + * Another fine patch from Eric Dorland, allows the configuration + of the reload button, --reload-button NUM. Also patches cam to use + button 1 to reload webcams :) Nifty ;) + +Thu Aug 3 23:04:38 2000 Tom Gilbert + + * Patch from David LaBissoniere + Adds a --start-at NUM option for jumping to number NUM of the + filelist (either from a file or the commandline). + * Thanks David. + +Fri Jul 28 21:07:32 2000 Tom Gilbert + + * Added --scale-down to automatically scale images down if they + are too big to fit on the screen. Only works with -P right now + because I am lame, but I'm on the case... + * The start of some builtin http code to replace wget. Part-done + and #ifdef'd out for now... + +Sun Jul 9 00:03:27 2000 Tom Gilbert + + * Fixed an ickle memleak when reloading a rotated image. + +Tue Jun 27 17:16:21 2000 Tom Gilbert + + * More --title stuff from Eric. It now works in thumbnail mode, + and an additional --thumb-title can be used to set the title of + the individual thumbnail windows. + +Sun Jun 25 03:39:57 2000 Tom Gilbert + + * Spec file fixes (I suck). + * Okay, if DEBUG is defined, then --debug-level NUM shows only + debug messages with a level equal to or below that + specified. Right now I'm using 0-5. + +Sun Jun 25 02:46:58 2000 Tom Gilbert + + * Started reworking the debugging macros. Nothing to see here, yet + ;) + * Another patch from Eric Dorland, makes --title work in all the + other modes but thumbnail mode. + +Sat Jun 24 23:43:03 2000 Tom Gilbert + + * Hehehe. Patch from Eric Dorland arrived + just after the release ;-) + * New format specifiers, --title works in multiwindow mode, and + --title is passed through feh_printf, so the new format specifiers + may be used in it... Coolio. + +Sat Jun 24 21:27:05 2000 Tom Gilbert + + * Released 0.9.9. + +Sat Jun 24 19:06:26 2000 Tom Gilbert + + * In multiwindow mode, handle events whilst opening windows. This + is very handy for when you accidentally do feh -rw / and have 14 + million images opening. 'q' will quit at any time ;) + +Sat Jun 24 18:57:22 2000 Tom Gilbert + + * Fixes for blending transparent stuff onto transparent stuff. + * Reindent and cleanup prior to release. + +Sat Jun 24 18:34:39 2000 Tom Gilbert + + * Fix for a reload when rotated. + +Sat Jun 24 18:27:49 2000 Tom Gilbert + + * Check panning after a zoom, move within constraints if + necessary. + +Sat Jun 24 18:15:35 2000 Tom Gilbert + + * Constraints for panning. + +Sat Jun 24 17:00:59 2000 Tom Gilbert + + * Context menu for thumbnail mode. + +Sat Jun 24 16:44:19 2000 Tom Gilbert + + * Fix for segv when tring to get image info for a generated (not + on fs) image. + +Sat Jun 24 16:28:11 2000 Tom Gilbert + + * Fix for rotation and panning and zooming in fullscreen mode. + +Sat Jun 24 12:21:02 2000 Tom Gilbert + + * Added --title, with a nice clean patch from Eric Dorland + , allows you to set the window title to be used + for slideshow mode. He also modified cam to use this to label it's + windows. A combined perl and C patch - neato ;-) + +Sat Jun 24 00:46:54 2000 Tom Gilbert + + * New menu item, Reset. It resets the zoom/pan/rotate etc. + * Currently only with -P (to be fixed), a reload does not force a + reset like it did before, so you can zoom a webcam and not have it + reset on reload. + +Sat Jun 24 00:13:53 2000 Tom Gilbert + + * Thumbnails, when clicked, now all open the clicked image in the + same window. Much better for browsing. + * Menu fixups, more efficient now. Also, better context menus, + having the right options for the right window types. + * If you open a thumbnail, and then delete it or remove it from + the filelist, the thumbnail view will update to show the + fact. This is cool :-) + +Fri Jun 23 17:15:07 2000 Tom Gilbert + + * Depreciated the FEH_OPTIONS envrionment variable in favour of + the configuration file themes. + +Fri Jun 23 14:46:21 2000 Tom Gilbert + + * Mwahahaha. Asynchronous events for index, thumbnails and + collages. All events are handled while the images are + generated. You can quit, bring up menus, zoom, pan and rotate, all + whilst the image is still being created. Much better. + * Pass the progress function around instead of using the + context. Kills two bugs. + +Fri Jun 23 14:11:56 2000 Tom Gilbert + + * Documentation fixups. + * --thumnbails can also be called with -t now. + * --title-font no longer has a short option. + * --theme is now also -T. + * Release preparations. + +Fri Jun 23 12:54:49 2000 Tom Gilbert + + * You can now select --bg trans to give indexes, collages, + montages and thumbnail selectors a transparent background. + +Fri Jun 23 12:18:44 2000 Tom Gilbert + + * Fixed a couple of minor bugs + * You can now open the same image multiple times... If you really + want to... + +Fri Jun 23 11:37:56 2000 Tom Gilbert + + * Thumbnails now stored in a linked list. + +Thu Jun 22 23:57:33 2000 Tom Gilbert + + * Optimisations to thumb hilites. Only show hilite when you can + click to open an image, don't show when over emtpy space, and + don't re-render if the selection hasn't changed from the last + mouseover. Speeds it up a lot. + +Thu Jun 22 23:49:07 2000 Tom Gilbert + + * Now thumbnails show as they load too. + * AND :-) + * Thumbnail hiliting on mouseover from richlowe. Coolio ;-) + +Thu Jun 22 23:32:45 2000 Tom Gilbert + + * Same for collage mode :) + +Thu Jun 22 23:28:33 2000 Tom Gilbert + + * Woop. Something I should've done a WHILE ago. If progressive + loading is enabled (ie not -P), you can see the index/montage + being created in front of your eyes ;-) It's sweet. + * Next I will make it respond to events during the creation + (quiting/zooming while still creating), and make it work for + thumbnail and collage modes too. + +Thu Jun 22 22:23:48 2000 Tom Gilbert + + * Fix for trying to reload a montage + * Rewrite of all linked-list code to a more generic form so I can + do more with it. I may have introduced bugs in this (big) rewrite, + so test test test ;-) + * Misc fixups + +Wed Jun 21 23:49:00 2000 Tom Gilbert + + * Can set background from multiwindow and thumbnail modes now. + +Wed Jun 21 22:43:37 2000 Tom Gilbert + + * Initial thumbnail mode, thanks to patches from richlowe and + modifications by me. Nice work dude. More to come, right now + there's just the click (although it works with a panned or zoomed + thumbnail list). To come - opening thumbs in a single window, + hiliting, and hey, the rest will be a surprise, okay? ;-) + * This is *initial* btw. I plan to properly add this to index and + montage modes, as it needn't be a seperate mode. There's lots of + duplication in the source right now, which needs to be cut down. + +Tue Jun 20 20:02:57 2000 Tom Gilbert + + * Fixed mousebutton swapping option code. It was broken for + certain combinations, now all seems well. + * Found a use for ctrl+button1 for now, it just blurs/sharpens the + image dynamically - for shits and giggles. It is somewhat spoiled + by the fact that imlib2 currently doesn't seem to care what radius + you pass to imlib_sharpen_image(), it always does the same thing. + +Mon Jun 19 17:47:37 2000 Tom Gilbert + + * Added new background setting mode. "Set seamless." It's purdy. + +Mon Jun 19 14:18:10 2000 Tom Gilbert + + * Mwahaha. Now the window is resized when rotation starts (to fit + the rotated image in). Also, checks are drawn properly behind the + image, and rotation works well in combination with pan and zoom. + * Now that all that's done, rotation is slow as shit ;) We'll see + if we can speed that up next ;) + +Sun Jun 18 21:49:35 2000 Tom Gilbert + + * No more eesh. We use E ipc properly now. IPC code pinched from + Eterm - thanks KainX. + +Sun Jun 18 19:38:02 2000 Tom Gilbert + + * Zooming is mostly fixed now. Works much better. A few little + tweaks and we'll be laughing :-) + +Sun Jun 18 16:11:47 2000 Tom Gilbert + + * More menu styles. Remove your ~/.fehrc (let it regenerate) and + run feh -t wood, feh -t aluminium or feh -t aqua to see them. + +Sun Jun 18 14:53:17 2000 Tom Gilbert + + * Better eesh availability determination, and a check that E is + actually being used at the time, too ;) + +Sun Jun 18 13:46:59 2000 Tom Gilbert + + * Now feh will query eesh for the number of desktops a user + has. If eesh is there, and there is more than one, the background + setting menu will offer a choice of which desktop to set. + +Sun Jun 18 03:47:58 2000 Tom Gilbert + + * Okay. Thanks to richlowe and me, the bg setting is getting + pretty cool now. It uses eesh under E, but if it can't find it, + nicely falls back to X calls. There are more options to come + (choosing which desktop etc), but for now, things are pretty sweet + ;-) + +Sun Jun 18 01:29:16 2000 Tom Gilbert + + * The first part of some background setting code from richlowe + - more to come, it'll be sweet. + * Doesn't work yet btw, so don't get excited ;) + +Sun Jun 18 00:40:28 2000 Tom Gilbert + + * New option, --rcfile FILE. Uses FILE instead of the normal + ~/.fehrc or /etc/fehrc for parsing configs/themes from. + +Sun Jun 18 00:26:06 2000 Tom Gilbert + + * Now feh will write a default ~/.fehrc if none is found, but only + if there is no /etc/fehrc in place already. + +Sat Jun 17 23:46:32 2000 Tom Gilbert + + * A couple of nice new menu bgs from pabsmonkey. + * The example.fehrc has theme entries for them, so if you copy it + to ~/.fehrc, using feh --theme brushed will use the brushed menu + bg. Same for --theme chrome. + +Sat Jun 17 12:57:49 PDT 2000 Paul Duncan + + * wget is now quiet by default (wget -q). it's verbose if the + -V or --verbose flag is passed to feh. Your terminal will + thank you. + * mirrored the same change too cam. cam -V or cam --verbose + will enable verbose mode for feh and the forked wgets. + * the second mouse button now zooms again, and the third button + pans. + * added menu-button option too (-4 or --menu-button). ctrl+the + menu button brings up the menu. defaults to the right mouse + button, and you can set it to 0 for any button (including ones + >3, there's no bounds checking). This feature is disabled by + the -N or --no-menus flag. + +Sat Jun 17 20:41:24 2000 Tom Gilbert + + * Apend ? and a random number to the image url for webcams so that + the image isn't cached. Much better. + +Fri Jun 16 22:52:50 2000 Tom Gilbert + + * Menus can have a background image now. There is a default one, + courtesy of Pablo P Duncan (http://10k.dhs.org/~dmron/arch.html). + * You can use any image you like for the background, by using + --menu-bg FILE to select one. I had a small amount of fun using + Britney as my menu background. Strange, but true. + +Wed Jun 14 18:53:06 2000 Tom Gilbert + + * Added --progress-gran NUM. Sets the progressive-loading + granularity to NUM, an integer between 0 and 100. This is the + percentage of the image to load before updating the display. 0 is + super-smooth, but slightly slower than 100, which loads the whole + image before showing anything. Use lower numbers to get + responsiveness over slow network connections... + +Sat Jun 10 21:25:33 2000 Tom Gilbert + + * Zooming is back, and it's as it was before. I'm still not happy + with it, but it works again anyhow. Next: fix, fix, fix. + * Don't forget, you need to hold control to get menus now... + +Sat Jun 10 12:36:58 2000 Tom Gilbert + + * Only render the current viewport. Big optimisation I should have + done earlier. Makes zooming big images smooooooooth ;-) + * Nearly finished the zooming rewrite, but it's disabled right now + (it's still a bit crappy). + +Sat Jun 10 00:05:10 2000 Tom Gilbert + + * Fixed check drawing after resize. Edge resistance against *all* + the edges, not just two of them ;-) + +Fri Jun 9 21:31:01 2000 Tom Gilbert + + * Fix fullscreen mode to work with new image placement code. Make + it work with --auto-zoom and --stretch too. + * Perform an antialiased pass after panning if needed. + +Fri Jun 9 19:48:05 2000 Tom Gilbert + + * Edge resistance when panning. Much better. + +Thu Jun 8 22:02:50 2000 Tom Gilbert + + * First part of zooming/scaling rewrite. Only panning so far, but + it works nice. Zooming is current *disabled*. + +Sun Jun 4 15:44:05 2000 Tom Gilbert + + * Added a wrapper to imlib2. I was getting some subtle bugs from + the singleton context (accidentally leaving context_antialias on, + not blending when I should be etc), and to fix them I was adding + lines and lines of context_set this, context_set that. I've + wrapped the imlib calls in an imlib1 + lots-of-params-per-function-call stylee, and now it's much more + readable and harder to break. + * In the process, made big speedups by not antialiasing when I + needn't, or blending when I shouldn't etc. Also blew away a few + hundred lines of context-setting. + +Fri Jun 2 22:58:50 2000 Tom Gilbert + + * Fixed pixmap resizing bug properly this time ;-) + +Thu Jun 1 19:36:19 2000 Tom Gilbert + + * Correct oversite in sizing pixmaps. + +Wed May 24 20:21:14 2000 Tom Gilbert + + * Massively speeded up image rendering and therefore zooming by + actually *thinking* about what I was doing and using a tiled + pixmap GC and XFillRectangle for drawing the background + checkerboard pattern. Much better. I'll clean it up a bit + next. + +Wed May 24 00:09:12 2000 Tom Gilbert + + * Fixed bug with --no-progressive and window resizing. The + rendering and resizing code is a *mess* now, which I'll have to + fix tomorrow (lots of duplication and a complex codepath). But at + least it works properly right now :-) + +Tue May 23 22:19:30 2000 Tom Gilbert + + * Optimised event handling from nasty big switch() to a table of + pointers to functions. + +Sun May 21 20:53:37 2000 Tom Gilbert + + * About.png contributed by Phil Morris (marmot) + + +Sun May 21 10:01:39 2000 Tom Gilbert + + * Gratituous eyecandy in the about box 'cos Boris asked nicely ;-) + +Sat May 20 01:09:15 2000 Tom Gilbert + + * Wired cam into the Makefile.am + +Fri May 19 19:21:01 2000 Tom Gilbert + + * You can now use --action with list or customlists too. In these + modes, the action is run automatically for each file listed. + +Thu May 18 21:34:03 2000 Tom Gilbert + + * Quotes, escaped quotes and escaped spaces in config files work + as one would expect. I think. Don't they? + +Thu May 18 20:43:16 2000 Tom Gilbert + + * \n now gets you a newline in a feh-interpreted string. + +Thu May 18 20:26:54 2000 Tom Gilbert + + * Changed how -l and -L work. -L is now --customlist, which takes + a string argument. The string is a feh-printf format specifier, + just like those used for action definitions. (Eg %f for filename, + %w for width etc). The format specifier is used to form the list + output for each file. Example usage: + feh -L "\"feh\"" pr0n.png + Stuck a new theme in the example.fehrc config, and found how lame + my config parsing code is :-) Quotes and escaped quotes currently + *do not* work right. I'm fixing it now :-) + +Tue May 16 17:51:40 2000 Tom Gilbert + + * Ignore duplicate MotionNotify events + * Same for ConfigureNotify + * Saved some wasted cycles + +Mon May 15 22:49:07 2000 Tom Gilbert + + * Hehe. Now I made a release I can break stuff again =P You can + resize the window again now, and it works okay, except zooming + isn't quite right when the window is bigger than the image right + now. I have to redo *all* that zooming code over the next week + or so 'cos it was shortsighted to start with :-( + +Sun May 14 17:34:48 2000 Tom Gilbert + + * New "Image Info" submenu. It tells you stuff. About the + image. Hence the name. + +Sun May 14 16:03:53 2000 Tom Gilbert + + * Reorganised and tidied the headers somewhat. Various cleanups. + +Sat May 13 20:53:12 2000 Tom Gilbert + + * Add -N, --no-menus option for people who Just Want The Pr0n [tm] + +Sat May 13 20:35:08 2000 Tom Gilbert + + * Now you can press 'r' to reload images too. + +Sat May 13 20:24:18 2000 Tom Gilbert + + * Hide menu, *then* perform action. Otherwise hitting "reload" on + an http:// image over a slow connection keeps the mouse grab until + finished. Messy ;-) + +Sat May 13 19:54:46 2000 Tom Gilbert + + * Make the menus slightly prettier. I wish I had an artistic bone + somewhere in my body... + +Sat May 13 18:04:58 2000 Tom Gilbert + + * Use realpath() to cleanup paths before sticking them in a + filelist. Added --menu-font, -M so that you can use whatever font + you like for menus. + +Sat May 13 00:11:06 2000 Tom Gilbert + + * Menus. They need some work, but are mostly good. + * I owe many thanks to raster here, 'cos I pinched some functions + from efm to save time :-) + * Added --auto-zoom. Currently only works with --no-progressive, I + need to fix that soonish... + +Tue May 9 22:04:37 2000 Tom Gilbert + + * Now --filelist is -f, relegating -font to -e. *shrug*. + +Tue May 9 21:57:14 2000 Tom Gilbert + + * Now --theme is -t instead of -C (duh). + +Tue May 9 21:35:34 2000 Tom Gilbert + + * Now --action is A, and --ignoreaspect is X. + +Tue May 9 21:30:59 2000 Tom Gilbert + + * Now randomize is -z, which makes a little more sense. + +Tue May 9 21:15:57 2000 Tom Gilbert + + * Swapped -g and -c so that --collage gets the -c it fits, and + randomize gets -g. I need to rework all these short options, + they're a mess right now. Sorry if I break anyone's configs doing + this :-( + +Tue May 9 21:09:15 2000 Tom Gilbert + + * Removed -B, --booth, as it's just a combo of options now doable + in the config file. I stuck it in the example config instead... + +Mon May 8 22:38:11 2000 Tom Gilbert + + * Don't apply colormods to each whole image. First scale it to + thumbnail size, then apply the colormod to that. + +Mon May 8 22:08:41 2000 Tom Gilbert + + * Made --alpha actually do stuff. I finally grokked color + modifiers, and now they're fun ;-) Imlib2.h is really gonna need + some comments at some point though - I had proper trial-and-error + fun and games there for a while ;-) + +Mon May 8 21:58:54 2000 Tom Gilbert + + * D'oh! if(foo & bar) isn't quite the same as if(foo && + bar). Stupid cheap keyboards ;-) + +Mon May 8 13:12:01 2000 Tom Gilbert + + * Fun with dmalloc + +Mon May 8 13:10:12 2000 Tom Gilbert + + * Ensure backgrounds of index and montage images are black by + default. Imlib2's behaviour changed in this respect at some point. + +Sun May 7 18:42:57 2000 Tom Gilbert + + * Fixed breakage (and segfault) when preloading images in verbose + mode if any of the images are unloadable. Stupid typo. + +Sun Apr 30 16:02:11 2000 Tom Gilbert + + * Added -n, --reverse. Reverses the sort order. + Use this to invert the order of the filelist. Eg to sort in + reverse width order, use -nSwidth + +Sun Apr 30 15:13:25 2000 Tom Gilbert + + * In slideshow and muliwindow modes, DELETE now removes the + current file from the filelist. CTRL+DELETE deletes the files from + the filesystem and removes it from the filelist. + +Sun Apr 30 14:48:04 2000 Tom Gilbert + + * Filelists can now be saved to and loaded from files, very much + like the playlists used by music players. + * Here's the details: + -e, --filelist FILE + This option is similar to the playlists used by music + software. If FILE exists, it will be read for a list + of files to load, in the order they appear. The for- + mat is a list of image filenames, absolute or rela- + tive to the current directory, one filename per line. + If FILE doesn't exist, it will be created from the + internal filelist at the end of a viewing session. + This is best used to store the results of complex + sorts (-Spixels for example) for later viewing. Any + changes to the internal filelist (such as deleting a + file or it being pruned for being unloadable) will be + saved to FILE when feh exits. You can add files to + filelists by specifying them on the commandline when + also specifying the list. + * I quite like this option. The reason I added was that I've been + testing some boundary conditions by recursing through complex + directory trees / sorting 10,000 images by pixel size etc, and + that can take a while. Now I can do it once, save the filelist, + and refer to that in future. You can of course use it to organise + and group pics too. ~/lists/britney.list, ~/lists/laetitia.list. + Hmmmmmm. + +Sun Apr 30 02:40:01 2000 Tom Gilbert + + * PageUp/PageDown in slideshows will jump back/forward about + 1/20th of the total number of files... + +Sat Apr 29 21:42:45 2000 Tom Gilbert + + * Hrm. Actually wait for X to resize the window before rendering + the pixmap, or the resize sometimes gets delayed... + +Sat Apr 29 04:52:20 2000 Tom Gilbert + + * Heh. Sanely handle deleting the only/last image in the + slideshow. + +Thu Apr 27 16:10:35 2000 Tom Gilbert + + * You can delete files using ctrl-del in multiwindow mode too now. + * Smoothing now occurs as soon as you stop zooming. This also + massively tidied the event loop and killed a couple of nasty + globals. + +Thu Apr 27 14:39:44 2000 Tom Gilbert + + * Spilt off the part of main_loop which loops for ever from the + part that responds to events. I now have a feh_main_iteration that + processes events and returns afterwards. This means I can process + events from outside the main loop. I'm gonna use this and the + new interruptable progressive loaders to do funky stuff soon ;-) + +Thu Apr 27 03:29:33 2000 Tom Gilbert + + * Progressive loading api change. + +Tue Apr 25 01:41:52 2000 Tom Gilbert + + * I'm bored, and a little drunk, so I made it pass -pedantic, for + kicks. + +Mon Apr 24 22:29:52 2000 Tom Gilbert + + * Make sure nothing's cached. + +Mon Apr 24 19:53:23 2000 Tom Gilbert + + * Changed some of the debugging macros. + * Found and fixed wasted extra loops in option file parsing. + +Mon Apr 24 16:48:15 2000 Tom Gilbert + + * Feh is hereby rereleased under a less restrictive license. Much + as I want to propagate Free software, I don't want to be a Free + software Nazi. Do with it what you wish. + * Various fixups, tweaks, and readability improvements. + +Mon Apr 24 04:47:44 2000 Tom Gilbert + + * Finally got off my arse and made the text center under the + images in index mode. + +Mon Apr 24 04:21:49 2000 Tom Gilbert + + * Now that I have the config file, feh can safely be called + without any paramters, they can all be defined in the theme. + This leaves my: + if(argc < 2) show_usage(); + looking pretty stupid. + +Mon Apr 24 03:53:16 2000 Tom Gilbert + + * Added --fontpath, to allow an extra directory to be specified in + which to look for fonts. You can add this to /etc/fehrc or + ~/.fehrc to make it permanent. Something like: + feh --fontpath /usr/share/ttfonts + +Sat Apr 22 01:48:46 2000 Tom Gilbert + + * A slideshow delay of zero is now permitted. It means "go as fast + as you can". I like it ;-) You can pause with the middle mouse + button. + +Wed Apr 19 19:42:45 2000 Tom Gilbert + + * Added -g, --collage. Collage mode is like montage mode, except + the image thumbnails are distributed randomly. Run test26 for an + example. + +Tue Apr 11 18:20:21 2000 Tom Gilbert + + * Make included getopt actually work if needed :) + +Sat Mar 25 17:42:43 2000 Tom Gilbert + + * Event loop and zooming tweak. + +Sat Mar 25 02:09:08 2000 Tom Gilbert + + * Okay, well, seeing as feh isn't resize-friendly (it's just not + designed for it - use gimp for that stuff ;), I'm disabling + resizing of the window. Bite me :) + +Fri Mar 24 19:22:51 2000 Tom Gilbert + + * Muhahaha. Config file. It had to be done, there are so many + options now. This is totally optional of course, if you don't + create one, you'll never notice the difference. Here's how it + works... + * If ~/.fehrc exists, or if not, but /etc/fehrc exists, feh will + look in it for name/options pairs. An example entry would be: + imagemap -rVq --thumb-width 40 --thumb-height 30 + * You can use the theme in two ways. Either + feh -C themename [images] + or you can create a symbolic link to feh with the name of the + options you want it to use. So from the example above: + ln -s `which feh` ~/bin/imagemap + Now I just run 'imagemap' to use those options. + A cooler example is + mkindex -iO index.jpg --title-font 20thcent/24 . + Notice the '.' at the end. + Now with a symlink I can create a mkindex command which will + create an index.jpg in the current directory. I just run: + $ mkindex. + * An example.fehrc is provided with a couple of cool examples. + +Fri Mar 24 19:17:27 2000 Tom Gilbert + + * Slightly increased the default index mode font size. + +Fri Mar 24 16:59:28 2000 Tom Gilbert + + * Modified index mode to only show the image name below each + thumbnail, and added -I, --fullindex mode to provide the other + info (size, dimensions). Squashed a bug where the index print was + always made 30 pixels too tall ;) + +Thu Mar 23 22:45:15 2000 Tom Gilbert + + * Feh will now read options from the environment variable + FEH_OPTIONS if it is set. These options will be loaded before + commandline ones, and so can be overidden. The syntax is the same + as the commandline, so multiples are allowed (eg "-Vq -Sname") + I would recommend export FEH_OPTIONS="-Vq" as being quite handy. + +Wed Mar 22 22:52:53 2000 Tom Gilbert + + * Well, it might be an idea to tell wget to ignore server-cached + data when reloading webcams :) + DOH! + +Wed Mar 22 19:57:04 2000 Tom Gilbert + + * Better man page. Examples of cool usage. + +Wed Mar 22 18:17:11 2000 Tom Gilbert + + * Man page! Whee! + +Wed Mar 22 04:14:12 2000 Tom Gilbert + + * Added format specifiers for actions. %w width, %h height, %p + pixels, %s size, %t type (jpeg etc). + +Wed Mar 22 03:50:24 2000 Tom Gilbert + + * User definable actions for slideshow and multiwindow modes. Use + -X or --action STRING to define an action. The action will be run + when the ENTER key is pressed. The action should be in the form of + a shell command, using %f to represent the image filename + (including path), and %n to refer to it's name. Example: + feh -X "mv %f ~/images/%n" + Use this to go through some images and pick out the good ones :) + More format specifiers will follow... + +Wed Mar 22 02:55:37 2000 Tom Gilbert + + * Okay. I found a naughty bug of mine. If the last image of a + montage/index was not loadable - core was dumped. Nice bug. Fun to + find =) I blame redhat. + +Tue Mar 21 15:45:02 2000 Tom Gilbert + + * Major cruft removal and tidying of code path. Progressive + loading code slightly less complex now. + +Tue Mar 21 15:18:08 2000 Tom Gilbert + + * Big optimisation for progressive loading in fullscreen mode. I + was recreating the pixmap at every iteration - damnit ;) + +Mon Mar 20 21:54:22 2000 Tom Gilbert + + * Dammit. Why do I find these things *after* a release? + +Mon Mar 20 19:24:46 2000 Tom Gilbert + + * Released 0.7.0 + +Sun Mar 19 20:55:57 2000 Tom Gilbert + + * Main event loop tidy up. + +Sat Mar 18 21:59:55 2000 Tom Gilbert + + * Added a coupla more tests... + +Sat Mar 18 21:56:08 2000 Tom Gilbert + + * Fixed stupid segfault using --list when there are no loadable + images. + +Sat Mar 18 14:06:08 2000 Tom Gilbert + + * --list tidy up. + +Sat Mar 18 02:56:03 2000 Tom Gilbert + + * More --verbose twiddles. + +Sat Mar 18 02:18:39 2000 Tom Gilbert + + * Made the --verbose output more useful, and prettier ;) + +Sat Mar 18 00:37:17 2000 Tom Gilbert + + * Made the -V, --verbose option give cooler output on loading + mulitple images. It's pretty flim now. + +Sat Mar 18 00:32:42 2000 Tom Gilbert + + * Added -U, --loadables, and -u, --unloadables. They don't show + images, just list all the files from the filelist that are + loadable or unloadable, respectively. + +Fri Mar 17 22:58:14 2000 Tom Gilbert + + * Don't need to create checkerboard for list mode, montage mode, + index mode, etc... + +Fri Mar 17 22:43:27 2000 Tom Gilbert + + * We don't need to allocate space for the file info unless we + intend to use it. Saves RAM on big file lists... + +Fri Mar 17 22:18:50 2000 Tom Gilbert + + * Big changes. I am tired ;) + * You can now sort the filelist in any mode. + * Sorting by name/filename is *fast* + * Sorting by image properties such as width, height, type etc + incurs a delay at startup while the images are preloaded. This + could get big for large lists of files. + * Added a -p, --preload option to force preloading before running + a slideshow. This weeds out images that imlib2 can't load so that + the initial number of slides is accurate. Normally, the bad/non + images are weeded out as you go, causing the number of slides to + update as things go. Preload is great for montage and index modes, + as it ensures the correctly sized space is allocated for the + images/thumbnails/whatever. + +Fri Mar 17 19:22:18 2000 Tom Gilbert + + * List modes can now sort by image info using -S, --sort. Allowed + sort modes are width, height, pixels, size, format, name, + filename. Default sort mode is none (ie order specified/read). + * eg. feh -lSpixels * to see the highest resolution images... + +Fri Mar 17 18:04:03 2000 Tom Gilbert + + * Added -L, --longlist to allow for more detailed listings. Lists + are sorted by filename now too. (Until I write more sorting + options...) + +Thu Mar 16 19:47:16 2000 Tom Gilbert + + * Slightly cleaner --list stuff... + +Thu Mar 16 17:46:39 2000 Tom Gilbert + + * Added -l, --list mode. Doesn't display images, just analyses + them a little and spits out an 'ls' style listing with some basic + info. Useful in scripts. I intend to extend this somewhat soon. + +Thu Mar 16 16:40:19 2000 Tom Gilbert + + * Added -q, --quiet option. Stops non-fatal image load errors + being reported. Useful when you want to do feh * on a directory + with some images, some other stuff. You'll only see what imlib2 + can load. + +Wed Mar 15 21:32:48 2000 Tom Gilbert + + * Fixed bug using the short versions of --limit-width and + --limit-height + +Wed Mar 15 21:17:26 2000 Tom Gilbert + + * Better still. Font size increases in fullscreen mode, but -d + works in windowed modes too now. + +Wed Mar 15 20:58:50 2000 Tom Gilbert + + * Hrm. Much better. + +Wed Mar 15 20:36:54 2000 Tom Gilbert + + * Added -d, --draw_filename for use with fullscreen mode. It + sticks the filename up in the top left. Needs some more work yet. + +Sat Mar 11 23:35:20 2000 Tom Gilbert + + * Added proper commandline option parsing courtesy of getopt_long + :) Obviously not everyone has this, so I include it myself. Now + you can combine args in nice ways: "feh -kR20 http://some.webcam" + * It passes "make test" okay, but I reserve the right to have + broken something =) Let me know? + +Sat Mar 11 01:34:36 2000 Tom Gilbert + + * 0.6.4 released + +Tue Mar 7 23:07:40 2000 Tom Gilbert + + * Fixed evil segv due to uninitialised gc. + +Sat Mar 4 16:33:29 2000 Tom Gilbert + + * --help output for the new options. + * Added --booth, with is a shortcut for a fullscreen slideshow + with an auto-change every 20 seconds... + +Sat Mar 4 15:59:44 2000 Tom Gilbert + + * Bah. Disabled zooming in fullscreen mode for now. I'll do the + math and fix it later. + * I think I'm gonna have to rewrite shedloads of it to support + window resizing etc... + +Sat Mar 4 14:46:42 2000 Tom Gilbert + + * Fixed progressive loading in fullscreen mode. Those callbacks + *are* on crack, but for them to make sense would be a big rewrite + I don't have time for now =) + * Unfortunately, zooming in fullscreen mode is broken, I'm looking + at this now. Also, I get a weird segv when I do "feh -F directory" + but not when I do "feh -F file" or "feh -F file1 file2", and not + when I do "feh directory" or "feh -b directory" etc. I'm trying to + work this out, but the fullscreen thing should be independent of + the filelist thing... + +Fri Mar 3 22:44:25 PST 2000 Michael Jennings + + * Added two new options. --randomize will take the file list and + rearrange it into a random order. --full-screen or -F will create + a screen-sized borderless window (akin to a screensaver) and will + center the image within it. NOTE: At this point, full screen mode + only works if you disable the progressive callback. I'm waaaay too + tired right now to try to make sense out of gilbertt's callback + logic. :-) I'll try to fix it this weekend if he doesn't beat me + to it. + +Wed Mar 1 15:13:04 PST 2000 Michael Jennings + + * Math lib + +Sun Feb 20 15:22:00 2000 Tom Gilbert + + * Remove some crufty duplication. + +Sat Feb 19 17:11:49 2000 Tom Gilbert + + * Reduced mem usage, tuned file handling. Tidied up. + +Sat Feb 19 00:55:46 2000 Tom Gilbert + + * Added -b, --borderless option. Can you guess what it does? + +Fri Feb 18 23:51:14 2000 Tom Gilbert + + * Well, if I wasn't so dumb, I'd have realised that my last + comment only holds true for depths > 4000 or so. I don't have that + here. So, s/massive/fscking enormous/g. + * Fixed the *actual* problem, which was, of course, that I forgot + to close my damn dirents. + * Pull out the cl00bats, for I have goofed. + +Fri Feb 18 23:33:54 2000 Tom Gilbert + + * Okay, okay. I suck. There is a mild problem I have to fix when + running recursively on *massive* hierarchy's. Basically, I run out + of file descriptors :( At least it now aborts when this happens, but + I need to fix this. + +Fri Feb 18 21:13:32 2000 Tom Gilbert + + * configure.in: less stupid + +Fri Feb 18 20:51:53 2000 Tom Gilbert + + * index.c: misc tidyups + +Fri Feb 18 20:41:02 2000 Tom Gilbert + + * Misc fixes and cleanups. + +Fri Feb 18 16:34:49 2000 Tom Gilbert + + * Stupid, stupid, stupid. I am stupid. + +Thu Feb 17 23:14:09 2000 Tom Gilbert + + * Ooh. Cool. Now slideshow/deletion numbering works more sanely - + thanks to the new filelist code. + +Thu Feb 17 23:13:22 2000 Tom Gilbert + + * Hehe. That was more dumb than usual. Deleting files somewhat + destroyed the list, and caused nice segfaults. + +Thu Feb 17 22:05:40 2000 Tom Gilbert + + * More file-list fixes. + +Thu Feb 17 21:55:53 2000 Tom Gilbert + + * Note to self: if you prepend everything to a list, the resultant + list will be in reverse. You'll be needing to fix that =) + +Thu Feb 17 21:35:15 2000 Tom Gilbert + + * Thank goodness for that :) I totally reworked the file handling + code, and things are cleaner internally now. The change shouldn't + show to a user, but for me, things are better. + * I broke stuff badly with this change, and only now have I got + everything back on track. There may be issues still, but it seems + good now, and I'll keep playing with it... + +Wed Feb 9 21:59:09 2000 Tom Gilbert + + * Removed all the image modification code from feh, seeing as + dphase is working on ee2. No point duplicating everything :) + * I figure feh can view pr0n, while ee2 modifies it :) Something + like that, anyway. + * I never wanted the modification stuff in here really, it was + just feature creep. Feh is a viewer and montager. That is all :) + +Tue Jan 11 21:11:11 2000 Tom Gilbert + + * Hrm. Just so you know what order they come in, the images are + now saved in /tmp (actually whatever tempdir is set up on your + system) in the format "number"_"unique bit"_"original filename" + +Tue Jan 11 20:52:19 2000 Tom Gilbert + + * Okay. The cached images are now deleted. The filenames are no + longer crap. ("Unique prefix"_feh_"original filename") + * New option -k, --keep-http, tell feh *not* to delete the files, + so that you can later claim them from /tmp. Saves you + downloading them again if you like them. + * A happy side effect of this is that if you use -k and -R to keep + http and reload, and point the thing at a webcam, you'll capture + each frame and save it as a separate image. + * I *can't* imagine why anyone would *want* that, but I thought + I'd pass it on ;-) + +Tue Jan 11 19:51:40 2000 Tom Gilbert + + * Caching of images loaded via http. When in slideshow mode, and + the --reload option is not specified, a file loaded by http will + be stored in /tmp to avoid reloading from the web it every time + you loop through the slideshow or whatever. + * The --reload option disables caching + * Right now, the cached images are left in temp with crap + filenames. I'm gonna fix it up so that they are normally deleted + on program exit, but there will be an option to save them to the + current directory. (So you still have the images after viewing + them). + +Tue Jan 11 19:07:07 2000 Tom Gilbert + + * New option, -R, --reload. Lets you specify a time in seconds, + feh will reload the image for you after this time. This works for + normal files and urls. The image will not be cached, so it is + ideal for viewing webcam images etc. + +Mon Jan 10 22:48:46 2000 Tom Gilbert + + * Whee. Now feh can load images from urls. + * Specify an image starting with http:// and feh will use wget to + load the image, store it in a temporary file and view it. + * You must have wget installed for this to work. + * I have some optimisations to add, the image is currently not + cached, so if you have http files in a slideshow, they will reload + each time you get to them ;) I'll do this soon. + +Sat Jan 8 18:44:05 2000 Tom Gilbert + + * Finally got around to adding timers to feh. Now there is a new + option, -D, or --slideshow-delay NUM. NUM is the time in seconds + between changing slides for you. There is a new test to + demonstrate this option. + * The timer will pause while you zoom, and will be reset if you + change slides yourself. + * The timers code is loosely based on raster's epplet timer + code, 'cos its cool. No need to re-invent the wheel ;) + +Mon Jan 3 18:29:46 2000 Tom Gilbert + + * Okay. feh is now capable of some minor touch-ups. Nothing major, + and no image saving yet, but it tests the selection and + modification code. + * We're not writing a full-blown editor here... The idea is to + browse through your images, select one, make minor changes if you + want, then set it as your desktop background. + * To test, toggle the various modes and use the left mouse button + to use 'em. + * 'c' - crop image to rectangle + * 'o' - increase contrast of rectangle + * 'b' - increase brightness of rectangle + * 'g' - increase gamma of rectangle + * 'Escape' - exit modification mode. + * I'll leave the rest of the modification stuff to Andrew ;-) I + guess maybe we should have some persistant rectangle selections, + but I don't want to go too far. + +Sat Jan 1 22:25:49 2000 Tom Gilbert + + * I prefer LineOnOffDash drawing more for selections :) + +Sat Jan 1 22:12:37 2000 Tom Gilbert + + * I'm alive!!! Somewhat hungover though ;) + * So, some changes to the rectangle selection code, some by + Andrew, some by me :) Again, press 'r' to test it. + +Sun Dec 26 22:57:53 1999 Tom Gilbert + + * Take the gc creation out of the loop, as much as poss. + * Is xmas over now? + * Am I still drunk? + +Fri Dec 24 13:22:19 1999 Tom Gilbert + + * I've switched to using XFindContext et al to associate X Windows + with internal structures. Much faster than my rubbish list + searching. + * Dammit. Why don't people tell me you can *do* stuff like this ;) + +Fri Dec 24 01:01:49 1999 Tom Gilbert + + * And now we can crop :) Thanks Andrew. + +Thu Dec 23 20:45:39 1999 Tom Gilbert + + * We can now draw selection rectangles on windows using XORed + lines. This rules. Once the editing functions and menus are in + place, we'll use them to do stuff :) + * For now, press r to toggle line drawing, so you can see it for + yourself. Click and drag lmb to see. + +Wed Dec 22 23:37:27 1999 Tom Gilbert + + * More stuff from Andrew (hoss), we're starting to add stuff for + drawing rectangles, applying mods to rectangles, setting + backgrounds (under any wm) and other stuff like that. + +Wed Dec 22 21:49:10 1999 Tom Gilbert + + * Memory usage down by ONE THIRD :) + * I finally did the checkerboard bg thing the Right Way, and saved + lots of wasted RAM. Hooray. + +Wed Dec 22 20:47:11 1999 Tom Gilbert + + * And now index mode has a go at recommending the image size for + you, if you specify one too small. + +Wed Dec 22 18:23:42 1999 Tom Gilbert + + * Hehe. Found it. Little bugger. *squish* + +Wed Dec 22 18:12:43 1999 Tom Gilbert + + * More modify.c submissions from Andrew, including the start of + some very funky background setting and image scaling ::) + * A total rewrite of the index generating code to take into + account the font size and string length. The old version was + pretty unflim, so its nice to clean it up a bit. However, the niew + code still has a couple of issues, which I am looking into. + +Wed Dec 22 13:21:12 1999 Tom Gilbert + + * Okay, index mode now kinda takes into account the height of the + font you use. Width is on its way, but is more tricky. + +Wed Dec 22 02:17:01 1999 Michael Jennings + + * Removed a warning, and added "make testclean" + +Tue Dec 21 23:28:20 1999 Tom Gilbert + + * More modify.c submissions from Andrew, and some initial menu + work. The menus are not compiled in right now, and would core if I + did, so don't touch 'em for now :) They are only 5 mins work atm. + * I have #ifdef'ed out the code which uses X86VidMode extensions + until I can find out how common it is not to have them :) + +Tue Dec 21 18:40:39 1999 Tom Gilbert + + * The winwidget_rerender_image() function now checks for changed + dimensions and acts accordingly, and the rotate() function now + updates the width and height attributes. The modify.c functions + are now available for testing using 1-9, 0, -, = key presses. + +Tue Dec 21 18:01:15 1999 Tom Gilbert + + * Encorporated modify.c, contributed by Andrew Glover + . These functions wrap imlib2 modification + functions, and will be handy when I make some menus :) We'll be + able to do scaling, tiling, color modifiers, and more. + +Tue Dec 21 03:28:30 1999 Tom Gilbert + + * And now the thing won't go mad when you hold down a change-slide + button in Slideshow mode... Before it stored *all* the KeyPresses + and responded to *all* of them. Hehe. It was fun watching it go + round though :) + +Mon Dec 20 17:35:25 1999 Tom Gilbert + + * Hehe. Ooops. I only need to blend on zoom if the image *has* an + alpha channel. Hehe. Ok, now zooming is *much* faster and + smoother, and I am slightly less of an idiot. + +Mon Dec 20 16:46:58 1999 Tom Gilbert + + * Okay, I'm still a newbie at this X stuff :) Made some + optimisations to the main loop which speed things up a + bunch. + * Added better error handling when loading images. + * The Q or q key can now be used to exit the app in any mode. + +Mon Dec 20 15:22:43 1999 Tom Gilbert + + * Added some utility functions, so I don't have to write + if((s=malloc(blah))==NULL){fprintf("oops\n");exit(2);} + 15 million times. It really bugs me ;-) + +Mon Dec 20 12:53:28 1999 Tom Gilbert + + * Hehe. I like slideshow mode so much its now the default :) + Having multiple images pop up one-per-window can be quite evil, so + Slideshow mode is prefered. To open multiple images + one-per-window, you now need to specify -w or -multiwindow. + * I also fixed a couple of things, lowered slideshow overhead, + tightened up the main loop somewhat, and a coupla things really + late last night which I can't remember ;-) + +Sun Dec 19 22:06:43 1999 Tom Gilbert + + * For packaging reasons, I have changed the scripts to run feh in + the current dir, if it is there, but to fall back on the installed + copy. + +Sun Dec 19 20:29:33 1999 Tom Gilbert + + * Added a .spec file for feh. Contributed by Alistair Sutton + , (who is obviously a metallica fan ;), + and has written specs for me before ::) Thanks dude :) + * Urm. I haven't actually tested this yet :) + +Sun Dec 19 18:55:39 1999 Tom Gilbert + + * Slideshow mode now has keyboard control ::) + Mouse button 1 still changes slides, but you now have: + p, P, , Goto previous slide + n, N, , Goto next slide + Goto first slide + Goto last slide + Delete the file currently being viewed + q, Q Quit the slideshow + + More to come. + +Sun Dec 19 15:43:07 1999 Tom Gilbert + + * Big performance improvements in the main loop. Squashed another + couple of bugs, and made things real stable. Tightened up the + tests somewhat, and split the source up more clearly. + +Sun Dec 19 02:58:35 1999 Tom Gilbert + + * Fixed a number of bugs introduced by the new progressive loading + and zooming code ::) + +Sat Dec 18 22:11:02 1999 Tom Gilbert + + * Whee. Progressive loading works :) It can be disabled with -P, + --noprogressive, if you don't want it. Can't think why though. It + rocks. Thanks again go to Raster. Progressive loading callbacks + *rule*. + +Sat Dec 18 18:15:18 1999 Tom Gilbert + + * The fonts are now installed, and loaded from the installation + directory. + +Sat Dec 18 15:45:39 1999 Tom Gilbert + + * Okay then, there is now a checkerboard background when + zooming out. There is a more memory efficent way of doing this, + but I'll do that later... + +Sat Dec 18 14:31:58 1999 Tom Gilbert + + * Wheeeee! Thanks to Raster's example code, we now have zooming + Raster, you are my hero :) + So, middle-mouse button and drag -> zoom. + There are some things to tidy up (eg adding a background when + zooming out), but these are trivial compared to getting the + zooming working with multiple windows, which I just did ::) + +Fri Dec 17 22:00:57 1999 Tom Gilbert + + * Added titles to index prints. A title will only be printed if + you specify --title-font. + +Fri Dec 17 21:33:55 1999 Michael Jennings + + * Added "make test" to run the test scripts one by one. + +Fri Dec 17 21:32:16 1999 Tom Gilbert + + * Added more info the the index output :) Try test14 now :) + +Fri Dec 17 21:01:21 1999 Tom Gilbert + + * Added a couple of fonts, found one small for doing index prints, + tidied the directory structure a bit. + +Fri Dec 17 18:37:14 1999 Tom Gilbert + + * Added some new options, here's an excerpt from --help + -S, --slideshow Enable slideshow mode. With this setting, instead + of opening multiple windows for multiple image + files, one window will be opened. Press mouse + button one to flick through the images. + -i, --index Enable Index mode. Index mode is similar to + montage mode, and accepts the same options. It + creates an index print of thumbails, printing user- + defined information beneath each thumbnail. Index + mode enables certain other options, see INDEX MODE + OPTIONS + -f FONT Use FONT to print the information under each + thumbnail. FONT should be defined in the form + fontname/size(points). eg -f myfont/12 + Now all I need is a font which is legible in very small point :) + I also added a couple of new tests for these options. + +Fri Dec 17 03:09:46 1999 Tom Gilbert + + * Made the test scripts more verbose. It appears that people who + run a test called test07_bork_non_image_files still expect it to + work ;) hehe. + +Fri Dec 17 02:09:20 1999 Tom Gilbert + + * Right-clicking in multi-image mode now closes ALL windows. I'll + add a popup menu soon. + +Thu Dec 16 22:58:21 1999 Tom Gilbert + + * Changed --help output to fit into 80 characters... + +Thu Dec 16 22:10:50 1999 Tom Gilbert + + * Initial import. Feh is currently at 0.5.0 release level. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..d082a96 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,26 @@ +## Process this file with automake to produce Makefile.in + +AUTOMAKE_OPTIONS = 1.4 foreign + +# A list of all the files in the current directory which can be regenerated +MAINTAINERCLEANFILES = Makefile.in feh.spec + +LDFLAGS = -L/usr/X11R6/lib -L/usr/lib -L/usr/local/lib +INCLUDES = -I/usr/X11R6/include \ +$(X_CFLAGS) -I$(prefix)/include -I$(includedir) -I. + +man_MANS = feh.1 + +docs_DATA = README AUTHORS ChangeLog TODO +docsdir = $(prefix)/doc/feh + +EXTRA_DIST = \ +feh.spec feh.1 $(docs_DATA) + +SUBDIRS = src cam + +test: + (cd src && $(MAKE) test) + +testclean: + (cd src && $(MAKE) testclean) diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..ddaec8f --- /dev/null +++ b/Makefile.in @@ -0,0 +1,454 @@ +# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CC = @CC@ +GIBLIB_CFLAGS = @GIBLIB_CFLAGS@ +GIBLIB_LIBS = @GIBLIB_LIBS@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_CONFIG = @GTK_CONFIG@ +GTK_LIBS = @GTK_LIBS@ +HAVE_LIB = @HAVE_LIB@ +HAVE_XINERAMA = @HAVE_XINERAMA@ +IMLIB_CFLAGS = @IMLIB_CFLAGS@ +IMLIB_LIBS = @IMLIB_LIBS@ +LIB = @LIB@ +LTLIB = @LTLIB@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +PACKAGE = @PACKAGE@ +UP = @UP@ +VERSION = @VERSION@ +XINERAMA_LIBS = @XINERAMA_LIBS@ + +AUTOMAKE_OPTIONS = 1.4 foreign + +# A list of all the files in the current directory which can be regenerated +MAINTAINERCLEANFILES = Makefile.in feh.spec + +LDFLAGS = -L/usr/X11R6/lib -L/usr/lib -L/usr/local/lib +INCLUDES = -I/usr/X11R6/include $(X_CFLAGS) -I$(prefix)/include -I$(includedir) -I. + + +man_MANS = feh.1 + +docs_DATA = README AUTHORS ChangeLog TODO +docsdir = $(prefix)/doc/feh + +EXTRA_DIST = feh.spec feh.1 $(docs_DATA) + + +SUBDIRS = src cam +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ./src/config.h +CONFIG_CLEAN_FILES = feh.spec +man1dir = $(mandir)/man1 +MANS = $(man_MANS) + +NROFF = nroff +DATA = $(docs_DATA) + +DIST_COMMON = README AUTHORS COPYING ChangeLog Makefile.am Makefile.in \ +TODO acinclude.m4 aclocal.m4 config.guess config.sub configure \ +configure.ac configure.in feh.spec.in install-sh missing mkinstalldirs \ +src/config.h.in src/stamp-h.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +all: all-redirect +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.ac acinclude.m4 + cd $(srcdir) && $(ACLOCAL) + +config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.ac $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +src/config.h: src/stamp-h + @if test ! -f $@; then \ + rm -f src/stamp-h; \ + $(MAKE) src/stamp-h; \ + else :; fi +src/stamp-h: $(srcdir)/src/config.h.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES= CONFIG_HEADERS=src/config.h \ + $(SHELL) ./config.status + @echo timestamp > src/stamp-h 2> /dev/null +$(srcdir)/src/config.h.in: @MAINTAINER_MODE_TRUE@$(srcdir)/src/stamp-h.in + @if test ! -f $@; then \ + rm -f $(srcdir)/src/stamp-h.in; \ + $(MAKE) $(srcdir)/src/stamp-h.in; \ + else :; fi +$(srcdir)/src/stamp-h.in: $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOHEADER) + @echo timestamp > $(srcdir)/src/stamp-h.in 2> /dev/null + +mostlyclean-hdr: + +clean-hdr: + +distclean-hdr: + -rm -f src/config.h + +maintainer-clean-hdr: +feh.spec: $(top_builddir)/config.status feh.spec.in + cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +install-man1: + $(mkinstalldirs) $(DESTDIR)$(man1dir) + @list='$(man1_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \ + done + +uninstall-man1: + @list='$(man1_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \ + rm -f $(DESTDIR)$(man1dir)/$$inst; \ + done +install-man: $(MANS) + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-man1 +uninstall-man: + @$(NORMAL_UNINSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-man1 + +install-docsDATA: $(docs_DATA) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(docsdir) + @list='$(docs_DATA)'; for p in $$list; do \ + if test -f $(srcdir)/$$p; then \ + echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(docsdir)/$$p"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(docsdir)/$$p; \ + else if test -f $$p; then \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(docsdir)/$$p"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(docsdir)/$$p; \ + fi; fi; \ + done + +uninstall-docsDATA: + @$(NORMAL_UNINSTALL) + list='$(docs_DATA)'; for p in $$list; do \ + rm -f $(DESTDIR)$(docsdir)/$$p; \ + done + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. + +@SET_MAKE@ + +all-recursive install-data-recursive install-exec-recursive \ +installdirs-recursive install-recursive uninstall-recursive \ +check-recursive installcheck-recursive info-recursive dvi-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ + rev="$$subdir $$rev"; \ + test "$$subdir" != "." || dot_seen=yes; \ + done; \ + test "$$dot_seen" = "no" && rev=". $$rev"; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP)) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -rm -rf $(distdir) + GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + dc_install_base=`cd $(distdir)/=inst && pwd`; \ + cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) dist + -rm -rf $(distdir) + @banner="$(distdir).tar.gz is ready for distribution"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes" +dist: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +dist-all: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +distdir: $(DISTFILES) + -rm -rf $(distdir) + mkdir $(distdir) + -chmod 777 $(distdir) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + for subdir in $(SUBDIRS); do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \ + || exit 1; \ + fi; \ + done +info-am: +info: info-recursive +dvi-am: +dvi: dvi-recursive +check-am: all-am +check: check-recursive +installcheck-am: +installcheck: installcheck-recursive +install-exec-am: +install-exec: install-exec-recursive + +install-data-am: install-man install-docsDATA +install-data: install-data-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-recursive +uninstall-am: uninstall-man uninstall-docsDATA +uninstall: uninstall-recursive +all-am: Makefile $(MANS) $(DATA) +all-redirect: all-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: installdirs-recursive +installdirs-am: + $(mkinstalldirs) $(DESTDIR)$(mandir)/man1 $(DESTDIR)$(docsdir) + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +mostlyclean-am: mostlyclean-hdr mostlyclean-tags mostlyclean-generic + +mostlyclean: mostlyclean-recursive + +clean-am: clean-hdr clean-tags clean-generic mostlyclean-am + +clean: clean-recursive + +distclean-am: distclean-hdr distclean-tags distclean-generic clean-am + +distclean: distclean-recursive + -rm -f config.status + +maintainer-clean-am: maintainer-clean-hdr maintainer-clean-tags \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-recursive + -rm -f config.status + +.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ +install-man1 uninstall-man1 install-man uninstall-man \ +uninstall-docsDATA install-docsDATA install-data-recursive \ +uninstall-data-recursive install-exec-recursive \ +uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \ +all-recursive check-recursive installcheck-recursive info-recursive \ +dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \ +maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs-am \ +installdirs mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +test: + (cd src && $(MAKE) test) + +testclean: + (cd src && $(MAKE) testclean) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/README b/README new file mode 100644 index 0000000..422ae93 --- /dev/null +++ b/README @@ -0,0 +1,17 @@ +Compile: + +$ ./configure +$ make +$ su -c "make install" + +(Red hat users, use $ ./configure --prefix=/usr) + +Run the test scripts in the src directory to see it in action. + + +What is feh? + +http://linuxbrit.co.uk/feh/ + + +feh contains code provided by the Independent JPEG Group diff --git a/TODO b/TODO new file mode 100644 index 0000000..ba5b7f3 --- /dev/null +++ b/TODO @@ -0,0 +1,20 @@ +put full path in .fehbh + +caching of thumbnails doesn't seem to take thumbnail size into account. +Change sizes and you get the old thumbs.... + +specifying --action1 but not --action segv's feh. + + +Feel free to add stuff to it. I am very happy to delete any lines other +people add =P + +Option --autograb for feh to grab keyboard - so you can control feh without +having to focus it. Have to be a bit careful with this but could be useful. + +Now we have 10 --action* options, would be nice to hit a key and get a text +overlay reminder showing what each one does :p + +option to hide mouse cursor in full screen.. + +key/option/signal/timeout to totally reload filelist (rescan directories etc) diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 0000000..d54976a --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,136 @@ +dnl @synopsis AC_PATH_GENERIC(LIBRARY [, MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl +dnl Runs a LIBRARY-config script and defines LIBRARY_CFLAGS and LIBRARY_LIBS +dnl +dnl The script must support `--cflags' and `--libs' args. +dnl If MINIMUM-VERSION is specified, the script must also support the +dnl `--version' arg. +dnl If the `--with-library-[exec-]prefix' arguments to ./configure are given, +dnl it must also support `--prefix' and `--exec-prefix'. +dnl (In other words, it must be like gtk-config.) +dnl +dnl For example: +dnl +dnl AC_PATH_GENERIC(Foo, 1.0.0) +dnl +dnl would run `foo-config --version' and check that it is at least 1.0.0 +dnl +dnl If so, the following would then be defined: +dnl +dnl FOO_CFLAGS to `foo-config --cflags` +dnl FOO_LIBS to `foo-config --libs` +dnl +dnl At present there is no support for additional "MODULES" (see AM_PATH_GTK) +dnl (shamelessly stolen from gtk.m4 and then hacked around a fair amount) +dnl +dnl @author Angus Lees +dnl @version $Id: acinclude.m4,v 1.1.1.1 2004/08/24 19:12:09 gilbertt Exp $ + +AC_DEFUN(AC_PATH_GENERIC, +[dnl +dnl we're going to need uppercase, lowercase and user-friendly versions of the +dnl string `LIBRARY' +pushdef([UP], translit([$1], [a-z], [A-Z]))dnl +pushdef([DOWN], translit([$1], [A-Z], [a-z]))dnl + +dnl +dnl Get the cflags and libraries from the LIBRARY-config script +dnl +AC_ARG_WITH(DOWN-prefix,[ --with-]DOWN[-prefix=PFX Prefix where $1 is installed (optional)], + DOWN[]_config_prefix="$withval", DOWN[]_config_prefix="") +AC_ARG_WITH(DOWN-exec-prefix,[ --with-]DOWN[-exec-prefix=PFX Exec prefix where $1 is installed (optional)], + DOWN[]_config_exec_prefix="$withval", DOWN[]_config_exec_prefix="") + + if test x$DOWN[]_config_exec_prefix != x ; then + DOWN[]_config_args="$DOWN[]_config_args --exec-prefix=$DOWN[]_config_exec_prefix" + if test x${UP[]_CONFIG+set} != xset ; then + UP[]_CONFIG=$DOWN[]_config_exec_prefix/bin/DOWN-config + fi + fi + if test x$DOWN[]_config_prefix != x ; then + DOWN[]_config_args="$DOWN[]_config_args --prefix=$DOWN[]_config_prefix" + if test x${UP[]_CONFIG+set} != xset ; then + UP[]_CONFIG=$DOWN[]_config_prefix/bin/DOWN-config + fi + fi + + AC_PATH_PROG(UP[]_CONFIG, DOWN-config, no) + ifelse([$2], , + AC_MSG_CHECKING(for $1), + AC_MSG_CHECKING(for $1 - version >= $2) + ) + no_[]DOWN="" + if test "$UP[]_CONFIG" = "no" ; then + no_[]DOWN=yes + else + UP[]_CFLAGS="`$UP[]_CONFIG $DOWN[]_config_args --cflags`" + UP[]_LIBS="`$UP[]_CONFIG $DOWN[]_config_args --libs`" + ifelse([$2], , ,[ + DOWN[]_config_major_version=`$UP[]_CONFIG $DOWN[]_config_args \ + --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + DOWN[]_config_minor_version=`$UP[]_CONFIG $DOWN[]_config_args \ + --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + DOWN[]_config_micro_version=`$UP[]_CONFIG $DOWN[]_config_args \ + --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + DOWN[]_wanted_major_version="regexp($2, [\<\([0-9]*\)], [\1])" + DOWN[]_wanted_minor_version="regexp($2, [\<\([0-9]*\)\.\([0-9]*\)], [\2])" + DOWN[]_wanted_micro_version="regexp($2, [\<\([0-9]*\).\([0-9]*\).\([0-9]*\)], [\3])" + + # Compare wanted version to what config script returned. + # If I knew what library was being run, i'd probably also compile + # a test program at this point (which also extracted and tested + # the version in some library-specific way) + if test "$DOWN[]_config_major_version" -lt \ + "$DOWN[]_wanted_major_version" \ + -o \( "$DOWN[]_config_major_version" -eq \ + "$DOWN[]_wanted_major_version" \ + -a "$DOWN[]_config_minor_version" -lt \ + "$DOWN[]_wanted_minor_version" \) \ + -o \( "$DOWN[]_config_major_version" -eq \ + "$DOWN[]_wanted_major_version" \ + -a "$DOWN[]_config_minor_version" -eq \ + "$DOWN[]_wanted_minor_version" \ + -a "$DOWN[]_config_micro_version" -lt \ + "$DOWN[]_wanted_micro_version" \) ; then + # older version found + no_[]DOWN=yes + echo -n "*** An old version of $1 " + echo -n "($DOWN[]_config_major_version" + echo -n ".$DOWN[]_config_minor_version" + echo ".$DOWN[]_config_micro_version) was found." + echo -n "*** You need a version of $1 newer than " + echo -n "$DOWN[]_wanted_major_version" + echo -n ".$DOWN[]_wanted_minor_version" + echo ".$DOWN[]_wanted_micro_version." + echo "***" + echo "*** If you have already installed a sufficiently new version, this error" + echo "*** probably means that the wrong copy of the DOWN-config shell script is" + echo "*** being found. The easiest way to fix this is to remove the old version" + echo "*** of $1, but you can also set the UP[]_CONFIG environment to point to the" + echo "*** correct copy of DOWN-config. (In this case, you will have to" + echo "*** modify your LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf" + echo "*** so that the correct libraries are found at run-time)" + fi + ]) + fi + if test "x$no_[]DOWN" = x ; then + AC_MSG_RESULT(yes) + ifelse([$3], , :, [$3]) + else + AC_MSG_RESULT(no) + if test "$UP[]_CONFIG" = "no" ; then + echo "*** The DOWN-config script installed by $1 could not be found" + echo "*** If $1 was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the UP[]_CONFIG environment variable to the" + echo "*** full path to DOWN-config." + fi + UP[]_CFLAGS="" + UP[]_LIBS="" + ifelse([$4], , :, [$4]) + fi + AC_SUBST(UP[]_CFLAGS) + AC_SUBST(UP[]_LIBS) + + popdef([UP]) + popdef([DOWN]) +]) diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..93e593b --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,1448 @@ +dnl aclocal.m4 generated automatically by aclocal 1.4-p6 + +dnl Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. + +dnl @synopsis AC_PATH_GENERIC(LIBRARY [, MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl +dnl Runs a LIBRARY-config script and defines LIBRARY_CFLAGS and LIBRARY_LIBS +dnl +dnl The script must support `--cflags' and `--libs' args. +dnl If MINIMUM-VERSION is specified, the script must also support the +dnl `--version' arg. +dnl If the `--with-library-[exec-]prefix' arguments to ./configure are given, +dnl it must also support `--prefix' and `--exec-prefix'. +dnl (In other words, it must be like gtk-config.) +dnl +dnl For example: +dnl +dnl AC_PATH_GENERIC(Foo, 1.0.0) +dnl +dnl would run `foo-config --version' and check that it is at least 1.0.0 +dnl +dnl If so, the following would then be defined: +dnl +dnl FOO_CFLAGS to `foo-config --cflags` +dnl FOO_LIBS to `foo-config --libs` +dnl +dnl At present there is no support for additional "MODULES" (see AM_PATH_GTK) +dnl (shamelessly stolen from gtk.m4 and then hacked around a fair amount) +dnl +dnl @author Angus Lees +dnl @version $Id: acinclude.m4,v 1.1.1.1 2004/08/24 19:12:09 gilbertt Exp $ + +AC_DEFUN(AC_PATH_GENERIC, +[dnl +dnl we're going to need uppercase, lowercase and user-friendly versions of the +dnl string `LIBRARY' +pushdef([UP], translit([$1], [a-z], [A-Z]))dnl +pushdef([DOWN], translit([$1], [A-Z], [a-z]))dnl + +dnl +dnl Get the cflags and libraries from the LIBRARY-config script +dnl +AC_ARG_WITH(DOWN-prefix,[ --with-]DOWN[-prefix=PFX Prefix where $1 is installed (optional)], + DOWN[]_config_prefix="$withval", DOWN[]_config_prefix="") +AC_ARG_WITH(DOWN-exec-prefix,[ --with-]DOWN[-exec-prefix=PFX Exec prefix where $1 is installed (optional)], + DOWN[]_config_exec_prefix="$withval", DOWN[]_config_exec_prefix="") + + if test x$DOWN[]_config_exec_prefix != x ; then + DOWN[]_config_args="$DOWN[]_config_args --exec-prefix=$DOWN[]_config_exec_prefix" + if test x${UP[]_CONFIG+set} != xset ; then + UP[]_CONFIG=$DOWN[]_config_exec_prefix/bin/DOWN-config + fi + fi + if test x$DOWN[]_config_prefix != x ; then + DOWN[]_config_args="$DOWN[]_config_args --prefix=$DOWN[]_config_prefix" + if test x${UP[]_CONFIG+set} != xset ; then + UP[]_CONFIG=$DOWN[]_config_prefix/bin/DOWN-config + fi + fi + + AC_PATH_PROG(UP[]_CONFIG, DOWN-config, no) + ifelse([$2], , + AC_MSG_CHECKING(for $1), + AC_MSG_CHECKING(for $1 - version >= $2) + ) + no_[]DOWN="" + if test "$UP[]_CONFIG" = "no" ; then + no_[]DOWN=yes + else + UP[]_CFLAGS="`$UP[]_CONFIG $DOWN[]_config_args --cflags`" + UP[]_LIBS="`$UP[]_CONFIG $DOWN[]_config_args --libs`" + ifelse([$2], , ,[ + DOWN[]_config_major_version=`$UP[]_CONFIG $DOWN[]_config_args \ + --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + DOWN[]_config_minor_version=`$UP[]_CONFIG $DOWN[]_config_args \ + --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + DOWN[]_config_micro_version=`$UP[]_CONFIG $DOWN[]_config_args \ + --version | sed 's/[[^0-9]]*\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + DOWN[]_wanted_major_version="regexp($2, [\<\([0-9]*\)], [\1])" + DOWN[]_wanted_minor_version="regexp($2, [\<\([0-9]*\)\.\([0-9]*\)], [\2])" + DOWN[]_wanted_micro_version="regexp($2, [\<\([0-9]*\).\([0-9]*\).\([0-9]*\)], [\3])" + + # Compare wanted version to what config script returned. + # If I knew what library was being run, i'd probably also compile + # a test program at this point (which also extracted and tested + # the version in some library-specific way) + if test "$DOWN[]_config_major_version" -lt \ + "$DOWN[]_wanted_major_version" \ + -o \( "$DOWN[]_config_major_version" -eq \ + "$DOWN[]_wanted_major_version" \ + -a "$DOWN[]_config_minor_version" -lt \ + "$DOWN[]_wanted_minor_version" \) \ + -o \( "$DOWN[]_config_major_version" -eq \ + "$DOWN[]_wanted_major_version" \ + -a "$DOWN[]_config_minor_version" -eq \ + "$DOWN[]_wanted_minor_version" \ + -a "$DOWN[]_config_micro_version" -lt \ + "$DOWN[]_wanted_micro_version" \) ; then + # older version found + no_[]DOWN=yes + echo -n "*** An old version of $1 " + echo -n "($DOWN[]_config_major_version" + echo -n ".$DOWN[]_config_minor_version" + echo ".$DOWN[]_config_micro_version) was found." + echo -n "*** You need a version of $1 newer than " + echo -n "$DOWN[]_wanted_major_version" + echo -n ".$DOWN[]_wanted_minor_version" + echo ".$DOWN[]_wanted_micro_version." + echo "***" + echo "*** If you have already installed a sufficiently new version, this error" + echo "*** probably means that the wrong copy of the DOWN-config shell script is" + echo "*** being found. The easiest way to fix this is to remove the old version" + echo "*** of $1, but you can also set the UP[]_CONFIG environment to point to the" + echo "*** correct copy of DOWN-config. (In this case, you will have to" + echo "*** modify your LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf" + echo "*** so that the correct libraries are found at run-time)" + fi + ]) + fi + if test "x$no_[]DOWN" = x ; then + AC_MSG_RESULT(yes) + ifelse([$3], , :, [$3]) + else + AC_MSG_RESULT(no) + if test "$UP[]_CONFIG" = "no" ; then + echo "*** The DOWN-config script installed by $1 could not be found" + echo "*** If $1 was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the UP[]_CONFIG environment variable to the" + echo "*** full path to DOWN-config." + fi + UP[]_CFLAGS="" + UP[]_LIBS="" + ifelse([$4], , :, [$4]) + fi + AC_SUBST(UP[]_CFLAGS) + AC_SUBST(UP[]_LIBS) + + popdef([UP]) + popdef([DOWN]) +]) + +# Configure paths for GTK+ +# Owen Taylor 97-11-3 + +dnl AM_PATH_GTK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) +dnl Test for GTK, and define GTK_CFLAGS and GTK_LIBS +dnl +AC_DEFUN(AM_PATH_GTK, +[dnl +dnl Get the cflags and libraries from the gtk-config script +dnl +AC_ARG_WITH(gtk-prefix,[ --with-gtk-prefix=PFX Prefix where GTK is installed (optional)], + gtk_config_prefix="$withval", gtk_config_prefix="") +AC_ARG_WITH(gtk-exec-prefix,[ --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)], + gtk_config_exec_prefix="$withval", gtk_config_exec_prefix="") +AC_ARG_ENABLE(gtktest, [ --disable-gtktest Do not try to compile and run a test GTK program], + , enable_gtktest=yes) + + for module in . $4 + do + case "$module" in + gthread) + gtk_config_args="$gtk_config_args gthread" + ;; + esac + done + + if test x$gtk_config_exec_prefix != x ; then + gtk_config_args="$gtk_config_args --exec-prefix=$gtk_config_exec_prefix" + if test x${GTK_CONFIG+set} != xset ; then + GTK_CONFIG=$gtk_config_exec_prefix/bin/gtk-config + fi + fi + if test x$gtk_config_prefix != x ; then + gtk_config_args="$gtk_config_args --prefix=$gtk_config_prefix" + if test x${GTK_CONFIG+set} != xset ; then + GTK_CONFIG=$gtk_config_prefix/bin/gtk-config + fi + fi + + AC_PATH_PROG(GTK_CONFIG, gtk-config, no) + min_gtk_version=ifelse([$1], ,0.99.7,$1) + AC_MSG_CHECKING(for GTK - version >= $min_gtk_version) + no_gtk="" + if test "$GTK_CONFIG" = "no" ; then + no_gtk=yes + else + GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags` + GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs` + gtk_config_major_version=`$GTK_CONFIG $gtk_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + gtk_config_minor_version=`$GTK_CONFIG $gtk_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + gtk_config_micro_version=`$GTK_CONFIG $gtk_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_gtktest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $GTK_CFLAGS" + LIBS="$GTK_LIBS $LIBS" +dnl +dnl Now check if the installed GTK is sufficiently new. (Also sanity +dnl checks the results of gtk-config to some extent +dnl + rm -f conf.gtktest + AC_TRY_RUN([ +#include +#include +#include + +int +main () +{ + int major, minor, micro; + char *tmp_version; + + system ("touch conf.gtktest"); + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = g_strdup("$min_gtk_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_gtk_version"); + exit(1); + } + + if ((gtk_major_version != $gtk_config_major_version) || + (gtk_minor_version != $gtk_config_minor_version) || + (gtk_micro_version != $gtk_config_micro_version)) + { + printf("\n*** 'gtk-config --version' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n", + $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version, + gtk_major_version, gtk_minor_version, gtk_micro_version); + printf ("*** was found! If gtk-config was correct, then it is best\n"); + printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n"); + printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); + printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); + printf("*** required on your system.\n"); + printf("*** If gtk-config was wrong, set the environment variable GTK_CONFIG\n"); + printf("*** to point to the correct copy of gtk-config, and remove the file config.cache\n"); + printf("*** before re-running configure\n"); + } +#if defined (GTK_MAJOR_VERSION) && defined (GTK_MINOR_VERSION) && defined (GTK_MICRO_VERSION) + else if ((gtk_major_version != GTK_MAJOR_VERSION) || + (gtk_minor_version != GTK_MINOR_VERSION) || + (gtk_micro_version != GTK_MICRO_VERSION)) + { + printf("*** GTK+ header files (version %d.%d.%d) do not match\n", + GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION); + printf("*** library (version %d.%d.%d)\n", + gtk_major_version, gtk_minor_version, gtk_micro_version); + } +#endif /* defined (GTK_MAJOR_VERSION) ... */ + else + { + if ((gtk_major_version > major) || + ((gtk_major_version == major) && (gtk_minor_version > minor)) || + ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n", + gtk_major_version, gtk_minor_version, gtk_micro_version); + printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n", + major, minor, micro); + printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the gtk-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of GTK+, but you can also set the GTK_CONFIG environment to point to the\n"); + printf("*** correct copy of gtk-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + } + return 1; +} +],, no_gtk=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_gtk" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$GTK_CONFIG" = "no" ; then + echo "*** The gtk-config script installed by GTK could not be found" + echo "*** If GTK was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the GTK_CONFIG environment variable to the" + echo "*** full path to gtk-config." + else + if test -f conf.gtktest ; then + : + else + echo "*** Could not run GTK test program, checking why..." + CFLAGS="$CFLAGS $GTK_CFLAGS" + LIBS="$LIBS $GTK_LIBS" + AC_TRY_LINK([ +#include +#include +], [ return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version)); ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding GTK or finding the wrong" + echo "*** version of GTK. If it is not finding GTK, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" + echo "***" + echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that" + echo "*** came with the system with the command" + echo "***" + echo "*** rpm --erase --nodeps gtk gtk-devel" ], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means GTK was incorrectly installed" + echo "*** or that you have moved GTK since it was installed. In the latter case, you" + echo "*** may want to edit the gtk-config script: $GTK_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + GTK_CFLAGS="" + GTK_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GTK_CFLAGS) + AC_SUBST(GTK_LIBS) + rm -f conf.gtktest +]) + +# lib-prefix.m4 serial 4 (gettext-0.14.2) +dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and +dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't +dnl require excessive bracketing. +ifdef([AC_HELP_STRING], +[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], +[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) + +dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed +dnl to access previously installed libraries. The basic assumption is that +dnl a user will want packages to use other packages he previously installed +dnl with the same --prefix option. +dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate +dnl libraries, but is otherwise very convenient. +AC_DEFUN([AC_LIB_PREFIX], +[ + AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_LIB_ARG_WITH([lib-prefix], +[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib + --without-lib-prefix don't search for libraries in includedir and libdir], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/lib" + fi + fi +]) + if test $use_additional = yes; then + dnl Potentially add $additional_includedir to $CPPFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's already present in $CPPFLAGS, + dnl 3. if it's /usr/local/include and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + for x in $CPPFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $CPPFLAGS. + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" + fi + fi + fi + fi + dnl Potentially add $additional_libdir to $LDFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's already present in $LDFLAGS, + dnl 3. if it's /usr/local/lib and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/lib"; then + haveit= + for x in $LDFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_libdir" = "X/usr/local/lib"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LDFLAGS. + LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" + fi + fi + fi + fi + fi +]) + +dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, +dnl acl_final_exec_prefix, containing the values to which $prefix and +dnl $exec_prefix will expand at the end of the configure script. +AC_DEFUN([AC_LIB_PREPARE_PREFIX], +[ + dnl Unfortunately, prefix and exec_prefix get only finally determined + dnl at the end of configure. + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the +dnl variables prefix and exec_prefix bound to the values they will have +dnl at the end of the configure script. +AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], +[ + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + $1 + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" +]) + +# lib-link.m4 serial 6 (gettext-0.14.3) +dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_PREREQ(2.50) + +dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and +dnl augments the CPPFLAGS variable. +AC_DEFUN([AC_LIB_LINKFLAGS], +[ + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + define([Name],[translit([$1],[./-], [___])]) + define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ + AC_LIB_LINKFLAGS_BODY([$1], [$2]) + ac_cv_lib[]Name[]_libs="$LIB[]NAME" + ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" + ac_cv_lib[]Name[]_cppflags="$INC[]NAME" + ]) + LIB[]NAME="$ac_cv_lib[]Name[]_libs" + LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" + INC[]NAME="$ac_cv_lib[]Name[]_cppflags" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the + dnl results of this search when this library appears as a dependency. + HAVE_LIB[]NAME=yes + undefine([Name]) + undefine([NAME]) +]) + +dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode) +dnl searches for libname and the libraries corresponding to explicit and +dnl implicit dependencies, together with the specified include files and +dnl the ability to compile and link the specified testcode. If found, it +dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and +dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and +dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs +dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. +AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], +[ + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + define([Name],[translit([$1],[./-], [___])]) + define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + + dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([$1], [$2]) + + dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, + dnl because if the user has installed lib[]Name and not disabled its use + dnl via --without-lib[]Name-prefix, he wants to use it. + ac_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) + + AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ + ac_save_LIBS="$LIBS" + LIBS="$LIBS $LIB[]NAME" + AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no]) + LIBS="$ac_save_LIBS" + ]) + if test "$ac_cv_lib[]Name" = yes; then + HAVE_LIB[]NAME=yes + AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.]) + AC_MSG_CHECKING([how to link with lib[]$1]) + AC_MSG_RESULT([$LIB[]NAME]) + else + HAVE_LIB[]NAME=no + dnl If $LIB[]NAME didn't lead to a usable library, we don't need + dnl $INC[]NAME either. + CPPFLAGS="$ac_save_CPPFLAGS" + LIB[]NAME= + LTLIB[]NAME= + fi + AC_SUBST([HAVE_LIB]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + undefine([Name]) + undefine([NAME]) +]) + +dnl Determine the platform dependent parameters needed to use rpath: +dnl libext, shlibext, hardcode_libdir_flag_spec, hardcode_libdir_separator, +dnl hardcode_direct, hardcode_minus_L. +AC_DEFUN([AC_LIB_RPATH], +[ + dnl Tell automake >= 1.10 to complain if config.rpath is missing. + m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) + AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS + AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld + AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host + AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir + AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [ + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + ]) + wl="$acl_cv_wl" + libext="$acl_cv_libext" + shlibext="$acl_cv_shlibext" + hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + hardcode_direct="$acl_cv_hardcode_direct" + hardcode_minus_L="$acl_cv_hardcode_minus_L" + dnl Determine whether the user wants rpath handling at all. + AC_ARG_ENABLE(rpath, + [ --disable-rpath do not hardcode runtime library paths], + :, enable_rpath=yes) +]) + +dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. +AC_DEFUN([AC_LIB_LINKFLAGS_BODY], +[ + define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_LIB_ARG_WITH([lib$1-prefix], +[ --with-lib$1-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib + --without-lib$1-prefix don't search for lib$1 in includedir and libdir], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/lib" + fi + fi +]) + dnl Search the library and its dependencies in $additional_libdir and + dnl $LDFLAGS. Using breadth-first-seach. + LIB[]NAME= + LTLIB[]NAME= + INC[]NAME= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='$1 $2' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + dnl See if it was already located by an earlier AC_LIB_LINKFLAGS + dnl or AC_LIB_HAVE_LINKFLAGS call. + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" + else + dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined + dnl that this library doesn't exist. So just drop it. + : + fi + else + dnl Search the library lib$name in $additional_libdir and $LDFLAGS + dnl and the already constructed $LIBNAME/$LTLIBNAME. + found_dir= + found_la= + found_so= + found_a= + if test $use_additional = yes; then + if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then + found_dir="$additional_libdir" + found_so="$additional_libdir/lib$name.$shlibext" + if test -f "$additional_libdir/lib$name.la"; then + found_la="$additional_libdir/lib$name.la" + fi + else + if test -f "$additional_libdir/lib$name.$libext"; then + found_dir="$additional_libdir" + found_a="$additional_libdir/lib$name.$libext" + if test -f "$additional_libdir/lib$name.la"; then + found_la="$additional_libdir/lib$name.la" + fi + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then + found_dir="$dir" + found_so="$dir/lib$name.$shlibext" + if test -f "$dir/lib$name.la"; then + found_la="$dir/lib$name.la" + fi + else + if test -f "$dir/lib$name.$libext"; then + found_dir="$dir" + found_a="$dir/lib$name.$libext" + if test -f "$dir/lib$name.la"; then + found_la="$dir/lib$name.la" + fi + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + dnl Found the library. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + dnl Linking with a shared library. We attempt to hardcode its + dnl directory into the executable's runpath, unless it's the + dnl standard /usr/lib. + if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then + dnl No hardcoding is needed. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + dnl The hardcoding into $LIBNAME is system dependent. + if test "$hardcode_direct" = yes; then + dnl Using DIR/libNAME.so during linking hardcodes DIR into the + dnl resulting binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + dnl Rely on "-L$found_dir". + dnl But don't add it if it's already contained in the LDFLAGS + dnl or the already constructed $LIBNAME + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" + fi + if test "$hardcode_minus_L" != no; then + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl We cannot use $hardcode_runpath_var and LD_RUN_PATH + dnl here, because this doesn't fit in flags passed to the + dnl compiler. So give up. No hardcoding. This affects only + dnl very old systems. + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + dnl Linking with a static library. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" + else + dnl We shouldn't come here, but anyway it's good to have a + dnl fallback. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" + fi + fi + dnl Assume the include files are nearby. + additional_includedir= + case "$found_dir" in + */lib | */lib/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'` + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + dnl Potentially add $additional_includedir to $INCNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's /usr/local/include and we are using GCC on Linux, + dnl 3. if it's already present in $CPPFLAGS or the already + dnl constructed $INCNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INC[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $INCNAME. + INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + dnl Look for dependencies. + if test -n "$found_la"; then + dnl Read the .la file. It defines the variables + dnl dlname, library_names, old_library, dependency_libs, current, + dnl age, revision, installed, dlopen, dlpreopen, libdir. + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + dnl We use only dependency_libs. + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's /usr/local/lib and we are using GCC on Linux, + dnl 3. if it's already present in $LDFLAGS or the already + dnl constructed $LIBNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/lib"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/lib"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LIBNAME. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LTLIBNAME. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + dnl Handle this in the next round. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + dnl Handle this in the next round. Throw away the .la's + dnl directory; it is already contained in a preceding -L + dnl option. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + dnl Most likely an immediate library name. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" + ;; + esac + done + fi + else + dnl Didn't find the library; assume it is in the system directories + dnl known to the linker and runtime loader. (All the system + dnl directories known to the linker should also be known to the + dnl runtime loader, otherwise the system is severely misconfigured.) + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user must + dnl pass all path elements in one option. We can arrange that for a + dnl single library, but not when more than one $LIBNAMEs are used. + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" + done + dnl Note: hardcode_libdir_flag_spec uses $libdir and $wl. + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + else + dnl The -rpath options are cumulative. + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + dnl When using libtool, the option that works for both libraries and + dnl executables is -R. The -R options are cumulative. + for found_dir in $ltrpathdirs; do + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" + done + fi +]) + +dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, +dnl unless already present in VAR. +dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes +dnl contains two or three consecutive elements that belong together. +AC_DEFUN([AC_LIB_APPENDTOVAR], +[ + for element in [$2]; do + haveit= + for x in $[$1]; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + [$1]="${[$1]}${[$1]:+ }$element" + fi + done +]) + +# lib-ld.m4 serial 3 (gettext-0.13) +dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Subroutines of libtool.m4, +dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision +dnl with libtool.m4. + +dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. +AC_DEFUN([AC_LIB_PROG_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +case `$LD -v 2>&1 conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by GCC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]* | [A-Za-z]:[\\/]*)] + [re_direlt='/[^/][^/]*/\.\./'] + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(acl_cv_path_LD, +[if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break ;; + *) + test "$with_gnu_ld" != yes && break ;; + esac + fi + done + IFS="$ac_save_ifs" +else + acl_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$acl_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_LIB_PROG_LD_GNU +]) + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 1 + +dnl Usage: +dnl AM_INIT_AUTOMAKE(package,version, [no-define]) + +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL]) +PACKAGE=[$1] +AC_SUBST(PACKAGE) +VERSION=[$2] +AC_SUBST(VERSION) +dnl test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi +ifelse([$3],, +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) +AC_REQUIRE([AM_SANITY_CHECK]) +AC_REQUIRE([AC_ARG_PROGRAM]) +dnl FIXME This is truly gross. +missing_dir=`cd $ac_aux_dir && pwd` +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}, $missing_dir) +AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}, $missing_dir) +AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_REQUIRE([AC_PROG_MAKE_SET])]) + +# Copyright 2002 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.4"]) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION so it can be traced. +# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], + [AM_AUTOMAKE_VERSION([1.4-p6])]) + +# +# Check to make sure that the build environment is sane. +# + +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "[$]*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "[$]*" != "X $srcdir/configure conftestfile" \ + && test "[$]*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "[$]2" = conftestfile + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +rm -f conftest* +AC_MSG_RESULT(yes)]) + +dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) +dnl The program must properly implement --version. +AC_DEFUN([AM_MISSING_PROG], +[AC_MSG_CHECKING(for working $2) +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if ($2 --version) < /dev/null > /dev/null 2>&1; then + $1=$2 + AC_MSG_RESULT(found) +else + $1="$3/missing $2" + AC_MSG_RESULT(missing) +fi +AC_SUBST($1)]) + +# Like AC_CONFIG_HEADER, but automatically create stamp file. + +AC_DEFUN([AM_CONFIG_HEADER], +[AC_PREREQ([2.12]) +AC_CONFIG_HEADER([$1]) +dnl When config.status generates a header, we must update the stamp-h file. +dnl This file resides in the same directory as the config header +dnl that is generated. We must strip everything past the first ":", +dnl and everything past the last "/". +AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl +ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>, +<>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>, +<>; do + case " <<$>>CONFIG_HEADERS " in + *" <<$>>am_file "*<<)>> + echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx + ;; + esac + am_indx=`expr "<<$>>am_indx" + 1` +done<<>>dnl>>) +changequote([,]))]) + + +# serial 1 + +# @defmac AC_PROG_CC_STDC +# @maindex PROG_CC_STDC +# @ovindex CC +# If the C compiler in not in ANSI C mode by default, try to add an option +# to output variable @code{CC} to make it so. This macro tries various +# options that select ANSI C on some system or another. It considers the +# compiler to be in ANSI C mode if it handles function prototypes correctly. +# +# If you use this macro, you should check after calling it whether the C +# compiler has been set to accept ANSI C; if not, the shell variable +# @code{am_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source +# code in ANSI C, you can make an un-ANSIfied copy of it by using the +# program @code{ansi2knr}, which comes with Ghostscript. +# @end defmac + +AC_DEFUN([AM_PROG_CC_STDC], +[AC_REQUIRE([AC_PROG_CC]) +AC_BEFORE([$0], [AC_C_INLINE]) +AC_BEFORE([$0], [AC_C_CONST]) +dnl Force this before AC_PROG_CPP. Some cpp's, eg on HPUX, require +dnl a magic option to avoid problems with ANSI preprocessor commands +dnl like #elif. +dnl FIXME: can't do this because then AC_AIX won't work due to a +dnl circular dependency. +dnl AC_BEFORE([$0], [AC_PROG_CPP]) +AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C) +AC_CACHE_VAL(am_cv_prog_cc_stdc, +[am_cv_prog_cc_stdc=no +ac_save_CC="$CC" +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + AC_TRY_COMPILE( +[#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +], [ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; +], +[am_cv_prog_cc_stdc="$ac_arg"; break]) +done +CC="$ac_save_CC" +]) +if test -z "$am_cv_prog_cc_stdc"; then + AC_MSG_RESULT([none needed]) +else + AC_MSG_RESULT($am_cv_prog_cc_stdc) +fi +case "x$am_cv_prog_cc_stdc" in + x|xno) ;; + *) CC="$CC $am_cv_prog_cc_stdc" ;; +esac +]) + +# Add --enable-maintainer-mode option to configure. +# From Jim Meyering + +# serial 1 + +AC_DEFUN([AM_MAINTAINER_MODE], +[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode is disabled by default + AC_ARG_ENABLE(maintainer-mode, +[ --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + USE_MAINTAINER_MODE=$enableval, + USE_MAINTAINER_MODE=no) + AC_MSG_RESULT($USE_MAINTAINER_MODE) + AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST(MAINT)dnl +] +) + +# Define a conditional. + +AC_DEFUN([AM_CONDITIONAL], +[AC_SUBST($1_TRUE) +AC_SUBST($1_FALSE) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi]) + + +# serial 1 + +AC_DEFUN([AM_WITH_DMALLOC], +[AC_MSG_CHECKING(if malloc debugging is wanted) +AC_ARG_WITH(dmalloc, +[ --with-dmalloc use dmalloc, as in + ftp://ftp.letters.com/src/dmalloc/dmalloc.tar.gz], +[if test "$withval" = yes; then + AC_MSG_RESULT(yes) + AC_DEFINE(WITH_DMALLOC,1, + [Define if using the dmalloc debugging malloc package]) + LIBS="$LIBS -ldmalloc" + LDFLAGS="$LDFLAGS -g" +else + AC_MSG_RESULT(no) +fi], [AC_MSG_RESULT(no)]) +]) + diff --git a/cam/ChangeLog b/cam/ChangeLog new file mode 100644 index 0000000..4a562bd --- /dev/null +++ b/cam/ChangeLog @@ -0,0 +1,14 @@ +0.3 +--- +- added this changelog.. + +0.4 +--- +- added richlowe's patch. since he pretty much rewrote everything, he's +an author, not a contributor. :) +- uses "use strict" now +- uses POD for documentation +- added title support in cam bookmarks file +- cmd line flag for different bookmars file +- getoppt_long use for command-line flags +- rmeoved richlow's damn nonstandard Pod::Usage stuff diff --git a/cam/Makefile.am b/cam/Makefile.am new file mode 100644 index 0000000..fb14a22 --- /dev/null +++ b/cam/Makefile.am @@ -0,0 +1,11 @@ +## Process this file with automake to produce Makefile.in + +AUTOMAKE_OPTIONS = 1.4 foreign + +# A list of all the files in the current directory which can be regenerated +MAINTAINERCLEANFILES = Makefile.in + +EXTRA_DIST = README cam_bookmarks cam gen_cam_menu.sh + +camdir = $(bindir) +cam_SCRIPTS = cam gen_cam_menu.sh diff --git a/cam/Makefile.in b/cam/Makefile.in new file mode 100644 index 0000000..97f79ca --- /dev/null +++ b/cam/Makefile.in @@ -0,0 +1,214 @@ +# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CC = @CC@ +GIBLIB_CFLAGS = @GIBLIB_CFLAGS@ +GIBLIB_LIBS = @GIBLIB_LIBS@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_CONFIG = @GTK_CONFIG@ +GTK_LIBS = @GTK_LIBS@ +HAVE_LIB = @HAVE_LIB@ +HAVE_XINERAMA = @HAVE_XINERAMA@ +IMLIB_CFLAGS = @IMLIB_CFLAGS@ +IMLIB_LIBS = @IMLIB_LIBS@ +LIB = @LIB@ +LTLIB = @LTLIB@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +PACKAGE = @PACKAGE@ +UP = @UP@ +VERSION = @VERSION@ +XINERAMA_LIBS = @XINERAMA_LIBS@ + +AUTOMAKE_OPTIONS = 1.4 foreign + +# A list of all the files in the current directory which can be regenerated +MAINTAINERCLEANFILES = Makefile.in + +EXTRA_DIST = README cam_bookmarks cam gen_cam_menu.sh + +camdir = $(bindir) +cam_SCRIPTS = cam gen_cam_menu.sh +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../src/config.h +CONFIG_CLEAN_FILES = +SCRIPTS = $(cam_SCRIPTS) + +DIST_COMMON = README ChangeLog Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +all: all-redirect +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps cam/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +install-camSCRIPTS: $(cam_SCRIPTS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(camdir) + @list='$(cam_SCRIPTS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_SCRIPT) $$p $(DESTDIR)$(camdir)/`echo $$p|sed '$(transform)'`"; \ + $(INSTALL_SCRIPT) $$p $(DESTDIR)$(camdir)/`echo $$p|sed '$(transform)'`; \ + else if test -f $(srcdir)/$$p; then \ + echo " $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(camdir)/`echo $$p|sed '$(transform)'`"; \ + $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(camdir)/`echo $$p|sed '$(transform)'`; \ + else :; fi; fi; \ + done + +uninstall-camSCRIPTS: + @$(NORMAL_UNINSTALL) + list='$(cam_SCRIPTS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(camdir)/`echo $$p|sed '$(transform)'`; \ + done +tags: TAGS +TAGS: + + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = cam + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: install-camSCRIPTS +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-camSCRIPTS +uninstall: uninstall-am +all-am: Makefile $(SCRIPTS) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(camdir) + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +mostlyclean-am: mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-generic clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: uninstall-camSCRIPTS install-camSCRIPTS tags distdir info-am \ +info dvi-am dvi check check-am installcheck-am installcheck \ +install-exec-am install-exec install-data-am install-data install-am \ +install uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/cam/README b/cam/README new file mode 100644 index 0000000..281c550 --- /dev/null +++ b/cam/README @@ -0,0 +1,45 @@ +Cam 0.4 README +============== +This document was last updated on 20010223-1620-PST. +Please see the file COPYING for licensing information. + +Description +=========== +Cam is a Perl wrapper for feh that simlifies viewing webcams. Cam uses +keyed bookmarks. Type "cam --help" at the command line for usage +information. + +Webcam Information +================== +All webcam images are the property of their respective owners. If you +enjoy the cam, you should check out the page too! The initial list of +cam bookmarks (in the cam_bookmarks file) is a combination of webcams +scoured from the #E People Page (http://bma.debian.net/~bma/e-irc/), +my favorite webcams from the Stile Project's cam pages +(http://www.stileproject.com/), and additional #e people cams that +have come online since cam's original release (0.1). + +Installation +============ +- Copy the "cam" script to a location in your PATH (ex /usr/bin, + /usr/local/bin, or $HOME/bin), and make sure hte execute bit on the + script is set (type "chmod a+x $HOME/.cam_bookmarks"). +- Copy the "cam_bookmarks" file to $HOME/.cam_bookmarks and make sure + cam can see it by typing "cam --list". +- Optionally, modify the options inside the cam script. You can pass + feh any options before the image by adjusting the $PRE variable, + and any options after the image by adjustin the $POST variable. + For example, I like to keep all cam images by default; you can enable + this behavior with the -k command line option, or enable it permanently + by adding it to the $PRE flags in cam. + +About the Authors +================= +Paul Duncan , pabs on #e +http://www.pablotron.org/ + +Richard Lowe , richlowe on #e +http://www.richlowe.btinternet.co.uk/ + +...but the real credit goes to Tom Gilbert for making feh, an awesome +image viewer. :) diff --git a/cam/cam b/cam/cam new file mode 100755 index 0000000..014b22b --- /dev/null +++ b/cam/cam @@ -0,0 +1,192 @@ +#!/usr/bin/perl -w + +use strict; +use Getopt::Long; + +############################################# +############# CAM RUN-TIME OPTIONS ########## +############################################# +my $feh = "feh"; + +# additional feh cmdline options +my $PRE = " -q -G -Twebcam -1 0 -0 1 "; +my $POST = ""; +############################################# +############################################# + +# Options +my $help = ''; +my $fullscreen = ''; +my $geometry = ''; +my $list = ''; +my $verbose = ''; +my $add = ''; +my $keep = ''; +my $deftitle = '%cCAM - %u'; +my $title = ''; +my $bp = $ENV{HOME}."/.cam_bookmarks"; +my $DEBUG = 0; + +# check args +&print_usage_and_exit unless (@ARGV); + + +# Url, Refresh, and bookmarks +my $url = ""; +my $ref = ""; +my %bms = (); + +GetOptions('help|?|h' => \$help, + 'full-screen|f|giblets-mom' => \$fullscreen, + 'list|l' => \$list, + 'geometry|g=s' => \$geometry, + 'verbose|v' => \$verbose, + 'add|a' => \$add, + 'keep-images|k|save-pr0n' => \$keep, + 'title|t=s' => \$title, + 'debug|d' => \$DEBUG, + 'bookmarks|b=s' => \$bp + ); + +my $key = shift @ARGV; + +&print_usage_and_exit if ($help); + +if ($verbose) { + $PRE .= " -V "; +} + +if ($fullscreen) { + $PRE =~ s/-w//; + $PRE .= " --full-screen --auto-zoom "; +} + +if ($geometry) { + $PRE .= " --geometry $geometry "; +} + +# if requested, add a key/url pair to bookmarks file +if ($add) { + my $mytitle = ''; + ($url,$ref,$mytitle) = @ARGV; + die "Bad key syntax\n" unless ($key && $url && $ref); + + $mytitle="" unless ($mytitle); + + open(BMF, ">>$bp") or die "Couldn't open bookmarks file \"$bp\": $!\n"; + print BMF "$key=$ref,$url \"$mytitle\"\n"; + close BMF; + print "Added URL key \"$key\" = $url, $ref.\n"; # its useful to have this even if you arent debugging --richlowe + exit 0; +} + +if ($keep) { + $PRE .= " -k "; +} + + + +# load bookmarks +open(BMF, "$bp") or die "Couldn't open bookmarks file \"$bp\": $!\n"; +foreach () { + next unless /^(.*?)=(.*)$/; + $bms{$1} = $2; + print "key=$1, url=$2\n" if ($DEBUG); +} +close BMF; + +# if requested, dump a list of key/url pair values +if ($list) { + foreach (sort keys %bms) { + my $t = $bms{$_}; + + $t =~ s/^(.+?),(.+?)(^ "(.*)"|)?$/$2/; + chomp $t; + print "$_ = $t, $1, $3\n"; + } + exit 0; +} + +# main loop +MAIN: { + do { + $title=""; + $url = $bms{$key}; + die "Couldn't find URL key \"$key.\"\n" unless($url); + + $url =~ s/^(.+?),(.+?)( "(.*)")?$/$2/; + $ref = $1; + + if ($4) { + $title = $4; + } else { + $title = $deftitle; + } + + if ($title) { + $title =~ s/\%c/$key/g; + $title =~ s/\%u/$url/g; + $title =~ s/\%r/$ref/g; + $title =~ s/\%\%/\%/g; + $title = " --title \"$title\" "; + } + + my $cmd = "$feh $PRE $title -T".$key."cam -R $ref $url $POST"; + print "$cmd\n" if ($DEBUG); + FORK: { + my $pid; + if ($pid = fork) { + # We're a daddy! :) + } elsif (defined $pid) { + # child + exec "$cmd" or die "Couldnt exec() $feh: $!\n"; + } elsif ( $! =~ /No more process/) { + sleep 5; + redo FORK; + } else { + # wtf? + die "Unrecoverable fork() error: $!\n"; + } + } + } while ($key = shift @ARGV); +} + + +sub print_usage_and_exit() { + print <, and + Richard Lowe + +Description: + A convenient webcam wrapper for feh. + +Usage: + $0 + Load the urls specified by the given keys. + key : a url key stored in the bookmarks file (\"$bp\"). + $0 <-a|--add> key url refresh + Add a key to the bookmarks file. + key : short key (ex \"jenni\"), + url : url (ex \"http://www.jennicam.org/webcam/cam.jpg\"), + refresh : refresh, in seconds (ex 120) + $0 <-l|--list> + List each url key in the bookmarks file (\"$bp\"). + $0 [-f|--full-screen] keys + Start feh in full-screen mode (aka --giblets-mom \"viewing\" mode). + $0 [-k|--keep-images] keys + Save each image in the current directory (aka --save-pr0n). + $0 [-g|--geometry] xxx + Use window geometry xxx (e.g. 640x480). + $0 [-v|--verbose] options + Start feh in verbose mode (feh -V). + $0 <-h|-?|--help> + Display usage information (this screen). + +Notes: +Thanks to giblet for feh, an awesome image and webcam viewing program, +and raster for Imlib2. +END_USAGE + exit(-1); +} + diff --git a/cam/cam_bookmarks b/cam/cam_bookmarks new file mode 100644 index 0000000..5a5f100 --- /dev/null +++ b/cam/cam_bookmarks @@ -0,0 +1,24 @@ +giblet=20,http://geeks.linux.com/~gilbrit/images/webcam.jpg +raster=120,http://www.rasterman.com/webcam/cam.jpg +raster_work=20,http://www.rasterman.com/webcam/cam2.jpg +dawn=240,http://www.suburbanchaos.com/cammie.jpg +jenni=600,http://www.jennicam.org/guests/cam.jpg +milo=300,http://www.mil0.com/images/webcam32.jpg +juju=300,http://www.jujucam.com/8533362.jpg +puce=300,http://www.puce.com/cam/puce.jpg +codi=300,http://manifestangel.com/codi/webcam32.jpg +dphase=20,http://saturn5.locnet.net/dphase/seed.jpg +mandrake=20,http://www.mandrake.net/mandrake-cam.jpg +kaitlin=300,http://illusion.org/webcam/krs.jpg +demonishi=20,http://demonishi.net/webcam.jpg +sbizz=10,http://voyeur.nontoxic.org/~webcam/webcam.jpg +schmoo=20,http://www.schmoo.org/bouncycam/pic/image.jpg +fusion94=20,http://fusion94.sourceforge.net/cam/webcam.jpg +ng=20,http://www.shagged.org/~ng/images/webcam.jpg +x5rings=30,http://x5rings.fsck.org/webcam/webcam.jpg +mich=30,http://mich.unelite.net/dorkarus/mich.jpg +deuce=30,http://home.pablotron.org/~cam/webcam.jpg +nasa_shuttle=60,http://science.ksc.nasa.gov/shuttle/countdown/video/chan2large.jpg +rock104=10,http://www.rock104.com/campict/fullsize.jpg +richlowe=30,http://www.richlowe.btinternet.co.uk/images/webcam.jpg + diff --git a/cam/gen_cam_menu.sh b/cam/gen_cam_menu.sh new file mode 100755 index 0000000..9fe3770 --- /dev/null +++ b/cam/gen_cam_menu.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +###################################################################### +# gen_cam_menu.sh 0.1 # +# by Paul Duncan # +# # +# This script will generate a menu of cam bookmarks for # +# Enlightenment DR0.16.x. TYou can safely run this script more than # +# once; it won't add an another entry to the left-click menu if it's # +# already been run once. It doesn't delete any existing menu # +# entries, and it backs up your existing menu files as well. (just # +# in case I screwed up.. hehe). THe two variables below allow you # +# rename the left-click menuitem, and the menu title. # +# # +# # +MENU_ITEM="Webcams"; # +MENU_TITLE="Webcam List"; # +BMARKS=$HOME"/.cam_bookmarks"; # +# # +###################################################################### + + +C_MENUFILE="webcam.menu"; +F_MENUFILE="file.menu"; +C_MENU=$HOME"/.enlightenment/"$C_MENUFILE; +F_MENU=$HOME"/.enlightenment/"$F_MENUFILE; + +# make backups, just in case +cp -f $C_MENU $C_MENU"-cam_menu.backup" +cp -f $F_MENU $F_MENU"-cam_menu.backup" + +# generate cam menu +echo "Generating \""$C_MENU"\"."; +echo "\"$TITLE\"" > "$C_MENU"; +cat $BMARKS | perl -e "while (<>) { /(.*?)=/; \$keys{\$1}=\"1\"; } foreach(sort keys %keys) { /(.)(.*$)/; print \"\\\"\".uc(\$1).\"\$2\\\" NULL exec \\\"cam \$1\$2\\\"\\n\"; }">> $C_MENU; + +# add entry to file menu if there isn't one +echo "Generating \""$F_MENU"\"."; +perl -i -e "\$already_there=0; while (<>) { \$already_there++ if (/$MENU_ITEM/); print \"\\\"$MENU_ITEM\\\" NULL menu \\\"$C_MENUFILE\\\"\\n\" if (!\$already_there&&/Restart/); print; }" $F_MENU; + +echo "Done."; diff --git a/config.guess b/config.guess new file mode 100755 index 0000000..45bee13 --- /dev/null +++ b/config.guess @@ -0,0 +1,1465 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +timestamp='2005-04-22' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + amd64:OpenBSD:*:*) + echo x86_64-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + cats:OpenBSD:*:*) + echo arm-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + luna88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + macppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvmeppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mips64-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit 0 ;; + macppc:MirBSD:*:*) + echo powerppc-unknown-mirbsd${UNAME_RELEASE} + exit 0 ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit 0 ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit 0 ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit 0 ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7 && exit 0 ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c \ + && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && exit 0 + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + # avoid double evaluation of $set_cc_for_build + test -n "$CC_FOR_BUILD" || eval $set_cc_for_build + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + x86:Interix*:[34]*) + echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' + exit 0 ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + amd64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit 0 ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit 0 ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 + ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit 0 ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit 0 ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i*86:*:5:[78]*) + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit 0 ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit 0 ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit 0 ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit 0 ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + *86) UNAME_PROCESSOR=i686 ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit 0 ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms && exit 0 ;; + I*) echo ia64-dec-vms && exit 0 ;; + V*) echo vax-dec-vms && exit 0 ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.sub b/config.sub new file mode 100755 index 0000000..87a1ee4 --- /dev/null +++ b/config.sub @@ -0,0 +1,1569 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +timestamp='2005-04-22' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ + kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | msp430 \ + | ns16k | ns32k \ + | openrisc | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | msp430-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + or32 | or32-*) + basic_machine=or32-unknown + os=-coff + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100755 index 0000000..f739e85 --- /dev/null +++ b/configure @@ -0,0 +1,4700 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.59. +# +# Copyright (C) 2003 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="src/main.c" +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO SET_MAKE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT IMLIB2_CONFIG IMLIB_LIBS IMLIB_CFLAGS IMLIB2_CFLAGS IMLIB2_LIBS GIBLIB_CONFIG GIBLIB_LIBS GIBLIB_CFLAGS HAVE_XINERAMA XINERAMA_LIBS LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-dmalloc use dmalloc, as in + ftp://ftp.letters.com/src/dmalloc/dmalloc.tar.gz + --with-imlib2=DIR use imlib2 in + --with-imlib2-prefix=PFX Prefix where imlib2 is installed (optional) + --with-imlib2-exec-prefix=PFX Exec prefix where imlib2 is installed (optional) + --with-giblib-prefix=PFX Prefix where giblib is installed (optional) + --with-giblib-exec-prefix=PFX Exec prefix where giblib is installed (optional) + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd "$ac_popdir" + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF + +Copyright (C) 2003 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + +am__api_version="1.4" +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo "$as_me:$LINENO: checking whether build environment is sane" >&5 +echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6 +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "$*" != "X $srcdir/configure conftestfile" \ + && test "$*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&5 +echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&2;} + { (exit 1); exit 1; }; } + fi + + test "$2" = conftestfile + ) +then + # Ok. + : +else + { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! +Check your system clock" >&5 +echo "$as_me: error: newly created file is older than distributed files! +Check your system clock" >&2;} + { (exit 1); exit 1; }; } +fi +rm -f conftest* +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +test "$program_prefix" != NONE && + program_transform_name="s,^,$program_prefix,;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$,$program_suffix,;$program_transform_name" +# Double any \ or $. echo might interpret backslashes. +# By default was `s,x,x', remove it if useless. +cat <<\_ACEOF >conftest.sed +s/[\\$]/&&/g;s/;s,x,x,$// +_ACEOF +program_transform_name=`echo $program_transform_name | sed -f conftest.sed` +rm conftest.sed + +echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="$(MAKE)"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +PACKAGE=feh + +VERSION=1.3.4 + +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 +echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} + { (exit 1); exit 1; }; } +fi + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + + + +missing_dir=`cd $ac_aux_dir && pwd` +echo "$as_me:$LINENO: checking for working aclocal-${am__api_version}" >&5 +echo $ECHO_N "checking for working aclocal-${am__api_version}... $ECHO_C" >&6 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (aclocal-${am__api_version} --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL=aclocal-${am__api_version} + echo "$as_me:$LINENO: result: found" >&5 +echo "${ECHO_T}found" >&6 +else + ACLOCAL="$missing_dir/missing aclocal-${am__api_version}" + echo "$as_me:$LINENO: result: missing" >&5 +echo "${ECHO_T}missing" >&6 +fi + +echo "$as_me:$LINENO: checking for working autoconf" >&5 +echo $ECHO_N "checking for working autoconf... $ECHO_C" >&6 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoconf --version) < /dev/null > /dev/null 2>&1; then + AUTOCONF=autoconf + echo "$as_me:$LINENO: result: found" >&5 +echo "${ECHO_T}found" >&6 +else + AUTOCONF="$missing_dir/missing autoconf" + echo "$as_me:$LINENO: result: missing" >&5 +echo "${ECHO_T}missing" >&6 +fi + +echo "$as_me:$LINENO: checking for working automake-${am__api_version}" >&5 +echo $ECHO_N "checking for working automake-${am__api_version}... $ECHO_C" >&6 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (automake-${am__api_version} --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake-${am__api_version} + echo "$as_me:$LINENO: result: found" >&5 +echo "${ECHO_T}found" >&6 +else + AUTOMAKE="$missing_dir/missing automake-${am__api_version}" + echo "$as_me:$LINENO: result: missing" >&5 +echo "${ECHO_T}missing" >&6 +fi + +echo "$as_me:$LINENO: checking for working autoheader" >&5 +echo $ECHO_N "checking for working autoheader... $ECHO_C" >&6 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoheader --version) < /dev/null > /dev/null 2>&1; then + AUTOHEADER=autoheader + echo "$as_me:$LINENO: result: found" >&5 +echo "${ECHO_T}found" >&6 +else + AUTOHEADER="$missing_dir/missing autoheader" + echo "$as_me:$LINENO: result: missing" >&5 +echo "${ECHO_T}missing" >&6 +fi + +echo "$as_me:$LINENO: checking for working makeinfo" >&5 +echo $ECHO_N "checking for working makeinfo... $ECHO_C" >&6 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (makeinfo --version) < /dev/null > /dev/null 2>&1; then + MAKEINFO=makeinfo + echo "$as_me:$LINENO: result: found" >&5 +echo "${ECHO_T}found" >&6 +else + MAKEINFO="$missing_dir/missing makeinfo" + echo "$as_me:$LINENO: result: missing" >&5 +echo "${ECHO_T}missing" >&6 +fi + + + + ac_config_headers="$ac_config_headers src/config.h" + + ac_config_commands="$ac_config_commands default-1" + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std1 is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std1. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + +echo "$as_me:$LINENO: checking for ${CC-cc} option to accept ANSI C" >&5 +echo $ECHO_N "checking for ${CC-cc} option to accept ANSI C... $ECHO_C" >&6 +if test "${am_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + am_cv_prog_cc_stdc=no +ac_save_CC="$CC" +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; + +int +main () +{ + +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + am_cv_prog_cc_stdc="$ac_arg"; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +CC="$ac_save_CC" + +fi + +if test -z "$am_cv_prog_cc_stdc"; then + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 +else + echo "$as_me:$LINENO: result: $am_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$am_cv_prog_cc_stdc" >&6 +fi +case "x$am_cv_prog_cc_stdc" in + x|xno) ;; + *) CC="$CC $am_cv_prog_cc_stdc" ;; +esac + +echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 +echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6 +if test "${ac_cv_c_const+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset x; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *ccp; + char **p; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + ccp = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++ccp; + p = (char**) ccp; + ccp = (char const *const *) p; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + } +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_const=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_const=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 +echo "${ECHO_T}$ac_cv_c_const" >&6 +if test $ac_cv_c_const = no; then + +cat >>confdefs.h <<\_ACEOF +#define const +_ACEOF + +fi + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="$(MAKE)"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +echo "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5 +echo $ECHO_N "checking whether to enable maintainer-specific portions of Makefiles... $ECHO_C" >&6 + # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then + enableval="$enable_maintainer_mode" + USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi; + echo "$as_me:$LINENO: result: $USE_MAINTAINER_MODE" >&5 +echo "${ECHO_T}$USE_MAINTAINER_MODE" >&6 + + +if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + MAINT=$MAINTAINER_MODE_TRUE + + +echo "$as_me:$LINENO: checking if malloc debugging is wanted" >&5 +echo $ECHO_N "checking if malloc debugging is wanted... $ECHO_C" >&6 + +# Check whether --with-dmalloc or --without-dmalloc was given. +if test "${with_dmalloc+set}" = set; then + withval="$with_dmalloc" + if test "$withval" = yes; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +cat >>confdefs.h <<\_ACEOF +#define WITH_DMALLOC 1 +_ACEOF + + LIBS="$LIBS -ldmalloc" + LDFLAGS="$LDFLAGS -g" +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi; + + + +# Check whether --with-imlib2 or --without-imlib2 was given. +if test "${with_imlib2+set}" = set; then + withval="$with_imlib2" + CFLAGS="$CFLAGS -I$withval/include" + LIBS="-L$withval/lib $LIBS" +fi; + + + +# Check whether --with-imlib2-prefix or --without-imlib2-prefix was given. +if test "${with_imlib2_prefix+set}" = set; then + withval="$with_imlib2_prefix" + imlib2_config_prefix="$withval" +else + imlib2_config_prefix="" +fi; + +# Check whether --with-imlib2-exec-prefix or --without-imlib2-exec-prefix was given. +if test "${with_imlib2_exec_prefix+set}" = set; then + withval="$with_imlib2_exec_prefix" + imlib2_config_exec_prefix="$withval" +else + imlib2_config_exec_prefix="" +fi; + + if test x$imlib2_config_exec_prefix != x ; then + imlib2_config_args="$imlib2_config_args --exec-prefix=$imlib2_config_exec_prefix" + if test x${IMLIB2_CONFIG+set} != xset ; then + IMLIB2_CONFIG=$imlib2_config_exec_prefix/bin/imlib2-config + fi + fi + if test x$imlib2_config_prefix != x ; then + imlib2_config_args="$imlib2_config_args --prefix=$imlib2_config_prefix" + if test x${IMLIB2_CONFIG+set} != xset ; then + IMLIB2_CONFIG=$imlib2_config_prefix/bin/imlib2-config + fi + fi + + # Extract the first word of "imlib2-config", so it can be a program name with args. +set dummy imlib2-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_IMLIB2_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $IMLIB2_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_IMLIB2_CONFIG="$IMLIB2_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_IMLIB2_CONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_path_IMLIB2_CONFIG" && ac_cv_path_IMLIB2_CONFIG="no" + ;; +esac +fi +IMLIB2_CONFIG=$ac_cv_path_IMLIB2_CONFIG + +if test -n "$IMLIB2_CONFIG"; then + echo "$as_me:$LINENO: result: $IMLIB2_CONFIG" >&5 +echo "${ECHO_T}$IMLIB2_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + echo "$as_me:$LINENO: checking for imlib2 - version >= 1.0.0" >&5 +echo $ECHO_N "checking for imlib2 - version >= 1.0.0... $ECHO_C" >&6 + + no_imlib2="" + if test "$IMLIB2_CONFIG" = "no" ; then + no_imlib2=yes + else + IMLIB2_CFLAGS="`$IMLIB2_CONFIG $imlib2_config_args --cflags`" + IMLIB2_LIBS="`$IMLIB2_CONFIG $imlib2_config_args --libs`" + + imlib2_config_major_version=`$IMLIB2_CONFIG $imlib2_config_args \ + --version | sed 's/[^0-9]*\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` + imlib2_config_minor_version=`$IMLIB2_CONFIG $imlib2_config_args \ + --version | sed 's/[^0-9]*\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` + imlib2_config_micro_version=`$IMLIB2_CONFIG $imlib2_config_args \ + --version | sed 's/[^0-9]*\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` + imlib2_wanted_major_version="1" + imlib2_wanted_minor_version="0" + imlib2_wanted_micro_version="0" + + # Compare wanted version to what config script returned. + # If I knew what library was being run, i'd probably also compile + # a test program at this point (which also extracted and tested + # the version in some library-specific way) + if test "$imlib2_config_major_version" -lt \ + "$imlib2_wanted_major_version" \ + -o \( "$imlib2_config_major_version" -eq \ + "$imlib2_wanted_major_version" \ + -a "$imlib2_config_minor_version" -lt \ + "$imlib2_wanted_minor_version" \) \ + -o \( "$imlib2_config_major_version" -eq \ + "$imlib2_wanted_major_version" \ + -a "$imlib2_config_minor_version" -eq \ + "$imlib2_wanted_minor_version" \ + -a "$imlib2_config_micro_version" -lt \ + "$imlib2_wanted_micro_version" \) ; then + # older version found + no_imlib2=yes + echo -n "*** An old version of imlib2 " + echo -n "($imlib2_config_major_version" + echo -n ".$imlib2_config_minor_version" + echo ".$imlib2_config_micro_version) was found." + echo -n "*** You need a version of imlib2 newer than " + echo -n "$imlib2_wanted_major_version" + echo -n ".$imlib2_wanted_minor_version" + echo ".$imlib2_wanted_micro_version." + echo "***" + echo "*** If you have already installed a sufficiently new version, this error" + echo "*** probably means that the wrong copy of the imlib2-config shell script is" + echo "*** being found. The easiest way to fix this is to remove the old version" + echo "*** of imlib2, but you can also set the IMLIB2_CONFIG environment to point to the" + echo "*** correct copy of imlib2-config. (In this case, you will have to" + echo "*** modify your LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf" + echo "*** so that the correct libraries are found at run-time)" + fi + + fi + if test "x$no_imlib2" = x ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + + + + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + if test "$IMLIB2_CONFIG" = "no" ; then + echo "*** The imlib2-config script installed by imlib2 could not be found" + echo "*** If imlib2 was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the IMLIB2_CONFIG environment variable to the" + echo "*** full path to imlib2-config." + fi + IMLIB2_CFLAGS="" + IMLIB2_LIBS="" + { { echo "$as_me:$LINENO: error: Cannot find imlib2: Is imlib2-config in the path?" >&5 +echo "$as_me: error: Cannot find imlib2: Is imlib2-config in the path?" >&2;} + { (exit 1); exit 1; }; } + fi + + + + + + +IMLIB_LIBS=`imlib2-config --libs` +IMLIB_CFLAGS=`imlib2-config --cflags` + + + + + +# Check whether --with-giblib-prefix or --without-giblib-prefix was given. +if test "${with_giblib_prefix+set}" = set; then + withval="$with_giblib_prefix" + giblib_config_prefix="$withval" +else + giblib_config_prefix="" +fi; + +# Check whether --with-giblib-exec-prefix or --without-giblib-exec-prefix was given. +if test "${with_giblib_exec_prefix+set}" = set; then + withval="$with_giblib_exec_prefix" + giblib_config_exec_prefix="$withval" +else + giblib_config_exec_prefix="" +fi; + + if test x$giblib_config_exec_prefix != x ; then + giblib_config_args="$giblib_config_args --exec-prefix=$giblib_config_exec_prefix" + if test x${GIBLIB_CONFIG+set} != xset ; then + GIBLIB_CONFIG=$giblib_config_exec_prefix/bin/giblib-config + fi + fi + if test x$giblib_config_prefix != x ; then + giblib_config_args="$giblib_config_args --prefix=$giblib_config_prefix" + if test x${GIBLIB_CONFIG+set} != xset ; then + GIBLIB_CONFIG=$giblib_config_prefix/bin/giblib-config + fi + fi + + # Extract the first word of "giblib-config", so it can be a program name with args. +set dummy giblib-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_GIBLIB_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GIBLIB_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_GIBLIB_CONFIG="$GIBLIB_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GIBLIB_CONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_path_GIBLIB_CONFIG" && ac_cv_path_GIBLIB_CONFIG="no" + ;; +esac +fi +GIBLIB_CONFIG=$ac_cv_path_GIBLIB_CONFIG + +if test -n "$GIBLIB_CONFIG"; then + echo "$as_me:$LINENO: result: $GIBLIB_CONFIG" >&5 +echo "${ECHO_T}$GIBLIB_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + echo "$as_me:$LINENO: checking for giblib - version >= 1.2.4" >&5 +echo $ECHO_N "checking for giblib - version >= 1.2.4... $ECHO_C" >&6 + + no_giblib="" + if test "$GIBLIB_CONFIG" = "no" ; then + no_giblib=yes + else + GIBLIB_CFLAGS="`$GIBLIB_CONFIG $giblib_config_args --cflags`" + GIBLIB_LIBS="`$GIBLIB_CONFIG $giblib_config_args --libs`" + + giblib_config_major_version=`$GIBLIB_CONFIG $giblib_config_args \ + --version | sed 's/[^0-9]*\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` + giblib_config_minor_version=`$GIBLIB_CONFIG $giblib_config_args \ + --version | sed 's/[^0-9]*\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` + giblib_config_micro_version=`$GIBLIB_CONFIG $giblib_config_args \ + --version | sed 's/[^0-9]*\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` + giblib_wanted_major_version="1" + giblib_wanted_minor_version="2" + giblib_wanted_micro_version="4" + + # Compare wanted version to what config script returned. + # If I knew what library was being run, i'd probably also compile + # a test program at this point (which also extracted and tested + # the version in some library-specific way) + if test "$giblib_config_major_version" -lt \ + "$giblib_wanted_major_version" \ + -o \( "$giblib_config_major_version" -eq \ + "$giblib_wanted_major_version" \ + -a "$giblib_config_minor_version" -lt \ + "$giblib_wanted_minor_version" \) \ + -o \( "$giblib_config_major_version" -eq \ + "$giblib_wanted_major_version" \ + -a "$giblib_config_minor_version" -eq \ + "$giblib_wanted_minor_version" \ + -a "$giblib_config_micro_version" -lt \ + "$giblib_wanted_micro_version" \) ; then + # older version found + no_giblib=yes + echo -n "*** An old version of giblib " + echo -n "($giblib_config_major_version" + echo -n ".$giblib_config_minor_version" + echo ".$giblib_config_micro_version) was found." + echo -n "*** You need a version of giblib newer than " + echo -n "$giblib_wanted_major_version" + echo -n ".$giblib_wanted_minor_version" + echo ".$giblib_wanted_micro_version." + echo "***" + echo "*** If you have already installed a sufficiently new version, this error" + echo "*** probably means that the wrong copy of the giblib-config shell script is" + echo "*** being found. The easiest way to fix this is to remove the old version" + echo "*** of giblib, but you can also set the GIBLIB_CONFIG environment to point to the" + echo "*** correct copy of giblib-config. (In this case, you will have to" + echo "*** modify your LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf" + echo "*** so that the correct libraries are found at run-time)" + fi + + fi + if test "x$no_giblib" = x ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + + + + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + if test "$GIBLIB_CONFIG" = "no" ; then + echo "*** The giblib-config script installed by giblib could not be found" + echo "*** If giblib was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the GIBLIB_CONFIG environment variable to the" + echo "*** full path to giblib-config." + fi + GIBLIB_CFLAGS="" + GIBLIB_LIBS="" + { { echo "$as_me:$LINENO: error: Cannot find giblib: Is giblib-config in the path?" >&5 +echo "$as_me: error: Cannot find giblib: Is giblib-config in the path?" >&2;} + { (exit 1); exit 1; }; } + fi + + + + + + + +GIBLIB_LIBS=`giblib-config --libs` +GIBLIB_CFLAGS=`giblib-config --cflags` + + + +CFLAGS="-I/usr/X11R6/include $CFLAGS" +LIBS="-L/usr/X11R6/lib $LIBS -lm -ljpeg" + +echo "$as_me:$LINENO: checking for XMissingExtension in -lXext" >&5 +echo $ECHO_N "checking for XMissingExtension in -lXext... $ECHO_C" >&6 +if test "${ac_cv_lib_Xext_XMissingExtension+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXext $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XMissingExtension (); +int +main () +{ +XMissingExtension (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xext_XMissingExtension=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xext_XMissingExtension=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xext_XMissingExtension" >&5 +echo "${ECHO_T}$ac_cv_lib_Xext_XMissingExtension" >&6 +if test $ac_cv_lib_Xext_XMissingExtension = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBXEXT 1 +_ACEOF + + LIBS="-lXext $LIBS" + +else + CFLAGS="$CFLAGS -I/usr/X11R6/include" +fi + + +echo "$as_me:$LINENO: checking for XineramaQueryScreens in -lXinerama" >&5 +echo $ECHO_N "checking for XineramaQueryScreens in -lXinerama... $ECHO_C" >&6 +if test "${ac_cv_lib_Xinerama_XineramaQueryScreens+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXinerama $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XineramaQueryScreens (); +int +main () +{ +XineramaQueryScreens (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xinerama_XineramaQueryScreens=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xinerama_XineramaQueryScreens=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xinerama_XineramaQueryScreens" >&5 +echo "${ECHO_T}$ac_cv_lib_Xinerama_XineramaQueryScreens" >&6 +if test $ac_cv_lib_Xinerama_XineramaQueryScreens = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBXINERAMA 1 +_ACEOF + + LIBS="-lXinerama $LIBS" + +else + CFLAGS="$CFLAGS -I/usr/X11R6/include" +fi + + + + +echo "$as_me:$LINENO: checking for jpeg_destroy_decompress in -ljpeg" >&5 +echo $ECHO_N "checking for jpeg_destroy_decompress in -ljpeg... $ECHO_C" >&6 +if test "${ac_cv_lib_jpeg_jpeg_destroy_decompress+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ljpeg $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char jpeg_destroy_decompress (); +int +main () +{ +jpeg_destroy_decompress (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_jpeg_jpeg_destroy_decompress=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_jpeg_jpeg_destroy_decompress=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_jpeg_jpeg_destroy_decompress" >&5 +echo "${ECHO_T}$ac_cv_lib_jpeg_jpeg_destroy_decompress" >&6 +if test $ac_cv_lib_jpeg_jpeg_destroy_decompress = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBJPEG 1 +_ACEOF + + LIBS="-ljpeg $LIBS" + +fi + + + +echo "checking for pr0n.... found" + + ac_config_files="$ac_config_files Makefile feh.spec cam/Makefile src/Makefile src/ttfonts/Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by $as_me, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.59, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS section. +# + + + +_ACEOF + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "feh.spec" ) CONFIG_FILES="$CONFIG_FILES feh.spec" ;; + "cam/Makefile" ) CONFIG_FILES="$CONFIG_FILES cam/Makefile" ;; + "src/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "src/ttfonts/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/ttfonts/Makefile" ;; + "default-1" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; + "src/config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS src/config.h" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@PACKAGE@,$PACKAGE,;t t +s,@VERSION@,$VERSION,;t t +s,@ACLOCAL@,$ACLOCAL,;t t +s,@AUTOCONF@,$AUTOCONF,;t t +s,@AUTOMAKE@,$AUTOMAKE,;t t +s,@AUTOHEADER@,$AUTOHEADER,;t t +s,@MAKEINFO@,$MAKEINFO,;t t +s,@SET_MAKE@,$SET_MAKE,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@MAINTAINER_MODE_TRUE@,$MAINTAINER_MODE_TRUE,;t t +s,@MAINTAINER_MODE_FALSE@,$MAINTAINER_MODE_FALSE,;t t +s,@MAINT@,$MAINT,;t t +s,@IMLIB2_CONFIG@,$IMLIB2_CONFIG,;t t +s,@IMLIB_LIBS@,$IMLIB_LIBS,;t t +s,@IMLIB_CFLAGS@,$IMLIB_CFLAGS,;t t +s,@IMLIB2_CFLAGS@,$IMLIB2_CFLAGS,;t t +s,@IMLIB2_LIBS@,$IMLIB2_LIBS,;t t +s,@GIBLIB_CONFIG@,$GIBLIB_CONFIG,;t t +s,@GIBLIB_LIBS@,$GIBLIB_LIBS,;t t +s,@GIBLIB_CFLAGS@,$GIBLIB_CFLAGS,;t t +s,@HAVE_XINERAMA@,$HAVE_XINERAMA,;t t +s,@XINERAMA_LIBS@,$XINERAMA_LIBS,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_HEADER section. +# + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' +ac_dC=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' +ac_uC=' ' +ac_uD=',;t' + +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + # Do quote $f, to prevent DOS paths from being IFS'd. + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + +_ACEOF + +# Transform confdefs.h into two sed scripts, `conftest.defines' and +# `conftest.undefs', that substitutes the proper values into +# config.h.in to produce config.h. The first handles `#define' +# templates, and the second `#undef' templates. +# And first: Protect against being on the right side of a sed subst in +# config.status. Protect against being in an unquoted here document +# in config.status. +rm -f conftest.defines conftest.undefs +# Using a here document instead of a string reduces the quoting nightmare. +# Putting comments in sed scripts is not portable. +# +# `end' is used to avoid that the second main sed command (meant for +# 0-ary CPP macros) applies to n-ary macro definitions. +# See the Autoconf documentation for `clear'. +cat >confdef2sed.sed <<\_ACEOF +s/[\\&,]/\\&/g +s,[\\$`],\\&,g +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +t end +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +: end +_ACEOF +# If some macros were called several times there might be several times +# the same #defines, which is useless. Nevertheless, we may not want to +# sort them, since we want the *last* AC-DEFINE to be honored. +uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines +sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs +rm -f confdef2sed.sed + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >>conftest.undefs <<\_ACEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +_ACEOF + +# Break up conftest.defines because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS +echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS +echo ' :' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.defines >/dev/null +do + # Write a limited-size here document to $tmp/defines.sed. + echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#define' lines. + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/defines.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines +echo ' fi # grep' >>$CONFIG_STATUS +echo >>$CONFIG_STATUS + +# Break up conftest.undefs because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #undef templates' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.undefs >/dev/null +do + # Write a limited-size here document to $tmp/undefs.sed. + echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#undef' + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/undefs.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail + rm -f conftest.undefs + mv conftest.tail conftest.undefs +done +rm -f conftest.undefs + +cat >>$CONFIG_STATUS <<\_ACEOF + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + echo "/* Generated by configure. */" >$tmp/config.h + else + echo "/* $ac_file. Generated by configure. */" >$tmp/config.h + fi + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if diff $ac_file $tmp/config.h >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_COMMANDS section. +# +for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue + ac_dest=`echo "$ac_file" | sed 's,:.*,,'` + ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_dir=`(dirname "$ac_dest") 2>/dev/null || +$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_dest" : 'X\(//\)[^/]' \| \ + X"$ac_dest" : 'X\(//\)$' \| \ + X"$ac_dest" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_dest" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 +echo "$as_me: executing $ac_dest commands" >&6;} + case $ac_dest in + default-1 ) test -z "$CONFIG_HEADERS" || echo timestamp > src/stamp-h ;; + esac +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + + +echo "" +echo "If you have used an earlier version of feh," +echo "please remove your ~/.fehrc config file." +echo "feh will create a new one when it is first run." diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..1ea9281 --- /dev/null +++ b/configure.ac @@ -0,0 +1,68 @@ +dnl Process this file with autoconf to create configure. + +AC_INIT +AC_CONFIG_SRCDIR([src/main.c]) +AM_INIT_AUTOMAKE(feh, 1.3.4) +AM_CONFIG_HEADER(src/config.h) + +AC_PROG_CC +AM_PROG_CC_STDC +AC_C_CONST + +AC_PROG_INSTALL +AC_PROG_MAKE_SET + +AM_MAINTAINER_MODE +AM_WITH_DMALLOC + +AC_ARG_WITH(imlib2, + [ --with-imlib2=DIR use imlib2 in ], + [CFLAGS="$CFLAGS -I$withval/include" + LIBS="-L$withval/lib $LIBS"]) + +AC_PATH_GENERIC(imlib2, 1.0.0, [ + AC_SUBST(IMLIB_LIBS) + AC_SUBST(IMLIB_CFLAGS) ], + AC_MSG_ERROR(Cannot find imlib2: Is imlib2-config in the path?) ) +IMLIB_LIBS=`imlib2-config --libs` +IMLIB_CFLAGS=`imlib2-config --cflags` +AC_SUBST(IMLIB_LIBS) +AC_SUBST(IMLIB_CFLAGS) + +AC_PATH_GENERIC(giblib, 1.2.4, [ + AC_SUBST(GIBLIB_LIBS) + AC_SUBST(GIBLIB_CFLAGS) ], + AC_MSG_ERROR(Cannot find giblib: Is giblib-config in the path?) ) + +dnl the above doesn't work for some reason :/ +GIBLIB_LIBS=`giblib-config --libs` +GIBLIB_CFLAGS=`giblib-config --cflags` +AC_SUBST(GIBLIB_LIBS) +AC_SUBST(GIBLIB_CFLAGS) + +dnl Check for Xinerama +CFLAGS="-I/usr/X11R6/include $CFLAGS" +LIBS="-L/usr/X11R6/lib $LIBS -lm -ljpeg" +AC_CHECK_LIB(Xext,XMissingExtension,, [CFLAGS="$CFLAGS -I/usr/X11R6/include"]) +AC_CHECK_LIB(Xinerama,XineramaQueryScreens,, [CFLAGS="$CFLAGS -I/usr/X11R6/include"]) +AC_SUBST(HAVE_XINERAMA) +AC_SUBST(XINERAMA_LIBS) +AC_CHECK_LIB(jpeg, jpeg_destroy_decompress) + +dnl AC_CHECK_FUNC(getopt_long,,[AC_LIBOBJ="$AC_LIBOBJ getopt.o getopt1.o"]) +dnl AC_SUBST(AC_LIBOBJ) + +echo "checking for pr0n.... found" + +AC_CONFIG_FILES([Makefile \ +feh.spec \ +cam/Makefile \ +src/Makefile \ +src/ttfonts/Makefile \ +]) +AC_OUTPUT + +echo "" +echo "If you have used an earlier version of feh," +echo "please remove your ~/.fehrc config file." +echo "feh will create a new one when it is first run." diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..d522bc2 --- /dev/null +++ b/configure.in @@ -0,0 +1,65 @@ +dnl Process this file with autoconf to create configure. + +AC_INIT(src/main.c) +AM_INIT_AUTOMAKE(feh, 1.3.4) +AM_CONFIG_HEADER(src/config.h) + +AC_PROG_CC +AM_PROG_CC_STDC +AC_C_CONST + +AC_PROG_INSTALL +AC_PROG_MAKE_SET + +AM_MAINTAINER_MODE +AM_WITH_DMALLOC + +AC_ARG_WITH(imlib2, + [ --with-imlib2=DIR use imlib2 in ], + [CFLAGS="$CFLAGS -I$withval/include" + LIBS="-L$withval/lib $LIBS"]) + +AC_PATH_GENERIC(imlib2, 1.0.0, [ + AC_SUBST(IMLIB_LIBS) + AC_SUBST(IMLIB_CFLAGS) ], + AC_MSG_ERROR(Cannot find imlib2: Is imlib2-config in the path?) ) +IMLIB_LIBS=`imlib2-config --libs` +IMLIB_CFLAGS=`imlib2-config --cflags` +AC_SUBST(IMLIB_LIBS) +AC_SUBST(IMLIB_CFLAGS) + +AC_PATH_GENERIC(giblib, 1.2.4, [ + AC_SUBST(GIBLIB_LIBS) + AC_SUBST(GIBLIB_CFLAGS) ], + AC_MSG_ERROR(Cannot find giblib: Is giblib-config in the path?) ) + +dnl the above doesn't work for some reason :/ +GIBLIB_LIBS=`giblib-config --libs` +GIBLIB_CFLAGS=`giblib-config --cflags` +AC_SUBST(GIBLIB_LIBS) +AC_SUBST(GIBLIB_CFLAGS) + +dnl Check for Xinerama +LIBS="-L/usr/X11R6/lib $LIBS -lm -ljpeg" +AC_CHECK_LIB(Xext,XMissingExtension) +AC_CHECK_LIB(Xinerama,XineramaQueryScreens) +AC_SUBST(HAVE_XINERAMA) +AC_SUBST(XINERAMA_LIBS) +AC_CHECK_LIB(jpeg, jpeg_destroy_decompress) + +dnl AC_CHECK_FUNC(getopt_long,,[LIBOBJS="$LIBOBJS getopt.o getopt1.o"]) +dnl AC_SUBST(LIBOBJS) + +echo "checking for pr0n.... found" + +AC_OUTPUT(Makefile \ +feh.spec \ +cam/Makefile \ +src/Makefile \ +src/ttfonts/Makefile \ +) + +echo "" +echo "If you have used an earlier version of feh," +echo "please remove your ~/.fehrc config file." +echo "feh will create a new one when it is first run." diff --git a/feh.1 b/feh.1 new file mode 100644 index 0000000..254949e --- /dev/null +++ b/feh.1 @@ -0,0 +1,631 @@ +.TH feh 1 "August 14, 2001" +.SH NAME +feh - image viewer and cataloguer +.SH SYNOPSIS +feh [options] file(s) +.SH DESCRIPTION +.B feh +is an image viewer using the +.B imlib2 +library to open and manipulate images. +.B feh +has a large number of operational modes. The default mode is an image +slideshow, showing one image at a time from those specified on the +commandline. Keys and mouse control may be used to move through them. Other +modes can be specified on the commandline, and are described below. +.PP +.B feh +can also recurse through a directory structure to form a filelist for +processing, and will convert directory names on the commandline into a list +of their contents automatically. +.PP +.B Filelists +can be sorted in a number of ways. The default is the order the files were +specified on the commandline, or the order they were read from the disk. You +can specify sorting modes such as +.B +randomize +or you can sort by filename, image name, width, height, pixels, etc. +Filelists can also be saved to or loaded from files. +.SH MODES +.B Montage mode +forms a montage from the filelist. The resultant image can be viewed or +saved, and it's size can be limited by height, width or both. +.PP +.B Collage mode +is very similar to montage mode, except the images are distributed randomly +and may overlap eachother +.PP +.B Index mode +forms an index print from the filelist. Image thumbnails are shown along +with the filename, filesize and pixel size, printed using a truetype font of +your choice. The resultant image can be viewed or saved, and it's size can +be limited by height, width or both. +.PP +.B Thumbnail mode +is like index mode, but the mini-images are clickable, and launch the +clicked image in a browser window. +.PP +.B Multiwindow mode +shows images in multiple windows, instead of as a slideshow in one window. +Don't use with a large filelist ;) +.PP +.B Fullscreen mode +shows image in fullscreen view, can be combined with a slide-change delay to +show an automated presentation. +.PP +.B List mode +doesn't display images. Outputs an 'ls'-style listing of the files in the +filelist, including image info such as size, pixels, type, etc. Customlist +mode will display whatever image info you want, in the format you choose. +.PP +.B feh +can also list either all the loadable files in a filelist or all the +unloadable files. Useful for preening a directory. +.PP +.B feh +also has the ability to load files over http or ftp, simply specify the url +on the commandline. +.PP +.B feh +can read options from the commandline, or from a config file. The syntax +is the same in each case. See +.B CONFIG FILE SYNTAX +for details about using themes defined in a config file. +These methods may be used in conjunction. +.SH OPTIONS +.TP 5 +.B -h, --help +display help output and exit +.TP 5 +.B -v, --version +output version information and exit +.TP 5 +.B -V, --verbose +output useful information, progress bars, etc +.TP 5 +.B -q, --quiet +Don't report non-fatal errors for failed loads. Verbose and quiet modes +are not mutually exclusive, the first controls informational messages, +the second only errors. +.TP 5 +.B -T, --theme THEME +Load options from config file with name THEME - see CONFIG FILE SYNTAX for more info. +.TP 5 +.B --rcfile FILE +Use FILE to parse themes and options from, +instead of the default ~/.fehrc, /etc/fehrc files. +.TP 5 +.B -r, --recursive +Recursively expand any directories in FILE to the content of those +directories, all the way down to the bottom level. (Take it easy) +.TP 5 +.B -z, --randomize +When viewing multiple files in a slideshow, randomise the file list before +displaying. +.TP 5 +.B -f, --filelist FILE +This option is similar to the playlists used by music software. If FILE +exists, it will be read for a list of files to load, in the order they +appear. The format is a list of image filenames, absolute or relative to the +current directory, one filename per line. +.br +If FILE doesn't exist, it will be created from the internal filelist at the +end of a viewing session. This is best used to store the results of complex +sorts (-Spixels for example) for later viewing. Any changes to the internal +filelist (such as deleting a file or it being pruned for being unloadable) +will be saved to FILE when feh exits. You can add files to filelists by +specifying them on the commandline when also specifying the list. +.TP 5 +.B -p, --preload +Preload images. This doesn't mean hold them in RAM, it means run through +them and eliminate unloadable images first. Otherwise they will be removed +as you flick through. This also analyses the images to get data for use in +sorting, such as pixel size, type etc. A preload run will be automatically +performed if you specify one of these sort modes. +.TP 5 +.B -F, --full-screen +Make the window fullscreen +.TP 5 +.B -g, --geometry STRING +Limit (and don't change) the window size. Takes +an X-style geometry string like 640x480. +Note that larger images will be zoomed out to fit +but you can see them at 1:1 by clicking the zoom +button. +.TP 5 +.B -Z, --auto-zoom +Zoom picture to screen size in fullscreen (affected by --stretch and +--ignore-aspect). +.TP 5 +.B --zoom PERCENT +Zooms images by a PERCENT, when in full screen mode or when window geometry +is fixed. If combined with --auto-zoom, zooming will be limited to the the +size. +.TP 5 +.B -w, --multiwindow +Disable slideshow mode. With this setting, instead of opening multiple +files in slideshow mode, multiple windows will be opened, one per file. +.TP 5 +.B -x, --borderless +Create borderless windows +.TP 5 +.B -d, --draw-filename +Draw the filename at the top-left of the image +.TP 5 +.B -D, --slideshow-delay NUM +For slideshow mode, specifies time delay (seconds, can be a decimal) between automatically +changing slides. Great for presentations. +.TP 5 +.B -R, --reload NUM +Use this option to tell +.B feh +to reload an image after NUM seconds. Useful for viewing webcams via http, +or even on your local machine. +.TP 5 +.B -k, --keep-http +When viewing files using HTTP, feh normally deletes the local copies after +viewing, or, if caching, on exit. This option prevents this so that you +get to keep the local copies. They will be in /tmp with "feh" in the name. +.TP 5 +.B -Q, --builtin +Use builtin http client to grab remote files instead of wget, useful if you +don't have wget installed. +.TP 5 +.B --caption-path PATH +Path to directory containing image captions. This turns on caption viewing, and +if captions are found in PATH, which is relative to the directory of each +image, they are overlayed on the displayed image. e.g with caption path +"captions", and viewing image images/foo.jpg, caption will be looked for as +"images/captions/foo.jpg.txt" +.TP 5 +.B -l, --list +Don't display images. Analyse them and display an 'ls'-style listing. +Useful in scripts hunt out images of a certain size/resolution/type etc. +.TP 5 +.B -L, --customlist FORMAT +Use FORMAT as the format specifier for list +output. FORMAT is a printf-like string containing +image info specifiers. See FORMAT SPECIFIERS. +.TP 5 +.B -U, --loadable +Don't display images. Just print out their names if imlib2 can successfully +load them. +.TP 5 +.B -u, --unloadable +Don't display images. Just print out their name if imlib2 can NOT +successfully load them. +.TP 5 +.B -S, --sort SORT_TYPE +The file list may be sorted according to image parameters. Allowed sort +types are: name, filename, width, height, pixels, size, format. For sort +modes other than name or filename, a preload run will be necessary, +causing a delay proportional to the number of images in the list +.TP 5 +.B -n, --reverse +Reverse the sort order. Use this to invert the order of the filelist. Eg +to sort in reverse width order, use +.B -nSwidth +.TP 5 +.B -A, --action ACTION +Specify a string as an action to perform on the image. In slideshow or +multiwindow modes, the action will be run when the enter key is pressed, in +list mode, the action will be run for each file listed. The action will be +executed by /bin/sh. Use format specifiers to refer to image info. See +FORMAT SPECIFIERS for examples +.br +Eg. feh -A "mv %f ~/images/%n" * +.br +In slideshow mode, the next image will be shown after running the action, +in multiwindow mode, the window will be closed. +.TP 5 +.B --action1...9 +Extra actions which can be set and triggered using the appropriate number +key. +.TP 5 +.B -m, --montage +Enable montage mode. Montage mode creates a new image consisting of a grid +of thumbnails of the images in the filelist. When montage mode is selected, +certain other options become available. See MONTAGE MODE OPTIONS +.TP 5 +.B -c, --collage +Enable collage mode. Collage mode is very similar to montage mode, except +the images are distributed randomly. +.TP 5 +.B -i, --index +Enable Index mode. Index mode is similar to montage mode, and accepts the +same options. It creates an index print of thumbails, printing the image +name beneath each thumbnail. Index mode enables certain other options, see +INDEX MODE OPTIONS +.TP 5 +.B -I, --fullindex +Same as Index mode, but you also get image size and dimensions printed +below each thumbnail. +.TP 5 +.B -t, --thumbnails +Same as Index mode, but the thumbnails are clickable image launchers. +.TP 5 +.B --bg-tile FILE +.TP 5 +.B --bg-center FILE +.TP 5 +.B --bg-scale FILE +.TP 5 +.B --bg-seamless FILE +Set your desktop background to FILE. Feh +can use enlightenment IPC if you are running +it, or will fall back to X methods. +Feh stores the commandline necessary to restore +the background you chose in ~/.fehbg. So to have +feh-set backgrounds restored when you restart X, +add the line "eval `cat $HOME/.fehbg`" to your +X startup script (e.g. ~/.xsession). Note that +you only need to do this for non E window +managers. +.TP 5 +.B -M, --menu-font FONT +Use FONT for the font in menus. +.TP 5 +.B --menu-style FILE +Use FILE as the style descriptor for menu text. +.TP 5 +.B --menu-bg BG +Use BG for the background image in menus. +.TP 5 +.B --menu-border INT +Specify number of pixels that define the menu +background's border. Borders are not stretched +when images are scaled. +.TP 5 +.B -N, --no-menus +Don't load or show any menus. +.TP 5 +.B -1, --next-button B +Use button B to advance to the next image in slideshow +mode (defaults to 1, usually the left button). +.TP 5 +.B -2, --zoom-button B +Use button B to zoom the current image in any +mode (defaults to 2, usually the middle button). +.TP 5 +.B -3, --pan-button B +Use button B to pan the current image in any mode (defaults to 3, usually the right button). +.TP 5 +.B --no-pan-ctrl-mask +Don't require CTRL+Button for panning in any mode -- just use the button (default=off). +.TP 5 +.B -4, --menu-button B +Use CTRL+Button B to activate the menu in any mode. Set to 0 to use any +button. This option is disabled if the -N or --no-menus option is set +(defaults to 3, usually the right button). +.TP 5 +.B -5, --no-menu-ctrl-mask +Don't require CTRL+Button for menu activation in any mode -- just use the button (default=off). +.TP 5 +.B -6, --rotate-button B +Use CTRL+Button B to rotate the current image in any mode (default=2). +.TP 5 +.B -7, --no-rotate-ctrl-mask +Don't require CTRL+Button for rotation in any mode -- just use the button (default=off). +.TP 5 +.B -8, --blur-button B +Use CTRL+Button B to blur the current image in any mode (default=1). +.TP 5 +.B -9, --no-blur-ctrl-mask +Don't require CTRL+Button for blurring in any mode -- just use the button (default=off). +.TP 5 +.B --xinerama +Enable/disable Xinerama support. Has no effect unless you have an Xinerama compiled in. +.TP 5 +.B --screen-clip +Enable/disable window clipping based on screen size. WARNING: With this disabled, windows could become very large, making them unmanageable in certain window managers. +.TP 5 +.B --hide-pointer +Hide the mouse pointer in full screen mode (useful for slideshows etc). +.SH FORMAT SPECIFIERS +.B %f +image path/filename +.br +.B %n +image name +.br +.B %s +image size (bytes) +.br +.B %p +image pixel size +.br +.B %w +image width +.br +.B %h +image height +.br +.B %t +image format +.br +.B %P +prints feh +.br +.B %v +prints the version +.br +.B %m +prints the mode (slideshow, multiwindow...) +.br +.B %l +prints the total number of files in the filelist +.br +.B %u +prints the current file number +.br +.nf +\\n newline +.fi +.br +Eg. feh -A "mv %f ~/images/%n" * +.SH MONTAGE MODE OPTIONS +.TP 5 +.B -X, --ignore-aspect +By default, the montage thumbnails will retain their aspect ratios, while +fitting in --thumb-width and --thumb-height. This option will force them to +be the size set by --thumb-width and --thumb-height This will prevent any +whitespace in the final montage +.TP 5 +.B -s, --stretch +Normally, if an image is smaller than the specified thumbnail size, it will +not be enlarged. If this option is set, the image will be scaled up to fit +the thumnail size. (Aspect ratio will be maintained unless --ignore-aspect is +specified) +.TP 5 +.B -y, --thumb-width NUM +Set thumbnail width in pixels +.TP 5 +.B -E, --thumb-height NUM +Set thumbnail height in pixels +Thumbnails default to 20x20 pixels +.TP 5 +.B -W, --limit-width NUM +Limit the width of the montage in pixels +.TP 5 +.B -H, --limit-height NUM +Limit the height of the montage in pixels These options can be used together +(to define the image size exactly), or separately. If only one is specified, +theother is calculated from the number of files specified and the size of +the thumbnails. The default is to limit width to 800 pixels and calculate +the height as necessary +.TP 5 +.B -b, --bg FILE|trans +Use FILE as a background for your montage. With this option specified, the +size of the montage will default to the size of FILE if no size restrictions +are specified. Alternatively, if FILE is 'trans', the background will be +made transparent. +.TP 5 +.B -a, --alpha NUM +When drawing thumbnails onto the background, apply them with a transparency +level of NUM (0-255). +.TP 5 +.B -o FILE +Save the created montage to FILE +.TP 5 +.B -O FILE +Just save the created montage to FILE without displaying it (use in scripts) +.SH INDEX MODE OPTIONS +.TP 5 +.B -e, --font FONT +Use FONT to print the information under each thumbnail. FONT should be a +truetype font, resident in the current directory, or in feh's font +directory, and should be defined in the form fontname/size(points). (No +extension). eg. --font myfont/12 +.TP 5 +.B --fontpath PATH +Specify PATH as an extra directory in which to search for fonts, can use +multiple times to add multiple paths, e.g --fontpath /path/a --fontpath +/path/b. +.TP 5 +.B --title-font FONT +Use FONT to print a title on the index, if no font is specified, a title +will not be printed +.SH CONFIG FILE SYNTAX +The feh config file allows the naming of option groups, or themes. +If +.B $HOME/.fehrc +exists, or if not, but +.B /etc/fehrc +exists, feh will look in it for theme name/options pairs. If neither +$HOME/.fehrc or /etc/fehrc exist, feh will create a default one in ~/.fehrc. +An example entry would be: +.br +.B imagemap -rVq --thumb-width 40 --thumb-height 30 +.br +You can then use this theme in two ways. Either +.br +.B feh --theme imagemap *.jpg +.br +or you can create a symbolic link to feh with the name of the options you +want it to use. So from the example above: +.br +.B ln -s `which feh` ~/bin/imagemap +.br +Now I just run +.B imagemap *.jpg +to use those options. A cooler example is +.br +.B mkindex -iVO index.jpg --title-font 20thcent/24 . +.br +Notice the '.' at the end. Now with a symlink I can create a mkindex +command which will create an index.jpg in the current directory. I just +run +.B mkindex +to do it. +.br +You can combine these themes with commandline options, they will be +combined. So in the example above, typing +.B mkindex -q +will create and index, suppressing error messages. +An example.fehrc is provided with a couple of cool examples. +.SH SLIDESHOW KEYS +The default mode for viewing mulitple images is Slideshow mode +When viewing a slideshow, the following keys may be used: +.TP 5 +.B p, P, , +Goto previous slide +.TP 5 +.B n, N, , +Goto next slide +.TP 5 +.B r, R +Reload current image. Useful for webcams. +.TP 5 +.B v, V +Toggle fullscreen. +.TP 5 +.B m, M +Show popup menu. +.TP 5 +.B c, C +Caption entry mode. If --caption-path has been specified, then this enables +caption editing. The caption will turn yellow and be editable, hit enter to +confirm and save the caption, or hit escape to cancel and revert the caption. +.TP 5 +.B w, W +Size window to current image size. +.TP 5 +.B h, H +Pause the slideshow (only useful when using +timed reloading or image changes) +.TP 5 +.B s, S +Save the current image to a unique filename. +.TP 5 +.B f, F +Save the current filelist to a unique filename. +.TP 5 +.B <, > +In place editing, rotate the image 90 degrees left/right. +.TP 5 +.B +Goto first slide +.TP 5 +.B +Goto last slide +.TP 5 +.B +Go forward around 5% of the way through the slideshow +.TP 5 +.B +Go backward around 5% of the way through the slideshow +.TP 5 +.B +Quit the slideshow +.TP 5 +.B +, = +Increase reload delay +.TP 5 +.B -, _ +Decrease reload delay +.TP 5 +.B +Remove the currently viewed file from the filelist +.TP 5 +.B +Delete the currently viewed file and remove it from the filelist +.TP 5 +.B x, X +Close current window. +.TP 5 +.B q, Q +Quit the slideshow +.B +Move the image to the left +.B +Move the image to the right +.B +Zoom in +.B +Zoom out +.B +Zoom to 100% +.B +Zoom to fit the window +.SH MOUSE ACTIONS +When viewing an image, mouse button 1 moves to the next image (slideshow +mode only), button 2 zooms (click and drag left->right to zoom in, right-> +left to zoom out, click once to restore 1x zoom), and mouse button 3 pans. +Ctrl+button 1 blurs or sharpens the image (drag left to blur and right to +sharpen). Ctrl+button 2 rotates the image around the center point. Ctrl+ +button 3 activates the context-sensitive menu. Buttons can be redefined +with the -1 through -9 (or --*-button) cmdline flags. All you people +with million button mice can remove the ctrl mask with the --no-*-ctrl-mask +options. +.SH SUGGESTED USAGE EXAMPLES +Here are some examples of nice option combinations to achieve cool results: +.TP 5 +.B feh -r /opt/images +Recursively scan /opt/images and show all the images in a slideshow. +.TP 5 +.B feh -rSname /opt/image +Same again, but sort by name before showing. +.TP 5 +.B feh -m /opt/images/landscapes +Create a montage from the images in /opt/images/landscapes +.TP 5 +.B feh -Xrm -W 400 --thumb-width 30 --thumb-height 20 ./landscapes +Create a montage from the images in /opt/images/landscapes and all +directories below it. Limit the width of the image to 400 and make the +thumbnails 30x20, ignoring aspect ratio. +.TP 5 +.B feh -irFarial/14 -O index.jpg /opt/images +Make an index print of /opt/images and all directories below it, using 14 +point arial to write the image info under each thumbnail. Save the image as +index.jpg and don't display it, just exit. +.TP 5 +.B feh -LrSpixels /opt/images +List the images in /opt/images and all directories within, sorted by pixel +size, giving as much info as possible. +.TP 5 +.B feh -kR30 http://url.of.a.webcam.jpg +Use feh to view a webcam, reloading every 30 seconds, and saving the images +in /tmp. +.TP 5 +.B feh --unloadables -r /opt/images +Weed out (list) all the unloadable images in /opt/images and below. +.TP 5 +.B feh -w /opt/images/holidays +Open each image in /opt/images/holidays in it's own window +.TP 5 +.B feh -FD5 -Sname /opt/images/presentation +Show the images in /opt/images/presentation, sorted by name, in fullscreen +view, automatically changing slides every 5 seconds. +.TP 5 +.B feh -rSwidth -A 'mv %f ~/images/%n\' /opt/images +View all the images in /opt/images and below, sorted by width (smallest +first) and move the image to ~/images/image_name when enter is pressed. +.SH BUGS +None known. However there are many, many options. It is possible that some +do not work well in conjuncion with each other. Let me know :) +.SH LICENSE +Copyright Tom Gilbert (and various contributors), 1999, 2000 +.PP +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: +.PP +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. +.PP +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. +.PP +Email bugs and feature requests to +.br +.B diff --git a/feh.spec b/feh.spec new file mode 100644 index 0000000..e73b0d2 --- /dev/null +++ b/feh.spec @@ -0,0 +1,43 @@ +Summary: Image viewer using Imlib 2 +Name: feh +Version: 1.3.4 +Release: 1 +Copyright: BSD +Group: Amusements/Graphics +Source: %{name}-%{version}.tar.gz +Url: http://www.linuxbrit.co.uk +BuildRoot: /var/tmp/%{name}-%{version}-root + +%description +feh is a versatile and fast image viewer using imlib2, the +premier image file handling library. feh has many features, +from simple single file viewing, to multiple file modes using +a slideshow or multiple windows. feh supports the creation of +montages as index prints with many user-configurable options. + +%prep +%setup + +%build +export CFLAGS="$RPM_OPT_FLAGS" +%{configure} --prefix=%{_prefix} --bindir=%{_bindir} \ + --mandir=%{_mandir} --datadir=%{_datadir} + +make CFLAGS="$RPM_OPT_FLAGS" + +%install +rm -rf $RPM_BUILD_ROOT +make DESTDIR=$RPM_BUILD_ROOT install + +%files +%defattr(-, root, root) +%{_bindir}/* +%{_mandir}/* +%{_datadir}/%{name}/* + +%doc AUTHORS ChangeLog README TODO + +%changelog +* Wed Aug 23 2000 Calum Selkirk +- removed the double entry for doc + diff --git a/feh.spec.in b/feh.spec.in new file mode 100644 index 0000000..fb63a58 --- /dev/null +++ b/feh.spec.in @@ -0,0 +1,43 @@ +Summary: Image viewer using Imlib 2 +Name: @PACKAGE@ +Version: @VERSION@ +Release: 1 +Copyright: BSD +Group: Amusements/Graphics +Source: %{name}-%{version}.tar.gz +Url: http://www.linuxbrit.co.uk +BuildRoot: /var/tmp/%{name}-%{version}-root + +%description +feh is a versatile and fast image viewer using imlib2, the +premier image file handling library. feh has many features, +from simple single file viewing, to multiple file modes using +a slideshow or multiple windows. feh supports the creation of +montages as index prints with many user-configurable options. + +%prep +%setup + +%build +export CFLAGS="$RPM_OPT_FLAGS" +%{configure} --prefix=%{_prefix} --bindir=%{_bindir} \ + --mandir=%{_mandir} --datadir=%{_datadir} + +make CFLAGS="$RPM_OPT_FLAGS" + +%install +rm -rf $RPM_BUILD_ROOT +make DESTDIR=$RPM_BUILD_ROOT install + +%files +%defattr(-, root, root) +%{_bindir}/* +%{_mandir}/* +%{_datadir}/%{name}/* + +%doc AUTHORS ChangeLog README TODO + +%changelog +* Wed Aug 23 2000 Calum Selkirk +- removed the double entry for doc + diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..c122ef9 --- /dev/null +++ b/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/missing b/missing new file mode 100755 index 0000000..22e101a --- /dev/null +++ b/missing @@ -0,0 +1,198 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright (C) 1996, 1997, 2001, 2002 Free Software Foundation, Inc. +# Franc,ois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.in; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + yacc create \`y.tab.[ch]', if possible, from existing .[ch]" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing - GNU libit 0.0" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acinclude.m4' or \`$configure_ac'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`$configure_ac'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acconfig.h' or \`$configure_ac'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' $configure_ac` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`$configure_ac'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequirements for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 diff --git a/mkinstalldirs b/mkinstalldirs new file mode 100755 index 0000000..4f58503 --- /dev/null +++ b/mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..5b78eec --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,43 @@ +# A list of all the files in the current directory which can be regenerated +MAINTAINERCLEANFILES = Makefile.in + +LDFLAGS = -L/usr/X11R6/lib -L/usr/local/lib -lz -lpng +INCLUDES = -I/usr/X11R6/include $(X_CFLAGS) \ + -I$(prefix)/include -I$(includedir) \ + -I. -I$(top_srcdir)/src \ + -I/usr/local/include/libpng \ + -DPREFIX=\""$(prefix)"\" \ + @IMLIB_CFLAGS@ @GIBLIB_CFLAGS@ +LIBOBJS = @LIBOBJS@ + +bin_PROGRAMS = feh +feh_SOURCES = main.c getopt.c getopt1.c getopt.h feh.h \ +options.c options.h winwidget.c winwidget.h menu.c menu.h structs.h \ +filelist.c filelist.h multiwindow.c imlib.c index.c slideshow.c \ +utils.c utils.h keyevents.c timers.c timers.h list.c collage.c debug.h \ +events.c events.h support.c support.h transupp.c transupp.h \ +thumbnail.c thumbnail.h ipc.c ipc.h md5.c md5.h feh_png.c feh_png.h \ +jpegint.h + +feh_LDADD = -lX11 -lz -lpng @IMLIB_LIBS@ @GIBLIB_LIBS@ + +images_DATA = about.png menubg_default.png menubg_sky.png \ +menubg_chrome.png menubg_brushed.png \ +menubg_pastel.png menubg_aluminium.png menubg_aqua.png \ +menubg_wood.png menubg_britney.png menubg_black.png + +imagesdir=$(prefix)/share/feh/images +EXTRA_DIST = $(images_DATA) + +test: + @for i in test[0-9]* ; do \ + if test -x $$i ; then \ + echo "Executing test script $$i..." ; \ + ./$$i ; \ + fi ; \ + done + +testclean: + -rm -f _test*.jpg + +SUBDIRS = ttfonts diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..7cf64b2 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,496 @@ +# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# A list of all the files in the current directory which can be regenerated + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CC = @CC@ +GIBLIB_CFLAGS = @GIBLIB_CFLAGS@ +GIBLIB_LIBS = @GIBLIB_LIBS@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_CONFIG = @GTK_CONFIG@ +GTK_LIBS = @GTK_LIBS@ +HAVE_LIB = @HAVE_LIB@ +HAVE_XINERAMA = @HAVE_XINERAMA@ +IMLIB_CFLAGS = @IMLIB_CFLAGS@ +IMLIB_LIBS = @IMLIB_LIBS@ +LIB = @LIB@ +LTLIB = @LTLIB@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +PACKAGE = @PACKAGE@ +UP = @UP@ +VERSION = @VERSION@ +XINERAMA_LIBS = @XINERAMA_LIBS@ + +MAINTAINERCLEANFILES = Makefile.in + +LDFLAGS = -L/usr/X11R6/lib -L/usr/local/lib -lz -lpng +INCLUDES = -I/usr/X11R6/include $(X_CFLAGS) -I$(prefix)/include -I$(includedir) -I. -I$(top_srcdir)/src -I/usr/local/include/libpng -DPREFIX=\""$(prefix)"\" @IMLIB_CFLAGS@ @GIBLIB_CFLAGS@ + +LIBOBJS = @LIBOBJS@ + +bin_PROGRAMS = feh +feh_SOURCES = main.c getopt.c getopt1.c getopt.h feh.h options.c options.h winwidget.c winwidget.h menu.c menu.h structs.h filelist.c filelist.h multiwindow.c imlib.c index.c slideshow.c utils.c utils.h keyevents.c timers.c timers.h list.c collage.c debug.h events.c events.h support.c support.h transupp.c transupp.h thumbnail.c thumbnail.h ipc.c ipc.h md5.c md5.h feh_png.c feh_png.h jpegint.h + + +feh_LDADD = -lX11 -lz -lpng @IMLIB_LIBS@ @GIBLIB_LIBS@ + +images_DATA = about.png menubg_default.png menubg_sky.png menubg_chrome.png menubg_brushed.png menubg_pastel.png menubg_aluminium.png menubg_aqua.png menubg_wood.png menubg_britney.png menubg_black.png + + +imagesdir = $(prefix)/share/feh/images +EXTRA_DIST = $(images_DATA) + +SUBDIRS = ttfonts +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +PROGRAMS = $(bin_PROGRAMS) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I. +CPPFLAGS = @CPPFLAGS@ +LIBS = @LIBS@ +feh_OBJECTS = main.o getopt.o getopt1.o options.o winwidget.o menu.o \ +filelist.o multiwindow.o imlib.o index.o slideshow.o utils.o \ +keyevents.o timers.o list.o collage.o events.o support.o transupp.o \ +thumbnail.o ipc.o md5.o feh_png.o +feh_DEPENDENCIES = +feh_LDFLAGS = +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DATA = $(images_DATA) + +DIST_COMMON = ./stamp-h.in Makefile.am Makefile.in config.h.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +SOURCES = $(feh_SOURCES) +OBJECTS = $(feh_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps src/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +config.h: stamp-h + @if test ! -f $@; then \ + rm -f stamp-h; \ + $(MAKE) stamp-h; \ + else :; fi +stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES= CONFIG_HEADERS=src/config.h \ + $(SHELL) ./config.status + @echo timestamp > stamp-h 2> /dev/null +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@$(srcdir)/stamp-h.in + @if test ! -f $@; then \ + rm -f $(srcdir)/stamp-h.in; \ + $(MAKE) $(srcdir)/stamp-h.in; \ + else :; fi +$(srcdir)/stamp-h.in: $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOHEADER) + @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null + +mostlyclean-hdr: + +clean-hdr: + +distclean-hdr: + -rm -f config.h + +maintainer-clean-hdr: + +mostlyclean-binPROGRAMS: + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +distclean-binPROGRAMS: + +maintainer-clean-binPROGRAMS: + +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ + $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(bin_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + done + +.c.o: + $(COMPILE) -c $< + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +feh: $(feh_OBJECTS) $(feh_DEPENDENCIES) + @rm -f feh + $(LINK) $(feh_LDFLAGS) $(feh_OBJECTS) $(feh_LDADD) $(LIBS) + +install-imagesDATA: $(images_DATA) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(imagesdir) + @list='$(images_DATA)'; for p in $$list; do \ + if test -f $(srcdir)/$$p; then \ + echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(imagesdir)/$$p"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(imagesdir)/$$p; \ + else if test -f $$p; then \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(imagesdir)/$$p"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(imagesdir)/$$p; \ + fi; fi; \ + done + +uninstall-imagesDATA: + @$(NORMAL_UNINSTALL) + list='$(images_DATA)'; for p in $$list; do \ + rm -f $(DESTDIR)$(imagesdir)/$$p; \ + done + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. + +@SET_MAKE@ + +all-recursive install-data-recursive install-exec-recursive \ +installdirs-recursive install-recursive uninstall-recursive \ +check-recursive installcheck-recursive info-recursive dvi-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + dot_seen=no; \ + rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ + rev="$$subdir $$rev"; \ + test "$$subdir" != "." || dot_seen=yes; \ + done; \ + test "$$dot_seen" = "no" && rev=". $$rev"; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP)) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = src + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + for subdir in $(SUBDIRS); do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \ + || exit 1; \ + fi; \ + done +collage.o: collage.c feh.h config.h getopt.h structs.h menu.h ipc.h \ + utils.h debug.h winwidget.h filelist.h options.h +events.o: events.c feh.h config.h getopt.h structs.h menu.h ipc.h \ + utils.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 config.h getopt.h structs.h menu.h \ + ipc.h utils.h debug.h +filelist.o: filelist.c feh.h config.h getopt.h structs.h menu.h ipc.h \ + utils.h debug.h filelist.h options.h +getopt.o: getopt.c config.h +getopt1.o: getopt1.c config.h getopt.h +imlib.o: imlib.c feh.h config.h getopt.h structs.h menu.h ipc.h utils.h \ + debug.h filelist.h winwidget.h options.h transupp.h +index.o: index.c feh.h config.h getopt.h structs.h menu.h ipc.h utils.h \ + debug.h filelist.h winwidget.h options.h +ipc.o: ipc.c feh.h config.h getopt.h structs.h menu.h ipc.h utils.h \ + debug.h options.h +keyevents.o: keyevents.c feh.h config.h getopt.h structs.h menu.h ipc.h \ + utils.h debug.h thumbnail.h filelist.h winwidget.h options.h +list.o: list.c feh.h config.h getopt.h structs.h menu.h ipc.h utils.h \ + debug.h filelist.h options.h +main.o: main.c feh.h config.h getopt.h structs.h menu.h ipc.h utils.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 config.h getopt.h structs.h menu.h ipc.h utils.h \ + debug.h support.h thumbnail.h filelist.h winwidget.h options.h +multiwindow.o: multiwindow.c feh.h config.h getopt.h structs.h menu.h \ + ipc.h utils.h debug.h winwidget.h timers.h filelist.h options.h +options.o: options.c feh.h config.h getopt.h structs.h menu.h ipc.h \ + utils.h debug.h filelist.h options.h +slideshow.o: slideshow.c feh.h config.h getopt.h structs.h menu.h ipc.h \ + utils.h debug.h filelist.h timers.h winwidget.h options.h +support.o: support.c feh.h config.h getopt.h structs.h menu.h ipc.h \ + utils.h debug.h filelist.h options.h support.h +thumbnail.o: thumbnail.c feh.h config.h getopt.h structs.h menu.h ipc.h \ + utils.h debug.h filelist.h winwidget.h options.h thumbnail.h \ + md5.h feh_png.h +timers.o: timers.c feh.h config.h getopt.h structs.h menu.h ipc.h \ + utils.h debug.h options.h timers.h +transupp.o: transupp.c transupp.h +utils.o: utils.c feh.h config.h getopt.h structs.h menu.h ipc.h utils.h \ + debug.h options.h +winwidget.o: winwidget.c feh.h config.h getopt.h structs.h menu.h ipc.h \ + utils.h debug.h filelist.h winwidget.h options.h + +info-am: +info: info-recursive +dvi-am: +dvi: dvi-recursive +check-am: all-am +check: check-recursive +installcheck-am: +installcheck: installcheck-recursive +all-recursive-am: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +install-exec-am: install-binPROGRAMS +install-exec: install-exec-recursive + +install-data-am: install-imagesDATA +install-data: install-data-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-recursive +uninstall-am: uninstall-binPROGRAMS uninstall-imagesDATA +uninstall: uninstall-recursive +all-am: Makefile $(PROGRAMS) $(DATA) config.h +all-redirect: all-recursive-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: installdirs-recursive +installdirs-am: + $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(imagesdir) + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +mostlyclean-am: mostlyclean-hdr mostlyclean-binPROGRAMS \ + mostlyclean-compile mostlyclean-tags \ + mostlyclean-generic + +mostlyclean: mostlyclean-recursive + +clean-am: clean-hdr clean-binPROGRAMS clean-compile clean-tags \ + clean-generic mostlyclean-am + +clean: clean-recursive + +distclean-am: distclean-hdr distclean-binPROGRAMS distclean-compile \ + distclean-tags distclean-generic clean-am + +distclean: distclean-recursive + +maintainer-clean-am: maintainer-clean-hdr maintainer-clean-binPROGRAMS \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-recursive + +.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ +mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \ +maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile uninstall-imagesDATA install-imagesDATA \ +install-data-recursive uninstall-data-recursive install-exec-recursive \ +uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \ +all-recursive check-recursive installcheck-recursive info-recursive \ +dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \ +maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ +dvi-am dvi check check-am installcheck-am installcheck all-recursive-am \ +install-exec-am install-exec install-data-am install-data install-am \ +install uninstall-am uninstall all-redirect all-am all installdirs-am \ +installdirs mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +test: + @for i in test[0-9]* ; do \ + if test -x $$i ; then \ + echo "Executing test script $$i..." ; \ + ./$$i ; \ + fi ; \ + done + +testclean: + -rm -f _test*.jpg + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/about.png b/src/about.png new file mode 100644 index 0000000..5aaaf17 Binary files /dev/null and b/src/about.png differ diff --git a/src/collage.c b/src/collage.c new file mode 100644 index 0000000..3377e84 --- /dev/null +++ b/src/collage.c @@ -0,0 +1,240 @@ +/* collage.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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; + char *s; + + D_ENTER(4); + + mode = "collage"; + + /* Use bg image dimensions for default size */ + if (opt.bg && opt.bg_file) + { + if (!strcmp(opt.bg_file, "trans")) + trans_bg = 1; + else + { + + D(4,("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) + fprintf(stdout, + 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"); + opt.limit_w = bg_w; + opt.limit_h = bg_h; + } + else + { + if (opt.verbose) + fprintf(stdout, + 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"); + opt.limit_w = 800; + opt.limit_h = 600; + } + } + + w = opt.limit_w; + h = opt.limit_h; + D(4,("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); + } + + /* Create the title string */ + + if (!opt.title) + s = estrdup(PACKAGE " [collage mode]"); + else + s = estrdup(feh_printf(opt.title, NULL)); + + if (opt.display) + { + winwid = + winwidget_create_from_image(im_main, s, WIN_TYPE_SINGLE); + 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); + filelist_len--; + last = NULL; + } + D(3,("About to load image %s\n", file->filename)); + if (feh_load_image(&im_temp, file) != 0) + { + D(3,("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(5,("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(4,("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) + fprintf(stdout, "\n"); + + 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, 1024); + 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(stdout, PACKAGE " - File saved as %s\n", output_buf); + fprintf(stdout, + " - 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); + free(s); + D_RETURN_(4); +} diff --git a/src/config.h.in b/src/config.h.in new file mode 100644 index 0000000..75777c7 --- /dev/null +++ b/src/config.h.in @@ -0,0 +1,37 @@ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the `jpeg' library (-ljpeg). */ +#undef HAVE_LIBJPEG + +/* Define to 1 if you have the `Xext' library (-lXext). */ +#undef HAVE_LIBXEXT + +/* Define to 1 if you have the `Xinerama' library (-lXinerama). */ +#undef HAVE_LIBXINERAMA + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Version number of package */ +#undef VERSION + +/* Define if using the dmalloc debugging malloc package */ +#undef WITH_DMALLOC + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const diff --git a/src/debug.h b/src/debug.h new file mode 100644 index 0000000..3585cd7 --- /dev/null +++ b/src/debug.h @@ -0,0 +1,115 @@ +/* debug.h + +Copyright (C) 1999-2003 Tom Gilbert. + +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. + +*/ + +#ifndef DEBUG_H +#define DEBUG_H + +/* #define DEBUG */ + +#ifdef WITH_DMALLOC +#include +#define emalloc(a) malloc(a) +#define estrdup(a) strdup(a) +#define erealloc(a,b) realloc(a,b) +#else +#define emalloc(a) _emalloc(a) +#define estrdup(a) _estrdup(a) +#define erealloc(a,b) _erealloc(a,b) +#endif + +#ifdef DEBUG +#ifdef __GNUC__ +#define D(i, a) \ +{ \ + if(i <= opt.debug_level) \ + { \ + printf("%s +%u %s() %s ",__FILE__,__LINE__,__FUNCTION__, stroflen(' ', call_level)); \ + printf a; \ + fflush(stdout); \ + } \ + } +#define D_ENTER(i) \ + { \ + call_level++; \ + if(i <= opt.debug_level) \ + { \ + printf("%s +%u %s() %s ENTER\n",__FILE__,__LINE__,__FUNCTION__, stroflen('>', call_level)); \ + fflush(stdout); \ + } \ + } +#define D_RETURN(i, a) \ +{ \ + if(i <= opt.debug_level) \ + { \ + printf("%s +%u %s() %s LEAVE\n",__FILE__,__LINE__,__FUNCTION__, stroflen('<', call_level)); \ + fflush(stdout); \ + } \ + call_level--; \ + return (a); \ + } +#define D_RETURN_(i) \ +{ \ + if(i <= opt.debug_level) \ + { \ + printf("%s +%u %s() %s LEAVE\n",__FILE__,__LINE__,__FUNCTION__, stroflen('<', call_level)); \ + fflush(stdout); \ + } \ + call_level--; \ + return; \ + } +#else +#define D(i, a) \ +{ \ + if(i <= opt.debug_level) \ + { \ + printf("%s +%u : ",__FILE__,__LINE__); \ + printf a; \ + } \ + fflush(stdout); \ + } +#define D_ENTER(a) +#define D_RETURN(i, a) \ + { \ + return(a); \ + } +#define D_RETURN_(i) \ + { \ + return; \ + } +#endif +#else +#define D(i,a) +#define D_ENTER(a) +#define D_RETURN(i, a) \ + { \ + return (a); \ + } +#define D_RETURN_(i) \ + { \ + return; \ + } +#endif + +#endif diff --git a/src/events.c b/src/events.c new file mode 100644 index 0000000..ad78fbe --- /dev/null +++ b/src/events.c @@ -0,0 +1,688 @@ +/* events.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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 "filelist.h" +#include "winwidget.h" +#include "timers.h" +#include "options.h" +#include "events.h" +#include "thumbnail.h" + +feh_event_handler *ev_handler[LASTEvent]; + +static void feh_event_handle_ButtonPress(XEvent * ev); +static void feh_event_handle_ButtonRelease(XEvent * ev); +static void feh_event_handle_ConfigureNotify(XEvent * ev); +static void feh_event_handle_EnterNotify(XEvent * ev); +static void feh_event_handle_LeaveNotify(XEvent * ev); +static void feh_event_handle_MotionNotify(XEvent * ev); +static void feh_event_handle_ClientMessage(XEvent * ev); + +void +feh_event_init(void) +{ + int i; + + D_ENTER(4); + for (i = 0; i < LASTEvent; i++) + ev_handler[i] = NULL; + + ev_handler[KeyPress] = feh_event_handle_keypress; + ev_handler[ButtonPress] = feh_event_handle_ButtonPress; + ev_handler[ButtonRelease] = feh_event_handle_ButtonRelease; + ev_handler[ConfigureNotify] = feh_event_handle_ConfigureNotify; + ev_handler[EnterNotify] = feh_event_handle_EnterNotify; + ev_handler[LeaveNotify] = feh_event_handle_LeaveNotify; + ev_handler[MotionNotify] = feh_event_handle_MotionNotify; + ev_handler[ClientMessage] = feh_event_handle_ClientMessage; + + D_RETURN_(4); +} + +static void +feh_event_handle_ButtonPress(XEvent * ev) +{ + winwidget winwid = NULL; + int scr_width, scr_height; + + D_ENTER(4); + + /* get the heck out if it's a mouse-click on the + cover, we'll hide the menus on release */ + if (ev->xbutton.window == menu_cover) { + D_RETURN_(4); + } + + scr_width = scr->width; + scr_height = scr->height; +#ifdef HAVE_LIBXINERAMA + if (opt.xinerama && xinerama_screens) { + scr_width = xinerama_screens[xinerama_screen].width; + scr_height = xinerama_screens[xinerama_screen].height; + } +#endif /* HAVE_LIBXINERAMA */ + + winwid = winwidget_get_from_window(ev->xbutton.window); + if (winwid && winwid->caption_entry) { + D_RETURN_(4); + } + + if (!opt.no_menus && EV_IS_MENU_BUTTON(ev)) { + D(3, ("Menu Button Press event\n")); + if (winwid != NULL) { + winwidget_show_menu(winwid); + } + } + else if ((ev->xbutton.button == opt.rotate_button) + && ((opt.no_rotate_ctrl_mask) + || (ev->xbutton.state & ControlMask))) + { + if (winwid != NULL) + { + opt.mode = MODE_ROTATE; + winwid->mode = MODE_ROTATE; + D(3, ("rotate starting at %d, %d\n", ev->xbutton.x, ev->xbutton.y)); + } + } + else if ((ev->xbutton.button == opt.blur_button) + && ((opt.no_blur_ctrl_mask) || (ev->xbutton.state & ControlMask))) + { + if (winwid != NULL) + { + opt.mode = MODE_BLUR; + winwid->mode = MODE_BLUR; + D(3, ("blur starting at %d, %d\n", ev->xbutton.x, ev->xbutton.y)); + } + } + else if (ev->xbutton.button == opt.next_button) + { + D(3, ("Next Button Press event\n")); + if (winwid != NULL) + { + D(3, ("Next button, but could be pan mode\n")); + opt.mode = MODE_NEXT; + winwid->mode = MODE_NEXT; + D(3, ("click offset is %d,%d\n", ev->xbutton.x, ev->xbutton.y)); + winwid->click_offset_x = ev->xbutton.x - winwid->im_x; + winwid->click_offset_y = ev->xbutton.y - winwid->im_y; + } + } + else if (ev->xbutton.button == opt.zoom_button) + { + D(3, ("Zoom Button Press event\n")); + if (winwid != NULL) + { + D(3, ("Zoom mode baby!\n")); + opt.mode = MODE_ZOOM; + winwid->mode = MODE_ZOOM; + D(3, ("click offset is %d,%d\n", ev->xbutton.x, ev->xbutton.y)); + winwid->click_offset_x = ev->xbutton.x - winwid->im_x; + winwid->click_offset_y = ev->xbutton.y - winwid->im_y; + winwid->im_click_offset_x = winwid->click_offset_x / winwid->zoom; + winwid->im_click_offset_y = winwid->click_offset_y / winwid->zoom; + winwid->zoom = 1.0; + if (winwid->full_screen) + { + winwid->im_x = (scr_width - winwid->im_w) >> 1; + winwid->im_y = (scr_height - winwid->im_h) >> 1; + } + else + { + if (opt.geom_flags & WidthValue) { + winwid->im_x = (opt.geom_w - winwid->im_w) >> 1; + } else { + winwid->im_x = 0; + } + if (opt.geom_flags & HeightValue) { + winwid->im_y = (opt.geom_h - winwid->im_h) >> 1; + } else { + winwid->im_y = 0; + } + } + if (winwid->im_click_offset_x < 30) + winwid->im_click_offset_x = 30; + if (winwid->im_click_offset_y < 0) + winwid->im_click_offset_y = 0; + if (winwid->im_click_offset_x > winwid->im_w) + winwid->im_click_offset_x = winwid->im_w; + if (winwid->im_click_offset_y > winwid->im_h) + winwid->im_click_offset_y = winwid->im_h; + + if (winwid->click_offset_x < 30) + winwid->click_offset_x = 30; + if (winwid->click_offset_y < 0) + winwid->click_offset_y = 0; + if (winwid->click_offset_x > winwid->w) + winwid->click_offset_x = winwid->w; + if (winwid->click_offset_y > winwid->h) + winwid->click_offset_y = winwid->h; + + winwidget_render_image(winwid, 0, 0); + } + } + else if (ev->xbutton.button == opt.reload_button) + { + D(3, ("Reload Button Press event\n")); + if (winwid != NULL) + feh_reload_image(winwid, 0, 0); + } + else if (ev->xbutton.button == 4 /* this is bad */ ) + { + D(3, ("Button 4 Press event\n")); + if ((winwid != NULL) && (winwid->type == WIN_TYPE_SLIDESHOW)) + slideshow_change_image(winwid, SLIDE_PREV); + } + else if (ev->xbutton.button == 5 /* this is bad */ ) + { + D(3, ("Button 5 Press event\n")); + if ((winwid != NULL) && (winwid->type == WIN_TYPE_SLIDESHOW)) + slideshow_change_image(winwid, SLIDE_NEXT); + } + else + { + D(3, ("Received other ButtonPress event\n")); + } + D_RETURN_(4); +} + +static void +feh_event_handle_ButtonRelease(XEvent * ev) +{ + winwidget winwid = NULL; + + D_ENTER(4); + if (menu_root) + { + /* if menus are open, close them, and execute action if needed */ + + if (ev->xbutton.window == menu_cover) { + feh_menu_hide(menu_root, True); + } else if (menu_root) { + feh_menu *m; + + if ((m = feh_menu_get_from_window(ev->xbutton.window))) + { + feh_menu_item *i = NULL; + + i = feh_menu_find_selected(m); + feh_menu_item_activate(m, i); + } + } + D_RETURN_(4); + } + + winwid = winwidget_get_from_window(ev->xbutton.window); + if (winwid && winwid->caption_entry) { + D_RETURN_(4); + } + + if ((ev->xbutton.button == opt.menu_button) + && + (((!opt.menu_ctrl_mask) + && ((!(ev->xbutton.state & ControlMask)) + || ((ev->xbutton.state & ControlMask) && (opt.menu_ctrl_mask))))) + && (opt.no_menus)) + winwidget_destroy_all(); + else if (ev->xbutton.button == opt.next_button) + { + if (opt.mode == MODE_PAN) + { + if (winwid != NULL) + { + D(3, ("Disabling pan mode\n")); + opt.mode = MODE_NORMAL; + winwid->mode = MODE_NORMAL; + winwidget_sanitise_offsets(winwid); + winwidget_render_image(winwid, 0, 1); + } + } + else + { + opt.mode = MODE_NORMAL; + if(winwid != NULL) + winwid->mode = MODE_NORMAL; + if ((winwid != NULL) && (winwid->type == WIN_TYPE_SLIDESHOW)) + { + slideshow_change_image(winwid, SLIDE_NEXT); + } + else if ((winwid != NULL) && (winwid->type == WIN_TYPE_THUMBNAIL)) + { + feh_file *thumbfile; + winwidget thumbwin = NULL; + int x, y; + char *s; + + x = ev->xbutton.x; + y = ev->xbutton.y; + x -= winwid->im_x; + y -= winwid->im_y; + x /= winwid->zoom; + y /= winwid->zoom; + thumbfile = feh_thumbnail_get_file_from_coords(x, y); + if (thumbfile) + { + if (!opt.thumb_title) + s = thumbfile->name; + else + s = feh_printf(opt.thumb_title, thumbfile); + thumbwin = + winwidget_get_first_window_of_type + (WIN_TYPE_THUMBNAIL_VIEWER); + if (!thumbwin) + { + thumbwin = + winwidget_create_from_file(gib_list_add_front + (NULL, thumbfile), s, + WIN_TYPE_THUMBNAIL_VIEWER); + winwidget_show(thumbwin); + } + else if (FEH_FILE(thumbwin->file->data) != thumbfile) + { + free(thumbwin->file); + thumbwin->file = gib_list_add_front(NULL, thumbfile); + winwidget_rename(thumbwin, s); + feh_reload_image(thumbwin, 1, 0); + } + } + } + } + } + else if ((ev->xbutton.button == opt.rotate_button) + || (ev->xbutton.button == opt.zoom_button)) + { + D(3, ("Mode-based Button Release event\n")); + if (winwid != NULL) + { + D(3, ("Disabling mode\n")); + opt.mode = MODE_NORMAL; + winwid->mode = MODE_NORMAL; + winwidget_sanitise_offsets(winwid); + winwidget_render_image(winwid, 0, 1); + } + } + else if ((ev->xbutton.button == opt.blur_button) + && ((opt.no_blur_ctrl_mask) || (ev->xbutton.state & ControlMask))) + { + D(3, ("Blur Button Release event\n")); + if (winwid != NULL) + { + D(3, ("Disabling Blur mode\n")); + opt.mode = MODE_NORMAL; + winwid->mode = MODE_NORMAL; + } + } + D_RETURN_(4); +} + +static void +feh_event_handle_ConfigureNotify(XEvent * ev) +{ + D_ENTER(4); + while (XCheckTypedWindowEvent + (disp, ev->xconfigure.window, ConfigureNotify, ev)); + if (!menu_root) + { + winwidget w = winwidget_get_from_window(ev->xconfigure.window); + + if (w) + { + D(3, + ("configure size %dx%d\n", ev->xconfigure.width, + ev->xconfigure.height)); + if ((w->w != ev->xconfigure.width) + || (w->h != ev->xconfigure.height)) + { + D(3, ("assigning size and rerendering\n")); + w->w = ev->xconfigure.width; + w->h = ev->xconfigure.height; + w->had_resize = 1; + if (opt.geom_flags & WidthValue || opt.geom_flags & HeightValue) + { + opt.geom_w = w->w; + opt.geom_h = w->h; + } + winwidget_render_image(w, 0, 1); + } + } + } + + D_RETURN_(4); +} + +static void +feh_event_handle_EnterNotify(XEvent * ev) +{ + D_ENTER(4); + D_RETURN_(4); + ev = NULL; +} + +static void +feh_event_handle_LeaveNotify(XEvent * ev) +{ + D_ENTER(4); + if ((menu_root) && (ev->xcrossing.window == menu_root->win)) + { + feh_menu_item *ii; + + D(4, ("It is for a menu\n")); + for (ii = menu_root->items; ii; ii = ii->next) + { + if (MENU_ITEM_IS_SELECTED(ii)) + { + D(4, ("Unselecting menu\n")); + MENU_ITEM_SET_NORMAL(ii); + menu_root->updates = + imlib_update_append_rect(menu_root->updates, ii->x, ii->y, + ii->w, ii->h); + menu_root->needs_redraw = 1; + } + } + feh_raise_all_menus(); + } + + D_RETURN_(4); +} + +static void +feh_event_handle_MotionNotify(XEvent * ev) +{ + winwidget winwid = NULL; + int dx, dy; + int scr_width, scr_height; + + scr_width = scr->width; + scr_height = scr->height; +#ifdef HAVE_LIBXINERAMA + if (opt.xinerama && xinerama_screens) { + scr_width = xinerama_screens[xinerama_screen].width; + scr_height = xinerama_screens[xinerama_screen].height; + } +#endif /* HAVE_LIBXINERAMA */ + + D_ENTER(5); + if (menu_root) + { + feh_menu *m; + feh_menu_item *selected_item, *mouseover_item; + + D(3, ("motion notify with menus open\n")); + while (XCheckTypedWindowEvent + (disp, ev->xmotion.window, MotionNotify, ev)); + + if (ev->xmotion.window == menu_cover) + { + D_RETURN_(5); + } + else if ((m = feh_menu_get_from_window(ev->xmotion.window))) + { + selected_item = feh_menu_find_selected(m); + mouseover_item = + feh_menu_find_at_xy(m, ev->xmotion.x, ev->xmotion.y); + + if (selected_item != mouseover_item) + { + D(4, ("selecting a menu item\n")); + if (selected_item) + feh_menu_deselect_selected(m); + if ((mouseover_item) + && ((mouseover_item->func) || (mouseover_item->submenu) + || (mouseover_item->func_gen_sub))) + feh_menu_select(m, mouseover_item); + } + /* check if we are close to the right and/or the bottom edge of the + * screen. If so, and if the menu we are currently over is partially + * hidden, slide the menu to the left and/or up until it is + * fully visible */ + + /* FIXME: get this working nicely with xinerama screen edges -- + * at the moment it does really funky stuff with + * scr_{width,height} instead of scr->{width,height} -- pabs*/ + if (mouseover_item + && ((scr->width - (ev->xmotion.x + m->x)) < m->w + || (scr->height - (ev->xmotion.y + m->y)) < m->w)) + { + dx = scr_width - (m->x + m->w); + dy = scr_height - (m->y + m->h); + dx = dx < 0 ? dx : 0; + dy = dy < 0 ? dy : 0; + if (dx || dy) + feh_menu_slide_all_menus_relative(dx, dy); + } + /* if a submenu is open we want to see that also */ + if (mouseover_item && m->next + && ((scr->width - (ev->xmotion.x + m->next->x)) < m->next->w + || (scr->height - (ev->xmotion.y + m->next->y)) < m->next->w)) + { + dx = scr->width - (m->next->x + m->next->w); + dy = scr->height - (m->next->y + m->next->h); + dx = dx < 0 ? dx : 0; + dy = dy < 0 ? dy : 0; + if (dx || dy) + feh_menu_slide_all_menus_relative(dx, dy); + } + } + } + else if (opt.mode == MODE_ZOOM) + { + while (XCheckTypedWindowEvent + (disp, ev->xmotion.window, MotionNotify, ev)); + + winwid = winwidget_get_from_window(ev->xmotion.window); + if (winwid) + { + winwid->zoom = + ((double) ev->xmotion.x - (double) winwid->click_offset_x) / 64.0; + if (winwid->zoom < 0) + winwid->zoom = + 1.0 + + ((winwid->zoom * 64.0) / + ((double) (winwid->click_offset_x + 1))); + else + winwid->zoom += 1.0; + + if (winwid->zoom < 0.01) + winwid->zoom = 0.01; + + /* calculate change in zoom and move im_x and im_y respectively to + enable zooming to the clicked spot... */ + /* for now, center around im_click_offset_x and im_click_offset_y */ + winwid->im_x = + (winwid->w / 2) - (winwid->im_click_offset_x * winwid->zoom); + winwid->im_y = + (winwid->h / 2) - (winwid->im_click_offset_y * winwid->zoom); + + winwidget_render_image(winwid, 0, 0); + } + } + else if ((opt.mode == MODE_PAN) || (opt.mode == MODE_NEXT)) + { + int orig_x, orig_y; + + while (XCheckTypedWindowEvent + (disp, ev->xmotion.window, MotionNotify, ev)); + winwid = winwidget_get_from_window(ev->xmotion.window); + if (winwid) + { + if (opt.mode == MODE_NEXT) + { + opt.mode = MODE_PAN; + winwid->mode = MODE_PAN; + } + D(5, ("Panning\n")); + orig_x = winwid->im_x; + orig_y = winwid->im_y; + + winwid->im_x = ev->xmotion.x - winwid->click_offset_x; + winwid->im_y = ev->xmotion.y - winwid->click_offset_y; + + winwidget_sanitise_offsets(winwid); + + if ((winwid->im_x != orig_x) || (winwid->im_y != orig_y)) + winwidget_render_image(winwid, 0, 0); + } + } + else if (opt.mode == MODE_ROTATE) + { + while (XCheckTypedWindowEvent + (disp, ev->xmotion.window, MotionNotify, ev)); + winwid = winwidget_get_from_window(ev->xmotion.window); + if (winwid) + { + D(5, ("Rotating\n")); + if (!winwid->has_rotated) + { + Imlib_Image temp; + + temp = gib_imlib_create_rotated_image(winwid->im, 0.0); + winwid->im_w = gib_imlib_image_get_width(temp); + winwid->im_h = gib_imlib_image_get_height(temp); + gib_imlib_free_image_and_decache(temp); + if (!winwid->full_screen && !opt.geom_flags) + winwidget_resize(winwid, winwid->im_w, winwid->im_h); + winwid->has_rotated = 1; + } + winwid->im_angle = + (ev->xmotion.x - + winwid->w / 2) / ((double) winwid->w / 2) * 3.1415926535; + D(5, ("angle: %f\n", winwid->im_angle)); + winwidget_render_image(winwid, 0, 0); + } + } + else if (opt.mode == MODE_BLUR) + { + while (XCheckTypedWindowEvent + (disp, ev->xmotion.window, MotionNotify, ev)); + winwid = winwidget_get_from_window(ev->xmotion.window); + if (winwid) + { + Imlib_Image temp, ptr; + signed int blur_radius; + + D(5, ("Blurring\n")); + + temp = gib_imlib_clone_image(winwid->im); + blur_radius = (((double) ev->xmotion.x / winwid->w) * 20) - 10; + D(5, ("angle: %d\n", blur_radius)); + if (blur_radius > 0) + gib_imlib_image_sharpen(temp, blur_radius); + else + gib_imlib_image_blur(temp, 0 - blur_radius); + ptr = winwid->im; + winwid->im = temp; + winwidget_render_image(winwid, 0, 0); + gib_imlib_free_image_and_decache(winwid->im); + winwid->im = ptr; + } + } + else + { + while (XCheckTypedWindowEvent + (disp, ev->xmotion.window, MotionNotify, ev)); + winwid = winwidget_get_from_window(ev->xmotion.window); + if (winwid != NULL) + { + if (winwid->type == WIN_TYPE_ABOUT) + { + Imlib_Image orig_im; + int x, y; + + x = ev->xmotion.x - winwid->im_x; + y = ev->xmotion.y - winwid->im_y; + orig_im = winwid->im; + winwid->im = gib_imlib_clone_image(orig_im); + 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); + gib_imlib_free_image_and_decache(winwid->im); + winwid->im = orig_im; + } + else if (winwid->type == WIN_TYPE_THUMBNAIL) + { + static feh_thumbnail *last_thumb = NULL; + feh_thumbnail *thumbnail; + int x, y; + + x = (ev->xbutton.x - winwid->im_x) / winwid->zoom; + y = (ev->xbutton.y - winwid->im_y) / winwid->zoom; + thumbnail = feh_thumbnail_get_thumbnail_from_coords(x, y); + if (thumbnail != last_thumb) + { + if (thumbnail) + { + Imlib_Image origwin; + + origwin = winwid->im; + winwid->im = gib_imlib_clone_image(origwin); + gib_imlib_image_fill_rectangle(winwid->im, thumbnail->x, + thumbnail->y, thumbnail->w, + thumbnail->h, 50, 50, 255, + 100); + gib_imlib_image_draw_rectangle(winwid->im, thumbnail->x, + thumbnail->y, thumbnail->w, + thumbnail->h, 255, 255, 255, + 255); + gib_imlib_image_draw_rectangle(winwid->im, thumbnail->x + 1, + thumbnail->y + 1, + thumbnail->w - 2, + thumbnail->h - 2, 0, 0, 0, + 255); + gib_imlib_image_draw_rectangle(winwid->im, thumbnail->x + 2, + thumbnail->y + 2, + thumbnail->w - 4, + thumbnail->h - 4, 255, 255, + 255, 255); + winwidget_render_image(winwid, 0, 1); + gib_imlib_free_image_and_decache(winwid->im); + winwid->im = origwin; + } + else + winwidget_render_image(winwid, 0, 1); + } + last_thumb = thumbnail; + } + } + } + D_RETURN_(5); +} + +static void +feh_event_handle_ClientMessage(XEvent * ev) +{ + winwidget winwid = NULL; + + D_ENTER(4); + if (ev->xclient.format == 32 + && ev->xclient.data.l[0] == (signed) wmDeleteWindow) + { + winwid = winwidget_get_from_window(ev->xclient.window); + if (winwid) + winwidget_destroy(winwid); + } + + D_RETURN_(4); +} diff --git a/src/events.h b/src/events.h new file mode 100644 index 0000000..22abaf7 --- /dev/null +++ b/src/events.h @@ -0,0 +1,37 @@ +/* events.h + +Copyright (C) 1999-2003 Tom Gilbert. + +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. + +*/ + +#ifndef EVENTS_H +#define EVENTS_H + +typedef void (feh_event_handler) (XEvent * ev); + +extern feh_event_handler *ev_handler[]; + +void feh_event_init(void); + +#define EV_IS_MENU_BUTTON(ev) ((((ev)->xbutton.button == opt.menu_button) || (opt.menu_button == 0)) && (((!opt.menu_ctrl_mask) && (!((ev)->xbutton.state & ControlMask))) || (((ev)->xbutton.state & ControlMask) && (opt.menu_ctrl_mask)))) + +#endif diff --git a/src/feh.h b/src/feh.h new file mode 100644 index 0000000..ea8657c --- /dev/null +++ b/src/feh.h @@ -0,0 +1,178 @@ +/* feh.h + +Copyright (C) 1999-2003 Tom Gilbert. + +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. + +*/ + +#ifndef FEH_H +#define FEH_H + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_LIBXINERAMA +#include +#include +#endif /* HAVE_LIBXINERAMA */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "structs.h" +#include "menu.h" +#include "ipc.h" + +#include "utils.h" +#include "getopt.h" + + +#include "debug.h" + +#define SLIDESHOW_RELOAD_MAX 4096 + +#ifndef TRUE +#define FALSE 0 +#define TRUE !FALSE +#endif + +#ifndef __GNUC__ +# define __attribute__(x) +#endif + +#define XY_IN_RECT(x, y, rx, ry, rw, rh) \ +(((x) >= (rx)) && ((y) >= (ry)) && ((x) < ((rx) + (rw))) && ((y) < ((ry) + (rh)))) + +#define DEFAULT_FONT "yudit/11" +#define DEFAULT_MENU_FONT "yudit/10" +#define DEFAULT_FONT_BIG "yudit/12" +#define DEFAULT_FONT_TITLE "yudit/14" + +enum mode_type +{ MODE_NORMAL = 0, MODE_PAN, MODE_ZOOM, MODE_ROTATE, MODE_BLUR, MODE_NEXT }; + +enum bgmode_type +{ BG_MODE_NONE = 0, BG_MODE_TILE, BG_MODE_CENTER, BG_MODE_SEAMLESS, BG_MODE_SCALE }; + +enum slide_change +{ SLIDE_NEXT, SLIDE_PREV, SLIDE_FIRST, SLIDE_LAST, SLIDE_JUMP_FWD, + SLIDE_JUMP_BACK +}; + +typedef void (*sighandler_t) (int); + +void show_usage(void); +void show_version(void); +int feh_main_iteration(int block); +void feh_handle_event(XEvent * ev); +void init_x_and_imlib(void); +#ifdef HAVE_LIBXINERAMA +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); +void init_loadables_mode(void); +void init_unloadables_mode(void); +void feh_clean_exit(void); +int feh_load_image(Imlib_Image * im, feh_file * file); +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); +char *chop_file_from_full_path(char *str); +void feh_event_handle_keypress(XEvent * ev); +void feh_action_run(feh_file * file, char *action); +char *feh_printf(char *str, feh_file * file); +void feh_draw_zoom(winwidget w); +void feh_draw_checks(winwidget win); +void cb_slide_timer(void *data); +void cb_reload_timer(void *data); +char *feh_http_load_image(char *url); +int feh_load_image_char(Imlib_Image * im, char *filename); +void feh_draw_filename(winwidget w); +void feh_draw_caption(winwidget w); +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); +struct hostent *feh_gethostbyname(const char *name); +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, int max_height, Imlib_Font fn, gib_style * style); +char *build_caption_filename(feh_file *file); +gib_list * feh_list_jump(gib_list * root, gib_list * l, int direction, int num); + + +/* Imlib stuff */ +extern Display *disp; +extern Visual *vis; +extern Colormap cm; +extern int depth; +extern Atom wmDeleteWindow; + +#ifdef HAVE_LIBXINERAMA +extern int num_xinerama_screens; +extern XineramaScreenInfo *xinerama_screens; +extern int xinerama_screen; +#endif /* HAVE_LIBXINERAMA */ + +/* Thumbnail sizes */ +extern int cmdargc; +extern char **cmdargv; +extern Window root; +extern XContext xid_context; +extern Screen *scr; +extern unsigned char reset_output; +extern int call_level; +extern feh_menu *menu_main; +extern feh_menu *menu_close; +extern char *mode; /* label for the current mode */ + +#endif diff --git a/src/feh_png.c b/src/feh_png.c new file mode 100644 index 0000000..7654880 --- /dev/null +++ b/src/feh_png.c @@ -0,0 +1,214 @@ +/* feh_png.c + +Copyright (C) 2004 Tom Gilbert. + +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_png.h" + +#include + +#include +#include + +#define FEH_PNG_COMPRESSION 3 +#define FEH_PNG_NUM_COMMENTS 2 /* only Thumb::URI and Thumb::MTime for now */ + +gib_hash* +feh_png_read_comments(char *file) +{ + gib_hash *hash = NULL; + + FILE *fp; + int i, sig_bytes, comments = 0; + + png_structp png_ptr; + png_infop info_ptr; + png_textp text_ptr; + + if (!(fp = fopen(file, "rb"))) + return hash; + + if (!(sig_bytes = feh_png_file_is_png(fp))) { + fclose(fp); + return hash; + } + + /* initialize data structures */ + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + { + fclose(fp); + return hash; + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); + fclose(fp); + return hash; + } + + if (setjmp(png_ptr->jmpbuf)) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(fp); + return hash; + } + + /* initialize reading */ + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, sig_bytes); + + png_read_info(png_ptr, info_ptr); + +#ifdef PNG_TEXT_SUPPORTED + png_get_text(png_ptr, info_ptr, &text_ptr, &comments); + if (comments > 0) { + hash = gib_hash_new(); + for (i = 0; i < comments; i++) + gib_hash_set(hash, text_ptr[i].key, estrdup(text_ptr[i].text)); + } +#endif /* PNG_TEXT_SUPPORTED */ + + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(fp); + + return hash; +} + +/* grab image data from image and write info file with comments ... */ +int +feh_png_write_png(Imlib_Image image, char *file, ...) +{ + FILE *fp; + int i, w, h; + + png_structp png_ptr; + png_infop info_ptr; + png_color_8 sig_bit; + + DATA32 *ptr; + +#ifdef PNG_TEXT_SUPPORTED + va_list args; + png_text text[FEH_PNG_NUM_COMMENTS]; + char *pair_key, *pair_text; +#endif /* PNG_TEXT_SUPPORTED */ + + if (!(fp = fopen(file, "wb"))) + return 0; + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + return 0; + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + return 0; + } + + if (setjmp(png_ptr->jmpbuf)) + { + fclose(fp); + png_destroy_write_struct(&png_ptr, &info_ptr); + png_destroy_info_struct(png_ptr, &info_ptr); + return 0; + } + + w = gib_imlib_image_get_width(image); + h = gib_imlib_image_get_height(image); + + png_init_io(png_ptr, fp); + + png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGB_ALPHA, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + +#ifdef WORDS_BIGENDIAN + png_set_swap_alpha(png_ptr); +#else /* !WORDS_BIGENDIAN */ + png_set_bgr(png_ptr); +#endif /* WORDS_BIGENDIAN */ + + sig_bit.red = 8; + sig_bit.green = 8; + sig_bit.blue = 8; + sig_bit.alpha = 8; + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + +#ifdef PNG_TEXT_SUPPORTED + va_start(args, file); + for (i = 0; i < FEH_PNG_NUM_COMMENTS; i++) + { + if ((pair_key = va_arg(args, char *)) && + (pair_text = va_arg(args, char *))) + { + /* got a complete pair, add to info structure */ + text[i].key = pair_key; + text[i].text = pair_text; + text[i].compression = PNG_TEXT_COMPRESSION_NONE; + } + else + break; + } + va_end(args); + + if (i > 0) + png_set_text(png_ptr, info_ptr, text, i); +#endif /* PNG_TEXT_SUPPORTED */ + + png_set_compression_level(png_ptr, FEH_PNG_COMPRESSION); + png_write_info(png_ptr, info_ptr); + png_set_shift(png_ptr, &sig_bit); + png_set_packing(png_ptr); + + /* write image data */ + imlib_context_set_image(image); + ptr = imlib_image_get_data(); + for (i = 0; i < h; i++, ptr += w) + png_write_row(png_ptr, (png_bytep) ptr); + + png_write_end(png_ptr, info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + png_destroy_info_struct(png_ptr, &info_ptr); + + fclose(fp); + + return 0; +} + +/* check PNG signature */ +int +feh_png_file_is_png(FILE *fp) +{ + unsigned char buf[8]; + + fread(buf, 1, 8, fp); + if (png_sig_cmp(buf, 0, 8)) { + return 0; + } + + return 8; +} diff --git a/src/feh_png.h b/src/feh_png.h new file mode 100644 index 0000000..458f6c5 --- /dev/null +++ b/src/feh_png.h @@ -0,0 +1,39 @@ +/* feh_png.h + +Copyright (C) 2004 Tom Gilbert. + +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. + +*/ + +#ifndef FEH_PNG_H +#define FEH_PNG_H + +#include "feh.h" + +#include +#include + +gib_hash *feh_png_read_comments(char *file); +int feh_png_write_png(Imlib_Image image, char *file, ...); + +int feh_png_file_is_png(FILE *fp); + +#endif /* FEH_PNG_H */ diff --git a/src/filelist.c b/src/filelist.c new file mode 100644 index 0000000..dcbab54 --- /dev/null +++ b/src/filelist.c @@ -0,0 +1,611 @@ +/* filelist.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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 "filelist.h" +#include "options.h" + +gib_list *filelist = NULL; +int filelist_len = 0; +gib_list *current_file = NULL; +extern int errno; + +static gib_list *rm_filelist = NULL; + +feh_file * +feh_file_new(char *filename) +{ + feh_file *newfile; + char *s; + + D_ENTER(4); + + newfile = (feh_file *) emalloc(sizeof(feh_file)); + newfile->caption = NULL; + newfile->filename = estrdup(filename); + s = strrchr(filename, '/'); + if (s) + newfile->name = estrdup(s + 1); + else + newfile->name = estrdup(filename); + newfile->info = NULL; + D_RETURN(4, newfile); +} + +void +feh_file_free(feh_file * file) +{ + D_ENTER(4); + if (!file) + D_RETURN_(4); + if (file->filename) + free(file->filename); + if (file->name) + free(file->name); + if (file->caption) + free(file->caption); + if (file->info) + feh_file_info_free(file->info); + free(file); + D_RETURN_(4); +} + +feh_file_info * +feh_file_info_new(void) +{ + feh_file_info *info; + + D_ENTER(4); + + info = (feh_file_info *) emalloc(sizeof(feh_file_info)); + + info->width = 0; + info->height = 0; + info->size = 0; + info->pixels = 0; + info->has_alpha = 0; + info->format = NULL; + info->extension = NULL; + + D_RETURN(4, info); +} + +void +feh_file_info_free(feh_file_info * info) +{ + D_ENTER(4); + if (!info) + D_RETURN_(4); + if (info->format) + free(info->format); + if (info->extension) + free(info->extension); + free(info); + D_RETURN_(4); +} + +gib_list * +feh_file_rm_and_free(gib_list * list, gib_list * l) +{ + D_ENTER(4); + unlink(FEH_FILE(l->data)->filename); + D_RETURN(4, feh_file_remove_from_list(list, l)); +} + +gib_list * +feh_file_remove_from_list(gib_list * list, gib_list * l) +{ + D_ENTER(4); + feh_file_free(FEH_FILE(l->data)); + D_RETURN(4, gib_list_remove(list, l)); +} + +/* Recursive */ +void +add_file_to_filelist_recursively(char *origpath, unsigned char level) +{ + struct stat st; + char *path; + + D_ENTER(5); + if (!origpath) + D_RETURN_(5); + + path = estrdup(origpath); + D(4, ("file is %s\n", path)); + + if (level == FILELIST_FIRST) + { + /* First time through, sort out pathname */ + int len = 0; + + len = strlen(path); + if (path[len - 1] == '/') + path[len - 1] = '\0'; + + if ((!strncmp(path, "http://", 7)) || + (!strncmp(path, "https://", 8)) || + (!strncmp(path, "ftp://", 6))) + { + /* Its a url */ + D(3, ("Adding url %s to filelist\n", path)); + filelist = gib_list_add_front(filelist, feh_file_new(path)); + /* We'll download it later... */ + free(path); + D_RETURN_(5); + } + else if (opt.filelistfile) + { + char *newpath = feh_absolute_path(path); + + free(path); + path = newpath; + } + } + + errno = 0; + if (stat(path, &st)) + { + /* Display useful error message */ + switch (errno) + { + case ENOENT: + case ENOTDIR: + if (!opt.quiet) + weprintf("%s does not exist - skipping", path); + break; + case ELOOP: + if (!opt.quiet) + weprintf("%s - too many levels of symbolic links - skipping", + path); + break; + case EACCES: + if (!opt.quiet) + weprintf("you don't have permission to open %s - skipping", + path); + break; + default: + if (!opt.quiet) + weprintf("couldn't open %s", path); + break; + } + free(path); + D_RETURN_(5); + } + + if ((S_ISDIR(st.st_mode)) && (level != FILELIST_LAST)) + { + struct dirent *de; + DIR *dir; + + D(4, ("It is a directory\n")); + + if ((dir = opendir(path)) == NULL) + { + if (!opt.quiet) + weprintf("couldn't open directory %s:", path); + free(path); + D_RETURN_(5); + } + de = readdir(dir); + while (de != NULL) + { + if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) + { + char *newfile; + + newfile = estrjoin("", path, "/", de->d_name, NULL); + + /* This ensures we go down one level even if not fully recursive + - this way "feh some_dir" expands to some_dir's contents */ + if (opt.recursive) + add_file_to_filelist_recursively(newfile, FILELIST_CONTINUE); + else + add_file_to_filelist_recursively(newfile, FILELIST_LAST); + + free(newfile); + } + de = readdir(dir); + } + closedir(dir); + } + else if (S_ISREG(st.st_mode)) + { + D(5, ("Adding regular file %s to filelist\n", path)); + filelist = gib_list_add_front(filelist, feh_file_new(path)); + } + free(path); + D_RETURN_(5); +} + +void +add_file_to_rm_filelist(char *file) +{ + D_ENTER(4); + rm_filelist = gib_list_add_front(rm_filelist, feh_file_new(file)); + D_RETURN_(4); +} + +void +delete_rm_files(void) +{ + gib_list *l; + + D_ENTER(4); + for (l = rm_filelist; l; l = l->next) + unlink(FEH_FILE(l->data)->filename); + D_RETURN_(4); +} + +gib_list * +feh_file_info_preload(gib_list * list) +{ + gib_list *l; + feh_file *file = NULL; + gib_list *remove_list = NULL; + + D_ENTER(4); + if (opt.verbose) + fprintf(stdout, PACKAGE " - preloading...\n"); + + for (l = list; l; l = l->next) + { + file = FEH_FILE(l->data); + D(5, + ("file %p, file->next %p, file->name %s\n", l, l->next, file->name)); + if (feh_file_info_load(file, NULL)) + { + D(3, ("Failed to load file %p\n", file)); + remove_list = gib_list_add_front(remove_list, l); + if (opt.verbose) + feh_display_status('x'); + } + else if (opt.verbose) + feh_display_status('.'); + } + if (opt.verbose) + fprintf(stdout, "\n"); + + if (remove_list) + { + for (l = remove_list; l; l = l->next) + filelist = list = gib_list_remove(list, (gib_list *) l->data); + + gib_list_free(remove_list); + } + + D_RETURN(4, list); +} + +int +feh_file_info_load(feh_file * file, Imlib_Image im) +{ + struct stat st; + int need_free = 1; + Imlib_Image im1; + + D_ENTER(4); + + D(4, ("im is %p\n", im)); + + if (im) + need_free = 0; + + errno = 0; + if (stat(file->filename, &st)) + { + /* Display useful error message */ + switch (errno) + { + case ENOENT: + case ENOTDIR: + if (!opt.quiet) + weprintf("%s does not exist - skipping", file->filename); + break; + case ELOOP: + if (!opt.quiet) + weprintf("%s - too many levels of symbolic links - skipping", + file->filename); + break; + case EACCES: + if (!opt.quiet) + weprintf("you don't have permission to open %s - skipping", + file->filename); + break; + default: + if (!opt.quiet) + weprintf("couldn't open %s ", file->filename); + break; + } + D_RETURN(4, 1); + } + + if (im) + im1 = im; + else if (!feh_load_image(&im1, file)) + D_RETURN(4, 1); + + if (!im1) + D_RETURN(4, 1); + + file->info = feh_file_info_new(); + + file->info->width = gib_imlib_image_get_width(im1); + file->info->height = gib_imlib_image_get_height(im1); + + file->info->has_alpha = gib_imlib_image_has_alpha(im1); + + file->info->pixels = file->info->width * file->info->height; + + file->info->format = estrdup(gib_imlib_image_format(im1)); + + file->info->size = st.st_size; + + if (need_free && im1) + gib_imlib_free_image_and_decache(im1); + D_RETURN(4, 0); +} + +int +feh_cmp_filename(void *file1, void *file2) +{ + D_ENTER(4); + D_RETURN(4, strcmp(FEH_FILE(file1)->filename, FEH_FILE(file2)->filename)); +} + +int +feh_cmp_name(void *file1, void *file2) +{ + D_ENTER(4); + D_RETURN(4, strcmp(FEH_FILE(file1)->name, FEH_FILE(file2)->name)); +} + +int +feh_cmp_width(void *file1, void *file2) +{ + D_ENTER(4); + D_RETURN(4, (FEH_FILE(file1)->info->width - FEH_FILE(file2)->info->width)); +} + +int +feh_cmp_height(void *file1, void *file2) +{ + D_ENTER(4); + D_RETURN(4, + (FEH_FILE(file1)->info->height - FEH_FILE(file2)->info->height)); +} + +int +feh_cmp_pixels(void *file1, void *file2) +{ + D_ENTER(4); + D_RETURN(4, + (FEH_FILE(file1)->info->pixels - FEH_FILE(file2)->info->pixels)); +} + +int +feh_cmp_size(void *file1, void *file2) +{ + D_ENTER(4); + D_RETURN(4, (FEH_FILE(file1)->info->size - FEH_FILE(file2)->info->size)); +} + +int +feh_cmp_format(void *file1, void *file2) +{ + D_ENTER(4); + D_RETURN(4, + strcmp(FEH_FILE(file1)->info->format, + FEH_FILE(file2)->info->format)); +} + +void +feh_prepare_filelist(void) +{ + D_ENTER(4); + if (opt.list || opt.customlist || (opt.sort > SORT_FILENAME) + || opt.preload) + { + /* For these sort options, we have to preload images */ + filelist = feh_file_info_preload(filelist); + if (!gib_list_length(filelist)) + show_mini_usage(); + } + + D(3, ("sort mode requested is: %d\n", opt.sort)); + switch (opt.sort) + { + case SORT_NONE: + if (opt.randomize) + { + /* Randomize the filename order */ + filelist = gib_list_randomize(filelist); + } + else if (!opt.reverse) + { + /* Let's reverse the list. Its back-to-front right now ;) */ + filelist = gib_list_reverse(filelist); + } + break; + case SORT_NAME: + filelist = gib_list_sort(filelist, feh_cmp_name); + break; + case SORT_FILENAME: + filelist = gib_list_sort(filelist, feh_cmp_filename); + break; + case SORT_WIDTH: + filelist = gib_list_sort(filelist, feh_cmp_width); + break; + case SORT_HEIGHT: + filelist = gib_list_sort(filelist, feh_cmp_height); + break; + case SORT_PIXELS: + filelist = gib_list_sort(filelist, feh_cmp_pixels); + break; + case SORT_SIZE: + filelist = gib_list_sort(filelist, feh_cmp_size); + break; + case SORT_FORMAT: + filelist = gib_list_sort(filelist, feh_cmp_format); + break; + default: + break; + } + + /* no point reversing a random list */ + if (opt.reverse && (opt.sort != SORT_NONE)) + { + D(3, ("Reversing filelist as requested\n")); + filelist = gib_list_reverse(filelist); + } + + D_RETURN_(4); +} + +int +feh_write_filelist(gib_list * list, char *filename) +{ + FILE *fp; + gib_list *l; + + D_ENTER(4); + + if (!list || !filename) + D_RETURN(4, 0); + + errno = 0; + if ((fp = fopen(filename, "w")) == NULL) + { + weprintf("can't write filelist %s:", filename); + D_RETURN(4, 0); + } + + for (l = list; l; l = l->next) + fprintf(fp, "%s\n", (FEH_FILE(l->data)->filename)); + + fclose(fp); + + D_RETURN(4, 1); +} + +gib_list * +feh_read_filelist(char *filename) +{ + FILE *fp; + gib_list *list = NULL; + char s[1024], s1[1024]; + Imlib_Image im1; + + D_ENTER(4); + + if (!filename) + D_RETURN(4, NULL); + + /* try and load the given filelist as an image, cowardly refuse to + * overwrite an image with a filelist. (requested by user who did feh -df * + * when he meant feh -dF *, as it overwrote the first image with the + * filelist). + */ + if (feh_load_image_char(&im1, filename)) { + weprintf("The file you specified as a filelist to read - %s - appears to be an image. Ignoring it (this is a common mistake).\n", filename); + opt.filelistfile = NULL; + D_RETURN(4, NULL); + } + + errno = 0; + if ((fp = fopen(filename, "r")) == NULL) + { + /* return quietly, as it's okay to specify a filelist file that doesn't + exist. In that case we create it on exit. */ + D_RETURN(4, NULL); + } + + for (; fgets(s, sizeof(s), fp);) + { + D(5, ("Got line '%s'\n", s)); + s1[0] = '\0'; + sscanf(s, "%[^\n]", (char *) &s1); + if (!(*s1) || (*s1 == '\n')) + continue; + D(5, ("Got filename %s from filelist file\n", s1)); + /* Add it to the new list */ + list = gib_list_add_front(list, feh_file_new(s1)); + } + fclose(fp); + + D_RETURN(4, list); +} + +char * +feh_absolute_path(char *path) +{ + char cwd[PATH_MAX]; + char fullpath[PATH_MAX]; + char temp[PATH_MAX]; + char *ret; + + D_ENTER(4); + + if (!path) + D_RETURN(4, NULL); + if (path[0] == '/') + D_RETURN(4, estrdup(path)); + /* This path is not relative. We're gonna convert it, so that a + filelist file can be saved anywhere and feh will still find the + images */ + D(4, ("Need to convert %s to an absolute form\n", path)); + /* I SHOULD be able to just use a simple realpath() here, but dumb * + old Solaris's realpath doesn't return an absolute path if the + path you give it is relative. Linux and BSD get this right... */ + getcwd(cwd, sizeof(cwd)); + snprintf(temp, sizeof(temp), "%s/%s", cwd, path); + if (realpath(temp, fullpath) != NULL) + { + ret = estrdup(fullpath); + } + else + { + ret = estrdup(temp); + } + D(4, ("Converted path to %s\n", ret)); + D_RETURN(4, ret); +} + +void feh_save_filelist() +{ + char *tmpname; + + D_ENTER(4); + + tmpname = + feh_unique_filename("", "filelist"); + + if(!opt.quiet) + printf("saving filelist to filename '%s'\n", tmpname); + + feh_write_filelist(filelist, tmpname); + free(tmpname); + D_RETURN_(4); +} diff --git a/src/filelist.h b/src/filelist.h new file mode 100644 index 0000000..a292bb4 --- /dev/null +++ b/src/filelist.h @@ -0,0 +1,89 @@ +/* filelist.h + +Copyright (C) 1999-2003 Tom Gilbert. + +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. + +*/ + +#ifndef FILELIST_H +#define FILELIST_H + +struct __feh_file +{ + char *filename; + char *caption; + char *name; + + /* info stuff */ + feh_file_info *info; /* only set when needed */ +}; + +struct __feh_file_info +{ + int width; + int height; + int size; + int pixels; + unsigned char has_alpha; + char *format; + char *extension; +}; + +#define FEH_FILE(l) ((feh_file *) l) + +enum filelist_recurse +{ FILELIST_FIRST, FILELIST_CONTINUE, FILELIST_LAST }; + +enum sort_type +{ SORT_NONE, SORT_NAME, SORT_FILENAME, SORT_WIDTH, SORT_HEIGHT, SORT_PIXELS, + SORT_SIZE, SORT_FORMAT +}; + +feh_file *feh_file_new(char *filename); +void feh_file_free(feh_file * file); +feh_file_info *feh_file_info_new(void); +void feh_file_info_free(feh_file_info * info); +gib_list *feh_file_rm_and_free(gib_list * list, gib_list * file); +void add_file_to_filelist_recursively(char *origpath, unsigned char level); +void add_file_to_rm_filelist(char *file); +void delete_rm_files(void); +gib_list *feh_file_info_preload(gib_list * list); +int feh_file_info_load(feh_file * file, Imlib_Image im); +void feh_prepare_filelist(void); +int feh_write_filelist(gib_list * list, char *filename); +gib_list *feh_read_filelist(char *filename); +char *feh_absolute_path(char *path); +gib_list *feh_file_remove_from_list(gib_list * list, gib_list * l); +void feh_save_filelist(); + +int feh_cmp_name(void *file1, void *file2); +int feh_cmp_filename(void *file1, void *file2); +int feh_cmp_width(void *file1, void *file2); +int feh_cmp_height(void *file1, void *file2); +int feh_cmp_pixels(void *file1, void *file2); +int feh_cmp_size(void *file1, void *file2); +int feh_cmp_format(void *file1, void *file2); + +extern gib_list *filelist; +extern int filelist_len; +extern gib_list *current_file; + +#endif diff --git a/src/getopt.c b/src/getopt.c new file mode 100644 index 0000000..4503953 --- /dev/null +++ b/src/getopt.c @@ -0,0 +1,1045 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 + Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in . + Ditto for AIX 3.2 and . */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if !defined (__STDC__) || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 +#include +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include +#include +#endif /* GNU C library. */ + +#ifdef VMS +#include +#if HAVE_STRING_H - 0 +#include +#endif +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. + When compiling libc, the _ macro is predefined. */ +#ifdef HAVE_LIBINTL_H +# include +# define _(msgid) gettext (msgid) +#else +# define _(msgid) (msgid) +#endif +#endif + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = NULL; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Formerly, initialization of getopt depended on optind==0, which + causes problems with re-calling getopt as programs generally don't + know that. */ + +int __getopt_initialized = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} +ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include +#define my_index strchr +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv(); + +static char * +my_index(str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +#if !defined (__STDC__) || !__STDC__ +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen(const char *); +#endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +#ifdef _LIBC +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +/* Defined in getopt_init.c */ +extern char *__getopt_nonoption_flags; + +static int nonoption_flags_max_len; +static int nonoption_flags_len; + +static int original_argc; +static char *const *original_argv; + +/* Make sure the environment variable bash 2.0 puts in the environment + is valid for the getopt call we must make sure that the ARGV passed + to getopt is that one passed to the process. */ +static void __attribute__ ((unused)) store_args_and_env(int argc, + char *const *argv) +{ + /* XXX This is no good solution. We should rather copy the args so that + we can compare them later. But we must not use malloc(3). */ + original_argc = argc; + original_argv = argv; +} + +# ifdef text_set_element +text_set_element(__libc_subinit, store_args_and_env); +# endif /* text_set_element */ + +# define SWAP_FLAGS(ch1, ch2) \ + if (nonoption_flags_len > 0) \ + { \ + char __tmp = __getopt_nonoption_flags[ch1]; \ + __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ + __getopt_nonoption_flags[ch2] = __tmp; \ + } +#else /* !_LIBC */ +# define SWAP_FLAGS(ch1, ch2) +#endif /* _LIBC */ + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +#if defined (__STDC__) && __STDC__ +static void exchange(char **); +#endif + +static void +exchange(argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. It leaves the + longer segment in the right place overall, but it consists of two parts + that need to be swapped next. */ + +#ifdef _LIBC + /* First make sure the handling of the `__getopt_nonoption_flags' string + can work normally. Our top argument must be in the range of the + string. */ + if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) + { + /* We must extend the array. The user plays games with us and presents + new arguments. */ + char *new_str = malloc(top + 1); + + if (new_str == NULL) + nonoption_flags_len = nonoption_flags_max_len = 0; + else + { + memset(__mempcpy + (new_str, __getopt_nonoption_flags, nonoption_flags_max_len), + '\0', top + 1 - nonoption_flags_max_len); + nonoption_flags_max_len = top + 1; + __getopt_nonoption_flags = new_str; + } + } +#endif + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS(bottom + i, top - (middle - bottom) + i); + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS(bottom + i, middle + i); + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +#if defined (__STDC__) && __STDC__ +static const char *_getopt_initialize(int, char *const *, const char *); +#endif +static const char * +_getopt_initialize(argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 is + the program name); the sequence of previously skipped non-option + ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind; + + nextchar = NULL; + + posixly_correct = getenv("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + +#ifdef _LIBC + if (posixly_correct == NULL && argc == original_argc + && argv == original_argv) + { + if (nonoption_flags_max_len == 0) + { + if (__getopt_nonoption_flags == NULL + || __getopt_nonoption_flags[0] == '\0') + nonoption_flags_max_len = -1; + else + { + const char *orig_str = __getopt_nonoption_flags; + int len = nonoption_flags_max_len = strlen(orig_str); + + if (nonoption_flags_max_len < argc) + nonoption_flags_max_len = argc; + __getopt_nonoption_flags = + (char *) malloc(nonoption_flags_max_len); + if (__getopt_nonoption_flags == NULL) + nonoption_flags_max_len = -1; + else + memset(__mempcpy(__getopt_nonoption_flags, orig_str, len), + '\0', nonoption_flags_max_len - len); + } + } + nonoption_flags_len = nonoption_flags_max_len; + } + else + nonoption_flags_len = 0; +#endif + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns -1. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal(argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + optarg = NULL; + + if (optind == 0 || !__getopt_initialized) + { + if (optind == 0) + optind = 1; /* Don't scan ARGV[0], the + program name. */ + optstring = _getopt_initialize(argc, argv, optstring); + __getopt_initialized = 1; + } + + /* Test whether ARGV[optind] points to a non-option argument. Either it + does not have option syntax, or there is an environment flag from the + shell indicating it is not an option. The later information is only + used when the used in the GNU libc. */ +#ifdef _LIBC +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && __getopt_nonoption_flags[optind] == '1')) +#else +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +#endif + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (last_nonopt > optind) + last_nonopt = optind; + if (first_nonopt > optind) + first_nonopt = optind; + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some + non-options, exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options and extend the range of + non-options previously skipped. */ + + while (optind < argc && NONOPTION_P) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. Skip + it like a null option, then exchange with previous non-options as if + it were an option, then skip everything else like a non-option. */ + + if (optind != argc && !strcmp(argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan and back over + any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options that we + previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, either stop + the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (ordering == REQUIRE_ORDER) + return -1; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. Skip the initial + punctuation. */ + + nextchar = + (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is a valid + short option, don't consider it an abbreviated form of a long option + that starts with f. Otherwise there would be no way to give the -f + short option. + + On the other hand, if there's a long option "fubar" and the + ARGV-element is "-fu", do consider that an abbreviation of the long + option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only + && (argv[optind][2] + || !my_index(optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match or abbreviated matches. + */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp(p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) == + (unsigned int) strlen(p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf(stderr, _("%s: option `%s' is ambiguous\n"), argv[0], + argv[optind]); + nextchar += strlen(nextchar); + optind++; + optopt = 0; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf(stderr, + _ + ("%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); + else + /* +option or -option */ + fprintf(stderr, + _ + ("%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[optind - 1][0], pfound->name); + } + + nextchar += strlen(nextchar); + + optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf(stderr, _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen(nextchar); + optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen(nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, or + the option starts with '--' or is not a valid short option, then + it's an error. Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index(optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf(stderr, _("%s: unrecognized option `--%s'\n"), argv[0], + nextchar); + else + /* +option or -option */ + fprintf(stderr, _("%s: unrecognized option `%c%s'\n"), argv[0], + argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index(optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { + if (posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf(stderr, _("%s: illegal option -- %c\n"), argv[0], c); + else + fprintf(stderr, _("%s: invalid option -- %c\n"), argv[0], c); + } + optopt = c; + return '?'; + } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, we + must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf(stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented `optind' once; increment it again when + taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + + /* optarg is now the argument, see if it's in the table of longopts. + */ + + for (nextchar = nameend = optarg; *nameend && *nameend != '='; + nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match or abbreviated + matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp(p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) == strlen(p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) + { + if (opterr) + fprintf(stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen(nextchar); + optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + fprintf(stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name); + + nextchar += strlen(nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf(stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen(nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen(nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + nextchar = NULL; + return 'W'; /* Let the application handle it. + */ + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf(stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; increment it again + when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt(argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal(argc, argv, optstring, (const struct option *) 0, + (int *) 0, 0); +} + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main(argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt(argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf("option %c\n", c); + break; + + case 'a': + printf("option a\n"); + break; + + case 'b': + printf("option b\n"); + break; + + case 'c': + printf("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf("non-option ARGV-elements: "); + while (optind < argc) + printf("%s ", argv[optind++]); + printf("\n"); + } + + exit(0); +} + +#endif /* TEST */ diff --git a/src/getopt.h b/src/getopt.h new file mode 100644 index 0000000..73ec1b7 --- /dev/null +++ b/src/getopt.h @@ -0,0 +1,136 @@ +/* Declarations for getopt. + Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + + extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + + extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + + extern int opterr; + +/* Set to an option character which was unrecognized. */ + + extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + + struct option + { +#if defined (__STDC__) && __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about type + mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; + }; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#if defined (__STDC__) && __STDC__ +#ifdef __GNU_LIBRARY__ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ + extern int getopt(int argc, char *const *argv, const char *shortopts); +#else /* not __GNU_LIBRARY__ */ +#ifndef __cplusplus +/* C++ is more pedantic, and demands a full prototype, not this. + Hope that stdlib.h has a prototype for `getopt'. */ + extern int getopt(); +#endif /* __cplusplus */ +#endif /* __GNU_LIBRARY__ */ + extern int getopt_long(int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); + extern int getopt_long_only(int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ + extern int _getopt_internal(int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ + extern int getopt(); + extern int getopt_long(); + extern int getopt_long_only(); + + extern int _getopt_internal(); +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* getopt.h */ diff --git a/src/getopt1.c b/src/getopt1.c new file mode 100644 index 0000000..24dd347 --- /dev/null +++ b/src/getopt1.c @@ -0,0 +1,187 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "getopt.h" + +#if !defined (__STDC__) || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 +#include +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#include +#endif + +#ifndef NULL +#define NULL 0 +#endif + +int +getopt_long(argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal(argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only(argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal(argc, argv, options, long_options, opt_index, 1); +} + + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +#include + +int +main(argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = + getopt_long(argc, argv, "abc:d:0123456789", long_options, + &option_index); + if (c == -1) + break; + + switch (c) + { + case 0: + printf("option %s", long_options[option_index].name); + if (optarg) + printf(" with arg %s", optarg); + printf("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf("option %c\n", c); + break; + + case 'a': + printf("option a\n"); + break; + + case 'b': + printf("option b\n"); + break; + + case 'c': + printf("option c with value `%s'\n", optarg); + break; + + case 'd': + printf("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf("non-option ARGV-elements: "); + while (optind < argc) + printf("%s ", argv[optind++]); + printf("\n"); + } + + exit(0); +} + +#endif /* TEST */ diff --git a/src/imlib.c b/src/imlib.c new file mode 100644 index 0000000..fc4dcf0 --- /dev/null +++ b/src/imlib.c @@ -0,0 +1,1292 @@ +/* imlib.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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 "filelist.h" +#include "winwidget.h" +#include "options.h" + +#include +#include +#include +#include +#include +#include + +#include "transupp.h" + +Display *disp = NULL; +Visual *vis = NULL; +Screen *scr = NULL; +Colormap cm; +int depth; +Atom wmDeleteWindow; +XContext xid_context = 0; +Window root = 0; + +/* Xinerama support */ +#ifdef HAVE_LIBXINERAMA +XineramaScreenInfo *xinerama_screens = NULL; +int xinerama_screen; +int num_xinerama_screens; +#endif /* HAVE_LIBXINERAMA */ + +#ifdef HAVE_LIBXINERAMA +void +init_xinerama(void) +{ + if (opt.xinerama && XineramaIsActive(disp)) { + int major, minor; + xinerama_screen = 0; + XineramaQueryVersion(disp, &major, &minor); + xinerama_screens = XineramaQueryScreens(disp, &num_xinerama_screens); + } +} +#endif /* HAVE_LIBXINERAMA */ + +void +init_x_and_imlib(void) +{ + D_ENTER(4); + + disp = XOpenDisplay(NULL); + if (!disp) + eprintf("Can't open X display. It *is* running, yeah?"); + vis = DefaultVisual(disp, DefaultScreen(disp)); + depth = DefaultDepth(disp, DefaultScreen(disp)); + cm = DefaultColormap(disp, DefaultScreen(disp)); + root = RootWindow(disp, DefaultScreen(disp)); + scr = ScreenOfDisplay(disp, DefaultScreen(disp)); + xid_context = XUniqueContext(); + +#ifdef HAVE_LIBXINERAMA + init_xinerama(); +#endif /* HAVE_LIBXINERAMA */ + + imlib_context_set_display(disp); + imlib_context_set_visual(vis); + imlib_context_set_colormap(cm); + imlib_context_set_color_modifier(NULL); + imlib_context_set_progress_function(NULL); + imlib_context_set_operation(IMLIB_OP_COPY); + wmDeleteWindow = XInternAtom(disp, "WM_DELETE_WINDOW", False); + + /* Initialise random numbers */ + srand(getpid() * time(NULL) % ((unsigned int) -1)); + + /* Set up the font stuff */ + imlib_add_path_to_font_path("."); + imlib_add_path_to_font_path(PREFIX "/share/feh/fonts"); + imlib_add_path_to_font_path("./ttfonts"); + + D_RETURN_(4); +} + +int +feh_load_image_char(Imlib_Image * im, char *filename) +{ + feh_file *file; + int i; + + D_ENTER(4); + file = feh_file_new(filename); + i = feh_load_image(im, file); + feh_file_free(file); + D_RETURN(4, i); +} + +int +feh_load_image(Imlib_Image * im, feh_file * file) +{ + Imlib_Load_Error err; + + D_ENTER(4); + D(3, ("filename is %s, image is %p\n", file->filename, im)); + + if (!file || !file->filename) + D_RETURN(4, 0); + + /* Handle URLs */ + if ((!strncmp(file->filename, "http://", 7)) || + (!strncmp(file->filename, "https://", 8)) || + (!strncmp(file->filename, "ftp://", 6))) + { + char *tmpname = NULL; + char *tempcpy; + + tmpname = feh_http_load_image(file->filename); + if (tmpname == NULL) + D_RETURN(4, 0); + *im = imlib_load_image_with_error_return(tmpname, &err); + if (im) + { + /* load the info now, in case it's needed after we delete the + temporary image file */ + tempcpy = file->filename; + file->filename = tmpname; + feh_file_info_load(file, *im); + file->filename = tempcpy; + } + if ((opt.slideshow) && (opt.reload == 0)) + { + /* Http, no reload, slideshow. Let's keep this image on hand... */ + free(file->filename); + file->filename = estrdup(tmpname); + } + else + { + /* Don't cache the image if we're doing reload + http (webcams etc) */ + if (!opt.keep_http) + unlink(tmpname); + } + if (!opt.keep_http) + add_file_to_rm_filelist(tmpname); + free(tmpname); + } + else + { + *im = imlib_load_image_with_error_return(file->filename, &err); + } + + if ((err) || (!im)) + { + if (opt.verbose && !opt.quiet) + { + fprintf(stdout, "\n"); + reset_output = 1; + } + /* Check error code */ + switch (err) + { + case IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST: + if (!opt.quiet) + weprintf("%s - File does not exist", file->filename); + break; + case IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY: + if (!opt.quiet) + weprintf("%s - Directory specified for image filename", + file->filename); + break; + case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_READ: + if (!opt.quiet) + weprintf("%s - No read access to directory", file->filename); + break; + case IMLIB_LOAD_ERROR_UNKNOWN: + case IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT: + if (!opt.quiet) + weprintf("%s - No Imlib2 loader for that file format", + file->filename); + break; + case IMLIB_LOAD_ERROR_PATH_TOO_LONG: + if (!opt.quiet) + weprintf("%s - Path specified is too long", file->filename); + break; + case IMLIB_LOAD_ERROR_PATH_COMPONENT_NON_EXISTANT: + if (!opt.quiet) + weprintf("%s - Path component does not exist", file->filename); + break; + case IMLIB_LOAD_ERROR_PATH_COMPONENT_NOT_DIRECTORY: + if (!opt.quiet) + weprintf("%s - Path component is not a directory", + file->filename); + break; + case IMLIB_LOAD_ERROR_PATH_POINTS_OUTSIDE_ADDRESS_SPACE: + if (!opt.quiet) + weprintf("%s - Path points outside address space", + file->filename); + break; + case IMLIB_LOAD_ERROR_TOO_MANY_SYMBOLIC_LINKS: + if (!opt.quiet) + weprintf("%s - Too many levels of symbolic links", + file->filename); + break; + case IMLIB_LOAD_ERROR_OUT_OF_MEMORY: + if (!opt.quiet) + weprintf("While loading %s - Out of memory", file->filename); + break; + case IMLIB_LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS: + eprintf("While loading %s - Out of file descriptors", + file->filename); + break; + case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_WRITE: + if (!opt.quiet) + weprintf("%s - Cannot write to directory", file->filename); + break; + case IMLIB_LOAD_ERROR_OUT_OF_DISK_SPACE: + if (!opt.quiet) + weprintf("%s - Cannot write - out of disk space", + file->filename); + break; + default: + if (!opt.quiet) + weprintf + ("While loading %s - Unknown error (%d). Attempting to continue", + file->filename, err); + break; + } + D(3, ("Load *failed*\n")); + D_RETURN(4, 0); + } + + D(3, ("Loaded ok\n")); + D_RETURN(4, 1); +} + +char * +feh_http_load_image(char *url) +{ + char *tmpname; + char *tmpname_timestamper = NULL; + char *basename; + char *newurl = NULL; + char randnum[20]; + int rnum; + char *path = NULL; + + D_ENTER(4); + + if (opt.keep_http) + { + if (opt.output_dir) + path = opt.output_dir; + else + path = ""; + } + else + path = "/tmp/"; + + basename = strrchr(url, '/') + 1; + tmpname = feh_unique_filename(path, basename); + + if (opt.wget_timestamp) + { + char cppid[10]; + pid_t ppid; + + ppid = getpid(); + snprintf(cppid, sizeof(cppid), "%06ld", (long)ppid); + tmpname_timestamper = + estrjoin("", "/tmp/feh_", cppid, "_", basename, NULL); + } + + if (opt.wget_timestamp) + { + newurl = estrdup(url); + } + else + { + rnum = rand(); + snprintf(randnum, sizeof(randnum), "%d", rnum); + newurl = estrjoin("?", url, randnum, NULL); + } + D(3, ("newurl: %s\n", newurl)); + + 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 sockaddr_in addr; + struct hostent *hptr; + 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(4, ("using builtin http collection\n")); + fp = fopen(tmpname, "w"); + if (!fp) + { + weprintf("couldn't write to file %s:", tmpname); + free(tmpname); + D_RETURN(4, NULL); + } + + hostname = feh_strip_hostname(newurl); + if (!hostname) + { + weprintf("couldn't work out hostname from %s:", newurl); + free(tmpname); + free(newurl); + D_RETURN(4, NULL); + } + + D(4, ("trying hostname %s\n", hostname)); + + if (!(hptr = feh_gethostbyname(hostname))) + { + weprintf("error resolving host %s:", hostname); + free(hostname); + free(tmpname); + free(newurl); + D_RETURN(4, NULL); + } + + /* Copy the address of the host to socket description. */ + memcpy(&addr.sin_addr, hptr->h_addr, hptr->h_length); + + /* Set port and protocol */ + addr.sin_family = AF_INET; + addr.sin_port = htons(80); + + if ((sockno = socket(PF_INET, SOCK_STREAM, 0)) == -1) + { + weprintf("error opening socket:"); + free(tmpname); + free(hostname); + free(newurl); + D_RETURN(4, NULL); + } + if (connect(sockno, (struct sockaddr *) &addr, sizeof(addr)) == -1) + { + weprintf("error connecting socket:"); + free(tmpname); + free(hostname); + free(newurl); + D_RETURN(4, NULL); + } + + get_url = strchr(newurl, '/') + 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); + free(newurl); + weprintf("error sending over socket:"); + D_RETURN(4, NULL); + } + free(get_string); + free(host_string); + free(query_string); + free(hostname); + free(newurl); + + 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 */ + } + } /* while read */ + close(sockno); + fclose(fp); + } + else + { + int pid; + int status; + + if ((pid = fork()) < 0) + { + weprintf("open url: fork failed:"); + free(tmpname); + free(newurl); + D_RETURN(4, NULL); + } + else if (pid == 0) + { + char *quiet = NULL; + + if (!opt.verbose) + quiet = estrdup("-q"); + + if (opt.wget_timestamp) + { + execlp("wget", "wget", "-N", "-O", tmpname_timestamper, newurl, + quiet, (char*) NULL); + } + else + { + execlp("wget", "wget", "--cache", "0", newurl, "-O", tmpname, + quiet, (char*) NULL); + } + eprintf("url: exec failed: wget:"); + } + else + { + waitpid(pid, &status, 0); + + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + { + weprintf("url: wget failed to load URL %s\n", url); + free(tmpname); + free(newurl); + D_RETURN(4, NULL); + } + if (opt.wget_timestamp) + { + char cmd[2048]; + + snprintf(cmd, sizeof(cmd), "/bin/cp %s %s", tmpname_timestamper, + tmpname); + system(cmd); + } + } + } + + free(newurl); + D_RETURN(4, tmpname); +} + +struct hostent * +feh_gethostbyname(const char *name) +{ + struct hostent *hp; + unsigned long addr; + + D_ENTER(3); + addr = (unsigned long) inet_addr(name); + if ((int) addr != -1) + hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET); + else + hp = gethostbyname(name); + D_RETURN(3, hp); +} + +char * +feh_strip_hostname(char *url) +{ + char *ret; + char *start; + char *finish; + int len; + + D_ENTER(3); + + start = strchr(url, '/'); + if (!start) + D_RETURN(3, NULL); + + start += 2; + + finish = strchr(start, '/'); + if (!finish) + D_RETURN(3, NULL); + + len = finish - start; + + ret = emalloc(len + 1); + strncpy(ret, start, len); + ret[len] = '\0'; + D_RETURN(3, ret); +} + +void +feh_draw_zoom(winwidget w) +{ + static Imlib_Font fn = NULL; + int tw = 0, th = 0; + Imlib_Image im = NULL; + char buf[100]; + static DATA8 atab[256]; + + D_ENTER(4); + + if (!w->im) + D_RETURN_(4); + + if (!fn) { + fn = gib_imlib_load_font(DEFAULT_FONT); + memset(atab, 0, sizeof(atab)); + } + + if (!fn) + { + weprintf("Couldn't load font for zoom printing"); + D_RETURN_(4); + } + + snprintf(buf, sizeof(buf), "%.0f%%, %dx%d", w->zoom * 100, + (int) (w->im_w * w->zoom), (int) (w->im_h * w->zoom)); + + /* Work out how high the font is */ + gib_imlib_get_text_size(fn, buf, NULL, &tw, &th, IMLIB_TEXT_TO_RIGHT); + + tw += 3; + th += 3; + im = imlib_create_image(tw, th); + if (!im) + eprintf("Couldn't create image. Out of memory?"); + + gib_imlib_image_set_has_alpha(im, 1); + gib_imlib_apply_color_modifier_to_rectangle(im, 0, 0, tw, th, + NULL, NULL, NULL, atab); + gib_imlib_image_fill_rectangle(im, 0, 0, tw, th, 0, 0, 0, 0); + + gib_imlib_text_draw(im, fn, NULL, 2, 2, buf, IMLIB_TEXT_TO_RIGHT, + 0, 0, 0, 255); + gib_imlib_text_draw(im, fn, NULL, 1, 1, buf, IMLIB_TEXT_TO_RIGHT, + 255, 255, 255, 255); + gib_imlib_render_image_on_drawable(w->bg_pmap, im, 0, w->h - th, 1, 1, 0); + gib_imlib_free_image_and_decache(im); + D_RETURN_(4); +} + +void +feh_draw_filename(winwidget w) +{ + static Imlib_Font fn = NULL; + int tw = 0, th = 0; + Imlib_Image im = NULL; + static DATA8 atab[256]; + char *s = NULL; + int len = 0; + + D_ENTER(4); + + if ((!w->file) || (!FEH_FILE(w->file->data)) + || (!FEH_FILE(w->file->data)->filename)) + D_RETURN_(4); + + if (!fn) + { + memset(atab, 0, sizeof(atab)); + if (w->full_screen) + fn = gib_imlib_load_font(DEFAULT_FONT_BIG); + else + fn = gib_imlib_load_font(DEFAULT_FONT); + } + + if (!fn) + { + weprintf("Couldn't load font for filename printing"); + D_RETURN_(4); + } + + /* Work out how high the font is */ + gib_imlib_get_text_size(fn, FEH_FILE(w->file->data)->filename, NULL, &tw, &th, + IMLIB_TEXT_TO_RIGHT); + + /* tw is no longer correct, if the filename is shorter than + * the string "%d of %d" used below in fullscreen mode */ + tw += 3; + th += 3; + im = imlib_create_image(tw, 2*th); + if (!im) + eprintf("Couldn't create image. Out of memory?"); + + gib_imlib_image_set_has_alpha(im, 1); + gib_imlib_apply_color_modifier_to_rectangle(im, 0, 0, tw, 2*th, + NULL, NULL, NULL, atab); + gib_imlib_image_fill_rectangle(im, 0, 0, tw, 2*th, 0, 0, 0, 0); + + gib_imlib_text_draw(im, fn, NULL, 2, 2, FEH_FILE(w->file->data)->filename, + IMLIB_TEXT_TO_RIGHT, 0, 0, 0, 255); + gib_imlib_text_draw(im, fn, NULL, 1, 1, FEH_FILE(w->file->data)->filename, + IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255); + /* Print the position in the filelist, if we are in fullscreen and the + * list has more than one element */ + if (w->full_screen && (gib_list_length(filelist)-1)) + { + /* sic! */ + len = snprintf(NULL, 0, "%d of %d", gib_list_length(filelist), gib_list_length(filelist))+1; + s = emalloc(len); + snprintf(s, len, "%d of %d", + gib_list_num(filelist, current_file) + 1, + gib_list_length(filelist)); + /* This should somehow be right-aligned */ + gib_imlib_text_draw(im, fn, NULL, 2, th+1, s, IMLIB_TEXT_TO_RIGHT, 0, 0, 0, 255); + gib_imlib_text_draw(im, fn, NULL, 1, th, s, IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255); + free(s); + } + + gib_imlib_render_image_on_drawable(w->bg_pmap, im, 0, 0, 1, 1, 0); + + gib_imlib_free_image_and_decache(im); + D_RETURN_(4); +} + +char *build_caption_filename(feh_file *file) { + char *caption_filename; + char *s, *dir; + s = strrchr(file->filename, '/'); + if (s) { + dir = estrdup(file->filename); + s = strrchr(dir, '/'); + *s = '\0'; + } else { + dir = estrdup("."); + } + caption_filename = estrjoin("", + dir, + "/", + opt.caption_path, + "/", + file->name, + ".txt", + NULL); + free(dir); + return caption_filename; +} + +void +feh_draw_caption(winwidget w) +{ + static Imlib_Font fn = NULL; + int tw = 0, th = 0, ww, hh; + int x, y; + Imlib_Image im = NULL; + static DATA8 atab[256]; + char *p; + gib_list *lines, *l; + static gib_style *caption_style = NULL; + feh_file *file; + + D_ENTER(4); + + if (!w->file) { + D_RETURN_(4); + } + file = FEH_FILE(w->file->data); + if (!file->filename) { + D_RETURN_(4); + } + + if (!file->caption) { + char *caption_filename; + caption_filename = build_caption_filename(file); + /* read caption from file */ + file->caption = ereadfile(caption_filename); + free(caption_filename); + } + + if (file->caption == NULL) { + /* caption file is not there, we want to cache that, otherwise we'll stat + * the damn file every time we render the image. Reloading an image will + * always cause the caption to be reread though so we're safe to do so. + * (Before this bit was added, when zooming a captionless image with + * captions enabled, the captions file would be stat()d like 30 times a + * second) - don't forget this function is called from + * winwidget_render_image(). + */ + file->caption = estrdup(""); + D_RETURN_(4); + } + + if (file->caption == '\0') { + D_RETURN_(4); + } + + if (!caption_style) { + caption_style = gib_style_new("caption"); + caption_style->bits = gib_list_add_front(caption_style->bits, + gib_style_bit_new(0,0,0,0,0,0)); + caption_style->bits = gib_list_add_front(caption_style->bits, + gib_style_bit_new(1,1,0,0,0,255)); + } + + if (!fn) + { + memset(atab, 0, sizeof(atab)); + if (w->full_screen) + fn = gib_imlib_load_font(DEFAULT_FONT_BIG); + else + fn = gib_imlib_load_font(DEFAULT_FONT); + } + + if (!fn) + { + weprintf("Couldn't load font for caption printing"); + D_RETURN_(4); + } + + lines = feh_wrap_string(file->caption, w->w, w->h, fn, NULL); + if (!lines) + D_RETURN_(4); + + /* Work out how high/wide the caption is */ + l = lines; + while (l) { + p = (char *) l->data; + gib_imlib_get_text_size(fn, p, caption_style, &ww, &hh, IMLIB_TEXT_TO_RIGHT); + if (ww > tw) + tw = ww; + th += hh; + if (l->next) + th += 1; /* line spacing */ + l = l->next; + } + + /* we don't want the caption overlay larger than our window */ + if (th > w->h) + th = w->h; + if (tw > w->w) + tw = w->w; + + im = imlib_create_image(tw, th); + if (!im) + eprintf("Couldn't create image. Out of memory?"); + + gib_imlib_image_set_has_alpha(im, 1); + gib_imlib_apply_color_modifier_to_rectangle(im, 0, 0, tw, th, + NULL, NULL, NULL, atab); + gib_imlib_image_fill_rectangle(im, 0, 0, tw, th, 0, 0, 0, 0); + + l = lines; + x = 0; + y = 0; + while (l) { + p = (char *) l->data; + gib_imlib_get_text_size(fn, p, caption_style, &ww, &hh, IMLIB_TEXT_TO_RIGHT); + x = (tw - ww) / 2; + if (w->caption_entry) { + gib_imlib_text_draw(im, fn, caption_style, x, y, p, IMLIB_TEXT_TO_RIGHT, + 255, 255, 0, 255); + } else { + gib_imlib_text_draw(im, fn, caption_style, x, y, p, IMLIB_TEXT_TO_RIGHT, + 255, 255, 255, 255); + } + + y += hh + 1; /* line spacing */ + l = l->next; + } + + gib_imlib_render_image_on_drawable(w->bg_pmap, im, (w->w - tw) / 2, w->h - th, 1, 1, 0); + gib_imlib_free_image_and_decache(im); + gib_list_free_and_data(lines); + D_RETURN_(4); +} + + +unsigned char reset_output = 0; + +void +feh_display_status(char stat) +{ + static int i = 0; + static int init_len = 0; + int j = 0; + + D_ENTER(5); + + D(5, ("filelist %p, filelist->next %p\n", filelist, filelist->next)); + + if (!init_len) + init_len = gib_list_length(filelist); + + if (i) + { + if (reset_output) + { + /* There's just been an error message. Unfortunate ;) */ + for (j = 0; j < (((i % 50) + ((i % 50) / 10)) + 7); j++) + fprintf(stdout, " "); + } + + if (!(i % 50)) + { + int len; + char buf[50]; + + len = gib_list_length(filelist); + snprintf(buf, sizeof(buf), " %5d/%d (%d)\n[%3d%%] ", i, init_len, + len, ((int) ((float) i / init_len * 100))); + fprintf(stdout, buf); + } + else if ((!(i % 10)) && (!reset_output)) + fprintf(stdout, " "); + + reset_output = 0; + } + else + fprintf(stdout, "[ 0%%] "); + + fprintf(stdout, "%c", stat); + fflush(stdout); + i++; + D_RETURN_(5); +} + +void feh_edit_inplace_orient(winwidget w, int orientation) { + int ret; + Imlib_Image old; + D_ENTER(4); + if(!w->file + || !w->file->data + || !FEH_FILE(w->file->data)->filename) + D_RETURN_(4); + + if (!strcmp(gib_imlib_image_format(w->im), "jpeg")) { + feh_edit_inplace_lossless_rotate(w, orientation); + feh_reload_image(w, 1, 1); + D_RETURN_(4); + } + + ret = feh_load_image(&old, FEH_FILE(w->file->data)); + if(ret) { + gib_imlib_image_orientate(old, orientation); + gib_imlib_save_image(old, FEH_FILE(w->file->data)->filename); + gib_imlib_free_image(old); + feh_reload_image(w, 1, 1); + } else { + weprintf("failed to load image from disk to edit it in place\n"); + } + + D_RETURN_(4); +} + + +/* TODO max_height is ignored... Could use a function which generates a + * transparent text overlay image, with wrapping and all. Would be useful */ +gib_list * +feh_wrap_string(char *text, int wrap_width, int max_height, Imlib_Font fn, gib_style * style) +{ + gib_list *ll, *lines = NULL, *list = NULL, *words; + gib_list *l = NULL; + char delim[2] = { '\n', '\0' }; + int w, line_width; + int tw, th; + char *p, *pp; + char *line = NULL; + char *temp; + int space_width = 0, m_width = 0, t_width = 0, new_width = 0; + + lines = gib_string_split(text, delim); + + if (wrap_width) + { + gib_imlib_get_text_size(fn, "M M", style, &t_width, NULL, + IMLIB_TEXT_TO_RIGHT); + gib_imlib_get_text_size(fn, "M", style, &m_width, NULL, + IMLIB_TEXT_TO_RIGHT); + space_width = t_width - (2 * m_width); + w = wrap_width; + l = lines; + while (l) + { + line_width = 0; + p = (char *) l->data; + /* quick check to see if whole line fits okay */ + gib_imlib_get_text_size(fn, p, style, &tw, &th, IMLIB_TEXT_TO_RIGHT); + if (tw <= w) { + list = gib_list_add_end(list, estrdup(p)); + } else if (strlen(p) == 0) { + list = gib_list_add_end(list, estrdup("")); + } else if (!strcmp(p, " ")) { + list = gib_list_add_end(list, estrdup(" ")); + } else { + words = gib_string_split(p, " "); + if (words) { + ll = words; + while (ll) { + pp = (char *) ll->data; + if (strcmp(pp, " ")) { + gib_imlib_get_text_size(fn, pp, style, &tw, &th, + IMLIB_TEXT_TO_RIGHT); + if (line_width == 0) + new_width = tw; + else + new_width = line_width + space_width + tw; + if (new_width <= w) { + /* add word to line */ + if (line) { + int len; + + len = strlen(line) + strlen(pp) + 2; + temp = emalloc(len); + snprintf(temp, len, "%s %s", line, pp); + free(line); + line = temp; + } else { + line = estrdup(pp); + } + line_width = new_width; + } else if (line_width == 0) { + /* can't fit single word in :/ + increase width limit to width of word + and jam the bastard in anyhow */ + w = tw; + line = estrdup(pp); + line_width = new_width; + } else { + /* finish this line, start next and add word there */ + if (line) { + list = gib_list_add_end(list, estrdup(line)); + free(line); + line = NULL; + } + line = estrdup(pp); + line_width = tw; + } + } + ll = ll->next; + } + if (line) { + /* finish last line */ + list = gib_list_add_end(list, estrdup(line)); + free(line); + line = NULL; + line_width = 0; + } + gib_list_free_and_data(words); + } + } + l = l->next; + } + gib_list_free_and_data(lines); + lines = list; + } + return lines; +} + +void feh_edit_inplace_lossless_rotate(winwidget w, int orientation) { + FILE *input_file; + FILE *output_file; + struct jpeg_decompress_struct srcinfo; + struct jpeg_compress_struct dstinfo; + struct jpeg_error_mgr jsrcerr, jdsterr; + jvirt_barray_ptr * src_coef_arrays; + jvirt_barray_ptr * dst_coef_arrays; + JCOPY_OPTION copyoption; + jpeg_transform_info transformoption; + int len; + char *outfilename; + char *infilename = FEH_FILE(w->file->data)->filename; + + copyoption = JCOPYOPT_ALL; + transformoption.transform = JXFORM_NONE; + transformoption.trim = FALSE; + transformoption.force_grayscale = FALSE; + + if (orientation == 1) { + transformoption.transform = JXFORM_ROT_90; + } else if (orientation == 2) { + transformoption.transform = JXFORM_ROT_180; + } else { + transformoption.transform = JXFORM_ROT_270; + } + + if ((input_file = fopen(infilename, "rb")) == NULL) { + weprintf("couldn't open file for reading: %s\n", infilename); + D_RETURN_(4); + } + len = strlen(infilename) + sizeof(".tmp") + 1; + outfilename = emalloc(len); + snprintf(outfilename, len, "%s.tmp", infilename); + + if ((output_file = fopen(outfilename, "wb")) == NULL) { + weprintf("couldn't open file for writing: %s\n", outfilename); + free(outfilename); + fclose(input_file); + D_RETURN_(4); + } + + /* Initialize the JPEG decompression object with default error handling. */ + srcinfo.err = jpeg_std_error(&jsrcerr); + jpeg_create_decompress(&srcinfo); + + /* Initialize the JPEG compression object with default error handling. */ + dstinfo.err = jpeg_std_error(&jdsterr); + jpeg_create_compress(&dstinfo); + jsrcerr.trace_level = jdsterr.trace_level; + + /* Specify data source for decompression */ + jpeg_stdio_src(&srcinfo, input_file); + + /* Enable saving of extra markers that we want to copy */ + jcopy_markers_setup(&srcinfo, copyoption); + + /* Read file header */ + (void) jpeg_read_header(&srcinfo, TRUE); + + /* Any space needed by a transform option must be requested before + * jpeg_read_coefficients so that memory allocation will be done right. + */ + jtransform_request_workspace(&srcinfo, &transformoption); + + /* Read source file as DCT coefficients */ + src_coef_arrays = jpeg_read_coefficients(&srcinfo); + + /* Initialize destination compression parameters from source values */ + jpeg_copy_critical_parameters(&srcinfo, &dstinfo); + + /* Adjust destination parameters if required by transform options; + * also find out which set of coefficient arrays will hold the output. + */ + dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo, + src_coef_arrays, + &transformoption); + + /* Specify data destination for compression */ + jpeg_stdio_dest(&dstinfo, output_file); + + /* Start compressor (note no image data is actually written here) */ + jpeg_write_coefficients(&dstinfo, dst_coef_arrays); + + /* Copy to the output file any extra markers that we want to preserve */ + jcopy_markers_execute(&srcinfo, &dstinfo, copyoption); + + /* Execute image transformation */ + jtransform_execute_transformation(&srcinfo, &dstinfo, + src_coef_arrays, + &transformoption); + + /* Finish compression and release memory */ + jpeg_finish_compress(&dstinfo); + jpeg_destroy_compress(&dstinfo); + + (void) jpeg_finish_decompress(&srcinfo); + jpeg_destroy_decompress(&srcinfo); + + fclose(input_file); + fclose(output_file); + + /* TODO fix EXIF tags (orientation, width, height) */ + + /* rename outfilename to infilename.. if it worked */ + if (jsrcerr.num_warnings > 0) { + weprintf("got errors from libjpeg (%d), not replacing file\n", jsrcerr.num_warnings); + } else { + if (rename(outfilename, infilename)) { + weprintf("failed to replace file %s with %s\n", infilename, outfilename); + } + } + free(outfilename); +} + +void +feh_draw_actions(winwidget w) +{ + static Imlib_Font fn = NULL; + int tw = 0, th = 0; + int max_tw = 0; + int line_th = 0; + Imlib_Image im = NULL; + static DATA8 atab[256]; + int i = 0; + int num_actions = 0; + + D_ENTER(4); + +// count the number of defined actions + for (num_actions=0;opt.actions[num_actions];num_actions++) + ; + if (num_actions == 0) + return; + + if ((!w->file) || (!FEH_FILE(w->file->data)) + || (!FEH_FILE(w->file->data)->filename)) + D_RETURN_(4); + + if (!fn) + { + memset(atab, 0, sizeof(atab)); + if (w->full_screen) + fn = gib_imlib_load_font(DEFAULT_FONT_BIG); + else + fn = gib_imlib_load_font(DEFAULT_FONT); + } + + if (!fn) + { + weprintf("Couldn't load font for actions printing"); + D_RETURN_(4); + } + + + gib_imlib_get_text_size(fn, "defined actions:", NULL, &tw, &th, + IMLIB_TEXT_TO_RIGHT); +// Check for the widest line + max_tw = tw; + for (i=0;opt.actions[i];i++) { + gib_imlib_get_text_size(fn, opt.actions[i], NULL, &tw, &th, + IMLIB_TEXT_TO_RIGHT); + if (tw>max_tw) { + max_tw = tw; + } + } + + tw = max_tw; + tw += 3; + th += 3; + line_th = th; + th = (th*num_actions)+line_th; + + im = imlib_create_image(tw, th); + if (!im) + eprintf("Couldn't create image. Out of memory?"); + + gib_imlib_image_set_has_alpha(im, 1); + gib_imlib_apply_color_modifier_to_rectangle(im, 0, 0, tw, th, + NULL, NULL, NULL, atab); + gib_imlib_image_fill_rectangle(im, 0, 0, tw, th, 0, 0, 0, 0); + + gib_imlib_text_draw(im, fn, NULL, 1, 1, "defined actions:", + IMLIB_TEXT_TO_RIGHT, 0, 0, 0, 255); + gib_imlib_text_draw(im, fn, NULL, 2, 2, "defined actions:", + IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255); + + for(i=0;ibg_pmap, im, 0, 0, 1, 1, 0); + + gib_imlib_free_image_and_decache(im); + D_RETURN_(4); +} diff --git a/src/index.c b/src/index.c new file mode 100644 index 0000000..90f34f8 --- /dev/null +++ b/src/index.c @@ -0,0 +1,611 @@ +/* index.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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 "filelist.h" +#include "winwidget.h" +#include "options.h" + +static char *create_index_dimension_string(int w, int h); +static char *create_index_size_string(char *file); +static char *create_index_title_string(int num, int w, int h); + +/* TODO Break this up a bit ;) */ +/* TODO s/bit/lot */ +void +init_index_mode(void) +{ + Imlib_Image im_main; + Imlib_Image im_temp; + int w = 800, h = 600, ww = 0, hh = 0, www, hhh, xxx, yyy; + int x = 0, y = 0; + int bg_w = 0, bg_h = 0; + winwidget winwid = NULL; + Imlib_Image bg_im = NULL, im_thumb = NULL; + int tot_thumb_h; + int text_area_h = 50; + int title_area_h = 0; + Imlib_Font fn = NULL; + Imlib_Font title_fn = NULL; + int text_area_w = 0; + int tw = 0, th = 0; + int fw_name, fw_size, fw_dim, fw, fh; + int vertical = 0; + int max_column_w = 0; + int thumbnailcount = 0; + gib_list *l = NULL, *last = NULL; + feh_file *file = NULL; + int lines; + unsigned char trans_bg = 0; + int index_image_width, index_image_height; + int x_offset_name = 0, x_offset_dim = 0, x_offset_size = 0; + char *s; + + D_ENTER(3); + + if (opt.montage) { + mode = "montage"; + } else { + mode = "index"; + } + + fn = gib_imlib_load_font(opt.font); + + if (opt.title_font) + { + int fh, fw; + + title_fn = gib_imlib_load_font(opt.title_font); + if (!fn) + title_fn = gib_imlib_load_font(DEFAULT_FONT_TITLE); + gib_imlib_get_text_size(title_fn, "W", NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT); + title_area_h = fh + 4; + } + else + title_fn = gib_imlib_load_font(DEFAULT_FONT_TITLE); + + if ((!fn) || (!title_fn)) + eprintf("Error loading fonts"); + + /* Work out how tall the font is */ + gib_imlib_get_text_size(fn, "W", NULL, &tw, &th, IMLIB_TEXT_TO_RIGHT); + /* For now, allow room for the right number of lines with small gaps */ + text_area_h = + ((th + 2) * (opt.index_show_name + opt.index_show_size + + opt.index_show_dim)) + 5; + + /* This includes the text area for index data */ + tot_thumb_h = opt.thumb_h + text_area_h; + + /* Use bg image dimensions for default size */ + if (opt.bg && opt.bg_file) + { + if (!strcmp(opt.bg_file, "trans")) + trans_bg = 1; + else + { + D(3, ("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) + fprintf(stdout, + PACKAGE " - No size restriction specified for index.\n" + " You did specify a background however, so the\n" + " index size has defaulted to the size of the image\n"); + opt.limit_w = bg_w; + opt.limit_h = bg_h; + } + else + { + if (opt.verbose) + fprintf(stdout, + PACKAGE " - No size restriction specified for index.\n" + " Using defaults (width limited to 800)\n"); + opt.limit_w = 800; + } + } + + + /* Here we need to whiz through the files, and look at the filenames and + info in the selected font, work out how much space we need, and + calculate the size of the image we will require */ + + if (opt.limit_w && opt.limit_h) + { + int rec_h = 0; + + w = opt.limit_w; + h = opt.limit_h; + + /* Work out if this is big enough, and give a warning if not */ + + /* Pretend we are limiting width by that specified, loop through, and + see it we fit in the height specified. If not, continue the loop, + and recommend the final value instead. Carry on and make the index + anyway. */ + + for (l = filelist; l; l = l->next) + { + file = FEH_FILE(l->data); + text_area_w = opt.thumb_w; + if (opt.index_show_name) + { + gib_imlib_get_text_size(fn, file->name, NULL, &fw, &fh, + IMLIB_TEXT_TO_RIGHT); + if (fw > text_area_w) + text_area_w = fw; + } + if (opt.index_show_dim) + { + gib_imlib_get_text_size(fn, + create_index_dimension_string(1000, 1000), + NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT); + if (fw > text_area_w) + text_area_w = fw; + } + if (opt.index_show_size) + { + gib_imlib_get_text_size(fn, + create_index_size_string(file->filename), + NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT); + if (fw > text_area_w) + text_area_w = fw; + } + if (text_area_w > opt.thumb_w) + text_area_w += 5; + + if ((x > w - text_area_w)) + { + x = 0; + y += tot_thumb_h; + } + + x += text_area_w; + } + rec_h = y + tot_thumb_h; + + if (h < rec_h) + { + weprintf("The image size you specified (%d by %d) is not large\n" + "enough to hold all the thumnails you specified (%d). To fit all\n" + "the thumnails, either decrease their size, choose a smaller font,\n" + "or use a larger image (may I recommend %d by %d?)", + opt.limit_w, opt.limit_h, filelist_len, opt.limit_w, rec_h); + } + } + else if (opt.limit_h) + { + vertical = 1; + h = opt.limit_h; + /* calc w */ + for (l = filelist; l; l = l->next) + { + file = FEH_FILE(l->data); + text_area_w = opt.thumb_w; + /* Calc width of text */ + if (opt.index_show_name) + { + gib_imlib_get_text_size(fn, file->name, NULL, &fw, &fh, + IMLIB_TEXT_TO_RIGHT); + if (fw > text_area_w) + text_area_w = fw; + } + if (opt.index_show_dim) + { + gib_imlib_get_text_size(fn, + create_index_dimension_string(1000, 1000), + NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT); + if (fw > text_area_w) + text_area_w = fw; + } + if (opt.index_show_size) + { + gib_imlib_get_text_size(fn, + create_index_size_string(file->filename), + NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT); + if (fw > text_area_w) + text_area_w = fw; + } + if (text_area_w > opt.thumb_w) + text_area_w += 5; + + if (text_area_w > max_column_w) + max_column_w = text_area_w; + + if ((y > h - tot_thumb_h)) + { + y = 0; + x += max_column_w; + max_column_w = 0; + } + + y += tot_thumb_h; + } + w = x + text_area_w; + max_column_w = 0; + } + else if (opt.limit_w) + { + w = opt.limit_w; + /* calc h */ + + for (l = filelist; l; l = l->next) + { + file = FEH_FILE(l->data); + text_area_w = opt.thumb_w; + if (opt.index_show_name) + { + gib_imlib_get_text_size(fn, file->name, NULL, &fw, &fh, + IMLIB_TEXT_TO_RIGHT); + if (fw > text_area_w) + text_area_w = fw; + } + if (opt.index_show_dim) + { + gib_imlib_get_text_size(fn, + create_index_dimension_string(1000, 1000), + NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT); + if (fw > text_area_w) + text_area_w = fw; + } + if (opt.index_show_size) + { + gib_imlib_get_text_size(fn, + create_index_size_string(file->filename), + NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT); + if (fw > text_area_w) + text_area_w = fw; + } + + if (text_area_w > opt.thumb_w) + text_area_w += 5; + + if ((x > w - text_area_w)) + { + x = 0; + y += tot_thumb_h; + } + + x += text_area_w; + } + h = y + tot_thumb_h; + } + + x = y = 0; + + index_image_width = w; + index_image_height = h + title_area_h; + im_main = imlib_create_image(index_image_width, index_image_height); + + if (!im_main) + eprintf("Imlib error creating index image, are you low on RAM?"); + + 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 + title_area_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 + title_area_h, 0, 0, + 0, 255); + } + + /* Create the window title at this point */ + + if (!opt.title) + s = estrdup(PACKAGE " [index mode]"); + else + s = estrdup(feh_printf(opt.title, NULL)); + + if (opt.display) + { + winwid = winwidget_create_from_image(im_main, s, WIN_TYPE_SINGLE); + 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); + filelist_len--; + last = NULL; + } + D(4, ("About to load image %s\n", file->filename)); + if (feh_load_image(&im_temp, file) != 0) + { + if (opt.verbose) + feh_display_status('.'); + D(4, ("Successfully loaded %s\n", file->filename)); + www = opt.thumb_w; + hhh = opt.thumb_h; + ww = gib_imlib_image_get_width(im_temp); + hh = gib_imlib_image_get_height(im_temp); + thumbnailcount++; + + 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; + } + + 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(3, ("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); + } + + text_area_w = opt.thumb_w; + /* Now draw on the info text */ + if (opt.index_show_name) + { + gib_imlib_get_text_size(fn, file->name, NULL, &fw_name, &fh, + IMLIB_TEXT_TO_RIGHT); + if (fw_name > text_area_w) + text_area_w = fw_name; + } + if (opt.index_show_dim) + { + gib_imlib_get_text_size(fn, create_index_dimension_string(ww, hh), + NULL, &fw_dim, &fh, IMLIB_TEXT_TO_RIGHT); + if (fw_dim > text_area_w) + text_area_w = fw_dim; + } + if (opt.index_show_size) + { + gib_imlib_get_text_size(fn, + create_index_size_string(file->filename), + NULL, &fw_size, &fh, IMLIB_TEXT_TO_RIGHT); + if (fw_size > text_area_w) + text_area_w = fw_size; + } + if (text_area_w > opt.thumb_w) + text_area_w += 5; + + /* offsets for centering text */ + x_offset_name = (text_area_w - fw_name) / 2; + x_offset_dim = (text_area_w - fw_dim) / 2; + x_offset_size = (text_area_w - fw_size) / 2; + + if (vertical) + { + if (text_area_w > max_column_w) + max_column_w = text_area_w; + if (y > h - tot_thumb_h) + { + y = 0; + x += max_column_w; + max_column_w = 0; + } + if (x > w - text_area_w) + break; + } + else + { + if (x > w - text_area_w) + { + x = 0; + y += tot_thumb_h; + } + if (y > h - tot_thumb_h) + break; + } + + if (opt.aspect) + { + xxx = x + ((opt.thumb_w - www) / 2); + yyy = y + ((opt.thumb_h - hhh) / 2); + } + else + { + /* Ignore the aspect ratio and squash the image in */ + xxx = x; + yyy = y; + } + + /* Draw now */ + 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); + + lines = 0; + if (opt.index_show_name) + gib_imlib_text_draw(im_main, fn, NULL, x + x_offset_name, + y + opt.thumb_h + (lines++ * (th + 2)) + 2, + file->name, IMLIB_TEXT_TO_RIGHT, 255, 255, + 255, 255); + if (opt.index_show_dim) + gib_imlib_text_draw(im_main, fn, NULL, x + x_offset_dim, + y + opt.thumb_h + (lines++ * (th + 2)) + 2, + create_index_dimension_string(ww, hh), + IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255); + if (opt.index_show_size) + gib_imlib_text_draw(im_main, fn, NULL, x + x_offset_size, + y + opt.thumb_h + (lines++ * (th + 2)) + 2, + create_index_size_string(file->filename), + IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255); + + if (vertical) + y += tot_thumb_h; + else + x += text_area_w; + + } + else + { + if (opt.verbose) + feh_display_status('x'); + last = l; + } + if (opt.display) + { + winwidget_render_image(winwid, 0, 0); + if (!feh_main_iteration(0)) + exit(0); + } + } + if (opt.verbose) + fprintf(stdout, "\n"); + + if (opt.title_font) + { + int fw, fh, fx, fy; + char *s; + + s = create_index_title_string(thumbnailcount, w, h); + gib_imlib_get_text_size(title_fn, s, NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT); + fx = (index_image_width - fw) >> 1; + fy = index_image_height - fh - 2; + gib_imlib_text_draw(im_main, title_fn, NULL, fx, fy, s, IMLIB_TEXT_TO_RIGHT, + 255, 255, 255, 255); + } + + 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, 1024); + + 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(stdout, PACKAGE " - File saved as %s\n", output_buf); + fprintf(stdout, + " - Image is %dx%d pixels and contains %d thumbnails\n", + tw, th, thumbnailcount); + } + } + + if (!opt.display) + gib_imlib_free_image_and_decache(im_main); + + free(s); + D_RETURN_(3); +} + + +char * +chop_file_from_full_path(char *str) +{ + D_ENTER(4); + D_RETURN(4, strrchr(str, '/') + 1); +} + +static char * +create_index_size_string(char *file) +{ + static char str[50]; + int size = 0; + double kbs = 0.0; + struct stat st; + + D_ENTER(4); + if (stat(file, &st)) + kbs = 0.0; + else + { + size = st.st_size; + kbs = (double) size / 1000; + } + + snprintf(str, sizeof(str), "%.2fKb", kbs); + D_RETURN(4, str); +} + +static char * +create_index_dimension_string(int w, int h) +{ + static char str[50]; + + D_ENTER(4); + snprintf(str, sizeof(str), "%dx%d", w, h); + D_RETURN(4, str); +} + +static char * +create_index_title_string(int num, int w, int h) +{ + static char str[50]; + + D_ENTER(4); + snprintf(str, sizeof(str), + PACKAGE " index - %d thumbnails, %d by %d pixels", num, w, h); + D_RETURN(4, str); +} diff --git a/src/ipc.c b/src/ipc.c new file mode 100644 index 0000000..4cc38dc --- /dev/null +++ b/src/ipc.c @@ -0,0 +1,94 @@ +/* ipc.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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 "debug.h" +#include "options.h" + +static int session_id = 0; +static char *socket_name; +static int socket_fd = 0; + +int feh_ipc_create_socket(void) { + struct sockaddr_un saddr; + int i; + + if ((socket_fd = socket(AF_UNIX, SOCK_STREAM, 0)) != -1) { + for (i = 0; ; i++) { + saddr.sun_family = AF_UNIX; + snprintf(saddr.sun_path, 108, "%s/feh_%s.%d", feh_get_tmp_dir(), feh_get_user_name(), i); +/* + if (!feh_remote_is_running(i)) { + if ((unlink(saddr.sun_path) == -1) && errno != ENOENT) { + close(socket_fd); + eprintf("feh_ipc_create_socket: failed to unlink %s:", saddr.sun_path); + } + } else { + continue; + } +*/ + if (bind(socket_fd, (struct sockaddr *) &saddr, sizeof(saddr)) != -1) { + session_id = i; + socket_name = estrdup(saddr.sun_path); + listen(socket_fd, 50); + break; + } else { + close(socket_fd); + eprintf("feh_ipc_create_socket: failed to bind %s to a socket:", saddr.sun_path); + } + } + } else { + eprintf("feh_ipc_create_socket: failed to open socket:"); + } +} + +int feh_ipc_get_session_id(void) { + return session_id; +} + +void feh_ipc_cleanup(void) { + close(socket_fd); + unlink(socket_name); + free(socket_name); +} + +static void feh_ipc_write_packet(int fd, void *data, int length) { + feh_ipc_server_header header; + header.version = FEH_IPC_VERSION; + header.data_length = length; + if (data && length > 0) { + write(fd, data, length); + } +} + +static void feh_ipc_write_int(int fd, int val) { + feh_ipc_write_packet(fd, &val, sizeof(int)); +} + +static void feh_ipc_write_string(int fd, char *string) { + feh_ipc_write_packet(fd, &string, string ? strlen(string) + 1 : 0); +} + + diff --git a/src/ipc.h b/src/ipc.h new file mode 100644 index 0000000..63f819e --- /dev/null +++ b/src/ipc.h @@ -0,0 +1,57 @@ +/* ipc.h + +Copyright (C) 1999-2003 Tom Gilbert. + +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. + +*/ + +#ifndef IPC_H +#define IPC_H + +#define FEH_IPC_VERSION 0x100; + +int feh_ipc_create_socket(void); +int feh_ipc_get_session_id(void); + +typedef struct +{ + unsigned int version; + unsigned int command; + unsigned int data_length; +} +feh_ipc_client_header; + +typedef struct +{ + unsigned int version; + unsigned int data_length; +} +feh_ipc_server_header; + +enum { + IPC_CMD_QUIT, + IPC_CMD_FILELIST_NEXT, + IPC_CMD_FILELIST_PREV, +}; + +#endif + + diff --git a/src/jpegint.h b/src/jpegint.h new file mode 100644 index 0000000..95b00d4 --- /dev/null +++ b/src/jpegint.h @@ -0,0 +1,392 @@ +/* + * jpegint.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides common declarations for the various JPEG modules. + * These declarations are considered internal to the JPEG library; most + * applications using the library shouldn't need to include this file. + */ + + +/* Declarations for both compression & decompression */ + +typedef enum { /* Operating modes for buffer controllers */ + JBUF_PASS_THRU, /* Plain stripwise operation */ + /* Remaining modes require a full-image buffer to have been created */ + JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ + JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ + JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ +} J_BUF_MODE; + +/* Values of global_state field (jdapi.c has some dependencies on ordering!) */ +#define CSTATE_START 100 /* after create_compress */ +#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ +#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ +#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */ +#define DSTATE_START 200 /* after create_decompress */ +#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */ +#define DSTATE_READY 202 /* found SOS, ready for start_decompress */ +#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/ +#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */ +#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */ +#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */ +#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */ +#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */ +#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ +#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ + + +/* Declarations for compression modules */ + +/* Master control module */ +struct jpeg_comp_master { + JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); + JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean call_pass_startup; /* True if pass_startup must be called */ + boolean is_last_pass; /* True during last pass */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_c_main_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail)); +}; + +/* Compression preprocessing (downsampling input buffer control) */ +struct jpeg_c_prep_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, + JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail)); +}; + +/* Coefficient buffer control */ +struct jpeg_c_coef_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf)); +}; + +/* Colorspace conversion */ +struct jpeg_color_converter { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, color_convert, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +}; + +/* Downsampling */ +struct jpeg_downsampler { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, downsample, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, + JDIMENSION out_row_group_index)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Forward DCT (also controls coefficient quantization) */ +struct jpeg_forward_dct { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + /* perhaps this should be an array??? */ + JMETHOD(void, forward_DCT, (j_compress_ptr cinfo, + jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks)); +}; + +/* Entropy encoding */ +struct jpeg_entropy_encoder { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics)); + JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); +}; + +/* Marker writing */ +struct jpeg_marker_writer { + JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); + JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); + /* These routines are exported to allow insertion of extra markers */ + /* Probably only COM and APPn markers should be written this way */ + JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, + unsigned int datalen)); + JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); +}; + + +/* Declarations for decompression modules */ + +/* Master control module */ +struct jpeg_decomp_master { + JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ +}; + +/* Input control module */ +struct jpeg_input_controller { + JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); + JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean has_multiple_scans; /* True if file has multiple scans */ + boolean eoi_reached; /* True when EOI has been consumed */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_d_main_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Coefficient buffer control */ +struct jpeg_d_coef_controller { + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); + JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, + JSAMPIMAGE output_buf)); + /* Pointer to array of coefficient virtual arrays, or NULL if none */ + jvirt_barray_ptr *coef_arrays; +}; + +/* Decompression postprocessing (color quantization buffer control) */ +struct jpeg_d_post_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Marker reading & parsing */ +struct jpeg_marker_reader { + JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); + /* Read markers until SOS or EOI. + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + */ + JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); + /* Read a restart marker --- exported for use by entropy decoder only */ + jpeg_marker_parser_method read_restart_marker; + + /* State of marker reader --- nominally internal, but applications + * supplying COM or APPn handlers might like to know the state. + */ + boolean saw_SOI; /* found SOI? */ + boolean saw_SOF; /* found SOF? */ + int next_restart_num; /* next restart number expected (0-7) */ + unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ +}; + +/* Entropy decoding */ +struct jpeg_entropy_decoder { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); + + /* This is here to share code between baseline and progressive decoders; */ + /* other modules probably should not use it */ + boolean insufficient_data; /* set TRUE after emitting warning */ +}; + +/* Inverse DCT (also performs dequantization) */ +typedef JMETHOD(void, inverse_DCT_method_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col)); + +struct jpeg_inverse_dct { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + /* It is useful to allow each component to have a separate IDCT method. */ + inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; +}; + +/* Upsampling (note that upsampler must also call color converter) */ +struct jpeg_upsampler { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, upsample, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Colorspace conversion */ +struct jpeg_color_deconverter { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, color_convert, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); +}; + +/* Color quantization or color precision reduction */ +struct jpeg_color_quantizer { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); + JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, + int num_rows)); + JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); +}; + + +/* Miscellaneous useful macros */ + +#undef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#undef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + + +/* We assume that right shift corresponds to signed division by 2 with + * rounding towards minus infinity. This is correct for typical "arithmetic + * shift" instructions that shift in copies of the sign bit. But some + * C compilers implement >> with an unsigned shift. For these machines you + * must define RIGHT_SHIFT_IS_UNSIGNED. + * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. + * It is only applied with constant shift counts. SHIFT_TEMPS must be + * included in the variables of any routine using RIGHT_SHIFT. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define SHIFT_TEMPS INT32 shift_temp; +#define RIGHT_SHIFT(x,shft) \ + ((shift_temp = (x)) < 0 ? \ + (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ + (shift_temp >> (shft))) +#else +#define SHIFT_TEMPS +#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jinit_compress_master jICompress +#define jinit_c_master_control jICMaster +#define jinit_c_main_controller jICMainC +#define jinit_c_prep_controller jICPrepC +#define jinit_c_coef_controller jICCoefC +#define jinit_color_converter jICColor +#define jinit_downsampler jIDownsampler +#define jinit_forward_dct jIFDCT +#define jinit_huff_encoder jIHEncoder +#define jinit_phuff_encoder jIPHEncoder +#define jinit_marker_writer jIMWriter +#define jinit_master_decompress jIDMaster +#define jinit_d_main_controller jIDMainC +#define jinit_d_coef_controller jIDCoefC +#define jinit_d_post_controller jIDPostC +#define jinit_input_controller jIInCtlr +#define jinit_marker_reader jIMReader +#define jinit_huff_decoder jIHDecoder +#define jinit_phuff_decoder jIPHDecoder +#define jinit_inverse_dct jIIDCT +#define jinit_upsampler jIUpsampler +#define jinit_color_deconverter jIDColor +#define jinit_1pass_quantizer jI1Quant +#define jinit_2pass_quantizer jI2Quant +#define jinit_merged_upsampler jIMUpsampler +#define jinit_memory_mgr jIMemMgr +#define jdiv_round_up jDivRound +#define jround_up jRound +#define jcopy_sample_rows jCopySamples +#define jcopy_block_row jCopyBlocks +#define jzero_far jZeroFar +#define jpeg_zigzag_order jZIGTable +#define jpeg_natural_order jZAGTable +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Compression module initialization routines */ +EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, + boolean transcode_only)); +EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); +/* Decompression module initialization routines */ +EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); +/* Memory manager initialization */ +EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); + +/* Utility routines in jutils.c */ +EXTERN(long) jdiv_round_up JPP((long a, long b)); +EXTERN(long) jround_up JPP((long a, long b)); +EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols)); +EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks)); +EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); +/* Constant tables in jutils.c */ +#if 0 /* This table is not actually needed in v6a */ +extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ +#endif +extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ + +/* Suppress undefined-structure complaints if necessary. */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +#endif +#endif /* INCOMPLETE_TYPES_BROKEN */ diff --git a/src/keyevents.c b/src/keyevents.c new file mode 100644 index 0000000..803b71c --- /dev/null +++ b/src/keyevents.c @@ -0,0 +1,445 @@ +/* keyevents.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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 "thumbnail.h" +#include "filelist.h" +#include "winwidget.h" +#include "options.h" + +void +feh_event_invoke_action(winwidget winwid, char *action) +{ + D_ENTER(4); + D(4, ("action is '%s'\n", action)); + D(4, ("winwid is '%p'\n", winwid)); + if (action) + { + if (opt.slideshow) + { + feh_action_run(FEH_FILE(winwid->file->data),action); + slideshow_change_image(winwid, SLIDE_NEXT); + } + else if ((winwid->type == WIN_TYPE_SINGLE) + || (winwid->type == WIN_TYPE_THUMBNAIL_VIEWER)) + { + feh_action_run(FEH_FILE(winwid->file->data),action); + winwidget_destroy(winwid); + } + else if (winwid->type == WIN_TYPE_THUMBNAIL) + { + printf("actions from the main thumb window aren't currentl supported!\n"); + printf("For now, open the image to perform the action on it.\n"); + } + } + D_RETURN_(4); +} + +void +feh_event_handle_keypress(XEvent * ev) +{ + int len; + char kbuf[20]; + KeySym keysym; + XKeyEvent *kev; + winwidget winwid = NULL; + int curr_screen = 0; + feh_menu_item *selected_item; + feh_menu *selected_menu; + + D_ENTER(4); + + winwid = winwidget_get_from_window(ev->xkey.window); + + /* nuke dupe events, unless we're typing text */ + if (winwid && !winwid->caption_entry) { + while (XCheckTypedWindowEvent(disp, ev->xkey.window, KeyPress, ev)); + } + + kev = (XKeyEvent *) ev; + len = XLookupString(&ev->xkey, (char *) kbuf, sizeof(kbuf), &keysym, NULL); + + /* 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: + feh_menu_hide(menu_root, True); + break; + case XK_Left: + feh_menu_select_parent(selected_menu, selected_item); + break; + case XK_Down: + feh_menu_select_next(selected_menu, selected_item); + break; + case XK_Up: + feh_menu_select_prev(selected_menu, selected_item); + break; + case XK_Right: + feh_menu_select_submenu(selected_menu, selected_item); + break; + case XK_Return: + feh_menu_item_activate(selected_menu, selected_item); + break; + default: + break; + } + if (len <= 0 || len > (int) sizeof(kbuf)) + D_RETURN_(4); + kbuf[len] = '\0'; + + switch (*kbuf) + { + case 'h': + feh_menu_select_parent(selected_menu, selected_item); + break; + case 'j': + feh_menu_select_next(selected_menu, selected_item); + break; + case 'k': + feh_menu_select_prev(selected_menu, selected_item); + break; + case 'l': + feh_menu_select_submenu(selected_menu, selected_item); + break; + case ' ': + feh_menu_item_activate(selected_menu, selected_item); + break; + default: + break; + } + + D_RETURN_(4); + } + + if (winwid == NULL) + D_RETURN_(4); + + if (winwid->caption_entry) { + switch(keysym) { + case XK_Return: + if (kev->state & ControlMask) { + /* insert actual newline */ + ESTRAPPEND(FEH_FILE(winwid->file->data)->caption, "\n"); + winwidget_render_image_cached(winwid); + } else { + /* finish caption entry, write to captions file */ + FILE *fp; + char *caption_filename; + caption_filename = build_caption_filename(FEH_FILE(winwid->file->data)); + 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); + D_RETURN_(4); + } + fprintf(fp, "%s", FEH_FILE(winwid->file->data)->caption); + free(caption_filename); + fclose(fp); + } + break; + case XK_Escape: + /* cancel, revert caption */ + winwid->caption_entry = 0; + free(FEH_FILE(winwid->file->data)->caption); + FEH_FILE(winwid->file->data)->caption = NULL; + winwidget_render_image_cached(winwid); + XFreePixmap(disp, winwid->bg_pmap_cache); + winwid->bg_pmap_cache = 0; + break; + case XK_BackSpace: + /* backspace */ + ESTRTRUNC(FEH_FILE(winwid->file->data)->caption, 1); + winwidget_render_image_cached(winwid); + break; + default: + if(isascii(keysym)) { + /* append to caption */ + ESTRAPPEND_CHAR(FEH_FILE(winwid->file->data)->caption, keysym); + winwidget_render_image_cached(winwid); + } + break; + } + D_RETURN_(4); + } + + + switch (keysym) + { + case XK_Left: + if (opt.slideshow) + slideshow_change_image(winwid, SLIDE_PREV); + break; + case XK_Right: + if (opt.slideshow) + slideshow_change_image(winwid, SLIDE_NEXT); + break; + case XK_Page_Up: + if (opt.slideshow) + slideshow_change_image(winwid, SLIDE_JUMP_BACK); + break; + case XK_Escape: + winwidget_destroy_all(); + break; + case XK_Page_Down: + 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: + if (opt.slideshow) + slideshow_change_image(winwid, SLIDE_FIRST); + break; + case XK_End: + case XK_KP_End: + if (opt.slideshow) + slideshow_change_image(winwid, SLIDE_LAST); + break; + case XK_Tab: + if (opt.draw_actions) + { + opt.draw_actions = 0; + winwidget_rerender_all(0, 1); + } + else + { + opt.draw_actions = 1; + winwidget_rerender_all(0, 1); + } + break; + case XK_Return: + feh_event_invoke_action(winwid,opt.actions[0]); + break; + case XK_0: + feh_event_invoke_action(winwid,opt.actions[0]); + break; + case XK_1: + feh_event_invoke_action(winwid,opt.actions[1]); + break; + case XK_2: + feh_event_invoke_action(winwid,opt.actions[2]); + break; + case XK_3: + feh_event_invoke_action(winwid,opt.actions[3]); + break; + case XK_4: + feh_event_invoke_action(winwid,opt.actions[4]); + break; + case XK_5: + feh_event_invoke_action(winwid,opt.actions[5]); + break; + case XK_6: + feh_event_invoke_action(winwid,opt.actions[6]); + break; + case XK_7: + feh_event_invoke_action(winwid,opt.actions[7]); + break; + case XK_8: + feh_event_invoke_action(winwid,opt.actions[8]); + break; + case XK_9: + feh_event_invoke_action(winwid,opt.actions[9]); + break; + case XK_KP_Left: + winwid->im_x = winwid->im_x - 10; + winwidget_render_image(winwid, 0, 0); + break; + case XK_KP_Right: + winwid->im_x = winwid->im_x + 10; + winwidget_render_image(winwid, 0, 0); + break; + case XK_KP_Up: + winwid->im_y = winwid->im_y - 10; + winwidget_render_image(winwid, 0, 0); + break; + case XK_KP_Down: + winwid->im_y = winwid->im_y + 10; + winwidget_render_image(winwid, 0, 0); + break; + case XK_KP_Add: + winwid->zoom = winwid->zoom * 1.25; + winwidget_render_image(winwid, 0, 0); + break; + case XK_KP_Subtract: + winwid->zoom = winwid->zoom * 0.75; + winwidget_render_image(winwid, 0, 0); + break; + case XK_KP_Multiply: + winwid->zoom = 1; + winwidget_render_image(winwid, 0, 0); + break; + case XK_KP_Divide: + feh_calc_needed_zoom(&winwid->zoom, winwid->im_w, winwid->im_h, winwid->w, winwid->h); + winwidget_render_image(winwid, 0, 0); + break; + default: + break; + } + + if (len <= 0 || len > (int) sizeof(kbuf)) + D_RETURN_(4); + kbuf[len] = '\0'; + + switch (*kbuf) + { + case 'n': + case 'N': + case ' ': + if (opt.slideshow) + slideshow_change_image(winwid, SLIDE_NEXT); + break; + case 'p': + case 'P': + case '\b': + if (opt.slideshow) + slideshow_change_image(winwid, SLIDE_PREV); + break; + case 'q': + case 'Q': + winwidget_destroy_all(); + break; + case 'c': + case 'C': + if (opt.caption_path) + winwid->caption_entry = 1; + winwidget_render_image(winwid, 0, 0); + break; + case 'r': + case 'R': + feh_reload_image(winwid, 0, 0); + break; + case 'h': + case 'H': + slideshow_pause_toggle(winwid); + break; + case 's': + case 'S': + slideshow_save_image(winwid); + break; + case 'f': + case 'F': + feh_save_filelist(); + break; + case 'w': + case 'W': + winwidget_size_to_image(winwid); + break; + case 'm': + case 'M': + winwidget_show_menu(winwid); + break; + case 'x': + case 'X': + winwidget_destroy(winwid); + break; + case '>': + feh_edit_inplace_orient(winwid, 1); + break; + case '<': + feh_edit_inplace_orient(winwid, 3); + break; + case 'v': + case 'V': +#ifdef HAVE_LIBXINERAMA + if (opt.xinerama && xinerama_screens) { + int i, rect[4]; + + /* FIXME: this doesn't do what it should; XGetGeometry always + * returns x,y == 0,0. I think that's due to the hints being passed + * (or more specifically, a missing hint) to X in winwidget_create + */ + winwidget_get_geometry(winwid, rect); + /* printf("window: (%d, %d)\n", rect[0], rect[1]); + printf("found %d screens.\n", num_xinerama_screens); */ + for (i = 0; i < num_xinerama_screens; i++) { + xinerama_screen = 0; + /* printf("%d: [%d, %d, %d, %d] (%d, %d)\n", + i, + xinerama_screens[i].x_org, xinerama_screens[i].y_org, + xinerama_screens[i].width, xinerama_screens[i].height, + rect[0], rect[1]);*/ + if (XY_IN_RECT(rect[0], rect[1], + xinerama_screens[i].x_org, xinerama_screens[i].y_org, + xinerama_screens[i].width, xinerama_screens[i].height)) { + curr_screen = xinerama_screen = i; + break; + } + } + } +#endif /* HAVE_LIBXINERAMA */ + 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_show(winwid); +#ifdef HAVE_LIBXINERAMA + /* if we have xinerama and we're using it, then full screen the window + * on the head that the window was active on */ + if (winwid->full_screen == TRUE && + opt.xinerama && xinerama_screens) { + xinerama_screen = curr_screen; + winwidget_move(winwid, + xinerama_screens[curr_screen].x_org, + xinerama_screens[curr_screen].y_org); + } +#endif /* HAVE_LIBXINERAMA */ + case '=': + case '+': + if (opt.reload < SLIDESHOW_RELOAD_MAX) + opt.reload++; + else if (opt.verbose) + weprintf("Cannot set RELOAD higher than %d seconds.", opt.reload); + break; + case '-': + case '_': + if (opt.reload > 1) + opt.reload--; + else if (opt.verbose) + weprintf("Cannot set RELOAD lower than 1 second."); + break; + default: + break; + } + D_RETURN_(4); +} diff --git a/src/list.c b/src/list.c new file mode 100644 index 0000000..98f9fe7 --- /dev/null +++ b/src/list.c @@ -0,0 +1,116 @@ +/* list.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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 "filelist.h" +#include "options.h" + +void +init_list_mode(void) +{ + gib_list *l; + feh_file *file = NULL; + int j = 0; + + D_ENTER(4); + + mode = "list"; + + if (!opt.customlist) + printf + ("NUM\tFORMAT\tWIDTH\tHEIGHT\tPIXELS\tSIZE(bytes)\tALPHA\tFILENAME\n"); + + for (l = filelist; l; l = l->next) + { + file = FEH_FILE(l->data); + if (opt.customlist) + printf("%s\n", feh_printf(opt.customlist, file)); + else + printf("%d\t%s\t%d\t%d\t%d\t%d\t\t%c\t%s\n", ++j, file->info->format, + file->info->width, file->info->height, file->info->pixels, + file->info->size, file->info->has_alpha ? 'X' : '-', + file->filename); + + feh_action_run(file,opt.actions[0]); + } + exit(0); +} + +void +init_loadables_mode(void) +{ + D_ENTER(4); + mode = "loadables"; + real_loadables_mode(1); + D_RETURN_(4); +} + +void +init_unloadables_mode(void) +{ + D_ENTER(4); + mode = "unloadables"; + real_loadables_mode(0); + D_RETURN_(4); +} + + +void +real_loadables_mode(int loadable) +{ + feh_file *file; + gib_list *l; + + D_ENTER(4); + opt.quiet = 1; + + for (l = filelist; l; l = l->next) + { + Imlib_Image im = NULL; + + file = FEH_FILE(l->data); + + if (feh_load_image(&im, file)) + { + /* loaded ok */ + if (loadable) + { + fprintf(stdout, "%s\n", file->filename); + feh_action_run(file,opt.actions[0]); + } + gib_imlib_free_image_and_decache(im); + } + else + { + /* Oh dear. */ + if (!loadable) + { + fprintf(stdout, "%s\n", file->filename); + feh_action_run(file,opt.actions[0]); + } + } + } + exit(0); +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..745fdf9 --- /dev/null +++ b/src/main.c @@ -0,0 +1,219 @@ +/* main.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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 "filelist.h" +#include "winwidget.h" +#include "timers.h" +#include "options.h" +#include "events.h" +#include "support.h" + +char **cmdargv = NULL; +int cmdargc = 0; +int call_level = 0; +char *mode = NULL; + +int +main(int argc, char **argv) +{ + D_ENTER(4); + atexit(feh_clean_exit); + + init_parse_options(argc, argv); + + init_x_and_imlib(); + + feh_event_init(); + + 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) + init_list_mode(); + else if (opt.loadables) + init_loadables_mode(); + else if (opt.unloadables) + init_unloadables_mode(); + else if (opt.thumbs) + init_thumbnail_mode(); + else if(opt.bgmode) + { + feh_wm_set_bg_file(opt.output_file, opt.bgmode); + exit(0); + } +/* else if (opt.fmmode) + { + fmmode(); + opt.slideshow = 1; + init_slideshow_mode(); + } + */ + else + { + /* Slideshow mode is the default. Because it's spiffy */ + opt.slideshow = 1; + init_slideshow_mode(); + } + + /* main event loop */ + while (feh_main_iteration(1)); + + D_RETURN(4,0); +} + + +/* Return 0 to stop iterating, 1 if ok to continue. */ +int +feh_main_iteration(int block) +{ + static int first = 1; + static int xfd = 0; + static int fdsize = 0; + static double pt = 0.0; + XEvent ev; + struct timeval tval; + fd_set fdset; + int count = 0; + double t1 = 0.0, t2 = 0.0; + fehtimer ft; + + D_ENTER(5); + + if (window_num == 0) + D_RETURN(5,0); + + if (first) + { + /* Only need to set these up the first time */ + xfd = ConnectionNumber(disp); + fdsize = xfd + 1; + pt = feh_get_time(); + first = 0; + } + + /* Timers */ + t1 = feh_get_time(); + t2 = t1 - pt; + pt = t1; + while (XPending(disp)) + { + XNextEvent(disp, &ev); + if (ev_handler[ev.type]) + (*(ev_handler[ev.type])) (&ev); + + if (window_num == 0) + D_RETURN(5,0); + } + XFlush(disp); + + feh_redraw_menus(); + + FD_ZERO(&fdset); + FD_SET(xfd, &fdset); + + /* Timers */ + ft = first_timer; + /* Don't do timers if we're zooming/panning/etc or if we are paused*/ + if (ft && (opt.mode == MODE_NORMAL) && !opt.paused) + { + D(5,("There are timers in the queue\n")); + if (ft->just_added) + { + D(5,("The first timer has just been added\n")); + D(5,("ft->in = %f\n", ft->in)); + ft->just_added = 0; + t1 = ft->in; + } + else + { + D(5,("The first timer was not just added\n")); + t1 = ft->in - t2; + if (t1 < 0.0) + t1 = 0.0; + ft->in = t1; + } + + XSync(disp, False); + D(5,("I next need to action a timer in %f seconds\n", t1)); + /* Only do a blocking select if there's a timer due, or no events + waiting */ + if (t1 == 0.0 || (block && !XPending(disp))) + { + tval.tv_sec = (long) t1; + tval.tv_usec = (long) ((t1 - ((double) tval.tv_sec)) * 1000000); + if (tval.tv_sec < 0) + tval.tv_sec = 0; + if (tval.tv_usec <= 1000) + tval.tv_usec = 1000; + errno = 0; + D(5,("Performing blocking select - waiting for timer or event\n")); + count = select(fdsize, &fdset, NULL, NULL, &tval); + if ((count < 0) + && ((errno == ENOMEM) || (errno == EINVAL) || (errno == EBADF))) + eprintf("Connection to X display lost"); + if ((ft) && (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 */ + feh_handle_timer(); + } + } + } + else + { + /* Don't block if there are events in the queue. That's a bit rude ;-) */ + if (block && !XPending(disp)) + { + errno = 0; + D(5,("Performing blocking select - no timers, or zooming\n")); + count = select(fdsize, &fdset, NULL, NULL, NULL); + if ((count < 0) + && ((errno == ENOMEM) || (errno == EINVAL) || (errno == EBADF))) + eprintf("Connection to X display lost"); + } + } + if (window_num == 0) + D_RETURN(5,0); + D_RETURN(5,1); +} + + +void +feh_clean_exit(void) +{ + D_ENTER(4); + + delete_rm_files(); + + if (opt.filelistfile) + feh_write_filelist(filelist, opt.filelistfile); + + D_RETURN_(4); +} diff --git a/src/md5.c b/src/md5.c new file mode 100644 index 0000000..d6f78b8 --- /dev/null +++ b/src/md5.c @@ -0,0 +1,392 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/*$Id: md5.c $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.c is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). + 1999-05-03 lpd Original version. + */ + +#include "md5.h" + +#ifdef TEST +/* + * Compile with -DTEST to create a self-contained executable test program. + * The test program should print out the same values as given in section + * A.5 of RFC 1321, reproduced below. + */ +#include +main() +{ + static const char *const test[7] = { + "", /*d41d8cd98f00b204e9800998ecf8427e*/ + "a", /*0cc175b9c0f1b6a831c399e269772661*/ + "abc", /*900150983cd24fb0d6963f7d28e17f72*/ + "message digest", /*f96b697d7cb7938d525a2f31aaf161d0*/ + "abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b*/ + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + /*d174ab98d277d9f5a5611c2c9f419d9f*/ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a*/ + }; + int i; + + for (i = 0; i < 7; ++i) { + md5_state_t state; + md5_byte_t digest[16]; + int di; + + md5_init(&state); + md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i])); + md5_finish(&state, digest); + printf("MD5 (\"%s\") = ", test[i]); + for (di = 0; di < 16; ++di) + printf("%02x", digest[di]); + printf("\n"); + } + return 0; +} +#endif /* TEST */ + + +/* + * For reference, here is the program that computed the T values. + */ +#if 0 +#include +main() +{ + int i; + for (i = 1; i <= 64; ++i) { + unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i))); + printf("#define T%d 0x%08lx\n", i, v); + } + return 0; +} +#endif +/* + * End of T computation program. + */ +#define T1 0xd76aa478 +#define T2 0xe8c7b756 +#define T3 0x242070db +#define T4 0xc1bdceee +#define T5 0xf57c0faf +#define T6 0x4787c62a +#define T7 0xa8304613 +#define T8 0xfd469501 +#define T9 0x698098d8 +#define T10 0x8b44f7af +#define T11 0xffff5bb1 +#define T12 0x895cd7be +#define T13 0x6b901122 +#define T14 0xfd987193 +#define T15 0xa679438e +#define T16 0x49b40821 +#define T17 0xf61e2562 +#define T18 0xc040b340 +#define T19 0x265e5a51 +#define T20 0xe9b6c7aa +#define T21 0xd62f105d +#define T22 0x02441453 +#define T23 0xd8a1e681 +#define T24 0xe7d3fbc8 +#define T25 0x21e1cde6 +#define T26 0xc33707d6 +#define T27 0xf4d50d87 +#define T28 0x455a14ed +#define T29 0xa9e3e905 +#define T30 0xfcefa3f8 +#define T31 0x676f02d9 +#define T32 0x8d2a4c8a +#define T33 0xfffa3942 +#define T34 0x8771f681 +#define T35 0x6d9d6122 +#define T36 0xfde5380c +#define T37 0xa4beea44 +#define T38 0x4bdecfa9 +#define T39 0xf6bb4b60 +#define T40 0xbebfbc70 +#define T41 0x289b7ec6 +#define T42 0xeaa127fa +#define T43 0xd4ef3085 +#define T44 0x04881d05 +#define T45 0xd9d4d039 +#define T46 0xe6db99e5 +#define T47 0x1fa27cf8 +#define T48 0xc4ac5665 +#define T49 0xf4292244 +#define T50 0x432aff97 +#define T51 0xab9423a7 +#define T52 0xfc93a039 +#define T53 0x655b59c3 +#define T54 0x8f0ccc92 +#define T55 0xffeff47d +#define T56 0x85845dd1 +#define T57 0x6fa87e4f +#define T58 0xfe2ce6e0 +#define T59 0xa3014314 +#define T60 0x4e0811a1 +#define T61 0xf7537e82 +#define T62 0xbd3af235 +#define T63 0x2ad7d2bb +#define T64 0xeb86d391 + +static void +md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) +{ + md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + md5_word_t t; + +#ifndef ARCH_IS_BIG_ENDIAN +# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */ +#endif +#if ARCH_IS_BIG_ENDIAN + + /* + * On big-endian machines, we must arrange the bytes in the right + * order. (This also works on machines of unknown byte order.) + */ + md5_word_t X[16]; + const md5_byte_t *xp = data; + int i; + + for (i = 0; i < 16; ++i, xp += 4) + X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + +#else /* !ARCH_IS_BIG_ENDIAN */ + + /* + * On little-endian machines, we can process properly aligned data + * without copying it. + */ + md5_word_t xbuf[16]; + const md5_word_t *X; + + if (!((data - (const md5_byte_t *)0) & 3)) { + /* data are properly aligned */ + X = (const md5_word_t *)data; + } else { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } +#endif + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); +#undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ +#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); +#undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); +#undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ +#define I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); +#undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +void +md5_init(md5_state_t *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = 0xefcdab89; + pms->abcd[2] = 0x98badcfe; + pms->abcd[3] = 0x10325476; +} + +void +md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) +{ + const md5_byte_t *p = data; + int left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + md5_word_t nbits = (md5_word_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + pms->count[1]++; + + /* Process an initial partial block. */ + if (offset) { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); +} + +void +md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +{ + static const md5_byte_t pad[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); +} diff --git a/src/md5.h b/src/md5.h new file mode 100644 index 0000000..0193f5d --- /dev/null +++ b/src/md5.h @@ -0,0 +1,94 @@ +/* + Copyright (C) 1999 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/*$Id: md5.h $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321. + It is derived directly from the text of the RFC and not from the + reference implementation. + + The original and principal author of md5.h is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); + added conditionalization for C++ compilation from Martin + Purschke . + 1999-05-03 lpd Original version. + */ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +/* + * This code has some adaptations for the Ghostscript environment, but it + * will compile and run correctly in any environment with 8-bit chars and + * 32-bit ints. Specifically, it assumes that if the following are + * defined, they have the same meaning as in Ghostscript: P1, P2, P3, + * ARCH_IS_BIG_ENDIAN. + */ + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s { + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Initialize the algorithm. */ +#ifdef P1 +void md5_init(P1(md5_state_t *pms)); +#else +void md5_init(md5_state_t *pms); +#endif + +/* Append a string to the message. */ +#ifdef P3 +void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes)); +#else +void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); +#endif + +/* Finish the message and return the digest. */ +#ifdef P2 +void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16])); +#else +void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* md5_INCLUDED */ diff --git a/src/menu.c b/src/menu.c new file mode 100644 index 0000000..34a236a --- /dev/null +++ b/src/menu.c @@ -0,0 +1,2144 @@ +/* menu.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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 "support.h" +#include "thumbnail.h" +#include "winwidget.h" +#include "filelist.h" +#include "options.h" + +Window menu_cover = 0; +feh_menu *menu_root = NULL; +feh_menu *menu_main = NULL; +feh_menu *menu_single_win = NULL; +feh_menu *menu_about_win = NULL; +feh_menu *menu_thumbnail_viewer = NULL; +feh_menu *menu_thumbnail_win = NULL; +feh_menu *menu_bg = NULL; +static feh_menu_list *menus = NULL; +static int common_menus = 0; + +static void feh_menu_cb_about(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_close(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_exit(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_reload(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_remove(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_delete(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_reset(feh_menu * m, + feh_menu_item * i, + void *data); + +static void feh_menu_cb_remove_thumb(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_delete_thumb(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_background_set_tiled(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_background_set_scaled(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_background_set_seamless(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_background_set_centered(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_background_set_tiled_no_file(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_background_set_scaled_no_file(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_background_set_centered_no_file(feh_menu * m, + feh_menu_item * i, + void *data); + +static void feh_menu_cb_sort_filename(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_sort_imagename(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_sort_filesize(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_sort_randomize(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_jump_to(feh_menu * m, + feh_menu_item * i, + void *data); +static feh_menu *feh_menu_func_gen_jump(feh_menu * m, + feh_menu_item * i, + void *data); +static feh_menu *feh_menu_func_gen_info(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_func_free_info(feh_menu * m, + void *data); +static void feh_menu_cb_save_image(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_save_filelist(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_fit(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_opt_draw_filename(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_opt_keep_http(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_opt_freeze_window(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_opt_fullscreen(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_func_free_options(feh_menu * m, + void *data); +static feh_menu *feh_menu_func_gen_options(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_edit_rotate(feh_menu * m, + feh_menu_item * i, + void *data); +static void feh_menu_cb_opt_auto_zoom(feh_menu * m, + feh_menu_item * i, + void *data); +#ifdef HAVE_LIBXINERAMA +static void feh_menu_cb_opt_xinerama(feh_menu * m, + feh_menu_item * i, + void *data); +#endif /* HAVE_LIBXINERAMA */ + + +feh_menu * +feh_menu_new(void) +{ + feh_menu *m; + XSetWindowAttributes attr; + feh_menu_list *l; + static Imlib_Image bg = NULL; + static Imlib_Border border; + + D_ENTER(4); + + m = (feh_menu *) emalloc(sizeof(feh_menu)); + + attr.backing_store = NotUseful; + attr.override_redirect = True; + attr.colormap = cm; + attr.border_pixel = 0; + attr.background_pixmap = None; + attr.save_under = False; + attr.do_not_propagate_mask = True; + + m->win = + XCreateWindow(disp, root, 1, 1, 1, 1, 0, depth, InputOutput, vis, + CWOverrideRedirect | CWSaveUnder | CWBackingStore | + CWColormap | CWBackPixmap | CWBorderPixel | CWDontPropagate, + &attr); + XSelectInput(disp, m->win, + ButtonPressMask | ButtonReleaseMask | EnterWindowMask | + LeaveWindowMask | PointerMotionMask | ButtonMotionMask); + + m->name = NULL; + m->fehwin = NULL; + m->pmap = 0; + m->x = 0; + m->y = 0; + m->w = 0; + m->h = 0; + m->visible = 0; + m->items = NULL; + m->next = NULL; + m->prev = NULL; + m->updates = NULL; + m->needs_redraw = 1; + m->func_free = NULL; + m->data = NULL; + m->calc = 0; + m->bg = NULL; + + l = emalloc(sizeof(feh_menu_list)); + l->menu = m; + l->next = menus; + menus = l; + + if (!bg) { + feh_load_image_char(&bg, opt.menu_bg); + if (bg) { + border.left = opt.menu_border; + border.right = opt.menu_border; + border.top = opt.menu_border; + border.bottom = opt.menu_border; + imlib_context_set_image(bg); + imlib_image_set_border(&border); + } + } + + if (bg) + m->bg = gib_imlib_clone_image(bg); + + D_RETURN(4, m); +} + +void +feh_menu_free(feh_menu * m) +{ + feh_menu_item *i; + feh_menu_list *l, *pl = NULL; + + D_ENTER(4); + + if (m->name) + free(m->name); + XDestroyWindow(disp, m->win); + if (m->pmap) + XFreePixmap(disp, m->pmap); + if (m->updates) + imlib_updates_free(m->updates); + for (i = m->items; i;) { + feh_menu_item *ii; + + ii = i; + i = i->next; + if (ii->func_free) + (ii->func_free) (ii->data); + if (ii->text) + free(ii->text); + if (ii->submenu) + free(ii->submenu); + free(ii); + } + + for (l = menus; l; l = l->next) { + if (l->menu == m) { + if (pl) + pl->next = l->next; + else + menus = l->next; + free(l); + break; + } + pl = l; + } + free(m); + + D_RETURN_(4); +} + +feh_menu_item * +feh_menu_find_selected(feh_menu * m) +{ + feh_menu_item *i; + + D_ENTER(4); + + D(5, ("menu %p\n", m)); + + for (i = m->items; i; i = i->next) { + if (MENU_ITEM_IS_SELECTED(i)) + D_RETURN(4, i); + } + D_RETURN(4, NULL); +} + +feh_menu_item * +feh_menu_find_selected_r(feh_menu * m, feh_menu **parent) +{ + feh_menu_item *i, *ii; + feh_menu *mm; + + D_ENTER(4); + + D(5, ("menu %p\n", m)); + + for (i = m->items; i; i = i->next) { + if (MENU_ITEM_IS_SELECTED(i)) { + if (parent) + *parent = m; + D_RETURN(4, i); + } else if (i->submenu) { + mm = feh_menu_find(i->submenu); + if (mm) { + ii = feh_menu_find_selected_r(mm, parent); + if (ii) + D_RETURN(4, ii); + } + } + } + if (parent) + *parent = m; + D_RETURN(4, NULL); +} + +void +feh_menu_select_next(feh_menu *selected_menu, feh_menu_item *selected_item) { + feh_menu_item *i; + if (!selected_item) { + /* jump to first item, select it */ + feh_menu_select(selected_menu, selected_menu->items); + } else { + i = selected_item; + while (1) { + i = i->next; + if (!i) + i = selected_menu->items; + if (i->func || i->submenu || i->func_gen_sub || i->text) { + break; + } + } + feh_menu_deselect_selected(selected_menu); + feh_menu_select(selected_menu, i); + } +} + +void +feh_menu_select_prev(feh_menu *selected_menu, feh_menu_item *selected_item) { + feh_menu_item *i, *ii; + if (!selected_item) { + /* jump to last item, select it */ + for (i = selected_menu->items; i->next; i = i->next); + feh_menu_select(selected_menu, i); + } else { + i = selected_item; + while (1) { + i = i->prev; + if (!i) { + i = selected_menu->items; + for (ii = selected_menu->items; ii->next; ii = ii->next); + i = ii; + } + if (i->func || i->submenu || i->func_gen_sub || i->text) { + break; + } + } + feh_menu_deselect_selected(selected_menu); + feh_menu_select(selected_menu, i); + } +} + +void +feh_menu_select_parent(feh_menu *selected_menu, feh_menu_item *selected_item) { + feh_menu *m; + feh_menu_item *i; + /* find the parent menu's item which refers to this menu's name */ + if (selected_menu->prev) { + m = selected_menu->prev; + for (i = m->items; i; i = i->next) { + if(i->submenu && !strcmp(i->submenu, selected_menu->name)) + break; + } + /* shouldn't ever happen */ + if (i == NULL) + i = m->items; + feh_menu_deselect_selected(selected_menu); + feh_menu_select(m, i); + } +} + +void +feh_menu_select_submenu(feh_menu *selected_menu, feh_menu_item *selected_item) { + if (selected_menu->next) { + feh_menu_deselect_selected(selected_menu); + feh_menu_select(selected_menu->next, selected_menu->next->items); + } +} + +void feh_menu_item_activate(feh_menu *m, + feh_menu_item *i) { + /* watch out for this. I put it this way around so the menu + goes away *before* we perform the action, if we start + freeing menus on hiding, it will break ;-) */ + if ((i) && (i->func)) { + feh_menu_hide(menu_root, False); + feh_main_iteration(0); + (i->func) (m, i, i->data); + if(m->func_free) + m->func_free(m, m->data); + } +} + +feh_menu_item * +feh_menu_find_at_xy(feh_menu * m, + int x, + int y) +{ + feh_menu_item *i; + + D_ENTER(4); + D(4, ("looking for menu item at %d,%d\n", x, y)); + for (i = m->items; i; i = i->next) { + if (XY_IN_RECT(x, y, i->x, i->y, i->w, i->h)) { + D(4, ("Found an item\n")); + D_RETURN(4, i); + } + } + D(4, ("didn't find an item\n")); + D_RETURN(4, NULL); +} + +void +feh_menu_deselect_selected(feh_menu * m) +{ + feh_menu_item *i; + + D_ENTER(4); + + if (!m) + D_RETURN_(4); + + i = feh_menu_find_selected(m); + if (i) { + D(4, ("found a selected menu, deselecting it\n")); + MENU_ITEM_SET_NORMAL(i); + m->updates = imlib_update_append_rect(m->updates, i->x, i->y, i->w, i->h); + m->needs_redraw = 1; + } + D_RETURN_(4); +} + +void +feh_menu_select(feh_menu * m, + feh_menu_item * i) +{ + D_ENTER(4); + MENU_ITEM_SET_SELECTED(i); + m->updates = imlib_update_append_rect(m->updates, i->x, i->y, i->w, i->h); + m->needs_redraw = 1; + if (m->next) { + m->next->prev = NULL; + feh_menu_hide(m->next, TRUE); + m->next = NULL; + } + if (i->submenu) { + feh_menu *mm; + + mm = feh_menu_find(i->submenu); + if (mm) + feh_menu_show_at_submenu(mm, m, i); + else if (i->func_gen_sub) + feh_menu_show_at_submenu(i->func_gen_sub(m, i, i->data), m, i); + } + D_RETURN_(4); +} + +void +feh_menu_show_at(feh_menu * m, int x, int y) +{ + D_ENTER(4); + + if (m->calc) + feh_menu_calc_size(m); + if (!menu_cover) { + XSetWindowAttributes attr; + + D(4, ("creating menu cover window\n")); + attr.override_redirect = True; + attr.do_not_propagate_mask = True; + menu_cover = + XCreateWindow(disp, root, 0, 0, scr->width, scr->height, 0, 0, + InputOnly, vis, CWOverrideRedirect | CWDontPropagate, + &attr); + XSelectInput(disp, menu_cover, + KeyPressMask | ButtonPressMask | ButtonReleaseMask | + EnterWindowMask | LeaveWindowMask | PointerMotionMask | + ButtonMotionMask); + + XRaiseWindow(disp, menu_cover); + XMapWindow(disp, menu_cover); + menu_root = m; + XUngrabPointer(disp, CurrentTime); + XSetInputFocus(disp, menu_cover, RevertToPointerRoot, CurrentTime); + } + m->visible = 1; + XMoveWindow(disp, m->win, x, y); + m->x = x; + m->y = y; + XRaiseWindow(disp, m->win); + feh_menu_redraw(m); + XMapWindow(disp, m->win); + D_RETURN_(4); +} + +void +feh_menu_show_at_xy(feh_menu * m, + winwidget winwid, + int x, + int y) +{ + D_ENTER(4); + + if (!m) + D_RETURN_(4); + + if (m->calc) + feh_menu_calc_size(m); + m->fehwin = winwid; + if ((x + m->w) > scr->width) + x = scr->width - m->w; + if ((y + m->h) > scr->height) + y = scr->height - m->h; + +#if 0 +/* #ifdef HAVE_LIBXINERAMA */ +/* this doesn't work correctly :( -- pabs */ + if (opt.xinerama && xinerama_screens) { + if ((x + m->w) > xinerama_screens[xinerama_screen].width) + x = xinerama_screens[xinerama_screen].width - m->w; + if ((y + m->h) > xinerama_screens[xinerama_screen].height) + y = xinerama_screens[xinerama_screen].height - m->h; + + } +#endif /* HAVE_LIBXINERAMA */ + + if (x < 0) + x = 0; + if (y < 0) + y = 0; + feh_menu_move(m, x, y); + feh_menu_show(m); + D_RETURN_(4); +} + +void +feh_menu_show_at_submenu(feh_menu * m, + feh_menu * parent_m, + feh_menu_item * i) +{ + int mx, my; + + D_ENTER(4); + + if (!m) + D_RETURN_(4); + + if (m->calc) + feh_menu_calc_size(m); + mx = parent_m->x + parent_m->w; + my = parent_m->y + i->y - FEH_MENU_PAD_TOP; + m->fehwin = parent_m->fehwin; + parent_m->next = m; + m->prev = parent_m; + feh_menu_move(m, mx, my); + feh_menu_show(m); + D_RETURN_(4); +} + +void +feh_menu_move(feh_menu * m, + int x, + int y) +{ + int dx, dy; + + D_ENTER(4); + + if (!m) + D_RETURN_(4); + dx = x - m->x; + dy = y - m->y; + if (m->visible) + XMoveWindow(disp, m->win, x, y); + m->x = x; + m->y = y; + D_RETURN_(4); +} + +void +feh_menu_slide_all_menus_relative(int dx, + int dy) +{ + int i; + feh_menu_list *m; + double vector_len = 0; + int stepx = 0; + int stepy = 0; + + D_ENTER(4); + vector_len = sqrt(dx * dx + dy * dy); + if (vector_len) { + if (dx) + stepx = rint(dx / vector_len); + + if (dy) + stepy = rint(dy / vector_len); + + } + for (i = 0; i < vector_len; i++) { + for (m = menus; m; m = m->next) { + if (m->menu->visible) + feh_menu_move(m->menu, m->menu->x + stepx, m->menu->y + stepy); + + } + XWarpPointer(disp, None, None, 0, 0, 0, 0, stepx, stepy); + } + D_RETURN_(4); +} + +void +feh_menu_hide(feh_menu * m, + int func_free) +{ + D_ENTER(4); + + if (!m->visible) + D_RETURN_(4); + if (m->next) { + m->next->prev = NULL; + feh_menu_hide(m->next, func_free); + m->next = NULL; + } + if (m == menu_root) { + if (menu_cover) { + D(4, ("DESTROYING menu cover\n")); + XDestroyWindow(disp, menu_cover); + menu_cover = 0; + } + menu_root = NULL; + } + m->visible = 0; + XUnmapWindow(disp, m->win); + if (func_free && m->func_free) + m->func_free(m, m->data); + else + feh_menu_deselect_selected(m); + D_RETURN_(4); +} + +void +feh_menu_show(feh_menu * m) +{ + D_ENTER(4); + if (!m) + D_RETURN_(4); + feh_menu_show_at(m, m->x, m->y); + D_RETURN_(4); +} + +feh_menu_item * +feh_menu_add_toggle_entry(feh_menu * m, + char *text, + Imlib_Image icon, + char *submenu, + menu_func func, + void *data, + void (*func_free) (void *data), + int setting) +{ + feh_menu_item *mi; + + D_ENTER(4); + mi = feh_menu_add_entry(m, text, icon, submenu, func, data, func_free); + mi->is_toggle = TRUE; + MENU_ITEM_TOGGLE_SET(mi, setting); + D_RETURN(4, mi); +} + +feh_menu_item * +feh_menu_add_entry(feh_menu * m, + char *text, + Imlib_Image icon, + char *submenu, + menu_func func, + void *data, + void (*func_free) (void *data)) +{ + feh_menu_item *mi, *ptr; + + D_ENTER(4); + + mi = (feh_menu_item *) emalloc(sizeof(feh_menu_item)); + mi->state = MENU_ITEM_STATE_NORMAL; + mi->icon = icon; + mi->is_toggle = FALSE; + if (text) + mi->text = estrdup(text); + else + mi->text = NULL; + if (submenu) + mi->submenu = estrdup(submenu); + else + mi->submenu = NULL; + mi->func = func; + mi->func_free = func_free; + mi->data = data; + mi->func_gen_sub = NULL; + mi->next = NULL; + mi->prev = NULL; + + if (!m->items) + m->items = mi; + else { + for (ptr = m->items; ptr; ptr = ptr->next) { + if (!ptr->next) { + ptr->next = mi; + mi->prev = ptr; + break; + } + } + } + m->calc = 1; + D_RETURN(4, mi); +} + + +void +feh_menu_entry_get_size(feh_menu * m, + feh_menu_item * i, + int *w, + int *h) +{ + int tw, th; + + D_ENTER(4); + + if (i->text) { + gib_imlib_get_text_size(opt.menu_fn, i->text, opt.menu_style_l, &tw, &th, + IMLIB_TEXT_TO_RIGHT); + *w = + tw + FEH_MENUITEM_PAD_LEFT + FEH_MENUITEM_PAD_RIGHT; + *h = + th + FEH_MENUITEM_PAD_TOP + FEH_MENUITEM_PAD_BOTTOM; + } else { + *w = FEH_MENUITEM_PAD_LEFT + FEH_MENUITEM_PAD_RIGHT; + *h = FEH_MENUITEM_PAD_TOP + FEH_MENUITEM_PAD_BOTTOM; + } + + D_RETURN_(4); + m = NULL; +} + +void +feh_menu_calc_size(feh_menu * m) +{ + int prev_w, prev_h; + feh_menu_item *i; + int j = 0, count = 0, max_w = 0, max_h = 0, icon_w = 0, next_w = 0; + int toggle_w = 0; + + D_ENTER(4); + + prev_w = m->w; + prev_h = m->h; + m->calc = 0; + + for (i = m->items; i; i = i->next) { + int w, h; + + feh_menu_entry_get_size(m, i, &w, &h); + if (w > max_w) + max_w = w; + if (h > max_h) + max_h = h; + if (i->submenu) { + next_w = FEH_MENU_SUBMENU_W; + if (FEH_MENU_SUBMENU_H > max_h) + max_h = FEH_MENU_SUBMENU_H; + } + if (i->is_toggle) { + toggle_w = FEH_MENU_TOGGLE_W + FEH_MENU_TOGGLE_PAD; + if (FEH_MENU_TOGGLE_H > max_h) + max_h = FEH_MENU_TOGGLE_H; + } + count++; + } + + for (i = m->items; i; i = i->next) { + if (i->icon) { + Imlib_Image im; + + im = i->icon; + if (im) { + int iw, ih, ow, oh; + + iw = gib_imlib_image_get_width(im); + ih = gib_imlib_image_get_height(im); + if (ih <= max_h) { + ow = iw; + oh = ih; + } else { + ow = (iw * max_h) / ih; + oh = max_h; + } + if (ow > icon_w) + icon_w = ow; + } + } + } + m->h = FEH_MENU_PAD_TOP; + for (i = m->items; i; i = i->next) { + i->x = FEH_MENU_PAD_LEFT; + i->y = m->h; + i->w = max_w + icon_w + toggle_w + next_w; + i->icon_x = FEH_MENUITEM_PAD_LEFT; + i->toggle_x = i->icon_x + icon_w; + i->text_x = i->toggle_x + toggle_w; + i->sub_x = i->text_x + max_w; + if (i->text) + i->h = max_h; + else + i->h = FEH_MENU_SEP_MAX_H; + m->h += i->h; + j++; + } + m->h += FEH_MENU_PAD_BOTTOM; + m->w = + next_w + toggle_w + icon_w + max_w + FEH_MENU_PAD_LEFT + + FEH_MENU_PAD_RIGHT; + + if ((prev_w != m->w) || (prev_h != m->h)) { + if (m->pmap) + XFreePixmap(disp, m->pmap); + m->pmap = 0; + m->needs_redraw = 1; + XResizeWindow(disp, m->win, m->w, m->h); + m->updates = imlib_update_append_rect(m->updates, 0, 0, m->w, m->h); + } + D(4, ("menu size calculated. w=%d h=%d\n", m->w, m->h)); + + /* Make sure bg is same size */ + if (m->bg) { + int bg_w, bg_h; + + bg_w = gib_imlib_image_get_width(m->bg); + bg_h = gib_imlib_image_get_height(m->bg); + + if (m->w != bg_w || m->h != bg_h) { + Imlib_Image newim = imlib_create_image(m->w, m->h); + + D(3, ("resizing bg to %dx%d\n", m->w, m->h)); + + gib_imlib_blend_image_onto_image(newim, m->bg, 0, 0, 0, bg_w, bg_h, 0, + 0, m->w, m->h, 0, 0, 1); + gib_imlib_free_image_and_decache(m->bg); + m->bg = newim; + } + } + + D_RETURN_(4); +} + +void +feh_menu_draw_item(feh_menu * m, + feh_menu_item * i, + Imlib_Image im, + int ox, + int oy) +{ + D_ENTER(5); + + D(5, + ("drawing item %p (text %s) on menu %p (name %s)\n", i, i->text, m, + m->name)); + + if (i->text) { + D(5, ("text item\n")); + if (MENU_ITEM_IS_SELECTED(i)) { + D(5, ("selected item\n")); + /* draw selected image */ + feh_menu_item_draw_at(i->x, i->y, i->w, i->h, im, ox, oy, 1); + } else { + D(5, ("unselected item\n")); + /* draw unselected image */ + feh_menu_item_draw_at(i->x, i->y, i->w, i->h, im, ox, oy, 0); + } + + /* draw text */ + gib_imlib_text_draw(im, opt.menu_fn, opt.menu_style_l, + i->x - ox + i->text_x, + i->y - oy + FEH_MENUITEM_PAD_TOP, i->text, + IMLIB_TEXT_TO_RIGHT, 0, 0, 0, 255); + if (i->icon) { + Imlib_Image im2; + + D(5, ("icon item\n")); + + im2 = i->icon; + if (im2) { + int iw, ih, ow, oh; + + iw = gib_imlib_image_get_width(im2); + ih = gib_imlib_image_get_height(im2); + if (ih <= (i->h - FEH_MENUITEM_PAD_TOP - FEH_MENUITEM_PAD_BOTTOM)) { + ow = iw; + oh = ih; + } else { + ow = + (iw * (i->h - FEH_MENUITEM_PAD_TOP - FEH_MENUITEM_PAD_BOTTOM)) / + ih; + oh = i->h - FEH_MENUITEM_PAD_TOP - FEH_MENUITEM_PAD_BOTTOM; + } + gib_imlib_blend_image_onto_image(im, im2, 0, 0, 0, iw, ih, + i->x + i->icon_x - ox, + i->y + FEH_MENUITEM_PAD_TOP + + (((i->h - FEH_MENUITEM_PAD_TOP - + FEH_MENUITEM_PAD_BOTTOM) - + oh) / 2) - oy, ow, oh, 1, 1, 1); + gib_imlib_free_image(im2); + } + } + if (i->submenu) { + D(5, ("submenu item\n")); + feh_menu_draw_submenu_at(i->x + i->sub_x, + i->y + FEH_MENUITEM_PAD_TOP + + ((i->h - FEH_MENUITEM_PAD_TOP - + FEH_MENUITEM_PAD_BOTTOM - + FEH_MENU_SUBMENU_H) / 2), FEH_MENU_SUBMENU_W, + FEH_MENU_SUBMENU_H, im, ox, oy, + MENU_ITEM_IS_SELECTED(i)); + } + if (i->is_toggle) { + D(5, ("toggleable item\n")); + feh_menu_draw_toggle_at(i->x + i->toggle_x, + i->y + FEH_MENUITEM_PAD_TOP + + ((i->h - FEH_MENUITEM_PAD_TOP - + FEH_MENUITEM_PAD_BOTTOM - + FEH_MENU_TOGGLE_H) / 2), FEH_MENU_TOGGLE_W, + FEH_MENU_TOGGLE_H, im, ox, oy, + MENU_ITEM_IS_ON(i)); + } + } else { + D(5, ("separator item\n")); + feh_menu_draw_separator_at(i->x, i->y, i->w, i->h, im, ox, oy); + } + D_RETURN_(5); + m = NULL; +} + +void +feh_menu_redraw(feh_menu * m) +{ + Imlib_Updates u, uu; + + D_ENTER(5); + + if ((!m->needs_redraw) || (!m->visible) || (!m->updates)) + D_RETURN_(5); + m->needs_redraw = 0; + if (!m->pmap) + m->pmap = XCreatePixmap(disp, m->win, m->w, m->h, depth); + XSetWindowBackgroundPixmap(disp, m->win, m->pmap); + + u = imlib_updates_merge_for_rendering(m->updates, m->w, m->h); + m->updates = NULL; + if (u) { + D(5, ("I have updates to render\n")); + for (uu = u; u; u = imlib_updates_get_next(u)) { + int x, y, w, h; + Imlib_Image im; + + imlib_updates_get_coordinates(u, &x, &y, &w, &h); + D(5, ("update coords %d,%d %d*%d\n", x, y, w, h)); + im = imlib_create_image(w, h); + gib_imlib_image_fill_rectangle(im, 0, 0, w, h, 0, 0, 0, 0); + if (im) { + feh_menu_draw_to_buf(m, im, x, y); + gib_imlib_render_image_on_drawable(m->pmap, im, x, y, 1, 0, 0); + gib_imlib_free_image(im); + XClearArea(disp, m->win, x, y, w, h, False); + } + } + imlib_updates_free(uu); + } + D_RETURN_(5); +} + +feh_menu * +feh_menu_find(char *name) +{ + feh_menu_list *l; + + D_ENTER(4); + for (l = menus; l; l = l->next) { + if ((l->menu->name) && (!strcmp(l->menu->name, name))) + D_RETURN(4, l->menu); + } + D_RETURN(4, NULL); +} + +void +feh_menu_draw_to_buf(feh_menu * m, + Imlib_Image im, + int ox, + int oy) +{ + feh_menu_item *i; + int w, h; + + D_ENTER(5); + w = gib_imlib_image_get_width(im); + h = gib_imlib_image_get_height(im); + + feh_menu_draw_menu_bg(m, im, ox, oy); + + for (i = m->items; i; i = i->next) { + if (RECTS_INTERSECT(i->x, i->y, i->w, i->h, ox, oy, w, h)) + feh_menu_draw_item(m, i, im, ox, oy); + } + D_RETURN_(5); +} + +void +feh_menu_draw_menu_bg(feh_menu * m, + Imlib_Image im, + int ox, + int oy) +{ + int w, h; + + D_ENTER(5); + + w = gib_imlib_image_get_width(im); + h = gib_imlib_image_get_height(im); + + if (m->bg) + gib_imlib_blend_image_onto_image(im, m->bg, 0, ox, oy, w, h, 0, 0, w, h, + 0, 0, 0); + else + gib_imlib_image_fill_rectangle(im, 0, 0, w, h, 205, 203, 176, 255); + + D_RETURN_(5); +} + +void +feh_menu_draw_toggle_at(int x, + int y, + int w, + int h, + Imlib_Image dst, + int ox, + int oy, + int on) +{ + D_ENTER(5); + x -= ox; + y -= oy; + if (on) + gib_imlib_image_fill_rectangle(dst, x, y, w, h, 0, 0, 0, 255); + else + gib_imlib_image_draw_rectangle(dst, x, y, w, h, 0, 0, 0, 255); + D_RETURN_(5); +} + +void +feh_menu_draw_submenu_at(int x, + int y, + int w, + int h, + Imlib_Image dst, + int ox, + int oy, + int selected) +{ + ImlibPolygon poly; + + D_ENTER(5); + + x -= ox; + y -= oy; + + imlib_context_set_image(dst); + poly = imlib_polygon_new(); + imlib_polygon_add_point(poly, x + 2, y + 5); + imlib_polygon_add_point(poly, x + 5, y + 7); + imlib_polygon_add_point(poly, x + 2, y + 11); + imlib_context_set_color(0, 0, 0, 60); + imlib_image_fill_polygon(poly); + imlib_polygon_free(poly); + + poly = imlib_polygon_new(); + imlib_polygon_add_point(poly, x, y + 3); + imlib_polygon_add_point(poly, x + 3, y + 6); + imlib_polygon_add_point(poly, x, y + 9); + imlib_context_set_color(0, 0, 0, 255); + imlib_image_fill_polygon(poly); + imlib_polygon_free(poly); + + D_RETURN_(5); + selected = 0; +} + + +void +feh_menu_draw_separator_at(int x, + int y, + int w, + int h, + Imlib_Image dst, + int ox, + int oy) +{ + D_ENTER(5); + gib_imlib_image_fill_rectangle(dst, x - ox + 2, y - oy + 2, w - 4, h - 4, 0, + 0, 0, 255); + D_RETURN_(5); +} + +void +feh_menu_item_draw_at(int x, + int y, + int w, + int h, + Imlib_Image dst, + int ox, + int oy, + int selected) +{ + D_ENTER(5); + imlib_context_set_image(dst); + if (selected) + gib_imlib_image_fill_rectangle(dst, x - ox, y - oy, w, h, 255, 255, 255, + 178); + D_RETURN_(5); +} + + +void +feh_raise_all_menus(void) +{ + feh_menu_list *l; + + D_ENTER(5); + + for (l = menus; l; l = l->next) { + if (l->menu->visible) + XRaiseWindow(disp, l->menu->win); + } + D_RETURN_(5); +} + +void +feh_redraw_menus(void) +{ + feh_menu_list *l; + + D_ENTER(5); + + for (l = menus; l; l = l->next) { + if (l->menu->needs_redraw) + feh_menu_redraw(l->menu); + } + + D_RETURN_(5); +} + +feh_menu * +feh_menu_get_from_window(Window win) +{ + feh_menu_list *l; + + D_ENTER(5); + for (l = menus; l; l = l->next) + if (l->menu->win == win) + D_RETURN(5, l->menu); + D_RETURN(5, NULL); +} + +void +feh_menu_init_main(void) +{ + feh_menu *m; + feh_menu_item *mi; + + D_ENTER(4); + if (!common_menus) + feh_menu_init_common(); + + menu_main = feh_menu_new(); + menu_main->name = estrdup("MAIN"); + + feh_menu_add_entry(menu_main, "File", NULL, "FILE", NULL, NULL, NULL); + if (opt.slideshow || opt.multiwindow) { +#if 0 + feh_menu_item *mi; + + mi = + feh_menu_add_entry(menu_main, "Jump to", NULL, "JUMP", NULL, NULL, + NULL); + mi->func_gen_sub = feh_menu_func_gen_jump; +#endif + + feh_menu_add_entry(menu_main, "Sort List", NULL, "SORT", NULL, NULL, + NULL); + mi = + feh_menu_add_entry(menu_main, "Image Info", NULL, "INFO", NULL, NULL, + NULL); + mi->func_gen_sub = feh_menu_func_gen_info; + feh_menu_add_entry(menu_main, NULL, NULL, NULL, NULL, NULL, NULL); + } + mi = + feh_menu_add_entry(menu_main, "Options", NULL, "OPTIONS", NULL, NULL, + NULL); + mi->func_gen_sub = feh_menu_func_gen_options; + + if (!opt.full_screen) + feh_menu_add_entry(menu_main, "About " PACKAGE, NULL, NULL, + feh_menu_cb_about, NULL, NULL); + if (opt.multiwindow) + feh_menu_add_entry(menu_main, "Close", NULL, NULL, feh_menu_cb_close, + NULL, NULL); + feh_menu_add_entry(menu_main, "Exit", NULL, NULL, feh_menu_cb_exit, NULL, + NULL); + + m = feh_menu_new(); + m->name = estrdup("FILE"); + feh_menu_add_entry(m, "Reset", NULL, NULL, feh_menu_cb_reset, NULL, NULL); + feh_menu_add_entry(m, "Resize Window", NULL, NULL, feh_menu_cb_fit, NULL, + NULL); + feh_menu_add_entry(m, "Reload", NULL, NULL, feh_menu_cb_reload, NULL, NULL); + feh_menu_add_entry(m, "Save Image", NULL, NULL, feh_menu_cb_save_image, + NULL, NULL); + feh_menu_add_entry(m, "Save List", NULL, NULL, + feh_menu_cb_save_filelist, NULL, NULL); + feh_menu_add_entry(m, "Edit in Place", NULL, "EDIT", NULL, NULL, NULL); + feh_menu_add_entry(m, "Background", NULL, "BACKGROUND", NULL, NULL, NULL); + feh_menu_add_entry(m, NULL, NULL, NULL, NULL, NULL, NULL); + feh_menu_add_entry(m, "Hide", NULL, NULL, feh_menu_cb_remove, NULL, NULL); + feh_menu_add_entry(m, "Delete", NULL, "CONFIRM", NULL, NULL, NULL); + + D_RETURN_(4); +} + + +void +feh_menu_init_common() +{ + int num_desks, i; + char buf[30]; + feh_menu *m; + + D_ENTER(4); + + if (!opt.menu_fn) { + opt.menu_fn = gib_imlib_load_font(opt.menu_font); + if (!opt.menu_fn) + eprintf + ("couldn't load menu font %s, did you make install?\nAre you specifying a nonexistant font?\nDid you tell feh where to find it with --fontpath?", + opt.menu_font); + } + if (!opt.menu_style_l) { + opt.menu_style_l = gib_style_new_from_ascii(opt.menu_style); + if (!opt.menu_style_l) { + weprintf + ("couldn't load style file for menu fonts, (%s).\nDid you make install? Menus will look boring without the style file.", + opt.menu_style); + } + } + + m = feh_menu_new(); + m->name = estrdup("SORT"); + + feh_menu_add_entry(m, "By File Name", NULL, NULL, feh_menu_cb_sort_filename, + NULL, NULL); + feh_menu_add_entry(m, "By Image Name", NULL, NULL, + feh_menu_cb_sort_imagename, NULL, NULL); + if (opt.preload || (opt.sort > SORT_FILENAME)) + feh_menu_add_entry(m, "By File Size", NULL, NULL, + feh_menu_cb_sort_filesize, NULL, NULL); + feh_menu_add_entry(m, "Randomize", NULL, NULL, feh_menu_cb_sort_randomize, + NULL, NULL); + + m = feh_menu_new(); + m->name = estrdup("CONFIRM"); + feh_menu_add_entry(m, "Confirm", NULL, NULL, feh_menu_cb_delete, NULL, + NULL); + + m = feh_menu_new(); + m->name = estrdup("EDIT"); + feh_menu_add_entry(m, "Rotate 90 CW", NULL, NULL, feh_menu_cb_edit_rotate, + (void *) 1, NULL); + feh_menu_add_entry(m, "Rotate 180", NULL, NULL, feh_menu_cb_edit_rotate, + (void *) 2, NULL); + feh_menu_add_entry(m, "Rotate 90 CCW", NULL, NULL, feh_menu_cb_edit_rotate, + (void *) 3, NULL); + + menu_bg = feh_menu_new(); + menu_bg->name = estrdup("BACKGROUND"); + + num_desks = feh_wm_get_num_desks(); + if (num_desks > 1) { + feh_menu_add_entry(menu_bg, "Set Tiled", NULL, "TILED", NULL, NULL, NULL); + feh_menu_add_entry(menu_bg, "Set Seamless", NULL, "SEAMLESS", NULL, NULL, + NULL); + feh_menu_add_entry(menu_bg, "Set Scaled", NULL, "SCALED", NULL, NULL, + NULL); + feh_menu_add_entry(menu_bg, "Set Centered", NULL, "CENTERED", NULL, NULL, + NULL); + + m = feh_menu_new(); + m->name = estrdup("TILED"); + for (i = 0; i < num_desks; i++) { + snprintf(buf, sizeof(buf), "Desktop %d", i + 1); + if (opt.slideshow || opt.multiwindow) + feh_menu_add_entry(m, buf, NULL, NULL, + feh_menu_cb_background_set_tiled, (void *) i, + NULL); + else + feh_menu_add_entry(m, buf, NULL, NULL, + feh_menu_cb_background_set_tiled_no_file, + (void *) i, NULL); + } + + m = feh_menu_new(); + m->name = estrdup("SEAMLESS"); + for (i = 0; i < num_desks; i++) { + snprintf(buf, sizeof(buf), "Desktop %d", i + 1); + feh_menu_add_entry(m, buf, NULL, NULL, + feh_menu_cb_background_set_seamless, (void *) i, + NULL); + } + + + m = feh_menu_new(); + m->name = estrdup("SCALED"); + for (i = 0; i < num_desks; i++) { + snprintf(buf, sizeof(buf), "Desktop %d", i + 1); + + if (opt.slideshow || opt.multiwindow) + feh_menu_add_entry(m, buf, NULL, NULL, + feh_menu_cb_background_set_scaled, (void *) i, + NULL); + else + feh_menu_add_entry(m, buf, NULL, NULL, + feh_menu_cb_background_set_scaled_no_file, + (void *) i, NULL); + } + + m = feh_menu_new(); + m->name = estrdup("CENTERED"); + for (i = 0; i < num_desks; i++) { + snprintf(buf, sizeof(buf), "Desktop %d", i + 1); + if (opt.slideshow || opt.multiwindow) + feh_menu_add_entry(m, buf, NULL, NULL, + feh_menu_cb_background_set_centered, (void *) i, + NULL); + else + feh_menu_add_entry(m, buf, NULL, NULL, + feh_menu_cb_background_set_centered_no_file, + (void *) i, NULL); + } + } else { + if (opt.slideshow || opt.multiwindow) { + feh_menu_add_entry(menu_bg, "Set Tiled", NULL, NULL, + feh_menu_cb_background_set_tiled, NULL, NULL); + feh_menu_add_entry(menu_bg, "Set Seamless", NULL, NULL, + feh_menu_cb_background_set_seamless, NULL, NULL); + feh_menu_add_entry(menu_bg, "Set Scaled", NULL, NULL, + feh_menu_cb_background_set_scaled, NULL, NULL); + feh_menu_add_entry(menu_bg, "Set Centered", NULL, NULL, + feh_menu_cb_background_set_centered, NULL, NULL); + } else { + feh_menu_add_entry(menu_bg, "Set Tiled", NULL, NULL, + feh_menu_cb_background_set_tiled_no_file, NULL, + NULL); + feh_menu_add_entry(menu_bg, "Set Seamless", NULL, NULL, + feh_menu_cb_background_set_seamless, NULL, NULL); + feh_menu_add_entry(menu_bg, "Set Scaled", NULL, NULL, + feh_menu_cb_background_set_scaled_no_file, NULL, + NULL); + feh_menu_add_entry(menu_bg, "Set Centered", NULL, NULL, + feh_menu_cb_background_set_centered_no_file, NULL, + NULL); + } + } + common_menus = 1; + + D_RETURN_(4); +} + +void +feh_menu_init_about_win(void) +{ + D_ENTER(4); + + menu_about_win = feh_menu_new(); + menu_about_win->name = estrdup("ABOUTWIN"); + + feh_menu_add_entry(menu_about_win, "Close", NULL, NULL, feh_menu_cb_close, + NULL, NULL); + feh_menu_add_entry(menu_about_win, "Exit", NULL, NULL, feh_menu_cb_exit, + NULL, NULL); + + D_RETURN_(4); +} + +void +feh_menu_init_single_win(void) +{ + feh_menu *m; + feh_menu_item *mi; + + D_ENTER(4); + if (!common_menus) + feh_menu_init_common(); + + menu_single_win = feh_menu_new(); + menu_single_win->name = estrdup("SINGLEWIN"); + + feh_menu_add_entry(menu_single_win, "File", NULL, "SINGLEWIN_FILE", NULL, + NULL, NULL); + m = feh_menu_new(); + m->name = estrdup("SINGLEWIN_FILE"); + feh_menu_add_entry(m, "Reset", NULL, NULL, feh_menu_cb_reset, NULL, NULL); + feh_menu_add_entry(m, "Resize Window", NULL, NULL, feh_menu_cb_fit, NULL, + NULL); + feh_menu_add_entry(m, "Reload", NULL, NULL, feh_menu_cb_reload, NULL, NULL); + feh_menu_add_entry(m, "Save Image", NULL, NULL, feh_menu_cb_save_image, + NULL, NULL); + feh_menu_add_entry(m, "Save List", NULL, NULL, + feh_menu_cb_save_filelist, NULL, NULL); + feh_menu_add_entry(m, "Edit in Place", NULL, "EDIT", NULL, NULL, NULL); + feh_menu_add_entry(m, "Background", NULL, "BACKGROUND", NULL, NULL, NULL); + if (opt.multiwindow || opt.slideshow) { + feh_menu_add_entry(m, NULL, NULL, NULL, NULL, NULL, NULL); + feh_menu_add_entry(m, "Hide", NULL, NULL, feh_menu_cb_remove, NULL, NULL); + feh_menu_add_entry(m, "Delete", NULL, "CONFIRM", NULL, NULL, NULL); + } + + mi = + feh_menu_add_entry(menu_single_win, "Image Info", NULL, "INFO", NULL, + NULL, NULL); + mi->func_gen_sub = feh_menu_func_gen_info; + feh_menu_add_entry(menu_single_win, NULL, NULL, NULL, NULL, NULL, NULL); + mi = + feh_menu_add_entry(menu_single_win, "Options", NULL, "OPTIONS", NULL, + NULL, NULL); + mi->func_gen_sub = feh_menu_func_gen_options; + feh_menu_add_entry(menu_single_win, "About " PACKAGE, NULL, NULL, + feh_menu_cb_about, NULL, NULL); + feh_menu_add_entry(menu_single_win, "Close", NULL, NULL, feh_menu_cb_close, + NULL, NULL); + feh_menu_add_entry(menu_single_win, "Exit", NULL, NULL, feh_menu_cb_exit, + NULL, NULL); + + D_RETURN_(4); +} + +void +feh_menu_init_thumbnail_win(void) +{ + feh_menu *m; + feh_menu_item *mi; + + D_ENTER(4); + if (!common_menus) + feh_menu_init_common(); + + menu_thumbnail_win = feh_menu_new(); + menu_thumbnail_win->name = estrdup("THUMBWIN"); + + feh_menu_add_entry(menu_thumbnail_win, "File", NULL, "THUMBWIN_FILE", NULL, + NULL, NULL); + m = feh_menu_new(); + m->name = estrdup("THUMBWIN_FILE"); + feh_menu_add_entry(m, "Reset", NULL, NULL, feh_menu_cb_reset, NULL, NULL); + feh_menu_add_entry(m, "Resize Window", NULL, NULL, feh_menu_cb_fit, NULL, + NULL); + feh_menu_add_entry(m, "Save Image", NULL, NULL, feh_menu_cb_save_image, + NULL, NULL); + feh_menu_add_entry(m, "Save List", NULL, NULL, + feh_menu_cb_save_filelist, NULL, NULL); + feh_menu_add_entry(m, "Background", NULL, "BACKGROUND", NULL, NULL, NULL); + feh_menu_add_entry(menu_thumbnail_win, NULL, NULL, NULL, NULL, NULL, NULL); + mi = + feh_menu_add_entry(menu_thumbnail_win, "Options", NULL, "OPTIONS", NULL, + NULL, NULL); + mi->func_gen_sub = feh_menu_func_gen_options; + feh_menu_add_entry(menu_thumbnail_win, "About " PACKAGE, NULL, NULL, + feh_menu_cb_about, NULL, NULL); + feh_menu_add_entry(menu_thumbnail_win, "Close", NULL, NULL, + feh_menu_cb_close, NULL, NULL); + feh_menu_add_entry(menu_thumbnail_win, "Exit", NULL, NULL, feh_menu_cb_exit, + NULL, NULL); + D_RETURN_(4); +} + + +void +feh_menu_init_thumbnail_viewer(void) +{ + feh_menu *m; + feh_menu_item *mi; + + D_ENTER(4); + if (!common_menus) + feh_menu_init_common(); + + menu_thumbnail_viewer = feh_menu_new(); + menu_thumbnail_viewer->name = estrdup("THUMBVIEW"); + + feh_menu_add_entry(menu_thumbnail_viewer, "File", NULL, "THUMBVIEW_FILE", + NULL, NULL, NULL); + m = feh_menu_new(); + m->name = estrdup("THUMBVIEW_FILE"); + feh_menu_add_entry(m, "Reset", NULL, NULL, feh_menu_cb_reset, NULL, NULL); + feh_menu_add_entry(m, "Resize Window", NULL, NULL, feh_menu_cb_fit, NULL, + NULL); + feh_menu_add_entry(m, "Reload", NULL, NULL, feh_menu_cb_reload, NULL, NULL); + feh_menu_add_entry(m, "Save Image", NULL, NULL, feh_menu_cb_save_image, + NULL, NULL); + feh_menu_add_entry(m, "Save List", NULL, NULL, + feh_menu_cb_save_filelist, NULL, NULL); + feh_menu_add_entry(m, "Edit in Place", NULL, "EDIT", NULL, NULL, NULL); + feh_menu_add_entry(m, "Background", NULL, "BACKGROUND", NULL, NULL, NULL); + feh_menu_add_entry(m, NULL, NULL, NULL, NULL, NULL, NULL); + feh_menu_add_entry(m, "Hide", NULL, NULL, feh_menu_cb_remove_thumb, NULL, + NULL); + feh_menu_add_entry(m, "Delete", NULL, "THUMBVIEW_CONFIRM", NULL, NULL, + NULL); + mi = + feh_menu_add_entry(menu_thumbnail_viewer, "Image Info", NULL, "INFO", + NULL, NULL, NULL); + mi->func_gen_sub = feh_menu_func_gen_info; + feh_menu_add_entry(menu_thumbnail_viewer, NULL, NULL, NULL, NULL, NULL, + NULL); + mi = + feh_menu_add_entry(menu_thumbnail_viewer, "Options", NULL, "OPTIONS", + NULL, NULL, NULL); + mi->func_gen_sub = feh_menu_func_gen_options; + feh_menu_add_entry(menu_thumbnail_viewer, "About " PACKAGE, NULL, NULL, + feh_menu_cb_about, NULL, NULL); + feh_menu_add_entry(menu_thumbnail_viewer, "Close", NULL, NULL, + feh_menu_cb_close, NULL, NULL); + feh_menu_add_entry(menu_thumbnail_viewer, "Exit", NULL, NULL, + feh_menu_cb_exit, NULL, NULL); + m = feh_menu_new(); + m->name = estrdup("THUMBVIEW_CONFIRM"); + feh_menu_add_entry(m, "Confirm", NULL, NULL, feh_menu_cb_delete_thumb, NULL, + NULL); + D_RETURN_(4); +} + +static void +feh_menu_cb_background_set_tiled(feh_menu * m, + feh_menu_item * i, + void *data) +{ + char *path; + + D_ENTER(4); + path = feh_absolute_path(FEH_FILE(m->fehwin->file->data)->filename); + feh_wm_set_bg(path, m->fehwin->im, 0, 0, (int) data, 1); + free(path); + D_RETURN_(4); + i = NULL; +} + +static void +feh_menu_cb_background_set_seamless(feh_menu * m, + feh_menu_item * i, + void *data) +{ + Imlib_Image im; + + D_ENTER(4); + im = gib_imlib_clone_image(m->fehwin->im); + gib_imlib_image_tile(im); + feh_wm_set_bg(NULL, im, 0, 0, (int) data, 1); + gib_imlib_free_image_and_decache(im); + D_RETURN_(4); + i = NULL; +} + +static void +feh_menu_cb_background_set_scaled(feh_menu * m, + feh_menu_item * i, + void *data) +{ + char *path; + + D_ENTER(4); + path = feh_absolute_path(FEH_FILE(m->fehwin->file->data)->filename); + feh_wm_set_bg(path, m->fehwin->im, 0, 1, (int) data, 1); + free(path); + D_RETURN_(4); + i = NULL; +} + +static void +feh_menu_cb_background_set_centered(feh_menu * m, + feh_menu_item * i, + void *data) +{ + char *path; + + D_ENTER(4); + path = feh_absolute_path(FEH_FILE(m->fehwin->file->data)->filename); + feh_wm_set_bg(path, m->fehwin->im, 1, 0, (int) data, 1); + free(path); + D_RETURN_(4); + i = NULL; +} + +static void +feh_menu_cb_background_set_tiled_no_file(feh_menu * m, + feh_menu_item * i, + void *data) +{ + D_ENTER(4); + feh_wm_set_bg(NULL, m->fehwin->im, 0, 0, (int) data, 1); + D_RETURN_(4); + i = NULL; +} + +static void +feh_menu_cb_background_set_scaled_no_file(feh_menu * m, + feh_menu_item * i, + void *data) +{ + D_ENTER(4); + feh_wm_set_bg(NULL, m->fehwin->im, 0, 1, (int) data, 1); + D_RETURN_(4); + i = NULL; +} + +static void +feh_menu_cb_background_set_centered_no_file(feh_menu * m, + feh_menu_item * i, + void *data) +{ + D_ENTER(4); + feh_wm_set_bg(NULL, m->fehwin->im, 1, 0, (int) data, 1); + D_RETURN_(4); + i = NULL; +} + +static void +feh_menu_cb_about(feh_menu * m, + feh_menu_item * i, + void *data) +{ + Imlib_Image im; + winwidget winwid; + + D_ENTER(4); + if (feh_load_image_char(&im, PREFIX "/share/feh/images/about.png") != 0) { + winwid = + winwidget_create_from_image(im, "About " PACKAGE, WIN_TYPE_ABOUT); + winwid->file = + gib_list_add_front(NULL, + feh_file_new(PREFIX "/share/feh/images/about.png")); + winwidget_show(winwid); + } + D_RETURN_(4); + m = NULL; + i = NULL; + data = NULL; +} + +static void +feh_menu_cb_close(feh_menu * m, + feh_menu_item * i, + void *data) +{ + D_ENTER(4); + winwidget_destroy(m->fehwin); + D_RETURN_(4); + i = NULL; + data = NULL; +} + +static void +feh_menu_cb_exit(feh_menu * m, + feh_menu_item * i, + void *data) +{ + D_ENTER(4); + winwidget_destroy_all(); + D_RETURN_(4); + m = NULL; + i = NULL; + data = NULL; +} + +static void +feh_menu_cb_reset(feh_menu * m, + feh_menu_item * i, + void *data) +{ + D_ENTER(4); + if (m->fehwin->has_rotated) { + m->fehwin->im_w = gib_imlib_image_get_width(m->fehwin->im); + m->fehwin->im_h = gib_imlib_image_get_height(m->fehwin->im); + winwidget_resize(m->fehwin, m->fehwin->im_w, m->fehwin->im_h); + } + winwidget_reset_image(m->fehwin); + winwidget_render_image(m->fehwin, 1, 1); + D_RETURN_(4); + i = NULL; + data = NULL; +} + + +static void +feh_menu_cb_reload(feh_menu * m, + feh_menu_item * i, + void *data) +{ + D_ENTER(4); + feh_reload_image(m->fehwin, 0, 0); + D_RETURN_(4); + i = NULL; + data = NULL; +} + +static void +feh_menu_cb_remove(feh_menu * m, + feh_menu_item * i, + void *data) +{ + D_ENTER(4); + feh_filelist_image_remove(m->fehwin, 0); + D_RETURN_(4); + i = NULL; + data = NULL; +} + +static void +feh_menu_cb_delete(feh_menu * m, + feh_menu_item * i, + void *data) +{ + D_ENTER(4); + feh_filelist_image_remove(m->fehwin, 1); + D_RETURN_(4); + i = NULL; + data = NULL; +} + +static void +feh_menu_cb_remove_thumb(feh_menu * m, + feh_menu_item * i, + void *data) +{ + D_ENTER(4); + feh_thumbnail_mark_removed(FEH_FILE(m->fehwin->file->data), 0); + feh_filelist_image_remove(m->fehwin, 0); + D_RETURN_(4); + i = NULL; + data = NULL; +} + +static void +feh_menu_cb_delete_thumb(feh_menu * m, + feh_menu_item * i, + void *data) +{ + D_ENTER(4); + feh_thumbnail_mark_removed(FEH_FILE(m->fehwin->file->data), 1); + feh_filelist_image_remove(m->fehwin, 1); + D_RETURN_(4); + i = NULL; + data = NULL; +} + + +static void +feh_menu_cb_sort_filename(feh_menu * m, + feh_menu_item * i, + void *data) +{ + D_ENTER(4); + filelist = gib_list_sort(filelist, feh_cmp_filename); + if(!opt.no_jump_on_resort){ + slideshow_change_image(m->fehwin, SLIDE_FIRST); + }; + D_RETURN_(4); + i = NULL; + data = NULL; +} + +static void +feh_menu_cb_sort_imagename(feh_menu * m, + feh_menu_item * i, + void *data) +{ + D_ENTER(4); + filelist = gib_list_sort(filelist, feh_cmp_name); + if(!opt.no_jump_on_resort){ + slideshow_change_image(m->fehwin, SLIDE_FIRST); + }; + D_RETURN_(4); + i = NULL; + data = NULL; +} + +static void +feh_menu_cb_sort_filesize(feh_menu * m, + feh_menu_item * i, + void *data) +{ + D_ENTER(4); + filelist = gib_list_sort(filelist, feh_cmp_size); + if(!opt.no_jump_on_resort){ + slideshow_change_image(m->fehwin, SLIDE_FIRST); + }; + D_RETURN_(4); + i = NULL; + data = NULL; +} + +static void +feh_menu_cb_sort_randomize(feh_menu * m, + feh_menu_item * i, + void *data) +{ + D_ENTER(4); + filelist = gib_list_randomize(filelist); + if(!opt.no_jump_on_resort){ + slideshow_change_image(m->fehwin, SLIDE_FIRST); + }; + D_RETURN_(4); + i = NULL; + data = NULL; +} + +static feh_menu * +feh_menu_func_gen_jump(feh_menu * m, + feh_menu_item * i, + void *data) +{ + feh_menu *mm; + gib_list *l; + + D_ENTER(4); + mm = feh_menu_new(); + mm->name = estrdup("JUMP"); + for (l = filelist; l; l = l->next) { + feh_menu_add_entry(mm, FEH_FILE(l->data)->name, NULL, NULL, + feh_menu_cb_jump_to, l, NULL); + } + D_RETURN(4, mm); + m = NULL; + i = NULL; + data = NULL; +} + +static feh_menu * +feh_menu_func_gen_info(feh_menu * m, + feh_menu_item * i, + void *data) +{ + Imlib_Image im; + feh_menu *mm; + feh_file *file; + char buffer[400]; + + D_ENTER(4); + if (!m->fehwin->file) + D_RETURN(4, NULL); + file = FEH_FILE(m->fehwin->file->data); + im = m->fehwin->im; + if (!im) + D_RETURN(4, NULL); + mm = feh_menu_new(); + mm->name = estrdup("INFO"); + snprintf(buffer, sizeof(buffer), "Filename: %s", file->name); + feh_menu_add_entry(mm, buffer, NULL, NULL, NULL, NULL, NULL); + if (!file->info) + feh_file_info_load(file, im); + if (file->info) { + snprintf(buffer, sizeof(buffer), "Size: %dKb", file->info->size / 1024); + feh_menu_add_entry(mm, buffer, NULL, NULL, NULL, NULL, NULL); + snprintf(buffer, sizeof(buffer), "Dimensions: %dx%d", file->info->width, + file->info->height); + feh_menu_add_entry(mm, buffer, NULL, NULL, NULL, NULL, NULL); + snprintf(buffer, sizeof(buffer), "Type: %s", file->info->format); + feh_menu_add_entry(mm, buffer, NULL, NULL, NULL, NULL, NULL); + } + + mm->func_free = feh_menu_func_free_info; + D_RETURN(4, mm); + i = NULL; + data = NULL; +} + +static void +feh_menu_func_free_info(feh_menu * m, + void *data) +{ + D_ENTER(4); + feh_menu_free(m); + D_RETURN_(4); + data = NULL; +} + + +static feh_menu * +feh_menu_func_gen_options(feh_menu * m, + feh_menu_item * i, + void *data) +{ + feh_menu *mm; + + D_ENTER(4); + mm = feh_menu_new(); + mm->name = estrdup("OPTIONS"); + mm->fehwin = m->fehwin; + feh_menu_add_toggle_entry(mm, "Auto-Zoom", NULL, NULL, + feh_menu_cb_opt_auto_zoom, NULL, NULL, + opt.auto_zoom); + feh_menu_add_toggle_entry(mm, "Freeze Window Size", NULL, NULL, + feh_menu_cb_opt_freeze_window, NULL, NULL, + opt.geom_flags); + feh_menu_add_toggle_entry(mm, "Fullscreen", NULL, NULL, + feh_menu_cb_opt_fullscreen, NULL, NULL, + m->fehwin->full_screen); +#ifdef HAVE_LIBXINERAMA + feh_menu_add_toggle_entry(mm, "Use Xinerama", NULL, NULL, + feh_menu_cb_opt_xinerama, NULL, NULL, + opt.xinerama); +#endif /* HAVE_LIBXINERAMA */ + feh_menu_add_entry(mm, NULL, NULL, NULL, NULL, NULL, NULL); + feh_menu_add_toggle_entry(mm, "Draw Filename", NULL, NULL, + feh_menu_cb_opt_draw_filename, NULL, NULL, + opt.draw_filename); + feh_menu_add_toggle_entry(mm, "Keep HTTP Files", NULL, NULL, + feh_menu_cb_opt_keep_http, NULL, NULL, + opt.keep_http); + mm->func_free = feh_menu_func_free_options; + D_RETURN(4, mm); + i = NULL; + data = NULL; +} + +static void +feh_menu_func_free_options(feh_menu * m, + void *data) +{ + D_ENTER(4); + feh_menu_free(m); + D_RETURN_(4); + data = NULL; +} + +static void +feh_menu_cb_jump_to(feh_menu * m, + feh_menu_item * i, + void *data) +{ + gib_list *l; + + D_ENTER(4); + l = (gib_list *) data; + if (l->prev) { + current_file = l->prev; + slideshow_change_image(m->fehwin, SLIDE_NEXT); + } else if (l->next) { + current_file = l->next; + slideshow_change_image(m->fehwin, SLIDE_PREV); + } + + D_RETURN_(4); + i = NULL; + m = NULL; +} + +static void +feh_menu_cb_fit(feh_menu * m, + feh_menu_item * i, + void *data) +{ + D_ENTER(4); + winwidget_size_to_image(m->fehwin); + D_RETURN_(4); + data = NULL; +} + +static void +feh_menu_cb_edit_rotate(feh_menu * m, + feh_menu_item * i, + void *data) +{ + D_ENTER(4); + feh_edit_inplace_orient(m->fehwin, (int) data); + D_RETURN_(4); +} + +static void +feh_menu_cb_save_image(feh_menu * m, + feh_menu_item * i, + void *data) +{ + slideshow_save_image(m->fehwin); +} + +static void +feh_menu_cb_save_filelist(feh_menu * m, + feh_menu_item * i, + void *data) +{ + feh_save_filelist(); +} + +static void +feh_menu_cb_opt_draw_filename(feh_menu * m, + feh_menu_item * i, + void *data) +{ + MENU_ITEM_TOGGLE(i); + if (MENU_ITEM_IS_ON(i)) + opt.draw_filename = TRUE; + else + opt.draw_filename = FALSE; + winwidget_rerender_all(0, 1); +} + +static void +feh_menu_cb_opt_keep_http(feh_menu * m, + feh_menu_item * i, + void *data) +{ + MENU_ITEM_TOGGLE(i); + if (MENU_ITEM_IS_ON(i)) + opt.keep_http = TRUE; + else + opt.keep_http = FALSE; +} + +static void +feh_menu_cb_opt_freeze_window(feh_menu * m, + feh_menu_item * i, + void *data) +{ + MENU_ITEM_TOGGLE(i); + if (MENU_ITEM_IS_ON(i)) { + opt.geom_flags = (WidthValue | HeightValue); + opt.geom_w = m->fehwin->w; + opt.geom_h = m->fehwin->h; + } else { + opt.geom_flags = 0; + } +} + +static void +feh_menu_cb_opt_fullscreen(feh_menu * m, + feh_menu_item * i, + void *data) +{ + int curr_screen = 0; + + MENU_ITEM_TOGGLE(i); + if (MENU_ITEM_IS_ON(i)) + m->fehwin->full_screen = TRUE; + else + m->fehwin->full_screen = FALSE; + +#ifdef HAVE_LIBXINERAMA + if (opt.xinerama && xinerama_screens) { + int i, rect[4]; + + /* FIXME: this doesn't do what it should; XGetGeometry always + * returns x,y == 0,0. I think that's due to the hints being passed + * (or more specifically, a missing hint) to X in winwidget_create + */ + winwidget_get_geometry(m->fehwin, rect); + /* printf("window: (%d, %d)\n", rect[0], rect[1]); + printf("found %d screens.\n", num_xinerama_screens); */ + for (i = 0; i < num_xinerama_screens; i++) { + xinerama_screen = 0; + /* printf("%d: [%d, %d, %d, %d] (%d, %d)\n", + i, + xinerama_screens[i].x_org, xinerama_screens[i].y_org, + xinerama_screens[i].width, xinerama_screens[i].height, + rect[0], rect[1]);*/ + if (XY_IN_RECT(rect[0], rect[1], + xinerama_screens[i].x_org, xinerama_screens[i].y_org, + xinerama_screens[i].width, xinerama_screens[i].height)) { + curr_screen = xinerama_screen = i; + break; + } + + } + } +#endif /* HAVE_LIBXINERAMA */ + + 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_show(m->fehwin); + +#ifdef HAVE_LIBXINERAMA + /* if we have xinerama and we're using it, then full screen the window + * on the head that the window was active on */ + if (m->fehwin->full_screen == TRUE && opt.xinerama && xinerama_screens) { + xinerama_screen = curr_screen; + winwidget_move(m->fehwin, + xinerama_screens[curr_screen].x_org, + xinerama_screens[curr_screen].y_org); + } +#endif /* HAVE_LIBXINERAMA */ +} + +static void +feh_menu_cb_opt_auto_zoom(feh_menu * m, + feh_menu_item * i, + void *data) +{ + MENU_ITEM_TOGGLE(i); + opt.auto_zoom = MENU_ITEM_IS_ON(i) ? 1 : 0; + winwidget_rerender_all(1, 1); +} + +#ifdef HAVE_LIBXINERAMA +static void +feh_menu_cb_opt_xinerama(feh_menu * m, + feh_menu_item * i, + void *data) +{ + MENU_ITEM_TOGGLE(i); + opt.xinerama = MENU_ITEM_IS_ON(i) ? 1 : 0; + + if (opt.xinerama) { + init_xinerama(); + } else { + XFree(xinerama_screens); + xinerama_screens = NULL; + } + winwidget_rerender_all(1, 1); +} +#endif /* HAVE_LIBXINERAMA */ diff --git a/src/menu.h b/src/menu.h new file mode 100644 index 0000000..214e8a2 --- /dev/null +++ b/src/menu.h @@ -0,0 +1,192 @@ +/* menu.h + +Copyright (C) 1999-2003 Tom Gilbert. + +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. + +*/ + +#ifndef MENU_H +#define MENU_H + +typedef struct _feh_menu feh_menu; +typedef struct _feh_menu_item feh_menu_item; +typedef struct _feh_menu_list feh_menu_list; + + +#define MENU_ITEM_STATE_NORMAL 0x00 +#define MENU_ITEM_STATE_SELECTED 0x01 +#define MENU_ITEM_STATE_ON 0x02 + +#define MENU_ITEM_IS_SELECTED(item) \ +((item)->state & MENU_ITEM_STATE_SELECTED) +#define MENU_ITEM_SET_NORMAL(item) \ +(item)->state = (item)->state & (~MENU_ITEM_STATE_SELECTED) +#define MENU_ITEM_SET_SELECTED(item) \ +(item)->state = (item)->state | MENU_ITEM_STATE_SELECTED + +#define MENU_ITEM_IS_ON(item) \ +((item)->state & MENU_ITEM_STATE_ON) +#define MENU_ITEM_TOGGLE_ON(item) \ +((item)->state |= MENU_ITEM_STATE_ON) +#define MENU_ITEM_TOGGLE_OFF(item) \ +((item)->state &= ~(MENU_ITEM_STATE_ON)) +#define MENU_ITEM_TOGGLE_SET(item, setting) \ +((setting) ? MENU_ITEM_TOGGLE_ON(item) : MENU_ITEM_TOGGLE_OFF(item)) +#define MENU_ITEM_TOGGLE(item) \ +(((item)->state & MENU_ITEM_STATE_ON) ? MENU_ITEM_TOGGLE_OFF(item) : MENU_ITEM_TOGGLE_ON(item)) + + +#define RECTS_INTERSECT(x, y, w, h, xx, yy, ww, hh) \ +((SPANS_COMMON((x), (w), (xx), (ww))) && (SPANS_COMMON((y), (h), (yy), (hh)))) +#define SPANS_COMMON(x1, w1, x2, w2) \ +(!((((x2) + (w2)) <= (x1)) || ((x2) >= ((x1) + (w1))))) + + +#define FEH_MENU_PAD_LEFT 3 +#define FEH_MENU_PAD_RIGHT 3 +#define FEH_MENU_PAD_TOP 3 +#define FEH_MENU_PAD_BOTTOM 3 + +#define FEH_MENUITEM_PAD_LEFT 2 +#define FEH_MENUITEM_PAD_RIGHT 2 +#define FEH_MENUITEM_PAD_TOP 1 +#define FEH_MENUITEM_PAD_BOTTOM 1 + +#define FEH_MENU_SEP_MAX_H 5 + +#define FEH_MENU_SUBMENU_H 14 +#define FEH_MENU_SUBMENU_W 9 + +#define FEH_MENU_TOGGLE_H 7 +#define FEH_MENU_TOGGLE_W 7 +#define FEH_MENU_TOGGLE_PAD 3 + +typedef void (*menu_func) (feh_menu * m, feh_menu_item * i, void *data); +typedef feh_menu *(*menuitem_func_gen) (feh_menu * m, feh_menu_item * i, + void *data); + +struct _feh_menu_list +{ + feh_menu *menu; + feh_menu_list *next; +}; + +struct _feh_menu_item +{ + int state; + Imlib_Image icon; + char *text; + char *submenu; + menu_func func; + void (*func_free) (void *data); + void *data; + feh_menu_item *next; + feh_menu_item *prev; + unsigned char is_toggle; + int text_x, icon_x, sub_x, toggle_x; + int x, y, w, h; + menuitem_func_gen func_gen_sub; +}; + +struct _feh_menu +{ + char *name; + winwidget fehwin; + Window win; + Pixmap pmap; + int x, y, w, h; + int item_w, item_h; + int visible; + feh_menu_item *items; + feh_menu *next; + feh_menu *prev; + Imlib_Updates updates; + Imlib_Image bg; + int needs_redraw; + void *data; + int calc; + void (*func_free) (feh_menu * m, void *data); +}; + +feh_menu *feh_menu_new(void); + +feh_menu_item *feh_menu_find_selected(feh_menu * m); +feh_menu_item *feh_menu_find_at_xy(feh_menu * m, int x, int y); +void feh_menu_deselect_selected(feh_menu * m); +void feh_menu_select(feh_menu * m, feh_menu_item * i); +void feh_menu_show_at(feh_menu * m, int x, int y); +void feh_menu_show_at_xy(feh_menu * m, winwidget winwin, int x, int y); +void feh_menu_show_at_submenu(feh_menu * m, feh_menu * parent_m, + feh_menu_item * i); +void feh_menu_hide(feh_menu * m, int func_free); +void feh_menu_show(feh_menu * m); +feh_menu_item *feh_menu_add_entry(feh_menu * m, char *text, Imlib_Image icon, + char *submenu, menu_func func, void *data, + void (*func_free) (void *data)); +feh_menu_item * +feh_menu_add_toggle_entry(feh_menu * m, char *text, Imlib_Image icon, + char *submenu, menu_func func, void *data, + void (*func_free) (void *data), int setting); +void feh_menu_entry_get_size(feh_menu * m, feh_menu_item * i, int *w, int *h); +void feh_menu_calc_size(feh_menu * m); +void feh_menu_draw_item(feh_menu * m, feh_menu_item * i, Imlib_Image im, + int ox, int oy); +void feh_menu_redraw(feh_menu * m); +void feh_menu_move(feh_menu * m, int x, int y); +void feh_menu_slide_all_menus_relative(int dx, int dy); +void feh_menu_init_main(void); +void feh_menu_init_single_win(void); +void feh_menu_init_about_win(void); +void feh_menu_init_common(void); +void feh_menu_init_thumbnail_viewer(void); +void feh_menu_init_thumbnail_win(void); +void feh_menu_draw_to_buf(feh_menu * m, Imlib_Image im, int ox, int oy); +void feh_menu_draw_menu_bg(feh_menu * m, Imlib_Image im, int ox, int oy); +void feh_menu_draw_submenu_at(int x, int y, int w, int h, Imlib_Image dst, + int ox, int oy, int selected); +void feh_menu_draw_separator_at(int x, int y, int w, int h, Imlib_Image dst, + int ox, int oy); +void feh_menu_item_draw_at(int x, int y, int w, int h, Imlib_Image dst, + int ox, int oy, int selected); +void feh_menu_draw_toggle_at(int x, int y, int w, int h, Imlib_Image dst, + int ox, int oy, int on); +void feh_redraw_menus(void); +feh_menu *feh_menu_find(char *name); +void feh_redraw_menus(void); +feh_menu *feh_menu_get_from_window(Window win); +void feh_raise_all_menus(void); +void feh_menu_free(feh_menu * m); +feh_menu_item *feh_menu_find_selected_r(feh_menu *m, feh_menu **parent); +void feh_menu_select_prev(feh_menu *selected_menu, feh_menu_item *selected_item); +void feh_menu_select_next(feh_menu *selected_menu, feh_menu_item *selected_item); +void feh_menu_item_activate(feh_menu *selected_menu, + feh_menu_item *selected_item); +void feh_menu_select_parent(feh_menu *selected_menu, feh_menu_item *selected_item); +void feh_menu_select_submenu(feh_menu *selected_menu, feh_menu_item *selected_item); + +extern feh_menu *menu_root; +extern feh_menu *menu_single_win; +extern feh_menu *menu_about_win; +extern feh_menu *menu_thumbnail_viewer; +extern feh_menu *menu_thumbnail_win; +extern Window menu_cover; + +#endif diff --git a/src/menubg_aluminium.png b/src/menubg_aluminium.png new file mode 100644 index 0000000..eed00f1 Binary files /dev/null and b/src/menubg_aluminium.png differ diff --git a/src/menubg_aqua.png b/src/menubg_aqua.png new file mode 100644 index 0000000..3a72590 Binary files /dev/null and b/src/menubg_aqua.png differ diff --git a/src/menubg_black.png b/src/menubg_black.png new file mode 100644 index 0000000..08b4c2b Binary files /dev/null and b/src/menubg_black.png differ diff --git a/src/menubg_britney.png b/src/menubg_britney.png new file mode 100644 index 0000000..1b1b94e Binary files /dev/null and b/src/menubg_britney.png differ diff --git a/src/menubg_brushed.png b/src/menubg_brushed.png new file mode 100644 index 0000000..32fad47 Binary files /dev/null and b/src/menubg_brushed.png differ diff --git a/src/menubg_chrome.png b/src/menubg_chrome.png new file mode 100644 index 0000000..24f3025 Binary files /dev/null and b/src/menubg_chrome.png differ diff --git a/src/menubg_default.png b/src/menubg_default.png new file mode 100644 index 0000000..dd21188 Binary files /dev/null and b/src/menubg_default.png differ diff --git a/src/menubg_pastel.png b/src/menubg_pastel.png new file mode 100644 index 0000000..ec96566 Binary files /dev/null and b/src/menubg_pastel.png differ diff --git a/src/menubg_sky.png b/src/menubg_sky.png new file mode 100644 index 0000000..e0be8ca Binary files /dev/null and b/src/menubg_sky.png differ diff --git a/src/menubg_wood.png b/src/menubg_wood.png new file mode 100644 index 0000000..4dc7440 Binary files /dev/null and b/src/menubg_wood.png differ diff --git a/src/multiwindow.c b/src/multiwindow.c new file mode 100644 index 0000000..60d5660 --- /dev/null +++ b/src/multiwindow.c @@ -0,0 +1,78 @@ +/* multiwindow.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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 "timers.h" +#include "filelist.h" +#include "options.h" + +void +init_multiwindow_mode(void) +{ + winwidget w = NULL; + gib_list *l; + feh_file *file = NULL; + + D_ENTER(2); + + mode = "multiwindow"; + + for (l = filelist; l; l = l->next) + { + char *s = NULL; + int len = 0; + file = FEH_FILE(l->data); + current_file = l; + + if (!opt.title) + { + len = strlen(PACKAGE " - ") + strlen(file->filename) + 1; + s = emalloc(len); + snprintf(s, len, PACKAGE " - %s", file->filename); + } + else + { + s = estrdup(feh_printf(opt.title, file)); + } + + if ((w = winwidget_create_from_file(l, s, WIN_TYPE_SINGLE)) != NULL) + { + winwidget_show(w); + if (opt.reload > 0) + feh_add_unique_timer(cb_reload_timer, w, opt.reload); + if (!feh_main_iteration(0)) + exit(0); + } + else + { + D(3, + ("EEEK. Couldn't load image in multiwindow mode. " + "I 'm not sure if this is a problem\n")); + } + free(s); + } + D_RETURN_(2); +} diff --git a/src/options.c b/src/options.c new file mode 100644 index 0000000..d9d803d --- /dev/null +++ b/src/options.c @@ -0,0 +1,1203 @@ +/* options.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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 "filelist.h" +#include "options.h" + +static void check_options(void); +static void feh_parse_option_array(int argc, char **argv); +static void feh_parse_environment_options(void); +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); +static char *theme; + +fehoptions opt; + +void +init_parse_options(int argc, char **argv) +{ + D_ENTER(4); + + /* For setting the command hint on X windows */ + cmdargc = argc; + cmdargv = argv; + + /* Set default options */ + memset(&opt, 0, sizeof(fehoptions)); + opt.display = 1; + opt.aspect = 1; + opt.slideshow_delay = -1.0; + opt.thumb_w = 60; + opt.thumb_h = 60; + opt.menu_font = estrdup(DEFAULT_MENU_FONT); + opt.font = estrdup(DEFAULT_FONT); + opt.menu_bg = estrdup(PREFIX "/share/feh/images/menubg_default.png"); + opt.menu_style = estrdup(PREFIX "/share/feh/fonts/menu.style"); + opt.menu_border = 4; + + opt.next_button = 1; + opt.zoom_button = 2; + opt.menu_button = 3; + opt.menu_ctrl_mask = 0; + opt.reload_button = 0; + + opt.rotate_button = 2; + opt.no_rotate_ctrl_mask = 0; + opt.blur_button = 1; + opt.no_blur_ctrl_mask = 0; + + opt.no_jump_on_resort = 0; + + opt.builtin_http = 0; + + opt.xinerama = 0; + opt.screen_clip = 1; +#ifdef HAVE_LIBXINERAMA + /* if we're using xinerama, then enable it by default */ + opt.xinerama = 1; +#endif /* HAVE_LIBXINERAMA */ + + opt.fmmode = 0; + + D(3, ("About to parse env options (if any)\n")); + /* Check for and parse any options in FEH_OPTIONS */ + feh_parse_environment_options(); + + D(3, ("About to parse commandline options\n")); + /* Parse the cmdline args */ + feh_parse_option_array(argc, argv); + + D(3, ("About to check for theme configuration\n")); + feh_check_theme_options(argc, argv); + + /* 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 + here, as files specified on the commandline end up at the *end* of + the combined filelist, in the specified order. */ + D(3, ("About to load filelist from file\n")); + filelist = gib_list_cat(filelist, feh_read_filelist(opt.filelistfile)); + } + + D(4, ("Options parsed\n")); + + if(opt.bgmode) + D_RETURN_(4); + + filelist_len = gib_list_length(filelist); + if (!filelist_len) + show_mini_usage(); + + check_options(); + + feh_prepare_filelist(); + D_RETURN_(4); +} + +static void +feh_check_theme_options(int arg, char **argv) +{ + D_ENTER(4); + if (!theme) + { + /* This prevents screw up when running src/feh or ./feh */ + char *pos = strrchr(argv[0], '/'); + + if (pos) + theme = estrdup(pos + 1); + else + theme = estrdup(argv[0]); + } + D(3, ("Theme name is %s\n", theme)); + + feh_load_options_for_theme(theme); + + free(theme); + D_RETURN_(4); + arg = 0; +} + +static void +feh_load_options_for_theme(char *theme) +{ + FILE *fp = NULL; + char *home; + char *rcpath = NULL; + char s[1024], s1[1024], s2[1024]; + + D_ENTER(4); + + if (opt.rcfile) + { + if ((fp = fopen(opt.rcfile, "r")) == NULL) + { + weprintf("couldn't load the specified rcfile %s\n", opt.rcfile); + D_RETURN_(4); + } + } + 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(3, ("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) + D_RETURN_(4); + } + + free(rcpath); + } + + /* Oooh. We have an options file :) */ + for (; fgets(s, sizeof(s), fp);) + { + s1[0] = '\0'; + s2[0] = '\0'; + sscanf(s, "%s %[^\n]\n", (char *) &s1, (char *) &s2); + if (!(*s1) || (!*s2) || (*s1 == '\n') || (*s1 == '#')) + continue; + D(5, ("Got theme/options pair %s/%s\n", s1, s2)); + if (!strcmp(s1, theme)) + { + D(4, ("A match. Using options %s\n", s2)); + feh_parse_options_from_string(s2); + break; + } + } + fclose(fp); + D_RETURN_(4); +} + +static void +feh_parse_environment_options(void) +{ + char *opts; + + D_ENTER(4); + + if ((opts = getenv("FEH_OPTIONS")) == NULL) + D_RETURN_(4); + + 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); + D_RETURN_(4); +} + +/* FIXME This function is a crufty bitch ;) */ +static void +feh_parse_options_from_string(char *opts) +{ + char **list = NULL; + int num = 0; + char *s; + char *t; + char last = 0; + int inquote = 0; + int i = 0; + + D_ENTER(4); + + /* So we don't reinvent the wheel (not again, anyway), we use the + getopt_long function to do this parsing as well. This means it has to + look like the real argv ;) */ + + list = malloc(sizeof(char *)); + + list[num++] = estrdup(PACKAGE); + + for (s = opts, t = opts;; t++) + { + if ((*t == ' ') && !(inquote)) + { + *t = '\0'; + num++; + list = erealloc(list, sizeof(char *) * num); + + list[num - 1] = feh_string_normalize(s); + s = t + 1; + } + else if (*t == '\0') + { + num++; + list = erealloc(list, sizeof(char *) * num); + + list[num - 1] = feh_string_normalize(s); + break; + } + else if (*t == '\"' && last != '\\') + inquote = !(inquote); + last = *t; + } + + feh_parse_option_array(num, list); + + for (i = 0; i < num; i++) + if (list[i]) + free(list[i]); + if (list) + free(list); + D_RETURN_(4); +} + +char * +feh_string_normalize(char *str) +{ + char ret[4096]; + char *s; + int i = 0; + char last = 0; + + D_ENTER(4); + D(4, ("normalizing %s\n", str)); + ret[0] = '\0'; + + for (s = str;; s++) + { + if (*s == '\0') + break; + else if ((*s == '\"') && (last == '\\')) + ret[i++] = '\"'; + else if ((*s == '\"') && (last == 0)) + ; + else if ((*s == ' ') && (last == '\\')) + ret[i++] = ' '; + else + ret[i++] = *s; + + last = *s; + } + if (i && ret[i - 1] == '\"') + ret[i - 1] = '\0'; + else + ret[i] = '\0'; + D(4, ("normalized to %s\n", ret)); + + D_RETURN(4, estrdup(ret)); +} + +static void +feh_parse_option_array(int argc, char **argv) +{ + static char stropts[] = + "a:A:b:BcC:dD:e:E:f:Fg:GhH:iIj:klL:mM:nNo:O:pqQrR:sS:tT:uUvVwW:xXy:zZ1:2:4:56:78:90:.@:^:~:):|:_:+:"; + static struct option lopts[] = { + /* actions */ + {"help", 0, 0, 'h'}, /* okay */ + {"version", 0, 0, 'v'}, /* okay */ + /* toggles */ + {"montage", 0, 0, 'm'}, /* okay */ + {"collage", 0, 0, 'c'}, /* okay */ + {"index", 0, 0, 'i'}, /* okay */ + {"fullindex", 0, 0, 'I'}, /* okay */ + {"verbose", 0, 0, 'V'}, /* okay */ + {"borderless", 0, 0, 'x'}, /* okay */ + {"keep-http", 0, 0, 'k'}, /* okay */ + {"stretch", 0, 0, 's'}, /* okay */ + {"multiwindow", 0, 0, 'w'}, /* okay */ + {"recursive", 0, 0, 'r'}, /* okay */ + {"randomize", 0, 0, 'z'}, /* okay */ + {"list", 0, 0, 'l'}, /* okay */ + {"quiet", 0, 0, 'q'}, /* okay */ + {"loadables", 0, 0, 'U'}, /* okay */ + {"unloadables", 0, 0, 'u'}, /* okay */ + {"no-menus", 0, 0, 'N'}, + {"full-screen", 0, 0, 'F'}, + {"auto-zoom", 0, 0, 'Z'}, + {"ignore-aspect", 0, 0, 'X'}, + {"draw-filename", 0, 0, 'd'}, + {"preload", 0, 0, 'p'}, + {"reverse", 0, 0, 'n'}, + {"thumbnails", 0, 0, 't'}, + {"wget-timestamp", 0, 0, 'G'}, + {"builtin", 0, 0, 'Q'}, + {"menu-ctrl-mask", 0, 0, '5'}, /* okay */ + {"scale-down", 0, 0, '.'}, /* okay */ + {"no-rotate-ctrl-mask", 0, 0, '7'}, + {"no-blur-ctrl-mask", 0, 0, '9'}, + {"no-jump-on-resort",0,0,220}, + {"hide-pointer",0,0,221}, + /* options with values */ + {"output", 1, 0, 'o'}, /* okay */ + {"output-only", 1, 0, 'O'}, /* okay */ + {"action", 1, 0, 'A'}, /* okay */ + {"limit-width", 1, 0, 'W'}, /* okay */ + {"limit-height", 1, 0, 'H'}, /* okay */ + {"reload", 1, 0, 'R'}, /* okay */ + {"alpha", 1, 0, 'a'}, /* okay */ + {"sort", 1, 0, 'S'}, /* okay */ + {"theme", 1, 0, 'T'}, /* okay */ + {"filelist", 1, 0, 'f'}, /* okay */ + {"customlist", 1, 0, 'L'}, /* okay */ + {"geometry", 1, 0, 'g'}, /* okay */ + {"menu-font", 1, 0, 'M'}, + {"thumb-width", 1, 0, 'y'}, + {"thumb-height", 1, 0, 'E'}, + {"slideshow-delay", 1, 0, 'D'}, + {"font", 1, 0, 'e'}, + {"title-font", 1, 0, '@'}, + {"title", 1, 0, '^'}, + {"thumb-title", 1, 0, '~'}, + {"bg", 1, 0, 'b'}, + {"fontpath", 1, 0, 'C'}, + {"menu-bg", 1, 0, ')'}, + {"next-button", 1, 0, '1'}, + {"zoom-button", 1, 0, '2'}, + {"menu-button", 1, 0, '4'}, + {"rotate-button", 1, 0, '6'}, + {"blur-button", 1, 0, '8'}, + {"reload-button", 1, 0, '0'}, + {"start-at", 1, 0, '|'}, + {"rcfile", 1, 0, '_'}, + {"debug-level", 1, 0, '+'}, + {"output-dir", 1, 0, 'j'}, + {"bg-tile", 1, 0, 200}, + {"bg-center", 1, 0, 201}, + {"bg-scale", 1, 0, 202}, + {"bg-seamless", 1, 0, 203}, + {"menu-style", 1, 0, 204}, + {"zoom", 1, 0, 205}, + {"xinerama", 1, 0, 206}, + {"screen-clip", 1, 0, 207}, + {"menu-border", 1, 0, 208}, + {"caption-path", 1, 0, 209}, + {"action1", 1, 0, 210}, + {"action2", 1, 0, 211}, + {"action3", 1, 0, 212}, + {"action4", 1, 0, 213}, + {"action5", 1, 0, 214}, + {"action6", 1, 0, 215}, + {"action7", 1, 0, 216}, + {"action8", 1, 0, 217}, + {"action9", 1, 0, 218}, + {"fmmode", 0, 0, 219}, + {"draw-actions", 0, 0, 222}, + {"cache-thumbnails", 0, 0, 223}, + {"cycle-once", 0, 0, 224}, + {0, 0, 0, 0} + }; + int optch = 0, cmdx = 0, i = 0; + int geomret; + + D_ENTER(4); + + /* Now to pass some optionarinos */ + while ((optch = getopt_long(argc, argv, stropts, lopts, &cmdx)) != EOF) + { + D(5, ("Got option, getopt calls it %d, or %c\n", optch, optch)); + switch (optch) + { + case 0: + break; + case 'h': + show_usage(); + break; + case 'v': + show_version(); + break; + case 'm': + opt.index = 1; + opt.index_show_name = 0; + opt.index_show_size = 0; + opt.index_show_dim = 0; + break; + case 'c': + opt.collage = 1; + break; + case 'i': + opt.index = 1; + opt.index_show_name = 1; + opt.index_show_size = 0; + opt.index_show_dim = 0; + break; + case '.': + opt.scale_down = 1; + break; + case 'I': + opt.index = 1; + opt.index_show_name = 1; + opt.index_show_size = 1; + opt.index_show_dim = 1; + break; + case 'l': + opt.list = 1; + break; + case 'G': + opt.wget_timestamp = 1; + break; + case 'Q': + opt.builtin_http = 1; + break; + case 'L': + opt.customlist = estrdup(optarg); + break; + case 'M': + free(opt.menu_font); + opt.menu_font = estrdup(optarg); + break; + case '+': + opt.debug_level = atoi(optarg); + break; + case 'n': + opt.reverse = 1; + break; + case 'g': + opt.geom_flags = XParseGeometry(optarg, &opt.geom_x, &opt.geom_y, &opt.geom_w, &opt.geom_h); + break; + case 'N': + opt.no_menus = 1; + break; + case 'V': + opt.verbose = 1; + break; + case 'q': + opt.quiet = 1; + break; + case 'x': + opt.borderless = 1; + break; + case 'k': + opt.keep_http = 1; + break; + case 's': + opt.stretch = 1; + break; + case 'w': + opt.multiwindow = 1; + break; + case 'r': + opt.recursive = 1; + break; + case 'z': + opt.randomize = 1; + break; + case 'd': + opt.draw_filename = 1; + break; + case 'F': + opt.full_screen = 1; + break; + case 'Z': + opt.auto_zoom = 1; + break; + case 'U': + opt.loadables = 1; + break; + case 'u': + opt.unloadables = 1; + break; + case 'p': + opt.preload = 1; + break; + case 'X': + opt.aspect = 0; + break; + case 'S': + if (!strcasecmp(optarg, "name")) + opt.sort = SORT_NAME; + else if (!strcasecmp(optarg, "filename")) + opt.sort = SORT_FILENAME; + else if (!strcasecmp(optarg, "width")) + opt.sort = SORT_WIDTH; + else if (!strcasecmp(optarg, "height")) + opt.sort = SORT_HEIGHT; + else if (!strcasecmp(optarg, "pixels")) + opt.sort = SORT_PIXELS; + else if (!strcasecmp(optarg, "size")) + opt.sort = SORT_SIZE; + else if (!strcasecmp(optarg, "format")) + opt.sort = SORT_FORMAT; + else + { + weprintf + ("Unrecognised sort mode \"%s\". Defaulting to sort by filename", + optarg); + opt.sort = SORT_FILENAME; + } + break; + case 'o': + opt.output = 1; + opt.output_file = estrdup(optarg); + break; + case 'O': + opt.output = 1; + opt.output_file = estrdup(optarg); + opt.display = 0; + break; + case 'T': + theme = estrdup(optarg); + break; + case 'C': + D(3, ("adding fontpath %s\n", optarg)); + imlib_add_path_to_font_path(optarg); + break; + case 'e': + opt.font = estrdup(optarg); + break; + case '@': + opt.title_font = estrdup(optarg); + break; + case '^': + opt.title = estrdup(optarg); + break; + case '~': + opt.thumb_title = estrdup(optarg); + break; + case 'b': + opt.bg = 1; + opt.bg_file = estrdup(optarg); + break; + case '_': + opt.rcfile = estrdup(optarg); + break; + case 'A': + opt.actions[0] = estrdup(optarg); + break; + case 'W': + opt.limit_w = atoi(optarg); + break; + case 'H': + opt.limit_h = atoi(optarg); + break; + case 'y': + opt.thumb_w = atoi(optarg); + break; + case 'E': + opt.thumb_h = atoi(optarg); + break; + case ')': + free(opt.menu_bg); + opt.menu_bg = estrdup(optarg); + break; + case 'D': + opt.slideshow_delay = atof(optarg); + break; + case 'R': + opt.reload = atoi(optarg); + break; + case 'a': + opt.alpha = 1; + opt.alpha_level = 255 - atoi(optarg); + break; + case 'f': + opt.filelistfile = estrdup(optarg); + break; + case '1': + opt.next_button = atoi(optarg); + break; + case '2': + opt.zoom_button = atoi(optarg); + break; + case '4': + opt.menu_button = atoi(optarg); + break; + case '5': + opt.menu_ctrl_mask = 1; + break; + case '6': + opt.rotate_button = atoi(optarg); + break; + case '7': + opt.no_rotate_ctrl_mask = 1; + break; + case '8': + opt.blur_button = atoi(optarg); + break; + case '9': + opt.no_blur_ctrl_mask = 1; + break; + case '|': + opt.start_list_at = atoi(optarg); + break; + case '0': + opt.reload_button = atoi(optarg); + break; + case 't': + opt.thumbs = 1; + opt.index_show_name = 1; + opt.index_show_size = 0; + opt.index_show_dim = 0; + break; + case 'j': + opt.output_dir = estrdup(optarg); + break; + case 200: + opt.bgmode = BG_MODE_TILE; + opt.output_file = estrdup(optarg); + break; + case 201: + opt.bgmode = BG_MODE_CENTER; + opt.output_file = estrdup(optarg); + break; + case 202: + opt.bgmode = BG_MODE_SCALE; + opt.output_file = estrdup(optarg); + break; + case 203: + opt.bgmode = BG_MODE_SEAMLESS; + opt.output_file = estrdup(optarg); + break; + case 204: + free(opt.menu_style); + opt.menu_style = estrdup(optarg); + break; + case 205: + opt.default_zoom = atoi(optarg); + break; + case 206: + opt.xinerama = atoi(optarg); + break; + case 207: + opt.screen_clip = atoi(optarg); + break; + case 208: + opt.menu_border = atoi(optarg); + break; + case 209: + opt.caption_path = estrdup(optarg); + break; + case 210: + opt.actions[1] = estrdup(optarg); + break; + case 211: + opt.actions[2] = estrdup(optarg); + break; + case 212: + opt.actions[3] = estrdup(optarg); + break; + case 213: + opt.actions[4] = estrdup(optarg); + break; + case 214: + opt.actions[5] = estrdup(optarg); + break; + case 215: + opt.actions[6] = estrdup(optarg); + break; + case 216: + opt.actions[7] = estrdup(optarg); + break; + case 217: + opt.actions[8] = estrdup(optarg); + break; + case 218: + opt.actions[9] = estrdup(optarg); + break; + case 220: + opt.no_jump_on_resort = 1; + break; + case 221: + opt.hide_pointer = 1; + break; + case 219: + opt.fmmode = 1; + opt.sort = SORT_FILENAME; + break; + case 222: + opt.draw_actions = 1; + break; + case 223: + opt.cache_thumbnails = 1; + break; + case 224: + opt.cycle_once = 1; + break; + default: + break; + } + } + + /* Now the leftovers, which must be files */ + if (optind < argc) + { + while (optind < argc) + { + /* If recursive is NOT set, but the only argument is a directory + name, we grab all the files in there, but not subdirs */ + add_file_to_filelist_recursively(argv[optind++], FILELIST_FIRST); + } + } + + /* So that we can safely be called again */ + optind = 1; + D_RETURN_(4); +} + + +static void +check_options(void) +{ + D_ENTER(4); + 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) + { + weprintf + ("you shouldn't combine multiwindow mode with full-screen mode,\n" + " Multiwindow mode has been disabled."); + opt.multiwindow = 0; + } + + if (opt.list && (opt.multiwindow || opt.index || opt.collage)) + { + weprintf("list mode can't be combined with other processing modes,\n" + " list mode disabled."); + opt.list = 0; + } + + if (opt.sort && opt.randomize) + { + weprintf("You cant sort AND randomize the filelist...\n" + "randomize mode has been unset\n"); + opt.randomize = 0; + } + + if (opt.loadables && opt.unloadables) + { + weprintf("You cant show loadables AND unloadables...\n" + "you might as well use ls ;)\n" + "loadables only will be shown\n"); + opt.unloadables = 0; + } + + if (opt.thumb_title && (!opt.thumbs)) + { + weprintf("Doesn't make sense to set thumbnail title when not in\n" + "thumbnail mode.\n"); + free(opt.thumb_title); + opt.thumb_title = NULL; + } + D_RETURN_(4); +} + +void +show_version(void) +{ + printf(PACKAGE " version " VERSION "\n"); + exit(0); +} + +void +show_mini_usage(void) +{ + fprintf(stdout, + PACKAGE " - No loadable images specified.\nUse " PACKAGE + " --help for detailed usage information\n"); + exit(0); +} + +void +show_usage(void) +{ + fprintf(stdout, +"Usage : " PACKAGE " [OPTIONS]... FILES...\n" +" Where a FILE is an image file or a directory.\n" +" Multiple files are supported.\n" +" Urls are supported. They must begin with http:// or ftp:// and you must\n" +" have wget installed to download the files for viewing.\n" +" Options can also be specified in the in the feh configuration file. See\n" +" man feh for more details\n" +" -h, --help display this help and exit\n" +" -v, --version output version information and exit\n" +" -V, --verbose output useful information, progress bars, etc\n" +" -q, --quiet Don't report non-fatal errors for failed loads\n" +" Verbose and quiet modes are not mutually exclusive,\n" +" the first controls informational messages, the\n" +" second only errors.\n" +" -T, --theme THEME Load options from config file with name THEME\n" +" see man feh for more info.\n" +" --rcfile FILE Use FILE to parse themes and options from,\n" +" instead of the default ~/.fehrc, /etc/fehrc files.\n" +" -r, --recursive Recursively expand any directories in FILE to\n" +" the content of those directories. (Take it easy)\n" +" -z, --randomize When viewing multiple files in a slideshow,\n" +" randomise the file list before displaying\n" +" --no-jump-on-resort Don't jump to the first image when the filelist\n" +" is resorted.\n" +" -g, --geometry STRING Limit (and don't change) the window size. Takes\n" +" an X-style geometry string like 640x480.\n" +" Note that larger images will be zoomed out to fit\n" +" but you can see them at 1:1 by clicking the zoom\n" +" button.\n" +" -f, --filelist FILE This option is similar to the playlists used by\n" +" music software. If FILE exists, it will be read\n" +" for a list of files to load, in the order they\n" +" appear. The format is a list of image filenames,\n" +" absolute or relative to the current directory,\n" +" one filename per line.\n" +" If FILE doesn't exist, it will be created from the\n" +" internal filelist at the end of a viewing session.\n" +" This is best used to store the results of complex\n" +" sorts (-Spixels for example) for later viewing.\n" +" Any changes to the internal filelist (such as\n" +" deleting a file or it being pruned for being\n" +" unloadable) will be saved to FILE when feh exits.\n" +" You can add files to filelists by specifying them\n" +" on the commandline when also specifying the list.\n" +" -p, --preload Preload images. This doesn't mean hold them in\n" +" RAM, it means run through and eliminate unloadable\n" +" images first. Otherwise they will be removed as you\n" +" flick through.\n" +" --scale-down Automatically scale down images too big for the\n" +" screen. Currently only works with -P\n" +" -F, --full-screen Make the window fullscreen\n" +" -Z, --auto-zoom Zoom picture to screen size in fullscreen mode,\n" +" is affected by the option --stretch\n" +" --zoom PERCENT Zooms images by a PERCENT, when in full screen\n" +" mode or when window geometry is fixed. If combined\n" +" with --auto-zoom, zooming will be limited to the\n" +" the size.\n" +" -w, --multiwindow Disable slideshow mode. With this setting,\n" +" instead of opening multiple files in slideshow\n" +" mode, multiple windows will be opened.\n" +" -x, --borderless Create borderless windows\n" +" -d, --draw-filename Draw the filename at the top-left of the image.\n" +" --title TITLE Use TITLE as the window title in slideshow mode.\n" +" -D, --slideshow-delay NUM For slideshow mode, specifies time delay (seconds,\n" +" can be a decimal) between automatically changing\n" +" slides.\n" +" --cycle-once exit feh after one loop through a slideshow\n" +" -R, --reload NUM Use this option to tell feh to reload an image\n" +" after NUM seconds. Useful for viewing webcams\n" +" via http, or even on your local machine.\n" +" -Q, --builtin Use builtin http grabber to grab remote files\n" +" instead of wget.\n" +" mechanism, useful if don't have wget.\n" +" -k, --keep-http When viewing files using http, feh normally\n" +" deletes the local copies after viewing, or,\n" +" if caching, on exit. This option prevents this\n" +" so that you get to keep the local copies.\n" +" They will be in the current working directory\n" +" with \"feh\" in the name.\n" +" --caption-path PATH Path to directory containing image captions.\n" +" This turns on caption viewing, and if captions\n" +" are found in PATH, which is relative to the\n" +" directory of each image, they are overlayed\n" +" on the displayed image.\n" +" e.g with caption path \"captions\", and viewing\n" +" image images/foo.jpg, caption will be looked for\n" +" as \"images/captions/foo.jpg.txt\"\n" +" -j, --output-dir Output directory for saved files. Really only\n" +" useful with the -k flag.\n" +" -G, --wget-timestamp When viewing http images with reload set (eg\n" +" webcams), try to only reload the image if the\n" +" remote file has changed.\n" +" -l, --list Don't display images. Analyse them and display an\n" +" 'ls' style listing. Useful in scripts hunt out\n" +" images of a certain size/resolution/type etc.\n" +" -L, --customlist FORMAT Use FORMAT as the format specifier for list\n" +" output. FORMAT is a printf-like string containing\n" +" image info specifiers. See FORMAT SPECIFIERS.\n" +" -U, --loadable Don't display images. Just print out their name\n" +" if imlib2 can successfully load them.\n" +" -u, --unloadable Don't display images. Just print out their name\n" +" if imlib2 can NOT successfully load them.\n" +" -S, --sort SORT_TYPE The file list may be sorted according to image\n" +" parameters. Allowed sort types are: name,\n" +" filename, width, height, pixels, size, format.\n" +" For sort modes other than name or filename, a\n" +" preload run will be necessary, causing a delay\n" +" proportional to the number of images in the list\n" +" -n, --reverse Reverse the sort order. Use this to invert the order\n" +" of the filelist. Eg to sort in reverse width order,\n" +" use -nSwidth\n" +" -A, --action ACTION Specify a string as an action to perform on the\n" +" image. In slideshow or multiwindow modes, the action\n" +" in list mode, or loadable|unloadable modes, the\n" +" action will be run for each file.\n" +" The action will be executed by /bin/sh. Use\n" +" format specifiers to refer to image info. See\n" +" FORMAT SPECIFIERS for examples\n" +" Eg. -A \"mv %%f ~/images/%%n\"\n" +" In slideshow mode, the next image will be shown\n" +" after running the command, in multiwindow mode,\n" +" the window will be closed.\n" +" --action1 ACTION These extra action options allow you to specify\n" +" --action2 ACTION multiple additional actions which can be invoked\n" +" ... using the appropriate number key 1-9\n" +" --action9 ACTION\n" +" -m, --montage Enable montage mode. Montage mode creates a new\n" +" image consisting of a grid of thumbnails of the\n" +" images specified using FILE... When montage mode\n" +" is selected, certain other options become\n" +" available. See MONTAGE MODE OPTIONS\n" +" -c, --collage Same as montage mode, but the thumbnails are\n" +" distributed randomly. You must specify width and\n" +" height or supply a background image or both\n" +" -i, --index Enable Index mode. Index mode is similar to\n" +" montage mode, and accepts the same options. It\n" +" creates an index print of thumbails, printing the\n" +" images name beneath each thumbnail. Index mode\n" +" enables certain other options, see INDEX MODE\n" +" OPTIONS\n" +" -t, --thumbnails As --index, but clicking an image will open it in\n" +" a new viewing window\n" +" --cache-thumbnails Enable thumbnail caching\n" +" -I, --fullindex Same as index mode, but below each thumbnail you\n" +" get image name, size and dimensions\n" +" --bg-tile FILE\n" +" --bg-center FILE\n" +" --bg-scale FILE\n" +" --bg-seamless FILE Set your desktop background to FILE. Feh can\n" +" use enlightenment IPC if you are running it,\n" +" or will fall back to X methods.\n" +" Feh stores the commandline necessary to restore\n" +" the background you chose in ~/.fehbg. So to have\n" +" feh-set backgrounds restored when you restart X,\n" +" add the line \"eval `cat $HOME/.fehbg`\" to your\n" +" X startup script (e.g. ~/.xsession). Note that\n" +" you only need to do this for non E window\n" +" managers.\n" +" --fontpath PATH Specify an extra directory to look in for fonts,\n" +" can be used multiple times to add multiple paths.\n" +" -M, --menu-font FONT Use FONT for the font in menus.\n" +" --menu-style FILE Use FILE as the style descriptor for menu text.\n" +" --menu-bg BG Use BG for the background image in menus.\n" +" --menu-border INT Specify number of pixels that define the menu\n" +" background's border. Borders are not stretched\n" +" when images are scaled.\n" +" -N, --no-menus Don't load or show any menus.\n" +" -1, --next-button B Use button B to advance to the next image in any\n" +" mode (defaults to 1, usually the left button).\n" +" -2, --zoom-button B Use button B to zoom the current image in any\n" +" mode (defaults to 2, usually the middle button).\n" +" -4, --menu-button B Use CTRL+Button B to activate the menu in any\n" +" mode. Set to 0 for any button. This option\n" +" is disabled if the -N or --no-menus option is set\n" +" (defaults to 3, usually the right button).\n" +" -5, --menu-ctrl-mask Require CTRL+Button for menu activation in\n" +" any mode (default=off).\n" +" -6, --rotate-button B Use CTRL+Button B to rotate the current image in\n" +" any mode (default=2).\n" +" -7, --no-rotate-ctrl-mask Don't require CTRL+Button for rotation in\n" +" any mode -- just use the button (default=off).\n" +" -8, --blur-button B Use CTRL+Button B to blur the current image in\n" +" any mode (default=1).\n" +" -9, --no-blur-ctrl-mask Don't require CTRL+Button for blurring in\n" +" any mode -- just use the button (default=off).\n" +" --xinerama [0|1] Enable/disable Xinerama support. Has no effect\n" +" unless you have an Xinerama compiled in.\n" +" --screen-clip [0|1] Enable/disable window clipping based on screen\n" +" size. WARNING: with this option disabled,\n" +" image windows could become very large, making\n" +" them unmanageable in certain window managers.\n" +" --hide-pointer In full screen mode, hide the X mouse pointer.\n" +" FORMAT SPECIFIERS\n" +" %%f image path/filename\n" +" %%n image name\n" +" %%s image size (bytes)\n" +" %%p image pixel size\n" +" %%w image width\n" +" %%h image height\n" +" %%t image format\n" +" %%P prints feh\n" +" %%v prints the version\n" +" %%m prints the mode (slideshow, multiwindow...)\n" +" %%l prints the total number of files in the filelist\n" +" %%u prints the current file number\n" +" \\n prints a newline\n" +" Eg. feh -A \"mv %%f ~/images/%%n\" *\n" +" MONTAGE MODE OPTIONS\n" +" -X, --ignore-aspect By default, the montage thumbnails will retain\n" +" their aspect ratios, while fitting in --thumb-width\n" +" and --thumb-height. This option will force them to\n" +" be the size set by --thumb-width and --thumb-height\n" +" This will prevent any whitespace in the final\n" +" montage\n" +" -s, --stretch Normally, if an image is smaller than the specified\n" +" thumbnail size, it will not be enlarged. If this\n" +" option is set, the image will be scaled up to fit\n" +" the thumbnail size. (Aspect ratio will be maintained\n" +" unless --ignore-aspect is specified)\n" +" -y, --thumb-width NUM Set thumbnail width in pixels\n" +" -E, --thumb-height NUM Set thumbnail height in pixels\n" +" Thumbnails default to 20x20 pixels\n" +" -W, --limit-width NUM Limit the width of the montage in pixels\n" +" -H, --limit-height NUM Limit the height of the montage in pixels\n" +" These options can be used together (to define the\n" +" image size exactly), or separately. If only one is\n" +" specified, theother is calculated from the number\n" +" of files specified and the size of the thumbnails.\n" +" The default is to limit width to 800 pixels and\n" +" calculate the height\n" +" -b, --bg FILE|trans Use FILE as a background for your montage. With\n" +" this option specified, the size of the montage will\n" +" default to the size of FILE if no size restrictions\n" +" are specified. Alternatively, if FILE is \"trans\",\n" +" make the background transparent.\n" +" -a, --alpha NUM When drawing thumbnails onto the background, apply\n" +" them with a transparency level of NUM (0-255).\n" +" -o FILE Save the created montage to FILE\n" +" -O FILE Just save the created montage to FILE\n" +" WITHOUT displaying it (use in scripts)\n" +" INDEX MODE OPTIONS\n" +" -e FONT Use FONT to print the information under each\n" +" thumbnail. FONT should be defined in the form\n" +" fontname/size(points). eg -e myfont/12\n" +" -t, --title-font FONT Use FONT to print a title on the index, if no\n" +" font is specified, a title will not be printed\n" +" SLIDESHOW KEYS\n" +" The default mode for viewing mulitple images is Slideshow mode\n" +" When viewing a slideshow, the following keys may be used:\n" +" p, P, , Goto previous slide\n" +" n, N, , Goto next slide\n" +" r, R Reload image (good for webcams)\n" +" v, V Toggle fullscreen\n" +" m, M Show popup menu\n" +" c, C Caption entry mode. If --caption-path has been\n" +" specified, then this enables caption editing.\n" +" The caption will turn yellow and be editable,\n" +" hit enter to confirm and save the caption, or\n" +" hit escape to cancel and revert the caption.\n" +" w, W Size window to current image dimensions\n" +" h, H Pause the slideshow (only useful when using\n" +" s, S Save current image to unique filename\n" +" f, F Save current filelist to unique filename\n" +" timed reloading or image changes)\n" +" <, > In place editing, rotate 90 degrees right/left\n" +" Goto first slide\n" +" Goto last slide\n" +" Quit the slideshow\n" +" +, = Increase reload delay\n" +" -, _ Decrease reload delay\n" +" Remove the currently viewed file from the filelist\n" +" Delete the currently viewed file and remove it\n" +" from the filelist\n" +" x, X Close current window\n" +" q, Q Quit the slideshow\n" +" Move the image to the left\n" +" Move the image to the right\n" +" Zoom in\n" +" Zoom out\n" +" Zoom to 100%%\n" +" Zoom to fit the window\n" +" ,0 Run action specified by --action option\n" +" 1-9 Run action 1-9 specified by --action[1-9] options\n" +"\n" +" MOUSE ACTIONS\n" +" When viewing an image, a click of mouse button 1 moves to the next image\n" +" (slideshow mode only), a drag of mouse button 1 pans the image, if the\n" +" viewable window is smaller than the image, button 2 zooms (click and drag\n" +" left->right to zoom in, right->left to zoom out, click once to restore\n" +" 1x zoom), and mouse button 3 pans.\n" +" Ctrl+button 1 blurs or sharpens the image (drag left to blur and right to\n" +" sharpen). Ctrl+button 2 rotates the image around the center point.\n" +" Button 3 activates the context-sensitive menu. Buttons can be redefined\n" +" with the -1 through -9 (or --*-button) cmdline flags. All you people\n" +" with million button mice can remove the ctrl mask with the --no-*-ctrl-mask\n" +" options.\n" "\n" "See 'man feh' for more detailed information\n" +"\n" +"This program is free software see the file COPYING for licensing info.\n" +"Copyright Tom Gilbert (and various contributors) 1999-2003\n" +"Email bugs to \n"); + exit(0); +} + +void +feh_create_default_config(char *rcfile) +{ + FILE *fp; + + D_ENTER(4); + + if ((fp = fopen(rcfile, "w")) == NULL) + { + weprintf("Unable to create default config file %s\n", rcfile); + D_RETURN_(4); + } + + fprintf(fp, + "# Feh configuration file.\n" + "# Lines starting with # are comments. Don't use comments mid-line.\n" + "\n" "# Feh expects to find this as ~/.fehrc or /etc/fehrc\n" + "# If both are available, ~/.fehrc will be used\n" "\n" + "# Options defined in theme_name/options pairs.\n" + "# Separate themename and options by whitespace.\n" "\n" + "# There are two ways of specifying the theme. Either use feh -Tthemename,\n" + "# or use a symbolic link to feh with the name of the theme. eg\n" + "# ln -s `which feh` ~/bin/mkindex\n" + "# Now when you run 'mkindex', feh will load the config specified for the\n" + "# mkindex theme.\n" "\n" "# ======================\n" + "# Some examples of usage\n" "# ======================\n" "\n" + "# Set the default feh options to be recursive and verbose\n" + "# feh -rV\n" "\n" + "# Multiple options can of course be used. They should all be on one line\n" + "# imagemap -rV --quiet -W 400 -H 300 --thumb-width 40 --thumb-height 30\n" + "\n" "# ================================================\n" + "# Here I set some useful themes for you to try out\n" + "# ================================================\n" "\n" + "# Webcam mode, simply specify the url(s).\n" + "# e.g. feh -Twebcam http://cam1 http://cam2\n" + "webcam --multiwindow --reload 20\n" "\n" + "# Create an index of the current directory. This version uses . as the\n" + "# current dir, so you don't even need any commandline arguments.\n" + "mkindex -iVO index.jpg .\n" "\n" "# More ambitious version...\n" + "imgidx -iVO .fehindex.jpg --limit-width 1200 --thumb-width 90 --thumb-height 90 .\n" + "\n" "# Show a presentation\n" + "present --full-screen --sort name\n" + "\n" + "# Booth mode ;-)\n" + "booth --full-screen --hide-pointer --slideshow-delay 20\n" + "\n" + "# Screw xscreensaver, use feh =)\n" + "screensave --full-screen --randomize --slideshow-delay 5\n" "\n" + "# Add tags to your html with ease :-)\n" + "newimg -q -L \"\\\"%%n\\\"\"\n" + "\n" + "# Different menus\n" + "chrome --menu-bg " PREFIX" /share/feh/images/menubg_chrome.png\n" + "brushed --menu-bg " PREFIX "/share/feh/images/menubg_brushed.png\n" + "pastel --menu-bg " PREFIX "/share/feh/images/menubg_pastel.png\n" + "aluminium --menu-bg " PREFIX "/share/feh/images/menubg_aluminium.png\n" + "wood --menu-bg " PREFIX "/share/feh/images/menubg_wood.png\n" + "aqua --menu-bg " PREFIX "/share/feh/images/menubg_aqua.png\n" + "sky --menu-bg " PREFIX "/share/feh/images/menubg_sky.png\n" + "orange --menu-bg " PREFIX "/share/feh/images/menubg_orange.png\n" + "light --menu-bg " PREFIX "/share/feh/images/menubg_light.png\n" + "black --menu-bg " PREFIX "/share/feh/images/menubg_black.png --menu-style " PREFIX "/share/feh/fonts/black.style\n" + "britney --menu-bg " PREFIX "/share/feh/images/menubg_britney.png\n"); + fclose(fp); + + D_RETURN_(4); +} diff --git a/src/options.h b/src/options.h new file mode 100644 index 0000000..0101885 --- /dev/null +++ b/src/options.h @@ -0,0 +1,137 @@ +/* options.h + +Copyright (C) 1999-2003 Tom Gilbert. + +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. + +*/ + +#ifndef OPTIONS_H +#define OPTIONS_H + +struct __fehoptions +{ + unsigned char multiwindow; + unsigned char montage; + unsigned char collage; + unsigned char index; + unsigned char index_show_name; + unsigned char index_show_dim; + unsigned char index_show_size; + unsigned char thumbs; + unsigned char slideshow; + unsigned char recursive; + unsigned char output; + unsigned char verbose; + unsigned char display; + unsigned char bg; + unsigned char alpha; + unsigned char alpha_level; + unsigned char aspect; + unsigned char stretch; + unsigned char keep_http; + unsigned char borderless; + unsigned char randomize; + unsigned char no_jump_on_resort; + unsigned char full_screen; + unsigned char auto_zoom; + unsigned char draw_filename; + unsigned char list; + unsigned char quiet; + unsigned char preload; + unsigned char loadables; + unsigned char unloadables; + unsigned char reverse; + unsigned char no_menus; + unsigned char scale_down; + unsigned char builtin_http; + unsigned char wget_timestamp; + unsigned char bgmode; + unsigned char xinerama; + unsigned char screen_clip; + unsigned char hide_pointer; + unsigned char fmmode; + unsigned char draw_actions; + unsigned char cache_thumbnails; + unsigned char cycle_once; + + char *output_file; + char *output_dir; + char *bg_file; + char *font; + char *title_font; + char *title; + char *thumb_title; + char *actions[10]; + char *fontpath; + char *filelistfile; + char *menu_font; + char *customlist; + char *menu_bg; + char *rcfile; + char *menu_style; + char *caption_path; + + gib_style *menu_style_l; + + unsigned char next_button; + unsigned char zoom_button; + unsigned char menu_button; + unsigned char menu_ctrl_mask; + + unsigned char rotate_button; + unsigned char blur_button; + unsigned char reload_button; + unsigned char no_rotate_ctrl_mask; + unsigned char no_blur_ctrl_mask; + unsigned char no_pan_ctrl_mask; + + int thumb_w; + int thumb_h; + int limit_w; + int limit_h; + int reload; + int sort; + int debug_level; + int geom_flags; + int geom_x; + int geom_y; + int geom_w; + int geom_h; + int default_zoom; + int menu_border; + unsigned char adjust_reload; + unsigned int start_list_at; + + unsigned char mode; + unsigned char paused; + + double slideshow_delay; + + Imlib_Font menu_fn; +}; + +void init_parse_options(int argc, char **argv); +char *feh_string_normalize(char *str); +void feh_create_default_config(char *rcfile); + +extern fehoptions opt; + +#endif diff --git a/src/slideshow.c b/src/slideshow.c new file mode 100644 index 0000000..2ec05a8 --- /dev/null +++ b/src/slideshow.c @@ -0,0 +1,582 @@ +/* slideshow.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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 "filelist.h" +#include "timers.h" +#include "winwidget.h" +#include "options.h" + +void +init_slideshow_mode(void) +{ + winwidget w = NULL; + int success = 0; + char *s = NULL; + gib_list *l = NULL, *last = NULL; + feh_file *file = NULL; + + D_ENTER(3); + + mode = "slideshow"; + if (opt.start_list_at) + { + l = gib_list_nth(filelist, opt.start_list_at); + opt.start_list_at = 0; /* for next time */ + } + else + { + l = filelist; + } + for (; l; l = l->next) + { + file = FEH_FILE(l->data); + if (last) + { + filelist = feh_file_remove_from_list(filelist, last); + filelist_len--; + last = NULL; + } + current_file = l; + s = slideshow_create_name(file); + if ((w = winwidget_create_from_file(l, s, WIN_TYPE_SLIDESHOW)) != NULL) + { + free(s); + success = 1; + winwidget_show(w); + if (opt.slideshow_delay >= 0.0) + feh_add_timer(cb_slide_timer, w, opt.slideshow_delay, + "SLIDE_CHANGE"); + else if (opt.reload > 0) + feh_add_unique_timer(cb_reload_timer, w, opt.reload); + break; + } + else + { + free(s); + last = l; + } + } + if (!success) + show_mini_usage(); + D_RETURN_(3); +} + +void +cb_slide_timer(void *data) +{ + D_ENTER(4); + slideshow_change_image((winwidget) data, SLIDE_NEXT); + D_RETURN_(4); +} + +void +cb_reload_timer(void *data) +{ + winwidget w = (winwidget) data; + + D_ENTER(4); + feh_reload_image(w, 0, 0); + feh_add_unique_timer(cb_reload_timer, w, opt.reload); + D_RETURN_(4); +} + +void +feh_reload_image(winwidget w, int resize, int force_new) +{ + char *title, *new_title; + int len; + Imlib_Image tmp; + + D_ENTER(4); + + if (!w->file) { + weprintf("couldn't reload, this image has no file associated with it."); + D_RETURN_(4); + } + + free(FEH_FILE(w->file->data)->caption); + FEH_FILE(w->file->data)->caption = NULL; + + len = strlen(w->name) + sizeof("Reloading: ") + 1; + new_title = emalloc(len); + snprintf(new_title, len, "Reloading: %s", w->name); + title = estrdup(w->name); + winwidget_rename(w, new_title); + + + /* force imlib2 not to cache */ + if (force_new) { + 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) { + if (force_new) { + eprintf("failed to reload image\n"); + } else { + weprintf("Couldn't reload image. Is it still there?"); + } + winwidget_rename(w, title); + free(title); + free(new_title); + D_RETURN_(4); + } + if (force_new) { + w->im = 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->mode = MODE_NORMAL; + if ((w->im_w != gib_imlib_image_get_width(w->im)) + || (w->im_h != gib_imlib_image_get_height(w->im))) + w->had_resize = 1; + if (w->has_rotated) + { + Imlib_Image temp; + + temp = gib_imlib_create_rotated_image(w->im, 0.0); + w->im_w = gib_imlib_image_get_width(temp); + w->im_h = gib_imlib_image_get_height(temp); + gib_imlib_free_image_and_decache(temp); + } + else + { + 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_rename(w, title); + free(title); + free(new_title); + + D_RETURN_(4); +} + + +void +slideshow_change_image(winwidget winwid, int change) +{ + int success = 0; + gib_list *last = NULL; + int i = 0; + int jmp = 1; + char *s; + + D_ENTER(4); + + /* Without this, clicking a one-image slideshow reloads it. Not very * + intelligent behaviour :-) */ + if (filelist_len < 2) + D_RETURN_(4); + + /* Ok. I do this in such an odd way to ensure that if the last or first * + image is not loadable, it will go through in the right direction to * + find the correct one. Otherwise SLIDE_LAST would try the last file, * + then loop forward to find a loadable one. */ + if (change == SLIDE_FIRST) + { + current_file = gib_list_last(filelist); + change = SLIDE_NEXT; + } + else if (change == SLIDE_LAST) + { + current_file = filelist; + change = SLIDE_PREV; + } + + /* The for loop prevents us looping infinitely */ + for (i = 0; i < filelist_len; i++) + { + winwidget_free_image(winwid); + switch (change) + { + case SLIDE_NEXT: + current_file = feh_list_jump(filelist, current_file, FORWARD, 1); + break; + case SLIDE_PREV: + current_file = feh_list_jump(filelist, current_file, BACK, 1); + break; + case SLIDE_JUMP_FWD: + if (filelist_len < 5) + jmp = 1; + else if (filelist_len < 40) + jmp = 2; + else + jmp = filelist_len / 20; + if (!jmp) + jmp = 2; + current_file = feh_list_jump(filelist, current_file, FORWARD, jmp); + /* important. if the load fails, we only want to step on ONCE to + try the next file, not another jmp */ + change = SLIDE_NEXT; + break; + case SLIDE_JUMP_BACK: + if (filelist_len < 5) + jmp = 1; + else if (filelist_len < 40) + jmp = 2; + else + jmp = filelist_len / 20; + if (!jmp) + jmp = 2; + current_file = feh_list_jump(filelist, current_file, BACK, jmp); + /* important. if the load fails, we only want to step back ONCE to + try the previous file, not another jmp */ + change = SLIDE_NEXT; + break; + default: + eprintf("BUG!\n"); + break; + } + + if (last) + { + filelist = feh_file_remove_from_list(filelist, last); + filelist_len--; + 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) + { + success = 1; + winwid->mode = MODE_NORMAL; + winwid->file = current_file; + if ((winwid->im_w != gib_imlib_image_get_width(winwid->im)) + || (winwid->im_h != gib_imlib_image_get_height(winwid->im))) + winwid->had_resize = 1; + 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); + break; + } + else + last = current_file; + } + if (!success) + { + /* We didn't manage to load any files. Maybe the last one in the show + was deleted? */ + eprintf("No more slides in show"); + } + if (opt.slideshow_delay >= 0.0) + feh_add_timer(cb_slide_timer, winwid, opt.slideshow_delay, + "SLIDE_CHANGE"); + D_RETURN_(4); +} + +void +slideshow_pause_toggle(winwidget w) +{ + char *title, *new_title; + int len; + + if (!opt.paused) + { + opt.paused = 1; + + len = strlen(w->name) + sizeof(" [Paused]") + 1; + new_title = emalloc(len); + snprintf(new_title, len, "%s [Paused]", w->name); + title = estrdup(w->name); + winwidget_rename(w, new_title); + } + else + { + opt.paused = 0; + } +} + +char * +slideshow_create_name(feh_file * file) +{ + char *s = NULL; + int len = 0; + + D_ENTER(4); + if (!opt.title) + { + len = + strlen(PACKAGE " [slideshow mode] - ") + strlen(file->filename) + 1; + s = emalloc(len); + snprintf(s, len, PACKAGE " [%d of %d] - %s", + gib_list_num(filelist, current_file) + 1, + gib_list_length(filelist), file->filename); + } + else + { + s = estrdup(feh_printf(opt.title, file)); + } + + D_RETURN(4, s); +} + +void +feh_action_run(feh_file * file, char *action) +{ + D_ENTER(4); + if (action) + { + D(3, ("Running action %s\n", action)); + char *sys; + sys = feh_printf(action, file); + + if (opt.verbose && !opt.list && !opt.customlist) + fprintf(stderr, "Running action -->%s<--\n", sys); + system(sys); + } + D_RETURN_(4); +} + +char * +feh_printf(char *str, feh_file * file) +{ + char *c; + char buf[20]; + static char ret[4096]; + + D_ENTER(4); + + ret[0] = '\0'; + + for (c = str; *c != '\0'; c++) + { + if (*c == '%') + { + c++; + switch (*c) + { + case 'f': + if (file) + strcat(ret, file->filename); + break; + case 'n': + if (file) + strcat(ret, file->name); + break; + case 'w': + if (file) + { + if (!file->info) + feh_file_info_load(file, NULL); + snprintf(buf, sizeof(buf), "%d", file->info->width); + strcat(ret, buf); + } + break; + case 'h': + if (file) + { + if (!file->info) + feh_file_info_load(file, NULL); + snprintf(buf, sizeof(buf), "%d", file->info->height); + strcat(ret, buf); + } + break; + case 's': + if (file) + { + if (!file->info) + feh_file_info_load(file, NULL); + snprintf(buf, sizeof(buf), "%d", file->info->size); + strcat(ret, buf); + } + break; + case 'p': + if (file) + { + if (!file->info) + feh_file_info_load(file, NULL); + snprintf(buf, sizeof(buf), "%d", file->info->pixels); + strcat(ret, buf); + } + break; + case 't': + if (file) + { + if (!file->info) + feh_file_info_load(file, NULL); + strcat(ret, file->info->format); + } + break; + case 'P': + strcat(ret, PACKAGE); + break; + case 'v': + strcat(ret, VERSION); + break; + case 'm': + strcat(ret, mode); + break; + case 'l': + snprintf(buf, sizeof(buf), "%d", gib_list_length(filelist)); + strcat(ret, buf); + break; + case 'u': + snprintf(buf, sizeof(buf), "%d", + current_file != NULL ? gib_list_num(filelist, + current_file) + + 1 : 0); + strcat(ret, buf); + break; + default: + strncat(ret, c, 1); + break; + } + } + else if (*c == '\\') + { + c++; + switch (*c) + { + case 'n': + strcat(ret, "\n"); + break; + default: + strncat(ret, c, 1); + break; + } + } + else + strncat(ret, c, 1); + } + D_RETURN(4, ret); +} + +void +feh_filelist_image_remove(winwidget winwid, char do_delete) +{ + if (winwid->type == WIN_TYPE_SLIDESHOW) + { + char *s; + gib_list *doomed; + + doomed = current_file; + slideshow_change_image(winwid, SLIDE_NEXT); + filelist_len--; + if (do_delete) + filelist = feh_file_rm_and_free(filelist, doomed); + else + filelist = feh_file_remove_from_list(filelist, doomed); + if (!filelist) + { + /* No more images. Game over ;-) */ + winwidget_destroy(winwid); + return; + } + s = slideshow_create_name(FEH_FILE(winwid->file->data)); + winwidget_rename(winwid, s); + free(s); + } + else if ((winwid->type == WIN_TYPE_SINGLE) + || (winwid->type == WIN_TYPE_THUMBNAIL_VIEWER)) + { + filelist_len--; + if (do_delete) + filelist = feh_file_rm_and_free(filelist, winwid->file); + else + filelist = feh_file_remove_from_list(filelist, winwid->file); + winwidget_destroy(winwid); + } +} + +void slideshow_save_image(winwidget win) +{ + char *tmpname; + + D_ENTER(4); + if(win->file) { + tmpname = feh_unique_filename("", FEH_FILE(win->file->data)->name); + } else if(mode) { + char *tmp; + tmp = estrjoin(".", mode, "png", NULL); + tmpname = feh_unique_filename("", tmp); + free(tmp); + } else { + tmpname = feh_unique_filename("", "noname.png"); + } + + if(!opt.quiet) + printf("saving image to filename '%s'\n", tmpname); + + gib_imlib_save_image(win->im, tmpname); + free(tmpname); + D_RETURN_(4); +} + +gib_list * +feh_list_jump(gib_list * root, gib_list * l, int direction, int num) +{ + int i; + gib_list *ret = NULL; + + if (!root) + return (NULL); + if (!l) + return (root); + + ret = l; + + for (i = 0; i < num; i++) + { + if (direction == FORWARD) + { + if (ret->next) + { + ret = ret->next; + } + else + { + if (opt.cycle_once) + { + exit(0); + } + ret = root; + } + } + else + { + if (ret->prev) + ret = ret->prev; + else + ret = gib_list_last(ret); + } + } + return (ret); +} + diff --git a/src/stamp-h.in b/src/stamp-h.in new file mode 100644 index 0000000..9788f70 --- /dev/null +++ b/src/stamp-h.in @@ -0,0 +1 @@ +timestamp diff --git a/src/structs.h b/src/structs.h new file mode 100644 index 0000000..a2d3527 --- /dev/null +++ b/src/structs.h @@ -0,0 +1,37 @@ +/* structs.h + +Copyright (C) 1999-2003 Tom Gilbert. + +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. + +*/ + +#ifndef STRUCTS_H +#define STRUCTS_H + +typedef struct __fehtimer _fehtimer; +typedef _fehtimer *fehtimer; +typedef struct __feh_file feh_file; +typedef struct __feh_file_info feh_file_info; +typedef struct __winwidget _winwidget; +typedef _winwidget *winwidget; +typedef struct __fehoptions fehoptions; + +#endif diff --git a/src/support.c b/src/support.c new file mode 100644 index 0000000..7f38f27 --- /dev/null +++ b/src/support.c @@ -0,0 +1,658 @@ +/* support.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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 "filelist.h" +#include "options.h" +#include "support.h" +Window ipc_win = None; +Window my_ipc_win = None; +Atom ipc_atom = None; +static unsigned char timeout = 0; + +/* + * This is a boolean indicating + * That while we seem to see E16 IPC + * it's actually E17 faking it + * -- richlowe 2005-06-22 + */ +static char e17_fake_ipc = 0; + +void +feh_wm_set_bg_file(char *file, unsigned char bgmode) +{ + Imlib_Image im; + feh_file *fil; + + fil = feh_file_new(file); + if (fil) + { + if (feh_load_image(&im, fil) == 0) + eprintf("Couldn't load image in order to set bg"); + switch (bgmode) + { + case BG_MODE_SEAMLESS: + gib_imlib_image_tile(im); + feh_wm_set_bg(NULL, im, 0, 0, 0, 1); + break; + case BG_MODE_TILE: + feh_wm_set_bg(file, im, 0, 0, 0, 1); + break; + case BG_MODE_SCALE: + feh_wm_set_bg(file, im, 0, 1, 0, 1); + break; + default: + feh_wm_set_bg(file, im, 1, 0, 0, 1); + break; + } + gib_imlib_free_image_and_decache(im); + feh_file_free(fil); + } +} + +void +feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled, + int desktop, int set) +{ + char bgname[20]; + int num = (int) rand(); + char bgfil[4096]; + char sendbuf[4096]; + + D_ENTER(4); + + snprintf(bgname, sizeof(bgname), "FEHBG_%d", num); + + if (!fil) + { + snprintf(bgfil, sizeof(bgfil), "%s/.%s.png", getenv("HOME"), bgname); + imlib_context_set_image(im); + imlib_image_set_format("png"); + gib_imlib_save_image(im, bgfil); + D(3, ("bg saved as %s\n", bgfil)); + fil = bgfil; + } + D(3, ("Setting bg %s\n", fil)); + + if (feh_wm_get_wm_is_e() && (enl_ipc_get_win() != None)) + { + snprintf(sendbuf, sizeof(sendbuf), "background %s bg.file %s", bgname, + fil); + enl_ipc_send(sendbuf); + + if (scaled) + { + snprintf(sendbuf, sizeof(sendbuf), "background %s bg.solid 0 0 0", + bgname); + enl_ipc_send(sendbuf); + snprintf(sendbuf, sizeof(sendbuf), "background %s bg.tile 0", + bgname); + enl_ipc_send(sendbuf); + snprintf(sendbuf, sizeof(sendbuf), "background %s bg.xjust 512", + bgname); + enl_ipc_send(sendbuf); + snprintf(sendbuf, sizeof(sendbuf), "background %s bg.yjust 512", + bgname); + enl_ipc_send(sendbuf); + snprintf(sendbuf, sizeof(sendbuf), "background %s bg.xperc 1024", + bgname); + enl_ipc_send(sendbuf); + snprintf(sendbuf, sizeof(sendbuf), "background %s bg.yperc 1024", + bgname); + enl_ipc_send(sendbuf); + } + else if (centered) + { + snprintf(sendbuf, sizeof(sendbuf), "background %s bg.solid 0 0 0", + bgname); + enl_ipc_send(sendbuf); + snprintf(sendbuf, sizeof(sendbuf), "background %s bg.tile 0", + bgname); + enl_ipc_send(sendbuf); + snprintf(sendbuf, sizeof(sendbuf), "background %s bg.xjust 512", + bgname); + enl_ipc_send(sendbuf); + snprintf(sendbuf, sizeof(sendbuf), "background %s bg.yjust 512", + bgname); + enl_ipc_send(sendbuf); + } + else + { + snprintf(sendbuf, sizeof(sendbuf), "background %s bg.tile 1", + bgname); + enl_ipc_send(sendbuf); + } + + if (set) + { + snprintf(sendbuf, sizeof(sendbuf), "use_bg %s %d", bgname, desktop); + enl_ipc_send(sendbuf); + } + enl_ipc_sync(); + } + else + { + Atom prop_root, prop_esetroot, type; + int format; + unsigned long length, after; + unsigned char *data_root, *data_esetroot; + Pixmap pmap_d1, pmap_d2; + /* string for sticking in ~/.fehbg */ + char *fehbg = NULL; + char *home; + + /* local display to set closedownmode on */ + Display *disp2; + Window root2; + int depth2; + XGCValues gcvalues; + GC gc; + int w, h; + + D(3, ("Falling back to XSetRootWindowPixmap\n")); + + 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", fil, NULL); + } else if (centered) { + XGCValues gcval; + GC gc; + int x, y; + + D(3, ("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 */ + + 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); + XFreeGC(disp, gc); + fehbg = estrjoin(" ", "feh --bg-center", fil, NULL); + } else { + w = gib_imlib_image_get_width(im); + h = gib_imlib_image_get_height(im); + pmap_d1 = + XCreatePixmap(disp, root, w, h, depth); + gib_imlib_render_image_on_drawable(pmap_d1, im, 0, 0, 1, 0, 0); + fehbg = estrjoin(" ", "feh --bg-tile", fil, NULL); + } + + if (fehbg) { + home = getenv("HOME"); + if(home) { + FILE *fp; + char *path; + path = estrjoin("/", home, ".fehbg", NULL); + if ((fp = fopen(path, "w")) == NULL) { + wprintf("Can't open %s for write", path); + } else { + fprintf(fp, "%s\n", fehbg); + fclose(fp); + } + free(path); + } + free(fehbg); + } + + /* create new display, copy pixmap to new display */ + disp2 = XOpenDisplay(NULL); + if (!disp2) + eprintf("Can't reopen X display."); + root2 = RootWindow(disp2, DefaultScreen(disp2)); + depth2 = DefaultDepth(disp2, DefaultScreen(disp2)); + XSync(disp, False); + pmap_d2 = XCreatePixmap(disp2, root2, scr->width, scr->height, depth2); + gcvalues.fill_style = FillTiled; + gcvalues.tile = pmap_d1; + gc = XCreateGC(disp2, pmap_d2, GCFillStyle|GCTile, &gcvalues); + XFillRectangle(disp2, pmap_d2, gc, 0, 0, scr->width, scr->height); + XFreeGC(disp2, gc); + XSync(disp2, False); + XSync(disp, False); + XFreePixmap(disp, pmap_d1); + + prop_root = XInternAtom(disp2, "_XROOTPMAP_ID", True); + prop_esetroot = XInternAtom(disp2, "ESETROOT_PMAP_ID", True); + + if (prop_root != None && prop_esetroot != None) + { + XGetWindowProperty(disp2, root2, prop_root, 0L, 1L, False, + AnyPropertyType, &type, &format, &length, &after, + &data_root); + if (type == XA_PIXMAP) + { + XGetWindowProperty(disp2, root2, prop_esetroot, 0L, 1L, False, + AnyPropertyType, &type, &format, &length, + &after, &data_esetroot); + if (data_root && data_esetroot) + { + if (type == XA_PIXMAP + && *((Pixmap *) data_root) == *((Pixmap *) data_esetroot)) + { + XKillClient(disp2, *((Pixmap *) data_root)); + } + } + } + } + /* This will locate the property, creating it if it doesn't exist */ + prop_root = XInternAtom(disp2, "_XROOTPMAP_ID", False); + prop_esetroot = XInternAtom(disp2, "ESETROOT_PMAP_ID", False); + + if (prop_root == None || prop_esetroot == None) + weprintf("creation of pixmap property failed."); + + XChangeProperty(disp2, root2, prop_root, XA_PIXMAP, 32, PropModeReplace, + (unsigned char *) &pmap_d2, 1); + XChangeProperty(disp2, root2, prop_esetroot, XA_PIXMAP, 32, + PropModeReplace, (unsigned char *) &pmap_d2, 1); + + XSetWindowBackgroundPixmap(disp2, root2, pmap_d2); + XClearWindow(disp2, root2); + XFlush(disp2); + XSetCloseDownMode(disp2, RetainPermanent); + XCloseDisplay(disp2); + } + D_RETURN_(4); +} + +signed char +feh_wm_get_wm_is_e(void) +{ + static signed char e = -1; + + D_ENTER(4); + + /* check if E is actually running */ + if (e == -1) + { + /* XXX: This only covers E17 prior to 6/22/05 */ + if ((XInternAtom(disp, "ENLIGHTENMENT_COMMS", True) != None) && + (XInternAtom(disp, "ENLIGHTENMENT_VERSION", True) != None)) + { + D(3, ("Enlightenment detected.\n")); + e = 1; + } + else + { + D(3, ("Enlightenment not detected.\n")); + e = 0; + } + } + D_RETURN(4, e); +} + +int +feh_wm_get_num_desks(void) +{ + char *buf, *ptr; + int desks; + + D_ENTER(4); + + if (!feh_wm_get_wm_is_e()) + D_RETURN(4, -1); + + buf = enl_send_and_wait("num_desks ?"); + if (buf == IPC_FAKE) /* Fake E17 IPC */ + D_RETURN(4, -1); + D(3, ("Got from E IPC: %s\n", buf)); + ptr = buf; + while (ptr && !isdigit(*ptr)) + ptr++; + desks = atoi(ptr); + +D_RETURN(4, desks)} + +Window +enl_ipc_get_win(void) +{ + + unsigned char *str = NULL; + Atom prop, prop2, ever; + unsigned long num, after; + int format; + Window dummy_win; + int dummy_int; + unsigned int dummy_uint; + + D_ENTER(4); + + D(3, ("Searching for IPC window.\n")); + + /* + * Shortcircuit this entire func + * if we already know it's an e17 fake + */ + if (e17_fake_ipc) + D_RETURN(4, ipc_win) + + prop = XInternAtom(disp, "ENLIGHTENMENT_COMMS", True); + if (prop == None) + { + D(3, ("Enlightenment is not running.\n")); + D_RETURN(4, None); + } else { + /* XXX: This will only work with E17 prior to 6/22/2005 */ + ever = XInternAtom(disp, "ENLIGHTENMENT_VERSION", True); + if (ever == None) { + /* This is an E without ENLIGHTENMENT_VERSION */ + D(3, ("E16 IPC Protocol not supported")); + D_RETURN(4, None); + } + } + XGetWindowProperty(disp, root, prop, 0, 14, False, AnyPropertyType, &prop2, + &format, &num, &after, &str); + if (str) + { + sscanf((char *) str, "%*s %x", (unsigned int *) &ipc_win); + XFree(str); + } + if (ipc_win != None) + { + if (!XGetGeometry + (disp, ipc_win, &dummy_win, &dummy_int, &dummy_int, &dummy_uint, + &dummy_uint, &dummy_uint, &dummy_uint)) + { + D(3, + (" -> IPC Window property is valid, but the window doesn't exist.\n")); + ipc_win = None; + } + str = NULL; + if (ipc_win != None) + { + XGetWindowProperty(disp, ipc_win, prop, 0, 14, False, + AnyPropertyType, &prop2, &format, &num, &after, + &str); + if (str) + { + XFree(str); + } + else + { + D(3, + (" -> IPC Window lacks the proper atom. I can't talk to fake IPC windows....\n")); + ipc_win = None; + } + } + } + if (ipc_win != None) + { + + XGetWindowProperty(disp, ipc_win, ever, 0, 14, False, AnyPropertyType, + &prop2, &format, &num, &after, &str); + if (str) { + /* + * This is E17's way of telling us it's only pretending + * as a workaround for a bug related to the way java handles + * Window Managers. + * (Only valid after date of this comment) + * -- richlowe 2005-06-22 + */ + XFree(str); + D(3,(" -> Found a fake E17 IPC window, ignoring")); + ipc_win = None; + e17_fake_ipc = 1; + D_RETURN(4, ipc_win); + } + + D(3, + (" -> IPC Window found and verified as 0x%08x. Registering feh as an IPC client.\n", + (int) ipc_win)); + XSelectInput(disp, ipc_win, + StructureNotifyMask | SubstructureNotifyMask); + enl_ipc_send("set clientname " PACKAGE); + enl_ipc_send("set version " VERSION); + enl_ipc_send("set email tom@linuxbrit.co.uk"); + enl_ipc_send("set web http://www.linuxbrit.co.uk"); + enl_ipc_send("set info Feh - be pr0n or be dead"); + } + if (my_ipc_win == None) + { + my_ipc_win = XCreateSimpleWindow(disp, root, -2, -2, 1, 1, 0, 0, 0); + } + D_RETURN(4, ipc_win); +} + +void +enl_ipc_send(char *str) +{ + + static char *last_msg = NULL; + char buff[21]; + register unsigned short i; + register unsigned char j; + unsigned short len; + XEvent ev; + + D_ENTER(4); + if (str == NULL) + { + if (last_msg == NULL) + eprintf("eeek"); + str = last_msg; + D(4, ("Resending last message \"%s\" to Enlightenment.\n", str)); + } + else + { + if (last_msg != NULL) + { + free(last_msg); + } + last_msg = estrdup(str); + D(4, ("Sending \"%s\" to Enlightenment.\n", str)); + } + if (ipc_win == None) + { + if ((ipc_win = enl_ipc_get_win()) == None) + { + D(3, + ("Hrm. Enlightenment doesn't seem to be running. No IPC window, no IPC.\n")); + D_RETURN_(4); + } + } + len = strlen(str); + ipc_atom = XInternAtom(disp, "ENL_MSG", False); + if (ipc_atom == None) + { + D(3, ("IPC error: Unable to find/create ENL_MSG atom.\n")); + D_RETURN_(4); + } + for (; XCheckTypedWindowEvent(disp, my_ipc_win, ClientMessage, &ev);); /* Discard any out-of-sync messages */ + ev.xclient.type = ClientMessage; + ev.xclient.serial = 0; + ev.xclient.send_event = True; + ev.xclient.window = ipc_win; + ev.xclient.message_type = ipc_atom; + ev.xclient.format = 8; + + for (i = 0; i < len + 1; i += 12) + { + sprintf(buff, "%8x", (int) my_ipc_win); + for (j = 0; j < 12; j++) + { + buff[8 + j] = str[i + j]; + if (!str[i + j]) + { + break; + } + } + buff[20] = 0; + for (j = 0; j < 20; j++) + { + ev.xclient.data.b[j] = buff[j]; + } + XSendEvent(disp, ipc_win, False, 0, (XEvent *) & ev); + } + D_RETURN_(4); +} + +static sighandler_t * +enl_ipc_timeout(int sig) +{ + timeout = 1; + D_RETURN(4, (sighandler_t *) sig); + sig = 0; +} + +char * +enl_wait_for_reply(void) +{ + + XEvent ev; + static char msg_buffer[20]; + register unsigned char i; + + D_ENTER(4); + + alarm(2); + for (; + !XCheckTypedWindowEvent(disp, my_ipc_win, ClientMessage, &ev) + && !timeout;); + alarm(0); + if (ev.xany.type != ClientMessage) + { + D_RETURN(4, IPC_TIMEOUT); + } + for (i = 0; i < 20; i++) + { + msg_buffer[i] = ev.xclient.data.b[i]; + } + D_RETURN(4, msg_buffer + 8); +} + +char * +enl_ipc_get(const char *msg_data) +{ + + static char *message = NULL; + static unsigned short len = 0; + char buff[13], *ret_msg = NULL; + register unsigned char i; + unsigned char blen; + + D_ENTER(4); + + if (msg_data == IPC_TIMEOUT) + { + D_RETURN(4, IPC_TIMEOUT); + } + for (i = 0; i < 12; i++) + { + buff[i] = msg_data[i]; + } + buff[12] = 0; + blen = strlen(buff); + if (message != NULL) + { + len += blen; + message = (char *) erealloc(message, len + 1); + strcat(message, buff); + } + else + { + len = blen; + message = (char *) emalloc(len + 1); + strcpy(message, buff); + } + if (blen < 12) + { + ret_msg = message; + message = NULL; + D(4, ("Received complete reply: \"%s\"\n", ret_msg)); + } + D_RETURN(4, ret_msg); +} + +char * +enl_send_and_wait(char *msg) +{ + char *reply = IPC_TIMEOUT; + sighandler_t old_alrm; + + D_ENTER(4); + + /* + * Shortcut this func and return IPC_FAKE + * If the IPC Window is the E17 fake + */ + if (e17_fake_ipc) + return IPC_FAKE; + + if (ipc_win == None) + { + /* The IPC window is missing. Wait for it to return or feh to be killed. */ + /* Only called once in the E17 case */ + for (; enl_ipc_get_win() == None;) + { + if (e17_fake_ipc) + return IPC_FAKE; + else + sleep(1); + } + } + old_alrm = (sighandler_t) signal(SIGALRM, (sighandler_t) enl_ipc_timeout); + for (; reply == IPC_TIMEOUT;) + { + timeout = 0; + enl_ipc_send(msg); + for (; !(reply = enl_ipc_get(enl_wait_for_reply()));); + if (reply == IPC_TIMEOUT) + { + /* We timed out. The IPC window must be AWOL. Reset and resend message. */ + D(3, ("IPC timed out. IPC window has gone. Clearing ipc_win.\n")); + XSelectInput(disp, ipc_win, None); + ipc_win = None; + } + } + signal(SIGALRM, old_alrm); + D_RETURN(4, reply); +} diff --git a/src/support.h b/src/support.h new file mode 100644 index 0000000..a8f81a1 --- /dev/null +++ b/src/support.h @@ -0,0 +1,56 @@ +/* support.h + +Copyright (C) 1999-2003 Tom Gilbert. + +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. + +*/ + +#ifndef SUPPORT_H +#define SUPPORT_H + +#include +#include /* Xlib, Xutil, Xresource, Xfuncproto */ + +#define IPC_TIMEOUT ((char *) 1) +#define IPC_FAKE ((char *) 2) /* Faked IPC */ + +#define enl_ipc_sync() do { \ + char *reply = enl_send_and_wait("nop"); \ + if ((reply != IPC_FAKE) && (reply != IPC_TIMEOUT)) \ + free(reply); \ + } while (0) + +extern Window ipc_win; +extern Atom ipc_atom; + +_XFUNCPROTOBEGIN extern Window enl_ipc_get_win(void); +extern void enl_ipc_send(char *); +extern char *enl_wait_for_reply(void); +extern char *enl_ipc_get(const char *); +extern char *enl_send_and_wait(char *); +extern void feh_wm_set_bg(char *fil, Imlib_Image im, int centered, int scaled, + int desktop, int set); +extern int feh_wm_get_num_desks(void); +extern signed char feh_wm_get_wm_is_e(void); +void feh_wm_set_bg_file(char *file, unsigned char bgmode); + +_XFUNCPROTOEND +#endif diff --git a/src/thumbnail.c b/src/thumbnail.c new file mode 100644 index 0000000..f85e434 --- /dev/null +++ b/src/thumbnail.c @@ -0,0 +1,992 @@ +/* thumbnail.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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 "filelist.h" +#include "winwidget.h" +#include "options.h" +#include "thumbnail.h" +#include "md5.h" +#include "feh_png.h" + +static char *create_index_dimension_string(int w, int h); +static char *create_index_size_string(char *file); +static char *create_index_title_string(int num, int w, int h); +static gib_list *thumbnails = NULL; + +static thumbmode_data td; + +/* TODO Break this up a bit ;) */ +/* TODO s/bit/lot */ +void +init_thumbnail_mode(void) +{ + /* moved to thumbnail_data: + Imlib_Image im_main; + Imlib_Image bg_im = NULL; + Imlib_Font fn = NULL; + Imlib_Font title_fn = NULL; + + int w = 800, h = 600; + int bg_w = 0, bg_h = 0; + + int text_area_w, text_area_h; + int max_column_w = 0; + */ + + + Imlib_Image im_temp; + int ww = 0, hh = 0, www, hhh, xxx, yyy; + int x = 0, y = 0; + winwidget winwid = NULL; + Imlib_Image im_thumb = NULL; + unsigned char trans_bg = 0; + int title_area_h = 0; + int tw = 0, th = 0; + int fw_name, fw_size, fw_dim, fh; + int thumbnailcount = 0; + feh_file *file = NULL; + gib_list *l, *last = NULL; + int lines; + int index_image_width, index_image_height; + int x_offset_name = 0, x_offset_dim = 0, x_offset_size = 0; + char *s; + + /* initialize thumbnail mode data */ + td.im_main = NULL; + td.im_bg = NULL; + td.font_main = NULL; + td.font_title = NULL; + + td.w = 640; + td.h = 480; + td.bg_w = 0; + td.bg_h = 0; + td.thumb_tot_h = 0; + td.text_area_w = 0; + td.text_area_h = 0; + + td.vertical = 0; + td.max_column_w = 0; + + D_ENTER(3); + + mode = "thumbnail"; + + td.font_main = gib_imlib_load_font(opt.font); + + if (opt.title_font) + { + int fh, fw; + + td.font_title = gib_imlib_load_font(opt.title_font); + gib_imlib_get_text_size(td.font_title, "W", NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT); + title_area_h = fh + 4; + } + else + td.font_title = imlib_load_font(DEFAULT_FONT_TITLE); + + if ((!td.font_main) || (!td.font_title)) + eprintf("Error loading fonts"); + + /* Work out how tall the font is */ + gib_imlib_get_text_size(td.font_main, "W", NULL, &tw, &th, IMLIB_TEXT_TO_RIGHT); + /* For now, allow room for the right number of lines with small gaps */ + td.text_area_h = + ((th + 2) * (opt.index_show_name + opt.index_show_size + + opt.index_show_dim)) + 5; + + /* This includes the text area for index data */ + td.thumb_tot_h = opt.thumb_h + td.text_area_h; + + /* Use bg image dimensions for default size */ + if (opt.bg && opt.bg_file) + { + if (!strcmp(opt.bg_file, "trans")) + trans_bg = 1; + else + { + + D(3, ("Time to apply a background to blend onto\n")); + if (feh_load_image_char(&td.im_bg, opt.bg_file) != 0) + { + td.bg_w = gib_imlib_image_get_width(td.im_bg); + td.bg_h = gib_imlib_image_get_height(td.im_bg); + } + } + } + + /* figure out geometry for the main window and entries */ + feh_thumbnail_calculate_geometry(); + + index_image_width = td.w; + index_image_height = td.h + title_area_h; + td.im_main = imlib_create_image(index_image_width, index_image_height); + + if (!td.im_main) + eprintf("Imlib error creating index image, are you low on RAM?"); + + if (td.im_bg) + gib_imlib_blend_image_onto_image(td.im_main, td.im_bg, + gib_imlib_image_has_alpha(td.im_bg), 0, 0, + td.bg_w, td.bg_h, 0, 0, td.w, td.h, 1, 0, 0); + else if (trans_bg) + { + gib_imlib_image_fill_rectangle(td.im_main, 0, 0, td.w, td.h + title_area_h, 0, 0, + 0, 0); + gib_imlib_image_set_has_alpha(td.im_main, 1); + } + else + { + /* Colour the background */ + gib_imlib_image_fill_rectangle(td.im_main, 0, 0, td.w, td.h + title_area_h, 0, 0, + 0, 255); + } + + /* Create title now */ + + if (!opt.title) + s = estrdup(PACKAGE " [thumbnail mode]"); + else + s = estrdup(feh_printf(opt.title, NULL)); + + if (opt.display) + { + winwid = winwidget_create_from_image(td.im_main, s, WIN_TYPE_THUMBNAIL); + winwidget_show(winwid); + } + + /* make sure we have an ~/.thumbnails/normal directory for storing + permanent thumbnails */ + td.cache_thumbnails = feh_thumbnail_setup_thumbnail_dir(); + td.cache_thumbnails = opt.cache_thumbnails; + + for (l = filelist; l; l = l->next) + { + file = FEH_FILE(l->data); + if (last) + { + filelist = feh_file_remove_from_list(filelist, last); + filelist_len--; + last = NULL; + } + D(4, ("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 (opt.verbose) + feh_display_status('.'); + D(4, ("Successfully loaded %s\n", file->filename)); + www = opt.thumb_w; + hhh = opt.thumb_h; + ww = gib_imlib_image_get_width(im_temp); + hh = gib_imlib_image_get_height(im_temp); + thumbnailcount++; + if (gib_imlib_image_has_alpha(im_temp)) + imlib_context_set_blend(1); + else + imlib_context_set_blend(0); + + 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; + } + + 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(3, ("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); + } + + td.text_area_w = opt.thumb_w; + /* Now draw on the info text */ + if (opt.index_show_name) + { + gib_imlib_get_text_size(td.font_main, file->name, NULL, &fw_name, &fh, + IMLIB_TEXT_TO_RIGHT); + if (fw_name > td.text_area_w) + td.text_area_w = fw_name; + } + if (opt.index_show_dim) + { + gib_imlib_get_text_size(td.font_main, create_index_dimension_string(ww, hh), + NULL, &fw_dim, &fh, IMLIB_TEXT_TO_RIGHT); + if (fw_dim > td.text_area_w) + td.text_area_w = fw_dim; + } + if (opt.index_show_size) + { + gib_imlib_get_text_size(td.font_main, + create_index_size_string(file->filename), + NULL, &fw_size, &fh, IMLIB_TEXT_TO_RIGHT); + if (fw_size > td.text_area_w) + td.text_area_w = fw_size; + } + if (td.text_area_w > opt.thumb_w) + td.text_area_w += 5; + + /* offsets for centering text */ + x_offset_name = (td.text_area_w - fw_name) / 2; + x_offset_dim = (td.text_area_w - fw_dim) / 2; + x_offset_size = (td.text_area_w - fw_size) / 2; + + if (td.vertical) + { + if (td.text_area_w > td.max_column_w) + td.max_column_w = td.text_area_w; + if (y > td.h - td.thumb_tot_h) + { + y = 0; + x += td.max_column_w; + td.max_column_w = 0; + } + if (x > td.w - td.text_area_w) + break; + } + else + { + if (x > td.w - td.text_area_w) + { + x = 0; + y += td.thumb_tot_h; + } + if (y > td.h - td.thumb_tot_h) + break; + } + + if (opt.aspect) + { + xxx = x + ((opt.thumb_w - www) / 2); + yyy = y + ((opt.thumb_h - hhh) / 2); + } + else + { + /* Ignore the aspect ratio and squash the image in */ + xxx = x; + yyy = y; + } + + /* Draw now */ + gib_imlib_blend_image_onto_image(td.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); + + thumbnails = + gib_list_add_front(thumbnails, + feh_thumbnail_new(file, xxx, yyy, www, hhh)); + + gib_imlib_free_image_and_decache(im_thumb); + + lines = 0; + if (opt.index_show_name) + gib_imlib_text_draw(td.im_main, td.font_main, NULL, x + x_offset_name, + y + opt.thumb_h + (lines++ * (th + 2)) + 2, + file->name, IMLIB_TEXT_TO_RIGHT, 255, 255, + 255, 255); + if (opt.index_show_dim) + gib_imlib_text_draw(td.im_main, td.font_main, NULL, x + x_offset_dim, + y + opt.thumb_h + (lines++ * (th + 2)) + 2, + create_index_dimension_string(ww, hh), + IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255); + if (opt.index_show_size) + gib_imlib_text_draw(td.im_main, td.font_main, NULL, x + x_offset_size, + y + opt.thumb_h + (lines++ * (th + 2)) + 2, + create_index_size_string(file->filename), + IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255); + + if (td.vertical) + y += td.thumb_tot_h; + else + x += td.text_area_w; + } + else + { + if (opt.verbose) + feh_display_status('x'); + last = l; + } + if (opt.display) + { + winwidget_render_image(winwid, 0, 0); + if (!feh_main_iteration(0)) + exit(0); + } + } + if (opt.verbose) + fprintf(stdout, "\n"); + + if (opt.title_font) + { + int fw, fh, fx, fy; + char *s; + + s = create_index_title_string(thumbnailcount, td.w, td.h); + gib_imlib_get_text_size(td.font_title, s, NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT); + fx = (index_image_width - fw) >> 1; + fy = index_image_height - fh - 2; + gib_imlib_text_draw(td.im_main, td.font_title, NULL, fx, fy, s, IMLIB_TEXT_TO_RIGHT, + 255, 255, 255, 255); + } + + 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, 1024); + gib_imlib_save_image(td.im_main, output_buf); + if (opt.verbose) + { + int tw, th; + + tw = gib_imlib_image_get_width(td.im_main); + th = gib_imlib_image_get_height(td.im_main); + fprintf(stdout, PACKAGE " - File saved as %s\n", output_buf); + fprintf(stdout, + " - Image is %dx%d pixels and contains %d thumbnails\n", + tw, th, thumbnailcount); + } + } + + if (!opt.display) + gib_imlib_free_image_and_decache(td.im_main); + + free(s); + D_RETURN_(3); +} + + +static char * +create_index_size_string(char *file) +{ + static char str[50]; + int size = 0; + double kbs = 0.0; + struct stat st; + + D_ENTER(4); + if (stat(file, &st)) + kbs = 0.0; + else + { + size = st.st_size; + kbs = (double) size / 1000; + } + + snprintf(str, sizeof(str), "%.2fKb", kbs); + D_RETURN(4, str); +} + +static char * +create_index_dimension_string(int w, int h) +{ + static char str[50]; + + D_ENTER(4); + snprintf(str, sizeof(str), "%dx%d", w, h); + D_RETURN(4, str); +} + +static char * +create_index_title_string(int num, int w, int h) +{ + static char str[50]; + + D_ENTER(4); + snprintf(str, sizeof(str), + PACKAGE " index - %d thumbnails, %d by %d pixels", num, w, h); + D_RETURN(4, str); +} + +feh_thumbnail * +feh_thumbnail_new(feh_file * file, int x, int y, int w, int h) +{ + feh_thumbnail *thumb; + + D_ENTER(4); + + thumb = (feh_thumbnail *) emalloc(sizeof(feh_thumbnail)); + thumb->x = x; + thumb->y = y; + thumb->w = w; + thumb->h = h; + thumb->file = file; + thumb->exists = 1; + + D_RETURN(4, thumb); +} + +feh_file * +feh_thumbnail_get_file_from_coords(int x, int y) +{ + gib_list *l; + feh_thumbnail *thumb; + + D_ENTER(4); + + for (l = thumbnails; l; l = l->next) + { + thumb = FEH_THUMB(l->data); + if (XY_IN_RECT(x, y, thumb->x, thumb->y, thumb->w, thumb->h)) + { + if (thumb->exists) + { + D_RETURN(4, thumb->file); + } + } + } + D(4, ("No matching %d %d\n", x, y)); + D_RETURN(4, NULL); +} + +feh_thumbnail * +feh_thumbnail_get_thumbnail_from_coords(int x, int y) +{ + gib_list *l; + feh_thumbnail *thumb; + + D_ENTER(4); + + for (l = thumbnails; l; l = l->next) + { + thumb = FEH_THUMB(l->data); + if (XY_IN_RECT(x, y, thumb->x, thumb->y, thumb->w, thumb->h)) + { + if (thumb->exists) + { + D_RETURN(4, thumb); + } + } + } + D(4, ("No matching %d %d\n", x, y)); + D_RETURN(4, NULL); +} + +feh_thumbnail * +feh_thumbnail_get_from_file(feh_file * file) +{ + gib_list *l; + feh_thumbnail *thumb; + + D_ENTER(4); + + for (l = thumbnails; l; l = l->next) + { + thumb = FEH_THUMB(l->data); + if (thumb->file == file) + { + if (thumb->exists) + { + D_RETURN(4, thumb); + } + } + } + D(4, ("No match\n")); + D_RETURN(4, NULL); +} + + +void +feh_thumbnail_mark_removed(feh_file * file, int deleted) +{ + feh_thumbnail *thumb; + winwidget w; + + D_ENTER(4); + + thumb = feh_thumbnail_get_from_file(file); + if (thumb) + { + w = winwidget_get_first_window_of_type(WIN_TYPE_THUMBNAIL); + if (w) + { + td.font_main = imlib_load_font(DEFAULT_FONT_TITLE); + if (deleted) + gib_imlib_image_fill_rectangle(w->im, thumb->x, thumb->y, + thumb->w, thumb->h, 255, 0, 0, + 150); + else + gib_imlib_image_fill_rectangle(w->im, thumb->x, thumb->y, + thumb->w, thumb->h, 0, 0, 255, + 150); + if (td.font_main) + { + int tw, th; + + gib_imlib_get_text_size(td.font_main, "X", NULL, &tw, &th, IMLIB_TEXT_TO_RIGHT); + gib_imlib_text_draw(w->im, td.font_main, NULL, thumb->x + ((thumb->w - tw) / 2), + thumb->y + ((thumb->h - th) / 2), "X", + IMLIB_TEXT_TO_RIGHT, 205, 205, 50, 255); + } + else + weprintf(DEFAULT_FONT_TITLE); + winwidget_render_image(w, 0, 1); + } + thumb->exists = 0; + } + D_RETURN_(4); +} + +void +feh_thumbnail_calculate_geometry(void) +{ + gib_list *l; + feh_file *file; + + int x = 0, y = 0; + int fw, fh; + + if (!opt.limit_w && !opt.limit_h) + { + if (td.im_bg) + { + if (opt.verbose) + fprintf(stdout, + PACKAGE " - No size restriction specified for index.\n" + " You did specify a background however, so the\n" + " index size has defaulted to the size of the image\n"); + opt.limit_w = td.bg_w; + opt.limit_h = td.bg_h; + } + else + { + if (opt.verbose) + fprintf(stdout, + PACKAGE " - No size restriction specified for index.\n" + " Using defaults (width limited to 640)\n"); + opt.limit_w = 640; + } + } + + + /* Here we need to whiz through the files, and look at the filenames and + info in the selected font, work out how much space we need, and + calculate the size of the image we will require */ + + if (opt.limit_w && opt.limit_h) + { + int rec_h = 0; + + td.w = opt.limit_w; + td.h = opt.limit_h; + + /* Work out if this is big enough, and give a warning if not */ + + /* Pretend we are limiting width by that specified, loop through, and + see it we fit in the height specified. If not, continue the loop, + and recommend the final value instead. Carry on and make the index + anyway. */ + + for (l = filelist; l; l = l->next) + { + file = FEH_FILE(l->data); + td.text_area_w = opt.thumb_w; + if (opt.index_show_name) + { + gib_imlib_get_text_size(td.font_main, file->name, NULL, &fw, &fh, + IMLIB_TEXT_TO_RIGHT); + if (fw > td.text_area_w) + td.text_area_w = fw; + } + if (opt.index_show_dim) + { + gib_imlib_get_text_size(td.font_main, + create_index_dimension_string(1000, 1000), + NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT); + if (fw > td.text_area_w) + td.text_area_w = fw; + } + if (opt.index_show_size) + { + gib_imlib_get_text_size(td.font_main, + create_index_size_string(file->filename), + NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT); + if (fw > td.text_area_w) + td.text_area_w = fw; + } + if (td.text_area_w > opt.thumb_w) + td.text_area_w += 5; + + if ((x > td.w - td.text_area_w)) + { + x = 0; + y += td.thumb_tot_h; + } + + x += td.text_area_w; + } + rec_h = y + td.thumb_tot_h; + + if (td.h < rec_h) + { + weprintf("The image size you specified (%d by %d) is not large\n" + "enough to hold all the thumnails you specified (%d). To fit all\n" + "the thumnails, either decrease their size, choose a smaller font,\n" + "or use a larger image (may I recommend %d by %d?)", + opt.limit_w, opt.limit_h, filelist_len, opt.limit_w, rec_h); + } + } + else if (opt.limit_h) + { + td.vertical = 1; + td.h = opt.limit_h; + /* calc w */ + for (l = filelist; l; l = l->next) + { + file = FEH_FILE(l->data); + td.text_area_w = opt.thumb_w; + /* Calc width of text */ + if (opt.index_show_name) + { + gib_imlib_get_text_size(td.font_main, file->name, NULL, &fw, &fh, + IMLIB_TEXT_TO_RIGHT); + if (fw > td.text_area_w) + td.text_area_w = fw; + } + if (opt.index_show_dim) + { + gib_imlib_get_text_size(td.font_main, + create_index_dimension_string(1000, 1000), + NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT); + if (fw > td.text_area_w) + td.text_area_w = fw; + } + if (opt.index_show_size) + { + gib_imlib_get_text_size(td.font_main, + create_index_size_string(file->filename), + NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT); + if (fw > td.text_area_w) + td.text_area_w = fw; + } + if (td.text_area_w > opt.thumb_w) + td.text_area_w += 5; + + if (td.text_area_w > td.max_column_w) + td.max_column_w = td.text_area_w; + + if ((y > td.h - td.thumb_tot_h)) + { + y = 0; + x += td.max_column_w; + td.max_column_w = 0; + } + + y += td.thumb_tot_h; + } + td.w = x + td.text_area_w; + td.max_column_w = 0; + } + else if (opt.limit_w) + { + td.w = opt.limit_w; + /* calc h */ + + for (l = filelist; l; l = l->next) + { + file = FEH_FILE(l->data); + td.text_area_w = opt.thumb_w; + if (opt.index_show_name) + { + gib_imlib_get_text_size(td.font_main, file->name, NULL, &fw, &fh, + IMLIB_TEXT_TO_RIGHT); + if (fw > td.text_area_w) + td.text_area_w = fw; + } + if (opt.index_show_dim) + { + gib_imlib_get_text_size(td.font_main, + create_index_dimension_string(1000, 1000), + NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT); + if (fw > td.text_area_w) + td.text_area_w = fw; + } + if (opt.index_show_size) + { + gib_imlib_get_text_size(td.font_main, + create_index_size_string(file->filename), + NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT); + if (fw > td.text_area_w) + td.text_area_w = fw; + } + + if (td.text_area_w > opt.thumb_w) + td.text_area_w += 5; + + if ((x > td.w - td.text_area_w)) + { + x = 0; + y += td.thumb_tot_h; + } + + x += td.text_area_w; + } + td.h = y + td.thumb_tot_h; + } +} + +int +feh_thumbnail_get_thumbnail(Imlib_Image *image, feh_file *file) +{ + int status = 0; + char *thumb_file = NULL, *uri = NULL; + + 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, uri); + + if (!status) + status = feh_thumbnail_generate(image, file, thumb_file, uri); + + printf("uri is %s, thumb_file is %s\n", uri, thumb_file); + free(uri); + free(thumb_file); + } + else + status = feh_load_image(image, file); + + return status; +} + +char* +feh_thumbnail_get_name(char *uri) +{ + char *home = NULL, *thumb_file = NULL, *md5_name = NULL; + + /* FIXME: make sure original file isn't under ~/.thumbnails */ + + + + md5_name = feh_thumbnail_get_name_md5(uri); + + home = getenv("HOME"); + if (home) + { + thumb_file = estrjoin("/", home, ".thumbnails/normal", md5_name, NULL); + } + + free(md5_name); + + return thumb_file; +} + +char* +feh_thumbnail_get_name_uri(char *name) +{ + char *cwd, *uri = NULL; + + /* FIXME: what happends with http, https, and ftp? MTime etc */ + if ((strncmp(name, "http://", 7) != 0) && + (strncmp(name, "https://", 8) != 0) && + (strncmp(name, "ftp://", 6) != 0) && + (strncmp(name, "file://", 7) != 0)) + { + + /* make sure it's an absoulte path */ + /* FIXME: add support for ~, need to investigate if it's expanded + somewhere else before adding (unecessary) code */ + if (name[0] != '/') { + cwd = getcwd(NULL, 0); + uri = estrjoin("/", "file:/", cwd, name, NULL); + free(cwd); + } else { + uri = estrjoin(NULL, "file://", name, NULL); + } + } + else + uri = estrdup(name); + + return uri; +} + +char* +feh_thumbnail_get_name_md5(char *uri) +{ + int i; + char *pos, *md5_name; + md5_state_t pms; + md5_byte_t digest[16]; + + /* generate the md5 sum */ + md5_init(&pms); + md5_append(&pms, uri, strlen(uri)); + md5_finish(&pms, digest); + + /* print the md5 as hex to a string */ + md5_name = emalloc(32 + 4 + 1 * sizeof(char)); /* md5 + .png + '\0' */ + for (i = 0, pos = md5_name; i < 16; i++, pos += 2) + { + sprintf(pos, "%02x", digest[i]); + } + sprintf(pos, ".png"); + + return md5_name; +} + +int +feh_thumbnail_generate(Imlib_Image *image, feh_file *file, char *thumb_file, char *uri) +{ + int w, h, thumb_w, thumb_h; + char *c_mtime; + Imlib_Image im_temp; + struct stat sb; + + if (feh_load_image(&im_temp, file) != 0) + { + w = gib_imlib_image_get_width(im_temp); + h = gib_imlib_image_get_height(im_temp); + thumb_w = 128; + thumb_h = 128; + + if ((w > 128) || (h > 128)) + { + double ratio = (double) w / h; + if (ratio > 1.0) + thumb_h = 128 / ratio; + else if (ratio != 1.0) + thumb_w = 128 * ratio; + } + + *image = gib_imlib_create_cropped_scaled_image(im_temp, 0, 0, w, h, + thumb_w, thumb_h, 1); + + if (!stat(file->filename, &sb)) + { + char c_mtime[256]; + sprintf(c_mtime, "%d", sb.st_mtime); + feh_png_write_png(*image, thumb_file, + "Thumb::URI", uri, "Thumb::MTime", c_mtime); + } + + gib_imlib_free_image_and_decache(im_temp); + + return(1); + } + + return(0); +} + +int +feh_thumbnail_get_generated(Imlib_Image *image, feh_file *file, char *thumb_file, char *uri) +{ + struct stat sb; + char *c_mtime; + 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"); + if (c_mtime != NULL) + mtime = (time_t) strtol(c_mtime, NULL,10); + gib_hash_free_and_data(hash); + } + + /* FIXME: should we bother about Thumb::URI? */ + if (mtime == sb.st_mtime) + { + feh_load_image_char(image, thumb_file); + + return(1); + } + } + + return(0); +} + +int +feh_thumbnail_setup_thumbnail_dir(void) +{ + int status = 0; + struct stat sb; + char *dir, *dir_thumbnails, *home; + + home = getenv("HOME"); + if (home != NULL) + { + dir = estrjoin("/", home, ".thumbnails/normal", NULL); + + if (!stat(dir, &sb)) { + if (S_ISDIR(sb.st_mode)) + status = 1; + else + weprintf("%s should be a directory", dir); + } else { + dir_thumbnails = estrjoin("/", home, ".thumbnails", NULL); + + if (stat(dir_thumbnails, &sb) != 0) + { + if (mkdir(dir_thumbnails, 0700) == -1) + weprintf("unable to create %s directory", dir_thumbnails); + } + + if (mkdir(dir, 0700) == -1) + weprintf("unable to create %s directory", dir); + else + status = 1; + } + } + + return status; +} diff --git a/src/thumbnail.h b/src/thumbnail.h new file mode 100644 index 0000000..bc986de --- /dev/null +++ b/src/thumbnail.h @@ -0,0 +1,86 @@ +/* thumbnail.h + +Copyright (C) 1999-2003 Tom Gilbert. + +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. + +*/ + +#ifndef THIMBNAIL_H +#define THIMBNAIL_H + + +#include "feh.h" +#include "filelist.h" +#include "winwidget.h" + +#define FEH_THUMB(l) ((feh_thumbnail *) l) + +typedef struct thumbnail +{ + int x; + int y; + int w; + int h; + feh_file *file; + unsigned char exists; + struct feh_thumbnail *next; +} +feh_thumbnail; + +typedef struct thumbmode_data +{ + /* FIXME: text_area_h not really needed, remove? */ + + Imlib_Image im_main; /* base image which all thumbnails are rendered on */ + Imlib_Image im_bg; /* background for the thumbnails */ + + Imlib_Font font_main; /* font used for file info */ + Imlib_Font font_title; /* font used for title */ + + int w, h, bg_w, bg_h; /* dimensions of the window and bg image */ + + int thumb_tot_h; /* total space needed for a thumbnail including description */ + int text_area_w, text_area_h; /* space needed for thumbnail description */ + + int max_column_w; /* FIXME: description */ + int vertical; /* FIXME: vertical in what way? */ + int cache_thumbnails; /* use cached thumbnails from ~/.thumbnails/normal */ +} +thumbmode_data; + +feh_thumbnail *feh_thumbnail_new(feh_file * fil, int x, int y, int w, int h); +feh_file *feh_thumbnail_get_file_from_coords(int x, int y); +feh_thumbnail *feh_thumbnail_get_thumbnail_from_coords(int x, int y); +feh_thumbnail *feh_thumbnail_get_from_file(feh_file * file); +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, char *uri); +char *feh_thumbnail_get_name(char *uri); +char *feh_thumbnail_get_name_uri(char *name); +char *feh_thumbnail_get_name_md5(char *uri); + +int feh_thumbnail_setup_thumbnail_dir(void); + +#endif diff --git a/src/timers.c b/src/timers.c new file mode 100644 index 0000000..5db92f0 --- /dev/null +++ b/src/timers.c @@ -0,0 +1,172 @@ +/* timers.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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 "options.h" +#include "timers.h" + +fehtimer first_timer = NULL; + +void +feh_handle_timer(void) +{ + fehtimer ft; + + D_ENTER(4); + if (!first_timer) + { + D(3,("No timer to handle, returning\n")); + D_RETURN_(4); + } + ft = first_timer; + first_timer = first_timer->next; + D(3,("Executing timer function now\n")); + (*(ft->func)) (ft->data); + D(3,("Freeing the timer\n")); + if (ft && ft->name) + free(ft->name); + if (ft) + free(ft); + D_RETURN_(4); +} + +double +feh_get_time(void) +{ + struct timeval timev; + + D_ENTER(4); + gettimeofday(&timev, NULL); + D_RETURN(4,(double) timev.tv_sec + (((double) timev.tv_usec) / 1000000)); +} + +void +feh_remove_timer(char *name) +{ + fehtimer ft, ptr, pptr; + + D_ENTER(4); + D(3,("removing %s\n", name)); + pptr = NULL; + ptr = first_timer; + while (ptr) + { + D(3,("Stepping through event list\n")); + ft = ptr; + if (!strcmp(ft->name, name)) + { + D(3,("Found it. Removing\n")); + if (pptr) + pptr->next = ft->next; + else + first_timer = ft->next; + if (ft->next) + ft->next->in += ft->in; + if (ft->name) + free(ft->name); + if (ft) + free(ft); + D_RETURN_(4); + } + pptr = ptr; + ptr = ptr->next; + } + D_RETURN_(4); +} + +void +feh_add_timer(void (*func) (void *data), void *data, double in, char *name) +{ + fehtimer ft, ptr, pptr; + double tally; + + D_ENTER(4); + D(3,("adding timer %s for %f seconds time\n", name, in)); + feh_remove_timer(name); + ft = malloc(sizeof(_fehtimer)); + ft->next = NULL; + ft->func = func; + ft->data = data; + ft->name = estrdup(name); + ft->just_added = 1; + ft->in = in; + D(3,("ft->in = %f\n", ft->in)); + tally = 0.0; + if (!first_timer) + { + D(3,("No first timer\n")); + first_timer = ft; + } + else + { + D(3,("There is a first timer\n")); + pptr = NULL; + ptr = first_timer; + tally = 0.0; + while (ptr) + { + tally += ptr->in; + if (tally > in) + { + tally -= ptr->in; + ft->next = ptr; + if (pptr) + pptr->next = ft; + else + first_timer = ft; + ft->in -= tally; + if (ft->next) + ft->next->in -= ft->in; + D_RETURN_(4); + } + pptr = ptr; + ptr = ptr->next; + } + if (pptr) + pptr->next = ft; + else + first_timer = ft; + ft->in -= tally; + } + D(3,("ft->in = %f\n", ft->in)); + D_RETURN_(4); +} + +void +feh_add_unique_timer(void (*func) (void *data), void *data, double in) +{ + static long i = 0; + char evname[20]; + + D_ENTER(4); + snprintf(evname, sizeof(evname), "T_%ld", i); + D(4,("adding timer with unique name %s\n", evname)); + feh_add_timer(func, data, in, evname); + i++; + /* Mega paranoia ;) */ + if (i > 1000000) + i = 0; + D_RETURN_(4); +} diff --git a/src/timers.h b/src/timers.h new file mode 100644 index 0000000..5cce160 --- /dev/null +++ b/src/timers.h @@ -0,0 +1,49 @@ +/* timers.h + +Copyright (C) 1999-2003 Tom Gilbert. + +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. + +*/ + +#ifndef TIMERS_H +#define TIMERS_H + +struct __fehtimer +{ + char *name; + void (*func) (void *data); + void *data; + double in; + char just_added; + fehtimer next; +}; + +void feh_handle_timer(void); +double feh_get_time(void); +void feh_remove_timer(char *name); +void feh_add_timer(void (*func) (void *data), void *data, double in, + + char *name); +void feh_add_unique_timer(void (*func) (void *data), void *data, double in); + +extern fehtimer first_timer; + +#endif diff --git a/src/transupp.c b/src/transupp.c new file mode 100644 index 0000000..7b6d7ee --- /dev/null +++ b/src/transupp.c @@ -0,0 +1,1233 @@ +/* + * transupp.c + * + * Copyright (C) 1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains image transformation routines and other utility code + * used by the jpegtran sample application. These are NOT part of the core + * JPEG library. But we keep these routines separate from jpegtran.c to + * ease the task of maintaining jpegtran-like programs that have other user + * interfaces. + */ + +/* Although this file really shouldn't have access to the library internals, + * it's helpful to let it call jround_up() and jcopy_block_row(). + */ +#define JPEG_INTERNALS + +#include +#include +#include +#include + +#include +#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) +#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) +#define SIZEOF(object) ((size_t) sizeof(object)) +#define JFREAD(file,buf,sizeofbuf) \ + ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) +#define JFWRITE(file,buf,sizeofbuf) \ + ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) + + +#include "jpeglib.h" +#include "transupp.h" /* My own external interface */ + + +#if TRANSFORMS_SUPPORTED + +/* + * Lossless image transformation routines. These routines work on DCT + * coefficient arrays and thus do not require any lossy decompression + * or recompression of the image. + * Thanks to Guido Vollbeding for the initial design and code of this feature. + * + * Horizontal flipping is done in-place, using a single top-to-bottom + * pass through the virtual source array. It will thus be much the + * fastest option for images larger than main memory. + * + * The other routines require a set of destination virtual arrays, so they + * need twice as much memory as jpegtran normally does. The destination + * arrays are always written in normal scan order (top to bottom) because + * the virtual array manager expects this. The source arrays will be scanned + * in the corresponding order, which means multiple passes through the source + * arrays for most of the transforms. That could result in much thrashing + * if the image is larger than main memory. + * + * Some notes about the operating environment of the individual transform + * routines: + * 1. Both the source and destination virtual arrays are allocated from the + * source JPEG object, and therefore should be manipulated by calling the + * source's memory manager. + * 2. The destination's component count should be used. It may be smaller + * than the source's when forcing to grayscale. + * 3. Likewise the destination's sampling factors should be used. When + * forcing to grayscale the destination's sampling factors will be all 1, + * and we may as well take that as the effective iMCU size. + * 4. When "trim" is in effect, the destination's dimensions will be the + * trimmed values but the source's will be untrimmed. + * 5. All the routines assume that the source and destination buffers are + * padded out to a full iMCU boundary. This is true, although for the + * source buffer it is an undocumented property of jdcoefct.c. + * Notes 2,3,4 boil down to this: generally we should use the destination's + * dimensions and ignore the source's. + */ + + +LOCAL(void) +do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays) +/* Horizontal flip; done in-place, so no separate dest array is required */ +{ + JDIMENSION MCU_cols, comp_width, blk_x, blk_y; + int ci, k, offset_y; + JBLOCKARRAY buffer; + JCOEFPTR ptr1, ptr2; + JCOEF temp1, temp2; + jpeg_component_info *compptr; + + /* Horizontal mirroring of DCT blocks is accomplished by swapping + * pairs of blocks in-place. Within a DCT block, we perform horizontal + * mirroring by changing the signs of odd-numbered columns. + * Partial iMCUs at the right edge are left untouched. + */ + MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + for (blk_y = 0; blk_y < compptr->height_in_blocks; + blk_y += compptr->v_samp_factor) { + buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) { + ptr1 = buffer[offset_y][blk_x]; + ptr2 = buffer[offset_y][comp_width - blk_x - 1]; + /* this unrolled loop doesn't need to know which row it's on... */ + for (k = 0; k < DCTSIZE2; k += 2) { + temp1 = *ptr1; /* swap even column */ + temp2 = *ptr2; + *ptr1++ = temp2; + *ptr2++ = temp1; + temp1 = *ptr1; /* swap odd column with sign change */ + temp2 = *ptr2; + *ptr1++ = -temp2; + *ptr2++ = -temp1; + } + } + } + } + } +} + + +LOCAL(void) +do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Vertical flip */ +{ + JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; + int ci, i, j, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JBLOCKROW src_row_ptr, dst_row_ptr; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* We output into a separate array because we can't touch different + * rows of the source virtual array simultaneously. Otherwise, this + * is a pretty straightforward analog of horizontal flip. + * Within a DCT block, vertical mirroring is done by changing the signs + * of odd-numbered rows. + * Partial iMCUs at the bottom edge are copied verbatim. + */ + MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_height = MCU_rows * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + if (dst_blk_y < comp_height) { + /* Row is within the mirrorable area. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } else { + /* Bottom-edge blocks will be copied verbatim. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + if (dst_blk_y < comp_height) { + /* Row is within the mirrorable area. */ + dst_row_ptr = dst_buffer[offset_y]; + src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x++) { + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[dst_blk_x]; + for (i = 0; i < DCTSIZE; i += 2) { + /* copy even row */ + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = *src_ptr++; + /* copy odd row with sign change */ + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = - *src_ptr++; + } + } + } else { + /* Just copy row verbatim. */ + jcopy_block_row(src_buffer[offset_y], dst_buffer[offset_y], + compptr->width_in_blocks); + } + } + } + } +} + + +LOCAL(void) +do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Transpose source into destination */ +{ + JDIMENSION dst_blk_x, dst_blk_y; + int ci, i, j, offset_x, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* Transposing pixels within a block just requires transposing the + * DCT coefficients. + * Partial iMCUs at the edges require no special treatment; we simply + * process all the available DCT blocks for every component. + */ + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x += compptr->h_samp_factor) { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, + (JDIMENSION) compptr->h_samp_factor, FALSE); + for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { + src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + for (i = 0; i < DCTSIZE; i++) + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + } + } + } + } + } +} + + +LOCAL(void) +do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* 90 degree rotation is equivalent to + * 1. Transposing the image; + * 2. Horizontal mirroring. + * These two steps are merged into a single processing routine. + */ +{ + JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; + int ci, i, j, offset_x, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* Because of the horizontal mirror step, we can't process partial iMCUs + * at the (output) right edge properly. They just get transposed and + * not mirrored. + */ + MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x += compptr->h_samp_factor) { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, + (JDIMENSION) compptr->h_samp_factor, FALSE); + for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { + src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; + if (dst_blk_x < comp_width) { + /* Block is within the mirrorable area. */ + dst_ptr = dst_buffer[offset_y] + [comp_width - dst_blk_x - offset_x - 1]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + i++; + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + } + } else { + /* Edge blocks are transposed but not mirrored. */ + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + for (i = 0; i < DCTSIZE; i++) + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + } + } + } + } + } + } +} + + +LOCAL(void) +do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* 270 degree rotation is equivalent to + * 1. Horizontal mirroring; + * 2. Transposing the image. + * These two steps are merged into a single processing routine. + */ +{ + JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; + int ci, i, j, offset_x, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* Because of the horizontal mirror step, we can't process partial iMCUs + * at the (output) bottom edge properly. They just get transposed and + * not mirrored. + */ + MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_height = MCU_rows * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x += compptr->h_samp_factor) { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, + (JDIMENSION) compptr->h_samp_factor, FALSE); + for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + if (dst_blk_y < comp_height) { + /* Block is within the mirrorable area. */ + src_ptr = src_buffer[offset_x] + [comp_height - dst_blk_y - offset_y - 1]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) { + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + j++; + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + } + } + } else { + /* Edge blocks are transposed but not mirrored. */ + src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; + for (i = 0; i < DCTSIZE; i++) + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + } + } + } + } + } + } +} + + +LOCAL(void) +do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* 180 degree rotation is equivalent to + * 1. Vertical mirroring; + * 2. Horizontal mirroring. + * These two steps are merged into a single processing routine. + */ +{ + JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; + int ci, i, j, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JBLOCKROW src_row_ptr, dst_row_ptr; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); + MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + comp_height = MCU_rows * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + if (dst_blk_y < comp_height) { + /* Row is within the vertically mirrorable area. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } else { + /* Bottom-edge rows are only mirrored horizontally. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + if (dst_blk_y < comp_height) { + /* Row is within the mirrorable area. */ + dst_row_ptr = dst_buffer[offset_y]; + src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; + /* Process the blocks that can be mirrored both ways. */ + for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) { + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[comp_width - dst_blk_x - 1]; + for (i = 0; i < DCTSIZE; i += 2) { + /* For even row, negate every odd column. */ + for (j = 0; j < DCTSIZE; j += 2) { + *dst_ptr++ = *src_ptr++; + *dst_ptr++ = - *src_ptr++; + } + /* For odd row, negate every even column. */ + for (j = 0; j < DCTSIZE; j += 2) { + *dst_ptr++ = - *src_ptr++; + *dst_ptr++ = *src_ptr++; + } + } + } + /* Any remaining right-edge blocks are only mirrored vertically. */ + for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[dst_blk_x]; + for (i = 0; i < DCTSIZE; i += 2) { + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = *src_ptr++; + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = - *src_ptr++; + } + } + } else { + /* Remaining rows are just mirrored horizontally. */ + dst_row_ptr = dst_buffer[offset_y]; + src_row_ptr = src_buffer[offset_y]; + /* Process the blocks that can be mirrored. */ + for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) { + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[comp_width - dst_blk_x - 1]; + for (i = 0; i < DCTSIZE2; i += 2) { + *dst_ptr++ = *src_ptr++; + *dst_ptr++ = - *src_ptr++; + } + } + /* Any remaining right-edge blocks are only copied. */ + for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[dst_blk_x]; + for (i = 0; i < DCTSIZE2; i++) + *dst_ptr++ = *src_ptr++; + } + } + } + } + } +} + + +LOCAL(void) +do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Transverse transpose is equivalent to + * 1. 180 degree rotation; + * 2. Transposition; + * or + * 1. Horizontal mirroring; + * 2. Transposition; + * 3. Horizontal mirroring. + * These steps are merged into a single processing routine. + */ +{ + JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; + int ci, i, j, offset_x, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); + MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + comp_height = MCU_rows * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x += compptr->h_samp_factor) { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, + (JDIMENSION) compptr->h_samp_factor, FALSE); + for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { + if (dst_blk_y < comp_height) { + src_ptr = src_buffer[offset_x] + [comp_height - dst_blk_y - offset_y - 1]; + if (dst_blk_x < comp_width) { + /* Block is within the mirrorable area. */ + dst_ptr = dst_buffer[offset_y] + [comp_width - dst_blk_x - offset_x - 1]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) { + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + j++; + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + } + i++; + for (j = 0; j < DCTSIZE; j++) { + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + j++; + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + } + } + } else { + /* Right-edge blocks are mirrored in y only */ + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) { + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + j++; + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + } + } + } + } else { + src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; + if (dst_blk_x < comp_width) { + /* Bottom-edge blocks are mirrored in x only */ + dst_ptr = dst_buffer[offset_y] + [comp_width - dst_blk_x - offset_x - 1]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + i++; + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + } + } else { + /* At lower right corner, just transpose, no mirroring */ + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + for (i = 0; i < DCTSIZE; i++) + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + } + } + } + } + } + } + } +} + + +/* Request any required workspace. + * + * We allocate the workspace virtual arrays from the source decompression + * object, so that all the arrays (both the original data and the workspace) + * will be taken into account while making memory management decisions. + * Hence, this routine must be called after jpeg_read_header (which reads + * the image dimensions) and before jpeg_read_coefficients (which realizes + * the source's virtual arrays). + */ + +GLOBAL(void) +jtransform_request_workspace (j_decompress_ptr srcinfo, + jpeg_transform_info *info) +{ + jvirt_barray_ptr *coef_arrays = NULL; + jpeg_component_info *compptr; + int ci; + + if (info->force_grayscale && + srcinfo->jpeg_color_space == JCS_YCbCr && + srcinfo->num_components == 3) { + /* We'll only process the first component */ + info->num_components = 1; + } else { + /* Process all the components */ + info->num_components = srcinfo->num_components; + } + + switch (info->transform) { + case JXFORM_NONE: + case JXFORM_FLIP_H: + /* Don't need a workspace array */ + break; + case JXFORM_FLIP_V: + case JXFORM_ROT_180: + /* Need workspace arrays having same dimensions as source image. + * Note that we allocate arrays padded out to the next iMCU boundary, + * so that transform routines need not worry about missing edge blocks. + */ + coef_arrays = (jvirt_barray_ptr *) + (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, + SIZEOF(jvirt_barray_ptr) * info->num_components); + for (ci = 0; ci < info->num_components; ci++) { + compptr = srcinfo->comp_info + ci; + coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) + ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->width_in_blocks, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + } + break; + case JXFORM_TRANSPOSE: + case JXFORM_TRANSVERSE: + case JXFORM_ROT_90: + case JXFORM_ROT_270: + /* Need workspace arrays having transposed dimensions. + * Note that we allocate arrays padded out to the next iMCU boundary, + * so that transform routines need not worry about missing edge blocks. + */ + coef_arrays = (jvirt_barray_ptr *) + (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, + SIZEOF(jvirt_barray_ptr) * info->num_components); + for (ci = 0; ci < info->num_components; ci++) { + compptr = srcinfo->comp_info + ci; + coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) + ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor), + (JDIMENSION) jround_up((long) compptr->width_in_blocks, + (long) compptr->h_samp_factor), + (JDIMENSION) compptr->h_samp_factor); + } + break; + } + info->workspace_coef_arrays = coef_arrays; +} + + +/* Transpose destination image parameters */ + +LOCAL(void) +transpose_critical_parameters (j_compress_ptr dstinfo) +{ + int tblno, i, j, ci, itemp; + jpeg_component_info *compptr; + JQUANT_TBL *qtblptr; + JDIMENSION dtemp; + UINT16 qtemp; + + /* Transpose basic image dimensions */ + dtemp = dstinfo->image_width; + dstinfo->image_width = dstinfo->image_height; + dstinfo->image_height = dtemp; + + /* Transpose sampling factors */ + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + itemp = compptr->h_samp_factor; + compptr->h_samp_factor = compptr->v_samp_factor; + compptr->v_samp_factor = itemp; + } + + /* Transpose quantization tables */ + for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { + qtblptr = dstinfo->quant_tbl_ptrs[tblno]; + if (qtblptr != NULL) { + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < i; j++) { + qtemp = qtblptr->quantval[i*DCTSIZE+j]; + qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i]; + qtblptr->quantval[j*DCTSIZE+i] = qtemp; + } + } + } + } +} + + +/* Trim off any partial iMCUs on the indicated destination edge */ + +LOCAL(void) +trim_right_edge (j_compress_ptr dstinfo) +{ + int ci, max_h_samp_factor; + JDIMENSION MCU_cols; + + /* We have to compute max_h_samp_factor ourselves, + * because it hasn't been set yet in the destination + * (and we don't want to use the source's value). + */ + max_h_samp_factor = 1; + for (ci = 0; ci < dstinfo->num_components; ci++) { + int h_samp_factor = dstinfo->comp_info[ci].h_samp_factor; + max_h_samp_factor = MAX(max_h_samp_factor, h_samp_factor); + } + MCU_cols = dstinfo->image_width / (max_h_samp_factor * DCTSIZE); + if (MCU_cols > 0) /* can't trim to 0 pixels */ + dstinfo->image_width = MCU_cols * (max_h_samp_factor * DCTSIZE); +} + +LOCAL(void) +trim_bottom_edge (j_compress_ptr dstinfo) +{ + int ci, max_v_samp_factor; + JDIMENSION MCU_rows; + + /* We have to compute max_v_samp_factor ourselves, + * because it hasn't been set yet in the destination + * (and we don't want to use the source's value). + */ + max_v_samp_factor = 1; + for (ci = 0; ci < dstinfo->num_components; ci++) { + int v_samp_factor = dstinfo->comp_info[ci].v_samp_factor; + max_v_samp_factor = MAX(max_v_samp_factor, v_samp_factor); + } + MCU_rows = dstinfo->image_height / (max_v_samp_factor * DCTSIZE); + if (MCU_rows > 0) /* can't trim to 0 pixels */ + dstinfo->image_height = MCU_rows * (max_v_samp_factor * DCTSIZE); +} + +LOCAL(void) +set_exif_orientation (JOCTET FAR * data, unsigned int length, + unsigned char new_orient) +{ + boolean is_motorola; /* Flag for byte order */ + unsigned int number_of_tags, tagnum; + unsigned int firstoffset, offset; + + if (length < 12) return; /* Length of an IFD entry */ + + /* Discover byte order */ + if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49) + is_motorola = FALSE; + else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D) + is_motorola = TRUE; + else + return; + + /* Check Tag Mark */ + if (is_motorola) { + if (GETJOCTET(data[2]) != 0) return; + if (GETJOCTET(data[3]) != 0x2A) return; + } else { + if (GETJOCTET(data[3]) != 0) return; + if (GETJOCTET(data[2]) != 0x2A) return; + } + + /* Get first IFD offset (offset to IFD0) */ + if (is_motorola) { + if (GETJOCTET(data[4]) != 0) return; + if (GETJOCTET(data[5]) != 0) return; + firstoffset = GETJOCTET(data[6]); + firstoffset <<= 8; + firstoffset += GETJOCTET(data[7]); + } else { + if (GETJOCTET(data[7]) != 0) return; + if (GETJOCTET(data[6]) != 0) return; + firstoffset = GETJOCTET(data[5]); + firstoffset <<= 8; + firstoffset += GETJOCTET(data[4]); + } + if (firstoffset > length - 2) return; /* check end of data segment */ + + /* Get the number of directory entries contained in this IFD */ + if (is_motorola) { + number_of_tags = GETJOCTET(data[firstoffset]); + number_of_tags <<= 8; + number_of_tags += GETJOCTET(data[firstoffset+1]); + } else { + number_of_tags = GETJOCTET(data[firstoffset+1]); + number_of_tags <<= 8; + number_of_tags += GETJOCTET(data[firstoffset]); + } + if (number_of_tags == 0) return; + firstoffset += 2; + + /* Search for Orientation offset Tag in IFD0 */ + for (;;) { + if (firstoffset > length - 12) return; /* check end of data segment */ + /* Get Tag number */ + if (is_motorola) { + tagnum = GETJOCTET(data[firstoffset]); + tagnum <<= 8; + tagnum += GETJOCTET(data[firstoffset+1]); + } else { + tagnum = GETJOCTET(data[firstoffset+1]); + tagnum <<= 8; + tagnum += GETJOCTET(data[firstoffset]); + } + if (tagnum == 0x0112) break; /* found Orientation Tag */ + if (--number_of_tags == 0) return; + firstoffset += 12; + } + + if (is_motorola) { + data[firstoffset+2] = 0; /* Format = unsigned short (2 octets) */ + data[firstoffset+3] = 3; + data[firstoffset+4] = 0; /* Number Of Components = 1 */ + data[firstoffset+5] = 0; + data[firstoffset+6] = 0; + data[firstoffset+7] = 1; + data[firstoffset+8] = 0; + data[firstoffset+9] = (unsigned char) new_orient; + data[firstoffset+10] = 0; + data[firstoffset+11] = 0; + } else { + data[firstoffset+2] = 3; /* Format = unsigned short (2 octets) */ + data[firstoffset+3] = 0; + data[firstoffset+4] = 1; /* Number Of Components = 1 */ + data[firstoffset+5] = 0; + data[firstoffset+6] = 0; + data[firstoffset+7] = 0; + data[firstoffset+8] = (unsigned char) new_orient; + data[firstoffset+9] = 0; + data[firstoffset+10] = 0; + data[firstoffset+11] = 0; + } +} + +/* Adjust Exif image parameters. + * + * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible. + */ + +LOCAL(void) +adjust_exif_parameters (JOCTET FAR * data, unsigned int length, + JDIMENSION new_width, JDIMENSION new_height) +{ + boolean is_motorola; /* Flag for byte order */ + unsigned int number_of_tags, tagnum; + unsigned int firstoffset, offset; + unsigned int new_orient; + JDIMENSION new_value; + + if (length < 12) return; /* Length of an IFD entry */ + + /* Discover byte order */ + if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49) + is_motorola = FALSE; + else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D) + is_motorola = TRUE; + else + return; + + /* Check Tag Mark */ + if (is_motorola) { + if (GETJOCTET(data[2]) != 0) return; + if (GETJOCTET(data[3]) != 0x2A) return; + } else { + if (GETJOCTET(data[3]) != 0) return; + if (GETJOCTET(data[2]) != 0x2A) return; + } + + /* Get first IFD offset (offset to IFD0) */ + if (is_motorola) { + if (GETJOCTET(data[4]) != 0) return; + if (GETJOCTET(data[5]) != 0) return; + firstoffset = GETJOCTET(data[6]); + firstoffset <<= 8; + firstoffset += GETJOCTET(data[7]); + } else { + if (GETJOCTET(data[7]) != 0) return; + if (GETJOCTET(data[6]) != 0) return; + firstoffset = GETJOCTET(data[5]); + firstoffset <<= 8; + firstoffset += GETJOCTET(data[4]); + } + if (firstoffset > length - 2) return; /* check end of data segment */ + + /* Get the number of directory entries contained in this IFD */ + if (is_motorola) { + number_of_tags = GETJOCTET(data[firstoffset]); + number_of_tags <<= 8; + number_of_tags += GETJOCTET(data[firstoffset+1]); + } else { + number_of_tags = GETJOCTET(data[firstoffset+1]); + number_of_tags <<= 8; + number_of_tags += GETJOCTET(data[firstoffset]); + } + if (number_of_tags == 0) return; + firstoffset += 2; + + /* Search for ExifSubIFD offset Tag in IFD0 */ + for (;;) { + if (firstoffset > length - 12) return; /* check end of data segment */ + /* Get Tag number */ + if (is_motorola) { + tagnum = GETJOCTET(data[firstoffset]); + tagnum <<= 8; + tagnum += GETJOCTET(data[firstoffset+1]); + } else { + tagnum = GETJOCTET(data[firstoffset+1]); + tagnum <<= 8; + tagnum += GETJOCTET(data[firstoffset]); + } + if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */ + if (--number_of_tags == 0) return; + firstoffset += 12; + } + + /* Get the ExifSubIFD offset */ + if (is_motorola) { + if (GETJOCTET(data[firstoffset+8]) != 0) return; + if (GETJOCTET(data[firstoffset+9]) != 0) return; + offset = GETJOCTET(data[firstoffset+10]); + offset <<= 8; + offset += GETJOCTET(data[firstoffset+11]); + } else { + if (GETJOCTET(data[firstoffset+11]) != 0) return; + if (GETJOCTET(data[firstoffset+10]) != 0) return; + offset = GETJOCTET(data[firstoffset+9]); + offset <<= 8; + offset += GETJOCTET(data[firstoffset+8]); + } + if (offset > length - 2) return; /* check end of data segment */ + + /* Get the number of directory entries contained in this SubIFD */ + if (is_motorola) { + number_of_tags = GETJOCTET(data[offset]); + number_of_tags <<= 8; + number_of_tags += GETJOCTET(data[offset+1]); + } else { + number_of_tags = GETJOCTET(data[offset+1]); + number_of_tags <<= 8; + number_of_tags += GETJOCTET(data[offset]); + } + if (number_of_tags < 2) return; + offset += 2; + + /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */ + do { + if (offset > length - 12) return; /* check end of data segment */ + /* Get Tag number */ + if (is_motorola) { + tagnum = GETJOCTET(data[offset]); + tagnum <<= 8; + tagnum += GETJOCTET(data[offset+1]); + } else { + tagnum = GETJOCTET(data[offset+1]); + tagnum <<= 8; + tagnum += GETJOCTET(data[offset]); + } + if (tagnum == 0xA002 || tagnum == 0xA003) { + if (tagnum == 0xA002) { + new_value = new_width; /* ExifImageWidth Tag */ + } else { + new_value = new_height; /* ExifImageHeight Tag */ + } + if (is_motorola) { + data[offset+2] = 0; /* Format = unsigned long (4 octets) */ + data[offset+3] = 4; + data[offset+4] = 0; /* Number Of Components = 1 */ + data[offset+5] = 0; + data[offset+6] = 0; + data[offset+7] = 1; + data[offset+8] = 0; + data[offset+9] = 0; + data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF); + data[offset+11] = (JOCTET)(new_value & 0xFF); + } else { + data[offset+2] = 4; /* Format = unsigned long (4 octets) */ + data[offset+3] = 0; + data[offset+4] = 1; /* Number Of Components = 1 */ + data[offset+5] = 0; + data[offset+6] = 0; + data[offset+7] = 0; + data[offset+8] = (JOCTET)(new_value & 0xFF); + data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF); + data[offset+10] = 0; + data[offset+11] = 0; + } + } + offset += 12; + } while (--number_of_tags); +} + + +/* Adjust output image parameters as needed. + * + * This must be called after jpeg_copy_critical_parameters() + * and before jpeg_write_coefficients(). + * + * The return value is the set of virtual coefficient arrays to be written + * (either the ones allocated by jtransform_request_workspace, or the + * original source data arrays). The caller will need to pass this value + * to jpeg_write_coefficients(). + */ + +GLOBAL(jvirt_barray_ptr *) +jtransform_adjust_parameters (j_decompress_ptr srcinfo, + j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info) +{ + jpeg_saved_marker_ptr marker; + /* If force-to-grayscale is requested, adjust destination parameters */ + if (info->force_grayscale) { + /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed + * properly. Among other things, the target h_samp_factor & v_samp_factor + * will get set to 1, which typically won't match the source. + * In fact we do this even if the source is already grayscale; that + * provides an easy way of coercing a grayscale JPEG with funny sampling + * factors to the customary 1,1. (Some decoders fail on other factors.) + */ + if ((dstinfo->jpeg_color_space == JCS_YCbCr && + dstinfo->num_components == 3) || + (dstinfo->jpeg_color_space == JCS_GRAYSCALE && + dstinfo->num_components == 1)) { + /* We have to preserve the source's quantization table number. */ + int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no; + jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE); + dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no; + } else { + /* Sorry, can't do it */ + ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL); + } + } + + /* Correct the destination's image dimensions etc if necessary */ + switch (info->transform) { + case JXFORM_NONE: + /* Nothing to do */ + break; + case JXFORM_FLIP_H: + if (info->trim) + trim_right_edge(dstinfo); + break; + case JXFORM_FLIP_V: + if (info->trim) + trim_bottom_edge(dstinfo); + break; + case JXFORM_TRANSPOSE: + transpose_critical_parameters(dstinfo); + /* transpose does NOT have to trim anything */ + break; + case JXFORM_TRANSVERSE: + transpose_critical_parameters(dstinfo); + if (info->trim) { + trim_right_edge(dstinfo); + trim_bottom_edge(dstinfo); + } + break; + case JXFORM_ROT_90: + transpose_critical_parameters(dstinfo); + if (info->trim) + trim_right_edge(dstinfo); + break; + case JXFORM_ROT_180: + if (info->trim) { + trim_right_edge(dstinfo); + trim_bottom_edge(dstinfo); + } + break; + case JXFORM_ROT_270: + transpose_critical_parameters(dstinfo); + if (info->trim) + trim_bottom_edge(dstinfo); + break; + } + + for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) { + if (marker->marker != JPEG_APP0+1) + continue; + /* Adjust Exif properties */ + if (marker->marker == JPEG_APP0+1 && + marker->data_length >= 6 && + GETJOCTET(marker->data[0]) == 0x45 && + GETJOCTET(marker->data[1]) == 0x78 && + GETJOCTET(marker->data[2]) == 0x69 && + GETJOCTET(marker->data[3]) == 0x66 && + GETJOCTET(marker->data[4]) == 0 && + GETJOCTET(marker->data[5]) == 0) { + /* Suppress output of JFIF marker */ + dstinfo->write_JFIF_header = FALSE; + /* Adjust Exif image parameters */ + if (dstinfo->image_width != srcinfo->image_width || + dstinfo->image_height != srcinfo->image_height) + /* Align data segment to start of TIFF structure for parsing */ + adjust_exif_parameters(marker->data + 6, + marker->data_length - 6, + dstinfo->image_width, dstinfo->image_height); + /* I'm honestly not sure what the right thing to do is here.. The + * existing orientation tag may be incorrect, so making a change based + * on the previous value seems like the wrong thing to do. For now, I'm + * going to assume that the user is always "fixing" the orientation, + * i.e. putting the image the "right way up". In this case, we want to + * set the orientation to "top left". + */ + set_exif_orientation(marker->data + 6, + marker->data_length - 6, + 1); + } + } + + /* Return the appropriate output data set */ + if (info->workspace_coef_arrays != NULL) + return info->workspace_coef_arrays; + return src_coef_arrays; +} + + +/* Execute the actual transformation, if any. + * + * This must be called *after* jpeg_write_coefficients, because it depends + * on jpeg_write_coefficients to have computed subsidiary values such as + * the per-component width and height fields in the destination object. + * + * Note that some transformations will modify the source data arrays! + */ + +GLOBAL(void) +jtransform_execute_transformation (j_decompress_ptr srcinfo, + j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info) +{ + jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays; + + switch (info->transform) { + case JXFORM_NONE: + break; + case JXFORM_FLIP_H: + do_flip_h(srcinfo, dstinfo, src_coef_arrays); + break; + case JXFORM_FLIP_V: + do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_TRANSPOSE: + do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_TRANSVERSE: + do_transverse(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_ROT_90: + do_rot_90(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_ROT_180: + do_rot_180(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_ROT_270: + do_rot_270(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; + } +} + +#endif /* TRANSFORMS_SUPPORTED */ + + +/* Setup decompression object to save desired markers in memory. + * This must be called before jpeg_read_header() to have the desired effect. + */ + +GLOBAL(void) +jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option) +{ +#ifdef SAVE_MARKERS_SUPPORTED + int m; + + /* Save comments except under NONE option */ + if (option != JCOPYOPT_NONE) { + jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF); + } + /* Save all types of APPn markers iff ALL option */ + if (option == JCOPYOPT_ALL) { + for (m = 0; m < 16; m++) + jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF); + } +#endif /* SAVE_MARKERS_SUPPORTED */ +} + +/* Copy markers saved in the given source object to the destination object. + * This should be called just after jpeg_start_compress() or + * jpeg_write_coefficients(). + * Note that those routines will have written the SOI, and also the + * JFIF APP0 or Adobe APP14 markers if selected. + */ + +GLOBAL(void) +jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JCOPY_OPTION option) +{ + jpeg_saved_marker_ptr marker; + + /* In the current implementation, we don't actually need to examine the + * option flag here; we just copy everything that got saved. + * But to avoid confusion, we do not output JFIF and Adobe APP14 markers + * if the encoder library already wrote one. + */ + for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) { + if (dstinfo->write_JFIF_header && + marker->marker == JPEG_APP0 && + marker->data_length >= 5 && + GETJOCTET(marker->data[0]) == 0x4A && + GETJOCTET(marker->data[1]) == 0x46 && + GETJOCTET(marker->data[2]) == 0x49 && + GETJOCTET(marker->data[3]) == 0x46 && + GETJOCTET(marker->data[4]) == 0) + continue; /* reject duplicate JFIF */ + if (dstinfo->write_Adobe_marker && + marker->marker == JPEG_APP0+14 && + marker->data_length >= 5 && + GETJOCTET(marker->data[0]) == 0x41 && + GETJOCTET(marker->data[1]) == 0x64 && + GETJOCTET(marker->data[2]) == 0x6F && + GETJOCTET(marker->data[3]) == 0x62 && + GETJOCTET(marker->data[4]) == 0x65) + continue; /* reject duplicate Adobe */ +#ifdef NEED_FAR_POINTERS + /* We could use jpeg_write_marker if the data weren't FAR... */ + { + unsigned int i; + jpeg_write_m_header(dstinfo, marker->marker, marker->data_length); + for (i = 0; i < marker->data_length; i++) + jpeg_write_m_byte(dstinfo, marker->data[i]); + } +#else + jpeg_write_marker(dstinfo, marker->marker, + marker->data, marker->data_length); +#endif + } +} diff --git a/src/transupp.h b/src/transupp.h new file mode 100644 index 0000000..5c2d32a --- /dev/null +++ b/src/transupp.h @@ -0,0 +1,135 @@ +/* + * transupp.h + * + * Copyright (C) 1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for image transformation routines and + * other utility code used by the jpegtran sample application. These are + * NOT part of the core JPEG library. But we keep these routines separate + * from jpegtran.c to ease the task of maintaining jpegtran-like programs + * that have other user interfaces. + * + * NOTE: all the routines declared here have very specific requirements + * about when they are to be executed during the reading and writing of the + * source and destination files. See the comments in transupp.c, or see + * jpegtran.c for an example of correct usage. + */ + +/* If you happen not to want the image transform support, disable it here */ +#ifndef TRANSFORMS_SUPPORTED +#define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */ +#endif + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jtransform_request_workspace jTrRequest +#define jtransform_adjust_parameters jTrAdjust +#define jtransform_execute_transformation jTrExec +#define jcopy_markers_setup jCMrkSetup +#define jcopy_markers_execute jCMrkExec +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* + * Codes for supported types of image transformations. + */ + +typedef enum { + JXFORM_NONE, /* no transformation */ + JXFORM_FLIP_H, /* horizontal flip */ + JXFORM_FLIP_V, /* vertical flip */ + JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */ + JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */ + JXFORM_ROT_90, /* 90-degree clockwise rotation */ + JXFORM_ROT_180, /* 180-degree rotation */ + JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */ +} JXFORM_CODE; + +/* + * Although rotating and flipping data expressed as DCT coefficients is not + * hard, there is an asymmetry in the JPEG format specification for images + * whose dimensions aren't multiples of the iMCU size. The right and bottom + * image edges are padded out to the next iMCU boundary with junk data; but + * no padding is possible at the top and left edges. If we were to flip + * the whole image including the pad data, then pad garbage would become + * visible at the top and/or left, and real pixels would disappear into the + * pad margins --- perhaps permanently, since encoders & decoders may not + * bother to preserve DCT blocks that appear to be completely outside the + * nominal image area. So, we have to exclude any partial iMCUs from the + * basic transformation. + * + * Transpose is the only transformation that can handle partial iMCUs at the + * right and bottom edges completely cleanly. flip_h can flip partial iMCUs + * at the bottom, but leaves any partial iMCUs at the right edge untouched. + * Similarly flip_v leaves any partial iMCUs at the bottom edge untouched. + * The other transforms are defined as combinations of these basic transforms + * and process edge blocks in a way that preserves the equivalence. + * + * The "trim" option causes untransformable partial iMCUs to be dropped; + * this is not strictly lossless, but it usually gives the best-looking + * result for odd-size images. Note that when this option is active, + * the expected mathematical equivalences between the transforms may not hold. + * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim + * followed by -rot 180 -trim trims both edges.) + * + * We also offer a "force to grayscale" option, which simply discards the + * chrominance channels of a YCbCr image. This is lossless in the sense that + * the luminance channel is preserved exactly. It's not the same kind of + * thing as the rotate/flip transformations, but it's convenient to handle it + * as part of this package, mainly because the transformation routines have to + * be aware of the option to know how many components to work on. + */ + +typedef struct { + /* Options: set by caller */ + JXFORM_CODE transform; /* image transform operator */ + boolean trim; /* if TRUE, trim partial MCUs as needed */ + boolean force_grayscale; /* if TRUE, convert color image to grayscale */ + + /* Internal workspace: caller should not touch these */ + int num_components; /* # of components in workspace */ + jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */ +} jpeg_transform_info; + + +#if TRANSFORMS_SUPPORTED + +/* Request any required workspace */ +EXTERN(void) jtransform_request_workspace + JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info)); +/* Adjust output image parameters */ +EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters + JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info)); +/* Execute the actual transformation, if any */ +EXTERN(void) jtransform_execute_transformation + JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info)); + +#endif /* TRANSFORMS_SUPPORTED */ + + +/* + * Support for copying optional markers from source to destination file. + */ + +typedef enum { + JCOPYOPT_NONE, /* copy no optional markers */ + JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */ + JCOPYOPT_ALL /* copy all optional markers */ +} JCOPY_OPTION; + +#define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */ + +/* Setup decompression object to save desired markers in memory */ +EXTERN(void) jcopy_markers_setup + JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option)); +/* Copy markers saved in the given source object to the destination object */ +EXTERN(void) jcopy_markers_execute + JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JCOPY_OPTION option)); diff --git a/src/ttfonts/Makefile.am b/src/ttfonts/Makefile.am new file mode 100644 index 0000000..7df955a --- /dev/null +++ b/src/ttfonts/Makefile.am @@ -0,0 +1,13 @@ +## Process this file with automake to produce Makefile.in + +AUTOMAKE_OPTIONS = 1.4 foreign + +# A list of all the files in the current directory which can be regenerated +MAINTAINERCLEANFILES = Makefile.in + +testfonts_DATA = \ +menu.style black.style yudit.ttf + +testfontsdir=$(prefix)/share/feh/fonts + +EXTRA_DIST = $(testfonts_DATA) diff --git a/src/ttfonts/Makefile.in b/src/ttfonts/Makefile.in new file mode 100644 index 0000000..ae93e14 --- /dev/null +++ b/src/ttfonts/Makefile.in @@ -0,0 +1,216 @@ +# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CC = @CC@ +GIBLIB_CFLAGS = @GIBLIB_CFLAGS@ +GIBLIB_LIBS = @GIBLIB_LIBS@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_CONFIG = @GTK_CONFIG@ +GTK_LIBS = @GTK_LIBS@ +HAVE_LIB = @HAVE_LIB@ +HAVE_XINERAMA = @HAVE_XINERAMA@ +IMLIB_CFLAGS = @IMLIB_CFLAGS@ +IMLIB_LIBS = @IMLIB_LIBS@ +LIB = @LIB@ +LTLIB = @LTLIB@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +PACKAGE = @PACKAGE@ +UP = @UP@ +VERSION = @VERSION@ +XINERAMA_LIBS = @XINERAMA_LIBS@ + +AUTOMAKE_OPTIONS = 1.4 foreign + +# A list of all the files in the current directory which can be regenerated +MAINTAINERCLEANFILES = Makefile.in + +testfonts_DATA = menu.style black.style yudit.ttf + + +testfontsdir = $(prefix)/share/feh/fonts + +EXTRA_DIST = $(testfonts_DATA) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../../src/config.h +CONFIG_CLEAN_FILES = +DATA = $(testfonts_DATA) + +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +all: all-redirect +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps src/ttfonts/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +install-testfontsDATA: $(testfonts_DATA) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(testfontsdir) + @list='$(testfonts_DATA)'; for p in $$list; do \ + if test -f $(srcdir)/$$p; then \ + echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(testfontsdir)/$$p"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(testfontsdir)/$$p; \ + else if test -f $$p; then \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(testfontsdir)/$$p"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(testfontsdir)/$$p; \ + fi; fi; \ + done + +uninstall-testfontsDATA: + @$(NORMAL_UNINSTALL) + list='$(testfonts_DATA)'; for p in $$list; do \ + rm -f $(DESTDIR)$(testfontsdir)/$$p; \ + done +tags: TAGS +TAGS: + + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = src/ttfonts + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: install-testfontsDATA +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-testfontsDATA +uninstall: uninstall-am +all-am: Makefile $(DATA) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(testfontsdir) + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +mostlyclean-am: mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-generic clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: uninstall-testfontsDATA install-testfontsDATA tags distdir \ +info-am info dvi-am dvi check check-am installcheck-am installcheck \ +install-exec-am install-exec install-data-am install-data install-am \ +install uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/ttfonts/black.style b/src/ttfonts/black.style new file mode 100644 index 0000000..d2a86a9 --- /dev/null +++ b/src/ttfonts/black.style @@ -0,0 +1,4 @@ +#Style +#NAME Menu +255 255 255 64 2 2 +255 255 255 255 0 0 diff --git a/src/ttfonts/menu.style b/src/ttfonts/menu.style new file mode 100644 index 0000000..8557360 --- /dev/null +++ b/src/ttfonts/menu.style @@ -0,0 +1,4 @@ +#Style +#NAME Menu +0 0 0 64 2 2 +0 0 0 0 0 0 diff --git a/src/ttfonts/yudit.ttf b/src/ttfonts/yudit.ttf new file mode 100644 index 0000000..8099e63 Binary files /dev/null and b/src/ttfonts/yudit.ttf differ diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..7183b66 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,248 @@ +/* utils.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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 "debug.h" +#include "options.h" + +static char *feh_user_name = NULL; +static char *feh_tmp_dir = NULL; + +/* eprintf: print error message and exit */ +void +eprintf(char *fmt, ...) +{ + va_list args; + + fflush(stdout); + fprintf(stderr, "%s ERROR: ", PACKAGE); + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + + if (fmt[0] != '\0' && fmt[strlen(fmt) - 1] == ':') + fprintf(stderr, " %s", strerror(errno)); + fprintf(stderr, "\n"); + exit(2); +} + +/* weprintf: print warning message and continue */ +void +weprintf(char *fmt, ...) +{ + va_list args; + + fflush(stdout); + fprintf(stderr, "%s WARNING: ", PACKAGE); + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + + if (fmt[0] != '\0' && fmt[strlen(fmt) - 1] == ':') + fprintf(stderr, " %s", strerror(errno)); + fprintf(stderr, "\n"); +} + +/* estrdup: duplicate a string, report if error */ +char * +_estrdup(char *s) +{ + char *t; + + if (!s) + return NULL; + + t = (char *) malloc(strlen(s) + 1); + if (t == NULL) + eprintf("estrdup(\"%.20s\") failed:", s); + strcpy(t, s); + return t; +} + +/* emalloc: malloc and report if error */ +void * +_emalloc(size_t n) +{ + void *p; + + p = malloc(n); + if (p == NULL) + eprintf("malloc of %u bytes failed:", n); + return p; +} + +/* erealloc: realloc and report if error */ +void * +_erealloc(void *ptr, size_t n) +{ + void *p; + + p = realloc(ptr, n); + if (p == NULL) + eprintf("realloc of %p by %u bytes failed:", ptr, n); + return p; +} + +char * +estrjoin(const char *separator, ...) +{ + char *string, *s; + va_list args; + int len; + int separator_len; + + if (separator == NULL) + separator = ""; + + separator_len = strlen(separator); + va_start(args, separator); + s = va_arg(args, char *); + + if (s) + { + len = strlen(s); + s = va_arg(args, char *); + + while (s) + { + len += separator_len + strlen(s); + s = va_arg(args, char *); + } + va_end(args); + string = malloc(sizeof(char) * (len + 1)); + + *string = 0; + va_start(args, separator); + s = va_arg(args, char *); + + strcat(string, s); + s = va_arg(args, char *); + + while (s) + { + strcat(string, separator); + strcat(string, s); + s = va_arg(args, char *); + } + } + else + string = estrdup(""); + va_end(args); + + return string; +} + +char * +stroflen(char c, int l) +{ + static char buf[1024]; + int i = 0; + + buf[0] = '\0'; + while (l--) + buf[i++] = c; + buf[i] = '\0'; + return buf; +} + +/* free the result please */ +char *feh_unique_filename(char *path, char *basename) +{ + char *tmpname; + char num[10]; + char cppid[10]; + static long int i = 1; + struct stat st; + pid_t ppid; + + D_ENTER(4); + /* Massive paranoia ;) */ + if (i > 999998) + i = 1; + + ppid = getpid(); + snprintf(cppid, sizeof(cppid), "%06ld", (long)ppid); + + /* make sure file doesn't exist */ + do + { + snprintf(num, sizeof(num), "%06ld", i++); + tmpname = + estrjoin("", path, "feh_", cppid, "_", num, "_", + basename, NULL); + } + while (stat(tmpname, &st) == 0); + D_RETURN(4, tmpname); +} + +/* reads file into a string, but limits o 4095 chars and ensures a \0 */ +char *ereadfile(char *path) { + char buffer[4096]; + FILE *fp; + int count; + + fp = fopen(path, "r"); + if (!fp) + return NULL; + + count = fread(buffer, sizeof(char), sizeof(buffer) - 1, fp); + if (buffer[count - 1] == '\n') + buffer[count - 1] = '\0'; + else + buffer[count] = '\0'; + + fclose(fp); + + return estrdup(buffer); +} + +char *feh_get_tmp_dir(void) { + char *tmp; + if (feh_tmp_dir) + return feh_tmp_dir; + tmp = getenv("TMPDIR"); + if (!tmp) + tmp = getenv("TMP"); + if (!tmp) + tmp = getenv("TEMP"); + if (!tmp) + tmp = "/tmp"; + feh_tmp_dir = estrdup(tmp); + return feh_tmp_dir; +} + +char *feh_get_user_name(void) { + struct passwd *pw = NULL; + + if (feh_user_name) + return feh_user_name; + setpwent (); + pw = getpwuid (getuid ()); + endpwent (); + feh_user_name = estrdup(pw->pw_name); + return feh_user_name; +} diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..221319c --- /dev/null +++ b/src/utils.h @@ -0,0 +1,90 @@ +/* utils.h + +Copyright (C) 1999-2003 Tom Gilbert. + +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. + +*/ + +#ifndef UTILS_H +#define UTILS_H + +#ifndef __GNUC__ +# define __attribute__(x) +#endif + +void eprintf(char *fmt, ...) __attribute__ ((noreturn)); +void weprintf(char *fmt, ...); +char *_estrdup(char *s); +void *_emalloc(size_t n); +void *_erealloc(void *ptr, size_t n); +char *estrjoin(const char *separator, ...); +char *stroflen(char, int); +char *feh_unique_filename(char *path, char *basename); +char *ereadfile(char *path); +char *feh_get_tmp_dir(void); +char *feh_get_user_name(void); + +#define ESTRAPPEND(a,b) \ + {\ + char *____newstr;\ + if (!(a)) {\ + a = estrdup(b);\ + } else {\ + ____newstr = emalloc(strlen(a) + strlen(b) + 1);\ + strcpy(____newstr, (a));\ + strcat(____newstr, (b));\ + free(a);\ + (a) = ____newstr;\ + }\ + } + +#define ESTRAPPEND_CHAR(a,b) \ + {\ + char *____newstr;\ + int ____len;\ + if (!(a)) {\ + (a) = emalloc(2);\ + (a)[0] = (b);\ + (a)[1] = '\0';\ + } else {\ + ____len = strlen((a));\ + ____newstr = emalloc(____len + 2);\ + strcpy(____newstr, (a));\ + ____newstr[____len] = (b);\ + ____newstr[____len+1] = '\0';\ + free(a);\ + (a) = ____newstr;\ + }\ + } + +#define ESTRTRUNC(string,chars) \ + {\ + int ____len;\ + if (string) {\ + ____len = strlen(string);\ + if (____len >= (chars)) {\ + (string)[strlen(string) - chars] = '\0';\ + }\ + }\ + } + + +#endif diff --git a/src/winwidget.c b/src/winwidget.c new file mode 100644 index 0000000..e3b9d35 --- /dev/null +++ b/src/winwidget.c @@ -0,0 +1,1058 @@ +/* winwidget.c + +Copyright (C) 1999-2003 Tom Gilbert. + +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 "filelist.h" +#include "winwidget.h" +#include "options.h" + +static void winwidget_unregister(winwidget win); +static void winwidget_register(winwidget win); +static winwidget winwidget_allocate(void); + +static char bm_no_data[] = { 0,0,0,0, 0,0,0,0 }; +int window_num = 0; /* For window list */ +winwidget *windows = NULL; /* List of windows to loop though */ + +static winwidget +winwidget_allocate(void) +{ + winwidget ret = NULL; + + D_ENTER(4); + ret = emalloc(sizeof(_winwidget)); + + ret->win = 0; + ret->w = 0; + ret->h = 0; + ret->full_screen = 0; + ret->im_w = 0; + ret->im_h = 0; + ret->im_angle = 0; + ret->bg_pmap = 0; + ret->bg_pmap_cache = 0; + ret->im = NULL; + ret->name = NULL; + ret->file = NULL; + ret->type = WIN_TYPE_UNSET; + ret->visible = 0; + ret->caption_entry = 0; + + /* Zoom stuff */ + ret->mode = MODE_NORMAL; + + ret->gc = None; + + /* New stuff */ + ret->im_x = 0; + ret->im_y = 0; + ret->zoom = 1.0; + + ret->click_offset_x = 0; + ret->click_offset_y = 0; + ret->im_click_offset_x = 0; + ret->im_click_offset_y = 0; + ret->has_rotated = 0; + + D_RETURN(4, ret); +} + +winwidget +winwidget_create_from_image(Imlib_Image im, + char *name, + char type) +{ + winwidget ret = NULL; + + D_ENTER(4); + + if (im == NULL) + D_RETURN(4, NULL); + + ret = winwidget_allocate(); + ret->type = type; + + ret->im = im; + ret->w = ret->im_w = gib_imlib_image_get_width(ret->im); + ret->h = ret->im_h = gib_imlib_image_get_height(ret->im); + + if (name) + ret->name = estrdup(name); + else + ret->name = estrdup(PACKAGE); + + if (opt.full_screen) + ret->full_screen = True; + winwidget_create_window(ret, ret->w, ret->h); + winwidget_render_image(ret, 1, 1); + + D_RETURN(4, ret); +} + +winwidget +winwidget_create_from_file(gib_list * list, + char *name, + char type) +{ + winwidget ret = NULL; + feh_file *file = FEH_FILE(list->data); + + D_ENTER(4); + + if (!file || !file->filename) + D_RETURN(4, NULL); + + ret = winwidget_allocate(); + ret->file = list; + ret->type = type; + if (name) + ret->name = estrdup(name); + else + ret->name = estrdup(file->filename); + + if (winwidget_loadimage(ret, file) == 0) { + winwidget_destroy(ret); + D_RETURN(4, NULL); + } + + if (!ret->win) { + ret->w = ret->im_w = gib_imlib_image_get_width(ret->im); + ret->h = ret->im_h = gib_imlib_image_get_height(ret->im); + D(3, + ("image is %dx%d pixels, format %s\n", ret->w, ret->h, + gib_imlib_image_format(ret->im))); + if (opt.full_screen) + ret->full_screen = True; + winwidget_create_window(ret, ret->w, ret->h); + winwidget_render_image(ret, 1, 1); + } + + D_RETURN(4, ret); +} + +void +winwidget_create_window(winwidget ret, + int w, + int h) +{ + XSetWindowAttributes attr; + XClassHint *xch; + MWMHints mwmhints; + Atom prop = None; + int x = 0; + int y = 0; + + D_ENTER(4); + + if (ret->full_screen) { + w = scr->width; + h = scr->height; + +#ifdef HAVE_LIBXINERAMA + if (opt.xinerama && xinerama_screens) { + w = xinerama_screens[xinerama_screen].width; + h = xinerama_screens[xinerama_screen].height; + } +#endif /* HAVE_LIBXINERAMA */ + } else if (opt.geom_flags) { + if (opt.geom_flags & WidthValue) { + w = opt.geom_w; + } + if (opt.geom_flags & HeightValue) { + h = opt.geom_h; + } + if (opt.geom_flags & XValue) { + if (opt.geom_flags & XNegative) { + x = scr->width - opt.geom_x; + } else { + x = opt.geom_x; + } + } + if (opt.geom_flags & YValue) { + if (opt.geom_flags & YNegative) { + y = scr->height - opt.geom_y; + } else { + y = opt.geom_y; + } + } + } else if (opt.screen_clip) { + if (w > scr->width) + w = scr->width; + if (h > scr->height) + h = scr->height; + +#ifdef HAVE_LIBXINERAMA + if (opt.xinerama && xinerama_screens) { + if (w > xinerama_screens[xinerama_screen].width) + w = xinerama_screens[xinerama_screen].width; + if (h > xinerama_screens[xinerama_screen].height) + h = xinerama_screens[xinerama_screen].height; + } +#endif /* HAVE_LIBXINERAMA */ + } + + ret->x = x; + ret->y = y; + ret->w = w; + ret->h = h; + ret->visible = False; + + attr.backing_store = NotUseful; + attr.override_redirect = False; + attr.colormap = cm; + attr.border_pixel = 0; + attr.background_pixel = 0; + attr.save_under = False; + attr.event_mask = + StructureNotifyMask | ButtonPressMask | ButtonReleaseMask | + PointerMotionMask | EnterWindowMask | LeaveWindowMask | KeyPressMask | + KeyReleaseMask | ButtonMotionMask | ExposureMask | FocusChangeMask | + PropertyChangeMask | VisibilityChangeMask; + + if (opt.borderless || ret->full_screen) { + prop = XInternAtom(disp, "_MOTIF_WM_HINTS", True); + if (prop == None) { + weprintf("Window Manager does not support MWM hints. " + "To get a borderless window I have to bypass your wm."); + attr.override_redirect = True; + mwmhints.flags = 0; + } else { + mwmhints.flags = MWM_HINTS_DECORATIONS; + mwmhints.decorations = 0; + } + } else + mwmhints.flags = 0; + + ret->win = + XCreateWindow(disp, DefaultRootWindow(disp), x, y, w, h, 0, depth, + InputOutput, vis, + CWOverrideRedirect | CWSaveUnder | CWBackingStore | + CWColormap | CWBackPixel | CWBorderPixel | CWEventMask, + &attr); + + if (mwmhints.flags) { + XChangeProperty(disp, ret->win, prop, prop, 32, PropModeReplace, + (unsigned char *) &mwmhints, PROP_MWM_HINTS_ELEMENTS); + } + + XSetWMProtocols(disp, ret->win, &wmDeleteWindow, 1); + winwidget_update_title(ret); + xch = XAllocClassHint(); + xch->res_name = "feh"; + xch->res_class = "feh"; + XSetClassHint(disp, ret->win, xch); + XFree(xch); + + /* Size hints */ + if (ret->full_screen || opt.geom_flags) { + XSizeHints xsz; + + xsz.flags = USPosition; + xsz.x = x; + xsz.y = y; + XSetWMNormalHints(disp, ret->win, &xsz); + XMoveWindow(disp, ret->win, x, y); + } + if (ret->full_screen && opt.hide_pointer) { + Cursor no_ptr; + XColor black, dummy; + Pixmap bm_no; + bm_no = XCreateBitmapFromData(disp, ret->win, bm_no_data, 8, 8); + XAllocNamedColor(disp, DefaultColormapOfScreen(DefaultScreenOfDisplay(disp)), "black", &black, &dummy); + + no_ptr = XCreatePixmapCursor(disp, bm_no, bm_no, &black, &black, 0, 0); + XDefineCursor(disp, ret->win, no_ptr); + } + + /* set the icon name property */ + XSetIconName(disp, ret->win, "feh"); + /* set the command hint */ + XSetCommand(disp, ret->win, cmdargv, cmdargc); + + winwidget_register(ret); + D_RETURN_(4); +} + +void +winwidget_update_title(winwidget ret) +{ + char *name; + + D_ENTER(4); + D(4, ("winwid->name = %s\n", ret->name)); + name = ret->name ? ret->name : "feh"; + XStoreName(disp, ret->win, name); + XSetIconName(disp, ret->win, name); + /* XFlush(disp); */ + D_RETURN_(4); +} + +void +winwidget_setup_pixmaps(winwidget winwid) +{ + D_ENTER(4); + + if (winwid->full_screen) { + if (!(winwid->bg_pmap)) { + if (winwid->gc == None) { + XGCValues gcval; + + gcval.foreground = BlackPixel(disp, DefaultScreen(disp)); + winwid->gc = XCreateGC(disp, winwid->win, GCForeground, &gcval); + } + winwid->bg_pmap = + XCreatePixmap(disp, winwid->win, scr->width, scr->height, depth); + } + XFillRectangle(disp, winwid->bg_pmap, winwid->gc, 0, 0, scr->width, + scr->height); + } else { + if (!winwid->bg_pmap || winwid->had_resize) { + D(4, ("recreating background pixmap (%dx%d)\n", winwid->w, winwid->h)); + if (winwid->bg_pmap) + XFreePixmap(disp, winwid->bg_pmap); + + if (winwid->w == 0) + winwid->w = 1; + if (winwid->h == 0) + winwid->h = 1; + winwid->bg_pmap = + XCreatePixmap(disp, winwid->win, winwid->w, winwid->h, depth); + winwid->had_resize = 0; + } + } + D_RETURN_(4); +} + +void +winwidget_render_image(winwidget winwid, + int resize, + int alias) +{ + int sx, sy, sw, sh, dx, dy, dw, dh; + int calc_w, calc_h; + + D_ENTER(4); + + if (!winwid->full_screen && resize) { + winwidget_resize(winwid, winwid->im_w, winwid->im_h); + winwidget_reset_image(winwid); + } + + /* bounds checks for panning */ + if (winwid->im_x > winwid->w) + winwid->im_x = winwid->w; + if (winwid->im_y > winwid->h) + winwid->im_y = winwid->h; + + winwidget_setup_pixmaps(winwid); + + if (!winwid->full_screen + && ((gib_imlib_image_has_alpha(winwid->im)) || (opt.geom_flags) + || (winwid->im_x || winwid->im_y) || (winwid->zoom != 1.0) + || (winwid->w > winwid->im_w || winwid->h > winwid->im_h) + || (winwid->has_rotated))) + feh_draw_checks(winwid); + + if (!winwid->full_screen && opt.scale_down + && ((winwid->w < winwid->im_w) || (winwid->h < winwid->im_h))) { + D(2, ("scaling down image\n")); + + feh_calc_needed_zoom(&(winwid->zoom), winwid->im_w, winwid->im_h, + winwid->w, winwid->h); + winwidget_resize(winwid, winwid->im_w * winwid->zoom, + winwid->im_h * winwid->zoom); + } + + if (resize && (winwid->full_screen || opt.geom_flags)) { + int smaller; /* Is the image smaller than screen? */ + int max_w, max_h; + + if (winwid->full_screen) { + max_w = scr->width; + max_h = scr->height; +#ifdef HAVE_LIBXINERAMA + if (opt.xinerama && xinerama_screens) { + max_w = xinerama_screens[xinerama_screen].width; + max_h = xinerama_screens[xinerama_screen].height; + } +#endif /* HAVE_LIBXINERAMA */ + } else { + if (opt.geom_flags & WidthValue) { + max_w = opt.geom_w; + } + if (opt.geom_flags & HeightValue) { + max_h = opt.geom_h; + } + } + + D(4, ("Calculating for fullscreen/fixed geom render\n")); + smaller = ((winwid->im_w < max_w) && (winwid->im_h < max_h)); + + if (!smaller || opt.auto_zoom) { + double ratio = 0.0; + + /* Image is larger than the screen (so wants shrinking), or it's + smaller but wants expanding to fill it */ + ratio = + feh_calc_needed_zoom(&(winwid->zoom), winwid->im_w, winwid->im_h, + max_w, max_h); + + /* contributed by Jens Laas + * What it does: + * zooms images by a fixed amount but never larger than the screen. + * + * Why: + * This is nice if you got a collection of images where some + * are small and can stand a small zoom. Large images are unaffected. + * + * When does it work, and how? + * You have to be in fullscreen mode _and_ have auto-zoom turned on. + * "feh -FZ --zoom 130 imagefile" will do the trick. + * -zoom percent - the new switch. + * 100 = orignal size, + * 130 is 30% larger. + */ + if (opt.default_zoom) { + double old_zoom = winwid->zoom; + + winwid->zoom = 0.01 * opt.default_zoom; + if ((winwid->im_h * winwid->zoom) > max_h) + winwid->zoom = old_zoom; + if ((winwid->im_w * winwid->zoom) > max_w) + winwid->zoom = old_zoom; + + winwid->im_x = ((int) (max_w - (winwid->im_w * winwid->zoom))) >> 1; + winwid->im_y = ((int) (max_h - (winwid->im_h * winwid->zoom))) >> 1; + } else { + if (ratio > 1.0) { + /* height is the factor */ + winwid->im_x = 0; + winwid->im_y = ((int) (max_h - (winwid->im_h * winwid->zoom))) >> 1; + } else { + /* width is the factor */ + winwid->im_x = ((int) (max_w - (winwid->im_w * winwid->zoom))) >> 1; + winwid->im_y = 0; + } + } + } else { + /* my modification to jens hack, allow --zoom without auto-zoom mode */ + if(opt.default_zoom) { + winwid->zoom = 0.01 * opt.default_zoom; + } else { + winwid->zoom = 1.0; + } + /* Just center the image in the window */ + winwid->im_x = (int)(max_w - (winwid->im_w * winwid->zoom)) >> 1; + winwid->im_y = (int)(max_h - (winwid->im_h * winwid->zoom)) >> 1; + } + } + + /* Now we ensure only to render the area we're looking at */ + dx = winwid->im_x; + dy = winwid->im_y; + if (dx < 0) + dx = 0; + if (dy < 0) + dy = 0; + + if (winwid->im_x < 0) + sx = 0 - (winwid->im_x / winwid->zoom); + else + sx = 0; + + if (winwid->im_y < 0) + sy = 0 - (winwid->im_y / winwid->zoom); + else + sy = 0; + + calc_w = winwid->im_w * winwid->zoom; + calc_h = winwid->im_h * winwid->zoom; + dw = (winwid->w - winwid->im_x); + dh = (winwid->h - winwid->im_y); + if (calc_w < dw) + dw = calc_w; + if (calc_h < dh) + dh = calc_h; + if (dw > winwid->w) + dw = winwid->w; + if (dh > winwid->h) + dh = winwid->h; + + sw = dw / winwid->zoom; + sh = dh / winwid->zoom; + + D(5, + ("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)); + + D(5, ("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); + 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); + if (opt.caption_path) { + /* cache bg pixmap. during caption entry, multiple redraws are done + * because the caption overlay changes - the image doesn't though, so re- + * rendering that is a waste of time */ + if (winwid->caption_entry) { + GC gc; + if (winwid->bg_pmap_cache) + XFreePixmap(disp, winwid->bg_pmap_cache); + winwid->bg_pmap_cache = XCreatePixmap(disp, + winwid->win, + winwid->w, + winwid->h, + depth); + gc = XCreateGC(disp, winwid->win, 0, NULL); + XCopyArea(disp, winwid->bg_pmap, winwid->bg_pmap_cache, gc, 0, 0, winwid->w, winwid->h, 0, 0); + XFreeGC(disp, gc); + } + feh_draw_caption(winwid); + } + + if (opt.draw_filename) + feh_draw_filename(winwid); + if (opt.draw_actions) + feh_draw_actions(winwid); + if ((opt.mode == MODE_ZOOM) && !alias) + feh_draw_zoom(winwid); + XSetWindowBackgroundPixmap(disp, winwid->win, winwid->bg_pmap); + XClearWindow(disp, winwid->win); + D_RETURN_(4); +} + +void winwidget_render_image_cached(winwidget winwid) { + static GC gc = None; + + if (gc == None) { + gc = XCreateGC(disp, winwid->win, 0, NULL); + } + XCopyArea(disp, winwid->bg_pmap_cache, winwid->bg_pmap, gc, 0, 0, winwid->w, winwid->h, 0, 0); + + if (opt.caption_path) + feh_draw_caption(winwid); + if (opt.draw_filename) + feh_draw_filename(winwid); + if (opt.draw_actions) + feh_draw_actions(winwid); + XSetWindowBackgroundPixmap(disp, winwid->win, winwid->bg_pmap); + XClearWindow(disp, winwid->win); +} + +double +feh_calc_needed_zoom(double *zoom, + int orig_w, + int orig_h, + int dest_w, + int dest_h) +{ + double ratio = 0.0; + + D_ENTER(4); + + ratio = ((double) orig_w / orig_h) / ((double) dest_w / dest_h); + + if (ratio > 1.0) + *zoom = ((double) dest_w / orig_w); + else + *zoom = ((double) dest_h / orig_h); + + D_RETURN(4, ratio); +} + +Pixmap +feh_create_checks(void) +{ + static Pixmap checks_pmap = None; + Imlib_Image checks = NULL; + + D_ENTER(4); + if (checks_pmap == None) { + int onoff, x, y; + + checks = imlib_create_image(16, 16); + + if (!checks) + eprintf + ("Unable to create a teeny weeny imlib image. I detect problems"); + + for (y = 0; y < 16; y += 8) { + onoff = (y / 8) & 0x1; + for (x = 0; x < 16; x += 8) { + if (onoff) + gib_imlib_image_fill_rectangle(checks, x, y, 8, 8, 144, 144, 144, + 255); + else + gib_imlib_image_fill_rectangle(checks, x, y, 8, 8, 100, 100, 100, + 255); + onoff++; + if (onoff == 2) + onoff = 0; + } + } + checks_pmap = XCreatePixmap(disp, root, 16, 16, depth); + gib_imlib_render_image_on_drawable(checks_pmap, checks, 0, 0, 1, 0, 0); + gib_imlib_free_image_and_decache(checks); + } + D_RETURN(4, checks_pmap); +} + +void +winwidget_clear_background(winwidget w) +{ + D_ENTER(4); + XSetWindowBackgroundPixmap(disp, w->win, feh_create_checks()); + /* XClearWindow(disp, w->win); */ + D_RETURN_(4); +} + +void +feh_draw_checks(winwidget win) +{ + static GC gc = None; + XGCValues gcval; + + D_ENTER(4); + if (gc == None) { + gcval.tile = feh_create_checks(); + gcval.fill_style = FillTiled; + gc = XCreateGC(disp, win->win, GCTile | GCFillStyle, &gcval); + } + XFillRectangle(disp, win->bg_pmap, gc, 0, 0, win->w, win->h); + D_RETURN_(4); +} + +void +winwidget_destroy_xwin(winwidget winwid) +{ + D_ENTER(4); + if (winwid->win) { + winwidget_unregister(winwid); + XDestroyWindow(disp, winwid->win); + } + if (winwid->bg_pmap) { + XFreePixmap(disp, winwid->bg_pmap); + winwid->bg_pmap = None; + } + D_RETURN_(4); +} + +void +winwidget_destroy(winwidget winwid) +{ + D_ENTER(4); + winwidget_destroy_xwin(winwid); + if (winwid->name) + free(winwid->name); + if ((winwid->type == WIN_TYPE_ABOUT) && winwid->file) { + feh_file_free(FEH_FILE(winwid->file->data)); + free(winwid->file); + } + if (winwid->gc) + XFreeGC(disp, winwid->gc); + if (winwid->im) + gib_imlib_free_image_and_decache(winwid->im); + free(winwid); + D_RETURN_(4); +} + +void +winwidget_destroy_all(void) +{ + int i; + + D_ENTER(4); + /* Have to DESCEND the list here, 'cos of the way _unregister works */ + for (i = window_num - 1; i >= 0; i--) + winwidget_destroy(windows[i]); + D_RETURN_(4); +} + +void +winwidget_rerender_all(int resize, + int alias) +{ + int i; + + D_ENTER(4); + /* 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); + D_RETURN_(4); +} + +winwidget +winwidget_get_first_window_of_type(unsigned int type) +{ + int i; + + D_ENTER(4); + for (i = 0; i < window_num; i++) + if (windows[i]->type == type) + D_RETURN(4, windows[i]); + D_RETURN(4, NULL); +} + +int +winwidget_loadimage(winwidget winwid, + feh_file * file) +{ + D_ENTER(4); + D(4, ("filename %s\n", file->filename)); + D_RETURN(4, feh_load_image(&(winwid->im), file)); +} + +void +winwidget_show(winwidget winwid) +{ + XEvent ev; + + D_ENTER(4); + + /* feh_debug_print_winwid(winwid); */ + if (!winwid->visible) { + XMapWindow(disp, winwid->win); + if (opt.full_screen) + XMoveWindow(disp, winwid->win, 0, 0); + /* wait for the window to map */ + D(4, ("Waiting for window to map\n")); + XMaskEvent(disp, StructureNotifyMask, &ev); + D(4, ("Window mapped\n")); + winwid->visible = 1; + } + D_RETURN_(4); +} + +int +winwidget_count(void) +{ + D_ENTER(4); + D_RETURN(4, window_num); +} + +void +winwidget_move(winwidget winwid, + int x, + int y) +{ + D_ENTER(4); + 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); + XFlush(disp); + } else { + D(4, ("No move actually needed\n")); + } + D_RETURN_(4); +} + +void +winwidget_resize(winwidget winwid, + int w, + int h) +{ + D_ENTER(4); + if (opt.geom_flags) { + winwid->had_resize = 1; + return; + } + if (winwid && ((winwid->w != w) || (winwid->h != h))) { + D(4, ("Really doing a resize\n")); + /* winwidget_clear_background(winwid); */ + if (opt.screen_clip) { + winwid->w = (w > scr->width) ? scr->width : w; + winwid->h = (h > scr->height) ? scr->height : h; + } + XResizeWindow(disp, winwid->win, winwid->w, winwid->h); + winwid->had_resize = 1; + XFlush(disp); + +#ifdef HAVE_LIBXINERAMA + if (opt.xinerama && xinerama_screens) { + int i; + + for (i = 0; i < num_xinerama_screens; i++) { + xinerama_screen = 0; + if (XY_IN_RECT(winwid->x, winwid->y, + xinerama_screens[i].x_org, xinerama_screens[i].y_org, + xinerama_screens[i].width, xinerama_screens[i].height)) { + xinerama_screen = i; + break; + } + + } + } +#endif /* HAVE_LIBXINERAMA */ + + } else { + D(4, ("No resize actually needed\n")); + } + + D_RETURN_(4); +} + +void +winwidget_hide(winwidget winwid) +{ + D_ENTER(4); + XUnmapWindow(disp, winwid->win); + winwid->visible = 0; + D_RETURN_(4); +} + +static void +winwidget_register(winwidget win) +{ + D_ENTER(4); + D(5, ("window %p\n", win)); + window_num++; + if (windows) + windows = erealloc(windows, window_num * sizeof(winwidget)); + else + windows = emalloc(window_num * sizeof(winwidget)); + windows[window_num - 1] = win; + + XSaveContext(disp, win->win, xid_context, (XPointer) win); + D_RETURN_(4); +} + +static void +winwidget_unregister(winwidget win) +{ + int i, j; + + D_ENTER(4); + for (i = 0; i < window_num; i++) { + if (windows[i] == win) { + for (j = i; j < window_num - 1; j++) + windows[j] = windows[j + 1]; + window_num--; + if (window_num > 0) + windows = erealloc(windows, window_num * sizeof(winwidget)); + else { + free(windows); + windows = NULL; + } + } + } + XDeleteContext(disp, win->win, xid_context); + D_RETURN_(4); +} + +winwidget +winwidget_get_from_window(Window win) +{ + winwidget ret = NULL; + + D_ENTER(4); + if (XFindContext(disp, win, xid_context, (XPointer *) & ret) != XCNOENT) + D_RETURN(4, ret); + D_RETURN(4, NULL); +} + +void +winwidget_rename(winwidget winwid, + char *newname) +{ + D_ENTER(4); + if (winwid->name) + free(winwid->name); + winwid->name = estrdup(newname); + winwidget_update_title(winwid); + D_RETURN_(4); +} + +void +winwidget_free_image(winwidget w) +{ + D_ENTER(4); + if (w->im) + gib_imlib_free_image_and_decache(w->im); + w->im = NULL; + w->im_w = 0; + w->im_h = 0; + D_RETURN_(4); +} + +void +feh_debug_print_winwid(winwidget w) +{ + printf("winwid_debug:\n" "winwid = %p\n" "win = %ld\n" "w = %d\n" "h = %d\n" + "im_w = %d\n" "im_h = %d\n" "im_angle = %f\n" "type = %d\n" + "had_resize = %d\n" "im = %p\n" "GC = %p\n" "pixmap = %ld\n" + "name = %s\n" "file = %p\n" "mode = %d\n" "im_x = %d\n" "im_y = %d\n" + "zoom = %f\n" "click_offset_x = %d\n" "click_offset_y = %d\n" + "im_click_offset_x = %d\n" "im_click_offset_y = %d\n" + "has_rotated = %d\n", w, w->win, w->w, w->h, w->im_w, w->im_h, + w->im_angle, w->type, w->had_resize, w->im, w->gc, w->bg_pmap, + w->name, w->file, w->mode, w->im_x, w->im_y, w->zoom, + w->click_offset_x, w->click_offset_y, w->im_click_offset_x, + w->im_click_offset_y, w->has_rotated); +} + +void +winwidget_reset_image(winwidget winwid) +{ + D_ENTER(4); + winwid->zoom = 1.0; + winwid->im_x = 0; + winwid->im_y = 0; + winwid->im_angle = 0.0; + winwid->has_rotated = 0; + D_RETURN_(4); +} + +void +winwidget_sanitise_offsets(winwidget winwid) +{ + int far_left, far_top; + int min_x, max_x, max_y, min_y; + + D_ENTER(4); + + far_left = winwid->w - (winwid->im_w * winwid->zoom); + far_top = winwid->h - (winwid->im_h * winwid->zoom); + + if ((winwid->im_w * winwid->zoom) > winwid->w) { + min_x = far_left; + max_x = 0; + } else { + min_x = 0; + max_x = far_left; + } + if ((winwid->im_h * winwid->zoom) > winwid->h) { + min_y = far_top; + max_y = 0; + } else { + min_y = 0; + max_y = far_top; + } + if (winwid->im_x > max_x) + winwid->im_x = max_x; + if (winwid->im_x < min_x) + winwid->im_x = min_x; + if (winwid->im_y > max_y) + winwid->im_y = max_y; + if (winwid->im_y < min_y) + winwid->im_y = min_y; + + D_RETURN_(4); +} + + +void +winwidget_size_to_image(winwidget winwid) +{ + D_ENTER(4); + 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); + D_RETURN_(4); +} + +int winwidget_get_width(winwidget winwid) { + int rect[4]; + D_ENTER(4); + winwidget_get_geometry(winwid, rect); + D_RETURN(4, rect[2]); +} + +int winwidget_get_height(winwidget winwid) { + int rect[4]; + D_ENTER(4); + winwidget_get_geometry(winwid, rect); + D_RETURN(4, rect[3]); +} + +void winwidget_get_geometry(winwidget winwid, int *rect) { + int bw, bp; + D_ENTER(4); + if (!rect) + return; + + XGetGeometry(disp, winwid->win, &root, + &(rect[0]), &(rect[1]), &(rect[2]), &(rect[3]), &bw, &bp); + + /* update the window geometry (in case it's inaccurate) */ + winwid->x = rect[0]; + winwid->y = rect[1]; + winwid->w = rect[2]; + winwid->h = rect[3]; + D_RETURN_(4); +} + +void winwidget_show_menu(winwidget winwid) { + int x, y, b; + unsigned int c; + Window r; + + XQueryPointer(disp, winwid->win, &r, &r, &x, &y, &b, &b, &c); + if (winwid->type == WIN_TYPE_ABOUT) + { + if (!menu_about_win) + feh_menu_init_about_win(); + feh_menu_show_at_xy(menu_about_win, winwid, x, y); + } + else if (winwid->type == WIN_TYPE_SINGLE) + { + if (!menu_single_win) + feh_menu_init_single_win(); + feh_menu_show_at_xy(menu_single_win, winwid, x, y); + } + else if (winwid->type == WIN_TYPE_THUMBNAIL) + { + if (!menu_thumbnail_win) + feh_menu_init_thumbnail_win(); + feh_menu_show_at_xy(menu_thumbnail_win, winwid, x, y); + } + else if (winwid->type == WIN_TYPE_THUMBNAIL_VIEWER) + { + if (!menu_single_win) + feh_menu_init_thumbnail_viewer(); + feh_menu_show_at_xy(menu_thumbnail_viewer, winwid, x, y); + } + else + { + if (!menu_main) + feh_menu_init_main(); + feh_menu_show_at_xy(menu_main, winwid, x, y); + } +} diff --git a/src/winwidget.h b/src/winwidget.h new file mode 100644 index 0000000..de08ec9 --- /dev/null +++ b/src/winwidget.h @@ -0,0 +1,158 @@ +/* winwidget.h + +Copyright (C) 1999-2003 Tom Gilbert. + +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. + +*/ + +#ifndef WINWIDGET_H +#define WINWIDGET_H + +/* This MWM stuff pinched from Eterm/src/command.h */ + +# include +# include + +/* Motif window hints */ +#define MWM_HINTS_FUNCTIONS (1L << 0) +#define MWM_HINTS_DECORATIONS (1L << 1) +#define MWM_HINTS_INPUT_MODE (1L << 2) +#define MWM_HINTS_STATUS (1L << 3) +/* bit definitions for MwmHints.functions */ +#define MWM_FUNC_ALL (1L << 0) +#define MWM_FUNC_RESIZE (1L << 1) +#define MWM_FUNC_MOVE (1L << 2) +#define MWM_FUNC_MINIMIZE (1L << 3) +#define MWM_FUNC_MAXIMIZE (1L << 4) +#define MWM_FUNC_CLOSE (1L << 5) +/* bit definitions for MwmHints.decorations */ +#define MWM_DECOR_ALL (1L << 0) +#define MWM_DECOR_BORDER (1L << 1) +#define MWM_DECOR_RESIZEH (1L << 2) +#define MWM_DECOR_TITLE (1L << 3) +#define MWM_DECOR_MENU (1L << 4) +#define MWM_DECOR_MINIMIZE (1L << 5) +#define MWM_DECOR_MAXIMIZE (1L << 6) +/* bit definitions for MwmHints.inputMode */ +#define MWM_INPUT_MODELESS 0 +#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1 +#define MWM_INPUT_SYSTEM_MODAL 2 +#define MWM_INPUT_FULL_APPLICATION_MODAL 3 +#define PROP_MWM_HINTS_ELEMENTS 5 + +/* Motif window hints */ +typedef struct _mwmhints +{ + CARD32 flags; + CARD32 functions; + CARD32 decorations; + INT32 input_mode; + CARD32 status; +} +MWMHints; + +enum win_type +{ + WIN_TYPE_UNSET, WIN_TYPE_SLIDESHOW, WIN_TYPE_SINGLE, WIN_TYPE_ABOUT, + WIN_TYPE_THUMBNAIL, WIN_TYPE_THUMBNAIL_VIEWER +}; + +struct __winwidget +{ + Window win; + int x; + int y; + int w; + int h; + int im_w; + int im_h; + double im_angle; + enum win_type type; + unsigned char had_resize, full_screen; + Imlib_Image im; + GC gc; + Pixmap bg_pmap; + Pixmap bg_pmap_cache; + char *name; + gib_list *file; + unsigned char visible; + + /* Stuff for zooming */ + unsigned char mode; + + unsigned char caption_entry; /* are we in caption entry mode? */ + + /* New stuff */ + int im_x; /* image offset from window top left */ + int im_y; /* image offset from window top left */ + double zoom; /* From 0 (not visible) to 100 (actual size) + all the way up to INT_MAX (ouch) */ + int click_offset_x; + int click_offset_y; + int im_click_offset_x; + int im_click_offset_y; + + unsigned char has_rotated; +}; + +int winwidget_loadimage(winwidget winwid, feh_file * filename); +void winwidget_show(winwidget winwid); +void winwidget_show_menu(winwidget winwid); +void winwidget_hide(winwidget winwid); +void winwidget_destroy_all(void); +void winwidget_free_image(winwidget w); +void winwidget_render_image(winwidget winwid, int resize, int 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_rerender_all(int resize, int alias); +void winwidget_destroy_xwin(winwidget winwid); +int winwidget_count(void); + +void winwidget_get_geometry(winwidget winwid, int *rect); +int winwidget_get_width(winwidget winwid); +int winwidget_get_height(winwidget winwid); +winwidget winwidget_get_from_window(Window win); +winwidget winwidget_create_from_file(gib_list * filename, char *name, + + char type); +winwidget winwidget_create_from_image(Imlib_Image im, char *name, char type); +void winwidget_rename(winwidget winwid, char *newname); +void winwidget_destroy(winwidget winwid); +void winwidget_create_window(winwidget ret, int w, int h); +void winwidget_clear_background(winwidget w); +Pixmap feh_create_checks(void); +double feh_calc_needed_zoom(double *zoom, int orig_w, int orig_h, int dest_w, + + int dest_h); +void feh_debug_print_winwid(winwidget winwid); +winwidget winwidget_get_first_window_of_type(unsigned int type); +void winwidget_reset_image(winwidget winwid); +void winwidget_sanitise_offsets(winwidget winwid); +void winwidget_size_to_image(winwidget winwid); +void winwidget_render_image_cached(winwidget winwid); + +extern int window_num; /* For window list */ +extern winwidget *windows; /* List of windows to loop though */ + +#endif -- cgit v1.2.3